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