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_pdu.h"
13 
14 #include <assert.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 coap_pdu_t *pdu;              /* Holds the parsed PDU for most tests */
20 
21 /************************************************************************
22  ** PDU decoder
23  ************************************************************************/
24 
25 static void
t_parse_pdu1(void)26 t_parse_pdu1(void) {
27   uint8_t teststr[] = {  0x40, 0x01, 0x93, 0x34 };
28   int result;
29 
30   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
31   CU_ASSERT(result > 0);
32 
33   CU_ASSERT(pdu->used_size == sizeof(teststr) - 4);
34   CU_ASSERT(pdu->type == COAP_MESSAGE_CON);
35   CU_ASSERT(pdu->e_token_length == 0);
36   CU_ASSERT(pdu->code == COAP_REQUEST_CODE_GET);
37   CU_ASSERT(pdu->mid == 0x9334);
38   CU_ASSERT_PTR_NULL(pdu->data);
39 }
40 
41 static void
t_parse_pdu2(void)42 t_parse_pdu2(void) {
43   uint8_t teststr[] = {  0x55, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' };
44   int result;
45 
46   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
47   CU_ASSERT(result > 0);
48 
49   CU_ASSERT(pdu->used_size == sizeof(teststr) - 4);
50   CU_ASSERT(pdu->type == COAP_MESSAGE_NON);
51   CU_ASSERT(pdu->e_token_length == 5);
52   CU_ASSERT(pdu->code == 0x69);
53   CU_ASSERT(pdu->mid == 0x1234);
54   CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0);
55   CU_ASSERT_PTR_NULL(pdu->data);
56 }
57 
58 static void
t_parse_pdu3(void)59 t_parse_pdu3(void) {
60   uint8_t teststr[] = {  0x53, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' };
61   int result;
62 
63   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
64   CU_ASSERT(result == 0);
65 }
66 
67 static void
t_parse_pdu4(void)68 t_parse_pdu4(void) {
69   /* illegal token length (token only 8 bytes) */
70   uint8_t teststr[] = {  0x59, 0x69, 0x12, 0x34,
71                          't', 'o', 'k', 'e', 'n', '1', '2', '3'
72                       };
73   int result;
74 
75   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
76   CU_ASSERT(result == 0);
77 
78   /* illegal token length */
79   teststr[0] = 0x5f;
80 
81   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
82   CU_ASSERT(result == 0);
83 }
84 
85 static void
t_parse_pdu5(void)86 t_parse_pdu5(void) {
87   /* PDU with options */
88   uint8_t teststr[] = {  0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e',
89                          'n',  0x00, 0xc1, 0x00
90                       };
91   int result;
92 
93   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
94   CU_ASSERT(result > 0);
95 
96   CU_ASSERT(pdu->used_size == sizeof(teststr) - 4);
97   CU_ASSERT(pdu->type == COAP_MESSAGE_NON);
98   CU_ASSERT(pdu->e_token_length == 5);
99   CU_ASSERT(pdu->code == 0x73);
100   CU_ASSERT(pdu->mid == 0x1234);
101   CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0);
102   CU_ASSERT_PTR_NULL(pdu->data);
103 
104   /* FIXME: check options */
105 }
106 
107 static void
t_parse_pdu6(void)108 t_parse_pdu6(void) {
109   /* PDU with options that exceed the PDU */
110   uint8_t teststr[] = {  0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e',
111                          'n',  0x00, 0xc1, 0x00, 0xae, 0xf0, 0x03
112                       };
113   int result;
114 
115   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
116   CU_ASSERT(result == 0);
117 }
118 
119 static void
t_parse_pdu7(void)120 t_parse_pdu7(void) {
121   /* PDU with options and payload */
122   uint8_t teststr[] = {  0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e',
123                          'n',  0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y',
124                          'l', 'o', 'a', 'd'
125                       };
126   int result;
127 
128   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
129   CU_ASSERT(result > 0);
130 
131   CU_ASSERT(pdu->used_size == sizeof(teststr) - 4);
132   CU_ASSERT(pdu->type == COAP_MESSAGE_NON);
133   CU_ASSERT(pdu->e_token_length == 5);
134   CU_ASSERT(pdu->code == 0x73);
135   CU_ASSERT(pdu->mid == 0x1234);
136   CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0);
137 
138   /* FIXME: check options */
139 
140   CU_ASSERT(pdu->data == pdu->token + 9);
141   CU_ASSERT(memcmp(pdu->data, teststr + 13, 7) == 0);
142 }
143 
144 static void
t_parse_pdu8(void)145 t_parse_pdu8(void) {
146   /* PDU without options but with payload */
147   uint8_t teststr[] = {  0x50, 0x73, 0x12, 0x34,
148                          0xff, 'p', 'a', 'y', 'l', 'o', 'a',
149                          'd'
150                       };
151   int result;
152 
153   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
154   CU_ASSERT(result > 0);
155 
156   CU_ASSERT(pdu->used_size == sizeof(teststr) - 4);
157   CU_ASSERT(pdu->type == COAP_MESSAGE_NON);
158   CU_ASSERT(pdu->e_token_length == 0);
159   CU_ASSERT(pdu->code == 0x73);
160   CU_ASSERT(pdu->mid == 0x1234);
161 
162   /* FIXME: check options */
163 
164   CU_ASSERT(pdu->data == pdu->token + 1);
165   CU_ASSERT(memcmp(pdu->data, teststr + 5, 7) == 0);
166 }
167 
168 static void
t_parse_pdu9(void)169 t_parse_pdu9(void) {
170   /* PDU without options and payload but with payload start marker */
171   uint8_t teststr[] = {  0x70, 0x00, 0x12, 0x34, 0xff };
172   int result;
173 
174   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
175   CU_ASSERT(result == 0);
176 }
177 
178 static void
t_parse_pdu10(void)179 t_parse_pdu10(void) {
180   /* PDU without payload but with options and payload start marker */
181   uint8_t teststr[] = {  0x53, 0x73, 0x12, 0x34, 't', 'o', 'k',
182                          0x31, 'a', 0xc1, 0x00, 0xff
183                       };
184   int result;
185 
186   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
187   CU_ASSERT(result == 0);
188 }
189 
190 static void
t_parse_pdu11(void)191 t_parse_pdu11(void) {
192   uint8_t teststr[] = {  0x60, 0x00, 0x12, 0x34 };
193   int result;
194 
195   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
196   CU_ASSERT(result > 0);
197 
198   CU_ASSERT(pdu->used_size == sizeof(teststr) - 4);
199   CU_ASSERT(pdu->type == COAP_MESSAGE_ACK);
200   CU_ASSERT(pdu->e_token_length == 0);
201   CU_ASSERT(pdu->code == 0);
202   CU_ASSERT(pdu->mid == 0x1234);
203 }
204 
205 static void
t_parse_pdu12(void)206 t_parse_pdu12(void) {
207   /* RST */
208   uint8_t teststr[] = {  0x70, 0x00, 0x12, 0x34 };
209   int result;
210 
211   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
212   CU_ASSERT(result > 0);
213 
214   CU_ASSERT(pdu->used_size == sizeof(teststr) - 4);
215   CU_ASSERT(pdu->type == COAP_MESSAGE_RST);
216   CU_ASSERT(pdu->e_token_length == 0);
217   CU_ASSERT(pdu->code == 0);
218   CU_ASSERT(pdu->mid == 0x1234);
219 }
220 
221 static void
t_parse_pdu13(void)222 t_parse_pdu13(void) {
223   /* RST with content */
224   uint8_t teststr[] = {  0x70, 0x00, 0x12, 0x34,
225                          0xff, 'c', 'o', 'n', 't', 'e', 'n', 't'
226                       };
227   int result;
228 
229   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
230   CU_ASSERT(result == 0);
231 }
232 
233 static void
t_parse_pdu14(void)234 t_parse_pdu14(void) {
235   /* ACK with content */
236   uint8_t teststr[] = {  0x60, 0x00, 0x12, 0x34,
237                          0xff, 'c', 'o', 'n', 't', 'e', 'n', 't'
238                       };
239   int result;
240 
241   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
242   CU_ASSERT(result == 0);
243 }
244 
245 /*
246  * To test Issue #199 which reads one byte past the end of teststr[]
247  * before fix to coap_opt_parse() as delta is two byte value and only
248  * one byte left
249  * Credit to OSS-Fuzz for finding this, work done by Bhargava Shastry
250  */
251 static void
t_parse_pdu15(void)252 t_parse_pdu15(void) {
253   int result;
254   uint8_t teststr[] = {
255     64,  91,  91,  91, 139,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,   0,
256     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  91,  91, 224, 224, 224,
257     224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
258     224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,   1,   0,   0,   0,
259     0,   0,   0,   0, 224, 192, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
260     224, 224, 224, 224, 224, 224, 224, 224, 228, 224, 224, 224, 224, 224, 224, 224,
261     224, 224, 224, 224, 224, 224, 224, 224, 224,  91,  91,  91,  91,  91,  91,  91,
262     91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,
263     91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,
264     91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,
265     91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,
266     91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,  91,
267     91,  91,  91,  91,  91,  91,  91, 224, 224, 224, 224, 224, 224, 224, 224, 224,
268     224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
269     224, 224, 224, 224, 224, 224,   1,   0,   0,   0,   0,   0,   0,   0, 224, 224,
270     224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
271     224, 224, 224, 224, 224
272   };
273 
274   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
275 
276   CU_ASSERT(pdu->data == NULL);
277 
278   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
279   CU_ASSERT(result == 0);
280 }
281 
282 static void
log_handler(coap_log_t level, const char *message)283 log_handler(coap_log_t level, const char *message) {
284   (void)level;
285   (void)message;
286 }
287 
288 /*
289  * To test Issue #214 which allows the token size to be set larger than the
290  * decoded PDU in coap_pdu_parse_header().  This then causes coap_show_pdu()
291  * to access invalid memory.
292  * Credit to OSS-Fuzz for finding this, work done by Bhargava Shastry
293  */
294 static void
t_parse_pdu16(void)295 t_parse_pdu16(void) {
296   int result;
297   coap_pdu_t *testpdu;
298   uint8_t teststr[] = { 0x5a, 0x0a, 0x5b, 0x5b };
299 
300   testpdu = coap_pdu_init(0, 0, 0, sizeof(teststr));
301   CU_ASSERT(testpdu != NULL);
302 
303   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), testpdu);
304   CU_ASSERT(result == 0);
305 
306   coap_set_show_pdu_output(0);
307   coap_set_log_handler(log_handler);
308   coap_show_pdu(COAP_LOG_ERR, testpdu);        /* display PDU */
309   coap_set_log_handler(NULL);
310 
311   coap_delete_pdu(testpdu);
312 }
313 
314 static void
t_parse_pdu17(void)315 t_parse_pdu17(void) {
316   uint8_t teststr[512] = {  0x40, 0x01, 0x93, 0x34 };
317   size_t idx;
318   int result;
319 
320   /* 245 * option delta 268 > 65535, causing a overflow in the option
321    * number */
322   for (idx = 4; idx < sizeof(teststr) - 4; idx += 2) {
323     teststr[idx] = 0xd0;     /* 1 byte option delta follows */
324     teststr[idx + 1] = 0xff; /* option delta 268 */
325   }
326 
327   result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu);
328   CU_ASSERT(result == 0);
329 }
330 
331 /************************************************************************
332  ** PDU encoder
333  ************************************************************************/
334 
335 static void
t_encode_pdu1(void)336 t_encode_pdu1(void) {
337   uint8_t teststr[] = { 0x45, 0x01, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' };
338   int result;
339 
340   coap_pdu_clear(pdu, pdu->max_size);
341   pdu->type = COAP_MESSAGE_CON;
342   pdu->code = COAP_REQUEST_CODE_GET;
343   pdu->mid = 0x1234;
344 
345   result = coap_add_token(pdu, 5, (const uint8_t *)"token");
346 
347   CU_ASSERT(result == 1);
348   CU_ASSERT(pdu->used_size == 5);
349   CU_ASSERT_PTR_NULL(pdu->data);
350   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
351   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
352 }
353 
354 static void
t_encode_pdu2(void)355 t_encode_pdu2(void) {
356   coap_log_t level = coap_get_log_level();
357   size_t old_max = pdu->max_size;
358   int result;
359 
360   coap_pdu_clear(pdu, 3);        /* set very small PDU size */
361 
362   pdu->type = COAP_MESSAGE_CON;
363   pdu->code = COAP_REQUEST_CODE_GET;
364   pdu->mid = 0x1234;
365 
366   coap_set_log_level(COAP_LOG_CRIT);
367   result = coap_add_token(pdu, 5, (const uint8_t *)"token");
368   coap_set_log_level(level);
369 
370   CU_ASSERT(result == 0);
371 
372   coap_pdu_clear(pdu, old_max);        /* restore PDU size */
373 }
374 
375 static void
t_encode_pdu3(void)376 t_encode_pdu3(void) {
377   int result;
378   coap_bin_const_t check_token;
379 
380   result = coap_add_token(pdu, 15, (const uint8_t *)"123456789012345");
381 
382   /* length of 15 triggers extension */
383   CU_ASSERT(result == 1 && pdu->actual_token.length == 15 &&
384             pdu->e_token_length == 16 && pdu->token[0] == 2);
385 
386   check_token = coap_pdu_get_token(pdu);
387   CU_ASSERT(check_token.length == 15);
388 }
389 
390 static void
t_encode_pdu4(void)391 t_encode_pdu4(void) {
392   /* PDU with options */
393   uint8_t teststr[] = { 0x60, 0x99, 0x12, 0x34, 0x3d, 0x05, 0x66, 0x61,
394                         0x6e, 0x63, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79,
395                         0x2e, 0x63, 0x6f, 0x61, 0x70, 0x2e, 0x6d, 0x65,
396                         0x84, 0x70, 0x61, 0x74, 0x68, 0x00, 0xe8, 0x1e,
397                         0x28, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x6f, 0x70,
398                         0x74
399                       };
400   int result;
401 
402   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
403 
404   pdu->type = COAP_MESSAGE_ACK;
405   pdu->code = 0x99;
406   pdu->mid = 0x1234;
407 
408   CU_ASSERT(pdu->used_size == 0);
409 
410   result = coap_add_option(pdu, COAP_OPTION_URI_HOST,
411                            18, (const uint8_t *)"fancyproxy.coap.me");
412 
413   CU_ASSERT(result == 20);
414   CU_ASSERT(pdu->max_opt == 3);
415   CU_ASSERT(pdu->used_size == 20);
416   CU_ASSERT_PTR_NULL(pdu->data);
417 
418   result = coap_add_option(pdu, COAP_OPTION_URI_PATH,
419                            4, (const uint8_t *)"path");
420 
421   CU_ASSERT(result == 5);
422   CU_ASSERT(pdu->max_opt == 11);
423   CU_ASSERT(pdu->used_size == 25);
424   CU_ASSERT_PTR_NULL(pdu->data);
425 
426   result = coap_add_option(pdu, COAP_OPTION_URI_PATH, 0, NULL);
427 
428   CU_ASSERT(result == 1);
429   CU_ASSERT(pdu->max_opt == 11);
430   CU_ASSERT(pdu->used_size == 26);
431   CU_ASSERT_PTR_NULL(pdu->data);
432 
433   result = coap_add_option(pdu, 8000, 8, (const uint8_t *)"fancyopt");
434 
435   CU_ASSERT(result == 11);
436   CU_ASSERT(pdu->max_opt == 8000);
437   CU_ASSERT(pdu->used_size == 37);
438   CU_ASSERT_PTR_NULL(pdu->data);
439 
440   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
441   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
442 }
443 
444 static void
t_encode_pdu5(void)445 t_encode_pdu5(void) {
446   /* PDU with token and options */
447   uint8_t teststr[] = { 0x68, 0x84, 0x12, 0x34, '1',  '2',  '3',  '4',
448                         '5',  '6',  '7',  '8',  0x18, 0x41, 0x42, 0x43,
449                         0x44, 0x45, 0x46, 0x47, 0x48, 0xd1, 0x03, 0x12
450                       };
451   int result;
452 
453   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
454 
455   pdu->type = COAP_MESSAGE_ACK;
456   pdu->code = COAP_RESPONSE_CODE(404);
457   pdu->mid = 0x1234;
458 
459   CU_ASSERT(pdu->used_size == 0);
460 
461   result = coap_add_token(pdu, 8, (const uint8_t *)"12345678");
462 
463   CU_ASSERT(pdu->used_size == 8);
464 
465   result = coap_add_option(pdu, COAP_OPTION_IF_MATCH,
466                            8, (const uint8_t *)"ABCDEFGH");
467 
468   CU_ASSERT(result == 9);
469   CU_ASSERT(pdu->max_opt == 1);
470   CU_ASSERT(pdu->used_size == 17);
471   CU_ASSERT_PTR_NULL(pdu->data);
472 
473   result = coap_add_option(pdu, COAP_OPTION_ACCEPT,
474                            1, (const uint8_t *)"\x12");
475 
476   CU_ASSERT(result == 3);
477   CU_ASSERT(pdu->max_opt == 17);
478   CU_ASSERT(pdu->used_size == 20);
479   CU_ASSERT_PTR_NULL(pdu->data);
480 
481   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
482   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
483 }
484 
485 static void
t_encode_pdu6(void)486 t_encode_pdu6(void) {
487   /* PDU with data */
488   uint8_t teststr[] = { 0x50, 0x02, 0x12, 0x34, 0xff, '1',  '2',  '3',
489                         '4', '5',  '6',  '7',  '8'
490                       };
491   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
492 
493   pdu->type = COAP_MESSAGE_NON;
494   pdu->code = COAP_REQUEST_CODE_POST;
495   pdu->mid = 0x1234;
496 
497   CU_ASSERT(pdu->used_size == 0);
498   CU_ASSERT_PTR_NULL(pdu->data);
499 
500   coap_add_data(pdu, 8, (const uint8_t *)"12345678");
501 
502   CU_ASSERT(pdu->used_size == 9);
503   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
504   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
505 }
506 
507 static void
t_encode_pdu7(void)508 t_encode_pdu7(void) {
509   /* PDU with empty data */
510   uint8_t teststr[] = { 0x40, 0x43, 0x12, 0x34 };
511   int result;
512   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
513 
514   pdu->type = COAP_MESSAGE_CON;
515   pdu->code = COAP_RESPONSE_CODE(203);
516   pdu->mid = 0x1234;
517 
518   CU_ASSERT(pdu->used_size == 0);
519 
520   result = coap_add_data(pdu, 0, NULL);
521 
522   CU_ASSERT(result > 0);
523   CU_ASSERT(pdu->used_size == 0);
524   CU_ASSERT_PTR_NULL(pdu->data);
525 
526   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
527   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
528 }
529 
530 static void
t_encode_pdu8(void)531 t_encode_pdu8(void) {
532   /* PDU with token and data */
533   uint8_t teststr[] = { 0x42, 0x43, 0x12, 0x34, 0x00, 0x01, 0xff, 0x00 };
534   int result;
535   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
536 
537   pdu->type = COAP_MESSAGE_CON;
538   pdu->code = COAP_RESPONSE_CODE(203);
539   pdu->mid = 0x1234;
540 
541   CU_ASSERT(pdu->used_size == 0);
542 
543   result = coap_add_token(pdu, 2, (const uint8_t *)"\x00\x01");
544 
545   CU_ASSERT(result > 0);
546 
547   result = coap_add_data(pdu, 1, (const uint8_t *)"\0");
548 
549   CU_ASSERT(result > 0);
550   CU_ASSERT(pdu->used_size == 4);
551   CU_ASSERT(pdu->data == pdu->token + 3);
552 
553   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
554   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
555 }
556 
557 static void
t_encode_pdu9(void)558 t_encode_pdu9(void) {
559   /* PDU with options and data */
560   uint8_t teststr[] = { 0x60, 0x44, 0x12, 0x34, 0x48, 's',  'o',  'm',
561                         'e',  'e',  't',  'a',  'g',  0x10, 0xdd, 0x11,
562                         0x04, 's',  'o',  'm',  'e',  'r',  'a',  't',
563                         'h',  'e',  'r',  'l',  'o',  'n',  'g',  'u',
564                         'r',  'i',  0xff, 'd',  'a',  't',  'a'
565                       };
566   int result;
567 
568   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
569 
570   pdu->type = COAP_MESSAGE_ACK;
571   pdu->code = COAP_RESPONSE_CODE(204);
572   pdu->mid = 0x1234;
573 
574   CU_ASSERT(pdu->used_size == 0);
575 
576   result = coap_add_option(pdu, COAP_OPTION_ETAG, 8, (const uint8_t *)"someetag");
577 
578   CU_ASSERT(result == 9);
579   CU_ASSERT(pdu->max_opt == 4);
580   CU_ASSERT(pdu->used_size == 9);
581   CU_ASSERT_PTR_NULL(pdu->data);
582 
583   result = coap_add_option(pdu, COAP_OPTION_IF_NONE_MATCH, 0, NULL);
584 
585   CU_ASSERT(result == 1);
586   CU_ASSERT(pdu->max_opt == 5);
587   CU_ASSERT(pdu->used_size == 10);
588   CU_ASSERT_PTR_NULL(pdu->data);
589 
590   result = coap_add_option(pdu, COAP_OPTION_PROXY_URI,
591                            17, (const uint8_t *)"someratherlonguri");
592 
593   CU_ASSERT(result == 20);
594   CU_ASSERT(pdu->max_opt == 35);
595   CU_ASSERT(pdu->used_size == 30);
596   CU_ASSERT_PTR_NULL(pdu->data);
597 
598   result = coap_add_data(pdu, 4, (const uint8_t *)"data");
599 
600   CU_ASSERT(result > 0);
601   CU_ASSERT(pdu->used_size == 35);
602   CU_ASSERT(pdu->data == pdu->token + 31);
603 
604   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
605   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
606 }
607 
608 static void
t_encode_pdu10(void)609 t_encode_pdu10(void) {
610   /* PDU with token, options and data */
611   uint8_t teststr[] = { 0x62, 0x44, 0x12, 0x34, 0x00, 0x00, 0x8d, 0xf2,
612                         'c',  'o',  'a',  'p',  ':',  '/',  '/',  'e',
613                         'x',  'a',  'm',  'p',  'l',  'e',  '.',  'c',
614                         'o',  'm',  '/',  '1',  '2',  '3',  '4',  '5',
615                         '/',  '%',  '3',  'F',  'x',  'y',  'z',  '/',
616                         '3',  '0',  '4',  '8',  '2',  '3',  '4',  '2',
617                         '3',  '4',  '/',  '2',  '3',  '4',  '0',  '2',
618                         '3',  '4',  '8',  '2',  '3',  '4',  '/',  '2',
619                         '3',  '9',  '0',  '8',  '4',  '2',  '3',  '4',
620                         '-',  '2',  '3',  '/',  '%',  'A',  'B',  '%',
621                         '3',  '0',  '%',  'a',  'f',  '/',  '+',  '1',
622                         '2',  '3',  '/',  'h',  'f',  'k',  's',  'd',
623                         'h',  '/',  '2',  '3',  '4',  '8',  '0',  '-',
624                         '2',  '3',  '4',  '-',  '9',  '8',  '2',  '3',
625                         '5',  '/',  '1',  '2',  '0',  '4',  '/',  '2',
626                         '4',  '3',  '5',  '4',  '6',  '3',  '4',  '5',
627                         '3',  '4',  '5',  '2',  '4',  '3',  '/',  '0',
628                         '1',  '9',  '8',  's',  'd',  'n',  '3',  '-',
629                         'a',  '-',  '3',  '/',  '/',  '/',  'a',  'f',
630                         'f',  '0',  '9',  '3',  '4',  '/',  '9',  '7',
631                         'u',  '2',  '1',  '4',  '1',  '/',  '0',  '0',
632                         '0',  '2',  '/',  '3',  '9',  '3',  '2',  '4',
633                         '2',  '3',  '5',  '3',  '2',  '/',  '5',  '6',
634                         '2',  '3',  '4',  '0',  '2',  '3',  '/',  '-',
635                         '-',  '-',  '-',  '/',  '=',  '1',  '2',  '3',
636                         '4',  '=',  '/',  '0',  '9',  '8',  '1',  '4',
637                         '1',  '-',  '9',  '5',  '6',  '4',  '6',  '4',
638                         '3',  '/',  '2',  '1',  '9',  '7',  '0',  '-',
639                         '-',  '-',  '-',  '-',  '/',  '8',  '2',  '3',
640                         '6',  '4',  '9',  '2',  '3',  '4',  '7',  '2',
641                         'w',  'e',  'r',  'e',  'r',  'e',  'w',  'r',
642                         '0',  '-',  '9',  '2',  '1',  '-',  '3',  '9',
643                         '1',  '2',  '3',  '-',  '3',  '4',  '/',  0x0d,
644                         0x01, '/',  '/',  '4',  '9',  '2',  '4',  '0',
645                         '3',  '-',  '-',  '0',  '9',  '8',  '/',  0xc1,
646                         '*',  0xff, 'd',  'a',  't',  'a'
647                       };
648   int result;
649 
650   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
651 
652   pdu->type = COAP_MESSAGE_ACK;
653   pdu->code = COAP_RESPONSE_CODE(204);
654   pdu->mid = 0x1234;
655 
656   CU_ASSERT(pdu->used_size == 0);
657 
658   result = coap_add_token(pdu, 2, (const uint8_t *)"\0\0");
659 
660   CU_ASSERT(result > 0);
661   result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 255,
662                            (const uint8_t *)
663                            "coap://example.com/12345/%3Fxyz/3048234234/23402348234/239084234-23/%AB%30%af/+123/hfksdh/23480-234-98235/1204/243546345345243/0198sdn3-a-3///aff0934/97u2141/0002/3932423532/56234023/----/=1234=/098141-9564643/21970-----/82364923472wererewr0-921-39123-34/");
664 
665   CU_ASSERT(result == 257);
666   CU_ASSERT(pdu->max_opt == 8);
667   CU_ASSERT(pdu->used_size == 259);
668   CU_ASSERT_PTR_NULL(pdu->data);
669 
670   result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 14,
671                            (const uint8_t *)"//492403--098/");
672 
673   CU_ASSERT(result == 16);
674   CU_ASSERT(pdu->max_opt == 8);
675   CU_ASSERT(pdu->used_size == 275);
676   CU_ASSERT_PTR_NULL(pdu->data);
677 
678   result = coap_add_option(pdu, COAP_OPTION_LOCATION_QUERY,
679                            1, (const uint8_t *)"*");
680 
681   CU_ASSERT(result == 2);
682   CU_ASSERT(pdu->max_opt == 20);
683   CU_ASSERT(pdu->used_size == 277);
684   CU_ASSERT_PTR_NULL(pdu->data);
685 
686   result = coap_add_data(pdu, 4, (const uint8_t *)"data");
687 
688   CU_ASSERT(result > 0);
689   CU_ASSERT(pdu->used_size == 282);
690   CU_ASSERT(pdu->data == pdu->token + 278);
691 
692   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
693   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
694 }
695 
696 static void
t_encode_pdu11(void)697 t_encode_pdu11(void) {
698   coap_log_t level = coap_get_log_level();
699   /* data too long for PDU */
700   size_t old_max = pdu->max_size;
701   int result;
702 
703   coap_pdu_clear(pdu, 8);        /* clear PDU, with small maximum */
704 
705   CU_ASSERT(pdu->data == NULL);
706   coap_set_log_level(COAP_LOG_CRIT);
707   result = coap_add_data(pdu, 10, (const uint8_t *)"0123456789");
708   coap_set_log_level(level);
709 
710   CU_ASSERT(result == 0);
711   CU_ASSERT(pdu->data == NULL);
712   CU_ASSERT(pdu->used_size == 0);
713 
714   pdu->max_size = old_max;
715 }
716 
717 static void
t_encode_pdu12(void)718 t_encode_pdu12(void) {
719   coap_optlist_t *optlist = NULL;
720   int n;
721   uint8_t opt_num[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };
722   uint8_t opt_val[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };
723   uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };
724   coap_opt_iterator_t oi;
725   coap_opt_t *option;
726 
727   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
728 
729   CU_ASSERT(pdu->data == NULL);
730 
731   for (n = 0; n < (int)sizeof(opt_num); n++) {
732     coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n],
733                                                    sizeof(opt_val[n]), &opt_val[n]));
734   }
735   coap_add_optlist_pdu(pdu, &optlist);
736 
737   /* Check options in pdu are in right order */
738   coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL);
739   for (n = 0; n < (int)sizeof(opt_num); n++) {
740     option = coap_option_next(&oi);
741     CU_ASSERT(oi.bad == 0);
742     CU_ASSERT(option != NULL);
743     CU_ASSERT(coap_opt_length(option) == 1);
744     CU_ASSERT(*coap_opt_value(option) == opt_srt[n]);
745   }
746   option = coap_option_next(&oi);
747   CU_ASSERT(oi.bad == 1);
748   CU_ASSERT(option == NULL);
749   coap_delete_optlist(optlist);
750 }
751 
752 static void
t_encode_pdu13(void)753 t_encode_pdu13(void) {
754   coap_optlist_t *optlist = NULL;
755   int n;
756   uint8_t opt_num[] = { 59, 58, 57, 56, 55, 54, 53, 52, 51, 50 };
757   uint8_t opt_val[] = { 59, 58, 57, 56, 55, 54, 53, 52, 51, 50 };
758   uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };
759   coap_opt_iterator_t oi;
760   coap_opt_t *option;
761 
762   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
763 
764   CU_ASSERT(pdu->data == NULL);
765 
766   for (n = 0; n < (int)sizeof(opt_num); n++) {
767     coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n],
768                                                    sizeof(opt_val[n]), &opt_val[n]));
769   }
770   coap_add_optlist_pdu(pdu, &optlist);
771 
772   /* Check options in pdu are in right order */
773   coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL);
774   for (n = 0; n < (int)sizeof(opt_num); n++) {
775     option = coap_option_next(&oi);
776     CU_ASSERT(oi.bad == 0);
777     CU_ASSERT(option != NULL);
778     CU_ASSERT(coap_opt_length(option) == 1);
779     CU_ASSERT(*coap_opt_value(option) == opt_srt[n]);
780   }
781   option = coap_option_next(&oi);
782   CU_ASSERT(oi.bad == 1);
783   CU_ASSERT(option == NULL);
784   coap_delete_optlist(optlist);
785 }
786 
787 static void
t_encode_pdu14(void)788 t_encode_pdu14(void) {
789   coap_optlist_t *optlist = NULL;
790   int n;
791   uint8_t opt_num[] = { 53, 52, 51, 50, 51, 52, 52, 51, 50, 50 };
792   uint8_t opt_val[] = { 59, 56, 53, 50, 54, 57, 58, 55, 51, 52 };
793   uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };
794   coap_opt_iterator_t oi;
795   coap_opt_t *option;
796 
797   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
798 
799   CU_ASSERT(pdu->data == NULL);
800 
801   for (n = 0; n < (int)sizeof(opt_num); n++) {
802     coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n],
803                                                    sizeof(opt_val[n]), &opt_val[n]));
804   }
805   coap_add_optlist_pdu(pdu, &optlist);
806 
807   /* Check options in pdu are in right order */
808   coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL);
809   for (n = 0; n < (int)sizeof(opt_num); n++) {
810     option = coap_option_next(&oi);
811     CU_ASSERT(oi.bad == 0);
812     CU_ASSERT(option != NULL);
813     CU_ASSERT(coap_opt_length(option) == 1);
814     CU_ASSERT(*coap_opt_value(option) == opt_srt[n]);
815   }
816   option = coap_option_next(&oi);
817   CU_ASSERT(oi.bad == 1);
818   CU_ASSERT(option == NULL);
819   coap_delete_optlist(optlist);
820 }
821 
822 /* Check inserting options with random types get put into the PDU in the
823    right order */
824 static void
t_encode_pdu15(void)825 t_encode_pdu15(void) {
826   size_t n;
827   uint16_t opt_num[] = { 300,  13,  10,   7,  11, 268, 269,  12,   8,   9 };
828   uint8_t  opt_val[] = {  59,  56,  53,  50,  54,  57,  58,  55,  51,  52 };
829   uint8_t  opt_srt[] = {  50,  51,  52,  53,  54,  55,  56,  57,  58,  59 };
830   coap_opt_iterator_t oi;
831   coap_opt_t *option;
832 
833   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
834 
835   CU_ASSERT(pdu->data == NULL);
836 
837   for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) {
838     coap_insert_option(pdu, opt_num[n],
839                        sizeof(opt_val[n]), &opt_val[n]);
840   }
841 
842   /* Check options in pdu are in right order */
843   coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL);
844   for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) {
845     option = coap_option_next(&oi);
846     CU_ASSERT(oi.bad == 0);
847     CU_ASSERT(option != NULL);
848     CU_ASSERT(coap_opt_length(option) == 1);
849     CU_ASSERT(*coap_opt_value(option) == opt_srt[n]);
850   }
851   option = coap_option_next(&oi);
852   CU_ASSERT(oi.bad == 1);
853   CU_ASSERT(option == NULL);
854 }
855 
856 /* Check changing value of options works */
857 static void
t_encode_pdu16(void)858 t_encode_pdu16(void) {
859   size_t n;
860   uint16_t opt_num[] = { 300,  10,   7 };
861   uint8_t  opt_val[] = {  53,  51,  50 };
862   uint8_t  data[] = { 'd', 'a', 't', 'a' };
863   uint8_t  data1[] = { 0x71, 0x32, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35,
864                        0xff, 0x64, 0x61, 0x74, 0x61
865                      };
866   uint8_t  data2[] = { 0x71, 0x32, 0x33, 0x01, 0x23, 0x45, 0xe1, 0x00,
867                        0x15, 0x35, 0xff, 0x64, 0x61, 0x74, 0x61
868                      };
869   uint8_t  data3[] = { 0x70, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35, 0xff,
870                        0x64, 0x61, 0x74, 0x61
871                      };
872   uint8_t  data4[] = { 0x71, 0x32, 0x31, 0x33, 0xe4, 0x00, 0x15, 0x06,
873                        0x54, 0x32, 0x10, 0xff, 0x64, 0x61, 0x74, 0x61
874                      };
875   int new_val;
876   unsigned char buf[4];
877 
878   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
879 
880   CU_ASSERT(pdu->data == NULL);
881 
882   for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) {
883     coap_add_option(pdu, opt_num[n],
884                     sizeof(opt_val[n]), &opt_val[n]);
885   }
886   coap_add_data(pdu, sizeof(data), data);
887   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
888   /* Now update an option in the middle */
889   new_val = 0x12345;
890   coap_update_option(pdu, 10,
891                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
892   CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0);
893   /* Shrink it back again */
894   new_val = 51;
895   coap_update_option(pdu, 10,
896                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
897   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
898   /* Now update an option at the start */
899   new_val = 0;
900   coap_update_option(pdu, 7,
901                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
902   CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0);
903   /* put it back again */
904   new_val = 50;
905   coap_update_option(pdu, 7,
906                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
907   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
908   /* Now update an option at the end */
909   new_val = 0x6543210;
910   coap_update_option(pdu, 300,
911                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
912   CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0);
913   /* put it back again */
914   new_val = 53;
915   coap_update_option(pdu, 300,
916                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
917   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
918 }
919 
920 /* Same as t_encode_pdu16, but without any data, but with a token */
921 static void
t_encode_pdu17(void)922 t_encode_pdu17(void) {
923   size_t n;
924   uint8_t  token[] = { 't' };
925   uint16_t opt_num[] = { 300,  10,   7 };
926   uint8_t  opt_val[] = {  53,  51,  50 };
927   uint8_t  data1[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xe1, 0x00, 0x15,
928                        0x35
929                      };
930   uint8_t  data2[] = { 0x74, 0x71, 0x32, 0x33, 0x01, 0x23, 0x45, 0xe1,
931                        0x00, 0x15, 0x35
932                      };
933   uint8_t  data3[] = { 0x74, 0x70, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35 };
934   uint8_t  data4[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xe4, 0x00, 0x15,
935                        0x06, 0x54, 0x32, 0x10
936                      };
937   int new_val;
938   unsigned char buf[4];
939 
940   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
941 
942   CU_ASSERT(pdu->data == NULL);
943 
944   coap_add_token(pdu, sizeof(token), token);
945   for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) {
946     coap_add_option(pdu, opt_num[n],
947                     sizeof(opt_val[n]), &opt_val[n]);
948   }
949   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
950   /* Now update an option in the middle */
951   new_val = 0x12345;
952   coap_update_option(pdu, 10,
953                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
954   CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0);
955   /* Shrink it back again */
956   new_val = 51;
957   coap_update_option(pdu, 10,
958                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
959   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
960   /* Now update an option at the start */
961   new_val = 0;
962   coap_update_option(pdu, 7,
963                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
964   CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0);
965   /* put it back again */
966   new_val = 50;
967   coap_update_option(pdu, 7,
968                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
969   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
970   /* Now update an option at the end */
971   new_val = 0x6543210;
972   coap_update_option(pdu, 300,
973                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
974   CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0);
975   /* put it back again */
976   new_val = 53;
977   coap_update_option(pdu, 300,
978                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
979   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
980 }
981 
982 static void
t_encode_pdu18(void)983 t_encode_pdu18(void) {
984   /* PDU with token, options and data */
985   uint8_t teststr[] = { 0x62, 0x44, 0x12, 0x34, 0x00, 0x00, 0x8d, 0xf2,
986                         'c',  'o',  'a',  'p',  ':',  '/',  '/',  'e',
987                         'x',  'a',  'm',  'p',  'l',  'e',  '.',  'c',
988                         'o',  'm',  '/',  '1',  '2',  '3',  '4',  '5',
989                         '/',  '%',  '3',  'F',  'x',  'y',  'z',  '/',
990                         '3',  '0',  '4',  '8',  '2',  '3',  '4',  '2',
991                         '3',  '4',  '/',  '2',  '3',  '4',  '0',  '2',
992                         '3',  '4',  '8',  '2',  '3',  '4',  '/',  '2',
993                         '3',  '9',  '0',  '8',  '4',  '2',  '3',  '4',
994                         '-',  '2',  '3',  '/',  '%',  'A',  'B',  '%',
995                         '3',  '0',  '%',  'a',  'f',  '/',  '+',  '1',
996                         '2',  '3',  '/',  'h',  'f',  'k',  's',  'd',
997                         'h',  '/',  '2',  '3',  '4',  '8',  '0',  '-',
998                         '2',  '3',  '4',  '-',  '9',  '8',  '2',  '3',
999                         '5',  '/',  '1',  '2',  '0',  '4',  '/',  '2',
1000                         '4',  '3',  '5',  '4',  '6',  '3',  '4',  '5',
1001                         '3',  '4',  '5',  '2',  '4',  '3',  '/',  '0',
1002                         '1',  '9',  '8',  's',  'd',  'n',  '3',  '-',
1003                         'a',  '-',  '3',  '/',  '/',  '/',  'a',  'f',
1004                         'f',  '0',  '9',  '3',  '4',  '/',  '9',  '7',
1005                         'u',  '2',  '1',  '4',  '1',  '/',  '0',  '0',
1006                         '0',  '2',  '/',  '3',  '9',  '3',  '2',  '4',
1007                         '2',  '3',  '5',  '3',  '2',  '/',  '5',  '6',
1008                         '2',  '3',  '4',  '0',  '2',  '3',  '/',  '-',
1009                         '-',  '-',  '-',  '/',  '=',  '1',  '2',  '3',
1010                         '4',  '=',  '/',  '0',  '9',  '8',  '1',  '4',
1011                         '1',  '-',  '9',  '5',  '6',  '4',  '6',  '4',
1012                         '3',  '/',  '2',  '1',  '9',  '7',  '0',  '-',
1013                         '-',  '-',  '-',  '-',  '/',  '8',  '2',  '3',
1014                         '6',  '4',  '9',  '2',  '3',  '4',  '7',  '2',
1015                         'w',  'e',  'r',  'e',  'r',  'e',  'w',  'r',
1016                         '0',  '-',  '9',  '2',  '1',  '-',  '3',  '9',
1017                         '1',  '2',  '3',  '-',  '3',  '4',  '/',  0x0d,
1018                         0x01, '/',  '/',  '4',  '9',  '2',  '4',  '0',
1019                         '3',  '-',  '-',  '0',  '9',  '8',  '/',  0xc1,
1020                         '*',  0xff, 'd',  'a',  't',  'a'
1021                       };
1022   int result;
1023 
1024   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
1025 
1026   pdu->type = COAP_MESSAGE_ACK;
1027   pdu->code = COAP_RESPONSE_CODE(204);
1028   pdu->mid = 0x1234;
1029 
1030   CU_ASSERT(pdu->used_size == 0);
1031 
1032   result = coap_add_token(pdu, 2, (const uint8_t *)"\0\0");
1033 
1034   CU_ASSERT(result > 0);
1035   result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 255,
1036                            (const uint8_t *)
1037                            "coap://example.com/12345/%3Fxyz/3048234234/23402348234/239084234-23/%AB%30%af/+123/hfksdh/23480-234-98235/1204/243546345345243/0198sdn3-a-3///aff0934/97u2141/0002/3932423532/56234023/----/=1234=/098141-9564643/21970-----/82364923472wererewr0-921-39123-34/");
1038 
1039   CU_ASSERT(result == 257);
1040   CU_ASSERT(pdu->max_opt == 8);
1041   CU_ASSERT(pdu->used_size == 259);
1042   CU_ASSERT_PTR_NULL(pdu->data);
1043 
1044   result = coap_add_option(pdu, COAP_OPTION_LOCATION_QUERY,
1045                            1, (const uint8_t *)"*");
1046 
1047   CU_ASSERT(result == 2);
1048   CU_ASSERT(pdu->used_size == 261);
1049   CU_ASSERT_PTR_NULL(pdu->data);
1050 
1051   result = coap_insert_option(pdu, COAP_OPTION_LOCATION_PATH, 14,
1052                               (const uint8_t *)"//492403--098/");
1053 
1054   CU_ASSERT(result == 16);
1055   CU_ASSERT(pdu->used_size == 277);
1056   CU_ASSERT_PTR_NULL(pdu->data);
1057 
1058   result = coap_add_data(pdu, 4, (const uint8_t *)"data");
1059 
1060   CU_ASSERT(result > 0);
1061   CU_ASSERT(pdu->used_size == 282);
1062   CU_ASSERT(pdu->data == pdu->token + 278);
1063 
1064   CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4);
1065   CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0);
1066 
1067 }
1068 
1069 /* Remove an option (no data) */
1070 /*
1071  * Next Delta New Delta
1072  *          4        18
1073  *         18        25
1074  */
1075 static void
t_encode_pdu19(void)1076 t_encode_pdu19(void) {
1077   size_t n;
1078   uint8_t  token[] = { 't' };
1079   uint16_t opt_num[] = { 300,   7,  21,  25 };
1080   uint8_t  opt_val[] = {  54,  50,  52,  53 };
1081   uint8_t  data1[] = { 0x74, 0x71, 0x32, 0xd1, 0x01, 0x34, 0x41, 0x35,
1082                        0xe1, 0x00, 0x06, 0x36
1083                      };
1084   uint8_t  data2[] = { 0x74, 0x71, 0x32, 0xd1, 0x05, 0x35, 0xe1, 0x00,
1085                        0x06, 0x36
1086                      };
1087   uint8_t  data3[] = { 0x74, 0xd1, 0x0c, 0x35, 0xe1, 0x00, 0x06, 0x36 };
1088   uint8_t  data4[] = { 0x74, 0xd1, 0x0c, 0x35 };
1089   uint8_t  data5[] = { 0x74 };
1090   uint8_t  data6[] = { 0x74, 0xd1, 0x0c, 0x0a };
1091   int new_val;
1092   unsigned char buf[4];
1093 
1094   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
1095 
1096   CU_ASSERT(pdu->data == NULL);
1097 
1098   coap_add_token(pdu, sizeof(token), token);
1099   for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) {
1100     coap_add_option(pdu, opt_num[n],
1101                     sizeof(opt_val[n]), &opt_val[n]);
1102   }
1103   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
1104 
1105   /* Now remove an option in the middle */
1106   coap_remove_option(pdu, 21);
1107   CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0);
1108 
1109   /* Now remove an option from the start */
1110   coap_remove_option(pdu, 7);
1111   CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0);
1112 
1113   /* Now remove an option from the end */
1114   coap_remove_option(pdu, 300);
1115   CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0);
1116 
1117   /* Now remove the final option */
1118   coap_remove_option(pdu, 25);
1119   CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0);
1120 
1121   /* Now insert an option */
1122   new_val = 10;
1123   coap_update_option(pdu, 25,
1124                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
1125   CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0);
1126 }
1127 
1128 /* Remove an option (no data), but exercise delta boundaries (13 and 269) */
1129 /*
1130  * Next Delta New Delta
1131  *         11        12 if (opt_delta < 13) {
1132  *          1        13 } else if (opt_delta < 269 && decode_next.delta < 13) {
1133  *        254       268 } else if (opt_delta < 269) {
1134  *          1       269 } else if (decode_next.delta < 13) { // opt_delta >= 269
1135  *         71       350 } else if (decode_next.delta < 269) { // opt_delta >= 269
1136  *        320       670 } else { // decode_next.delta >= 269 && opt_delta >= 269
1137  */
1138 static void
t_encode_pdu20(void)1139 t_encode_pdu20(void) {
1140   size_t n;
1141   uint8_t  token[] = { 't' };
1142   uint16_t opt_num[] = { 1,  12,  13,  268, 269, 350, 670 };
1143   uint8_t  opt_val[] = { 50, 51,  52,  53,  54,  55,  56 };
1144   uint8_t  data1[] = { 0x74, 0x11, 0x32, 0xb1, 0x33, 0x11, 0x34, 0xd1,
1145                        0xf2, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1,
1146                        0x00, 0x33, 0x38
1147                      };
1148   uint8_t  data2[] = { 0x74, 0xc1, 0x33, 0x11, 0x34, 0xd1, 0xf2, 0x35,
1149                        0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33,
1150                        0x38
1151                      };
1152   uint8_t  data3[] = { 0x74, 0xd1, 0x00, 0x34, 0xd1, 0xf2, 0x35, 0x11,
1153                        0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38
1154                      };
1155   uint8_t  data4[] = { 0x74, 0xd1, 0xff, 0x35, 0x11, 0x36, 0xd1, 0x44,
1156                        0x37, 0xe1, 0x00, 0x33, 0x38
1157                      };
1158   uint8_t  data5[] = { 0x74, 0xe1, 0x00, 0x00, 0x36, 0xd1, 0x44, 0x37,
1159                        0xe1, 0x00, 0x33, 0x38
1160                      };
1161   uint8_t  data6[] = { 0x74, 0xe1, 0x00, 0x51, 0x37, 0xe1, 0x00, 0x33,
1162                        0x38
1163                      };
1164   uint8_t  data7[] = { 0x74, 0xe1, 0x01, 0x91, 0x38 };
1165   uint8_t  data8[] = { 0x74 };
1166 
1167   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
1168 
1169   CU_ASSERT(pdu->data == NULL);
1170 
1171   coap_add_token(pdu, sizeof(token), token);
1172   /* Put the options in in reverse order to test that logic */
1173   for (n = sizeof(opt_num)/sizeof(opt_num[0]); n > 0; n--) {
1174     coap_insert_option(pdu, opt_num[n-1],
1175                        sizeof(opt_val[n-1]), &opt_val[n-1]);
1176   }
1177   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
1178 
1179   /* Now remove an option from the start */
1180   coap_remove_option(pdu, 1);
1181   CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0);
1182 
1183   /* Now remove an option from the start */
1184   coap_remove_option(pdu, 12);
1185   CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0);
1186 
1187   /* Now remove an option from the start */
1188   coap_remove_option(pdu, 13);
1189   CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0);
1190 
1191   /* Now remove an option from the start */
1192   coap_remove_option(pdu, 268);
1193   CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0);
1194 
1195   /* Now remove an option from the start */
1196   coap_remove_option(pdu, 269);
1197   CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0);
1198 
1199   /* Now remove an option from the start */
1200   coap_remove_option(pdu, 350);
1201   CU_ASSERT(memcmp(pdu->token, data7, pdu->used_size) == 0);
1202 
1203   /* Now remove the final option */
1204   coap_remove_option(pdu, 670);
1205   CU_ASSERT(memcmp(pdu->token, data8, pdu->used_size) == 0);
1206 }
1207 
1208 /* Remove an option (with data) */
1209 /*
1210  * Next Delta New Delta
1211  *          4        18
1212  *         18        25
1213  */
1214 static void
t_encode_pdu21(void)1215 t_encode_pdu21(void) {
1216   size_t n;
1217   uint8_t  token[] = { 't' };
1218   uint16_t opt_num[] = { 300,   7,  21,  25 };
1219   uint8_t  opt_val[] = {  54,  50,  52,  53 };
1220   uint8_t  data[] = { 'd', 'a', 't', 'a' };
1221   uint8_t  data1[] = { 0x74, 0x71, 0x32, 0xd1, 0x01, 0x34, 0x41, 0x35,
1222                        0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74,
1223                        0x61
1224                      };
1225   uint8_t  data2[] = { 0x74, 0x71, 0x32, 0xd1, 0x05, 0x35, 0xe1, 0x00,
1226                        0x06, 0x36, 0xff, 0x64, 0x61, 0x74, 0x61
1227                      };
1228   uint8_t  data3[] = { 0x74, 0xd1, 0x0c, 0x35, 0xe1, 0x00, 0x06, 0x36,
1229                        0xff, 0x64, 0x61, 0x74, 0x61
1230                      };
1231   uint8_t  data4[] = { 0x74, 0xd1, 0x0c, 0x35, 0xff, 0x64, 0x61, 0x74,
1232                        0x61
1233                      };
1234   uint8_t  data5[] = { 0x74, 0xff, 0x64, 0x61, 0x74, 0x61 };
1235   uint8_t  data6[] = { 0x74, 0xd1, 0x0c, 0x0a, 0xff, 0x64, 0x61, 0x74,
1236                        0x61
1237                      };
1238   int new_val;
1239   unsigned char buf[4];
1240 
1241   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
1242 
1243   CU_ASSERT(pdu->data == NULL);
1244 
1245   coap_add_token(pdu, sizeof(token), token);
1246   for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) {
1247     coap_add_option(pdu, opt_num[n],
1248                     sizeof(opt_val[n]), &opt_val[n]);
1249   }
1250   coap_add_data(pdu, sizeof(data), data);
1251   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
1252 
1253   /* Now remove an option in the middle */
1254   coap_remove_option(pdu, 21);
1255   CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0);
1256 
1257   /* Now remove an option from the start */
1258   coap_remove_option(pdu, 7);
1259   CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0);
1260 
1261   /* Now remove an option from the end */
1262   coap_remove_option(pdu, 300);
1263   CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0);
1264 
1265   /* Now remove the final option */
1266   coap_remove_option(pdu, 25);
1267   CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0);
1268 
1269   /* Now insert an option */
1270   new_val = 10;
1271   coap_update_option(pdu, 25,
1272                      coap_encode_var_safe(buf, sizeof(buf), new_val), buf);
1273   CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0);
1274 }
1275 
1276 /* Remove an option (with data), but exercise delta boundaries (13 and 269) */
1277 /*
1278  * Next Delta New Delta
1279  *         11        12 if (opt_delta < 13) {
1280  *          1        13 } else if (opt_delta < 269 && decode_next.delta < 13) {
1281  *        254       268 } else if (opt_delta < 269) {
1282  *          1       269 } else if (decode_next.delta < 13) { // opt_delta >= 269
1283  *         71       350 } else if (decode_next.delta < 269) { // opt_delta >= 269
1284  *        320       670 } else { // decode_next.delta >= 269 && opt_delta >= 269
1285  */
1286 static void
t_encode_pdu22(void)1287 t_encode_pdu22(void) {
1288   size_t n;
1289   uint8_t  token[] = { 't' };
1290   uint16_t opt_num[] = { 1,  12,  13,  268, 269, 350, 670 };
1291   uint8_t  opt_val[] = { 50, 51,  52,  53,  54,  55,  56 };
1292   uint8_t  data[] = { 'd', 'a', 't', 'a' };
1293   uint8_t  data1[] = { 0x74, 0x11, 0x32, 0xb1, 0x33, 0x11, 0x34, 0xd1,
1294                        0xf2, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1,
1295                        0x00, 0x33, 0x38, 0xff, 0x64, 0x61, 0x74, 0x61
1296                      };
1297   uint8_t  data2[] = { 0x74, 0xc1, 0x33, 0x11, 0x34, 0xd1, 0xf2, 0x35,
1298                        0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33,
1299                        0x38, 0xff, 0x64, 0x61, 0x74, 0x61
1300                      };
1301   uint8_t  data3[] = { 0x74, 0xd1, 0x00, 0x34, 0xd1, 0xf2, 0x35, 0x11,
1302                        0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38,
1303                        0xff, 0x64, 0x61, 0x74, 0x61
1304                      };
1305   uint8_t  data4[] = { 0x74, 0xd1, 0xff, 0x35, 0x11, 0x36, 0xd1, 0x44,
1306                        0x37, 0xe1, 0x00, 0x33, 0x38, 0xff, 0x64, 0x61,
1307                        0x74, 0x61
1308                      };
1309   uint8_t  data5[] = { 0x74, 0xe1, 0x00, 0x00, 0x36, 0xd1, 0x44, 0x37,
1310                        0xe1, 0x00, 0x33, 0x38, 0xff, 0x64, 0x61, 0x74,
1311                        0x61
1312                      };
1313   uint8_t  data6[] = { 0x74, 0xe1, 0x00, 0x51, 0x37, 0xe1, 0x00, 0x33,
1314                        0x38, 0xff, 0x64, 0x61, 0x74, 0x61
1315                      };
1316   uint8_t  data7[] = { 0x74, 0xe1, 0x01, 0x91, 0x38, 0xff, 0x64, 0x61,
1317                        0x74, 0x61
1318                      };
1319   uint8_t  data8[] = { 0x74, 0xff, 0x64, 0x61, 0x74, 0x61 };
1320 
1321   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
1322 
1323   CU_ASSERT(pdu->data == NULL);
1324 
1325   coap_add_token(pdu, sizeof(token), token);
1326 
1327   coap_add_data(pdu, sizeof(data), data);
1328 
1329   /* Put the options in in reverse order to test that logic */
1330   for (n = sizeof(opt_num)/sizeof(opt_num[0]); n > 0; n--) {
1331     coap_insert_option(pdu, opt_num[n-1],
1332                        sizeof(opt_val[n-1]), &opt_val[n-1]);
1333   }
1334   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
1335 
1336   /* Now remove an option from the start */
1337   coap_remove_option(pdu, 1);
1338   CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0);
1339 
1340   /* Now remove an option from the start */
1341   coap_remove_option(pdu, 12);
1342   CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0);
1343 
1344   /* Now remove an option from the start */
1345   coap_remove_option(pdu, 13);
1346   CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0);
1347 
1348   /* Now remove an option from the start */
1349   coap_remove_option(pdu, 268);
1350   CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0);
1351 
1352   /* Now remove an option from the start */
1353   coap_remove_option(pdu, 269);
1354   CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0);
1355 
1356   /* Now remove an option from the start */
1357   coap_remove_option(pdu, 350);
1358   CU_ASSERT(memcmp(pdu->token, data7, pdu->used_size) == 0);
1359 
1360   /* Now remove the final option */
1361   coap_remove_option(pdu, 670);
1362   CU_ASSERT(memcmp(pdu->token, data8, pdu->used_size) == 0);
1363 }
1364 
1365 
1366 /* Update token */
1367 static void
t_encode_pdu23(void)1368 t_encode_pdu23(void) {
1369   size_t n;
1370   uint8_t  token[] = { 't' };
1371   uint8_t  new_token[] = { 't', 'o', 'k', 'e', 'n' };
1372   uint16_t opt_num[] = { 300,  10,   7,  21,  25 };
1373   uint8_t  opt_val[] = {  54,  51,  50,  52,  53 };
1374   uint8_t  data[] = { 'd', 'a', 't', 'a' };
1375   uint8_t  data1[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xb1, 0x34, 0x41,
1376                        0x35, 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61,
1377                        0x74, 0x61
1378                      };
1379   uint8_t  data2[] = { 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x71, 0x32, 0x31,
1380                        0x33, 0xb1, 0x34, 0x41, 0x35, 0xe1, 0x00, 0x06,
1381                        0x36, 0xff, 0x64, 0x61, 0x74, 0x61
1382                      };
1383   uint8_t  data3[] = { 0x71, 0x32, 0x31, 0x33, 0xb1, 0x34, 0x41, 0x35,
1384                        0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74,
1385                        0x61
1386                      };
1387 
1388   coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
1389 
1390   CU_ASSERT(pdu->data == NULL);
1391 
1392   coap_add_token(pdu, sizeof(token), token);
1393   for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) {
1394     coap_add_option(pdu, opt_num[n],
1395                     sizeof(opt_val[n]), &opt_val[n]);
1396   }
1397   coap_add_data(pdu, sizeof(data), data);
1398   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
1399 
1400   /* Now update token */
1401   coap_update_token(pdu, sizeof(new_token), new_token);
1402   CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0);
1403 
1404   /* Now restore token */
1405   coap_update_token(pdu, sizeof(token), token);
1406   CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0);
1407 
1408   /* Now set token to zero length */
1409   coap_update_token(pdu, 0, NULL);
1410   CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0);
1411 }
1412 
1413 /* insert option before (large) final one */
1414 static void
t_encode_pdu24(void)1415 t_encode_pdu24(void) {
1416   size_t n;
1417   uint8_t  token[] = { 't' };
1418   uint8_t  buf[4];
1419   uint16_t opt_num[] = { 28,  28,    28,      28 };
1420   uint32_t opt_val[] = { 0x1, 0x100, 0x10000, 0x1000000 };
1421   uint8_t data1[][8] = {
1422     { 0x74, 0xd1, 0x0f, 0x01 },
1423     { 0x74, 0xd2, 0x0f, 0x01, 0x00 },
1424     { 0x74, 0xd3, 0x0f, 0x01, 0x00, 0x00 },
1425     { 0x74, 0xd4, 0x0f, 0x01, 0x00, 0x00, 0x00 }
1426   };
1427   uint8_t  data2[][16] = {
1428     { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x51, 0x01 },
1429     {
1430       0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x52, 0x01,
1431       0x00
1432     },
1433     {
1434       0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x53, 0x01,
1435       0x00, 0x00
1436     },
1437     {
1438       0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x54, 0x01,
1439       0x00, 0x00, 0x00
1440     }
1441   };
1442 
1443   for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) {
1444     coap_pdu_clear(pdu, pdu->max_size);        /* clear PDU */
1445 
1446     CU_ASSERT(pdu->data == NULL);
1447 
1448     coap_add_token(pdu, sizeof(token), token);
1449     coap_add_option(pdu, opt_num[n],
1450                     coap_encode_var_safe(buf, sizeof(buf), opt_val[n]), buf);
1451     CU_ASSERT(memcmp(pdu->token, data1[n], pdu->used_size) == 0);
1452 
1453     /* Now insert option */
1454     coap_insert_option(pdu, 23,
1455                        coap_encode_var_safe(buf, sizeof(buf), 0xfffff6), buf);
1456     CU_ASSERT(memcmp(pdu->token, data2[n], pdu->used_size) == 0);
1457   }
1458 }
1459 
1460 static int
t_pdu_tests_create(void)1461 t_pdu_tests_create(void) {
1462   pdu = coap_pdu_init(0, 0, 0, COAP_DEFAULT_MTU);
1463 
1464   return pdu == NULL;
1465 }
1466 
1467 static int
t_pdu_tests_remove(void)1468 t_pdu_tests_remove(void) {
1469   coap_delete_pdu(pdu);
1470   return 0;
1471 }
1472 
1473 CU_pSuite
t_init_pdu_tests(void)1474 t_init_pdu_tests(void) {
1475   CU_pSuite suite[2];
1476 
1477   suite[0] = CU_add_suite("pdu parser", t_pdu_tests_create, t_pdu_tests_remove);
1478   if (!suite[0]) {                        /* signal error */
1479     fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n",
1480             CU_get_error_msg());
1481 
1482     return NULL;
1483   }
1484 
1485 #define PDU_TEST(s,t)                                                      \
1486   if (!CU_ADD_TEST(s,t)) {                                              \
1487     fprintf(stderr, "W: cannot add pdu parser test (%s)\n",              \
1488             CU_get_error_msg());                                      \
1489   }
1490 
1491   PDU_TEST(suite[0], t_parse_pdu1);
1492   PDU_TEST(suite[0], t_parse_pdu2);
1493   PDU_TEST(suite[0], t_parse_pdu3);
1494   PDU_TEST(suite[0], t_parse_pdu4);
1495   PDU_TEST(suite[0], t_parse_pdu5);
1496   PDU_TEST(suite[0], t_parse_pdu6);
1497   PDU_TEST(suite[0], t_parse_pdu7);
1498   PDU_TEST(suite[0], t_parse_pdu8);
1499   PDU_TEST(suite[0], t_parse_pdu9);
1500   PDU_TEST(suite[0], t_parse_pdu10);
1501   PDU_TEST(suite[0], t_parse_pdu11);
1502   PDU_TEST(suite[0], t_parse_pdu12);
1503   PDU_TEST(suite[0], t_parse_pdu13);
1504   PDU_TEST(suite[0], t_parse_pdu14);
1505   PDU_TEST(suite[0], t_parse_pdu15);
1506   PDU_TEST(suite[0], t_parse_pdu16);
1507   PDU_TEST(suite[0], t_parse_pdu17);
1508 
1509   suite[1] = CU_add_suite("pdu encoder", t_pdu_tests_create, t_pdu_tests_remove);
1510   if (suite[1]) {
1511 #define PDU_ENCODER_TEST(s,t)                                                      \
1512   if (!CU_ADD_TEST(s,t)) {                                              \
1513     fprintf(stderr, "W: cannot add pdu encoder test (%s)\n",              \
1514             CU_get_error_msg());                                      \
1515   }
1516     PDU_ENCODER_TEST(suite[1], t_encode_pdu1);
1517     PDU_ENCODER_TEST(suite[1], t_encode_pdu2);
1518     PDU_ENCODER_TEST(suite[1], t_encode_pdu3);
1519     PDU_ENCODER_TEST(suite[1], t_encode_pdu4);
1520     PDU_ENCODER_TEST(suite[1], t_encode_pdu5);
1521     PDU_ENCODER_TEST(suite[1], t_encode_pdu6);
1522     PDU_ENCODER_TEST(suite[1], t_encode_pdu7);
1523     PDU_ENCODER_TEST(suite[1], t_encode_pdu8);
1524     PDU_ENCODER_TEST(suite[1], t_encode_pdu9);
1525     PDU_ENCODER_TEST(suite[1], t_encode_pdu10);
1526     PDU_ENCODER_TEST(suite[1], t_encode_pdu11);
1527     PDU_ENCODER_TEST(suite[1], t_encode_pdu12);
1528     PDU_ENCODER_TEST(suite[1], t_encode_pdu13);
1529     PDU_ENCODER_TEST(suite[1], t_encode_pdu14);
1530     PDU_ENCODER_TEST(suite[1], t_encode_pdu15);
1531     PDU_ENCODER_TEST(suite[1], t_encode_pdu16);
1532     PDU_ENCODER_TEST(suite[1], t_encode_pdu17);
1533     PDU_ENCODER_TEST(suite[1], t_encode_pdu18);
1534     PDU_ENCODER_TEST(suite[1], t_encode_pdu19);
1535     PDU_ENCODER_TEST(suite[1], t_encode_pdu20);
1536     PDU_ENCODER_TEST(suite[1], t_encode_pdu21);
1537     PDU_ENCODER_TEST(suite[1], t_encode_pdu22);
1538     PDU_ENCODER_TEST(suite[1], t_encode_pdu23);
1539     PDU_ENCODER_TEST(suite[1], t_encode_pdu24);
1540 
1541   } else                         /* signal error */
1542     fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n",
1543             CU_get_error_msg());
1544 
1545   return suite[0];
1546 }
1547