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