• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015 SPUDlib authors.  See LICENSE file.
3  */
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <stdbool.h>
7 #include <stdio.h>
8 #include <assert.h>
9 #include <string.h>
10 
11 #include "cn-cbor/cn-cbor.h"
12 
13 #define CTEST_MAIN
14 #include "ctest.h"
15 
main(int argc,const char * argv[])16 int main(int argc, const char *argv[])
17 {
18     return ctest_main(argc, argv);
19 }
20 
21 #ifdef USE_CBOR_CONTEXT
22 #define CONTEXT_NULL , NULL
23 #define CONTEXT_NULL_COMMA NULL,
24 #else
25 #define CONTEXT_NULL
26 #define CONTEXT_NULL_COMMA
27 #endif
28 
29 typedef struct _buffer {
30     size_t sz;
31     unsigned char *ptr;
32 } buffer;
33 
parse_hex(char * inp,buffer * b)34 static bool parse_hex(char *inp, buffer *b)
35 {
36     int len = strlen(inp);
37     size_t i;
38     if (len%2 != 0) {
39         b->sz = -1;
40         b->ptr = NULL;
41         return false;
42     }
43     b->sz  = len / 2;
44     b->ptr = malloc(b->sz);
45     for (i=0; i<b->sz; i++) {
46         sscanf(inp+(2*i), "%02hhx", &b->ptr[i]);
47     }
48     return true;
49 }
50 
CTEST(cbor,error)51 CTEST(cbor, error)
52 {
53     ASSERT_STR(cn_cbor_error_str[CN_CBOR_NO_ERROR], "CN_CBOR_NO_ERROR");
54     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_OUT_OF_DATA], "CN_CBOR_ERR_OUT_OF_DATA");
55     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED], "CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED");
56     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_ODD_SIZE_INDEF_MAP], "CN_CBOR_ERR_ODD_SIZE_INDEF_MAP");
57     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_BREAK_OUTSIDE_INDEF], "CN_CBOR_ERR_BREAK_OUTSIDE_INDEF");
58     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_MT_UNDEF_FOR_INDEF], "CN_CBOR_ERR_MT_UNDEF_FOR_INDEF");
59     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_RESERVED_AI], "CN_CBOR_ERR_RESERVED_AI");
60     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING], "CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING");
61     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_INVALID_PARAMETER], "CN_CBOR_ERR_INVALID_PARAMETER");
62     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_OUT_OF_MEMORY], "CN_CBOR_ERR_OUT_OF_MEMORY");
63     ASSERT_STR(cn_cbor_error_str[CN_CBOR_ERR_FLOAT_NOT_SUPPORTED], "CN_CBOR_ERR_FLOAT_NOT_SUPPORTED");
64 }
65 
CTEST(cbor,parse)66 CTEST(cbor, parse)
67 {
68     cn_cbor_errback err;
69     char *tests[] = {
70         "00",         // 0
71         "01",         // 1
72         "17",         // 23
73         "1818",       // 24
74         "190100",     // 256
75         "1a00010000", // 65536
76         "1b0000000100000000", // 4294967296
77         "20",         // -1
78         "37",         // -24
79         "3818",       // -25
80         "390100",     // -257
81         "3a00010000", // -65537
82         "3b0000000100000000", // -4294967297
83         "4161",     // h"a"
84         "6161",     // "a"
85         "80",       // []
86         "8100",     // [0]
87         "820102",   // [1,2]
88         "818100",   // [[0]]
89         "a1616100",	// {"a":0}
90         "d8184100", // tag
91         "f4",	      // false
92         "f5",	      // true
93         "f6",	      // null
94         "f7",	      // undefined
95         "f8ff",     // simple(255)
96 #ifndef CBOR_NO_FLOAT
97         "f93c00",     // 1.0
98         "f9bc00",     // -1.0
99         "f903ff",     // 6.097555160522461e-05
100         "f90400",     // 6.103515625e-05
101         "f907ff",     // 0.00012201070785522461
102         "f90800",     // 0.0001220703125
103         "fa47800000", // 65536.0
104         "fb3ff199999999999a",     // 1.1
105         "f97e00",   // NaN
106 #endif /* CBOR_NO_FLOAT */
107         "5f42010243030405ff",     // (_ h'0102', h'030405')
108         "7f61616161ff",           // (_ "a", "a")
109         "9fff",                   // [_ ]
110         "9f9f9fffffff",           // [_ [_ [_ ]]]
111         "9f009f00ff00ff",         // [_ 0, [_ 0], 0]
112         "bf61610161629f0203ffff", // {_ "a": 1, "b": [_ 2, 3]}
113     };
114     cn_cbor *cb;
115     buffer b;
116     size_t i;
117     unsigned char encoded[1024];
118     ssize_t enc_sz;
119 
120     for (i=0; i<sizeof(tests)/sizeof(char*); i++) {
121         ASSERT_TRUE(parse_hex(tests[i], &b));
122         err.err = CN_CBOR_NO_ERROR;
123         cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
124         //CTEST_LOG("%s: %s", tests[i], cn_cbor_error_str[err.err]);
125         ASSERT_EQUAL(err.err, CN_CBOR_NO_ERROR);
126         ASSERT_NOT_NULL(cb);
127 
128         enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), cb);
129         ASSERT_DATA(b.ptr, b.sz, encoded, enc_sz);
130         free(b.ptr);
131         cn_cbor_free(cb CONTEXT_NULL);
132     }
133 }
134 
135 
CTEST(cbor,parse_normalize)136 CTEST(cbor, parse_normalize)
137 {
138     cn_cbor_errback err;
139     char *basic_tests[] = {
140       "00", "00",                       // 0
141       "1800", "00",
142       "1818", "1818",
143       "190000", "00",
144       "190018", "1818",
145       "1a00000000", "00",
146       "1b0000000000000000", "00",
147       "20", "20",                       // -1
148       "3800", "20",
149       "c600", "c600",                   // 6(0) (undefined tag)
150       "d80600", "c600",
151       "d9000600", "c600",
152     };
153     char *float_tests[] = {
154       "fb3ff0000000000000", "f93c00",   // 1.0
155       "fbbff0000000000000", "f9bc00",   // -1.0
156       "fb40f86a0000000000", "fa47c35000", // 100000.0
157       "fb7ff8000000000000", "f97e00",   // NaN
158       "fb3e70000000000000", "f90001",   // 5.960464477539063e-08
159       "fb3e78000000000000", "fa33c00000", //  8.940696716308594e-08
160       "fb3e80000000000000", "f90002",   // 1.1920928955078125e-07
161     };
162     cn_cbor *cb;
163     buffer b, b2;
164     size_t i;
165     unsigned char encoded[1024];
166     ssize_t enc_sz;
167 
168     for (i=0; i<sizeof(basic_tests)/sizeof(char*); i+=2) {
169         ASSERT_TRUE(parse_hex(basic_tests[i], &b));
170         ASSERT_TRUE(parse_hex(basic_tests[i+1], &b2));
171         err.err = CN_CBOR_NO_ERROR;
172         cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
173         CTEST_LOG("%s: %s", basic_tests[i], cn_cbor_error_str[err.err]);
174         ASSERT_EQUAL(err.err, CN_CBOR_NO_ERROR);
175         ASSERT_NOT_NULL(cb);
176 
177         enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), cb);
178         ASSERT_DATA(b2.ptr, b2.sz, encoded, enc_sz);
179         free(b.ptr);
180         free(b2.ptr);
181         cn_cbor_free(cb CONTEXT_NULL);
182     }
183 
184     for (i=0; i<sizeof(float_tests)/sizeof(char*); i+=2) {
185         ASSERT_TRUE(parse_hex(float_tests[i], &b));
186         ASSERT_TRUE(parse_hex(float_tests[i+1], &b2));
187         err.err = CN_CBOR_NO_ERROR;
188         cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
189         CTEST_LOG("%s: %s", float_tests[i], cn_cbor_error_str[err.err]);
190 #ifndef CBOR_NO_FLOAT
191         ASSERT_EQUAL(err.err, CN_CBOR_NO_ERROR);
192         ASSERT_NOT_NULL(cb);
193 #else /* CBOR_NO_FLOAT */
194         ASSERT_EQUAL(err.err, CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
195         ASSERT_NULL(cb);
196 #endif /* CBOR_NO_FLOAT */
197 
198         /* enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), cb); */
199         /* ASSERT_DATA(b2.ptr, b2.sz, encoded, enc_sz); */
200         free(b.ptr);
201         free(b2.ptr);
202         cn_cbor_free(cb CONTEXT_NULL);
203     }
204 }
205 
206 typedef struct _cbor_failure
207 {
208     char *hex;
209     cn_cbor_error err;
210 } cbor_failure;
211 
CTEST(cbor,fail)212 CTEST(cbor, fail)
213 {
214     cn_cbor_errback err;
215     cbor_failure tests[] = {
216         {"81", CN_CBOR_ERR_OUT_OF_DATA},
217         {"0000", CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED},
218         {"bf00ff", CN_CBOR_ERR_ODD_SIZE_INDEF_MAP},
219         {"ff", CN_CBOR_ERR_BREAK_OUTSIDE_INDEF},
220         {"1f", CN_CBOR_ERR_MT_UNDEF_FOR_INDEF},
221         {"1c", CN_CBOR_ERR_RESERVED_AI},
222         {"7f4100", CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING},
223     };
224     cn_cbor *cb;
225     buffer b;
226     size_t i;
227     uint8_t buf[10];
228     cn_cbor inv = {CN_CBOR_INVALID, 0, {0}, 0, NULL, NULL, NULL, NULL};
229 
230     ASSERT_EQUAL(-1, cn_cbor_encoder_write(buf, 0, sizeof(buf), &inv));
231 
232     for (i=0; i<sizeof(tests)/sizeof(cbor_failure); i++) {
233         ASSERT_TRUE(parse_hex(tests[i].hex, &b));
234         cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
235         ASSERT_NULL(cb);
236         ASSERT_EQUAL(err.err, tests[i].err);
237 
238         free(b.ptr);
239         cn_cbor_free(cb CONTEXT_NULL);
240     }
241 }
242 
243 // Decoder loses float size information
CTEST(cbor,float)244 CTEST(cbor, float)
245 {
246 #ifndef CBOR_NO_FLOAT
247     cn_cbor_errback err;
248     char *tests[] = {
249         "f90001", // 5.960464477539063e-08
250         "f9c400", // -4.0
251         "fa47c35000", // 100000.0
252         "f97e00", // Half NaN, half beast
253         "f9fc00", // -Inf
254         "f97c00", // Inf
255     };
256     cn_cbor *cb;
257     buffer b;
258     size_t i;
259     unsigned char encoded[1024];
260     ssize_t enc_sz;
261 
262     for (i=0; i<sizeof(tests)/sizeof(char*); i++) {
263         ASSERT_TRUE(parse_hex(tests[i], &b));
264         cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
265         ASSERT_NOT_NULL(cb);
266 
267         enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), cb);
268         ASSERT_DATA(b.ptr, b.sz, encoded, enc_sz);
269 
270         free(b.ptr);
271         cn_cbor_free(cb CONTEXT_NULL);
272     }
273 #endif /* CBOR_NO_FLOAT */
274 }
275 
CTEST(cbor,getset)276 CTEST(cbor, getset)
277 {
278     buffer b;
279     cn_cbor *cb;
280     cn_cbor *val;
281     cn_cbor_errback err;
282 
283     ASSERT_TRUE(parse_hex("a40000436363630262626201616100", &b));
284     cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
285     ASSERT_NOT_NULL(cb);
286     val = cn_cbor_mapget_string(cb, "a");
287     ASSERT_NOT_NULL(val);
288     val = cn_cbor_mapget_string(cb, "bb");
289     ASSERT_NOT_NULL(val);
290     val = cn_cbor_mapget_string(cb, "ccc");
291     ASSERT_NOT_NULL(val);
292     val = cn_cbor_mapget_string(cb, "b");
293     ASSERT_NULL(val);
294     free(b.ptr);
295     cn_cbor_free(cb CONTEXT_NULL);
296 
297     ASSERT_TRUE(parse_hex("a3616100006161206162", &b));
298     cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
299     ASSERT_NOT_NULL(cb);
300     val = cn_cbor_mapget_int(cb, 0);
301     ASSERT_NOT_NULL(val);
302     val = cn_cbor_mapget_int(cb, -1);
303     ASSERT_NOT_NULL(val);
304     val = cn_cbor_mapget_int(cb, 1);
305     ASSERT_NULL(val);
306     free(b.ptr);
307     cn_cbor_free(cb CONTEXT_NULL);
308 
309     ASSERT_TRUE(parse_hex("8100", &b));
310     cb = cn_cbor_decode(b.ptr, b.sz CONTEXT_NULL, &err);
311     ASSERT_NOT_NULL(cb);
312     val = cn_cbor_index(cb, 0);
313     ASSERT_NOT_NULL(val);
314     val = cn_cbor_index(cb, 1);
315     ASSERT_NULL(val);
316     val = cn_cbor_index(cb, -1);
317     ASSERT_NULL(val);
318     free(b.ptr);
319     cn_cbor_free(cb CONTEXT_NULL);
320 }
321 
CTEST(cbor,create)322 CTEST(cbor, create)
323 {
324     cn_cbor_errback err;
325     const cn_cbor* val;
326     const char* data = "abc";
327     cn_cbor *cb_map = cn_cbor_map_create(CONTEXT_NULL_COMMA &err);
328     cn_cbor *cb_int;
329     cn_cbor *cb_data;
330 #ifndef CBOR_NO_FLOAT
331     cn_cbor *cb_dbl;
332 #endif
333 
334     ASSERT_NOT_NULL(cb_map);
335     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
336 
337     cb_int = cn_cbor_int_create(256 CONTEXT_NULL, &err);
338     ASSERT_NOT_NULL(cb_int);
339     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
340 
341     cb_data = cn_cbor_data_create((const uint8_t*)data, 4 CONTEXT_NULL, &err);
342     ASSERT_NOT_NULL(cb_data);
343     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
344 
345 #ifndef CBOR_NO_FLOAT
346     cb_dbl = cn_cbor_double_create(3.14159 CONTEXT_NULL, &err);
347     ASSERT_NOT_NULL(cb_dbl);
348     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
349 #endif
350 
351     cn_cbor_mapput_int(cb_map, 5, cb_int CONTEXT_NULL, &err);
352     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
353     ASSERT_TRUE(cb_map->length == 2);
354 
355     cn_cbor_mapput_int(cb_map, -7, cb_data CONTEXT_NULL, &err);
356     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
357     ASSERT_TRUE(cb_map->length == 4);
358 
359     cn_cbor_mapput_string(cb_map, "foo",
360                           cn_cbor_string_create(data CONTEXT_NULL, &err)
361                           CONTEXT_NULL, &err);
362     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
363     ASSERT_TRUE(cb_map->length == 6);
364 
365     cn_cbor_map_put(cb_map,
366                     cn_cbor_string_create("bar" CONTEXT_NULL, &err),
367                     cn_cbor_string_create("qux" CONTEXT_NULL, &err),
368                     &err);
369     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
370     ASSERT_TRUE(cb_map->length == 8);
371 
372 #ifndef CBOR_NO_FLOAT
373     cn_cbor_mapput_int(cb_map, 42, cb_dbl CONTEXT_NULL, &err);
374     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
375     ASSERT_TRUE(cb_map->length == 10);
376 #endif
377 
378     val = cn_cbor_mapget_int(cb_map, 5);
379     ASSERT_NOT_NULL(val);
380     ASSERT_TRUE(val->v.sint == 256);
381 
382     val = cn_cbor_mapget_int(cb_map, -7);
383     ASSERT_NOT_NULL(val);
384     ASSERT_STR(val->v.str, "abc");
385 
386 #ifndef CBOR_NO_FLOAT
387     val = cn_cbor_mapget_int(cb_map, 42);
388     ASSERT_NOT_NULL(val);
389     ASSERT_TRUE(val->v.dbl > 3.14 && val->v.dbl < 3.15);
390 #endif
391 
392     cn_cbor_free(cb_map CONTEXT_NULL);
393 }
394 
CTEST(cbor,map_errors)395 CTEST(cbor, map_errors)
396 {
397     cn_cbor_errback err;
398     cn_cbor *ci;
399     ci = cn_cbor_int_create(65536, CONTEXT_NULL_COMMA &err);
400     cn_cbor_mapput_int(ci, -5, NULL, CONTEXT_NULL_COMMA &err);
401     ASSERT_EQUAL(err.err, CN_CBOR_ERR_INVALID_PARAMETER);
402     cn_cbor_mapput_string(ci, "foo", NULL, CONTEXT_NULL_COMMA &err);
403     ASSERT_EQUAL(err.err, CN_CBOR_ERR_INVALID_PARAMETER);
404     cn_cbor_map_put(ci, NULL, NULL, &err);
405 }
406 
CTEST(cbor,array)407 CTEST(cbor, array)
408 {
409     cn_cbor_errback err;
410     cn_cbor *a = cn_cbor_array_create(CONTEXT_NULL_COMMA &err);
411     ASSERT_NOT_NULL(a);
412     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
413     ASSERT_EQUAL(a->length, 0);
414 
415     cn_cbor_array_append(a, cn_cbor_int_create(256, CONTEXT_NULL_COMMA &err), &err);
416     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
417     ASSERT_EQUAL(a->length, 1);
418 
419     cn_cbor_array_append(a, cn_cbor_string_create("five", CONTEXT_NULL_COMMA &err), &err);
420     ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR);
421     ASSERT_EQUAL(a->length, 2);
422 }
423 
CTEST(cbor,array_errors)424 CTEST(cbor, array_errors)
425 {
426     cn_cbor_errback err;
427     cn_cbor *ci = cn_cbor_int_create(12, CONTEXT_NULL_COMMA &err);
428     cn_cbor_array_append(NULL, ci, &err);
429     ASSERT_EQUAL(err.err, CN_CBOR_ERR_INVALID_PARAMETER);
430     cn_cbor_array_append(ci, NULL, &err);
431     ASSERT_EQUAL(err.err, CN_CBOR_ERR_INVALID_PARAMETER);
432 }
433 
CTEST(cbor,create_encode)434 CTEST(cbor, create_encode)
435 {
436   cn_cbor *map;
437   cn_cbor *cdata;
438   char data[] = "data";
439   unsigned char encoded[1024];
440   ssize_t enc_sz;
441 
442   map = cn_cbor_map_create(CONTEXT_NULL_COMMA NULL);
443   ASSERT_NOT_NULL(map);
444 
445   cdata = cn_cbor_data_create((uint8_t*)data, sizeof(data)-1, CONTEXT_NULL_COMMA NULL);
446   ASSERT_NOT_NULL(cdata);
447 
448   ASSERT_TRUE(cn_cbor_mapput_int(map, 0, cdata, CONTEXT_NULL_COMMA NULL));
449   enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), map);
450   ASSERT_EQUAL(7, enc_sz);
451 }
452