1 /* libcoap unit tests
2  *
3  * Copyright (C) 2013,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_error_response.h"
11 
12 #include <coap.h>
13 
14 #include <assert.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 coap_pdu_t *pdu;	      /* Holds the request PDU for most tests */
20 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 
28 static void
t_error_response1(void)29 t_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->hdr->type = COAP_MESSAGE_CON;
38   pdu->hdr->id = htons(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->length == sizeof(teststr));
47   CU_ASSERT(response->hdr->version == 1);
48   CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK);
49   CU_ASSERT(response->hdr->token_length == 0);
50   CU_ASSERT(response->hdr->code == 0x80);
51   CU_ASSERT(pdu->hdr->id == htons(0x1234));
52 
53   CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0);
54 }
55 
56 static void
t_error_response2(void)57 t_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->hdr->type = COAP_MESSAGE_NON;
67   pdu->hdr->id = htons(0x1234);
68   coap_add_token(pdu, 5, (unsigned char *)"token");
69   coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"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->length == sizeof(teststr));
77   CU_ASSERT(response->hdr->version == 1);
78   CU_ASSERT(response->hdr->type == COAP_MESSAGE_NON);
79   CU_ASSERT(response->hdr->token_length == 5);
80   CU_ASSERT(response->hdr->code == 0x84);
81 
82   CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0);
83 }
84 
85 static void
t_error_response3(void)86 t_error_response3(void) {
87   const unsigned char code = COAP_RESPONSE_CODE(402);
88   uint8_t teststr[] = {
89     0x65, code, 0x00, 0x00, 't', 'o', 'k', 'e',
90     'n', 0x90, 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->hdr->type = COAP_MESSAGE_CON;
97   coap_add_token(pdu, 5, (unsigned char *)"token");
98   /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */
99 
100   /* unknown critical option 9 */
101   coap_add_option(pdu, 9, 0, NULL);
102 
103   coap_option_filter_clear(opts);
104   coap_option_setb(opts, 9);
105   response = coap_new_error_response(pdu, code, opts);
106 
107   CU_ASSERT_PTR_NOT_NULL(response);
108 
109   CU_ASSERT(response->length == sizeof(teststr));
110   CU_ASSERT(response->hdr->version == 1);
111   CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK);
112   CU_ASSERT(response->hdr->token_length == 5);
113   CU_ASSERT(response->hdr->code == code);
114 
115   CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0);
116 }
117 
118 static void
t_error_response4(void)119 t_error_response4(void) {
120   const unsigned char 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', 0x9c, 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->hdr->type = COAP_MESSAGE_CON;
136   coap_add_token(pdu, 5, (unsigned char *)"token");
137   /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */
138 
139   /* unknown critical option 9 */
140   coap_add_option(pdu, 9, sizeof(optval), optval);
141 
142   coap_option_filter_clear(opts);
143   coap_option_setb(opts, 9);
144   response = coap_new_error_response(pdu, code, opts);
145 
146   CU_ASSERT_PTR_NOT_NULL(response);
147 
148   CU_ASSERT(response->length == sizeof(teststr));
149   CU_ASSERT(response->hdr->version == 1);
150   CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK);
151   CU_ASSERT(response->hdr->token_length == 5);
152   CU_ASSERT(response->hdr->code == code);
153 
154   CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0);
155 }
156 
157 static void
t_error_response5(void)158 t_error_response5(void) {
159   const unsigned char 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', 0x9d, 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->hdr->type = COAP_MESSAGE_CON;
177   coap_add_token(pdu, 5, (unsigned char *)"token");
178   /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"time"); */
179 
180   /* unknown critical option 9 */
181   coap_add_option(pdu, 9, sizeof(optval), optval);
182 
183   coap_option_filter_clear(opts);
184   coap_option_setb(opts, 9);
185   response = coap_new_error_response(pdu, code, opts);
186 
187   CU_ASSERT_PTR_NOT_NULL(response);
188 
189   CU_ASSERT(response->length == sizeof(teststr));
190   CU_ASSERT(response->hdr->version == 1);
191   CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK);
192   CU_ASSERT(response->hdr->token_length == 5);
193   CU_ASSERT(response->hdr->code == code);
194 
195   CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0);
196 }
197 
198 static void
t_error_response6(void)199 t_error_response6(void) {
200   const unsigned char 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->hdr->type = COAP_MESSAGE_CON;
218   coap_add_token(pdu, 5, (unsigned char *)"token");
219   /* coap_add_option(pdu, COAP_OPTION_URI_HOST, 4, (unsigned char *)"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_setb(opts, 23);
226   response = coap_new_error_response(pdu, code, opts);
227 
228   CU_ASSERT_PTR_NOT_NULL(response);
229 
230   CU_ASSERT(response->length == sizeof(teststr));
231   CU_ASSERT(response->hdr->version == 1);
232   CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK);
233   CU_ASSERT(response->hdr->token_length == 5);
234   CU_ASSERT(response->hdr->code == code);
235 
236   CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0);
237 }
238 
239 static void
t_error_response7(void)240 t_error_response7(void) {
241   const unsigned char 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->hdr->type = COAP_MESSAGE_CON;
259   coap_add_token(pdu, 5, (unsigned char *)"token");
260   /* known option 11 */
261   coap_add_option(pdu, 11, 4, (unsigned char *)"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_setb(opts, 23);
268   response = coap_new_error_response(pdu, code, opts);
269 
270   CU_ASSERT_PTR_NOT_NULL(response);
271 
272   CU_ASSERT(response->length == sizeof(teststr));
273   CU_ASSERT(response->hdr->version == 1);
274   CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK);
275   CU_ASSERT(response->hdr->token_length == 5);
276   CU_ASSERT(response->hdr->code == code);
277 
278   CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0);
279 }
280 
281 static void
t_error_response8(void)282 t_error_response8(void) {
283   const unsigned char 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->hdr->type = COAP_MESSAGE_CON;
295   coap_add_token(pdu, 5, (unsigned char *)"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_setb(opts, 1001);
308   coap_option_setb(opts, 1014);
309   response = coap_new_error_response(pdu, code, opts);
310 
311   CU_ASSERT_PTR_NOT_NULL(response);
312 
313   CU_ASSERT(response->length == sizeof(teststr));
314   CU_ASSERT(response->hdr->version == 1);
315   CU_ASSERT(response->hdr->type == COAP_MESSAGE_ACK);
316   CU_ASSERT(response->hdr->token_length == 5);
317   CU_ASSERT(response->hdr->code == code);
318 
319   CU_ASSERT(memcmp(response->hdr, teststr, sizeof(teststr)) == 0);
320 }
321 
322 static int
t_error_response_tests_create(void)323 t_error_response_tests_create(void) {
324   pdu = coap_pdu_init(0, 0, 0, COAP_MAX_PDU_SIZE);
325 
326   return pdu == NULL;
327 }
328 
329 static int
t_error_response_tests_remove(void)330 t_error_response_tests_remove(void) {
331   coap_delete_pdu(pdu);
332   return 0;
333 }
334 
335 CU_pSuite
t_init_error_response_tests(void)336 t_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 
367