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