• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libcoap unit tests
2  *
3  * Copyright (C) 2012,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_options.h"
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 /************************************************************************
19  ** decoder tests
20  ************************************************************************/
21 
22 static void
t_parse_option1(void)23 t_parse_option1(void) {
24   /* delta == 0, length == 0, value == 0 */
25   coap_str_const_t teststr = {  1, (const uint8_t *)"" };
26 
27   size_t result;
28   coap_option_t option;
29 
30   /* result = coap_opt_parse(teststr.s, teststr.s + teststr.length, &option); */
31   result = coap_opt_parse(teststr.s, teststr.length, &option);
32   CU_ASSERT(result == 1);
33   CU_ASSERT(option.delta == 0);
34   CU_ASSERT(option.length == 0);
35   /* FIXME: value? */
36 }
37 
38 static void
t_parse_option2(void)39 t_parse_option2(void) {
40   /* delta == 12, length == 1, value == 0 */
41   coap_str_const_t teststr = {  2, (const uint8_t *)"\xc1" };
42 
43   size_t result;
44   coap_option_t option;
45 
46   result = coap_opt_parse(teststr.s, teststr.length, &option);
47   CU_ASSERT(result == 2);
48   CU_ASSERT(option.delta == 12);
49   CU_ASSERT(option.length == 1);
50   CU_ASSERT(option.value == teststr.s + 1);
51 }
52 
53 static void
t_parse_option3(void)54 t_parse_option3(void) {
55   /* delta == 3, length == 12, value == 0 */
56   coap_str_const_t teststr = { 13, (const uint8_t *)"\x3c\x00\x01\x02\x03\x04"
57                                        "\x05\x06\x07\x08\x09\x0a\x0b" };
58 
59   size_t result;
60   coap_option_t option;
61 
62   result = coap_opt_parse(teststr.s, teststr.length, &option);
63   CU_ASSERT(result == 13);
64   CU_ASSERT(option.delta == 3);
65   CU_ASSERT(option.length == 12);
66   CU_ASSERT(option.value == teststr.s + 1);
67   /* CU_ASSERT(memcmp(option.value, teststr.s + 1, 12) == 0); */
68 }
69 
70 static void
t_parse_option4(void)71 t_parse_option4(void) {
72   /* delta == 15, length == 3, value == 0 */
73   coap_str_const_t teststr = {  2, (const uint8_t *)"\xf3" };
74 
75   size_t result;
76   coap_option_t option;
77 
78   result = coap_opt_parse(teststr.s, teststr.length, &option);
79   CU_ASSERT(result == 0);
80 }
81 
82 static void
t_parse_option5(void)83 t_parse_option5(void) {
84   /* delta == 3, length == 15, value == 0 */
85   coap_str_const_t teststr = {  2, (const uint8_t *)"\x3f" };
86 
87   size_t result;
88   coap_option_t option;
89 
90   result = coap_opt_parse(teststr.s, teststr.length, &option);
91   CU_ASSERT(result == 0);
92 }
93 
94 static void
t_parse_option6(void)95 t_parse_option6(void) {
96   /* delta == 15, length == 15 */
97   coap_str_const_t teststr = {  1, (const uint8_t *)"\xff" };
98 
99   size_t result;
100   coap_option_t option;
101 
102   result = coap_opt_parse(teststr.s, teststr.length, &option);
103   CU_ASSERT(result == 0);
104 }
105 
106 static void
t_parse_option7(void)107 t_parse_option7(void) {
108   /* delta == 20, length == 0 */
109   coap_str_const_t teststr = {  2, (const uint8_t *)"\xd0\x07" };
110 
111   size_t result;
112   coap_option_t option;
113 
114   result = coap_opt_parse(teststr.s, teststr.length, &option);
115   CU_ASSERT(result == 2);
116   CU_ASSERT(option.delta == 20);
117   CU_ASSERT(option.length == 0);
118 }
119 
120 static void
t_parse_option8(void)121 t_parse_option8(void) {
122   /* delta == 780, length == 0 */
123   coap_str_const_t teststr = {  3, (const uint8_t *)"\xe0\x01\xff" };
124 
125   size_t result;
126   coap_option_t option;
127 
128   result = coap_opt_parse(teststr.s, teststr.length, &option);
129   CU_ASSERT(result == 3);
130   CU_ASSERT(option.delta == 780);
131   CU_ASSERT(option.length == 0);
132 }
133 
134 static void
t_parse_option9(void)135 t_parse_option9(void) {
136   /* delta == 65535, length == 0 */
137   coap_str_const_t teststr = {  3, (const uint8_t *)"\xe0\xfe\xf2" };
138 
139   size_t result;
140   coap_option_t option;
141 
142   result = coap_opt_parse(teststr.s, teststr.length, &option);
143   CU_ASSERT(result == 3);
144   CU_ASSERT(option.delta == 65535);
145 }
146 
147 static void
t_parse_option10(void)148 t_parse_option10(void) {
149   /* delta > 65535 (illegal), length == 0 */
150   coap_str_const_t teststr = {  3, (const uint8_t *)"\xe0\xff\xff" };
151 
152   size_t result;
153   coap_option_t option;
154 
155   result = coap_opt_parse(teststr.s, teststr.length, &option);
156   CU_ASSERT(result == 0);
157 }
158 
159 static void
t_parse_option11(void)160 t_parse_option11(void) {
161   /* illegal delta value (option too short) */
162   coap_str_const_t teststr = {  1, (const uint8_t *)"\xd0" };
163 
164   size_t result;
165   coap_option_t option;
166 
167   result = coap_opt_parse(teststr.s, teststr.length, &option);
168   CU_ASSERT(result == 0);
169 }
170 
171 static void
t_parse_option12(void)172 t_parse_option12(void) {
173   /* delta == 280, length == 500 */
174   coap_str_const_t teststr = {  3, (const uint8_t *)"\xee\xff\x0b" };
175 
176   size_t result;
177   coap_option_t option;
178 
179   result = coap_opt_parse(teststr.s, teststr.length, &option);
180   CU_ASSERT(result == 0);
181 }
182 
183 static void
t_parse_option13(void)184 t_parse_option13(void) {
185   /* delta == 280, length == 500 */
186   unsigned char _data[505];
187   coap_string_t teststr = {  sizeof(_data), _data };
188   teststr.s[0] = 0xee;
189   teststr.s[1] = 0x00;
190   teststr.s[2] = 0x0b;
191   teststr.s[3] = 0x00;
192   teststr.s[4] = 0xe7;
193 
194   size_t result;
195   coap_option_t option;
196 
197   result = coap_opt_parse(teststr.s, teststr.length, &option);
198   CU_ASSERT(result == sizeof(_data));
199   CU_ASSERT(option.delta == 280);
200   CU_ASSERT(option.length == 500);
201   CU_ASSERT(option.value == &_data[5]);
202 }
203 
204 static void
t_parse_option14(void)205 t_parse_option14(void) {
206   /* delta == 268, length == 65535 */
207   unsigned char *data;
208   unsigned int length = 4 + 65535;
209 
210   data = (unsigned char *)malloc(length);
211   if (!data) {
212     CU_FAIL("internal error in test framework -- insufficient memory\n");
213     return;
214   }
215 
216   data[0] = 0xde;
217   data[1] = 0xff;
218   data[2] = 0xfe;
219   data[3] = 0xf2;
220 
221   size_t result;
222   coap_option_t option;
223 
224   result = coap_opt_parse(data, length, &option);
225   CU_ASSERT(result == length);
226   CU_ASSERT(option.delta == 268);
227   CU_ASSERT(option.length == 65535);
228   CU_ASSERT(option.value == &data[4]);
229   free(data);
230 }
231 
232 /************************************************************************
233  ** encoder tests
234  ************************************************************************/
235 
236 static void
t_encode_option1(void)237 t_encode_option1(void) {
238   char teststr[] = { 0x00 };
239   unsigned char buf[40];
240   size_t result;
241 
242   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 0, 0);
243   CU_ASSERT(result == sizeof(teststr));
244 
245   CU_ASSERT(memcmp(buf, teststr, result) == 0);
246 }
247 
248 static void
t_encode_option2(void)249 t_encode_option2(void) {
250   uint8_t teststr[] = { 0x5d, 0xff };
251   unsigned char buf[40];
252   size_t result;
253 
254   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 5, 268);
255   CU_ASSERT(result == sizeof(teststr));
256 
257   CU_ASSERT(memcmp(buf, teststr, result) == 0);
258 }
259 
260 static void
t_encode_option3(void)261 t_encode_option3(void) {
262   uint8_t teststr[] = { 0xd1, 0x01 };
263   unsigned char buf[40];
264   size_t result;
265 
266   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 14, 1);
267   CU_ASSERT(result == sizeof(teststr));
268 
269   CU_ASSERT(memcmp(buf, teststr, result) == 0);
270 }
271 
272 static void
t_encode_option4(void)273 t_encode_option4(void) {
274   uint8_t teststr[] = { 0xdd, 0xff, 0xab };
275   unsigned char buf[40];
276   size_t result;
277 
278   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 268, 184);
279   CU_ASSERT(result == sizeof(teststr));
280 
281   CU_ASSERT(memcmp(buf, teststr, result) == 0);
282 }
283 
284 static void
t_encode_option5(void)285 t_encode_option5(void) {
286   uint8_t teststr[] = { 0xed, 0x13, 0x00, 0xff };
287   unsigned char buf[40];
288   size_t result;
289 
290   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 5133, 268);
291   CU_ASSERT(result == sizeof(teststr));
292 
293   CU_ASSERT(memcmp(buf, teststr, result) == 0);
294 }
295 
296 static void
t_encode_option6(void)297 t_encode_option6(void) {
298   uint8_t teststr[] = { 0xee, 0xfe, 0xf2, 0xfe, 0xf2 };
299   unsigned char buf[40];
300   size_t result;
301 
302   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 65535, 65535);
303   CU_ASSERT(result == sizeof(teststr));
304 
305   CU_ASSERT(memcmp(buf, teststr, result) == 0);
306 }
307 
308 static void
t_encode_option7(void)309 t_encode_option7(void) {
310   uint8_t teststr[] = { 0x35, 'v', 'a', 'l', 'u', 'e' };
311   const size_t valoff = 1;
312   unsigned char buf[40];
313   size_t result;
314 
315   result = coap_opt_encode((coap_opt_t *)buf, sizeof(buf), 3,
316                            (unsigned char *)teststr + valoff,
317                            sizeof(teststr) - valoff);
318 
319   CU_ASSERT(result == sizeof(teststr));
320 
321   CU_ASSERT(memcmp(buf, teststr, result) == 0);
322 }
323 
324 static void
t_encode_option8(void)325 t_encode_option8(void) {
326   /* value does not fit in message buffer */
327   unsigned char buf[40];
328   size_t result;
329 
330   result = coap_opt_encode((coap_opt_t *)buf, 8, 15,
331                            (const uint8_t *)"something", 9);
332 
333   CU_ASSERT(result == 0);
334 
335   result = coap_opt_encode((coap_opt_t *)buf, 1, 15,
336                            (const uint8_t *)"something", 9);
337 
338   CU_ASSERT(result == 0);
339 }
340 
341 static void
t_encode_option9(void)342 t_encode_option9(void) {
343   uint8_t teststr[] = { 0xe1, 0x00, 0x00 };
344   unsigned char buf[40] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
345   size_t result;
346 
347   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 269, 1);
348   CU_ASSERT(result == sizeof(teststr));
349 
350   CU_ASSERT(memcmp(buf, teststr, result) == 0);
351 }
352 
353 /************************************************************************
354  ** accessor tests
355  ************************************************************************/
356 
357 static void
t_access_option1(void)358 t_access_option1(void) {
359   const uint8_t teststr[] = { 0x12, 'a', 'b' };
360   coap_option_t opt;
361 
362   CU_ASSERT(sizeof(teststr) == coap_opt_parse((const coap_opt_t *)teststr,
363                                               sizeof(teststr), &opt));
364   CU_ASSERT(opt.delta == 1);
365   CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 2);
366   CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 1);
367   CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == sizeof(teststr));
368 }
369 
370 static void
t_access_option2(void)371 t_access_option2(void) {
372   const uint8_t teststr[] = { 0xe2, 0x18, 0xfd, 'a', 'b' };
373   coap_option_t opt;
374 
375   CU_ASSERT(sizeof(teststr) == coap_opt_parse((const coap_opt_t *)teststr,
376                                               sizeof(teststr), &opt));
377   CU_ASSERT(opt.delta == 6666);
378   CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 2);
379   CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 3);
380   CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == sizeof(teststr));
381 }
382 
383 static void
t_access_option3(void)384 t_access_option3(void) {
385   const uint8_t teststr[] = { 0xed, 0x18, 0x0a, 0x00, 'a', 'b', 'c', 'd',
386                            'e',  'f',  'g',  'h',  'i', 'j', 'k', 'l',
387                            'm'
388   };
389   coap_option_t opt;
390 
391   CU_ASSERT(sizeof(teststr) == coap_opt_parse((const coap_opt_t *)teststr,
392                                               sizeof(teststr), &opt));
393   CU_ASSERT(opt.delta == 6423);
394   CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 13);
395   CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 4);
396   CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == sizeof(teststr));
397 }
398 
399 static void
t_access_option4(void)400 t_access_option4(void) {
401   const uint8_t teststr[] = { 0xde, 0xff, 0xfe, 0xf2, 'a', 'b', 'c' };
402   coap_option_t opt;
403 
404   CU_ASSERT(0 == coap_opt_parse((const coap_opt_t *)teststr,
405                                 sizeof(teststr), &opt));
406   CU_ASSERT(opt.delta == 268);
407   CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 65535);
408   CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 4);
409   CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == 65535 + 4);
410 }
411 
412 static void
t_access_option5(void)413 t_access_option5(void) {
414   const uint8_t teststr[] = { 0xee, 0xfe, 0xf2, 0x00, 0xdd, 'a', 'b', 'c' };
415   coap_option_t opt;
416 
417   CU_ASSERT(0 == coap_opt_parse((const coap_opt_t *)teststr,
418                                 sizeof(teststr), &opt));
419   CU_ASSERT(opt.delta == 65535);
420   CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 490);
421   CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), teststr + 5);
422   CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == 495);
423 }
424 
425 static void
t_access_option6(void)426 t_access_option6(void) {
427   coap_log_t level = coap_get_log_level();
428   const uint8_t teststr[] = { 0xf2, 'a', 'b' };
429   coap_option_t opt;
430 
431   coap_set_log_level(LOG_CRIT);
432 
433   CU_ASSERT(0 == coap_opt_parse((const coap_opt_t *)teststr,
434                                 sizeof(teststr), &opt));
435   coap_set_log_level(level);
436   CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 0);
437   CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), NULL);
438   CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == 0);
439 }
440 
441 static void
t_access_option7(void)442 t_access_option7(void) {
443   const uint8_t teststr[] = { 0x2f, 'a', 'b' };
444   coap_option_t opt;
445 
446   CU_ASSERT(0 == coap_opt_parse((const coap_opt_t *)teststr,
447                                 sizeof(teststr), &opt));
448   CU_ASSERT(opt.delta == 2);
449   CU_ASSERT(coap_opt_length((const coap_opt_t *)teststr) == 0);
450   CU_ASSERT_PTR_EQUAL_C(coap_opt_value((const coap_opt_t *)teststr), NULL);
451   CU_ASSERT(coap_opt_size((const coap_opt_t *)teststr) == 0);
452 }
453 
454 /************************************************************************
455  ** accessor tests
456  ************************************************************************/
457 
458 #define TEST_MAX_SIZE 1000
459 
460 #ifdef _MSC_VER
461 #  define ALIGNED(x)
462 #else
463 #  define ALIGNED(x) __attribute__ ((aligned (x)))
464 #endif
465 
466 static void
t_iterate_option1(void)467 t_iterate_option1(void) {
468   /* CoAP PDU without token, options, or data */
469   uint8_t teststr[] ALIGNED(8) = {
470     0x00, 0x00, 0x00, 0x00
471   };
472 
473   coap_pdu_t pdu = {
474     .max_size = TEST_MAX_SIZE,
475     .token = teststr,
476     .used_size = 0
477   };
478   coap_opt_iterator_t oi, *result;
479   coap_opt_t *option;
480 
481   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
482 
483   CU_ASSERT(result == NULL);
484   CU_ASSERT(oi.bad == 1);
485 
486   option = coap_option_next(&oi);
487   CU_ASSERT(oi.bad == 1);
488   CU_ASSERT(option == NULL);
489 }
490 
491 static void
t_iterate_option2(void)492 t_iterate_option2(void) {
493   /* CoAP PDU with token but without options and data */
494   uint8_t teststr[3] ALIGNED(8) = {
495     't', 'o', 'k'
496   };
497 
498   coap_pdu_t pdu = {
499     .max_size = TEST_MAX_SIZE,
500     .token_length = 3,
501     .token = teststr,
502     .used_size = sizeof(teststr)
503   };
504   coap_opt_iterator_t oi, *result;
505   coap_opt_t *option;
506 
507   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
508 
509   CU_ASSERT(result == NULL);
510   CU_ASSERT(oi.bad == 1);
511 
512   option = coap_option_next(&oi);
513   CU_ASSERT(oi.bad == 1);
514   CU_ASSERT(option == NULL);
515 }
516 
517 static void
t_iterate_option3(void)518 t_iterate_option3(void) {
519   /* CoAP PDU with token and options */
520   uint8_t teststr[] ALIGNED(8) = {
521     't', 'o', 'k', 0x13,
522     'o',  'p',  't',  0x00, 0xd1, 0x10, 'x'
523   };
524 
525   coap_pdu_t pdu = {
526     .max_size = TEST_MAX_SIZE,
527     .token_length = 3,
528     .token = teststr,
529     .used_size = sizeof(teststr)
530   };
531   coap_opt_iterator_t oi, *result;
532   coap_opt_t *option;
533 
534   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
535 
536   CU_ASSERT_PTR_EQUAL(result, &oi);
537   CU_ASSERT(oi.bad == 0);
538 
539   option = coap_option_next(&oi);
540   CU_ASSERT(oi.bad == 0);
541   CU_ASSERT(oi.number == 1);
542   CU_ASSERT_PTR_EQUAL(option, teststr + 3);
543 
544   option = coap_option_next(&oi);
545   CU_ASSERT(oi.bad == 0);
546   CU_ASSERT(oi.number == 1);
547   CU_ASSERT_PTR_EQUAL(option, teststr + 7);
548 
549   option = coap_option_next(&oi);
550   CU_ASSERT(oi.bad == 0);
551   CU_ASSERT(oi.number == 30);
552   CU_ASSERT_PTR_EQUAL(option, teststr + 8);
553 
554   option = coap_option_next(&oi);
555   CU_ASSERT(oi.bad == 1);
556   CU_ASSERT_PTR_EQUAL(option, NULL);
557 }
558 
559 static void
t_iterate_option4(void)560 t_iterate_option4(void) {
561   /* CoAP PDU with token, options, and data */
562   uint8_t teststr[] ALIGNED(8) = {
563     't', 'o', 'k', 0x13,
564     'o',  'p',  't',  0x00, 0xd1, 0x10, 'x', 0xff,
565     'd',  'a',  't',  'a'
566   };
567 
568   coap_pdu_t pdu = {
569     .max_size = TEST_MAX_SIZE,
570     .token_length = 3,
571     .token = teststr,
572     .used_size = sizeof(teststr)
573   };
574   coap_opt_iterator_t oi, *result;
575   coap_opt_t *option;
576 
577   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
578 
579   CU_ASSERT_PTR_EQUAL(result, &oi);
580   CU_ASSERT(oi.bad == 0);
581 
582   option = coap_option_next(&oi);
583   CU_ASSERT(oi.bad == 0);
584   CU_ASSERT(oi.number == 1);
585   CU_ASSERT_PTR_EQUAL(option, teststr + 3);
586 
587   option = coap_option_next(&oi);
588   CU_ASSERT(oi.bad == 0);
589   CU_ASSERT(oi.number == 1);
590   CU_ASSERT_PTR_EQUAL(option, teststr + 7);
591 
592   option = coap_option_next(&oi);
593   CU_ASSERT(oi.bad == 0);
594   CU_ASSERT(oi.number == 30);
595   CU_ASSERT_PTR_EQUAL(option, teststr + 8);
596 
597   option = coap_option_next(&oi);
598   CU_ASSERT(oi.bad == 1);
599   CU_ASSERT_PTR_EQUAL(option, NULL);
600 }
601 
602 static void
t_iterate_option5(void)603 t_iterate_option5(void) {
604   /* CoAP PDU with malformed option */
605   uint8_t teststr[] ALIGNED(8) = {
606     0x52, 'o', 'p', 0xee,
607     0x12, 0x03, 0x00
608   };
609 
610   coap_pdu_t pdu = {
611     .max_size = TEST_MAX_SIZE,
612     .token_length = 0,
613     .token = teststr,
614     .used_size = sizeof(teststr)
615   };
616   coap_opt_iterator_t oi, *result;
617   coap_opt_t *option;
618 
619   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
620 
621   CU_ASSERT_PTR_EQUAL(result, &oi);
622   CU_ASSERT(oi.bad == 0);
623 
624   option = coap_option_next(&oi);
625   CU_ASSERT(oi.bad == 0);
626   CU_ASSERT(oi.number == 5);
627   CU_ASSERT_PTR_EQUAL(option, teststr);
628 
629   option = coap_option_next(&oi);
630   CU_ASSERT(oi.bad == 1);
631   CU_ASSERT_PTR_EQUAL(option, NULL);
632 }
633 
634 static void
t_iterate_option6(void)635 t_iterate_option6(void) {
636   /* option filter */
637   /* CoAP PDU with token, options, and data */
638   uint8_t teststr[] ALIGNED(8) = {
639     0x80, 0x20, 0x00, 0x00,
640     0xc0, 0x00
641   };
642 
643   coap_pdu_t pdu = {
644     .max_size = TEST_MAX_SIZE,
645     .token_length = 0,
646     .token = teststr,
647     .used_size = sizeof(teststr)
648   };
649   coap_opt_iterator_t oi, *result;
650   coap_opt_t *option;
651   coap_opt_filter_t filter;
652 
653   coap_option_filter_clear(&filter);
654   coap_option_filter_set(&filter, 10);        /* option nr 10 only */
655   result = coap_option_iterator_init(&pdu, &oi, &filter);
656 
657   CU_ASSERT_PTR_EQUAL(result, &oi);
658   CU_ASSERT(oi.bad == 0);
659 
660   option = coap_option_next(&oi);
661   CU_ASSERT(oi.bad == 0);
662   CU_ASSERT(oi.number == 10);
663   CU_ASSERT_PTR_EQUAL(option, teststr + 1);
664 
665   option = coap_option_next(&oi);
666   CU_ASSERT(oi.bad == 0);
667   CU_ASSERT(oi.number == 10);
668   CU_ASSERT_PTR_EQUAL(option, teststr + 2);
669 
670   option = coap_option_next(&oi);
671   CU_ASSERT(oi.bad == 0);
672   CU_ASSERT(oi.number == 10);
673   CU_ASSERT_PTR_EQUAL(option, teststr + 3);
674 
675   option = coap_option_next(&oi);
676   CU_ASSERT(oi.bad == 1);
677   CU_ASSERT_PTR_EQUAL(option, NULL);
678 }
679 
680 static void
t_iterate_option7(void)681 t_iterate_option7(void) {
682   /* option filter */
683   uint8_t teststr[] ALIGNED(8) = {
684     0x80, 0x20, 0x00, 0x00,
685     0xc0, 0x00, 0x10, 0x10, 0x00
686   };
687 
688   coap_pdu_t pdu = {
689     .max_size = TEST_MAX_SIZE,
690     .token_length = 0,
691     .token = teststr,
692     .used_size = sizeof(teststr)
693   };
694   coap_opt_iterator_t oi, *result;
695   coap_opt_t *option;
696   coap_opt_filter_t filter;
697 
698   /* search options nr 8 and 22 */
699   coap_option_filter_clear(&filter);
700   coap_option_filter_set(&filter, 8);
701   coap_option_filter_set(&filter, 22);
702   result = coap_option_iterator_init(&pdu, &oi, &filter);
703 
704   CU_ASSERT_PTR_EQUAL(result, &oi);
705   CU_ASSERT(oi.bad == 0);
706 
707   option = coap_option_next(&oi);
708   CU_ASSERT(oi.bad == 0);
709   CU_ASSERT(oi.number == 8);
710   CU_ASSERT_PTR_EQUAL(option, teststr);
711 
712   option = coap_option_next(&oi);
713   CU_ASSERT(oi.bad == 0);
714   CU_ASSERT(oi.number == 22);
715   CU_ASSERT_PTR_EQUAL(option, teststr + 4);
716 
717   option = coap_option_next(&oi);
718   CU_ASSERT(oi.bad == 0);
719   CU_ASSERT(oi.number == 22);
720   CU_ASSERT_PTR_EQUAL(option, teststr + 5);
721 
722   option = coap_option_next(&oi);
723   CU_ASSERT(oi.bad == 1);
724   CU_ASSERT_PTR_EQUAL(option, NULL);
725 }
726 
727 static void
t_iterate_option8(void)728 t_iterate_option8(void) {
729   /* option filter */
730   uint8_t teststr[] ALIGNED(8) = {
731     0x80, 0x20, 0x00, 0x00,
732     0xc0, 0x00, 0x10, 0x10, 0x00
733   };
734 
735   coap_pdu_t pdu = {
736     .max_size = TEST_MAX_SIZE,
737     .token_length = 0,
738     .token = teststr,
739     .used_size = sizeof(teststr)
740   };
741   coap_opt_iterator_t oi, *result;
742   coap_opt_t *option;
743   coap_opt_filter_t filter;
744 
745   /* search option nr 36 */
746   coap_option_filter_clear(&filter);
747   coap_option_filter_set(&filter, 36);
748   result = coap_option_iterator_init(&pdu, &oi, &filter);
749 
750   CU_ASSERT_PTR_EQUAL(result, &oi);
751   CU_ASSERT(oi.bad == 0);
752 
753   option = coap_option_next(&oi);
754   CU_ASSERT(oi.bad == 1);
755   CU_ASSERT_PTR_EQUAL(option, NULL);
756 }
757 
758 static void
t_iterate_option9(void)759 t_iterate_option9(void) {
760   /* options filter: option number too large for filter */
761   uint8_t teststr[] ALIGNED(8) = {
762     0x80, 0x20, 0x00, 0x00,
763     0xc0, 0x00, 0x10, 0x10, 0x00
764   };
765 
766   coap_pdu_t pdu = {
767     .max_size = TEST_MAX_SIZE,
768     .token_length = 0,
769     .token = teststr,
770     .used_size = sizeof(teststr)
771   };
772   coap_opt_iterator_t oi, *result;
773   coap_opt_t *option;
774   coap_opt_filter_t filter;
775 
776   /* search option nr 100 */
777   coap_option_filter_clear(&filter);
778   coap_option_filter_set(&filter, 100);
779   result = coap_option_iterator_init(&pdu, &oi, &filter);
780 
781   CU_ASSERT_PTR_EQUAL(result, &oi);
782   CU_ASSERT(oi.bad == 0);
783 
784   option = coap_option_next(&oi);
785   CU_ASSERT(oi.bad == 1);
786   CU_ASSERT_PTR_EQUAL(option, NULL);
787 }
788 
789 static void
t_iterate_option10(void)790 t_iterate_option10(void) {
791   /* options filter: option numbers in PDU exceed filter size */
792   uint8_t teststr[] ALIGNED(8) = {
793     0x80, 0x20, 0x00, 0x00,
794     0xd0, 0x26, 0xe0, 0x10, 0x00
795   };
796 
797   coap_pdu_t pdu = {
798     .max_size = TEST_MAX_SIZE,
799     .token_length = 0,
800     .token = teststr,
801     .used_size = sizeof(teststr)
802   };
803   coap_opt_iterator_t oi, *result;
804   coap_opt_t *option;
805   coap_opt_filter_t filter;
806 
807   /* search option nr 61 */
808   coap_option_filter_clear(&filter);
809   coap_option_filter_set(&filter, 61);
810   result = coap_option_iterator_init(&pdu, &oi, &filter);
811 
812   CU_ASSERT_PTR_EQUAL(result, &oi);
813   CU_ASSERT(oi.bad == 0);
814 
815   option = coap_option_next(&oi);
816   CU_ASSERT(oi.bad == 0);
817   CU_ASSERT_PTR_EQUAL(option, teststr + 4);
818 
819   option = coap_option_next(&oi);
820   CU_ASSERT(oi.bad == 1);
821   CU_ASSERT_PTR_EQUAL(option, NULL);
822 }
823 
824 /************************************************************************
825  ** filter tests
826  ************************************************************************/
827 
828 static void
t_filter_option1(void)829 t_filter_option1(void) {
830   coap_opt_filter_t filter;
831 
832   coap_option_filter_clear(&filter);
833 
834   CU_ASSERT(coap_option_filter_set(&filter, 0) == 1);
835   CU_ASSERT(coap_option_filter_set(&filter, 37) == 1);
836   CU_ASSERT(coap_option_filter_set(&filter, 37) == 1);
837   CU_ASSERT(coap_option_filter_set(&filter, 43) == 1);
838   CU_ASSERT(coap_option_filter_set(&filter, 290) == 1);
839   CU_ASSERT(coap_option_filter_set(&filter, 65535) == 1);
840 
841   CU_ASSERT(coap_option_filter_get(&filter, 0) == 1);
842   CU_ASSERT(coap_option_filter_get(&filter, 37) == 1);
843   CU_ASSERT(coap_option_filter_get(&filter, 43) == 1);
844   CU_ASSERT(coap_option_filter_get(&filter, 290) == 1);
845   CU_ASSERT(coap_option_filter_get(&filter, 65535) == 1);
846 
847   CU_ASSERT(coap_option_filter_unset(&filter, 37) == 1);
848 
849   CU_ASSERT(coap_option_filter_get(&filter, 0) == 1);
850   CU_ASSERT(coap_option_filter_get(&filter, 43) == 1);
851   CU_ASSERT(coap_option_filter_get(&filter, 290) == 1);
852   CU_ASSERT(coap_option_filter_get(&filter, 65535) == 1);
853 
854   CU_ASSERT(coap_option_filter_get(&filter, 37) == 0);
855   CU_ASSERT(coap_option_filter_get(&filter, 89) == 0);
856 }
857 
858 static void
t_filter_option2(void)859 t_filter_option2(void) {
860   coap_opt_filter_t filter;
861   int s;
862 
863   coap_option_filter_clear(&filter);
864 
865   /* fill all COAP_OPT_FILTER_SHORT slots */
866   for (s = 0; s < COAP_OPT_FILTER_SHORT; s++) {
867     CU_ASSERT(coap_option_filter_set(&filter, s));
868   }
869 
870   /* adding a short option type must fail */
871   CU_ASSERT(coap_option_filter_set(&filter, COAP_OPT_FILTER_SHORT) == 0);
872 
873   /* adding a long option type must succeed */
874   CU_ASSERT(coap_option_filter_set(&filter, 256) == 1);
875 }
876 
877 static void
t_filter_option3(void)878 t_filter_option3(void) {
879   coap_opt_filter_t filter;
880   int l;
881 
882   coap_option_filter_clear(&filter);
883 
884   /* set COAP_OPT_FILTER_LONG long filters */
885   for (l = 0; l < COAP_OPT_FILTER_LONG; l++) {
886     CU_ASSERT(coap_option_filter_set(&filter, 256 + l) == 1);
887   }
888 
889   /* the next must fail and must not be found */
890   CU_ASSERT(coap_option_filter_set(&filter, 256 + COAP_OPT_FILTER_LONG) == 0);
891   CU_ASSERT(coap_option_filter_get(&filter, 256 + COAP_OPT_FILTER_LONG) == 0);
892 
893   /* remove one item */
894   CU_ASSERT(coap_option_filter_unset(&filter, 256) == 1);
895   CU_ASSERT(coap_option_filter_get(&filter, 256) == 0);
896 
897   /* now, storing a new filter must succeed */
898   CU_ASSERT(coap_option_filter_set(&filter, 256 + COAP_OPT_FILTER_LONG) == 1);
899   CU_ASSERT(coap_option_filter_get(&filter, 256 + COAP_OPT_FILTER_LONG) == 1);
900 
901   /* and all other items must be available as well */
902   for (l = 0; l < COAP_OPT_FILTER_LONG; l++) {
903     CU_ASSERT(coap_option_filter_get(&filter, 256 + l + 1) == 1);
904   }
905 
906   /* set COAP_OPT_FILTER_SHORT short filters */
907   for (l = 0; l < COAP_OPT_FILTER_SHORT; l++) {
908     CU_ASSERT(coap_option_filter_set(&filter, l) == 1);
909   }
910 
911   /* the next must fail and must not be found */
912   CU_ASSERT(coap_option_filter_set(&filter, COAP_OPT_FILTER_SHORT) == 0);
913   CU_ASSERT(coap_option_filter_get(&filter, COAP_OPT_FILTER_SHORT) == 0);
914 
915   /* remove one item */
916   CU_ASSERT(coap_option_filter_unset(&filter, 0) == 1);
917   CU_ASSERT(coap_option_filter_get(&filter, 0) == 0);
918 
919   /* now, storing a new filter must succeed */
920   CU_ASSERT(coap_option_filter_set(&filter, COAP_OPT_FILTER_SHORT) == 1);
921   CU_ASSERT(coap_option_filter_get(&filter, COAP_OPT_FILTER_SHORT) == 1);
922 
923   /* and all other items must be available as well */
924   for (l = 0; l < COAP_OPT_FILTER_SHORT; l++) {
925     CU_ASSERT(coap_option_filter_get(&filter, l + 1) == 1);
926   }
927 }
928 
929 /************************************************************************
930  ** initialization
931  ************************************************************************/
932 
933 CU_pSuite
t_init_option_tests(void)934 t_init_option_tests(void) {
935   CU_pSuite suite[5];
936 
937   suite[0] = CU_add_suite("option parser", NULL, NULL);
938   if (!suite[0]) {                        /* signal error */
939     fprintf(stderr, "W: cannot add option parser test suite (%s)\n",
940             CU_get_error_msg());
941 
942     return NULL;
943   }
944 
945 #define OPTION_TEST(n,s)                                       \
946   if (!CU_add_test(suite[0], s, t_parse_option##n)) {          \
947     fprintf(stderr, "W: cannot add option parser test (%s)\n", \
948             CU_get_error_msg());                               \
949   }
950 
951   OPTION_TEST(1, "parse option #1");
952   OPTION_TEST(2, "parse option #2");
953   OPTION_TEST(3, "parse option #3");
954   OPTION_TEST(4, "parse option #4");
955   OPTION_TEST(5, "parse option #5");
956   OPTION_TEST(6, "parse option #6");
957   OPTION_TEST(7, "parse option #7");
958   OPTION_TEST(8, "parse option #8");
959   OPTION_TEST(9, "parse option #9");
960   OPTION_TEST(10, "parse option #10");
961   OPTION_TEST(11, "parse option #11");
962   OPTION_TEST(12, "parse option #12");
963   OPTION_TEST(13, "parse option #13");
964   OPTION_TEST(14, "parse option #14");
965 
966   if ((suite[1] = CU_add_suite("option encoder", NULL, NULL))) {
967 #define OPTION_ENCODER_TEST(n,s)                                  \
968     if (!CU_add_test(suite[1], s, t_encode_option##n)) {          \
969       fprintf(stderr, "W: cannot add option encoder test (%s)\n", \
970               CU_get_error_msg());                                \
971     }
972 
973     OPTION_ENCODER_TEST(1, "encode option #1");
974     OPTION_ENCODER_TEST(2, "encode option #2");
975     OPTION_ENCODER_TEST(3, "encode option #3");
976     OPTION_ENCODER_TEST(4, "encode option #4");
977     OPTION_ENCODER_TEST(5, "encode option #5");
978     OPTION_ENCODER_TEST(6, "encode option #6");
979     OPTION_ENCODER_TEST(7, "encode option #7");
980     OPTION_ENCODER_TEST(8, "encode option #8");
981     OPTION_ENCODER_TEST(9, "encode option #9");
982 
983   } else {
984     fprintf(stderr, "W: cannot add option encoder test suite (%s)\n",
985             CU_get_error_msg());
986   }
987 
988   if ((suite[2] = CU_add_suite("option accessors", NULL, NULL))) {
989 #define OPTION_ACCESSOR_TEST(n,s)                                           \
990     if (!CU_add_test(suite[2], s, t_access_option##n)) {                    \
991       fprintf(stderr, "W: cannot add option accessor function test (%s)\n", \
992               CU_get_error_msg());                                          \
993     }
994 
995     OPTION_ACCESSOR_TEST(1, "access option #1");
996     OPTION_ACCESSOR_TEST(2, "access option #2");
997     OPTION_ACCESSOR_TEST(3, "access option #3");
998     OPTION_ACCESSOR_TEST(4, "access option #4");
999     OPTION_ACCESSOR_TEST(5, "access option #5");
1000     OPTION_ACCESSOR_TEST(6, "access option #6");
1001     OPTION_ACCESSOR_TEST(7, "access option #7");
1002 
1003   } else {
1004     fprintf(stderr, "W: cannot add option acessor function test suite (%s)\n",
1005             CU_get_error_msg());
1006   }
1007 
1008   if ((suite[3] = CU_add_suite("option iterator", NULL, NULL))) {
1009 #define OPTION_ITERATOR_TEST(n,s)                                  \
1010     if (!CU_add_test(suite[3], s, t_iterate_option##n)) {          \
1011       fprintf(stderr, "W: cannot add option iterator test (%s)\n", \
1012               CU_get_error_msg());                                 \
1013     }
1014 
1015     OPTION_ITERATOR_TEST(1, "option iterator #1");
1016     OPTION_ITERATOR_TEST(2, "option iterator #2");
1017     OPTION_ITERATOR_TEST(3, "option iterator #3");
1018     OPTION_ITERATOR_TEST(4, "option iterator #4");
1019     OPTION_ITERATOR_TEST(5, "option iterator #5");
1020     OPTION_ITERATOR_TEST(6, "option iterator #6");
1021     OPTION_ITERATOR_TEST(7, "option iterator #7");
1022     OPTION_ITERATOR_TEST(8, "option iterator #8");
1023     OPTION_ITERATOR_TEST(9, "option iterator #9");
1024     OPTION_ITERATOR_TEST(10, "option iterator #10");
1025 
1026   } else {
1027     fprintf(stderr, "W: cannot add option iterator test suite (%s)\n",
1028             CU_get_error_msg());
1029   }
1030 
1031   if ((suite[4] = CU_add_suite("option filter", NULL, NULL))) {
1032 #define OPTION_FILTER_TEST(n,s)                                  \
1033     if (!CU_add_test(suite[4], s, t_filter_option##n)) {         \
1034       fprintf(stderr, "W: cannot add option filter test (%s)\n", \
1035               CU_get_error_msg());                               \
1036     }
1037 
1038     OPTION_FILTER_TEST(1, "option filter #1");
1039     OPTION_FILTER_TEST(2, "option filter #2");
1040     OPTION_FILTER_TEST(3, "option filter #3");
1041 
1042   } else {
1043     fprintf(stderr, "W: cannot add option filter test suite (%s)\n",
1044             CU_get_error_msg());
1045   }
1046 
1047   return suite[0];
1048 }
1049 
1050