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 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 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 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 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 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 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 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 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 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 331 ASSERT_NOT_NULL(cb_map); 332 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 333 334 cb_int = cn_cbor_int_create(256 CONTEXT_NULL, &err); 335 ASSERT_NOT_NULL(cb_int); 336 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 337 338 cb_data = cn_cbor_data_create((const uint8_t*)data, 4 CONTEXT_NULL, &err); 339 ASSERT_NOT_NULL(cb_data); 340 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 341 342 cn_cbor_mapput_int(cb_map, 5, cb_int CONTEXT_NULL, &err); 343 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 344 ASSERT_TRUE(cb_map->length == 2); 345 346 cn_cbor_mapput_int(cb_map, -7, cb_data CONTEXT_NULL, &err); 347 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 348 ASSERT_TRUE(cb_map->length == 4); 349 350 cn_cbor_mapput_string(cb_map, "foo", 351 cn_cbor_string_create(data CONTEXT_NULL, &err) 352 CONTEXT_NULL, &err); 353 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 354 ASSERT_TRUE(cb_map->length == 6); 355 356 cn_cbor_map_put(cb_map, 357 cn_cbor_string_create("bar" CONTEXT_NULL, &err), 358 cn_cbor_string_create("qux" CONTEXT_NULL, &err), 359 &err); 360 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 361 ASSERT_TRUE(cb_map->length == 8); 362 363 val = cn_cbor_mapget_int(cb_map, 5); 364 ASSERT_NOT_NULL(val); 365 ASSERT_TRUE(val->v.sint == 256); 366 367 val = cn_cbor_mapget_int(cb_map, -7); 368 ASSERT_NOT_NULL(val); 369 ASSERT_STR(val->v.str, "abc"); 370 371 cn_cbor_free(cb_map CONTEXT_NULL); 372 } 373 374 CTEST(cbor, map_errors) 375 { 376 cn_cbor_errback err; 377 cn_cbor *ci; 378 ci = cn_cbor_int_create(65536, CONTEXT_NULL_COMMA &err); 379 cn_cbor_mapput_int(ci, -5, NULL, CONTEXT_NULL_COMMA &err); 380 ASSERT_EQUAL(err.err, CN_CBOR_ERR_INVALID_PARAMETER); 381 cn_cbor_mapput_string(ci, "foo", NULL, CONTEXT_NULL_COMMA &err); 382 ASSERT_EQUAL(err.err, CN_CBOR_ERR_INVALID_PARAMETER); 383 cn_cbor_map_put(ci, NULL, NULL, &err); 384 } 385 386 CTEST(cbor, array) 387 { 388 cn_cbor_errback err; 389 cn_cbor *a = cn_cbor_array_create(CONTEXT_NULL_COMMA &err); 390 ASSERT_NOT_NULL(a); 391 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 392 ASSERT_EQUAL(a->length, 0); 393 394 cn_cbor_array_append(a, cn_cbor_int_create(256, CONTEXT_NULL_COMMA &err), &err); 395 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 396 ASSERT_EQUAL(a->length, 1); 397 398 cn_cbor_array_append(a, cn_cbor_string_create("five", CONTEXT_NULL_COMMA &err), &err); 399 ASSERT_TRUE(err.err == CN_CBOR_NO_ERROR); 400 ASSERT_EQUAL(a->length, 2); 401 } 402 403 CTEST(cbor, array_errors) 404 { 405 cn_cbor_errback err; 406 cn_cbor *ci = cn_cbor_int_create(12, CONTEXT_NULL_COMMA &err); 407 cn_cbor_array_append(NULL, ci, &err); 408 ASSERT_EQUAL(err.err, CN_CBOR_ERR_INVALID_PARAMETER); 409 cn_cbor_array_append(ci, NULL, &err); 410 ASSERT_EQUAL(err.err, CN_CBOR_ERR_INVALID_PARAMETER); 411 } 412 413 CTEST(cbor, create_encode) 414 { 415 cn_cbor *map; 416 cn_cbor *cdata; 417 char data[] = "data"; 418 unsigned char encoded[1024]; 419 ssize_t enc_sz; 420 421 map = cn_cbor_map_create(CONTEXT_NULL_COMMA NULL); 422 ASSERT_NOT_NULL(map); 423 424 cdata = cn_cbor_data_create((uint8_t*)data, sizeof(data)-1, CONTEXT_NULL_COMMA NULL); 425 ASSERT_NOT_NULL(cdata); 426 427 ASSERT_TRUE(cn_cbor_mapput_int(map, 0, cdata, CONTEXT_NULL_COMMA NULL)); 428 enc_sz = cn_cbor_encoder_write(encoded, 0, sizeof(encoded), map); 429 ASSERT_EQUAL(7, enc_sz); 430 } 431