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