• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 static coap_context_t *ctx;       /* Holds the coap context for most tests */
28 static coap_pdu_t *pdu;           /* Holds the parsed PDU for most tests */
29 static coap_session_t *session;   /* Holds a reference-counted session object
30                                    * that is passed to coap_wellknown_response(). */
31 
32 static void
t_wellknown1(void)33 t_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 
81 static void
t_wellknown2(void)82 t_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 
134 static void
t_wellknown3(void)135 t_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 
166 static void
t_wellknown4(void)167 t_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 
191 static int
t_wkc_tests_create(void)192 t_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 
244 static int
t_wkc_tests_remove(void)245 t_wkc_tests_remove(void) {
246   coap_delete_pdu(pdu);
247   coap_free_context(ctx);
248   return 0;
249 }
250 
251 CU_pSuite
t_init_wellknown_tests(void)252 t_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