1/* libcoap unit tests 2 * 3 * Copyright (C) 2013,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_error_response.h" 13 14#include <assert.h> 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18 19static coap_pdu_t *pdu; /* Holds the request PDU for most tests */ 20static coap_opt_filter_t opts; /* option filter used for generating responses */ 21 22/************************************************************************ 23 ** PDU decoder 24 ************************************************************************/ 25 26/* FIXME: handle COAP_ERROR_PHRASE_LENGTH == 0 */ 27 28static void 29t_error_response1(void) { 30 uint8_t teststr[] = { 31 0x60, 0x80, 0x12, 0x34, 0xff, 'B', 'a', 'd', 32 ' ', 'R', 'e', 'q', 'u', 'e', 's', 't' 33 }; 34 coap_pdu_t *response; 35 36 coap_pdu_clear(pdu, pdu->max_size); 37 pdu->type = COAP_MESSAGE_CON; 38 pdu->mid = 0x1234; 39 40 /* result = coap_add_token(pdu, 5, (unsigned char *)"token"); */ 41 coap_option_filter_clear(&opts); 42 response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(400), &opts); 43 44 CU_ASSERT_PTR_NOT_NULL(response); 45 46 CU_ASSERT(response->used_size == sizeof(teststr) - 4); 47 CU_ASSERT(response->type == COAP_MESSAGE_ACK); 48 CU_ASSERT(response->e_token_length == 0); 49 CU_ASSERT(response->code == 0x80); 50 CU_ASSERT(response->mid == 0x1234); 51 CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); 52 CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); 53 coap_delete_pdu(response); 54} 55 56static void 57t_error_response2(void) { 58 uint8_t teststr[] = { 59 0x55, 0x84, 0x12, 0x34, 't', 'o', 'k', 'e', 60 'n', 0xff, 'N', 'o', 't', ' ', 'F', 'o', 61 'u', 'n', 'd' 62 }; 63 coap_pdu_t *response; 64 65 coap_pdu_clear(pdu, pdu->max_size); 66 pdu->type = COAP_MESSAGE_NON; 67 pdu->mid = 0x1234; 68 coap_add_token(pdu, 5, (const uint8_t *)"token"); 69 coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); 70 71 coap_option_filter_clear(&opts); 72 response = coap_new_error_response(pdu, COAP_RESPONSE_CODE(404), &opts); 73 74 CU_ASSERT_PTR_NOT_NULL(response); 75 76 CU_ASSERT(response->used_size == sizeof(teststr) - 4); 77 CU_ASSERT(response->type == COAP_MESSAGE_NON); 78 CU_ASSERT(response->e_token_length == 5); 79 CU_ASSERT(response->code == 0x84); 80 CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); 81 CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); 82 coap_delete_pdu(response); 83} 84 85static void 86t_error_response3(void) { 87 const uint8_t code = COAP_RESPONSE_CODE(402); 88 uint8_t teststr[] = { 89 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 90 'n', 0xd0, 0x0c, 0xff, 'B', 'a', 'd', ' ', 'O', 91 'p', 't', 'i', 'o', 'n' 92 }; 93 coap_pdu_t *response; 94 95 coap_pdu_clear(pdu, pdu->max_size); 96 pdu->type = COAP_MESSAGE_CON; 97 coap_add_token(pdu, 5, (const uint8_t *)"token"); 98 /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); */ 99 100 /* unknown critical option 25 */ 101 coap_add_option(pdu, 25, 0, NULL); 102 103 coap_option_filter_clear(&opts); 104 coap_option_filter_set(&opts, 25); 105 response = coap_new_error_response(pdu, code, &opts); 106 107 CU_ASSERT_PTR_NOT_NULL(response); 108 109 CU_ASSERT(response->used_size == sizeof(teststr) - 4); 110 CU_ASSERT(response->type == COAP_MESSAGE_ACK); 111 CU_ASSERT(response->e_token_length == 5); 112 CU_ASSERT(response->code == code); 113 CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); 114 CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); 115 coap_delete_pdu(response); 116} 117 118static void 119t_error_response4(void) { 120 const uint8_t code = COAP_RESPONSE_CODE(402); 121 unsigned char optval[] = { 122 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 123 0x08, 0x09, 0x0a, 0x0b 124 }; 125 uint8_t teststr[] = { 126 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 127 'n', 0xdc, 0x0c, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 128 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0xff, 'B', 129 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', 130 'n' 131 }; 132 coap_pdu_t *response; 133 134 coap_pdu_clear(pdu, pdu->max_size); 135 pdu->type = COAP_MESSAGE_CON; 136 coap_add_token(pdu, 5, (const uint8_t *)"token"); 137 /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); */ 138 139 /* unknown critical option 25 */ 140 coap_add_option(pdu, 25, sizeof(optval), optval); 141 142 coap_option_filter_clear(&opts); 143 coap_option_filter_set(&opts, 25); 144 response = coap_new_error_response(pdu, code, &opts); 145 146 CU_ASSERT_PTR_NOT_NULL(response); 147 148 CU_ASSERT(response->used_size == sizeof(teststr) - 4); 149 CU_ASSERT(response->type == COAP_MESSAGE_ACK); 150 CU_ASSERT(response->e_token_length == 5); 151 CU_ASSERT(response->code == code); 152 CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); 153 CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); 154 coap_delete_pdu(response); 155} 156 157static void 158t_error_response5(void) { 159 const uint8_t code = COAP_RESPONSE_CODE(402); 160 unsigned char optval[] = { 161 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 162 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 163 0x10, 0x11, 0x12 164 }; 165 uint8_t teststr[] = { 166 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 167 'n', 0xdd, 0x0c, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, 168 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 169 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, 'B', 170 'a', 'd', ' ', 'O', 'p', 't', 'i', 'o', 171 'n' 172 }; 173 coap_pdu_t *response; 174 175 coap_pdu_clear(pdu, pdu->max_size); 176 pdu->type = COAP_MESSAGE_CON; 177 coap_add_token(pdu, 5, (const uint8_t *)"token"); 178 /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); */ 179 180 /* unknown critical option 25 */ 181 coap_add_option(pdu, 25, sizeof(optval), optval); 182 183 coap_option_filter_clear(&opts); 184 coap_option_filter_set(&opts, 25); 185 response = coap_new_error_response(pdu, code, &opts); 186 187 CU_ASSERT_PTR_NOT_NULL(response); 188 189 CU_ASSERT(response->used_size == sizeof(teststr) - 4); 190 CU_ASSERT(response->type == COAP_MESSAGE_ACK); 191 CU_ASSERT(response->e_token_length == 5); 192 CU_ASSERT(response->code == code); 193 CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); 194 CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); 195 coap_delete_pdu(response); 196} 197 198static void 199t_error_response6(void) { 200 const uint8_t code = COAP_RESPONSE_CODE(402); 201 unsigned char optval[] = { 202 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 203 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 204 0x10, 0x11, 0x12 205 }; 206 uint8_t teststr[] = { 207 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 208 'n', 0xdd, 0x0a, 0x06, 0x00, 0x01, 0x02, 0x03, 209 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 210 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, 211 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', 212 'o', 'n' 213 }; 214 coap_pdu_t *response; 215 216 coap_pdu_clear(pdu, pdu->max_size); 217 pdu->type = COAP_MESSAGE_CON; 218 coap_add_token(pdu, 5, (const uint8_t *)"token"); 219 /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (const uint8_t *)"time"); */ 220 221 /* unknown critical option 23 */ 222 coap_add_option(pdu, 23, sizeof(optval), optval); 223 224 coap_option_filter_clear(&opts); 225 coap_option_filter_set(&opts, 23); 226 response = coap_new_error_response(pdu, code, &opts); 227 228 CU_ASSERT_PTR_NOT_NULL(response); 229 230 CU_ASSERT(response->used_size == sizeof(teststr) - 4); 231 CU_ASSERT(response->type == COAP_MESSAGE_ACK); 232 CU_ASSERT(response->e_token_length == 5); 233 CU_ASSERT(response->code == code); 234 CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); 235 CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); 236 coap_delete_pdu(response); 237} 238 239static void 240t_error_response7(void) { 241 const uint8_t code = COAP_RESPONSE_CODE(402); 242 unsigned char optval[] = { 243 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 244 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 245 0x10, 0x11, 0x12 246 }; 247 uint8_t teststr[] = { 248 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 249 'n', 0xdd, 0x0a, 0x06, 0x00, 0x01, 0x02, 0x03, 250 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 251 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0xff, 252 'B', 'a', 'd', ' ', 'O', 'p', 't', 'i', 253 'o', 'n' 254 }; 255 coap_pdu_t *response; 256 257 coap_pdu_clear(pdu, pdu->max_size); 258 pdu->type = COAP_MESSAGE_CON; 259 coap_add_token(pdu, 5, (const uint8_t *)"token"); 260 /* known option 11 */ 261 coap_add_option(pdu, 11, 4, (const uint8_t *)"time"); 262 263 /* unknown critical option 23 */ 264 coap_add_option(pdu, 23, sizeof(optval), optval); 265 266 coap_option_filter_clear(&opts); 267 coap_option_filter_set(&opts, 23); 268 response = coap_new_error_response(pdu, code, &opts); 269 270 CU_ASSERT_PTR_NOT_NULL(response); 271 272 CU_ASSERT(response->used_size == sizeof(teststr) - 4); 273 CU_ASSERT(response->type == COAP_MESSAGE_ACK); 274 CU_ASSERT(response->e_token_length == 5); 275 CU_ASSERT(response->code == code); 276 CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); 277 CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); 278 coap_delete_pdu(response); 279} 280 281static void 282t_error_response8(void) { 283 const uint8_t code = COAP_RESPONSE_CODE(503); 284 uint8_t teststr[] = { 285 0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e', 286 'n', 0xe0, 0x02, 0xdc, 0xd0, 0x00, 0xff, 'S', 287 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'U', 288 'n', 'a', 'v', 'a', 'i', 'l', 'a', 'b', 289 'l', 'e' 290 }; 291 coap_pdu_t *response; 292 293 coap_pdu_clear(pdu, pdu->max_size); 294 pdu->type = COAP_MESSAGE_CON; 295 coap_add_token(pdu, 5, (const uint8_t *)"token"); 296 /* known option 1000 */ 297 coap_add_option(pdu, 1000, 0, NULL); 298 299 /* unknown options 1001 and 1014 */ 300 coap_add_option(pdu, 1001, 0, NULL); 301 coap_add_option(pdu, 1014, 0, NULL); 302 303 /* known option 2000 */ 304 coap_add_option(pdu, 2000, 0, NULL); 305 306 coap_option_filter_clear(&opts); 307 coap_option_filter_set(&opts, 1001); 308 coap_option_filter_set(&opts, 1014); 309 response = coap_new_error_response(pdu, code, &opts); 310 311 CU_ASSERT_PTR_NOT_NULL(response); 312 313 CU_ASSERT(response->used_size == sizeof(teststr) - 4); 314 CU_ASSERT(response->type == COAP_MESSAGE_ACK); 315 CU_ASSERT(response->e_token_length == 5); 316 CU_ASSERT(response->code == code); 317 CU_ASSERT(coap_pdu_encode_header(response, COAP_PROTO_UDP) == 4); 318 CU_ASSERT(memcmp(response->token - 4, teststr, sizeof(teststr)) == 0); 319 coap_delete_pdu(response); 320} 321 322static int 323t_error_response_tests_create(void) { 324 pdu = coap_pdu_init(0, 0, 0, COAP_DEFAULT_MTU); 325 326 return pdu == NULL; 327} 328 329static int 330t_error_response_tests_remove(void) { 331 coap_delete_pdu(pdu); 332 return 0; 333} 334 335CU_pSuite 336t_init_error_response_tests(void) { 337 CU_pSuite suite[1]; 338 339 suite[0] = CU_add_suite("error response generator", 340 t_error_response_tests_create, 341 t_error_response_tests_remove); 342 if (!suite[0]) { /* signal error */ 343 fprintf(stderr, "W: cannot add error response generator test suite (%s)\n", 344 CU_get_error_msg()); 345 346 return NULL; 347 } 348 349#define ERROR_RESPONSE_TEST(s,t) \ 350 if (!CU_ADD_TEST(s,t)) { \ 351 fprintf(stderr, "W: cannot add error response generator test (%s)\n", \ 352 CU_get_error_msg()); \ 353 } 354 355 ERROR_RESPONSE_TEST(suite[0], t_error_response1); 356 ERROR_RESPONSE_TEST(suite[0], t_error_response2); 357 ERROR_RESPONSE_TEST(suite[0], t_error_response3); 358 ERROR_RESPONSE_TEST(suite[0], t_error_response4); 359 ERROR_RESPONSE_TEST(suite[0], t_error_response5); 360 ERROR_RESPONSE_TEST(suite[0], t_error_response6); 361 ERROR_RESPONSE_TEST(suite[0], t_error_response7); 362 ERROR_RESPONSE_TEST(suite[0], t_error_response8); 363 364 return suite[0]; 365} 366