114 |
114 |
115 cxJsonDestroy(&json); |
115 cxJsonDestroy(&json); |
116 } |
116 } |
117 } |
117 } |
118 |
118 |
|
119 CX_TEST(test_json_escaped_strings) { |
|
120 cxstring text = cx_str( |
|
121 "{\n" |
|
122 "\t\"object\":\"{\\n\\t\\\"object\\\":null\\n}\"}\"\n" |
|
123 "}" |
|
124 ); |
|
125 |
|
126 CxJson json; |
|
127 cxJsonInit(&json, NULL); |
|
128 CX_TEST_DO { |
|
129 cxJsonFill(&json, text); |
|
130 CxJsonValue *obj; |
|
131 CxJsonStatus result = cxJsonNext(&json, &obj); |
|
132 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
|
133 CX_TEST_ASSERT(cxJsonIsObject(obj)); |
|
134 CxJsonValue *object = cxJsonObjGet(obj, "object"); |
|
135 CX_TEST_ASSERT(cxJsonIsString(object)); |
|
136 CX_TEST_ASSERT(0 == cx_strcmp( |
|
137 cxJsonAsCxString(object), |
|
138 CX_STR("{\n\t\"object\":null\n}")) |
|
139 ); |
|
140 } |
|
141 cxJsonDestroy(&json); |
|
142 } |
|
143 |
119 CX_TEST(test_json_object_incomplete_token) { |
144 CX_TEST(test_json_object_incomplete_token) { |
120 cxstring text = cx_str( |
145 cxstring text = cx_str( |
121 "{\"message\":\"success\" , \"__timestamp\":1729348561}"); |
146 "{\"message\":\"success\" , \"__timestamp\":1729348561}"); |
122 cxstring parts[16]; |
147 cxstring parts[16]; |
123 size_t nparts = 0; // split the json text into mulple parts |
148 size_t nparts = 0; // split the json text into mulple parts |
162 result = cxJsonNext(&json, &obj); |
187 result = cxJsonNext(&json, &obj); |
163 CX_TEST_ASSERT(result == CX_JSON_NO_DATA); |
188 CX_TEST_ASSERT(result == CX_JSON_NO_DATA); |
164 |
189 |
165 cxJsonDestroy(&json); |
190 cxJsonDestroy(&json); |
166 } |
191 } |
|
192 } |
|
193 |
|
194 CX_TEST(test_json_token_wrongly_completed) { |
|
195 cxstring text = cx_str("{\"number\": 47110815!}"); |
|
196 cxstring part1 = cx_strsubsl(text, 0, 16); |
|
197 cxstring part2 = cx_strsubs(text, 16); |
|
198 |
|
199 CxJson json; |
|
200 cxJsonInit(&json, NULL); |
|
201 CX_TEST_DO { |
|
202 CxJsonStatus result; |
|
203 CxJsonValue *obj; |
|
204 |
|
205 cxJsonFill(&json, part1); |
|
206 result = cxJsonNext(&json, &obj); |
|
207 CX_TEST_ASSERT(result == CX_JSON_INCOMPLETE_DATA); |
|
208 cxJsonFill(&json, part2); |
|
209 result = cxJsonNext(&json, &obj); |
|
210 CX_TEST_ASSERT(result == CX_JSON_FORMAT_ERROR_NUMBER); |
|
211 CX_TEST_ASSERT(obj->type == CX_JSON_NOTHING); |
|
212 } |
|
213 cxJsonDestroy(&json); |
167 } |
214 } |
168 |
215 |
169 CX_TEST(test_json_subsequent_fill) { |
216 CX_TEST(test_json_subsequent_fill) { |
170 cxstring text = cx_str( |
217 cxstring text = cx_str( |
171 "{\"message\":\"success\" , \"__timestamp\":1729348561}"); |
218 "{\"message\":\"success\" , \"__timestamp\":1729348561}"); |
294 |
341 |
295 CX_TEST(test_json_number) { |
342 CX_TEST(test_json_number) { |
296 CxJson json; |
343 CxJson json; |
297 cxJsonInit(&json, NULL); |
344 cxJsonInit(&json, NULL); |
298 CX_TEST_DO { |
345 CX_TEST_DO { |
299 // TODO: find a better way to terminate values that are not arrays/objects |
|
300 CxJsonValue *v; |
346 CxJsonValue *v; |
301 CxJsonStatus result; |
347 CxJsonStatus result; |
|
348 |
302 cxJsonFill(&json, "3.1415 "); |
349 cxJsonFill(&json, "3.1415 "); |
303 result = cxJsonNext(&json, &v); |
350 result = cxJsonNext(&json, &v); |
304 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
351 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
305 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
352 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
306 CX_TEST_ASSERT(cxJsonAsDouble(v) == 3.1415); |
353 CX_TEST_ASSERT(cxJsonAsDouble(v) == 3.1415); |
307 cxJsonValueFree(v); |
354 cxJsonValueFree(v); |
|
355 |
308 cxJsonFill(&json, "-47.11e2 "); |
356 cxJsonFill(&json, "-47.11e2 "); |
309 result = cxJsonNext(&json, &v); |
357 result = cxJsonNext(&json, &v); |
310 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
358 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
311 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
359 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
312 CX_TEST_ASSERT(cxJsonAsDouble(v) == -4711.0); |
360 CX_TEST_ASSERT(cxJsonAsDouble(v) == -4711.0); |
313 cxJsonValueFree(v); |
361 cxJsonValueFree(v); |
|
362 |
|
363 cxJsonFill(&json, "0.815e-3 "); |
|
364 result = cxJsonNext(&json, &v); |
|
365 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
|
366 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
|
367 CX_TEST_ASSERT(cxJsonAsDouble(v) == 0.000815); |
|
368 |
|
369 cxJsonFill(&json, "1.23E4 "); |
|
370 result = cxJsonNext(&json, &v); |
|
371 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
|
372 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
|
373 CX_TEST_ASSERT(cxJsonAsInteger(v) == 12300); |
|
374 CX_TEST_ASSERT(cxJsonAsDouble(v) == 12300.0); |
|
375 |
|
376 cxJsonValueFree(v); |
|
377 } |
|
378 cxJsonDestroy(&json); |
|
379 } |
|
380 |
|
381 CX_TEST(test_json_number_format_errors) { |
|
382 CxJson json; |
|
383 cxJsonInit(&json, NULL); |
|
384 CX_TEST_DO { |
|
385 CxJsonValue *v; |
|
386 CxJsonStatus result; |
|
387 |
|
388 cxJsonFill(&json, "+3.1415 "); |
|
389 result = cxJsonNext(&json, &v); |
|
390 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
391 "leading plus is not RFC-8259 compliant"); |
|
392 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
393 cxJsonReset(&json); |
|
394 |
|
395 #if 0 // TODO: discuss if it is intended that this produces -47 as valid value |
|
396 cxJsonFill(&json, "-47,11e2 "); |
|
397 result = cxJsonNext(&json, &v); |
|
398 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN, |
|
399 "decimal separator cannot be a comma"); |
|
400 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
401 cxJsonReset(&json); |
|
402 #endif |
|
403 |
|
404 cxJsonFill(&json, "0.815e-3.0 "); |
|
405 result = cxJsonNext(&json, &v); |
|
406 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
407 "exponent must be an integer"); |
|
408 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
409 cxJsonReset(&json); |
|
410 |
|
411 cxJsonFill(&json, "3.14e "); |
|
412 result = cxJsonNext(&json, &v); |
|
413 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
414 "exponent cannot be empty"); |
|
415 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
416 cxJsonReset(&json); |
|
417 |
|
418 cxJsonFill(&json, "3.14e~7 "); |
|
419 result = cxJsonNext(&json, &v); |
|
420 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
421 "exponent cannot start with bullshit"); |
|
422 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
423 cxJsonReset(&json); |
|
424 |
|
425 cxJsonFill(&json, "1.23e4f "); |
|
426 result = cxJsonNext(&json, &v); |
|
427 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
428 "non-digits in exponent"); |
|
429 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
430 cxJsonReset(&json); |
|
431 |
|
432 cxJsonFill(&json, "1.23f "); |
|
433 result = cxJsonNext(&json, &v); |
|
434 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
435 "non-digits in value"); |
|
436 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
437 cxJsonReset(&json); |
|
438 |
|
439 cxJsonFill(&json, "1.23.45 "); |
|
440 result = cxJsonNext(&json, &v); |
|
441 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
442 "multiple decimal separators"); |
|
443 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
444 cxJsonReset(&json); |
|
445 |
|
446 cxJsonFill(&json, "184467440737095516150123456789 "); |
|
447 result = cxJsonNext(&json, &v); |
|
448 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
449 "30 digit int does not fit into 64-bit int"); |
|
450 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
451 cxJsonReset(&json); |
|
452 |
|
453 cxJsonFill(&json, "18446744073709551615.0123456789 "); |
|
454 result = cxJsonNext(&json, &v); |
|
455 CX_TEST_ASSERTM(result == CX_JSON_FORMAT_ERROR_NUMBER, |
|
456 "numbers with more than 30 characters are unsupported in general"); |
|
457 CX_TEST_ASSERT(v->type == CX_JSON_NOTHING); |
|
458 cxJsonReset(&json); |
314 } |
459 } |
315 cxJsonDestroy(&json); |
460 cxJsonDestroy(&json); |
316 } |
461 } |
317 |
462 |
318 CX_TEST(test_json_multiple_values) { |
463 CX_TEST(test_json_multiple_values) { |
363 // read literal |
508 // read literal |
364 cxJsonFill(&json, "true\n"); |
509 cxJsonFill(&json, "true\n"); |
365 result = cxJsonNext(&json, &v); |
510 result = cxJsonNext(&json, &v); |
366 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
511 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
367 CX_TEST_ASSERT(cxJsonIsLiteral(v)); |
512 CX_TEST_ASSERT(cxJsonIsLiteral(v)); |
|
513 CX_TEST_ASSERT(cxJsonIsBool(v)); |
|
514 CX_TEST_ASSERT(cxJsonIsTrue(v)); |
368 CX_TEST_ASSERT(cxJsonAsBool(v)); |
515 CX_TEST_ASSERT(cxJsonAsBool(v)); |
369 cxJsonValueFree(v); |
516 cxJsonValueFree(v); |
370 // read null |
517 cxJsonFill(&json, "false\n"); |
|
518 result = cxJsonNext(&json, &v); |
|
519 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
|
520 CX_TEST_ASSERT(cxJsonIsLiteral(v)); |
|
521 CX_TEST_ASSERT(cxJsonIsBool(v)); |
|
522 CX_TEST_ASSERT(cxJsonIsFalse(v)); |
|
523 CX_TEST_ASSERT(!cxJsonAsBool(v)); |
|
524 cxJsonValueFree(v); |
371 cxJsonFill(&json, "null\n"); |
525 cxJsonFill(&json, "null\n"); |
372 result = cxJsonNext(&json, &v); |
526 result = cxJsonNext(&json, &v); |
373 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
527 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
|
528 CX_TEST_ASSERT(cxJsonIsLiteral(v)); |
|
529 CX_TEST_ASSERT(!cxJsonIsBool(v)); |
374 CX_TEST_ASSERT(cxJsonIsNull(v)); |
530 CX_TEST_ASSERT(cxJsonIsNull(v)); |
375 cxJsonValueFree(v); |
531 cxJsonValueFree(v); |
376 } |
532 } |
377 cxJsonDestroy(&json); |
533 cxJsonDestroy(&json); |
378 } |
534 } |
441 CxTestSuite *cx_test_suite_json(void) { |
597 CxTestSuite *cx_test_suite_json(void) { |
442 CxTestSuite *suite = cx_test_suite_new("json"); |
598 CxTestSuite *suite = cx_test_suite_new("json"); |
443 |
599 |
444 cx_test_register(suite, test_json_init_default); |
600 cx_test_register(suite, test_json_init_default); |
445 cx_test_register(suite, test_json_simple_object); |
601 cx_test_register(suite, test_json_simple_object); |
|
602 cx_test_register(suite, test_json_escaped_strings); |
446 cx_test_register(suite, test_json_object_incomplete_token); |
603 cx_test_register(suite, test_json_object_incomplete_token); |
|
604 cx_test_register(suite, test_json_token_wrongly_completed); |
447 cx_test_register(suite, test_json_object_error); |
605 cx_test_register(suite, test_json_object_error); |
448 cx_test_register(suite, test_json_subsequent_fill); |
606 cx_test_register(suite, test_json_subsequent_fill); |
449 cx_test_register(suite, test_json_large_nesting_depth); |
607 cx_test_register(suite, test_json_large_nesting_depth); |
450 cx_test_register(suite, test_json_number); |
608 cx_test_register(suite, test_json_number); |
|
609 cx_test_register(suite, test_json_number_format_errors); |
451 cx_test_register(suite, test_json_multiple_values); |
610 cx_test_register(suite, test_json_multiple_values); |
452 cx_test_register(suite, test_json_allocator); |
611 cx_test_register(suite, test_json_allocator); |
453 cx_test_register(suite, test_json_allocator_parse_error); |
612 cx_test_register(suite, test_json_allocator_parse_error); |
454 |
613 |
455 return suite; |
614 return suite; |