tests/test_json.c

changeset 1513
4d641c6a2f82
parent 1338
cc153bffea28
equal deleted inserted replaced
1512:0dc866c7863b 1513:4d641c6a2f82
76 76
77 CxJsonValue *message = cxJsonObjGet(obj, "message"); 77 CxJsonValue *message = cxJsonObjGet(obj, "message");
78 CX_TEST_ASSERT(cxJsonIsString(message)); 78 CX_TEST_ASSERT(cxJsonIsString(message));
79 CX_TEST_ASSERT(0 == cx_strcmp( 79 CX_TEST_ASSERT(0 == cx_strcmp(
80 cxJsonAsCxString(message), 80 cxJsonAsCxString(message),
81 cx_str("success")) 81 "success")
82 ); 82 );
83 83
84 CxJsonValue *position = cxJsonObjGet(obj, "position"); 84 CxJsonValue *position = cxJsonObjGet(obj, "position");
85 CX_TEST_ASSERT(cxJsonIsObject(position)); 85 CX_TEST_ASSERT(cxJsonIsObject(position));
86 CxJsonValue *longitude = cxJsonObjGet(position, "longitude"); 86 CxJsonValue *longitude = cxJsonObjGet(position, "longitude");
115 115
116 cxJsonDestroy(&json); 116 cxJsonDestroy(&json);
117 } 117 }
118 } 118 }
119 119
120 CX_TEST(test_json_large_object) {
121 CxJsonValue *obj = cxJsonCreateObj(NULL);
122 CX_TEST_DO {
123 cxJsonObjPutString(obj, "mystring", "test");
124 char buf[10];
125 for (unsigned i = 0 ; i < 300 ; i++) {
126 sprintf(buf, "key %d", i);
127 cxJsonObjPutInteger(obj, buf, i);
128 }
129 CX_TEST_ASSERT(301 == cxJsonObjSize(obj));
130 // some samples
131 CxJsonValue *v;
132 v = cxJsonObjGet(obj, "key 64");
133 CX_TEST_ASSERT(cxJsonIsInteger(v));
134 CX_TEST_ASSERT(cxJsonAsInteger(v) == 64);
135 v = cxJsonObjGet(obj, "key 228");
136 CX_TEST_ASSERT(cxJsonIsInteger(v));
137 CX_TEST_ASSERT(cxJsonAsInteger(v) == 228);
138
139 v = cxJsonObjGet(obj, "mystring");
140 CX_TEST_ASSERT(cxJsonIsString(v));
141 CX_TEST_ASSERT(0 == cx_strcmp(cxJsonAsCxMutStr(v), "test"));
142 }
143 cxJsonValueFree(obj);
144 }
145
120 CX_TEST(test_json_escaped_strings) { 146 CX_TEST(test_json_escaped_strings) {
121 cxstring text = cx_str( 147 cxstring text = cx_str(
122 "{\n" 148 "{\n"
123 "\t\"object\":\"{\\n\\t\\\"object\\\":null\\n}\",\n" 149 "\t\"object\":\"{\\n\\t\\\"object\\\":null\\n}\",\n"
124 "\t\"ctrl-chars\":\"\\\\foo\\r\\nbar\\f*ring\\/ring*\\b\"\n" 150 "\t\"ctrl-chars\":\"\\\\foo\\r\\nbar\\f*ring\\/ring*\\b\"\n"
135 CX_TEST_ASSERT(cxJsonIsObject(obj)); 161 CX_TEST_ASSERT(cxJsonIsObject(obj));
136 CxJsonValue *object = cxJsonObjGet(obj, "object"); 162 CxJsonValue *object = cxJsonObjGet(obj, "object");
137 CX_TEST_ASSERT(cxJsonIsString(object)); 163 CX_TEST_ASSERT(cxJsonIsString(object));
138 CX_TEST_ASSERT(0 == cx_strcmp( 164 CX_TEST_ASSERT(0 == cx_strcmp(
139 cxJsonAsCxString(object), 165 cxJsonAsCxString(object),
140 CX_STR("{\n\t\"object\":null\n}")) 166 "{\n\t\"object\":null\n}")
141 ); 167 );
142 CxJsonValue *ctrl = cxJsonObjGet(obj, "ctrl-chars"); 168 CxJsonValue *ctrl = cxJsonObjGet(obj, "ctrl-chars");
143 CX_TEST_ASSERT(cxJsonIsString(ctrl)); 169 CX_TEST_ASSERT(cxJsonIsString(ctrl));
144 CX_TEST_ASSERT(0 == cx_strcmp( 170 CX_TEST_ASSERT(0 == cx_strcmp(
145 cxJsonAsCxString(ctrl), 171 cxJsonAsCxString(ctrl),
146 CX_STR("\\foo\r\nbar\f*ring/ring*\b")) 172 "\\foo\r\nbar\f*ring/ring*\b")
147 ); 173 );
148 cxJsonValueFree(obj); 174 cxJsonValueFree(obj);
149 } 175 }
150 cxJsonDestroy(&json); 176 cxJsonDestroy(&json);
151 } 177 }
174 200
175 CxJsonValue *ascii = cxJsonObjGet(obj, "ascii"); 201 CxJsonValue *ascii = cxJsonObjGet(obj, "ascii");
176 CX_TEST_ASSERT(cxJsonIsString(ascii)); 202 CX_TEST_ASSERT(cxJsonIsString(ascii));
177 CX_TEST_ASSERT(0 == cx_strcmp( 203 CX_TEST_ASSERT(0 == cx_strcmp(
178 cxJsonAsCxString(ascii), 204 cxJsonAsCxString(ascii),
179 CX_STR("ASCII")) 205 "ASCII")
180 ); 206 );
181 207
182 CxJsonValue *unicode = cxJsonObjGet(obj, "unicode"); 208 CxJsonValue *unicode = cxJsonObjGet(obj, "unicode");
183 CX_TEST_ASSERT(cxJsonIsString(unicode)); 209 CX_TEST_ASSERT(cxJsonIsString(unicode));
184 CX_TEST_ASSERT(0 == cx_strcmp( 210 CX_TEST_ASSERT(0 == cx_strcmp(
185 cxJsonAsCxString(unicode), 211 cxJsonAsCxString(unicode),
186 CX_STR("ßß")) 212 "ßß")
187 ); 213 );
188 214
189 CxJsonValue *mixed = cxJsonObjGet(obj, "mixed"); 215 CxJsonValue *mixed = cxJsonObjGet(obj, "mixed");
190 CX_TEST_ASSERT(cxJsonIsString(mixed)); 216 CX_TEST_ASSERT(cxJsonIsString(mixed));
191 CX_TEST_ASSERT(0 == cx_strcmp( 217 CX_TEST_ASSERT(0 == cx_strcmp(
192 cxJsonAsCxString(mixed), 218 cxJsonAsCxString(mixed),
193 CX_STR("mixed ä ö ä ö")) 219 "mixed ä ö ä ö")
194 ); 220 );
195 221
196 CxJsonValue *wide = cxJsonObjGet(obj, "wide"); 222 CxJsonValue *wide = cxJsonObjGet(obj, "wide");
197 CX_TEST_ASSERT(cxJsonIsString(wide)); 223 CX_TEST_ASSERT(cxJsonIsString(wide));
198 CX_TEST_ASSERT(0 == cx_strcmp(cxJsonAsCxString(wide), CX_STR("Σ⦰"))); 224 CX_TEST_ASSERT(0 == cx_strcmp(cxJsonAsCxString(wide), "Σ⦰"));
199 225
200 CxJsonValue *surrogatepair1 = cxJsonObjGet(obj, "surrogatepair1"); 226 CxJsonValue *surrogatepair1 = cxJsonObjGet(obj, "surrogatepair1");
201 CX_TEST_ASSERT(cxJsonIsString(surrogatepair1)); 227 CX_TEST_ASSERT(cxJsonIsString(surrogatepair1));
202 CX_TEST_ASSERT(0 == cx_strcmp( 228 CX_TEST_ASSERT(0 == cx_strcmp(
203 cxJsonAsCxString(surrogatepair1), 229 cxJsonAsCxString(surrogatepair1),
204 CX_STR("\xf0\x9f\xaf\xb5")) 230 "\xf0\x9f\xaf\xb5")
205 ); 231 );
206 232
207 CxJsonValue *surrogatepair2 = cxJsonObjGet(obj, "surrogatepair2"); 233 CxJsonValue *surrogatepair2 = cxJsonObjGet(obj, "surrogatepair2");
208 CX_TEST_ASSERT(cxJsonIsString(surrogatepair2)); 234 CX_TEST_ASSERT(cxJsonIsString(surrogatepair2));
209 CX_TEST_ASSERT(0 == cx_strcmp( 235 CX_TEST_ASSERT(0 == cx_strcmp(
210 cxJsonAsCxString(surrogatepair2), 236 cxJsonAsCxString(surrogatepair2),
211 CX_STR("test\xf0\x9f\xaf\xb1" "AA")) 237 "test\xf0\x9f\xaf\xb1" "AA")
212 ); 238 );
213 239
214 CxJsonValue *mixed2 = cxJsonObjGet(obj, "mixed2"); 240 CxJsonValue *mixed2 = cxJsonObjGet(obj, "mixed2");
215 char test[16]; 241 char test[16];
216 strncpy(test, mixed2->value.string.ptr, 15); 242 strncpy(test, mixed2->value.string.ptr, 15);
217 CX_TEST_ASSERT(cxJsonIsString(mixed2)); 243 CX_TEST_ASSERT(cxJsonIsString(mixed2));
218 CX_TEST_ASSERT(0 == cx_strcmp( 244 CX_TEST_ASSERT(0 == cx_strcmp(
219 cxJsonAsCxString(mixed2), 245 cxJsonAsCxString(mixed2),
220 CX_STR("123\xce\xa3\xf0\x9f\xaf\x85ß")) 246 "123\xce\xa3\xf0\x9f\xaf\x85ß")
221 ); 247 );
222 248
223 cxJsonValueFree(obj); 249 cxJsonValueFree(obj);
224 } 250 }
225 cxJsonDestroy(&json); 251 cxJsonDestroy(&json);
229 CxJson json; 255 CxJson json;
230 cxJsonInit(&json, NULL); 256 cxJsonInit(&json, NULL);
231 CxJsonValue *obj; 257 CxJsonValue *obj;
232 CxJsonStatus result; 258 CxJsonStatus result;
233 CX_TEST_DO { 259 CX_TEST_DO {
234 cxJsonFill(&json, "\"too few \\u123 digits\""); 260 cxJsonFill(&json, "\"too few digits \\u123\"");
235 result = cxJsonNext(&json, &obj); 261 result = cxJsonNext(&json, &obj);
236 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 262 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
237 CX_TEST_ASSERT(cxJsonIsString(obj)); 263 CX_TEST_ASSERT(cxJsonIsString(obj));
238 CX_TEST_ASSERT(0 == cx_strcmp( 264 CX_TEST_ASSERT(0 == cx_strcmp(
239 cxJsonAsCxString(obj), 265 cxJsonAsCxString(obj),
240 CX_STR("too few \\u123 digits") 266 "too few digits \\u123"
241 )); 267 ));
242 cxJsonValueFree(obj); 268 cxJsonValueFree(obj);
243 cxJsonFill(&json, "\"too many \\u00E456 digits\""); 269 cxJsonFill(&json, "\"too many digits \\u00E456\"");
244 result = cxJsonNext(&json, &obj); 270 result = cxJsonNext(&json, &obj);
245 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 271 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
246 CX_TEST_ASSERT(cxJsonIsString(obj)); 272 CX_TEST_ASSERT(cxJsonIsString(obj));
247 CX_TEST_ASSERT(0 == cx_strcmp( 273 CX_TEST_ASSERT(0 == cx_strcmp(
248 cxJsonAsCxString(obj), 274 cxJsonAsCxString(obj),
249 CX_STR("too many ä56 digits") 275 "too many digits ä56"
250 )); 276 ));
251 cxJsonValueFree(obj); 277 cxJsonValueFree(obj);
252 cxJsonFill(&json, "\"only high \\uD800 surrogate\""); 278 cxJsonFill(&json, "\"only high \\uD800 surrogate\"");
253 result = cxJsonNext(&json, &obj); 279 result = cxJsonNext(&json, &obj);
254 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 280 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
255 CX_TEST_ASSERT(cxJsonIsString(obj)); 281 CX_TEST_ASSERT(cxJsonIsString(obj));
256 CX_TEST_ASSERT(0 == cx_strcmp( 282 CX_TEST_ASSERT(0 == cx_strcmp(
257 cxJsonAsCxString(obj), 283 cxJsonAsCxString(obj),
258 CX_STR("only high \\uD800 surrogate") 284 "only high \\uD800 surrogate"
259 )); 285 ));
260 cxJsonValueFree(obj); 286 cxJsonValueFree(obj);
261 cxJsonFill(&json, "\"only low \\uDC00 surrogate\""); 287 cxJsonFill(&json, "\"only low \\uDC00 surrogate\"");
262 result = cxJsonNext(&json, &obj); 288 result = cxJsonNext(&json, &obj);
263 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 289 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
264 CX_TEST_ASSERT(cxJsonIsString(obj)); 290 CX_TEST_ASSERT(cxJsonIsString(obj));
265 CX_TEST_ASSERT(0 == cx_strcmp( 291 CX_TEST_ASSERT(0 == cx_strcmp(
266 cxJsonAsCxString(obj), 292 cxJsonAsCxString(obj),
267 CX_STR("only low \\uDC00 surrogate") 293 "only low \\uDC00 surrogate"
268 )); 294 ));
269 cxJsonValueFree(obj); 295 cxJsonValueFree(obj);
270 cxJsonFill(&json, "\"two high \\uD800\\uD800 surrogates\""); 296 cxJsonFill(&json, "\"two high \\uD800\\uD800 surrogates\"");
271 result = cxJsonNext(&json, &obj); 297 result = cxJsonNext(&json, &obj);
272 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 298 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
273 CX_TEST_ASSERT(cxJsonIsString(obj)); 299 CX_TEST_ASSERT(cxJsonIsString(obj));
274 CX_TEST_ASSERT(0 == cx_strcmp( 300 CX_TEST_ASSERT(0 == cx_strcmp(
275 cxJsonAsCxString(obj), 301 cxJsonAsCxString(obj),
276 CX_STR("two high \\uD800\\uD800 surrogates") 302 "two high \\uD800\\uD800 surrogates"
277 )); 303 ));
278 cxJsonValueFree(obj); 304 cxJsonValueFree(obj);
279 cxJsonFill(&json, "\"high plus bullshit \\uD800\\u567 foo\""); 305 cxJsonFill(&json, "\"high plus bullshit \\uD800\\u567 foo\"");
280 result = cxJsonNext(&json, &obj); 306 result = cxJsonNext(&json, &obj);
281 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 307 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
282 CX_TEST_ASSERT(cxJsonIsString(obj)); 308 CX_TEST_ASSERT(cxJsonIsString(obj));
283 CX_TEST_ASSERT(0 == cx_strcmp( 309 CX_TEST_ASSERT(0 == cx_strcmp(
284 cxJsonAsCxString(obj), 310 cxJsonAsCxString(obj),
285 CX_STR("high plus bullshit \\uD800\\u567 foo") 311 "high plus bullshit \\uD800\\u567 foo"
286 )); 312 ));
287 cxJsonValueFree(obj); 313 cxJsonValueFree(obj);
288 } 314 }
289 cxJsonDestroy(&json); 315 cxJsonDestroy(&json);
290 } 316 }
299 CxJsonStatus result = cxJsonNext(&json, &val); 325 CxJsonStatus result = cxJsonNext(&json, &val);
300 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 326 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
301 CX_TEST_ASSERT(cxJsonIsString(val)); 327 CX_TEST_ASSERT(cxJsonIsString(val));
302 CX_TEST_ASSERT(0 == cx_strcmp( 328 CX_TEST_ASSERT(0 == cx_strcmp(
303 cxJsonAsCxString(val), 329 cxJsonAsCxString(val),
304 cx_str("a \"test\" string")) 330 "a \"test\" string")
305 ); 331 );
306 cxJsonValueFree(val); 332 cxJsonValueFree(val);
307 333
308 // second test - uncompleted token with hanging escape char 334 // second test - uncompleted token with hanging escape char
309 cxJsonFill(&json, "\"a \\\"test\\"); 335 cxJsonFill(&json, "\"a \\\"test\\");
313 result = cxJsonNext(&json, &val); 339 result = cxJsonNext(&json, &val);
314 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 340 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
315 CX_TEST_ASSERT(cxJsonIsString(val)); 341 CX_TEST_ASSERT(cxJsonIsString(val));
316 CX_TEST_ASSERT(0 == cx_strcmp( 342 CX_TEST_ASSERT(0 == cx_strcmp(
317 cxJsonAsCxString(val), 343 cxJsonAsCxString(val),
318 cx_str("a \"test\" string")) 344 "a \"test\" string")
319 ); 345 );
320 cxJsonValueFree(val); 346 cxJsonValueFree(val);
321 } 347 }
322 cxJsonDestroy(&json); 348 cxJsonDestroy(&json);
323 } 349 }
352 378
353 CxJsonValue *message = cxJsonObjGet(obj, "message"); 379 CxJsonValue *message = cxJsonObjGet(obj, "message");
354 CX_TEST_ASSERT(cxJsonIsString(message)); 380 CX_TEST_ASSERT(cxJsonIsString(message));
355 CX_TEST_ASSERT(0 == cx_strcmp( 381 CX_TEST_ASSERT(0 == cx_strcmp(
356 cxJsonAsCxString(message), 382 cxJsonAsCxString(message),
357 cx_str("success")) 383 "success")
358 ); 384 );
359 CxJsonValue *timestamp = cxJsonObjGet(obj, "__timestamp"); 385 CxJsonValue *timestamp = cxJsonObjGet(obj, "__timestamp");
360 CX_TEST_ASSERT(message->type == CX_JSON_STRING); 386 CX_TEST_ASSERT(message->type == CX_JSON_STRING);
361 CX_TEST_ASSERT(cxJsonIsInteger(timestamp)); 387 CX_TEST_ASSERT(cxJsonIsInteger(timestamp));
362 CX_TEST_ASSERT(cxJsonAsInteger(timestamp) == 1729348561); 388 CX_TEST_ASSERT(cxJsonAsInteger(timestamp) == 1729348561);
400 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 426 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
401 } 427 }
402 cx_testing_allocator_destroy(&talloc); 428 cx_testing_allocator_destroy(&talloc);
403 } 429 }
404 430
431 CX_TEST(test_json_parenthesis_mismatch) {
432 CxTestingAllocator talloc;
433 cx_testing_allocator_init(&talloc);
434 const CxAllocator *alloc = &talloc.base;
435
436 CX_TEST_DO {
437 CxJson json;
438 cxJsonInit(&json, alloc);
439
440 CxJsonStatus result;
441 CxJsonValue *obj;
442
443 cxJsonFill(&json, "[0, 1, 2, 3}");
444 result = cxJsonNext(&json, &obj);
445 CX_TEST_ASSERT(result == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN);
446
447 cxJsonReset(&json);
448 cxJsonFill(&json, "{\"test\": 42]");
449 result = cxJsonNext(&json, &obj);
450 CX_TEST_ASSERT(result == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN);
451
452 cxJsonDestroy(&json);
453 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
454 }
455 cx_testing_allocator_destroy(&talloc);
456 }
457
458 CX_TEST(test_json_object_name_is_no_string) {
459 CxTestingAllocator talloc;
460 cx_testing_allocator_init(&talloc);
461 const CxAllocator *alloc = &talloc.base;
462
463 CX_TEST_DO {
464 CxJson json;
465 cxJsonInit(&json, alloc);
466
467 CxJsonStatus result;
468 CxJsonValue *obj;
469
470 cxJsonFill(&json, "{42: \"test\"}");
471 result = cxJsonNext(&json, &obj);
472 CX_TEST_ASSERT(result == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN);
473
474 cxJsonDestroy(&json);
475 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
476 }
477 cx_testing_allocator_destroy(&talloc);
478 }
479
405 CX_TEST(test_json_subsequent_fill) { 480 CX_TEST(test_json_subsequent_fill) {
406 cxstring text = cx_str( 481 cxstring text = cx_str(
407 "{\"message\":\"success\" , \"__timestamp\":1729348561}"); 482 "{\"message\":\"success\" , \"__timestamp\":1729348561}");
408 483
409 cxstring part1 = cx_strsubsl(text, 0, 25); 484 cxstring part1 = cx_strsubsl(text, 0, 25);
422 497
423 CxJsonValue *message = cxJsonObjGet(obj, "message"); 498 CxJsonValue *message = cxJsonObjGet(obj, "message");
424 CX_TEST_ASSERT(cxJsonIsString(message)); 499 CX_TEST_ASSERT(cxJsonIsString(message));
425 CX_TEST_ASSERT(0 == cx_strcmp( 500 CX_TEST_ASSERT(0 == cx_strcmp(
426 cxJsonAsCxString(message), 501 cxJsonAsCxString(message),
427 cx_str("success")) 502 "success")
428 ); 503 );
429 CxJsonValue *timestamp = cxJsonObjGet(obj, "__timestamp"); 504 CxJsonValue *timestamp = cxJsonObjGet(obj, "__timestamp");
430 CX_TEST_ASSERT(message->type == CX_JSON_STRING); 505 CX_TEST_ASSERT(message->type == CX_JSON_STRING);
431 CX_TEST_ASSERT(cxJsonIsInteger(timestamp)); 506 CX_TEST_ASSERT(cxJsonIsInteger(timestamp));
432 CX_TEST_ASSERT(cxJsonAsInteger(timestamp) == 1729348561); 507 CX_TEST_ASSERT(cxJsonAsInteger(timestamp) == 1729348561);
435 result = cxJsonNext(&json, &obj); 510 result = cxJsonNext(&json, &obj);
436 CX_TEST_ASSERT(result == CX_JSON_NO_DATA); 511 CX_TEST_ASSERT(result == CX_JSON_NO_DATA);
437 512
438 cxJsonDestroy(&json); 513 cxJsonDestroy(&json);
439 } 514 }
515 }
516
517 CX_TEST(test_json_no_fill) {
518 CxJson json;
519 cxJsonInit(&json, NULL);
520 CX_TEST_DO {
521 CxJsonValue *obj = NULL;
522 CxJsonStatus result = cxJsonNext(&json, &obj);
523 CX_TEST_ASSERT(result == CX_JSON_NULL_DATA);
524 CX_TEST_ASSERT(obj != NULL);
525 CX_TEST_ASSERT(obj->type == CX_JSON_NOTHING);
526 }
527 cxJsonDestroy(&json);
528 }
529
530 CX_TEST(test_json_null_fill) {
531 CxJson json;
532 cxJsonInit(&json, NULL);
533 CX_TEST_DO {
534 CxJsonStatus result;
535 CxJsonValue *obj = NULL;
536 cxstring nullstr = cx_strn(NULL, 0);
537 cxJsonFill(&json, nullstr);
538 result = cxJsonNext(&json, &obj);
539 CX_TEST_ASSERT(result == CX_JSON_NO_DATA);
540 CX_TEST_ASSERT(obj != NULL);
541 CX_TEST_ASSERT(obj->type == CX_JSON_NOTHING);
542 obj = NULL;
543
544 cxJsonFill(&json, "[0, 1");
545 result = cxJsonNext(&json, &obj);
546 CX_TEST_ASSERT(result == CX_JSON_INCOMPLETE_DATA);
547 CX_TEST_ASSERT(obj != NULL);
548 CX_TEST_ASSERT(obj->type == CX_JSON_NOTHING);
549 obj = NULL;
550
551 cxJsonFill(&json, nullstr);
552 result = cxJsonNext(&json, &obj);
553 CX_TEST_ASSERT(result == CX_JSON_INCOMPLETE_DATA);
554 CX_TEST_ASSERT(obj != NULL);
555 CX_TEST_ASSERT(obj->type == CX_JSON_NOTHING);
556 obj = NULL;
557
558 cxJsonFill(&json, ", 2]");
559 result = cxJsonNext(&json, &obj);
560 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
561 CX_TEST_ASSERT(obj != NULL);
562 CX_TEST_ASSERT(cxJsonIsArray(obj));
563 cxJsonValueFree(obj);
564
565 cxJsonFill(&json, nullstr);
566 result = cxJsonNext(&json, &obj);
567 CX_TEST_ASSERT(result == CX_JSON_NO_DATA);
568 CX_TEST_ASSERT(obj != NULL);
569 CX_TEST_ASSERT(obj->type == CX_JSON_NOTHING);
570 }
571 cxJsonDestroy(&json);
440 } 572 }
441 573
442 CX_TEST(test_json_object_error) { 574 CX_TEST(test_json_object_error) {
443 cxstring text0 = cx_str( 575 cxstring text0 = cx_str(
444 "{\n" 576 "{\n"
487 cx_testing_allocator_init(&talloc); 619 cx_testing_allocator_init(&talloc);
488 const CxAllocator *alloc = &talloc.base; 620 const CxAllocator *alloc = &talloc.base;
489 CX_TEST_DO { 621 CX_TEST_DO {
490 CxJson json; 622 CxJson json;
491 cxJsonInit(&json, alloc); 623 cxJsonInit(&json, alloc);
492 cxJsonFill(&json, cx_str( 624 cxJsonFill(&json,
493 "{\n" 625 "{\n"
494 "\t\"message\":\"success\",\n" 626 "\t\"message\":\"success\",\n"
495 "\t\"data\":{\n" 627 "\t\"data\":{\n"
496 "\t\t\"obj\":{\n" 628 "\t\t\"obj\":{\n"
497 "\t\t\t\"array\": [1, 2, 3]\n" 629 "\t\t\t\"array\": [1, 2, 3]\n"
498 "\t\t}\n" 630 "\t\t}\n"
499 "\t},\n" 631 "\t},\n"
500 "\t\"timestamp\":1729348561\n" 632 "\t\"timestamp\":1729348561\n"
501 "}" 633 "}"
502 )); 634 );
503 CxJsonValue *obj; 635 CxJsonValue *obj;
504 CX_TEST_ASSERT(CX_JSON_NO_ERROR == cxJsonNext(&json, &obj)); 636 CX_TEST_ASSERT(CX_JSON_NO_ERROR == cxJsonNext(&json, &obj));
505 cxJsonDestroy(&json); 637 cxJsonDestroy(&json);
506 638
507 CX_TEST_ASSERT(cxJsonIsObject(cxJsonObjGet(obj, "data"))); 639 CX_TEST_ASSERT(cxJsonIsObject(cxJsonObjGet(obj, "data")));
702 // read string 834 // read string
703 cxJsonFill(&json, "\"hello world\"\n"); 835 cxJsonFill(&json, "\"hello world\"\n");
704 result = cxJsonNext(&json, &v); 836 result = cxJsonNext(&json, &v);
705 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); 837 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR);
706 CX_TEST_ASSERT(cxJsonIsString(v)); 838 CX_TEST_ASSERT(cxJsonIsString(v));
707 CX_TEST_ASSERT(!cx_strcmp(cxJsonAsCxString(v), CX_STR("hello world"))); 839 CX_TEST_ASSERT(!cx_strcmp(cxJsonAsCxString(v), "hello world"));
708 cxJsonValueFree(v); 840 cxJsonValueFree(v);
709 // don't process the remaining newline this time 841 // don't process the remaining newline this time
710 // read obj 842 // read obj
711 cxJsonFill(&json, "{ \"value\": \"test\" }\n"); 843 cxJsonFill(&json, "{ \"value\": \"test\" }\n");
712 result = cxJsonNext(&json, &v); 844 result = cxJsonNext(&json, &v);
902 CX_TEST_ASSERT(cxJsonIsObject(obj)); 1034 CX_TEST_ASSERT(cxJsonIsObject(obj));
903 CX_TEST_ASSERT(obj->allocator == allocator); 1035 CX_TEST_ASSERT(obj->allocator == allocator);
904 1036
905 // add the members 1037 // add the members
906 { 1038 {
907 cxJsonObjPutLiteral(obj, CX_STR("bool"), CX_JSON_FALSE); 1039 cxJsonObjPutLiteral(obj, "bool", CX_JSON_FALSE);
908 cxJsonObjPutInteger(obj, CX_STR("int"), 47); 1040 cxJsonObjPutInteger(obj, "int", 47);
909 CxJsonValue *strings = cxJsonObjPutArr(obj, CX_STR("strings")); 1041 CxJsonValue *strings = cxJsonObjPutArr(obj, "strings");
910 CX_TEST_ASSERT(strings != NULL); 1042 CX_TEST_ASSERT(strings != NULL);
911 CX_TEST_ASSERT(cxJsonIsArray(strings)); 1043 CX_TEST_ASSERT(cxJsonIsArray(strings));
912 const char* str[] = {"hello", "world"}; 1044 const char* str[] = {"hello", "world"};
913 CX_TEST_ASSERT(0 == cxJsonArrAddStrings(strings, str, 2)); 1045 CX_TEST_ASSERT(0 == cxJsonArrAddStrings(strings, str, 2));
914 1046
915 CxJsonValue *nested = cxJsonObjPutObj(obj, CX_STR("nested")); 1047 CxJsonValue *nested = cxJsonObjPutObj(obj, "nested");
916 CX_TEST_ASSERT(nested != NULL); 1048 CX_TEST_ASSERT(nested != NULL);
917 CX_TEST_ASSERT(cxJsonIsObject(nested)); 1049 CX_TEST_ASSERT(cxJsonIsObject(nested));
918 cxJsonObjPutCxString(nested, CX_STR("string"), CX_STR("test")); 1050 cxJsonObjPutString(nested, "string", "test");
919 1051
920 cxJsonArrAddNumbers(cxJsonObjPutArr(nested, CX_STR("floats")), 1052 cxJsonArrAddNumbers(cxJsonObjPutArr(nested, "floats"),
921 (double[]){3.1415, 47.11, 8.15}, 3); 1053 (double[]){3.1415, 47.11, 8.15}, 3);
922 cxJsonArrAddIntegers(cxJsonObjPutArr(nested, CX_STR("ints")), 1054 cxJsonArrAddIntegers(cxJsonObjPutArr(nested, "ints"),
923 (int64_t[]){4, 8, 15, 16, 23, 42}, 6); 1055 (int64_t[]){4, 8, 15, 16, 23, 42}, 6);
924 cxJsonArrAddLiterals(cxJsonObjPutArr(nested, CX_STR("literals")), 1056 cxJsonArrAddLiterals(cxJsonObjPutArr(nested, "literals"),
925 (CxJsonLiteral[]){CX_JSON_TRUE, CX_JSON_NULL, CX_JSON_FALSE}, 3); 1057 (CxJsonLiteral[]){CX_JSON_TRUE, CX_JSON_NULL, CX_JSON_FALSE}, 3);
926 } 1058 }
927 1059
928 // verify the contents 1060 // verify the contents
929 { 1061 {
930 CX_TEST_ASSERT(cxJsonIsFalse(cxJsonObjGet(obj, "bool"))); 1062 CX_TEST_ASSERT(cxJsonIsFalse(cxJsonObjGet(obj, "bool")));
931 CX_TEST_ASSERT(47 == cxJsonAsInteger(cxJsonObjGet(obj, "int"))); 1063 CX_TEST_ASSERT(47 == cxJsonAsInteger(cxJsonObjGet(obj, "int")));
932 CxJsonValue *strings = cxJsonObjGet(obj, "strings"); 1064 CxJsonValue *strings = cxJsonObjGet(obj, "strings");
933 CX_TEST_ASSERT(cxJsonIsArray(strings)); 1065 CX_TEST_ASSERT(cxJsonIsArray(strings));
934 CX_TEST_ASSERT(2 == cxJsonArrSize(strings)); 1066 CX_TEST_ASSERT(2 == cxJsonArrSize(strings));
935 CX_TEST_ASSERT(0 == cx_strcmp(CX_STR("hello"), cxJsonAsCxString(cxJsonArrGet(strings, 0)))); 1067 CX_TEST_ASSERT(0 == cx_strcmp("hello", cxJsonAsString(cxJsonArrGet(strings, 0))));
936 CX_TEST_ASSERT(0 == cx_strcmp(CX_STR("world"), cxJsonAsCxString(cxJsonArrGet(strings, 1)))); 1068 CX_TEST_ASSERT(0 == cx_strcmp("world", cxJsonAsString(cxJsonArrGet(strings, 1))));
937 1069
938 CxJsonValue *nested = cxJsonObjGet(obj, "nested"); 1070 CxJsonValue *nested = cxJsonObjGet(obj, "nested");
939 CX_TEST_ASSERT(cxJsonIsObject(nested)); 1071 CX_TEST_ASSERT(cxJsonIsObject(nested));
940 CX_TEST_ASSERT(0 == strcmp("test", cxJsonAsString(cxJsonObjGet(nested, "string")))); 1072 CX_TEST_ASSERT(0 == strcmp("test", cxJsonAsString(cxJsonObjGet(nested, "string"))));
941 CxJsonValue *floats = cxJsonObjGet(nested, "floats"); 1073 CxJsonValue *floats = cxJsonObjGet(nested, "floats");
966 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 1098 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
967 } 1099 }
968 cx_testing_allocator_destroy(&talloc); 1100 cx_testing_allocator_destroy(&talloc);
969 } 1101 }
970 1102
1103 CX_TEST(test_json_overwrite_value) {
1104 CxTestingAllocator talloc;
1105 cx_testing_allocator_init(&talloc);
1106 CxAllocator *allocator = &talloc.base;
1107 CX_TEST_DO {
1108 CxJsonValue *obj = cxJsonCreateObj(allocator);
1109
1110 // put some values
1111 cxJsonObjPutInteger(obj, "test1", 1);
1112 cxJsonObjPutInteger(obj, "test2", 2);
1113 cxJsonObjPutInteger(obj, "test3", 3);
1114
1115 // overwrite test2
1116 cxJsonObjPutInteger(obj, "test2", 0);
1117
1118 // verify the values
1119 CxIterator iter = cxJsonObjIter(obj);
1120 bool found[5] = {0};
1121 cx_foreach(CxJsonObjValue *, ov, iter) {
1122 CxJsonValue *v = ov->value;
1123 CX_TEST_ASSERT(cxJsonIsInteger(v));
1124 int64_t i = cxJsonAsInteger(v);
1125 CX_TEST_ASSERT(i >= 0 && i <= 4);
1126 found[i] = true;
1127 }
1128 CX_TEST_ASSERT(found[0]);
1129 CX_TEST_ASSERT(found[1]);
1130 CX_TEST_ASSERT(!found[2]);
1131 CX_TEST_ASSERT(found[3]);
1132 CX_TEST_ASSERT(!found[4]);
1133
1134 // destroy the value and verify the allocations
1135 cxJsonValueFree(obj);
1136 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
1137 }
1138 cx_testing_allocator_destroy(&talloc);
1139 }
971 1140
972 CX_TEST_SUBROUTINE(test_json_write_sub, 1141 CX_TEST_SUBROUTINE(test_json_write_sub,
973 const CxAllocator *allocator, 1142 const CxAllocator *allocator,
974 cxstring expected, 1143 cxstring expected,
975 const CxJsonWriter *writer 1144 const CxJsonWriter *writer
976 ) { 1145 ) {
977 // create the value 1146 // create the value
978 CxJsonValue *obj = cxJsonCreateObj(allocator); 1147 CxJsonValue *obj = cxJsonCreateObj(allocator);
979 cxJsonObjPutLiteral(obj, CX_STR("bool"), CX_JSON_FALSE); 1148 cxJsonObjPutLiteral(obj, "bool", CX_JSON_FALSE);
980 cxJsonObjPutNumber(obj, CX_STR("int"), 47); // purposely use PutNumber to put an int 1149 cxJsonObjPutNumber(obj, "int", 47); // purposely use PutNumber to put an int
981 CxJsonValue *strings = cxJsonObjPutArr(obj, CX_STR("strings")); 1150 CxJsonValue *strings = cxJsonObjPutArr(obj, "strings");
982 cxJsonArrAddCxStrings(strings, (cxstring[]) {CX_STR("hello"), CX_STR("world")}, 2); 1151 cxJsonArrAddCxStrings(strings, (cxstring[]) {CX_STR("hello"), CX_STR("world")}, 2);
983 CxJsonValue *nested = cxJsonObjPutObj(obj, CX_STR("nested")); 1152 CxJsonValue *nested = cxJsonObjPutObj(obj, "nested");
984 CxJsonValue *objects = cxJsonObjPutArr(nested, CX_STR("objects")); 1153 CxJsonValue *objects = cxJsonObjPutArr(nested, "objects");
985 CxJsonValue *obj_in_arr[2] = {cxJsonCreateObj(allocator), cxJsonCreateObj(allocator)}; 1154 CxJsonValue *obj_in_arr[2] = {cxJsonCreateObj(allocator), cxJsonCreateObj(allocator)};
986 cxJsonObjPutInteger(obj_in_arr[0], CX_STR("name1"), 1); 1155 cxJsonObjPutInteger(obj_in_arr[0], "name1", 1);
987 cxJsonObjPutInteger(obj_in_arr[0], CX_STR("name2"), 3); 1156 cxJsonObjPutInteger(obj_in_arr[0], "name2", 3);
988 cxJsonObjPutInteger(obj_in_arr[1], CX_STR("name2"), 7); 1157 cxJsonObjPutInteger(obj_in_arr[1], "name2", 7);
989 cxJsonObjPutInteger(obj_in_arr[1], CX_STR("name1"), 3); 1158 cxJsonObjPutInteger(obj_in_arr[1], "name1", 3);
990 cxJsonArrAddValues(objects, obj_in_arr, 2); 1159 cxJsonArrAddValues(objects, obj_in_arr, 2);
991 cxJsonArrAddNumbers(cxJsonObjPutArr(nested, CX_STR("floats")), 1160 cxJsonArrAddNumbers(cxJsonObjPutArr(nested, "floats"),
992 (double[]){3.1415, 47.11, 8.15}, 3); 1161 (double[]){3.1415, 47.11, 8.15}, 3);
993 cxJsonArrAddLiterals(cxJsonObjPutArr(nested, CX_STR("literals")), 1162 cxJsonArrAddLiterals(cxJsonObjPutArr(nested, "literals"),
994 (CxJsonLiteral[]){CX_JSON_TRUE, CX_JSON_NULL, CX_JSON_FALSE}, 3); 1163 (CxJsonLiteral[]){CX_JSON_TRUE, CX_JSON_NULL, CX_JSON_FALSE}, 3);
995 CxJsonValue *ints = cxJsonObjPutArr(nested, CX_STR("ints")); 1164 CxJsonValue *ints = cxJsonObjPutArr(nested, "ints");
996 cxJsonArrAddIntegers(ints, (int64_t[]){4, 8, 15}, 3); 1165 cxJsonArrAddIntegers(ints, (int64_t[]){4, 8, 15}, 3);
997 CxJsonValue *nested_array = cxJsonCreateArr(allocator); 1166 CxJsonValue *nested_array = cxJsonCreateArr(allocator);
998 cxJsonArrAddValues(ints, &nested_array, 1); 1167 cxJsonArrAddValues(ints, &nested_array, 1);
999 cxJsonArrAddIntegers(nested_array, (int64_t[]){16, 23}, 2); 1168 cxJsonArrAddIntegers(nested_array, (int64_t[]){16, 23}, 2);
1000 cxJsonArrAddIntegers(ints, (int64_t[]){42}, 1); 1169 cxJsonArrAddIntegers(ints, (int64_t[]){42}, 1);
1018 CxTestingAllocator talloc; 1187 CxTestingAllocator talloc;
1019 cx_testing_allocator_init(&talloc); 1188 cx_testing_allocator_init(&talloc);
1020 CxAllocator *allocator = &talloc.base; 1189 CxAllocator *allocator = &talloc.base;
1021 CX_TEST_DO { 1190 CX_TEST_DO {
1022 // expected value 1191 // expected value
1023 cxstring expected = CX_STR( 1192 cxstring expected = cx_str(
1024 "{\"bool\":false," 1193 "{\"bool\":false,"
1025 "\"int\":47," 1194 "\"int\":47,"
1026 "\"nested\":{" 1195 "\"nested\":{"
1027 "\"floats\":[3.1415,47.11,8.15]," 1196 "\"floats\":[3.1415,47.11,8.15],"
1028 "\"ints\":[4,8,15,[16,23],42]," 1197 "\"ints\":[4,8,15,[16,23],42],"
1039 "}" 1208 "}"
1040 ); 1209 );
1041 1210
1042 CxJsonWriter writer = cxJsonWriterCompact(); 1211 CxJsonWriter writer = cxJsonWriterCompact();
1043 CX_TEST_CALL_SUBROUTINE(test_json_write_sub, allocator, expected, &writer); 1212 CX_TEST_CALL_SUBROUTINE(test_json_write_sub, allocator, expected, &writer);
1213 // try again, but this time with implicitly defaulted writer
1214 CX_TEST_CALL_SUBROUTINE(test_json_write_sub, allocator, expected, NULL);
1044 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 1215 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
1045 } 1216 }
1046 cx_testing_allocator_destroy(&talloc); 1217 cx_testing_allocator_destroy(&talloc);
1047 } 1218 }
1048 1219
1049 CX_TEST(test_json_write_pretty_default_spaces) { 1220 CX_TEST(test_json_write_pretty_default_spaces) {
1050 CxTestingAllocator talloc; 1221 CxTestingAllocator talloc;
1051 cx_testing_allocator_init(&talloc); 1222 cx_testing_allocator_init(&talloc);
1052 CxAllocator *allocator = &talloc.base; 1223 CxAllocator *allocator = &talloc.base;
1053 CX_TEST_DO { 1224 CX_TEST_DO {
1054 cxstring expected = CX_STR( 1225 cxstring expected = cx_str(
1055 "{\n" 1226 "{\n"
1056 " \"bool\": false,\n" 1227 " \"bool\": false,\n"
1057 " \"int\": 47,\n" 1228 " \"int\": 47,\n"
1058 " \"nested\": {\n" 1229 " \"nested\": {\n"
1059 " \"floats\": [3.1415, 47.11, 8.15],\n" 1230 " \"floats\": [3.1415, 47.11, 8.15],\n"
1081 CX_TEST(test_json_write_pretty_default_tabs) { 1252 CX_TEST(test_json_write_pretty_default_tabs) {
1082 CxTestingAllocator talloc; 1253 CxTestingAllocator talloc;
1083 cx_testing_allocator_init(&talloc); 1254 cx_testing_allocator_init(&talloc);
1084 CxAllocator *allocator = &talloc.base; 1255 CxAllocator *allocator = &talloc.base;
1085 CX_TEST_DO { 1256 CX_TEST_DO {
1086 cxstring expected = CX_STR( 1257 cxstring expected = cx_str(
1087 "{\n" 1258 "{\n"
1088 "\t\"bool\": false,\n" 1259 "\t\"bool\": false,\n"
1089 "\t\"int\": 47,\n" 1260 "\t\"int\": 47,\n"
1090 "\t\"nested\": {\n" 1261 "\t\"nested\": {\n"
1091 "\t\t\"floats\": [3.1415, 47.11, 8.15],\n" 1262 "\t\t\"floats\": [3.1415, 47.11, 8.15],\n"
1112 CX_TEST(test_json_write_pretty_preserve_order) { 1283 CX_TEST(test_json_write_pretty_preserve_order) {
1113 CxTestingAllocator talloc; 1284 CxTestingAllocator talloc;
1114 cx_testing_allocator_init(&talloc); 1285 cx_testing_allocator_init(&talloc);
1115 CxAllocator *allocator = &talloc.base; 1286 CxAllocator *allocator = &talloc.base;
1116 CX_TEST_DO { 1287 CX_TEST_DO {
1117 cxstring expected = CX_STR( 1288 cxstring expected = cx_str(
1118 "{\n" 1289 "{\n"
1119 " \"bool\": false,\n" 1290 " \"bool\": false,\n"
1120 " \"int\": 47,\n" 1291 " \"int\": 47,\n"
1121 " \"strings\": [\"hello\", \"world\"],\n" 1292 " \"strings\": [\"hello\", \"world\"],\n"
1122 " \"nested\": {\n" 1293 " \"nested\": {\n"
1140 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 1311 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
1141 } 1312 }
1142 cx_testing_allocator_destroy(&talloc); 1313 cx_testing_allocator_destroy(&talloc);
1143 } 1314 }
1144 1315
1316 CX_TEST(test_json_write_pretty_deep_nesting) {
1317 CxTestingAllocator talloc;
1318 cx_testing_allocator_init(&talloc);
1319 CxAllocator *allocator = &talloc.base;
1320 CX_TEST_DO {
1321 cxstring expected = cx_str(
1322 "{\n"
1323 " \"test\": {\n"
1324 " \"test\": {\n"
1325 " \"test\": {\n"
1326 " \"test\": {\n"
1327 " \"test\": {\n"
1328 " \"test\": 47\n"
1329 " }\n"
1330 " }\n"
1331 " }\n"
1332 " }\n"
1333 " }\n"
1334 "}"
1335 );
1336
1337 CxJsonValue *obj = cxJsonCreateObj(allocator);
1338 CxJsonValue *test = obj;
1339 for (unsigned i = 0 ; i < 5 ; i++) {
1340 test = cxJsonObjPutObj(test, "test");
1341 }
1342 cxJsonObjPutInteger(test, "test", 47);
1343
1344 CxJsonWriter writer = cxJsonWriterPretty(true);
1345 writer.indent = 8;
1346 CxBuffer buf;
1347 cxBufferInit(&buf, NULL, 512, NULL, CX_BUFFER_DEFAULT);
1348 int result = cxJsonWrite(&buf, obj, cxBufferWriteFunc, &writer);
1349 cxBufferTerminate(&buf); // makes debugging easier
1350 CX_TEST_ASSERT(result == 0);
1351
1352 // compare the string
1353 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), expected));
1354
1355 // destroy everything
1356 cxBufferDestroy(&buf);
1357 cxJsonValueFree(obj);
1358
1359 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
1360 }
1361 cx_testing_allocator_destroy(&talloc);
1362 }
1363
1145 CX_TEST(test_json_write_frac_max_digits) { 1364 CX_TEST(test_json_write_frac_max_digits) {
1146 CxJsonValue* num = cxJsonCreateNumber(NULL, 3.141592653589793); 1365 CxJsonValue* num = cxJsonCreateNumber(NULL, 3.141592653589793);
1147 CxJsonWriter writer = cxJsonWriterCompact(); 1366 CxJsonWriter writer = cxJsonWriterCompact();
1148 CxBuffer buf; 1367 CxBuffer buf;
1149 cxBufferInit(&buf, NULL, 32, NULL, 0); 1368 cxBufferInit(&buf, NULL, 32, NULL, 0);
1150 CX_TEST_DO { 1369 CX_TEST_DO {
1151 // test default settings (6 digits) 1370 // test default settings (6 digits)
1152 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer); 1371 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer);
1153 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("3.141592"))); 1372 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "3.141592"));
1154 1373
1155 // test too many digits 1374 // test too many digits
1156 cxBufferReset(&buf); 1375 cxBufferReset(&buf);
1157 writer.frac_max_digits = 200; 1376 writer.frac_max_digits = 200;
1158 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer); 1377 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer);
1159 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("3.141592653589793"))); 1378 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "3.141592653589793"));
1160 1379
1161 // test 0 digits 1380 // test 0 digits
1162 cxBufferReset(&buf); 1381 cxBufferReset(&buf);
1163 writer.frac_max_digits = 0; 1382 writer.frac_max_digits = 0;
1164 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer); 1383 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer);
1165 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("3"))); 1384 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "3"));
1166 1385
1167 // test 2 digits 1386 // test 2 digits
1168 cxBufferReset(&buf); 1387 cxBufferReset(&buf);
1169 writer.frac_max_digits = 2; 1388 writer.frac_max_digits = 2;
1170 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer); 1389 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer);
1171 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("3.14"))); 1390 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "3.14"));
1172 1391
1173 // test 3 digits 1392 // test 3 digits
1174 cxBufferReset(&buf); 1393 cxBufferReset(&buf);
1175 writer.frac_max_digits = 3; 1394 writer.frac_max_digits = 3;
1176 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer); 1395 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer);
1177 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("3.141"))); 1396 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "3.141"));
1178 1397
1179 // test 6 digits, but two are left of the decimal point 1398 // test 6 digits, but two are left of the decimal point
1180 num->value.number = 47.110815; 1399 num->value.number = 47.110815;
1181 cxBufferReset(&buf); 1400 cxBufferReset(&buf);
1182 writer.frac_max_digits = 6; 1401 writer.frac_max_digits = 6;
1183 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer); 1402 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer);
1184 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("47.110815"))); 1403 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "47.110815"));
1185 1404
1186 // test 4 digits with exponent 1405 // test 4 digits with exponent
1187 num->value.number = 5.11223344e23; 1406 num->value.number = 5.11223344e23;
1188 cxBufferReset(&buf); 1407 cxBufferReset(&buf);
1189 writer.frac_max_digits = 4; 1408 writer.frac_max_digits = 4;
1190 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer); 1409 cxJsonWrite(&buf, num, cxBufferWriteFunc, &writer);
1191 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("5.1122e+23"))); 1410 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "5.1122e+23"));
1192 } 1411 }
1193 cxBufferDestroy(&buf); 1412 cxBufferDestroy(&buf);
1194 cxJsonValueFree(num); 1413 cxJsonValueFree(num);
1195 } 1414 }
1196 1415
1214 CxBuffer buf; 1433 CxBuffer buf;
1215 cxBufferInit(&buf, NULL, 128, NULL, 0); 1434 cxBufferInit(&buf, NULL, 128, NULL, 0);
1216 CX_TEST_DO { 1435 CX_TEST_DO {
1217 cxJsonWrite(&buf, str, cxBufferWriteFunc, &writer); 1436 cxJsonWrite(&buf, str, cxBufferWriteFunc, &writer);
1218 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), 1437 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size),
1219 CX_STR("\"hello\\twörld\\r\\nthis is\\\\a \\\"string\\\"\\b in \\u0007 string\\f\""))); 1438 "\"hello\\twörld\\r\\nthis is\\\\a \\\"string\\\"\\b in \\u0007 string\\f\""));
1220 } 1439 }
1221 cxBufferDestroy(&buf); 1440 cxBufferDestroy(&buf);
1222 cxJsonValueFree(str); 1441 cxJsonValueFree(str);
1223 } 1442 }
1224 1443
1225 CX_TEST(test_json_write_name_escape) { 1444 CX_TEST(test_json_write_name_escape) {
1226 CxJsonValue* obj = cxJsonCreateObj(NULL); 1445 CxJsonValue* obj = cxJsonCreateObj(NULL);
1227 cxJsonObjPutLiteral(obj, 1446 cxJsonObjPutLiteral(obj,
1228 CX_STR("hello\twörld\r\nthis is\\a \"string\"\b in \a string\f"), CX_JSON_TRUE); 1447 "hello\twörld\r\nthis is\\a \"string\"\b in \a string\f", CX_JSON_TRUE);
1229 CxJsonWriter writer = cxJsonWriterCompact(); 1448 CxJsonWriter writer = cxJsonWriterCompact();
1230 CxBuffer buf; 1449 CxBuffer buf;
1231 cxBufferInit(&buf, NULL, 128, NULL, 0); 1450 cxBufferInit(&buf, NULL, 128, NULL, 0);
1232 CX_TEST_DO { 1451 CX_TEST_DO {
1233 cxJsonWrite(&buf, obj, cxBufferWriteFunc, &writer); 1452 cxJsonWrite(&buf, obj, cxBufferWriteFunc, &writer);
1234 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), 1453 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size),
1235 CX_STR("{\"hello\\twörld\\r\\nthis is\\\\a \\\"string\\\"\\b in \\u0007 string\\f\":true}"))); 1454 "{\"hello\\twörld\\r\\nthis is\\\\a \\\"string\\\"\\b in \\u0007 string\\f\":true}"));
1236 } 1455 }
1237 cxBufferDestroy(&buf); 1456 cxBufferDestroy(&buf);
1238 cxJsonValueFree(obj); 1457 cxJsonValueFree(obj);
1239 } 1458 }
1240 1459
1244 CxBuffer buf; 1463 CxBuffer buf;
1245 cxBufferInit(&buf, NULL, 16, NULL, 0); 1464 cxBufferInit(&buf, NULL, 16, NULL, 0);
1246 CX_TEST_DO { 1465 CX_TEST_DO {
1247 // default: do not escape 1466 // default: do not escape
1248 cxJsonWrite(&buf, str, cxBufferWriteFunc, &writer); 1467 cxJsonWrite(&buf, str, cxBufferWriteFunc, &writer);
1249 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("\"test/solidus\""))); 1468 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "\"test/solidus\""));
1250 1469
1251 // enable escaping 1470 // enable escaping
1252 writer.escape_slash = true; 1471 writer.escape_slash = true;
1253 cxBufferReset(&buf); 1472 cxBufferReset(&buf);
1254 cxJsonWrite(&buf, str, cxBufferWriteFunc, &writer); 1473 cxJsonWrite(&buf, str, cxBufferWriteFunc, &writer);
1255 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), CX_STR("\"test\\/solidus\""))); 1474 CX_TEST_ASSERT(0 == cx_strcmp(cx_strn(buf.space, buf.size), "\"test\\/solidus\""));
1256 } 1475 }
1257 cxBufferDestroy(&buf); 1476 cxBufferDestroy(&buf);
1258 cxJsonValueFree(str); 1477 cxJsonValueFree(str);
1259 } 1478 }
1260 1479
1480 CX_TEST(test_json_write_nothing) {
1481 CxBuffer buf;
1482 cxBufferInit(&buf, NULL, 16, NULL, 0);
1483 CX_TEST_DO {
1484 CxJsonValue nothing;
1485 nothing.type = CX_JSON_NOTHING;
1486 cxJsonWrite(&buf, &nothing, cxBufferWriteFunc, NULL);
1487 CX_TEST_ASSERT(buf.size == 0);
1488 }
1489 cxBufferDestroy(&buf);
1490 }
1491
1261 CxTestSuite *cx_test_suite_json(void) { 1492 CxTestSuite *cx_test_suite_json(void) {
1262 CxTestSuite *suite = cx_test_suite_new("json"); 1493 CxTestSuite *suite = cx_test_suite_new("json");
1263 1494
1264 cx_test_register(suite, test_json_init_default); 1495 cx_test_register(suite, test_json_init_default);
1265 cx_test_register(suite, test_json_simple_object); 1496 cx_test_register(suite, test_json_simple_object);
1497 cx_test_register(suite, test_json_large_object);
1266 cx_test_register(suite, test_json_escaped_strings); 1498 cx_test_register(suite, test_json_escaped_strings);
1267 cx_test_register(suite, test_json_escaped_unicode_strings); 1499 cx_test_register(suite, test_json_escaped_unicode_strings);
1268 cx_test_register(suite, test_json_escaped_unicode_malformed); 1500 cx_test_register(suite, test_json_escaped_unicode_malformed);
1269 cx_test_register(suite, test_json_escaped_end_of_string); 1501 cx_test_register(suite, test_json_escaped_end_of_string);
1270 cx_test_register(suite, test_json_object_incomplete_token); 1502 cx_test_register(suite, test_json_object_incomplete_token);
1503 cx_test_register(suite, test_json_parenthesis_mismatch);
1504 cx_test_register(suite, test_json_object_name_is_no_string);
1271 cx_test_register(suite, test_json_token_wrongly_completed); 1505 cx_test_register(suite, test_json_token_wrongly_completed);
1272 cx_test_register(suite, test_json_object_error); 1506 cx_test_register(suite, test_json_object_error);
1273 cx_test_register(suite, test_json_object_remove_member); 1507 cx_test_register(suite, test_json_object_remove_member);
1274 cx_test_register(suite, test_json_subsequent_fill); 1508 cx_test_register(suite, test_json_subsequent_fill);
1509 cx_test_register(suite, test_json_no_fill);
1510 cx_test_register(suite, test_json_null_fill);
1275 cx_test_register(suite, test_json_large_nesting_depth); 1511 cx_test_register(suite, test_json_large_nesting_depth);
1276 cx_test_register(suite, test_json_number); 1512 cx_test_register(suite, test_json_number);
1277 cx_test_register(suite, test_json_number_format_errors); 1513 cx_test_register(suite, test_json_number_format_errors);
1278 cx_test_register(suite, test_json_multiple_values); 1514 cx_test_register(suite, test_json_multiple_values);
1279 cx_test_register(suite, test_json_array); 1515 cx_test_register(suite, test_json_array);
1280 cx_test_register(suite, test_json_array_iterator); 1516 cx_test_register(suite, test_json_array_iterator);
1281 cx_test_register(suite, test_json_allocator); 1517 cx_test_register(suite, test_json_allocator);
1282 cx_test_register(suite, test_json_allocator_parse_error); 1518 cx_test_register(suite, test_json_allocator_parse_error);
1283 cx_test_register(suite, test_json_create_value); 1519 cx_test_register(suite, test_json_create_value);
1520 cx_test_register(suite, test_json_overwrite_value);
1284 cx_test_register(suite, test_json_write_default_format); 1521 cx_test_register(suite, test_json_write_default_format);
1285 cx_test_register(suite, test_json_write_pretty_default_spaces); 1522 cx_test_register(suite, test_json_write_pretty_default_spaces);
1286 cx_test_register(suite, test_json_write_pretty_default_tabs); 1523 cx_test_register(suite, test_json_write_pretty_default_tabs);
1287 cx_test_register(suite, test_json_write_pretty_preserve_order); 1524 cx_test_register(suite, test_json_write_pretty_preserve_order);
1525 cx_test_register(suite, test_json_write_pretty_deep_nesting);
1288 cx_test_register(suite, test_json_write_frac_max_digits); 1526 cx_test_register(suite, test_json_write_frac_max_digits);
1289 cx_test_register(suite, test_json_write_string_escape); 1527 cx_test_register(suite, test_json_write_string_escape);
1290 cx_test_register(suite, test_json_write_name_escape); 1528 cx_test_register(suite, test_json_write_name_escape);
1291 cx_test_register(suite, test_json_write_solidus); 1529 cx_test_register(suite, test_json_write_solidus);
1530 cx_test_register(suite, test_json_write_nothing);
1292 1531
1293 return suite; 1532 return suite;
1294 } 1533 }
1295 1534

mercurial