1/* libcoap unit tests 2 * 3 * Copyright (C) 2013--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_wellknown.h" 13 14#if COAP_SERVER_SUPPORT 15#if COAP_CLIENT_SUPPORT 16#include <assert.h> 17#ifdef HAVE_NETINET_IN_H 18#include <netinet/in.h> 19#endif 20#include <stdio.h> 21#include <stdlib.h> 22#include <string.h> 23 24#define TEST_PDU_SIZE 120 25#define TEST_URI_LEN 4 26 27static coap_context_t *ctx; /* Holds the coap context for most tests */ 28static coap_pdu_t *pdu; /* Holds the parsed PDU for most tests */ 29static coap_session_t *session; /* Holds a reference-counted session object 30 * that is passed to coap_wellknown_response(). */ 31 32static void 33t_wellknown1(void) { 34 coap_print_status_t result; 35 coap_resource_t *r; 36 unsigned char buf[40]; 37 size_t buflen, offset, ofs; 38 39 char teststr[] = { /* </>;title="some attribute";ct=0 (31 chars) */ 40 '<', '/', '>', ';', 't', 'i', 't', 'l', 41 'e', '=', '"', 's', 'o', 'm', 'e', ' ', 42 'a', 't', 't', 'r', 'i', 'b', 'u', 't', 43 'e', '"', ';', 'c', 't', '=', '0' 44 }; 45 46 r = coap_resource_init(NULL, 0); 47 48 coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); 49 coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"some attribute\""), 0); 50 51 coap_add_resource(ctx, r); 52 53 for (offset = 0; offset < sizeof(teststr); offset++) { 54 ofs = offset; 55 buflen = sizeof(buf); 56 57 result = coap_print_link(r, buf, &buflen, &ofs); 58 59 CU_ASSERT(result == sizeof(teststr) - offset); 60 CU_ASSERT(buflen == sizeof(teststr)); 61 CU_ASSERT(memcmp(buf, teststr + offset, sizeof(teststr) - offset) == 0); 62 } 63 64 /* offset points behind teststr */ 65 ofs = offset; 66 buflen = sizeof(buf); 67 result = coap_print_link(r, buf, &buflen, &ofs); 68 69 CU_ASSERT(result == 0); 70 CU_ASSERT(buflen == sizeof(teststr)); 71 72 /* offset exceeds buffer */ 73 buflen = sizeof(buf); 74 ofs = buflen; 75 result = coap_print_link(r, buf, &buflen, &ofs); 76 77 CU_ASSERT(result == 0); 78 CU_ASSERT(buflen == sizeof(teststr)); 79} 80 81static void 82t_wellknown2(void) { 83 coap_print_status_t result; 84 coap_resource_t *r; 85 unsigned char buf[10]; /* smaller than teststr */ 86 size_t buflen, offset, ofs; 87 88 char teststr[] = { /* ,</abcd>;if="one";obs (21 chars) */ 89 '<', '/', 'a', 'b', 'c', 'd', '>', ';', 90 'i', 'f', '=', '"', 'o', 'n', 'e', '"', 91 ';', 'o', 'b', 's' 92 }; 93 94 r = coap_resource_init(coap_make_str_const("abcd"), 0); 95 coap_resource_set_get_observable(r, 1); 96 coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"one\""), 0); 97 98 coap_add_resource(ctx, r); 99 100 for (offset = 0; offset < sizeof(teststr) - sizeof(buf); offset++) { 101 ofs = offset; 102 buflen = sizeof(buf); 103 104 result = coap_print_link(r, buf, &buflen, &ofs); 105 106 CU_ASSERT(result == (COAP_PRINT_STATUS_TRUNC | sizeof(buf))); 107 CU_ASSERT(buflen == sizeof(teststr)); 108 CU_ASSERT(ofs == 0); 109 CU_ASSERT(memcmp(buf, teststr + offset, sizeof(buf)) == 0); 110 } 111 112 /* from here on, the resource description fits into buf */ 113 for (; offset < sizeof(teststr); offset++) { 114 ofs = offset; 115 buflen = sizeof(buf); 116 result = coap_print_link(r, buf, &buflen, &ofs); 117 118 CU_ASSERT(result == sizeof(teststr) - offset); 119 CU_ASSERT(buflen == sizeof(teststr)); 120 CU_ASSERT(ofs == 0); 121 CU_ASSERT(memcmp(buf, teststr + offset, 122 COAP_PRINT_OUTPUT_LENGTH(result)) == 0); 123 } 124 125 /* offset exceeds buffer */ 126 buflen = sizeof(buf); 127 ofs = offset; 128 result = coap_print_link(r, buf, &buflen, &ofs); 129 CU_ASSERT(result == 0); 130 CU_ASSERT(buflen == sizeof(teststr)); 131 CU_ASSERT(ofs == offset - sizeof(teststr)); 132} 133 134static void 135t_wellknown3(void) { 136 coap_print_status_t result; 137 int j; 138 coap_resource_t *r; 139 static char uris[2 * 1024]; 140 unsigned char *uribuf = (unsigned char *)uris; 141 unsigned char buf[40]; 142 size_t buflen = sizeof(buf); 143 size_t offset; 144 const uint16_t num_resources = (sizeof(uris) / TEST_URI_LEN) - 1; 145 146 /* ,</0000> (TEST_URI_LEN + 4 chars) */ 147 for (j = 0; j < num_resources; j++) { 148 int len = snprintf((char *)uribuf, TEST_URI_LEN + 1, 149 "%0*d", TEST_URI_LEN, j); 150 coap_str_const_t uri_path = {.length = len, .s = uribuf}; 151 r = coap_resource_init(&uri_path, 0); 152 coap_add_resource(ctx, r); 153 uribuf += TEST_URI_LEN; 154 } 155 156 /* the following test assumes that the first two resources from 157 * t_wellknown1() and t_wellknown2() need more than buflen 158 * characters. Otherwise, CU_ASSERT(result > 0) will fail. 159 */ 160 offset = num_resources * (TEST_URI_LEN + 4); 161 result = coap_print_wellknown(ctx, buf, &buflen, offset, NULL); 162 CU_ASSERT((result & COAP_PRINT_STATUS_ERROR) == 0); 163 CU_ASSERT(COAP_PRINT_OUTPUT_LENGTH(result) > 0); 164} 165 166static void 167t_wellknown4(void) { 168 coap_print_status_t result; 169 coap_string_t *query; 170 unsigned char buf[40]; 171 size_t buflen = sizeof(buf); 172 char teststr[] = { /* ,</abcd>;if="one";obs (21 chars) */ 173 '<', '/', 'a', 'b', 'c', 'd', '>', ';', 174 'i', 'f', '=', '"', 'o', 'n', 'e', '"', 175 ';', 'o', 'b', 's' 176 }; 177 178 /* Check for the resource added in t_wellknown2 */ 179 query = coap_new_string(sizeof("if=one")-1); 180 CU_ASSERT(query != NULL); 181 memcpy(query->s, "if=one", sizeof("if=one")-1); 182 result = coap_print_wellknown(ctx, buf, &buflen, 0, query); 183 CU_ASSERT((result & COAP_PRINT_STATUS_ERROR) == 0); 184 CU_ASSERT(COAP_PRINT_OUTPUT_LENGTH(result) == sizeof(teststr)); 185 CU_ASSERT(buflen == sizeof(teststr)); 186 CU_ASSERT(memcmp(buf, teststr, buflen) == 0); 187 coap_delete_string(query); 188} 189 190 191static int 192t_wkc_tests_create(void) { 193 coap_address_t addr; 194 195 coap_address_init(&addr); 196 197 addr.size = sizeof(struct sockaddr_in6); 198 addr.addr.sin6.sin6_family = AF_INET6; 199 addr.addr.sin6.sin6_addr = in6addr_any; 200 addr.addr.sin6.sin6_port = htons(COAP_DEFAULT_PORT); 201 202 ctx = coap_new_context(&addr); 203 204 addr.addr.sin6.sin6_addr = in6addr_loopback; 205 session = coap_new_client_session(ctx, NULL, &addr, COAP_PROTO_UDP); 206 207 pdu = coap_pdu_init(0, 0, 0, TEST_PDU_SIZE); 208#if 0 209 /* add resources to coap context */ 210 if (ctx && pdu) { 211 coap_resource_t *r; 212 static char _buf[2 * 1024]; 213 unsigned char *buf = (unsigned char *)_buf; 214 int i; 215 216 /* </>;title="some attribute";ct=0 (31 chars) */ 217 r = coap_resource_init(NULL, 0, 0); 218 219 coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); 220 coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"some attribute\""), 0); 221 coap_add_resource(ctx, r); 222 223 /* ,</abcd>;if="one";obs (21 chars) */ 224 r = coap_resource_init((const uint8_t *)"abcd", 4, 0); 225 r->observable = 1; 226 coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"one\""), 0); 227 228 coap_add_resource(ctx, r); 229 230 /* ,</0000> (TEST_URI_LEN + 4 chars) */ 231 for (i = 0; i < sizeof(_buf) / (TEST_URI_LEN + 4); i++) { 232 int len = snprintf((char *)buf, TEST_URI_LEN + 1, 233 "%0*d", TEST_URI_LEN, i); 234 r = coap_resource_init(buf, len, 0); 235 coap_add_resource(ctx, r); 236 buf += TEST_URI_LEN + 1; 237 } 238 239 } 240#endif 241 return ctx == NULL || pdu == NULL; 242} 243 244static int 245t_wkc_tests_remove(void) { 246 coap_delete_pdu(pdu); 247 coap_free_context(ctx); 248 return 0; 249} 250 251CU_pSuite 252t_init_wellknown_tests(void) { 253 CU_pSuite suite; 254 255 suite = CU_add_suite(".well-known/core", t_wkc_tests_create, t_wkc_tests_remove); 256 if (!suite) { /* signal error */ 257 fprintf(stderr, "W: cannot add .well-known/core test suite (%s)\n", 258 CU_get_error_msg()); 259 260 return NULL; 261 } 262 263#define WKC_TEST(s,t) \ 264 if (!CU_ADD_TEST(s,t)) { \ 265 fprintf(stderr, "W: cannot add .well-known/core test (%s)\n", \ 266 CU_get_error_msg()); \ 267 } 268 269 WKC_TEST(suite, t_wellknown1); 270 WKC_TEST(suite, t_wellknown2); 271 WKC_TEST(suite, t_wellknown3); 272 WKC_TEST(suite, t_wellknown4); 273 274 return suite; 275} 276#endif /* COAP_CLIENT_SUPPORT */ 277#endif /* COAP_SERVER_SUPPORT */ 278