9 #define VIR_FROM_THIS VIR_FROM_NONE
20 testJSONFromFile(const void *data
)
22 const struct testInfo
*info
= data
;
23 VIR_AUTOPTR(virJSONValue
) injson
= NULL
;
24 VIR_AUTOFREE(char *) infile
= NULL
;
25 VIR_AUTOFREE(char *) indata
= NULL
;
26 VIR_AUTOFREE(char *) outfile
= NULL
;
27 VIR_AUTOFREE(char *) actual
= NULL
;
29 if (virAsprintf(&infile
, "%s/virjsondata/parse-%s-in.json",
30 abs_srcdir
, info
->name
) < 0 ||
31 virAsprintf(&outfile
, "%s/virjsondata/parse-%s-out.json",
32 abs_srcdir
, info
->name
) < 0)
35 if (virTestLoadFile(infile
, &indata
) < 0)
38 injson
= virJSONValueFromString(indata
);
42 VIR_TEST_VERBOSE("Failed to parse %s\n", info
->doc
);
45 VIR_TEST_DEBUG("As expected, failed to parse %s\n", info
->doc
);
50 VIR_TEST_VERBOSE("Unexpected success while parsing %s\n", info
->doc
);
55 if (!(actual
= virJSONValueToString(injson
, false)))
58 if (virTestCompareToFile(actual
, outfile
) < 0)
66 testJSONFromString(const void *data
)
68 const struct testInfo
*info
= data
;
69 VIR_AUTOPTR(virJSONValue
) json
= NULL
;
70 const char *expectstr
= info
->expect
? info
->expect
: info
->doc
;
71 VIR_AUTOFREE(char *) formatted
= NULL
;
73 json
= virJSONValueFromString(info
->doc
);
77 VIR_TEST_VERBOSE("Failed to parse %s\n", info
->doc
);
80 VIR_TEST_DEBUG("As expected, failed to parse %s\n", info
->doc
);
85 VIR_TEST_VERBOSE("Unexpected success while parsing %s\n", info
->doc
);
90 VIR_TEST_DEBUG("Parsed %s\n", info
->doc
);
92 if (!(formatted
= virJSONValueToString(json
, false))) {
93 VIR_TEST_VERBOSE("Failed to format json data\n");
97 if (STRNEQ(expectstr
, formatted
)) {
98 virTestDifference(stderr
, expectstr
, formatted
);
107 testJSONAddRemove(const void *data
)
109 const struct testInfo
*info
= data
;
110 VIR_AUTOPTR(virJSONValue
) json
= NULL
;
111 VIR_AUTOPTR(virJSONValue
) name
= NULL
;
112 VIR_AUTOFREE(char *) infile
= NULL
;
113 VIR_AUTOFREE(char *) indata
= NULL
;
114 VIR_AUTOFREE(char *) outfile
= NULL
;
115 VIR_AUTOFREE(char *) actual
= NULL
;
117 if (virAsprintf(&infile
, "%s/virjsondata/add-remove-%s-in.json",
118 abs_srcdir
, info
->name
) < 0 ||
119 virAsprintf(&outfile
, "%s/virjsondata/add-remove-%s-out.json",
120 abs_srcdir
, info
->name
) < 0)
123 if (virTestLoadFile(infile
, &indata
) < 0)
126 json
= virJSONValueFromString(indata
);
128 VIR_TEST_VERBOSE("Fail to parse %s\n", info
->name
);
132 switch (virJSONValueObjectRemoveKey(json
, "name", &name
)) {
135 VIR_TEST_VERBOSE("should not remove from non-object %s\n",
144 VIR_TEST_VERBOSE("Fail to recognize non-object %s\n", info
->name
);
147 VIR_TEST_VERBOSE("unexpected result when removing from %s\n",
151 if (STRNEQ_NULLABLE(virJSONValueGetString(name
), "sample")) {
152 VIR_TEST_VERBOSE("unexpected value after removing name: %s\n",
153 NULLSTR(virJSONValueGetString(name
)));
156 if (virJSONValueObjectRemoveKey(json
, "name", NULL
)) {
157 VIR_TEST_VERBOSE("%s",
158 "unexpected success when removing missing key\n");
161 if (virJSONValueObjectAppendString(json
, "newname", "foo") < 0) {
162 VIR_TEST_VERBOSE("%s", "unexpected failure adding new key\n");
165 if (!(actual
= virJSONValueToString(json
, false))) {
166 VIR_TEST_VERBOSE("%s", "failed to stringize result\n");
170 if (virTestCompareToFile(actual
, outfile
) < 0)
178 testJSONLookup(const void *data
)
180 const struct testInfo
*info
= data
;
181 VIR_AUTOPTR(virJSONValue
) json
= NULL
;
182 virJSONValuePtr value
= NULL
;
183 VIR_AUTOFREE(char *) result
= NULL
;
188 json
= virJSONValueFromString(info
->doc
);
190 VIR_TEST_VERBOSE("Fail to parse %s\n", info
->doc
);
194 value
= virJSONValueObjectGetObject(json
, "a");
197 VIR_TEST_VERBOSE("lookup for 'a' in '%s' should have failed\n",
201 result
= virJSONValueToString(value
, false);
202 if (STRNEQ_NULLABLE(result
, "{}")) {
203 VIR_TEST_VERBOSE("lookup for 'a' in '%s' found '%s' but "
204 "should have found '{}'\n",
205 info
->doc
, NULLSTR(result
));
210 } else if (info
->pass
) {
211 VIR_TEST_VERBOSE("lookup for 'a' in '%s' should have succeeded\n",
217 rc
= virJSONValueObjectGetNumberInt(json
, "b", &number
);
220 VIR_TEST_VERBOSE("lookup for 'b' in '%s' should have failed\n",
223 } else if (number
!= 1) {
224 VIR_TEST_VERBOSE("lookup for 'b' in '%s' found %d but "
225 "should have found 1\n",
229 } else if (info
->pass
) {
230 VIR_TEST_VERBOSE("lookup for 'b' in '%s' should have succeeded\n",
235 str
= virJSONValueObjectGetString(json
, "c");
238 VIR_TEST_VERBOSE("lookup for 'c' in '%s' should have failed\n",
241 } else if (STRNEQ(str
, "str")) {
242 VIR_TEST_VERBOSE("lookup for 'c' in '%s' found '%s' but "
243 "should have found 'str'\n", info
->doc
, str
);
246 } else if (info
->pass
) {
247 VIR_TEST_VERBOSE("lookup for 'c' in '%s' should have succeeded\n",
252 value
= virJSONValueObjectGetArray(json
, "d");
255 VIR_TEST_VERBOSE("lookup for 'd' in '%s' should have failed\n",
259 result
= virJSONValueToString(value
, false);
260 if (STRNEQ_NULLABLE(result
, "[]")) {
261 VIR_TEST_VERBOSE("lookup for 'd' in '%s' found '%s' but "
262 "should have found '[]'\n",
263 info
->doc
, NULLSTR(result
));
268 } else if (info
->pass
) {
269 VIR_TEST_VERBOSE("lookup for 'd' in '%s' should have succeeded\n",
279 testJSONCopy(const void *data
)
281 const struct testInfo
*info
= data
;
282 VIR_AUTOPTR(virJSONValue
) json
= NULL
;
283 VIR_AUTOPTR(virJSONValue
) jsonCopy
= NULL
;
284 VIR_AUTOFREE(char *) result
= NULL
;
285 VIR_AUTOFREE(char *) resultCopy
= NULL
;
287 json
= virJSONValueFromString(info
->doc
);
289 VIR_TEST_VERBOSE("Failed to parse %s\n", info
->doc
);
293 jsonCopy
= virJSONValueCopy(json
);
295 VIR_TEST_VERBOSE("Failed to copy JSON data\n");
299 result
= virJSONValueToString(json
, false);
301 VIR_TEST_VERBOSE("Failed to format original JSON data\n");
305 resultCopy
= virJSONValueToString(json
, false);
307 VIR_TEST_VERBOSE("Failed to format copied JSON data\n");
311 if (STRNEQ(result
, resultCopy
)) {
312 if (virTestGetVerbose())
313 virTestDifference(stderr
, result
, resultCopy
);
318 VIR_FREE(resultCopy
);
320 result
= virJSONValueToString(json
, true);
322 VIR_TEST_VERBOSE("Failed to format original JSON data\n");
326 resultCopy
= virJSONValueToString(json
, true);
328 VIR_TEST_VERBOSE("Failed to format copied JSON data\n");
332 if (STRNEQ(result
, resultCopy
)) {
333 if (virTestGetVerbose())
334 virTestDifference(stderr
, result
, resultCopy
);
343 testJSONDeflatten(const void *data
)
345 const struct testInfo
*info
= data
;
346 VIR_AUTOPTR(virJSONValue
) injson
= NULL
;
347 VIR_AUTOPTR(virJSONValue
) deflattened
= NULL
;
348 VIR_AUTOFREE(char *) infile
= NULL
;
349 VIR_AUTOFREE(char *) indata
= NULL
;
350 VIR_AUTOFREE(char *) outfile
= NULL
;
351 VIR_AUTOFREE(char *) actual
= NULL
;
353 if (virAsprintf(&infile
, "%s/virjsondata/deflatten-%s-in.json",
354 abs_srcdir
, info
->name
) < 0 ||
355 virAsprintf(&outfile
, "%s/virjsondata/deflatten-%s-out.json",
356 abs_srcdir
, info
->name
) < 0)
359 if (virTestLoadFile(infile
, &indata
) < 0)
362 if (!(injson
= virJSONValueFromString(indata
)))
365 if ((deflattened
= virJSONValueObjectDeflatten(injson
))) {
367 VIR_TEST_VERBOSE("%s: deflattening should have failed\n", info
->name
);
377 if (!(actual
= virJSONValueToString(deflattened
, true)))
380 if (virTestCompareToFile(actual
, outfile
) < 0)
388 testJSONEscapeObj(const void *data ATTRIBUTE_UNUSED
)
390 VIR_AUTOPTR(virJSONValue
) json
= NULL
;
391 VIR_AUTOPTR(virJSONValue
) nestjson
= NULL
;
392 VIR_AUTOPTR(virJSONValue
) parsejson
= NULL
;
393 VIR_AUTOFREE(char *) neststr
= NULL
;
394 VIR_AUTOFREE(char *) result
= NULL
;
395 const char *parsednestedstr
;
397 if (virJSONValueObjectCreate(&nestjson
,
398 "s:stringkey", "stringvalue",
400 "b:booleankey", false, NULL
) < 0) {
401 VIR_TEST_VERBOSE("failed to create nested json object");
405 if (!(neststr
= virJSONValueToString(nestjson
, false))) {
406 VIR_TEST_VERBOSE("failed to format nested json object");
410 if (virJSONValueObjectCreate(&json
, "s:test", neststr
, NULL
) < 0) {
411 VIR_TEST_VERBOSE("Failed to create json object");
415 if (!(result
= virJSONValueToString(json
, false))) {
416 VIR_TEST_VERBOSE("Failed to format json object");
420 if (!(parsejson
= virJSONValueFromString(result
))) {
421 VIR_TEST_VERBOSE("Failed to parse JSON with nested JSON in string");
425 if (!(parsednestedstr
= virJSONValueObjectGetString(parsejson
, "test"))) {
426 VIR_TEST_VERBOSE("Failed to retrieve string containing nested json");
430 if (STRNEQ(parsednestedstr
, neststr
)) {
431 virTestDifference(stderr
, neststr
, parsednestedstr
);
440 testJSONObjectFormatSteal(const void *opaque ATTRIBUTE_UNUSED
)
442 VIR_AUTOPTR(virJSONValue
) a1
= NULL
;
443 VIR_AUTOPTR(virJSONValue
) a2
= NULL
;
444 VIR_AUTOPTR(virJSONValue
) t1
= NULL
;
445 VIR_AUTOPTR(virJSONValue
) t2
= NULL
;
447 if (!(a1
= virJSONValueNewString("test")) ||
448 !(a2
= virJSONValueNewString("test"))) {
449 VIR_TEST_VERBOSE("Failed to create json object");
452 if (virJSONValueObjectCreate(&t1
, "a:t", &a1
, "s:f", NULL
, NULL
) != -1) {
453 VIR_TEST_VERBOSE("virJSONValueObjectCreate(t1) should have failed\n");
458 VIR_TEST_VERBOSE("appended object a1 was not consumed\n");
462 if (virJSONValueObjectCreate(&t2
, "s:f", NULL
, "a:t", &a1
, NULL
) != -1) {
463 VIR_TEST_VERBOSE("virJSONValueObjectCreate(t2) should have failed\n");
468 VIR_TEST_VERBOSE("appended object a2 was consumed\n");
481 #define DO_TEST_FULL(name, cmd, doc, expect, pass) \
483 struct testInfo info = { name, doc, expect, pass }; \
484 if (virTestRun(name, testJSON ## cmd, &info) < 0) \
491 * @doc: source JSON string
492 * @expect: expected output JSON formatted from parsed @doc
494 * Parses @doc and formats it back. If @expect is NULL the result has to be
497 #define DO_TEST_PARSE(name, doc, expect) \
498 DO_TEST_FULL(name, FromString, doc, expect, true)
500 #define DO_TEST_PARSE_FAIL(name, doc) \
501 DO_TEST_FULL(name, FromString, doc, NULL, false)
503 #define DO_TEST_PARSE_FILE(name) \
504 DO_TEST_FULL(name, FromFile, NULL, NULL, true)
507 DO_TEST_PARSE_FILE("Simple");
508 DO_TEST_PARSE_FILE("NotSoSimple");
509 DO_TEST_PARSE_FILE("Harder");
510 DO_TEST_PARSE_FILE("VeryHard");
512 DO_TEST_FULL("success", AddRemove
, NULL
, NULL
, true);
513 DO_TEST_FULL("failure", AddRemove
, NULL
, NULL
, false);
515 DO_TEST_FULL("copy and free", Copy
,
516 "{\"return\": [{\"name\": \"quit\"}, {\"name\": \"eject\"},"
517 "{\"name\": \"change\"}, {\"name\": \"screendump\"},"
518 "{\"name\": \"stop\"}, {\"name\": \"cont\"}, {\"name\": "
519 "\"system_reset\"}, {\"name\": \"system_powerdown\"}, "
520 "{\"name\": \"device_add\"}, {\"name\": \"device_del\"}, "
521 "{\"name\": \"cpu\"}, {\"name\": \"memsave\"}, {\"name\": "
522 "\"pmemsave\"}, {\"name\": \"migrate\"}, {\"name\": "
523 "\"migrate_cancel\"}, {\"name\": \"migrate_set_speed\"},"
524 "{\"name\": \"client_migrate_info\"}, {\"name\": "
525 "\"migrate_set_downtime\"}, {\"name\": \"netdev_add\"}, "
526 "{\"name\": \"netdev_del\"}, {\"name\": \"block_resize\"},"
527 "{\"name\": \"balloon\"}, {\"name\": \"set_link\"}, {\"name\":"
528 "\"getfd\"}, {\"name\": \"closefd\"}, {\"name\": \"block_passwd\"},"
529 "{\"name\": \"set_password\"}, {\"name\": \"expire_password\"},"
530 "{\"name\": \"qmp_capabilities\"}, {\"name\": "
531 "\"human-monitor-command\"}, {\"name\": \"query-version\"},"
532 "{\"name\": \"query-commands\"}, {\"name\": \"query-chardev\"},"
533 "{\"name\": \"query-block\"}, {\"name\": \"query-blockstats\"}, "
534 "{\"name\": \"query-cpus\"}, {\"name\": \"query-pci\"}, {\"name\":"
535 "\"query-kvm\"}, {\"name\": \"query-status\"}, {\"name\": "
536 "\"query-mice\"}, {\"name\": \"query-vnc\"}, {\"name\": "
537 "\"query-spice\"}, {\"name\": \"query-name\"}, {\"name\": "
538 "\"query-uuid\"}, {\"name\": \"query-migrate\"}, {\"name\": "
539 "\"query-balloon\"}], \"id\": \"libvirt-2\"}", NULL
, true);
542 DO_TEST_PARSE("almost nothing", "[]", NULL
);
543 DO_TEST_PARSE_FAIL("nothing", "");
545 DO_TEST_PARSE("number without garbage", "[ 234545 ]", "[234545]");
546 DO_TEST_PARSE_FAIL("number with garbage", "[ 2345b45 ]");
548 DO_TEST_PARSE("float without garbage", "[ 1.024e19 ]", "[1.024e19]");
549 DO_TEST_PARSE_FAIL("float with garbage", "[ 0.0314159ee+100 ]");
551 DO_TEST_PARSE("unsigned minus one", "[ 18446744073709551615 ]", "[18446744073709551615]");
552 DO_TEST_PARSE("another big number", "[ 9223372036854775808 ]", "[9223372036854775808]");
554 DO_TEST_PARSE("string", "[ \"The meaning of life\" ]",
555 "[\"The meaning of life\"]");
556 DO_TEST_PARSE_FAIL("unterminated string", "[ \"The meaning of lif ]");
558 DO_TEST_PARSE("integer", "1", NULL
);
559 DO_TEST_PARSE("boolean", "true", NULL
);
560 DO_TEST_PARSE("null", "null", NULL
);
562 DO_TEST_PARSE("escaping symbols", "[\"\\\"\\t\\n\\\\\"]", NULL
);
563 DO_TEST_PARSE("escaped strings", "[\"{\\\"blurb\\\":\\\"test\\\"}\"]", NULL
);
565 DO_TEST_PARSE_FAIL("incomplete keyword", "tr");
566 DO_TEST_PARSE_FAIL("overdone keyword", "[ truest ]");
567 DO_TEST_PARSE_FAIL("unknown keyword", "huh");
568 DO_TEST_PARSE_FAIL("comments", "[ /* nope */\n1 // not this either\n]");
569 DO_TEST_PARSE_FAIL("trailing garbage", "[] []");
570 DO_TEST_PARSE_FAIL("list without array", "1, 1");
571 DO_TEST_PARSE_FAIL("parser abuse", "1] [2");
572 DO_TEST_PARSE_FAIL("invalid UTF-8", "\"\x80\"");
574 DO_TEST_PARSE_FAIL("object with numeric keys", "{ 1:1, 2:1, 3:2 }");
575 DO_TEST_PARSE_FAIL("unterminated object", "{ \"1\":1, \"2\":1, \"3\":2");
576 DO_TEST_PARSE_FAIL("unterminated array of objects",
577 "[ {\"name\": \"John\"}, {\"name\": \"Paul\"}, ");
578 DO_TEST_PARSE_FAIL("array of an object with an array as a key",
579 "[ {[\"key1\", \"key2\"]: \"value\"} ]");
580 DO_TEST_PARSE_FAIL("object with unterminated key", "{ \"key:7 }");
581 DO_TEST_PARSE_FAIL("duplicate key", "{ \"a\": 1, \"a\": 1 }");
583 DO_TEST_FULL("lookup on array", Lookup
,
584 "[ 1 ]", NULL
, false);
585 DO_TEST_FULL("lookup on string", Lookup
,
586 "\"str\"", NULL
, false);
587 DO_TEST_FULL("lookup on integer", Lookup
,
589 DO_TEST_FULL("lookup with missing key", Lookup
,
591 DO_TEST_FULL("lookup with wrong type", Lookup
,
592 "{ \"a\": 1, \"b\": \"str\", \"c\": [], \"d\": {} }",
594 DO_TEST_FULL("lookup with correct type", Lookup
,
595 "{ \"a\": {}, \"b\": 1, \"c\": \"str\", \"d\": [] }",
597 DO_TEST_FULL("create object with nested json in attribute", EscapeObj
,
599 DO_TEST_FULL("stealing of attributes while creating objects",
600 ObjectFormatSteal
, NULL
, NULL
, true);
602 #define DO_TEST_DEFLATTEN(name, pass) \
603 DO_TEST_FULL(name, Deflatten, NULL, NULL, pass)
605 DO_TEST_DEFLATTEN("unflattened", true);
606 DO_TEST_DEFLATTEN("basic-file", true);
607 DO_TEST_DEFLATTEN("basic-generic", true);
608 DO_TEST_DEFLATTEN("deep-file", true);
609 DO_TEST_DEFLATTEN("deep-generic", true);
610 DO_TEST_DEFLATTEN("nested", true);
611 DO_TEST_DEFLATTEN("double-key", false);
612 DO_TEST_DEFLATTEN("concat", true);
613 DO_TEST_DEFLATTEN("concat-double-key", false);
614 DO_TEST_DEFLATTEN("qemu-sheepdog", true);
616 return (ret
== 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;
619 VIR_TEST_MAIN(mymain
)