/* libcoap unit tests * * Copyright (C) 2012,2015,2022-2023 Olaf Bergmann * * SPDX-License-Identifier: BSD-2-Clause * * This file is part of the CoAP library libcoap. Please see * README for terms of use. */ #include "test_common.h" #include "test_pdu.h" #include #include #include #include coap_pdu_t *pdu; /* Holds the parsed PDU for most tests */ /************************************************************************ ** PDU decoder ************************************************************************/ static void t_parse_pdu1(void) { uint8_t teststr[] = { 0x40, 0x01, 0x93, 0x34 }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); CU_ASSERT(pdu->type == COAP_MESSAGE_CON); CU_ASSERT(pdu->e_token_length == 0); CU_ASSERT(pdu->code == COAP_REQUEST_CODE_GET); CU_ASSERT(pdu->mid == 0x9334); CU_ASSERT_PTR_NULL(pdu->data); } static void t_parse_pdu2(void) { uint8_t teststr[] = { 0x55, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); CU_ASSERT(pdu->type == COAP_MESSAGE_NON); CU_ASSERT(pdu->e_token_length == 5); CU_ASSERT(pdu->code == 0x69); CU_ASSERT(pdu->mid == 0x1234); CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0); CU_ASSERT_PTR_NULL(pdu->data); } static void t_parse_pdu3(void) { uint8_t teststr[] = { 0x53, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } static void t_parse_pdu4(void) { /* illegal token length (token only 8 bytes) */ uint8_t teststr[] = { 0x59, 0x69, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', '1', '2', '3' }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); /* illegal token length */ teststr[0] = 0x5f; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } static void t_parse_pdu5(void) { /* PDU with options */ uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00 }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); CU_ASSERT(pdu->type == COAP_MESSAGE_NON); CU_ASSERT(pdu->e_token_length == 5); CU_ASSERT(pdu->code == 0x73); CU_ASSERT(pdu->mid == 0x1234); CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0); CU_ASSERT_PTR_NULL(pdu->data); /* FIXME: check options */ } static void t_parse_pdu6(void) { /* PDU with options that exceed the PDU */ uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00, 0xae, 0xf0, 0x03 }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } static void t_parse_pdu7(void) { /* PDU with options and payload */ uint8_t teststr[] = { 0x55, 0x73, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd' }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); CU_ASSERT(pdu->type == COAP_MESSAGE_NON); CU_ASSERT(pdu->e_token_length == 5); CU_ASSERT(pdu->code == 0x73); CU_ASSERT(pdu->mid == 0x1234); CU_ASSERT(memcmp(pdu->token, teststr + 4, 5) == 0); /* FIXME: check options */ CU_ASSERT(pdu->data == pdu->token + 9); CU_ASSERT(memcmp(pdu->data, teststr + 13, 7) == 0); } static void t_parse_pdu8(void) { /* PDU without options but with payload */ uint8_t teststr[] = { 0x50, 0x73, 0x12, 0x34, 0xff, 'p', 'a', 'y', 'l', 'o', 'a', 'd' }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); CU_ASSERT(pdu->type == COAP_MESSAGE_NON); CU_ASSERT(pdu->e_token_length == 0); CU_ASSERT(pdu->code == 0x73); CU_ASSERT(pdu->mid == 0x1234); /* FIXME: check options */ CU_ASSERT(pdu->data == pdu->token + 1); CU_ASSERT(memcmp(pdu->data, teststr + 5, 7) == 0); } static void t_parse_pdu9(void) { /* PDU without options and payload but with payload start marker */ uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34, 0xff }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } static void t_parse_pdu10(void) { /* PDU without payload but with options and payload start marker */ uint8_t teststr[] = { 0x53, 0x73, 0x12, 0x34, 't', 'o', 'k', 0x31, 'a', 0xc1, 0x00, 0xff }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } static void t_parse_pdu11(void) { uint8_t teststr[] = { 0x60, 0x00, 0x12, 0x34 }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); CU_ASSERT(pdu->type == COAP_MESSAGE_ACK); CU_ASSERT(pdu->e_token_length == 0); CU_ASSERT(pdu->code == 0); CU_ASSERT(pdu->mid == 0x1234); } static void t_parse_pdu12(void) { /* RST */ uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34 }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == sizeof(teststr) - 4); CU_ASSERT(pdu->type == COAP_MESSAGE_RST); CU_ASSERT(pdu->e_token_length == 0); CU_ASSERT(pdu->code == 0); CU_ASSERT(pdu->mid == 0x1234); } static void t_parse_pdu13(void) { /* RST with content */ uint8_t teststr[] = { 0x70, 0x00, 0x12, 0x34, 0xff, 'c', 'o', 'n', 't', 'e', 'n', 't' }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } static void t_parse_pdu14(void) { /* ACK with content */ uint8_t teststr[] = { 0x60, 0x00, 0x12, 0x34, 0xff, 'c', 'o', 'n', 't', 'e', 'n', 't' }; int result; result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } /* * To test Issue #199 which reads one byte past the end of teststr[] * before fix to coap_opt_parse() as delta is two byte value and only * one byte left * Credit to OSS-Fuzz for finding this, work done by Bhargava Shastry */ static void t_parse_pdu15(void) { int result; uint8_t teststr[] = { 64, 91, 91, 91, 139, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 91, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 1, 0, 0, 0, 0, 0, 0, 0, 224, 192, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 228, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 1, 0, 0, 0, 0, 0, 0, 0, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224 }; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } static void log_handler(coap_log_t level, const char *message) { (void)level; (void)message; } /* * To test Issue #214 which allows the token size to be set larger than the * decoded PDU in coap_pdu_parse_header(). This then causes coap_show_pdu() * to access invalid memory. * Credit to OSS-Fuzz for finding this, work done by Bhargava Shastry */ static void t_parse_pdu16(void) { int result; coap_pdu_t *testpdu; uint8_t teststr[] = { 0x5a, 0x0a, 0x5b, 0x5b }; testpdu = coap_pdu_init(0, 0, 0, sizeof(teststr)); CU_ASSERT(testpdu != NULL); result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), testpdu); CU_ASSERT(result == 0); coap_set_show_pdu_output(0); coap_set_log_handler(log_handler); coap_show_pdu(COAP_LOG_ERR, testpdu); /* display PDU */ coap_set_log_handler(NULL); coap_delete_pdu(testpdu); } static void t_parse_pdu17(void) { uint8_t teststr[512] = { 0x40, 0x01, 0x93, 0x34 }; size_t idx; int result; /* 245 * option delta 268 > 65535, causing a overflow in the option * number */ for (idx = 4; idx < sizeof(teststr) - 4; idx += 2) { teststr[idx] = 0xd0; /* 1 byte option delta follows */ teststr[idx + 1] = 0xff; /* option delta 268 */ } result = coap_pdu_parse(COAP_PROTO_UDP, teststr, sizeof(teststr), pdu); CU_ASSERT(result == 0); } /************************************************************************ ** PDU encoder ************************************************************************/ static void t_encode_pdu1(void) { uint8_t teststr[] = { 0x45, 0x01, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' }; int result; coap_pdu_clear(pdu, pdu->max_size); pdu->type = COAP_MESSAGE_CON; pdu->code = COAP_REQUEST_CODE_GET; pdu->mid = 0x1234; result = coap_add_token(pdu, 5, (const uint8_t *)"token"); CU_ASSERT(result == 1); CU_ASSERT(pdu->used_size == 5); CU_ASSERT_PTR_NULL(pdu->data); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } static void t_encode_pdu2(void) { coap_log_t level = coap_get_log_level(); size_t old_max = pdu->max_size; int result; coap_pdu_clear(pdu, 3); /* set very small PDU size */ pdu->type = COAP_MESSAGE_CON; pdu->code = COAP_REQUEST_CODE_GET; pdu->mid = 0x1234; coap_set_log_level(COAP_LOG_CRIT); result = coap_add_token(pdu, 5, (const uint8_t *)"token"); coap_set_log_level(level); CU_ASSERT(result == 0); coap_pdu_clear(pdu, old_max); /* restore PDU size */ } static void t_encode_pdu3(void) { int result; coap_bin_const_t check_token; result = coap_add_token(pdu, 15, (const uint8_t *)"123456789012345"); /* length of 15 triggers extension */ CU_ASSERT(result == 1 && pdu->actual_token.length == 15 && pdu->e_token_length == 16 && pdu->token[0] == 2); check_token = coap_pdu_get_token(pdu); CU_ASSERT(check_token.length == 15); } static void t_encode_pdu4(void) { /* PDU with options */ uint8_t teststr[] = { 0x60, 0x99, 0x12, 0x34, 0x3d, 0x05, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x63, 0x6f, 0x61, 0x70, 0x2e, 0x6d, 0x65, 0x84, 0x70, 0x61, 0x74, 0x68, 0x00, 0xe8, 0x1e, 0x28, 0x66, 0x61, 0x6e, 0x63, 0x79, 0x6f, 0x70, 0x74 }; int result; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ pdu->type = COAP_MESSAGE_ACK; pdu->code = 0x99; pdu->mid = 0x1234; CU_ASSERT(pdu->used_size == 0); result = coap_add_option(pdu, COAP_OPTION_URI_HOST, 18, (const uint8_t *)"fancyproxy.coap.me"); CU_ASSERT(result == 20); CU_ASSERT(pdu->max_opt == 3); CU_ASSERT(pdu->used_size == 20); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, COAP_OPTION_URI_PATH, 4, (const uint8_t *)"path"); CU_ASSERT(result == 5); CU_ASSERT(pdu->max_opt == 11); CU_ASSERT(pdu->used_size == 25); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, COAP_OPTION_URI_PATH, 0, NULL); CU_ASSERT(result == 1); CU_ASSERT(pdu->max_opt == 11); CU_ASSERT(pdu->used_size == 26); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, 8000, 8, (const uint8_t *)"fancyopt"); CU_ASSERT(result == 11); CU_ASSERT(pdu->max_opt == 8000); CU_ASSERT(pdu->used_size == 37); CU_ASSERT_PTR_NULL(pdu->data); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } static void t_encode_pdu5(void) { /* PDU with token and options */ uint8_t teststr[] = { 0x68, 0x84, 0x12, 0x34, '1', '2', '3', '4', '5', '6', '7', '8', 0x18, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0xd1, 0x03, 0x12 }; int result; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ pdu->type = COAP_MESSAGE_ACK; pdu->code = COAP_RESPONSE_CODE(404); pdu->mid = 0x1234; CU_ASSERT(pdu->used_size == 0); result = coap_add_token(pdu, 8, (const uint8_t *)"12345678"); CU_ASSERT(pdu->used_size == 8); result = coap_add_option(pdu, COAP_OPTION_IF_MATCH, 8, (const uint8_t *)"ABCDEFGH"); CU_ASSERT(result == 9); CU_ASSERT(pdu->max_opt == 1); CU_ASSERT(pdu->used_size == 17); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, COAP_OPTION_ACCEPT, 1, (const uint8_t *)"\x12"); CU_ASSERT(result == 3); CU_ASSERT(pdu->max_opt == 17); CU_ASSERT(pdu->used_size == 20); CU_ASSERT_PTR_NULL(pdu->data); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } static void t_encode_pdu6(void) { /* PDU with data */ uint8_t teststr[] = { 0x50, 0x02, 0x12, 0x34, 0xff, '1', '2', '3', '4', '5', '6', '7', '8' }; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ pdu->type = COAP_MESSAGE_NON; pdu->code = COAP_REQUEST_CODE_POST; pdu->mid = 0x1234; CU_ASSERT(pdu->used_size == 0); CU_ASSERT_PTR_NULL(pdu->data); coap_add_data(pdu, 8, (const uint8_t *)"12345678"); CU_ASSERT(pdu->used_size == 9); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } static void t_encode_pdu7(void) { /* PDU with empty data */ uint8_t teststr[] = { 0x40, 0x43, 0x12, 0x34 }; int result; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ pdu->type = COAP_MESSAGE_CON; pdu->code = COAP_RESPONSE_CODE(203); pdu->mid = 0x1234; CU_ASSERT(pdu->used_size == 0); result = coap_add_data(pdu, 0, NULL); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == 0); CU_ASSERT_PTR_NULL(pdu->data); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } static void t_encode_pdu8(void) { /* PDU with token and data */ uint8_t teststr[] = { 0x42, 0x43, 0x12, 0x34, 0x00, 0x01, 0xff, 0x00 }; int result; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ pdu->type = COAP_MESSAGE_CON; pdu->code = COAP_RESPONSE_CODE(203); pdu->mid = 0x1234; CU_ASSERT(pdu->used_size == 0); result = coap_add_token(pdu, 2, (const uint8_t *)"\x00\x01"); CU_ASSERT(result > 0); result = coap_add_data(pdu, 1, (const uint8_t *)"\0"); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == 4); CU_ASSERT(pdu->data == pdu->token + 3); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } static void t_encode_pdu9(void) { /* PDU with options and data */ uint8_t teststr[] = { 0x60, 0x44, 0x12, 0x34, 0x48, 's', 'o', 'm', 'e', 'e', 't', 'a', 'g', 0x10, 0xdd, 0x11, 0x04, 's', 'o', 'm', 'e', 'r', 'a', 't', 'h', 'e', 'r', 'l', 'o', 'n', 'g', 'u', 'r', 'i', 0xff, 'd', 'a', 't', 'a' }; int result; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ pdu->type = COAP_MESSAGE_ACK; pdu->code = COAP_RESPONSE_CODE(204); pdu->mid = 0x1234; CU_ASSERT(pdu->used_size == 0); result = coap_add_option(pdu, COAP_OPTION_ETAG, 8, (const uint8_t *)"someetag"); CU_ASSERT(result == 9); CU_ASSERT(pdu->max_opt == 4); CU_ASSERT(pdu->used_size == 9); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, COAP_OPTION_IF_NONE_MATCH, 0, NULL); CU_ASSERT(result == 1); CU_ASSERT(pdu->max_opt == 5); CU_ASSERT(pdu->used_size == 10); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, COAP_OPTION_PROXY_URI, 17, (const uint8_t *)"someratherlonguri"); CU_ASSERT(result == 20); CU_ASSERT(pdu->max_opt == 35); CU_ASSERT(pdu->used_size == 30); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_data(pdu, 4, (const uint8_t *)"data"); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == 35); CU_ASSERT(pdu->data == pdu->token + 31); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } static void t_encode_pdu10(void) { /* PDU with token, options and data */ uint8_t teststr[] = { 0x62, 0x44, 0x12, 0x34, 0x00, 0x00, 0x8d, 0xf2, 'c', 'o', 'a', 'p', ':', '/', '/', 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', '/', '1', '2', '3', '4', '5', '/', '%', '3', 'F', 'x', 'y', 'z', '/', '3', '0', '4', '8', '2', '3', '4', '2', '3', '4', '/', '2', '3', '4', '0', '2', '3', '4', '8', '2', '3', '4', '/', '2', '3', '9', '0', '8', '4', '2', '3', '4', '-', '2', '3', '/', '%', 'A', 'B', '%', '3', '0', '%', 'a', 'f', '/', '+', '1', '2', '3', '/', 'h', 'f', 'k', 's', 'd', 'h', '/', '2', '3', '4', '8', '0', '-', '2', '3', '4', '-', '9', '8', '2', '3', '5', '/', '1', '2', '0', '4', '/', '2', '4', '3', '5', '4', '6', '3', '4', '5', '3', '4', '5', '2', '4', '3', '/', '0', '1', '9', '8', 's', 'd', 'n', '3', '-', 'a', '-', '3', '/', '/', '/', 'a', 'f', 'f', '0', '9', '3', '4', '/', '9', '7', 'u', '2', '1', '4', '1', '/', '0', '0', '0', '2', '/', '3', '9', '3', '2', '4', '2', '3', '5', '3', '2', '/', '5', '6', '2', '3', '4', '0', '2', '3', '/', '-', '-', '-', '-', '/', '=', '1', '2', '3', '4', '=', '/', '0', '9', '8', '1', '4', '1', '-', '9', '5', '6', '4', '6', '4', '3', '/', '2', '1', '9', '7', '0', '-', '-', '-', '-', '-', '/', '8', '2', '3', '6', '4', '9', '2', '3', '4', '7', '2', 'w', 'e', 'r', 'e', 'r', 'e', 'w', 'r', '0', '-', '9', '2', '1', '-', '3', '9', '1', '2', '3', '-', '3', '4', '/', 0x0d, 0x01, '/', '/', '4', '9', '2', '4', '0', '3', '-', '-', '0', '9', '8', '/', 0xc1, '*', 0xff, 'd', 'a', 't', 'a' }; int result; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ pdu->type = COAP_MESSAGE_ACK; pdu->code = COAP_RESPONSE_CODE(204); pdu->mid = 0x1234; CU_ASSERT(pdu->used_size == 0); result = coap_add_token(pdu, 2, (const uint8_t *)"\0\0"); CU_ASSERT(result > 0); result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 255, (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/"); CU_ASSERT(result == 257); CU_ASSERT(pdu->max_opt == 8); CU_ASSERT(pdu->used_size == 259); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 14, (const uint8_t *)"//492403--098/"); CU_ASSERT(result == 16); CU_ASSERT(pdu->max_opt == 8); CU_ASSERT(pdu->used_size == 275); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, COAP_OPTION_LOCATION_QUERY, 1, (const uint8_t *)"*"); CU_ASSERT(result == 2); CU_ASSERT(pdu->max_opt == 20); CU_ASSERT(pdu->used_size == 277); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_data(pdu, 4, (const uint8_t *)"data"); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == 282); CU_ASSERT(pdu->data == pdu->token + 278); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } static void t_encode_pdu11(void) { coap_log_t level = coap_get_log_level(); /* data too long for PDU */ size_t old_max = pdu->max_size; int result; coap_pdu_clear(pdu, 8); /* clear PDU, with small maximum */ CU_ASSERT(pdu->data == NULL); coap_set_log_level(COAP_LOG_CRIT); result = coap_add_data(pdu, 10, (const uint8_t *)"0123456789"); coap_set_log_level(level); CU_ASSERT(result == 0); CU_ASSERT(pdu->data == NULL); CU_ASSERT(pdu->used_size == 0); pdu->max_size = old_max; } static void t_encode_pdu12(void) { coap_optlist_t *optlist = NULL; int n; uint8_t opt_num[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; uint8_t opt_val[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; coap_opt_iterator_t oi; coap_opt_t *option; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); for (n = 0; n < (int)sizeof(opt_num); n++) { coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n], sizeof(opt_val[n]), &opt_val[n])); } coap_add_optlist_pdu(pdu, &optlist); /* Check options in pdu are in right order */ coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL); for (n = 0; n < (int)sizeof(opt_num); n++) { option = coap_option_next(&oi); CU_ASSERT(oi.bad == 0); CU_ASSERT(option != NULL); CU_ASSERT(coap_opt_length(option) == 1); CU_ASSERT(*coap_opt_value(option) == opt_srt[n]); } option = coap_option_next(&oi); CU_ASSERT(oi.bad == 1); CU_ASSERT(option == NULL); coap_delete_optlist(optlist); } static void t_encode_pdu13(void) { coap_optlist_t *optlist = NULL; int n; uint8_t opt_num[] = { 59, 58, 57, 56, 55, 54, 53, 52, 51, 50 }; uint8_t opt_val[] = { 59, 58, 57, 56, 55, 54, 53, 52, 51, 50 }; uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; coap_opt_iterator_t oi; coap_opt_t *option; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); for (n = 0; n < (int)sizeof(opt_num); n++) { coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n], sizeof(opt_val[n]), &opt_val[n])); } coap_add_optlist_pdu(pdu, &optlist); /* Check options in pdu are in right order */ coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL); for (n = 0; n < (int)sizeof(opt_num); n++) { option = coap_option_next(&oi); CU_ASSERT(oi.bad == 0); CU_ASSERT(option != NULL); CU_ASSERT(coap_opt_length(option) == 1); CU_ASSERT(*coap_opt_value(option) == opt_srt[n]); } option = coap_option_next(&oi); CU_ASSERT(oi.bad == 1); CU_ASSERT(option == NULL); coap_delete_optlist(optlist); } static void t_encode_pdu14(void) { coap_optlist_t *optlist = NULL; int n; uint8_t opt_num[] = { 53, 52, 51, 50, 51, 52, 52, 51, 50, 50 }; uint8_t opt_val[] = { 59, 56, 53, 50, 54, 57, 58, 55, 51, 52 }; uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; coap_opt_iterator_t oi; coap_opt_t *option; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); for (n = 0; n < (int)sizeof(opt_num); n++) { coap_insert_optlist(&optlist, coap_new_optlist(opt_num[n], sizeof(opt_val[n]), &opt_val[n])); } coap_add_optlist_pdu(pdu, &optlist); /* Check options in pdu are in right order */ coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL); for (n = 0; n < (int)sizeof(opt_num); n++) { option = coap_option_next(&oi); CU_ASSERT(oi.bad == 0); CU_ASSERT(option != NULL); CU_ASSERT(coap_opt_length(option) == 1); CU_ASSERT(*coap_opt_value(option) == opt_srt[n]); } option = coap_option_next(&oi); CU_ASSERT(oi.bad == 1); CU_ASSERT(option == NULL); coap_delete_optlist(optlist); } /* Check inserting options with random types get put into the PDU in the right order */ static void t_encode_pdu15(void) { size_t n; uint16_t opt_num[] = { 300, 13, 10, 7, 11, 268, 269, 12, 8, 9 }; uint8_t opt_val[] = { 59, 56, 53, 50, 54, 57, 58, 55, 51, 52 }; uint8_t opt_srt[] = { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 }; coap_opt_iterator_t oi; coap_opt_t *option; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { coap_insert_option(pdu, opt_num[n], sizeof(opt_val[n]), &opt_val[n]); } /* Check options in pdu are in right order */ coap_option_iterator_init(pdu, &oi, COAP_OPT_ALL); for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { option = coap_option_next(&oi); CU_ASSERT(oi.bad == 0); CU_ASSERT(option != NULL); CU_ASSERT(coap_opt_length(option) == 1); CU_ASSERT(*coap_opt_value(option) == opt_srt[n]); } option = coap_option_next(&oi); CU_ASSERT(oi.bad == 1); CU_ASSERT(option == NULL); } /* Check changing value of options works */ static void t_encode_pdu16(void) { size_t n; uint16_t opt_num[] = { 300, 10, 7 }; uint8_t opt_val[] = { 53, 51, 50 }; uint8_t data[] = { 'd', 'a', 't', 'a' }; uint8_t data1[] = { 0x71, 0x32, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data2[] = { 0x71, 0x32, 0x33, 0x01, 0x23, 0x45, 0xe1, 0x00, 0x15, 0x35, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data3[] = { 0x70, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data4[] = { 0x71, 0x32, 0x31, 0x33, 0xe4, 0x00, 0x15, 0x06, 0x54, 0x32, 0x10, 0xff, 0x64, 0x61, 0x74, 0x61 }; int new_val; unsigned char buf[4]; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { coap_add_option(pdu, opt_num[n], sizeof(opt_val[n]), &opt_val[n]); } coap_add_data(pdu, sizeof(data), data); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now update an option in the middle */ new_val = 0x12345; coap_update_option(pdu, 10, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); /* Shrink it back again */ new_val = 51; coap_update_option(pdu, 10, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now update an option at the start */ new_val = 0; coap_update_option(pdu, 7, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); /* put it back again */ new_val = 50; coap_update_option(pdu, 7, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now update an option at the end */ new_val = 0x6543210; coap_update_option(pdu, 300, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); /* put it back again */ new_val = 53; coap_update_option(pdu, 300, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); } /* Same as t_encode_pdu16, but without any data, but with a token */ static void t_encode_pdu17(void) { size_t n; uint8_t token[] = { 't' }; uint16_t opt_num[] = { 300, 10, 7 }; uint8_t opt_val[] = { 53, 51, 50 }; uint8_t data1[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35 }; uint8_t data2[] = { 0x74, 0x71, 0x32, 0x33, 0x01, 0x23, 0x45, 0xe1, 0x00, 0x15, 0x35 }; uint8_t data3[] = { 0x74, 0x70, 0x31, 0x33, 0xe1, 0x00, 0x15, 0x35 }; uint8_t data4[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xe4, 0x00, 0x15, 0x06, 0x54, 0x32, 0x10 }; int new_val; unsigned char buf[4]; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); coap_add_token(pdu, sizeof(token), token); for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { coap_add_option(pdu, opt_num[n], sizeof(opt_val[n]), &opt_val[n]); } CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now update an option in the middle */ new_val = 0x12345; coap_update_option(pdu, 10, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); /* Shrink it back again */ new_val = 51; coap_update_option(pdu, 10, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now update an option at the start */ new_val = 0; coap_update_option(pdu, 7, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); /* put it back again */ new_val = 50; coap_update_option(pdu, 7, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now update an option at the end */ new_val = 0x6543210; coap_update_option(pdu, 300, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); /* put it back again */ new_val = 53; coap_update_option(pdu, 300, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); } static void t_encode_pdu18(void) { /* PDU with token, options and data */ uint8_t teststr[] = { 0x62, 0x44, 0x12, 0x34, 0x00, 0x00, 0x8d, 0xf2, 'c', 'o', 'a', 'p', ':', '/', '/', 'e', 'x', 'a', 'm', 'p', 'l', 'e', '.', 'c', 'o', 'm', '/', '1', '2', '3', '4', '5', '/', '%', '3', 'F', 'x', 'y', 'z', '/', '3', '0', '4', '8', '2', '3', '4', '2', '3', '4', '/', '2', '3', '4', '0', '2', '3', '4', '8', '2', '3', '4', '/', '2', '3', '9', '0', '8', '4', '2', '3', '4', '-', '2', '3', '/', '%', 'A', 'B', '%', '3', '0', '%', 'a', 'f', '/', '+', '1', '2', '3', '/', 'h', 'f', 'k', 's', 'd', 'h', '/', '2', '3', '4', '8', '0', '-', '2', '3', '4', '-', '9', '8', '2', '3', '5', '/', '1', '2', '0', '4', '/', '2', '4', '3', '5', '4', '6', '3', '4', '5', '3', '4', '5', '2', '4', '3', '/', '0', '1', '9', '8', 's', 'd', 'n', '3', '-', 'a', '-', '3', '/', '/', '/', 'a', 'f', 'f', '0', '9', '3', '4', '/', '9', '7', 'u', '2', '1', '4', '1', '/', '0', '0', '0', '2', '/', '3', '9', '3', '2', '4', '2', '3', '5', '3', '2', '/', '5', '6', '2', '3', '4', '0', '2', '3', '/', '-', '-', '-', '-', '/', '=', '1', '2', '3', '4', '=', '/', '0', '9', '8', '1', '4', '1', '-', '9', '5', '6', '4', '6', '4', '3', '/', '2', '1', '9', '7', '0', '-', '-', '-', '-', '-', '/', '8', '2', '3', '6', '4', '9', '2', '3', '4', '7', '2', 'w', 'e', 'r', 'e', 'r', 'e', 'w', 'r', '0', '-', '9', '2', '1', '-', '3', '9', '1', '2', '3', '-', '3', '4', '/', 0x0d, 0x01, '/', '/', '4', '9', '2', '4', '0', '3', '-', '-', '0', '9', '8', '/', 0xc1, '*', 0xff, 'd', 'a', 't', 'a' }; int result; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ pdu->type = COAP_MESSAGE_ACK; pdu->code = COAP_RESPONSE_CODE(204); pdu->mid = 0x1234; CU_ASSERT(pdu->used_size == 0); result = coap_add_token(pdu, 2, (const uint8_t *)"\0\0"); CU_ASSERT(result > 0); result = coap_add_option(pdu, COAP_OPTION_LOCATION_PATH, 255, (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/"); CU_ASSERT(result == 257); CU_ASSERT(pdu->max_opt == 8); CU_ASSERT(pdu->used_size == 259); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_option(pdu, COAP_OPTION_LOCATION_QUERY, 1, (const uint8_t *)"*"); CU_ASSERT(result == 2); CU_ASSERT(pdu->used_size == 261); CU_ASSERT_PTR_NULL(pdu->data); result = coap_insert_option(pdu, COAP_OPTION_LOCATION_PATH, 14, (const uint8_t *)"//492403--098/"); CU_ASSERT(result == 16); CU_ASSERT(pdu->used_size == 277); CU_ASSERT_PTR_NULL(pdu->data); result = coap_add_data(pdu, 4, (const uint8_t *)"data"); CU_ASSERT(result > 0); CU_ASSERT(pdu->used_size == 282); CU_ASSERT(pdu->data == pdu->token + 278); CU_ASSERT(coap_pdu_encode_header(pdu, COAP_PROTO_UDP) == 4); CU_ASSERT(memcmp(pdu->token - 4, teststr, sizeof(teststr)) == 0); } /* Remove an option (no data) */ /* * Next Delta New Delta * 4 18 * 18 25 */ static void t_encode_pdu19(void) { size_t n; uint8_t token[] = { 't' }; uint16_t opt_num[] = { 300, 7, 21, 25 }; uint8_t opt_val[] = { 54, 50, 52, 53 }; uint8_t data1[] = { 0x74, 0x71, 0x32, 0xd1, 0x01, 0x34, 0x41, 0x35, 0xe1, 0x00, 0x06, 0x36 }; uint8_t data2[] = { 0x74, 0x71, 0x32, 0xd1, 0x05, 0x35, 0xe1, 0x00, 0x06, 0x36 }; uint8_t data3[] = { 0x74, 0xd1, 0x0c, 0x35, 0xe1, 0x00, 0x06, 0x36 }; uint8_t data4[] = { 0x74, 0xd1, 0x0c, 0x35 }; uint8_t data5[] = { 0x74 }; uint8_t data6[] = { 0x74, 0xd1, 0x0c, 0x0a }; int new_val; unsigned char buf[4]; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); coap_add_token(pdu, sizeof(token), token); for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { coap_add_option(pdu, opt_num[n], sizeof(opt_val[n]), &opt_val[n]); } CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now remove an option in the middle */ coap_remove_option(pdu, 21); CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 7); CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); /* Now remove an option from the end */ coap_remove_option(pdu, 300); CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); /* Now remove the final option */ coap_remove_option(pdu, 25); CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0); /* Now insert an option */ new_val = 10; coap_update_option(pdu, 25, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0); } /* Remove an option (no data), but exercise delta boundaries (13 and 269) */ /* * Next Delta New Delta * 11 12 if (opt_delta < 13) { * 1 13 } else if (opt_delta < 269 && decode_next.delta < 13) { * 254 268 } else if (opt_delta < 269) { * 1 269 } else if (decode_next.delta < 13) { // opt_delta >= 269 * 71 350 } else if (decode_next.delta < 269) { // opt_delta >= 269 * 320 670 } else { // decode_next.delta >= 269 && opt_delta >= 269 */ static void t_encode_pdu20(void) { size_t n; uint8_t token[] = { 't' }; uint16_t opt_num[] = { 1, 12, 13, 268, 269, 350, 670 }; uint8_t opt_val[] = { 50, 51, 52, 53, 54, 55, 56 }; uint8_t data1[] = { 0x74, 0x11, 0x32, 0xb1, 0x33, 0x11, 0x34, 0xd1, 0xf2, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38 }; uint8_t data2[] = { 0x74, 0xc1, 0x33, 0x11, 0x34, 0xd1, 0xf2, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38 }; uint8_t data3[] = { 0x74, 0xd1, 0x00, 0x34, 0xd1, 0xf2, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38 }; uint8_t data4[] = { 0x74, 0xd1, 0xff, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38 }; uint8_t data5[] = { 0x74, 0xe1, 0x00, 0x00, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38 }; uint8_t data6[] = { 0x74, 0xe1, 0x00, 0x51, 0x37, 0xe1, 0x00, 0x33, 0x38 }; uint8_t data7[] = { 0x74, 0xe1, 0x01, 0x91, 0x38 }; uint8_t data8[] = { 0x74 }; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); coap_add_token(pdu, sizeof(token), token); /* Put the options in in reverse order to test that logic */ for (n = sizeof(opt_num)/sizeof(opt_num[0]); n > 0; n--) { coap_insert_option(pdu, opt_num[n-1], sizeof(opt_val[n-1]), &opt_val[n-1]); } CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 1); CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 12); CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 13); CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 268); CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 269); CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 350); CU_ASSERT(memcmp(pdu->token, data7, pdu->used_size) == 0); /* Now remove the final option */ coap_remove_option(pdu, 670); CU_ASSERT(memcmp(pdu->token, data8, pdu->used_size) == 0); } /* Remove an option (with data) */ /* * Next Delta New Delta * 4 18 * 18 25 */ static void t_encode_pdu21(void) { size_t n; uint8_t token[] = { 't' }; uint16_t opt_num[] = { 300, 7, 21, 25 }; uint8_t opt_val[] = { 54, 50, 52, 53 }; uint8_t data[] = { 'd', 'a', 't', 'a' }; uint8_t data1[] = { 0x74, 0x71, 0x32, 0xd1, 0x01, 0x34, 0x41, 0x35, 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data2[] = { 0x74, 0x71, 0x32, 0xd1, 0x05, 0x35, 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data3[] = { 0x74, 0xd1, 0x0c, 0x35, 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data4[] = { 0x74, 0xd1, 0x0c, 0x35, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data5[] = { 0x74, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data6[] = { 0x74, 0xd1, 0x0c, 0x0a, 0xff, 0x64, 0x61, 0x74, 0x61 }; int new_val; unsigned char buf[4]; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); coap_add_token(pdu, sizeof(token), token); for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { coap_add_option(pdu, opt_num[n], sizeof(opt_val[n]), &opt_val[n]); } coap_add_data(pdu, sizeof(data), data); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now remove an option in the middle */ coap_remove_option(pdu, 21); CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 7); CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); /* Now remove an option from the end */ coap_remove_option(pdu, 300); CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); /* Now remove the final option */ coap_remove_option(pdu, 25); CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0); /* Now insert an option */ new_val = 10; coap_update_option(pdu, 25, coap_encode_var_safe(buf, sizeof(buf), new_val), buf); CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0); } /* Remove an option (with data), but exercise delta boundaries (13 and 269) */ /* * Next Delta New Delta * 11 12 if (opt_delta < 13) { * 1 13 } else if (opt_delta < 269 && decode_next.delta < 13) { * 254 268 } else if (opt_delta < 269) { * 1 269 } else if (decode_next.delta < 13) { // opt_delta >= 269 * 71 350 } else if (decode_next.delta < 269) { // opt_delta >= 269 * 320 670 } else { // decode_next.delta >= 269 && opt_delta >= 269 */ static void t_encode_pdu22(void) { size_t n; uint8_t token[] = { 't' }; uint16_t opt_num[] = { 1, 12, 13, 268, 269, 350, 670 }; uint8_t opt_val[] = { 50, 51, 52, 53, 54, 55, 56 }; uint8_t data[] = { 'd', 'a', 't', 'a' }; uint8_t data1[] = { 0x74, 0x11, 0x32, 0xb1, 0x33, 0x11, 0x34, 0xd1, 0xf2, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data2[] = { 0x74, 0xc1, 0x33, 0x11, 0x34, 0xd1, 0xf2, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data3[] = { 0x74, 0xd1, 0x00, 0x34, 0xd1, 0xf2, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data4[] = { 0x74, 0xd1, 0xff, 0x35, 0x11, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data5[] = { 0x74, 0xe1, 0x00, 0x00, 0x36, 0xd1, 0x44, 0x37, 0xe1, 0x00, 0x33, 0x38, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data6[] = { 0x74, 0xe1, 0x00, 0x51, 0x37, 0xe1, 0x00, 0x33, 0x38, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data7[] = { 0x74, 0xe1, 0x01, 0x91, 0x38, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data8[] = { 0x74, 0xff, 0x64, 0x61, 0x74, 0x61 }; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); coap_add_token(pdu, sizeof(token), token); coap_add_data(pdu, sizeof(data), data); /* Put the options in in reverse order to test that logic */ for (n = sizeof(opt_num)/sizeof(opt_num[0]); n > 0; n--) { coap_insert_option(pdu, opt_num[n-1], sizeof(opt_val[n-1]), &opt_val[n-1]); } CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 1); CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 12); CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 13); CU_ASSERT(memcmp(pdu->token, data4, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 268); CU_ASSERT(memcmp(pdu->token, data5, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 269); CU_ASSERT(memcmp(pdu->token, data6, pdu->used_size) == 0); /* Now remove an option from the start */ coap_remove_option(pdu, 350); CU_ASSERT(memcmp(pdu->token, data7, pdu->used_size) == 0); /* Now remove the final option */ coap_remove_option(pdu, 670); CU_ASSERT(memcmp(pdu->token, data8, pdu->used_size) == 0); } /* Update token */ static void t_encode_pdu23(void) { size_t n; uint8_t token[] = { 't' }; uint8_t new_token[] = { 't', 'o', 'k', 'e', 'n' }; uint16_t opt_num[] = { 300, 10, 7, 21, 25 }; uint8_t opt_val[] = { 54, 51, 50, 52, 53 }; uint8_t data[] = { 'd', 'a', 't', 'a' }; uint8_t data1[] = { 0x74, 0x71, 0x32, 0x31, 0x33, 0xb1, 0x34, 0x41, 0x35, 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data2[] = { 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x71, 0x32, 0x31, 0x33, 0xb1, 0x34, 0x41, 0x35, 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, 0x61 }; uint8_t data3[] = { 0x71, 0x32, 0x31, 0x33, 0xb1, 0x34, 0x41, 0x35, 0xe1, 0x00, 0x06, 0x36, 0xff, 0x64, 0x61, 0x74, 0x61 }; coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); coap_add_token(pdu, sizeof(token), token); for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { coap_add_option(pdu, opt_num[n], sizeof(opt_val[n]), &opt_val[n]); } coap_add_data(pdu, sizeof(data), data); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now update token */ coap_update_token(pdu, sizeof(new_token), new_token); CU_ASSERT(memcmp(pdu->token, data2, pdu->used_size) == 0); /* Now restore token */ coap_update_token(pdu, sizeof(token), token); CU_ASSERT(memcmp(pdu->token, data1, pdu->used_size) == 0); /* Now set token to zero length */ coap_update_token(pdu, 0, NULL); CU_ASSERT(memcmp(pdu->token, data3, pdu->used_size) == 0); } /* insert option before (large) final one */ static void t_encode_pdu24(void) { size_t n; uint8_t token[] = { 't' }; uint8_t buf[4]; uint16_t opt_num[] = { 28, 28, 28, 28 }; uint32_t opt_val[] = { 0x1, 0x100, 0x10000, 0x1000000 }; uint8_t data1[][8] = { { 0x74, 0xd1, 0x0f, 0x01 }, { 0x74, 0xd2, 0x0f, 0x01, 0x00 }, { 0x74, 0xd3, 0x0f, 0x01, 0x00, 0x00 }, { 0x74, 0xd4, 0x0f, 0x01, 0x00, 0x00, 0x00 } }; uint8_t data2[][16] = { { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x51, 0x01 }, { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x52, 0x01, 0x00 }, { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x53, 0x01, 0x00, 0x00 }, { 0x74, 0xd3, 0x0a, 0xff, 0xff, 0xf6, 0x54, 0x01, 0x00, 0x00, 0x00 } }; for (n = 0; n < (sizeof(opt_num)/sizeof(opt_num[0])); n++) { coap_pdu_clear(pdu, pdu->max_size); /* clear PDU */ CU_ASSERT(pdu->data == NULL); coap_add_token(pdu, sizeof(token), token); coap_add_option(pdu, opt_num[n], coap_encode_var_safe(buf, sizeof(buf), opt_val[n]), buf); CU_ASSERT(memcmp(pdu->token, data1[n], pdu->used_size) == 0); /* Now insert option */ coap_insert_option(pdu, 23, coap_encode_var_safe(buf, sizeof(buf), 0xfffff6), buf); CU_ASSERT(memcmp(pdu->token, data2[n], pdu->used_size) == 0); } } static int t_pdu_tests_create(void) { pdu = coap_pdu_init(0, 0, 0, COAP_DEFAULT_MTU); return pdu == NULL; } static int t_pdu_tests_remove(void) { coap_delete_pdu(pdu); return 0; } CU_pSuite t_init_pdu_tests(void) { CU_pSuite suite[2]; suite[0] = CU_add_suite("pdu parser", t_pdu_tests_create, t_pdu_tests_remove); if (!suite[0]) { /* signal error */ fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n", CU_get_error_msg()); return NULL; } #define PDU_TEST(s,t) \ if (!CU_ADD_TEST(s,t)) { \ fprintf(stderr, "W: cannot add pdu parser test (%s)\n", \ CU_get_error_msg()); \ } PDU_TEST(suite[0], t_parse_pdu1); PDU_TEST(suite[0], t_parse_pdu2); PDU_TEST(suite[0], t_parse_pdu3); PDU_TEST(suite[0], t_parse_pdu4); PDU_TEST(suite[0], t_parse_pdu5); PDU_TEST(suite[0], t_parse_pdu6); PDU_TEST(suite[0], t_parse_pdu7); PDU_TEST(suite[0], t_parse_pdu8); PDU_TEST(suite[0], t_parse_pdu9); PDU_TEST(suite[0], t_parse_pdu10); PDU_TEST(suite[0], t_parse_pdu11); PDU_TEST(suite[0], t_parse_pdu12); PDU_TEST(suite[0], t_parse_pdu13); PDU_TEST(suite[0], t_parse_pdu14); PDU_TEST(suite[0], t_parse_pdu15); PDU_TEST(suite[0], t_parse_pdu16); PDU_TEST(suite[0], t_parse_pdu17); suite[1] = CU_add_suite("pdu encoder", t_pdu_tests_create, t_pdu_tests_remove); if (suite[1]) { #define PDU_ENCODER_TEST(s,t) \ if (!CU_ADD_TEST(s,t)) { \ fprintf(stderr, "W: cannot add pdu encoder test (%s)\n", \ CU_get_error_msg()); \ } PDU_ENCODER_TEST(suite[1], t_encode_pdu1); PDU_ENCODER_TEST(suite[1], t_encode_pdu2); PDU_ENCODER_TEST(suite[1], t_encode_pdu3); PDU_ENCODER_TEST(suite[1], t_encode_pdu4); PDU_ENCODER_TEST(suite[1], t_encode_pdu5); PDU_ENCODER_TEST(suite[1], t_encode_pdu6); PDU_ENCODER_TEST(suite[1], t_encode_pdu7); PDU_ENCODER_TEST(suite[1], t_encode_pdu8); PDU_ENCODER_TEST(suite[1], t_encode_pdu9); PDU_ENCODER_TEST(suite[1], t_encode_pdu10); PDU_ENCODER_TEST(suite[1], t_encode_pdu11); PDU_ENCODER_TEST(suite[1], t_encode_pdu12); PDU_ENCODER_TEST(suite[1], t_encode_pdu13); PDU_ENCODER_TEST(suite[1], t_encode_pdu14); PDU_ENCODER_TEST(suite[1], t_encode_pdu15); PDU_ENCODER_TEST(suite[1], t_encode_pdu16); PDU_ENCODER_TEST(suite[1], t_encode_pdu17); PDU_ENCODER_TEST(suite[1], t_encode_pdu18); PDU_ENCODER_TEST(suite[1], t_encode_pdu19); PDU_ENCODER_TEST(suite[1], t_encode_pdu20); PDU_ENCODER_TEST(suite[1], t_encode_pdu21); PDU_ENCODER_TEST(suite[1], t_encode_pdu22); PDU_ENCODER_TEST(suite[1], t_encode_pdu23); PDU_ENCODER_TEST(suite[1], t_encode_pdu24); } else /* signal error */ fprintf(stderr, "W: cannot add pdu parser test suite (%s)\n", CU_get_error_msg()); return suite[0]; }