xref: /third_party/libcoap/tests/test_options.c (revision c87c5fba)
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
22static void
23t_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
38static void
39t_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
53static void
54t_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
71static void
72t_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
83static void
84t_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
95static void
96t_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
107static void
108t_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
121static void
122t_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
135static void
136t_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
148static void
149t_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
160static void
161t_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
172static void
173t_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
184static void
185t_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
205static void
206t_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
237static void
238t_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
249static void
250t_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
261static void
262t_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
273static void
274t_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
285static void
286t_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
297static void
298t_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
309static void
310t_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
325static void
326t_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
342static void
343t_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
358static void
359t_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
371static void
372t_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
384static void
385t_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
400static void
401t_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
413static void
414t_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
426static void
427t_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
442static void
443t_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
467static void
468t_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
492static void
493t_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
518static void
519t_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
560static void
561t_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
603static void
604t_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
635static void
636t_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
681static void
682t_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
728static void
729t_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
759static void
760t_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
790static void
791t_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
829static void
830t_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
859static void
860t_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
878static void
879t_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
934CU_pSuite
935t_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