1 /* libcoap unit tests
2 *
3 * Copyright (C) 2013,2015 Olaf Bergmann <bergmann@tzi.org>
4 *
5 * This file is part of the CoAP library libcoap. Please see
6 * README for terms of use.
7 */
8
9 #include "coap_config.h"
10 #include "test_sendqueue.h"
11
12 #include <coap.h>
13
14 #include <stdio.h>
15
16 static coap_queue_t *sendqueue;
17
18 /* timestamps for tests. The first element in this array denotes the
19 * base time in ticks, the following elements are timestamps relative
20 * to this basetime.
21 */
22 static coap_tick_t timestamp[] = {
23 0, 100, 200, 30, 160
24 };
25
26 /* nodes for testing. node[0] is left empty */
27 coap_queue_t *node[5];
28
29 static coap_tick_t
add_timestamps(coap_queue_t * queue,size_t num)30 add_timestamps(coap_queue_t *queue, size_t num) {
31 coap_tick_t t = 0;
32 while (queue && num--) {
33 t += queue->t;
34 queue = queue->next;
35 }
36
37 return t;
38 }
39
40 static void
t_sendqueue1(void)41 t_sendqueue1(void) {
42 int result = coap_insert_node(&sendqueue, node[1]);
43
44 CU_ASSERT(result > 0);
45 CU_ASSERT_PTR_NOT_NULL(sendqueue);
46 CU_ASSERT_PTR_EQUAL(sendqueue, node[1]);
47 CU_ASSERT(node[1]->t == timestamp[1]);
48 }
49
50 static void
t_sendqueue2(void)51 t_sendqueue2(void) {
52 int result;
53
54 result = coap_insert_node(&sendqueue, node[2]);
55
56 CU_ASSERT(result > 0);
57 CU_ASSERT_PTR_EQUAL(sendqueue, node[1]);
58 CU_ASSERT_PTR_EQUAL(sendqueue->next, node[2]);
59
60 CU_ASSERT(sendqueue->t == timestamp[1]);
61 CU_ASSERT(node[2]->t == timestamp[2] - timestamp[1]);
62 }
63
64 /* insert new node as first element in queue */
65 static void
t_sendqueue3(void)66 t_sendqueue3(void) {
67 int result;
68 result = coap_insert_node(&sendqueue, node[3]);
69
70 CU_ASSERT(result > 0);
71
72 CU_ASSERT_PTR_EQUAL(sendqueue, node[3]);
73 CU_ASSERT(node[3]->t == timestamp[3]);
74
75 CU_ASSERT_PTR_NOT_NULL(sendqueue->next);
76 CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next);
77
78 CU_ASSERT(sendqueue->next->t == timestamp[1] - timestamp[3]);
79 CU_ASSERT(sendqueue->next->next->t == timestamp[2] - timestamp[1]);
80 }
81
82 /* insert new node as fourth element in queue */
83 static void
t_sendqueue4(void)84 t_sendqueue4(void) {
85 int result;
86
87 result = coap_insert_node(&sendqueue, node[4]);
88
89 CU_ASSERT(result > 0);
90
91 CU_ASSERT_PTR_EQUAL(sendqueue, node[3]);
92
93 CU_ASSERT_PTR_NOT_NULL(sendqueue->next);
94 CU_ASSERT_PTR_EQUAL(sendqueue->next, node[1]);
95
96 CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next);
97 CU_ASSERT_PTR_EQUAL(sendqueue->next->next, node[4]);
98
99 CU_ASSERT_PTR_NOT_NULL(sendqueue->next->next->next);
100 CU_ASSERT_PTR_EQUAL(sendqueue->next->next->next, node[2]);
101
102 CU_ASSERT(sendqueue->next->t == timestamp[1] - timestamp[3]);
103 CU_ASSERT(add_timestamps(sendqueue, 1) == timestamp[3]);
104 CU_ASSERT(add_timestamps(sendqueue, 2) == timestamp[1]);
105 CU_ASSERT(add_timestamps(sendqueue, 3) == timestamp[4]);
106 CU_ASSERT(add_timestamps(sendqueue, 4) == timestamp[2]);
107 }
108
109 static void
t_sendqueue5(void)110 t_sendqueue5(void) {
111 const coap_tick_diff_t delta1 = 20, delta2 = 130;
112 unsigned int result;
113 coap_tick_t now;
114 struct coap_context_t ctx;
115
116 /* space for saving the current node timestamps */
117 static coap_tick_t times[sizeof(timestamp)/sizeof(coap_tick_t)];
118 coap_queue_t *p;
119 int i;
120
121 /* save timestamps of nodes in the sendqueue in their actual order */
122 memset(times, 0, sizeof(times));
123 for (p = sendqueue, i = 0; p; p = p->next, i++) {
124 times[i] = p->t;
125 }
126
127 coap_ticks(&now);
128 ctx.sendqueue = sendqueue;
129 ctx.sendqueue_basetime = now;
130
131 now -= delta1;
132 result = coap_adjust_basetime(&ctx, now);
133
134 CU_ASSERT(result == 0);
135 CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue);
136 CU_ASSERT(ctx.sendqueue_basetime == now);
137 CU_ASSERT(ctx.sendqueue->t == timestamp[3] + delta1);
138
139 now += delta2;
140 result = coap_adjust_basetime(&ctx, now);
141 CU_ASSERT(result == 2);
142 CU_ASSERT(ctx.sendqueue_basetime == now);
143 CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue);
144 CU_ASSERT(ctx.sendqueue->t == 0);
145
146 CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue->next);
147 CU_ASSERT(ctx.sendqueue->next->t == 0);
148
149 CU_ASSERT_PTR_NOT_NULL(ctx.sendqueue->next->next);
150 CU_ASSERT(ctx.sendqueue->next->next->t == delta2 - delta1 - timestamp[1]);
151
152 /* restore timestamps of nodes in the sendqueue */
153 for (p = sendqueue, i = 0; p; p = p->next, i++) {
154 p->t = times[i];
155 }
156 }
157
158 static void
t_sendqueue6(void)159 t_sendqueue6(void) {
160 unsigned int result;
161 coap_tick_t now;
162 const coap_tick_diff_t delta = 20;
163 struct coap_context_t ctx;
164
165 /* space for saving the current node timestamps */
166 static coap_tick_t times[sizeof(timestamp)/sizeof(coap_tick_t)];
167 coap_queue_t *p;
168 int i;
169
170 /* save timestamps of nodes in the sendqueue in their actual order */
171 memset(times, 0, sizeof(times));
172 for (p = sendqueue, i = 0; p; p = p->next, i++) {
173 times[i] = p->t;
174 }
175
176 coap_ticks(&now);
177 ctx.sendqueue = NULL;
178 ctx.sendqueue_basetime = now;
179
180 result = coap_adjust_basetime(&ctx, now + delta);
181
182 CU_ASSERT(result == 0);
183 CU_ASSERT(ctx.sendqueue_basetime == now + delta);
184
185 /* restore timestamps of nodes in the sendqueue */
186 for (p = sendqueue, i = 0; p; p = p->next, i++) {
187 p->t = times[i];
188 }
189 }
190
191 static void
t_sendqueue7(void)192 t_sendqueue7(void) {
193 int result;
194 coap_queue_t *tmp_node;
195
196 CU_ASSERT_PTR_NOT_NULL(sendqueue);
197 CU_ASSERT_PTR_EQUAL(sendqueue, node[3]);
198
199 CU_ASSERT_PTR_NOT_NULL(sendqueue->next);
200 CU_ASSERT_PTR_EQUAL(sendqueue->next, node[1]);
201
202 result = coap_remove_from_queue(&sendqueue, 3, &tmp_node);
203
204 CU_ASSERT(result == 1);
205 CU_ASSERT_PTR_NOT_NULL(tmp_node);
206 CU_ASSERT_PTR_EQUAL(tmp_node, node[3]);
207
208 CU_ASSERT_PTR_NOT_NULL(sendqueue);
209 CU_ASSERT_PTR_EQUAL(sendqueue, node[1]);
210
211 CU_ASSERT(sendqueue->t == timestamp[1]);
212 }
213
214 static void
t_sendqueue8(void)215 t_sendqueue8(void) {
216 int result;
217 coap_queue_t *tmp_node;
218
219 result = coap_remove_from_queue(&sendqueue, 4, &tmp_node);
220
221 CU_ASSERT(result == 1);
222 CU_ASSERT_PTR_NOT_NULL(tmp_node);
223 CU_ASSERT_PTR_EQUAL(tmp_node, node[4]);
224
225 CU_ASSERT_PTR_NOT_NULL(sendqueue);
226 CU_ASSERT_PTR_EQUAL(sendqueue, node[1]);
227 CU_ASSERT(sendqueue->t == timestamp[1]);
228
229 CU_ASSERT_PTR_NOT_NULL(sendqueue->next);
230 CU_ASSERT_PTR_EQUAL(sendqueue->next, node[2]);
231 CU_ASSERT(sendqueue->next->t == timestamp[2] - timestamp[1]);
232
233 CU_ASSERT_PTR_NULL(sendqueue->next->next);
234 }
235
236 static void
t_sendqueue9(void)237 t_sendqueue9(void) {
238 coap_queue_t *tmp_node;
239 struct coap_context_t ctx;
240
241 /* Initialize a fake context that points to our global sendqueue
242 * Note that all changes happen on ctx.sendqueue. */
243 ctx.sendqueue = sendqueue;
244 tmp_node = coap_peek_next(&ctx);
245 sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */
246
247 CU_ASSERT_PTR_NOT_NULL(tmp_node);
248 CU_ASSERT_PTR_EQUAL(tmp_node, node[1]);
249 CU_ASSERT_PTR_EQUAL(tmp_node, ctx.sendqueue);
250
251 tmp_node = coap_pop_next(&ctx);
252 sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */
253
254 CU_ASSERT_PTR_NOT_NULL(tmp_node);
255 CU_ASSERT_PTR_EQUAL(tmp_node, node[1]);
256
257 CU_ASSERT_PTR_NOT_NULL(sendqueue);
258 CU_ASSERT_PTR_EQUAL(sendqueue, node[2]);
259
260 CU_ASSERT(tmp_node->t == timestamp[1]);
261 CU_ASSERT(sendqueue->t == timestamp[2]);
262
263 CU_ASSERT_PTR_NULL(sendqueue->next);
264 }
265
266 static void
t_sendqueue10(void)267 t_sendqueue10(void) {
268 coap_queue_t *tmp_node;
269 struct coap_context_t ctx;
270
271 /* Initialize a fake context that points to our global sendqueue
272 * Note that all changes happen on ctx.sendqueue. */
273 ctx.sendqueue = sendqueue;
274
275 tmp_node = coap_pop_next(&ctx);
276 sendqueue = ctx.sendqueue; /* must update global sendqueue for correct result */
277
278 CU_ASSERT_PTR_NOT_NULL(tmp_node);
279 CU_ASSERT_PTR_EQUAL(tmp_node, node[2]);
280
281 CU_ASSERT_PTR_NULL(sendqueue);
282
283 CU_ASSERT(tmp_node->t == timestamp[2]);
284 }
285
286 /* This function creates a set of nodes for testing. These nodes
287 * will exist for all tests and are modified by coap_insert_node()
288 * and coap_remove_from_queue().
289 */
290 static int
t_sendqueue_tests_create(void)291 t_sendqueue_tests_create(void) {
292 size_t n, error = 0;
293 sendqueue = NULL;
294 coap_ticks(×tamp[0]);
295
296 memset(node, 0, sizeof(node));
297 for (n = 1; n < sizeof(node)/sizeof(coap_queue_t *); n++) {
298 node[n] = coap_new_node();
299 if (!node[n]) {
300 error = 1;
301 break;
302 }
303
304 node[n]->id = n;
305 node[n]->t = timestamp[n];
306 }
307
308 if (error) {
309 /* destroy all test nodes and set entry to zero */
310 for (n = 0; n < sizeof(node)/sizeof(coap_queue_t *); n++) {
311 if (node[n]) {
312 coap_delete_node(node[n]);
313 node[n] = NULL;
314 }
315 }
316 }
317
318 return error;
319 }
320
321 static int
t_sendqueue_tests_remove(void)322 t_sendqueue_tests_remove(void) {
323 size_t n;
324
325 /* destroy all test nodes */
326 for (n = 0; n < sizeof(node)/sizeof(coap_queue_t *); n++) {
327 if (node[n]) {
328 coap_delete_node(node[n]);
329 }
330 }
331
332 return 0;
333 }
334
335 CU_pSuite
t_init_sendqueue_tests(void)336 t_init_sendqueue_tests(void) {
337 CU_pSuite suite;
338
339 suite = CU_add_suite("sendqueue",
340 t_sendqueue_tests_create, t_sendqueue_tests_remove);
341 if (!suite) { /* signal error */
342 fprintf(stderr, "W: cannot add sendqueue test suite (%s)\n",
343 CU_get_error_msg());
344
345 return NULL;
346 }
347
348 #define SENDQUEUE_TEST(s,t) \
349 if (!CU_ADD_TEST(s,t)) { \
350 fprintf(stderr, "W: cannot add sendqueue test (%s)\n", \
351 CU_get_error_msg()); \
352 }
353
354 SENDQUEUE_TEST(suite, t_sendqueue1);
355 SENDQUEUE_TEST(suite, t_sendqueue2);
356 SENDQUEUE_TEST(suite, t_sendqueue3);
357 SENDQUEUE_TEST(suite, t_sendqueue4);
358 SENDQUEUE_TEST(suite, t_sendqueue5);
359 SENDQUEUE_TEST(suite, t_sendqueue6);
360 SENDQUEUE_TEST(suite, t_sendqueue7);
361 SENDQUEUE_TEST(suite, t_sendqueue8);
362 SENDQUEUE_TEST(suite, t_sendqueue9);
363 SENDQUEUE_TEST(suite, t_sendqueue10);
364
365 return suite;
366 }
367
368