1 /* libcoap unit tests
2  *
3  * Copyright (C) 2012,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_options.h"
11 
12 #include <coap.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   str teststr = {  1, (unsigned char *)"" };
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   str teststr = {  2, (unsigned char *)"\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   str teststr = { 13, (unsigned char *)"\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   str teststr = {  2, (unsigned char *)"\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   str teststr = {  2, (unsigned char *)"\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   str teststr = {  1, (unsigned char *)"\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   str teststr = {  2, (unsigned char *)"\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   str teststr = {  3, (unsigned char *)"\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   str teststr = {  3, (unsigned char *)"\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   str teststr = {  3, (unsigned char *)"\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   str teststr = {  1, (unsigned char *)"\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   str teststr = {  3, (unsigned char *)"\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   str 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 }
230 
231 /************************************************************************
232  ** encoder tests
233  ************************************************************************/
234 
235 static void
t_encode_option1(void)236 t_encode_option1(void) {
237   char teststr[] = { 0x00 };
238   unsigned char buf[40];
239   size_t result;
240 
241   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 0, 0);
242   CU_ASSERT(result == sizeof(teststr));
243 
244   CU_ASSERT(memcmp(buf, teststr, result) == 0);
245 }
246 
247 static void
t_encode_option2(void)248 t_encode_option2(void) {
249   uint8_t teststr[] = { 0x5d, 0xff };
250   unsigned char buf[40];
251   size_t result;
252 
253   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 5, 268);
254   CU_ASSERT(result == sizeof(teststr));
255 
256   CU_ASSERT(memcmp(buf, teststr, result) == 0);
257 }
258 
259 static void
t_encode_option3(void)260 t_encode_option3(void) {
261   uint8_t teststr[] = { 0xd1, 0x01 };
262   unsigned char buf[40];
263   size_t result;
264 
265   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 14, 1);
266   CU_ASSERT(result == sizeof(teststr));
267 
268   CU_ASSERT(memcmp(buf, teststr, result) == 0);
269 }
270 
271 static void
t_encode_option4(void)272 t_encode_option4(void) {
273   uint8_t teststr[] = { 0xdd, 0xff, 0xab };
274   unsigned char buf[40];
275   size_t result;
276 
277   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 268, 184);
278   CU_ASSERT(result == sizeof(teststr));
279 
280   CU_ASSERT(memcmp(buf, teststr, result) == 0);
281 }
282 
283 static void
t_encode_option5(void)284 t_encode_option5(void) {
285   uint8_t teststr[] = { 0xed, 0x13, 0x00, 0xff };
286   unsigned char buf[40];
287   size_t result;
288 
289   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 5133, 268);
290   CU_ASSERT(result == sizeof(teststr));
291 
292   CU_ASSERT(memcmp(buf, teststr, result) == 0);
293 }
294 
295 static void
t_encode_option6(void)296 t_encode_option6(void) {
297   uint8_t teststr[] = { 0xee, 0xfe, 0xf2, 0xfe, 0xf2 };
298   unsigned char buf[40];
299   size_t result;
300 
301   result = coap_opt_setheader((coap_opt_t *)buf, sizeof(buf), 65535, 65535);
302   CU_ASSERT(result == sizeof(teststr));
303 
304   CU_ASSERT(memcmp(buf, teststr, result) == 0);
305 }
306 
307 static void
t_encode_option7(void)308 t_encode_option7(void) {
309   uint8_t teststr[] = { 0x35, 'v', 'a', 'l', 'u', 'e' };
310   const size_t valoff = 1;
311   unsigned char buf[40];
312   size_t result;
313 
314   result = coap_opt_encode((coap_opt_t *)buf, sizeof(buf), 3,
315 			   (unsigned char *)teststr + valoff,
316 			   sizeof(teststr) - valoff);
317 
318   CU_ASSERT(result == sizeof(teststr));
319 
320   CU_ASSERT(memcmp(buf, teststr, result) == 0);
321 }
322 
323 static void
t_encode_option8(void)324 t_encode_option8(void) {
325   /* value does not fit in message buffer */
326   unsigned char buf[40];
327   size_t result;
328 
329   result = coap_opt_encode((coap_opt_t *)buf, 8, 15,
330 			   (unsigned char *)"something", 9);
331 
332   CU_ASSERT(result == 0);
333 
334   result = coap_opt_encode((coap_opt_t *)buf, 1, 15,
335 			   (unsigned char *)"something", 9);
336 
337   CU_ASSERT(result == 0);
338 }
339 
340 /************************************************************************
341  ** accessor tests
342  ************************************************************************/
343 
344 static void
t_access_option1(void)345 t_access_option1(void) {
346   const uint8_t teststr[] = { 0x12, 'a', 'b' };
347 
348   CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 1);
349   CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 2);
350   CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 1);
351   CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == sizeof(teststr));
352 }
353 
354 static void
t_access_option2(void)355 t_access_option2(void) {
356   const uint8_t teststr[] = { 0xe2, 0x18, 0xfd, 'a', 'b' };
357 
358   CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 6666);
359   CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 2);
360   CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 3);
361   CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == sizeof(teststr));
362 }
363 
364 static void
t_access_option3(void)365 t_access_option3(void) {
366   const uint8_t teststr[] = { 0xed, 0x18, 0x0a, 0x00, 'a', 'b', 'c', 'd',
367 			   'e',  'f',  'g',  'h',  'i', 'j', 'k', 'l',
368 			   'm'
369   };
370 
371   CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 6423);
372   CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 13);
373   CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 4);
374   CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == sizeof(teststr));
375 }
376 
377 static void
t_access_option4(void)378 t_access_option4(void) {
379   const uint8_t teststr[] = { 0xde, 0xff, 0xfe, 0xf2, 'a', 'b', 'c' };
380 
381   CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 268);
382   CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 65535);
383   CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 4);
384   CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == 65535 + 4);
385 }
386 
387 static void
t_access_option5(void)388 t_access_option5(void) {
389   const uint8_t teststr[] = { 0xee, 0xfe, 0xf2, 0x00, 0xdd, 'a', 'b', 'c' };
390 
391   CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 65535);
392   CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 490);
393   CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), teststr + 5);
394   CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == 495);
395 }
396 
397 static void
t_access_option6(void)398 t_access_option6(void) {
399   coap_log_t level = coap_get_log_level();
400   const uint8_t teststr[] = { 0xf2, 'a', 'b' };
401 
402   coap_set_log_level(LOG_CRIT);
403   CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 0);
404   coap_set_log_level(level);
405   CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 0);
406   CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), NULL);
407   CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == 0);
408 }
409 
410 static void
t_access_option7(void)411 t_access_option7(void) {
412   const uint8_t teststr[] = { 0x2f, 'a', 'b' };
413 
414   CU_ASSERT(coap_opt_delta((coap_opt_t *)teststr) == 2);
415   CU_ASSERT(coap_opt_length((coap_opt_t *)teststr) == 0);
416   CU_ASSERT_PTR_EQUAL(coap_opt_value((coap_opt_t *)teststr), NULL);
417   CU_ASSERT(coap_opt_size((coap_opt_t *)teststr) == 0);
418 }
419 
420 /************************************************************************
421  ** accessor tests
422  ************************************************************************/
423 
424 #define TEST_MAX_SIZE 1000
425 
426 static void
t_iterate_option1(void)427 t_iterate_option1(void) {
428   /* CoAP PDU without token, options, or data */
429   uint8_t teststr[] __attribute__ ((aligned (8))) = {
430     0x00, 0x00, 0x00, 0x00
431   };
432 
433   coap_pdu_t pdu = {
434     .max_size = TEST_MAX_SIZE,
435     .hdr = (coap_hdr_t *)teststr,
436     .length = sizeof(teststr)
437   };
438   coap_opt_iterator_t oi, *result;
439   coap_opt_t *option;
440 
441   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
442 
443   CU_ASSERT(result == NULL);
444   CU_ASSERT(oi.bad == 1);
445 
446   option = coap_option_next(&oi);
447   CU_ASSERT(oi.bad == 1);
448   CU_ASSERT(option == NULL);
449 }
450 
451 static void
t_iterate_option2(void)452 t_iterate_option2(void) {
453   /* CoAP PDU with token but without options and data */
454   uint8_t teststr[] __attribute__ ((aligned (8))) = {
455     0x03, 0x00, 0x00, 0x00, 't', 'o', 'k'
456   };
457 
458   coap_pdu_t pdu = {
459     .max_size = TEST_MAX_SIZE,
460     .hdr = (coap_hdr_t *)teststr,
461     .length = sizeof(teststr)
462   };
463   coap_opt_iterator_t oi, *result;
464   coap_opt_t *option;
465 
466   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
467 
468   CU_ASSERT(result == NULL);
469   CU_ASSERT(oi.bad == 1);
470 
471   option = coap_option_next(&oi);
472   CU_ASSERT(oi.bad == 1);
473   CU_ASSERT(option == NULL);
474 }
475 
476 static void
t_iterate_option3(void)477 t_iterate_option3(void) {
478   /* CoAP PDU with token and options */
479   uint8_t teststr[] __attribute__ ((aligned (8))) = {
480     0x03, 0x00, 0x00, 0x00, 't', 'o', 'k', 0x13,
481     'o',  'p',  't',  0x00, 0xd1, 0x10, 'x'
482   };
483 
484   coap_pdu_t pdu = {
485     .max_size = TEST_MAX_SIZE,
486     .hdr = (coap_hdr_t *)teststr,
487     .length = sizeof(teststr)
488   };
489   coap_opt_iterator_t oi, *result;
490   coap_opt_t *option;
491 
492   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
493 
494   CU_ASSERT_PTR_EQUAL(result, &oi);
495   CU_ASSERT(oi.bad == 0);
496 
497   option = coap_option_next(&oi);
498   CU_ASSERT(oi.bad == 0);
499   CU_ASSERT(oi.type == 1);
500   CU_ASSERT_PTR_EQUAL(option, teststr + 7);
501 
502   option = coap_option_next(&oi);
503   CU_ASSERT(oi.bad == 0);
504   CU_ASSERT(oi.type == 1);
505   CU_ASSERT_PTR_EQUAL(option, teststr + 11);
506 
507   option = coap_option_next(&oi);
508   CU_ASSERT(oi.bad == 0);
509   CU_ASSERT(oi.type == 30);
510   CU_ASSERT_PTR_EQUAL(option, teststr + 12);
511 
512   option = coap_option_next(&oi);
513   CU_ASSERT(oi.bad == 1);
514   CU_ASSERT_PTR_EQUAL(option, NULL);
515 }
516 
517 static void
t_iterate_option4(void)518 t_iterate_option4(void) {
519   /* CoAP PDU with token, options, and data */
520   uint8_t teststr[] __attribute__ ((aligned (8))) = {
521     0x03, 0x00, 0x00, 0x00, 't', 'o', 'k', 0x13,
522     'o',  'p',  't',  0x00, 0xd1, 0x10, 'x', 0xff,
523     'd',  'a',  't',  'a'
524   };
525 
526   coap_pdu_t pdu = {
527     .max_size = TEST_MAX_SIZE,
528     .hdr = (coap_hdr_t *)teststr,
529     .length = 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.type == 1);
542   CU_ASSERT_PTR_EQUAL(option, teststr + 7);
543 
544   option = coap_option_next(&oi);
545   CU_ASSERT(oi.bad == 0);
546   CU_ASSERT(oi.type == 1);
547   CU_ASSERT_PTR_EQUAL(option, teststr + 11);
548 
549   option = coap_option_next(&oi);
550   CU_ASSERT(oi.bad == 0);
551   CU_ASSERT(oi.type == 30);
552   CU_ASSERT_PTR_EQUAL(option, teststr + 12);
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_option5(void)560 t_iterate_option5(void) {
561   /* CoAP PDU with malformed option */
562   uint8_t teststr[] __attribute__ ((aligned (8))) = {
563     0x00, 0x00, 0x00, 0x00, 0x52, 'o', 'p', 0xee,
564     0x12, 0x03, 0x00
565   };
566 
567   coap_pdu_t pdu = {
568     .max_size = TEST_MAX_SIZE,
569     .hdr = (coap_hdr_t *)teststr,
570     .length = sizeof(teststr)
571   };
572   coap_opt_iterator_t oi, *result;
573   coap_opt_t *option;
574 
575   result = coap_option_iterator_init(&pdu, &oi, COAP_OPT_ALL);
576 
577   CU_ASSERT_PTR_EQUAL(result, &oi);
578   CU_ASSERT(oi.bad == 0);
579 
580   option = coap_option_next(&oi);
581   CU_ASSERT(oi.bad == 0);
582   CU_ASSERT(oi.type == 5);
583   CU_ASSERT_PTR_EQUAL(option, teststr + 4);
584 
585   option = coap_option_next(&oi);
586   CU_ASSERT(oi.bad == 1);
587   CU_ASSERT_PTR_EQUAL(option, NULL);
588 }
589 
590 static void
t_iterate_option6(void)591 t_iterate_option6(void) {
592   /* option filter */
593   /* CoAP PDU with token, options, and data */
594   uint8_t teststr[] __attribute__ ((aligned (8))) = {
595     0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00,
596     0xc0, 0x00
597   };
598 
599   coap_pdu_t pdu = {
600     .max_size = TEST_MAX_SIZE,
601     .hdr = (coap_hdr_t *)teststr,
602     .length = sizeof(teststr)
603   };
604   coap_opt_iterator_t oi, *result;
605   coap_opt_t *option;
606   coap_opt_filter_t filter;
607 
608   coap_option_filter_clear(filter);
609   coap_option_setb(filter, 10);	/* option nr 10 only */
610   result = coap_option_iterator_init(&pdu, &oi, filter);
611 
612   CU_ASSERT_PTR_EQUAL(result, &oi);
613   CU_ASSERT(oi.bad == 0);
614 
615   option = coap_option_next(&oi);
616   CU_ASSERT(oi.bad == 0);
617   CU_ASSERT(oi.type == 10);
618   CU_ASSERT_PTR_EQUAL(option, teststr + 5);
619 
620   option = coap_option_next(&oi);
621   CU_ASSERT(oi.bad == 0);
622   CU_ASSERT(oi.type == 10);
623   CU_ASSERT_PTR_EQUAL(option, teststr + 6);
624 
625   option = coap_option_next(&oi);
626   CU_ASSERT(oi.bad == 0);
627   CU_ASSERT(oi.type == 10);
628   CU_ASSERT_PTR_EQUAL(option, teststr + 7);
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_option7(void)636 t_iterate_option7(void) {
637   /* option filter */
638   uint8_t teststr[] __attribute__ ((aligned (8))) = {
639     0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00,
640     0xc0, 0x00, 0x10, 0x10, 0x00
641   };
642 
643   coap_pdu_t pdu = {
644     .max_size = TEST_MAX_SIZE,
645     .hdr = (coap_hdr_t *)teststr,
646     .length = sizeof(teststr)
647   };
648   coap_opt_iterator_t oi, *result;
649   coap_opt_t *option;
650   coap_opt_filter_t filter;
651 
652   /* search options nr 8 and 22 */
653   coap_option_filter_clear(filter);
654   coap_option_setb(filter, 8);
655   coap_option_setb(filter, 22);
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.type == 8);
664   CU_ASSERT_PTR_EQUAL(option, teststr + 4);
665 
666   option = coap_option_next(&oi);
667   CU_ASSERT(oi.bad == 0);
668   CU_ASSERT(oi.type == 22);
669   CU_ASSERT_PTR_EQUAL(option, teststr + 8);
670 
671   option = coap_option_next(&oi);
672   CU_ASSERT(oi.bad == 0);
673   CU_ASSERT(oi.type == 22);
674   CU_ASSERT_PTR_EQUAL(option, teststr + 9);
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_option8(void)682 t_iterate_option8(void) {
683   /* option filter */
684   uint8_t teststr[] __attribute__ ((aligned (8))) = {
685     0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00,
686     0xc0, 0x00, 0x10, 0x10, 0x00
687   };
688 
689   coap_pdu_t pdu = {
690     .max_size = TEST_MAX_SIZE,
691     .hdr = (coap_hdr_t *)teststr,
692     .length = sizeof(teststr)
693   };
694   coap_opt_iterator_t oi, *result;
695   coap_opt_t *option;
696   coap_opt_filter_t filter;
697 
698   /* search option nr 36 */
699   coap_option_filter_clear(filter);
700   coap_option_setb(filter, 36);
701   result = coap_option_iterator_init(&pdu, &oi, filter);
702 
703   CU_ASSERT_PTR_EQUAL(result, &oi);
704   CU_ASSERT(oi.bad == 0);
705 
706   option = coap_option_next(&oi);
707   CU_ASSERT(oi.bad == 1);
708   CU_ASSERT_PTR_EQUAL(option, NULL);
709 }
710 
711 static void
t_iterate_option9(void)712 t_iterate_option9(void) {
713   /* options filter: option number too large for filter */
714   uint8_t teststr[] __attribute__ ((aligned (8))) = {
715     0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00,
716     0xc0, 0x00, 0x10, 0x10, 0x00
717   };
718 
719   coap_pdu_t pdu = {
720     .max_size = TEST_MAX_SIZE,
721     .hdr = (coap_hdr_t *)teststr,
722     .length = sizeof(teststr)
723   };
724   coap_opt_iterator_t oi, *result;
725   coap_opt_t *option;
726   coap_opt_filter_t filter;
727 
728   /* search option nr 100 */
729   coap_option_filter_clear(filter);
730   coap_option_setb(filter, 100);
731   result = coap_option_iterator_init(&pdu, &oi, filter);
732 
733   CU_ASSERT_PTR_EQUAL(result, &oi);
734   CU_ASSERT(oi.bad == 0);
735 
736   option = coap_option_next(&oi);
737   CU_ASSERT(oi.bad == 1);
738   CU_ASSERT_PTR_EQUAL(option, NULL);
739 }
740 
741 static void
t_iterate_option10(void)742 t_iterate_option10(void) {
743   /* options filter: option numbers in PDU exceed filter size */
744   uint8_t teststr[] __attribute__ ((aligned (8))) = {
745     0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00,
746     0xd0, 0x26, 0xe0, 0x10, 0x00
747   };
748 
749   coap_pdu_t pdu = {
750     .max_size = TEST_MAX_SIZE,
751     .hdr = (coap_hdr_t *)teststr,
752     .length = sizeof(teststr)
753   };
754   coap_opt_iterator_t oi, *result;
755   coap_opt_t *option;
756   coap_opt_filter_t filter;
757 
758   /* search option nr 61 */
759   coap_option_filter_clear(filter);
760   coap_option_setb(filter, 61);
761   result = coap_option_iterator_init(&pdu, &oi, filter);
762 
763   CU_ASSERT_PTR_EQUAL(result, &oi);
764   CU_ASSERT(oi.bad == 0);
765 
766   option = coap_option_next(&oi);
767   CU_ASSERT(oi.bad == 0);
768   CU_ASSERT_PTR_EQUAL(option, teststr + 8);
769 
770   option = coap_option_next(&oi);
771   CU_ASSERT(oi.bad == 1);
772   CU_ASSERT_PTR_EQUAL(option, NULL);
773 }
774 
775 /************************************************************************
776  ** filter tests
777  ************************************************************************/
778 
779 static void
t_filter_option1(void)780 t_filter_option1(void) {
781   coap_opt_filter_t filter;
782 
783   coap_option_filter_clear(filter);
784 
785   CU_ASSERT(coap_option_filter_set(filter, 0) == 1);
786   CU_ASSERT(coap_option_filter_set(filter, 37) == 1);
787   CU_ASSERT(coap_option_filter_set(filter, 37) == 1);
788   CU_ASSERT(coap_option_filter_set(filter, 43) == 1);
789   CU_ASSERT(coap_option_filter_set(filter, 290) == 1);
790   CU_ASSERT(coap_option_filter_set(filter, 65535) == 1);
791 
792   CU_ASSERT(coap_option_filter_get(filter, 0) == 1);
793   CU_ASSERT(coap_option_filter_get(filter, 37) == 1);
794   CU_ASSERT(coap_option_filter_get(filter, 43) == 1);
795   CU_ASSERT(coap_option_filter_get(filter, 290) == 1);
796   CU_ASSERT(coap_option_filter_get(filter, 65535) == 1);
797 
798   CU_ASSERT(coap_option_filter_unset(filter, 37) == 1);
799 
800   CU_ASSERT(coap_option_filter_get(filter, 0) == 1);
801   CU_ASSERT(coap_option_filter_get(filter, 43) == 1);
802   CU_ASSERT(coap_option_filter_get(filter, 290) == 1);
803   CU_ASSERT(coap_option_filter_get(filter, 65535) == 1);
804 
805   CU_ASSERT(coap_option_filter_get(filter, 37) == 0);
806   CU_ASSERT(coap_option_filter_get(filter, 89) == 0);
807 }
808 
809 static void
t_filter_option2(void)810 t_filter_option2(void) {
811   coap_opt_filter_t filter;
812   int s;
813 
814   coap_option_filter_clear(filter);
815 
816   /* fill all COAP_OPT_FILTER_SHORT slots */
817   for (s = 0; s < COAP_OPT_FILTER_SHORT; s++) {
818     CU_ASSERT(coap_option_filter_set(filter, s));
819   }
820 
821   /* adding a short option type must fail */
822   CU_ASSERT(coap_option_filter_set(filter, COAP_OPT_FILTER_SHORT) == 0);
823 
824   /* adding a long option type must succeed */
825   CU_ASSERT(coap_option_filter_set(filter, 256) == 1);
826 }
827 
828 static void
t_filter_option3(void)829 t_filter_option3(void) {
830   coap_opt_filter_t filter;
831   int l;
832 
833   coap_option_filter_clear(filter);
834 
835   /* set COAP_OPT_FILTER_LONG long filters */
836   for (l = 0; l < COAP_OPT_FILTER_LONG; l++) {
837     CU_ASSERT(coap_option_filter_set(filter, 256 + l) == 1);
838   }
839 
840   /* the next must fail and must not be found */
841   CU_ASSERT(coap_option_filter_set(filter, 256 + COAP_OPT_FILTER_LONG) == 0);
842   CU_ASSERT(coap_option_filter_get(filter, 256 + COAP_OPT_FILTER_LONG) == 0);
843 
844   /* remove one item */
845   CU_ASSERT(coap_option_filter_unset(filter, 256) == 1);
846   CU_ASSERT(coap_option_filter_get(filter, 256) == 0);
847 
848   /* now, storing a new filter must succeed */
849   CU_ASSERT(coap_option_filter_set(filter, 256 + COAP_OPT_FILTER_LONG) == 1);
850   CU_ASSERT(coap_option_filter_get(filter, 256 + COAP_OPT_FILTER_LONG) == 1);
851 
852   /* and all other items must be available as well */
853   for (l = 0; l < COAP_OPT_FILTER_LONG; l++) {
854     CU_ASSERT(coap_option_filter_get(filter, 256 + l + 1) == 1);
855   }
856 
857   /* set COAP_OPT_FILTER_SHORT short filters */
858   for (l = 0; l < COAP_OPT_FILTER_SHORT; l++) {
859     CU_ASSERT(coap_option_filter_set(filter, l) == 1);
860   }
861 
862   /* the next must fail and must not be found */
863   CU_ASSERT(coap_option_filter_set(filter, COAP_OPT_FILTER_SHORT) == 0);
864   CU_ASSERT(coap_option_filter_get(filter, COAP_OPT_FILTER_SHORT) == 0);
865 
866   /* remove one item */
867   CU_ASSERT(coap_option_filter_unset(filter, 0) == 1);
868   CU_ASSERT(coap_option_filter_get(filter, 0) == 0);
869 
870   /* now, storing a new filter must succeed */
871   CU_ASSERT(coap_option_filter_set(filter, COAP_OPT_FILTER_SHORT) == 1);
872   CU_ASSERT(coap_option_filter_get(filter, COAP_OPT_FILTER_SHORT) == 1);
873 
874   /* and all other items must be available as well */
875   for (l = 0; l < COAP_OPT_FILTER_SHORT; l++) {
876     CU_ASSERT(coap_option_filter_get(filter, l + 1) == 1);
877   }
878 }
879 
880 /************************************************************************
881  ** initialization
882  ************************************************************************/
883 
884 CU_pSuite
t_init_option_tests(void)885 t_init_option_tests(void) {
886   CU_pSuite suite[5];
887 
888   suite[0] = CU_add_suite("option parser", NULL, NULL);
889   if (!suite[0]) {			/* signal error */
890     fprintf(stderr, "W: cannot add option parser test suite (%s)\n",
891 	    CU_get_error_msg());
892 
893     return NULL;
894   }
895 
896 #define OPTION_TEST(n,s)						      \
897   if (!CU_add_test(suite[0], s, t_parse_option##n)) {	      \
898     fprintf(stderr, "W: cannot add option parser test (%s)\n",	      \
899 	    CU_get_error_msg());				      \
900   }
901 
902   OPTION_TEST(1, "parse option #1");
903   OPTION_TEST(2, "parse option #2");
904   OPTION_TEST(3, "parse option #3");
905   OPTION_TEST(4, "parse option #4");
906   OPTION_TEST(5, "parse option #5");
907   OPTION_TEST(6, "parse option #6");
908   OPTION_TEST(7, "parse option #7");
909   OPTION_TEST(8, "parse option #8");
910   OPTION_TEST(9, "parse option #9");
911   OPTION_TEST(10, "parse option #10");
912   OPTION_TEST(11, "parse option #11");
913   OPTION_TEST(12, "parse option #12");
914   OPTION_TEST(13, "parse option #13");
915   OPTION_TEST(14, "parse option #14");
916 
917   if ((suite[1] = CU_add_suite("option encoder", NULL, NULL))) {
918 #define OPTION_ENCODER_TEST(n,s)			      \
919     if (!CU_add_test(suite[1], s, t_encode_option##n)) {		      \
920       fprintf(stderr, "W: cannot add option encoder test (%s)\n",     \
921 	      CU_get_error_msg());				      \
922     }
923 
924     OPTION_ENCODER_TEST(1, "encode option #1");
925     OPTION_ENCODER_TEST(2, "encode option #2");
926     OPTION_ENCODER_TEST(3, "encode option #3");
927     OPTION_ENCODER_TEST(4, "encode option #4");
928     OPTION_ENCODER_TEST(5, "encode option #5");
929     OPTION_ENCODER_TEST(6, "encode option #6");
930     OPTION_ENCODER_TEST(7, "encode option #7");
931     OPTION_ENCODER_TEST(8, "encode option #8");
932 
933   } else {
934     fprintf(stderr, "W: cannot add option encoder test suite (%s)\n",
935 	    CU_get_error_msg());
936   }
937 
938   if ((suite[2] = CU_add_suite("option accessors", NULL, NULL))) {
939 #define OPTION_ACCESSOR_TEST(n,s)			      \
940     if (!CU_add_test(suite[2], s, t_access_option##n)) {		      \
941       fprintf(stderr, "W: cannot add option accessor function test (%s)\n",     \
942 	      CU_get_error_msg());				      \
943     }
944 
945     OPTION_ACCESSOR_TEST(1, "access option #1");
946     OPTION_ACCESSOR_TEST(2, "access option #2");
947     OPTION_ACCESSOR_TEST(3, "access option #3");
948     OPTION_ACCESSOR_TEST(4, "access option #4");
949     OPTION_ACCESSOR_TEST(5, "access option #5");
950     OPTION_ACCESSOR_TEST(6, "access option #6");
951     OPTION_ACCESSOR_TEST(7, "access option #7");
952 
953   } else {
954     fprintf(stderr, "W: cannot add option acessor function test suite (%s)\n",
955 	    CU_get_error_msg());
956   }
957 
958   if ((suite[3] = CU_add_suite("option iterator", NULL, NULL))) {
959 #define OPTION_ITERATOR_TEST(n,s)			      \
960     if (!CU_add_test(suite[3], s, t_iterate_option##n)) {		      \
961       fprintf(stderr, "W: cannot add option iterator test (%s)\n",     \
962 	      CU_get_error_msg());				      \
963     }
964 
965     OPTION_ITERATOR_TEST(1, "option iterator #1");
966     OPTION_ITERATOR_TEST(2, "option iterator #2");
967     OPTION_ITERATOR_TEST(3, "option iterator #3");
968     OPTION_ITERATOR_TEST(4, "option iterator #4");
969     OPTION_ITERATOR_TEST(5, "option iterator #5");
970     OPTION_ITERATOR_TEST(6, "option iterator #6");
971     OPTION_ITERATOR_TEST(7, "option iterator #7");
972     OPTION_ITERATOR_TEST(8, "option iterator #8");
973     OPTION_ITERATOR_TEST(9, "option iterator #9");
974     OPTION_ITERATOR_TEST(10, "option iterator #10");
975 
976   } else {
977     fprintf(stderr, "W: cannot add option iterator test suite (%s)\n",
978 	    CU_get_error_msg());
979   }
980 
981   if ((suite[4] = CU_add_suite("option filter", NULL, NULL))) {
982 #define OPTION_FILTER_TEST(n,s)			      \
983     if (!CU_add_test(suite[4], s, t_filter_option##n)) {		      \
984       fprintf(stderr, "W: cannot add option filter test (%s)\n",     \
985 	      CU_get_error_msg());				      \
986     }
987 
988     OPTION_FILTER_TEST(1, "option filter #1");
989     OPTION_FILTER_TEST(2, "option filter #2");
990     OPTION_FILTER_TEST(3, "option filter #3");
991 
992   } else {
993     fprintf(stderr, "W: cannot add option filter test suite (%s)\n",
994 	    CU_get_error_msg());
995   }
996 
997   return suite[0];
998 }
999 
1000