xref: /third_party/libcoap/tests/test_pdu.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_pdu.h"
13
14#include <assert.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19coap_pdu_t *pdu;              /* Holds the parsed PDU for most tests */
20
21/************************************************************************
22 ** PDU decoder
23 ************************************************************************/
24
25static void
26t_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
41static void
42t_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
58static void
59t_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
67static void
68t_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
85static void
86t_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
107static void
108t_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
119static void
120t_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
144static void
145t_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
168static void
169t_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
178static void
179t_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
190static void
191t_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
205static void
206t_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
221static void
222t_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
233static void
234t_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 */
251static void
252t_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
282static void
283log_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 */
294static void
295t_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
314static void
315t_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
335static void
336t_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
354static void
355t_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
375static void
376t_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
390static void
391t_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
444static void
445t_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
485static void
486t_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
507static void
508t_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
530static void
531t_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
557static void
558t_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
608static void
609t_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
696static void
697t_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
717static void
718t_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
752static void
753t_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
787static void
788t_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 */
824static void
825t_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 */
857static void
858t_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 */
921static void
922t_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
982static void
983t_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 */
1075static void
1076t_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 */
1138static void
1139t_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 */
1214static void
1215t_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 */
1286static void
1287t_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 */
1367static void
1368t_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 */
1414static void
1415t_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
1460static int
1461t_pdu_tests_create(void) {
1462  pdu = coap_pdu_init(0, 0, 0, COAP_DEFAULT_MTU);
1463
1464  return pdu == NULL;
1465}
1466
1467static int
1468t_pdu_tests_remove(void) {
1469  coap_delete_pdu(pdu);
1470  return 0;
1471}
1472
1473CU_pSuite
1474t_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