1 /* libcoap unit tests
2  *
3  * Copyright (C) 2012,2015 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * This file is part of the CoAP library libcoap. Please see
6  * README for terms of use.
7  */
8 
9 #include "coap_config.h"
10 #include "test_uri.h"
11 
12 #include <coap.h>
13 
14 #include <stdio.h>
15 
16 static void
t_parse_uri1(void)17 t_parse_uri1(void) {
18   char teststr[] = "coap://[::1]/.well-known/core";
19 
20   int result;
21   coap_uri_t uri;
22 
23   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
24   if (result == 0) {
25     CU_ASSERT(uri.host.length == 3);
26     CU_ASSERT_NSTRING_EQUAL(uri.host.s, "::1", 3);
27 
28     CU_ASSERT(uri.port == COAP_DEFAULT_PORT);
29 
30     CU_ASSERT(uri.path.length == 16);
31     CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16);
32 
33     CU_ASSERT(uri.query.length == 0);
34     CU_ASSERT(uri.query.s == NULL);
35   } else {
36     CU_FAIL("uri parser error");
37   }
38 }
39 
40 static void
t_parse_uri2(void)41 t_parse_uri2(void) {
42   char teststr[] = "coap://[::1]:8000/.well-known/core";
43   int result;
44   coap_uri_t uri;
45 
46   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
47   if (result == 0) {
48     CU_ASSERT(uri.host.length == 3);
49     CU_ASSERT_NSTRING_EQUAL(uri.host.s, "::1", 3);
50 
51     CU_ASSERT(uri.port == 8000);
52 
53     CU_ASSERT(uri.path.length == 16);
54     CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16);
55 
56     CU_ASSERT(uri.query.length == 0);
57     CU_ASSERT(uri.query.s == NULL);
58   } else {
59     CU_FAIL("uri parser error");
60   }
61 }
62 
63 static void
t_parse_uri3(void)64 t_parse_uri3(void) {
65   char teststr[] = "coap://localhost/?foo&bla=fasel";
66   int result;
67   coap_uri_t uri;
68 
69   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
70   if (result == 0) {
71     CU_ASSERT(uri.host.length == 9);
72     CU_ASSERT_NSTRING_EQUAL(uri.host.s, "localhost", 9);
73 
74     CU_ASSERT(uri.port == COAP_DEFAULT_PORT);
75 
76     CU_ASSERT(uri.path.length == 0);
77 
78     CU_ASSERT(uri.query.length == 13);
79     CU_ASSERT_NSTRING_EQUAL(uri.query.s, "foo&bla=fasel", 13);
80   } else {
81     CU_FAIL("uri parser error");
82   }
83 }
84 
85 static void
t_parse_uri4(void)86 t_parse_uri4(void) {
87   char teststr[] = "coap://:100000";
88   int result;
89   coap_uri_t uri;
90 
91   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
92   CU_ASSERT(result < 0);
93 }
94 
95 static void
t_parse_uri5(void)96 t_parse_uri5(void) {
97   char teststr[] = "coap://foo:100000";
98   int result;
99   coap_uri_t uri;
100 
101   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
102   if (result == 0) {
103     CU_ASSERT(uri.host.length == 3);
104     CU_ASSERT_NSTRING_EQUAL(uri.host.s, "foo", 3);
105 
106     CU_ASSERT(uri.path.length == 0);
107     CU_ASSERT(uri.path.s == NULL);
108 
109     CU_ASSERT(uri.query.length == 0);
110     CU_ASSERT(uri.query.s == NULL);
111 
112     CU_FAIL("invalid port not detected");
113   } else {
114     CU_PASS("detected invalid port");
115   }
116 }
117 
118 static void
t_parse_uri6(void)119 t_parse_uri6(void) {
120   char teststr[] = "coap://134.102.218.2/.well-known/core";
121   int result;
122   coap_uri_t uri;
123 
124   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
125   if (result == 0) {
126     CU_ASSERT(uri.host.length == 13);
127     CU_ASSERT_NSTRING_EQUAL(uri.host.s, "134.102.218.2", 13);
128 
129     CU_ASSERT(uri.port == COAP_DEFAULT_PORT);
130 
131     CU_ASSERT(uri.path.length == 16);
132     CU_ASSERT_NSTRING_EQUAL(uri.path.s, ".well-known/core", 16);
133 
134     CU_ASSERT(uri.query.length == 0);
135     CU_ASSERT(uri.query.s == NULL);
136   } else {
137     CU_FAIL("uri parser error");
138   }
139 }
140 
141 static void
t_parse_uri7(void)142 t_parse_uri7(void) {
143   char teststr[] = "coap://foo.bar:5683/some_resource/with/multiple/segments";
144   int result;
145   coap_uri_t uri;
146   unsigned char buf[40];
147   size_t buflen = sizeof(buf);
148 
149   /* The list of path segments to check against. Each segment is
150      preceded by a dummy option indicating that holds the (dummy)
151      delta value 0 and the actual segment length. */
152   const unsigned char checkbuf[] = {
153     0x0d, 0x00, 's', 'o', 'm', 'e', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e',
154     0x04, 'w', 'i', 't', 'h',
155     0x08, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e',
156     0x08, 's', 'e', 'g', 'm', 'e', 'n', 't', 's'
157   };
158 
159   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
160   if (result == 0) {
161     CU_ASSERT(uri.host.length == 7);
162     CU_ASSERT_NSTRING_EQUAL(uri.host.s, "foo.bar", 7);
163 
164     CU_ASSERT(uri.port == 5683);
165 
166     CU_ASSERT(uri.path.length == 36);
167     CU_ASSERT_NSTRING_EQUAL(uri.path.s, "some_resource/with/multiple/segments", 36);
168 
169     CU_ASSERT(uri.query.length == 0);
170     CU_ASSERT(uri.query.s == NULL);
171 
172     /* check path segments */
173     result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
174     CU_ASSERT(result == 4);
175     CU_ASSERT(buflen == sizeof(checkbuf));
176     CU_ASSERT_NSTRING_EQUAL(buf, checkbuf, buflen);
177   } else {
178     CU_FAIL("uri parser error");
179   }
180 }
181 
182 static void
t_parse_uri8(void)183 t_parse_uri8(void) {
184   char teststr[] = "http://example.com/%7E%AB%13";
185   int result;
186   coap_uri_t uri;
187 
188   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
189   if (result < 0) {
190     CU_PASS("detected non-coap URI");
191   } else {
192     CU_FAIL("non-coap URI not recognized");
193   }
194 }
195 
196 static void
t_parse_uri9(void)197 t_parse_uri9(void) {
198   char teststr[] = "http://example.com/%x";
199   int result;
200   coap_uri_t uri;
201 
202   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
203   if (result < 0) {
204     CU_PASS("detected non-coap URI");
205   } else {
206     CU_FAIL("non-coap URI not recognized");
207   }
208 }
209 
210 static void
t_parse_uri10(void)211 t_parse_uri10(void) {
212   char teststr[] = "/absolute/path";
213   int result;
214   coap_uri_t uri;
215 
216   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
217   if (result == 0) {
218     CU_ASSERT(uri.host.length == 0);
219     CU_ASSERT(uri.host.s == NULL);
220 
221     CU_ASSERT(uri.port == COAP_DEFAULT_PORT);
222 
223     CU_ASSERT(uri.path.length == 13);
224     CU_ASSERT_NSTRING_EQUAL(uri.path.s, "absolute/path", 13);
225 
226     CU_ASSERT(uri.query.length == 0);
227     CU_ASSERT(uri.query.s == NULL);
228   } else {
229     CU_FAIL("uri parser error");
230   }
231 }
232 
233 static void
t_parse_uri11(void)234 t_parse_uri11(void) {
235   char teststr[] =
236     "coap://xn--18j4d.example/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF";
237   int result;
238   coap_uri_t uri;
239   unsigned char buf[40];
240   size_t buflen = sizeof(buf);
241 
242   /* The list of path segments to check against. Each segment is
243      preceded by a dummy option indicating that holds the (dummy)
244      delta value 0 and the actual segment length. */
245   const unsigned char checkbuf[] = {
246     0x0d, 0x02, 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93,
247     0xE3, 0x81, 0xAB, 0xE3, 0x81, 0xA1, 0xE3, 0x81,
248     0xAF
249   };
250 
251   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
252   if (result == 0) {
253     CU_ASSERT(uri.host.length == 17);
254     CU_ASSERT_NSTRING_EQUAL(uri.host.s, "xn--18j4d.example", 17);
255 
256     CU_ASSERT(uri.port == COAP_DEFAULT_PORT);
257 
258     CU_ASSERT(uri.path.length == 45);
259     CU_ASSERT_NSTRING_EQUAL(uri.path.s,
260 			    "%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF", 45);
261 
262     CU_ASSERT(uri.query.length == 0);
263     CU_ASSERT(uri.query.s == NULL);
264 
265     /* check path segments */
266     result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
267     CU_ASSERT(result == 1);
268     CU_ASSERT(buflen == sizeof(checkbuf));
269     CU_ASSERT_NSTRING_EQUAL(buf, checkbuf, buflen);
270   } else {
271     CU_FAIL("uri parser error");
272   }
273 }
274 
275 static void
t_parse_uri12(void)276 t_parse_uri12(void) {
277   char teststr[] = "coap://198.51.100.1:61616//%2F//?%2F%2F&?%26";
278   int result;
279   coap_uri_t uri;
280   unsigned char buf[40];
281   size_t buflen = sizeof(buf);
282 
283   /* The list of path segments to check against. Each segment is
284      preceded by a dummy option indicating that holds the (dummy)
285      delta value 0 and the actual segment length. */
286   const unsigned char uricheckbuf[] = { 0x00, 0x01, 0x2f, 0x00, 0x00 };
287   const unsigned char querycheckbuf[] = { 0x02, 0x2f, 0x2f, 0x02, 0x3f, 0x26 };
288 
289   result = coap_split_uri((unsigned char *)teststr, strlen(teststr), &uri);
290   if (result == 0) {
291     CU_ASSERT(uri.host.length == 12);
292     CU_ASSERT_NSTRING_EQUAL(uri.host.s, "198.51.100.1", 12);
293 
294     CU_ASSERT(uri.port == 61616);
295 
296     CU_ASSERT(uri.path.length == 6);
297     CU_ASSERT_NSTRING_EQUAL(uri.path.s, "/%2F//", 6);
298 
299     CU_ASSERT(uri.query.length == 11);
300     CU_ASSERT_NSTRING_EQUAL(uri.query.s, "%2F%2F&?%26", 11);
301 
302     /* check path segments */
303     result = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
304     CU_ASSERT(result == 4);
305     CU_ASSERT(buflen == sizeof(uricheckbuf));
306     CU_ASSERT_NSTRING_EQUAL(buf, uricheckbuf, buflen);
307 
308     /* check query segments */
309     buflen = sizeof(buf);
310     result = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
311     CU_ASSERT(result == 2);
312     CU_ASSERT(buflen == sizeof(querycheckbuf));
313     CU_ASSERT_NSTRING_EQUAL(buf, querycheckbuf, buflen);
314   } else {
315     CU_FAIL("uri parser error");
316   }
317 }
318 
319 static void
t_parse_uri13(void)320 t_parse_uri13(void) {
321   uint8_t teststr[] __attribute__ ((aligned (8))) = {
322     0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 'f',  'o',
323     'o',  0x3b, '.',  'w',  'e',  'l',  'l',  '-',
324     'k',  'n',  'o',  'w',  'n',  0x04,  'c', 'o',
325     'r',  'e'
326   };
327 
328   coap_pdu_t pdu = {
329     .max_size = sizeof(teststr),
330     .hdr = (coap_hdr_t *)teststr,
331     .length = sizeof(teststr)
332   };
333 
334   coap_key_t key;
335 
336   coap_hash_request_uri(&pdu, key);
337 
338   CU_ASSERT(sizeof(key) == sizeof(COAP_DEFAULT_WKC_HASHKEY) - 1);
339   CU_ASSERT_NSTRING_EQUAL(key, COAP_DEFAULT_WKC_HASHKEY, sizeof(key));
340 }
341 
342 CU_pSuite
t_init_uri_tests(void)343 t_init_uri_tests(void) {
344   CU_pSuite suite;
345 
346   suite = CU_add_suite("uri parser", NULL, NULL);
347   if (!suite) {			/* signal error */
348     fprintf(stderr, "W: cannot add uri parser test suite (%s)\n",
349 	    CU_get_error_msg());
350 
351     return NULL;
352   }
353 
354 #define URI_TEST(s,t)						      \
355   if (!CU_ADD_TEST(s,t)) {					      \
356     fprintf(stderr, "W: cannot add uri parser test (%s)\n",	      \
357 	    CU_get_error_msg());				      \
358   }
359 
360   URI_TEST(suite, t_parse_uri1);
361   URI_TEST(suite, t_parse_uri2);
362   URI_TEST(suite, t_parse_uri3);
363   URI_TEST(suite, t_parse_uri4);
364   URI_TEST(suite, t_parse_uri5);
365   URI_TEST(suite, t_parse_uri6);
366   URI_TEST(suite, t_parse_uri7);
367   URI_TEST(suite, t_parse_uri8);
368   URI_TEST(suite, t_parse_uri9);
369   URI_TEST(suite, t_parse_uri10);
370   URI_TEST(suite, t_parse_uri11);
371   URI_TEST(suite, t_parse_uri12);
372   URI_TEST(suite, t_parse_uri13);
373 
374   return suite;
375 }
376 
377