virjsontest.c 19.3 KB
Newer Older
1 2 3 4 5
#include <config.h>

#include <time.h>

#include "internal.h"
6
#include "virjson.h"
7 8
#include "testutils.h"

9 10
#define VIR_FROM_THIS VIR_FROM_NONE

11
struct testInfo {
J
Ján Tomko 已提交
12
    const char *name;
13
    const char *doc;
14
    const char *expect;
15 16 17 18
    bool pass;
};


19 20 21 22 23 24 25
static int
testJSONFromFile(const void *data)
{
    const struct testInfo *info = data;
    VIR_AUTOPTR(virJSONValue) injson = NULL;
    VIR_AUTOFREE(char *) infile = NULL;
    VIR_AUTOFREE(char *) indata = NULL;
26
    VIR_AUTOFREE(char *) outfile = NULL;
27 28 29
    VIR_AUTOFREE(char *) actual = NULL;

    if (virAsprintf(&infile, "%s/virjsondata/parse-%s-in.json",
30 31
                    abs_srcdir, info->name) < 0 ||
        virAsprintf(&outfile, "%s/virjsondata/parse-%s-out.json",
32 33 34 35 36 37 38 39 40 41
                    abs_srcdir, info->name) < 0)
        return -1;

    if (virTestLoadFile(infile, &indata) < 0)
        return -1;

    injson = virJSONValueFromString(indata);

    if (!injson) {
        if (info->pass) {
42
            VIR_TEST_VERBOSE("Failed to parse %s", info->doc);
43 44
            return -1;
        } else {
45
            VIR_TEST_DEBUG("As expected, failed to parse %s", info->doc);
46 47 48 49
            return 0;
        }
    } else {
        if (!info->pass) {
50
            VIR_TEST_VERBOSE("Unexpected success while parsing %s", info->doc);
51 52 53 54 55 56 57
            return -1;
        }
    }

    if (!(actual = virJSONValueToString(injson, false)))
        return -1;

58
    if (virTestCompareToFile(actual, outfile) < 0)
59 60 61 62 63 64
        return -1;

    return 0;
}


65 66 67 68
static int
testJSONFromString(const void *data)
{
    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;
72 73 74

    json = virJSONValueFromString(info->doc);

75 76
    if (!json) {
        if (info->pass) {
77
            VIR_TEST_VERBOSE("Failed to parse %s", info->doc);
78
            return -1;
79
        } else {
80
            VIR_TEST_DEBUG("As expected, failed to parse %s", info->doc);
81
            return 0;
82
        }
83 84
    } else {
        if (!info->pass) {
85
            VIR_TEST_VERBOSE("Unexpected success while parsing %s", info->doc);
86
            return -1;
87
        }
88 89
    }

90
    VIR_TEST_DEBUG("Parsed %s", info->doc);
91

92
    if (!(formatted = virJSONValueToString(json, false))) {
93
        VIR_TEST_VERBOSE("Failed to format json data");
94
        return -1;
95 96 97 98
    }

    if (STRNEQ(expectstr, formatted)) {
        virTestDifference(stderr, expectstr, formatted);
99
        return -1;
100 101
    }

102
    return 0;
103 104 105
}


106 107 108 109
static int
testJSONAddRemove(const void *data)
{
    const struct testInfo *info = data;
110 111
    VIR_AUTOPTR(virJSONValue) json = NULL;
    VIR_AUTOPTR(virJSONValue) name = NULL;
112 113 114 115
    VIR_AUTOFREE(char *) infile = NULL;
    VIR_AUTOFREE(char *) indata = NULL;
    VIR_AUTOFREE(char *) outfile = NULL;
    VIR_AUTOFREE(char *) actual = NULL;
116

117 118 119 120
    if (virAsprintf(&infile, "%s/virjsondata/add-remove-%s-in.json",
                    abs_srcdir, info->name) < 0 ||
        virAsprintf(&outfile, "%s/virjsondata/add-remove-%s-out.json",
                    abs_srcdir, info->name) < 0)
121
        return -1;
122 123

    if (virTestLoadFile(infile, &indata) < 0)
124
        return -1;
125 126

    json = virJSONValueFromString(indata);
127
    if (!json) {
128
        VIR_TEST_VERBOSE("Fail to parse %s", info->name);
129
        return -1;
130
    }
131 132 133 134

    switch (virJSONValueObjectRemoveKey(json, "name", &name)) {
    case 1:
        if (!info->pass) {
135
            VIR_TEST_VERBOSE("should not remove from non-object %s",
136
                             info->name);
137
            return -1;
138 139 140 141
        }
        break;
    case -1:
        if (!info->pass)
142
            return 0;
143
        else
144
            VIR_TEST_VERBOSE("Fail to recognize non-object %s", info->name);
145
        return -1;
146
    default:
147
        VIR_TEST_VERBOSE("unexpected result when removing from %s",
148
                         info->name);
149
        return -1;
150 151
    }
    if (STRNEQ_NULLABLE(virJSONValueGetString(name), "sample")) {
152
        VIR_TEST_VERBOSE("unexpected value after removing name: %s",
153
                         NULLSTR(virJSONValueGetString(name)));
154
        return -1;
155 156
    }
    if (virJSONValueObjectRemoveKey(json, "name", NULL)) {
157
        VIR_TEST_VERBOSE("%s",
158
                         "unexpected success when removing missing key");
159
        return -1;
160 161
    }
    if (virJSONValueObjectAppendString(json, "newname", "foo") < 0) {
162
        VIR_TEST_VERBOSE("%s", "unexpected failure adding new key");
163
        return -1;
164
    }
165
    if (!(actual = virJSONValueToString(json, false))) {
166
        VIR_TEST_VERBOSE("%s", "failed to stringize result");
167
        return -1;
168
    }
169

170 171
    if (virTestCompareToFile(actual, outfile) < 0)
        return -1;
172

173
    return 0;
174 175 176
}


177 178 179 180
static int
testJSONLookup(const void *data)
{
    const struct testInfo *info = data;
181
    VIR_AUTOPTR(virJSONValue) json = NULL;
182
    virJSONValuePtr value = NULL;
183
    VIR_AUTOFREE(char *) result = NULL;
184 185 186 187 188 189
    int rc;
    int number;
    const char *str;

    json = virJSONValueFromString(info->doc);
    if (!json) {
190
        VIR_TEST_VERBOSE("Fail to parse %s", info->doc);
191
        return -1;
192 193 194 195 196
    }

    value = virJSONValueObjectGetObject(json, "a");
    if (value) {
        if (!info->pass) {
197
            VIR_TEST_VERBOSE("lookup for 'a' in '%s' should have failed",
198
                             info->doc);
199
            return -1;
200 201 202 203
        } else {
            result = virJSONValueToString(value, false);
            if (STRNEQ_NULLABLE(result, "{}")) {
                VIR_TEST_VERBOSE("lookup for 'a' in '%s' found '%s' but "
204
                                 "should have found '{}'",
205
                                 info->doc, NULLSTR(result));
206
                return -1;
207 208 209 210
            }
            VIR_FREE(result);
        }
    } else if (info->pass) {
211
        VIR_TEST_VERBOSE("lookup for 'a' in '%s' should have succeeded",
212
                         info->doc);
213
        return -1;
214 215 216 217 218 219
    }

    number = 2;
    rc = virJSONValueObjectGetNumberInt(json, "b", &number);
    if (rc == 0) {
        if (!info->pass) {
220
            VIR_TEST_VERBOSE("lookup for 'b' in '%s' should have failed",
221
                             info->doc);
222
            return -1;
223 224
        } else if (number != 1) {
            VIR_TEST_VERBOSE("lookup for 'b' in '%s' found %d but "
225
                             "should have found 1",
226
                             info->doc, number);
227
            return -1;
228 229
        }
    } else if (info->pass) {
230
        VIR_TEST_VERBOSE("lookup for 'b' in '%s' should have succeeded",
231
                         info->doc);
232
        return -1;
233 234 235 236 237
    }

    str = virJSONValueObjectGetString(json, "c");
    if (str) {
        if (!info->pass) {
238
            VIR_TEST_VERBOSE("lookup for 'c' in '%s' should have failed",
239
                             info->doc);
240
            return -1;
241 242
        } else if (STRNEQ(str, "str")) {
            VIR_TEST_VERBOSE("lookup for 'c' in '%s' found '%s' but "
243
                             "should have found 'str'", info->doc, str);
244
                return -1;
245 246
        }
    } else if (info->pass) {
247
        VIR_TEST_VERBOSE("lookup for 'c' in '%s' should have succeeded",
248
                         info->doc);
249
        return -1;
250 251 252 253 254
    }

    value = virJSONValueObjectGetArray(json, "d");
    if (value) {
        if (!info->pass) {
255
            VIR_TEST_VERBOSE("lookup for 'd' in '%s' should have failed",
256
                             info->doc);
257
            return -1;
258 259 260 261
        } else {
            result = virJSONValueToString(value, false);
            if (STRNEQ_NULLABLE(result, "[]")) {
                VIR_TEST_VERBOSE("lookup for 'd' in '%s' found '%s' but "
262
                                 "should have found '[]'",
263
                                 info->doc, NULLSTR(result));
264
                return -1;
265 266 267 268
            }
            VIR_FREE(result);
        }
    } else if (info->pass) {
269
        VIR_TEST_VERBOSE("lookup for 'd' in '%s' should have succeeded",
270
                         info->doc);
271
        return -1;
272 273
    }

274
    return 0;
275 276 277
}


M
Martin Kletzander 已提交
278 279 280 281
static int
testJSONCopy(const void *data)
{
    const struct testInfo *info = data;
282 283
    VIR_AUTOPTR(virJSONValue) json = NULL;
    VIR_AUTOPTR(virJSONValue) jsonCopy = NULL;
284 285
    VIR_AUTOFREE(char *) result = NULL;
    VIR_AUTOFREE(char *) resultCopy = NULL;
M
Martin Kletzander 已提交
286 287 288

    json = virJSONValueFromString(info->doc);
    if (!json) {
289
        VIR_TEST_VERBOSE("Failed to parse %s", info->doc);
290
        return -1;
M
Martin Kletzander 已提交
291 292 293 294
    }

    jsonCopy = virJSONValueCopy(json);
    if (!jsonCopy) {
295
        VIR_TEST_VERBOSE("Failed to copy JSON data");
296
        return -1;
M
Martin Kletzander 已提交
297 298 299 300
    }

    result = virJSONValueToString(json, false);
    if (!result) {
301
        VIR_TEST_VERBOSE("Failed to format original JSON data");
302
        return -1;
M
Martin Kletzander 已提交
303 304 305 306
    }

    resultCopy = virJSONValueToString(json, false);
    if (!resultCopy) {
307
        VIR_TEST_VERBOSE("Failed to format copied JSON data");
308
        return -1;
M
Martin Kletzander 已提交
309 310 311 312
    }

    if (STRNEQ(result, resultCopy)) {
        if (virTestGetVerbose())
313
            virTestDifference(stderr, result, resultCopy);
314
        return -1;
M
Martin Kletzander 已提交
315 316 317 318 319 320 321
    }

    VIR_FREE(result);
    VIR_FREE(resultCopy);

    result = virJSONValueToString(json, true);
    if (!result) {
322
        VIR_TEST_VERBOSE("Failed to format original JSON data");
323
        return -1;
M
Martin Kletzander 已提交
324 325 326 327
    }

    resultCopy = virJSONValueToString(json, true);
    if (!resultCopy) {
328
        VIR_TEST_VERBOSE("Failed to format copied JSON data");
329
        return -1;
M
Martin Kletzander 已提交
330 331 332 333
    }

    if (STRNEQ(result, resultCopy)) {
        if (virTestGetVerbose())
334
            virTestDifference(stderr, result, resultCopy);
335
        return -1;
M
Martin Kletzander 已提交
336 337
    }

338
    return 0;
M
Martin Kletzander 已提交
339 340 341
}


342 343 344 345
static int
testJSONDeflatten(const void *data)
{
    const struct testInfo *info = data;
346 347
    VIR_AUTOPTR(virJSONValue) injson = NULL;
    VIR_AUTOPTR(virJSONValue) deflattened = NULL;
348 349 350 351
    VIR_AUTOFREE(char *) infile = NULL;
    VIR_AUTOFREE(char *) indata = NULL;
    VIR_AUTOFREE(char *) outfile = NULL;
    VIR_AUTOFREE(char *) actual = NULL;
352 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)
357
        return -1;
358 359

    if (virTestLoadFile(infile, &indata) < 0)
360
        return -1;
361 362

    if (!(injson = virJSONValueFromString(indata)))
363
        return -1;
364 365 366

    if ((deflattened = virJSONValueObjectDeflatten(injson))) {
        if (!info->pass) {
367
            VIR_TEST_VERBOSE("%s: deflattening should have failed", info->name);
368
            return -1;
369 370 371
        }
    } else {
        if (!info->pass)
372
            return 0;
373

374
        return -1;
375 376 377
    }

    if (!(actual = virJSONValueToString(deflattened, true)))
378
        return -1;
379 380

    if (virTestCompareToFile(actual, outfile) < 0)
381
        return -1;
382

383
    return 0;
384 385 386 387 388 389
}


static int
testJSONEscapeObj(const void *data ATTRIBUTE_UNUSED)
{
390 391 392
    VIR_AUTOPTR(virJSONValue) json = NULL;
    VIR_AUTOPTR(virJSONValue) nestjson = NULL;
    VIR_AUTOPTR(virJSONValue) parsejson = NULL;
393 394
    VIR_AUTOFREE(char *) neststr = NULL;
    VIR_AUTOFREE(char *) result = NULL;
395 396 397 398 399 400 401
    const char *parsednestedstr;

    if (virJSONValueObjectCreate(&nestjson,
                                 "s:stringkey", "stringvalue",
                                 "i:numberkey", 1234,
                                 "b:booleankey", false, NULL) < 0) {
        VIR_TEST_VERBOSE("failed to create nested json object");
402
        return -1;
403 404 405 406
    }

    if (!(neststr = virJSONValueToString(nestjson, false))) {
        VIR_TEST_VERBOSE("failed to format nested json object");
407
        return -1;
408 409 410 411
    }

    if (virJSONValueObjectCreate(&json, "s:test", neststr, NULL) < 0) {
        VIR_TEST_VERBOSE("Failed to create json object");
412
        return -1;
413 414 415 416
    }

    if (!(result = virJSONValueToString(json, false))) {
        VIR_TEST_VERBOSE("Failed to format json object");
417
        return -1;
418 419 420 421
    }

    if (!(parsejson = virJSONValueFromString(result))) {
        VIR_TEST_VERBOSE("Failed to parse JSON with nested JSON in string");
422
        return -1;
423 424 425 426
    }

    if (!(parsednestedstr = virJSONValueObjectGetString(parsejson, "test"))) {
        VIR_TEST_VERBOSE("Failed to retrieve string containing nested json");
427
        return -1;
428
    }
429

430 431
    if (STRNEQ(parsednestedstr, neststr)) {
        virTestDifference(stderr, neststr, parsednestedstr);
432
        return -1;
433 434
    }

435
    return 0;
436 437 438
}


439 440 441
static int
testJSONObjectFormatSteal(const void *opaque ATTRIBUTE_UNUSED)
{
442 443 444 445
    VIR_AUTOPTR(virJSONValue) a1 = NULL;
    VIR_AUTOPTR(virJSONValue) a2 = NULL;
    VIR_AUTOPTR(virJSONValue) t1 = NULL;
    VIR_AUTOPTR(virJSONValue) t2 = NULL;
446 447 448 449 450 451 452

    if (!(a1 = virJSONValueNewString("test")) ||
        !(a2 = virJSONValueNewString("test"))) {
        VIR_TEST_VERBOSE("Failed to create json object");
    }

    if (virJSONValueObjectCreate(&t1, "a:t", &a1, "s:f", NULL, NULL) != -1) {
453
        VIR_TEST_VERBOSE("virJSONValueObjectCreate(t1) should have failed");
454
        return -1;
455 456 457
    }

    if (a1) {
458
        VIR_TEST_VERBOSE("appended object a1 was not consumed");
459
        return -1;
460 461 462
    }

    if (virJSONValueObjectCreate(&t2, "s:f", NULL, "a:t", &a1, NULL) != -1) {
463
        VIR_TEST_VERBOSE("virJSONValueObjectCreate(t2) should have failed");
464
        return -1;
465 466 467
    }

    if (!a2) {
468
        VIR_TEST_VERBOSE("appended object a2 was consumed");
469
        return -1;
470 471
    }

472
    return 0;
473 474 475
}


476 477 478 479 480
static int
mymain(void)
{
    int ret = 0;

481 482
#define DO_TEST_FULL(name, cmd, doc, expect, pass) \
    do { \
J
Ján Tomko 已提交
483
        struct testInfo info = { name, doc, expect, pass }; \
484 485
        if (virTestRun(name, testJSON ## cmd, &info) < 0) \
            ret = -1; \
486 487
    } while (0)

488 489 490 491 492 493 494 495 496
/**
 * DO_TEST_PARSE:
 * @name: test name
 * @doc: source JSON string
 * @expect: expected output JSON formatted from parsed @doc
 *
 * Parses @doc and formats it back. If @expect is NULL the result has to be
 * identical to @doc.
 */
497
#define DO_TEST_PARSE(name, doc, expect) \
498
    DO_TEST_FULL(name, FromString, doc, expect, true)
499

500
#define DO_TEST_PARSE_FAIL(name, doc) \
501 502
    DO_TEST_FULL(name, FromString, doc, NULL, false)

503 504 505 506 507 508 509 510
#define DO_TEST_PARSE_FILE(name) \
    DO_TEST_FULL(name, FromFile, NULL, NULL, true)


    DO_TEST_PARSE_FILE("Simple");
    DO_TEST_PARSE_FILE("NotSoSimple");
    DO_TEST_PARSE_FILE("Harder");
    DO_TEST_PARSE_FILE("VeryHard");
511

512 513
    DO_TEST_FULL("success", AddRemove, NULL, NULL, true);
    DO_TEST_FULL("failure", AddRemove, NULL, NULL, false);
514

M
Martin Kletzander 已提交
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
    DO_TEST_FULL("copy and free", Copy,
                 "{\"return\": [{\"name\": \"quit\"}, {\"name\": \"eject\"},"
                 "{\"name\": \"change\"}, {\"name\": \"screendump\"},"
                 "{\"name\": \"stop\"}, {\"name\": \"cont\"}, {\"name\": "
                 "\"system_reset\"}, {\"name\": \"system_powerdown\"}, "
                 "{\"name\": \"device_add\"}, {\"name\": \"device_del\"}, "
                 "{\"name\": \"cpu\"}, {\"name\": \"memsave\"}, {\"name\": "
                 "\"pmemsave\"}, {\"name\": \"migrate\"}, {\"name\": "
                 "\"migrate_cancel\"}, {\"name\": \"migrate_set_speed\"},"
                 "{\"name\": \"client_migrate_info\"}, {\"name\": "
                 "\"migrate_set_downtime\"}, {\"name\": \"netdev_add\"}, "
                 "{\"name\": \"netdev_del\"}, {\"name\": \"block_resize\"},"
                 "{\"name\": \"balloon\"}, {\"name\": \"set_link\"}, {\"name\":"
                 "\"getfd\"}, {\"name\": \"closefd\"}, {\"name\": \"block_passwd\"},"
                 "{\"name\": \"set_password\"}, {\"name\": \"expire_password\"},"
                 "{\"name\": \"qmp_capabilities\"}, {\"name\": "
                 "\"human-monitor-command\"}, {\"name\": \"query-version\"},"
                 "{\"name\": \"query-commands\"}, {\"name\": \"query-chardev\"},"
                 "{\"name\": \"query-block\"}, {\"name\": \"query-blockstats\"}, "
                 "{\"name\": \"query-cpus\"}, {\"name\": \"query-pci\"}, {\"name\":"
                 "\"query-kvm\"}, {\"name\": \"query-status\"}, {\"name\": "
                 "\"query-mice\"}, {\"name\": \"query-vnc\"}, {\"name\": "
                 "\"query-spice\"}, {\"name\": \"query-name\"}, {\"name\": "
                 "\"query-uuid\"}, {\"name\": \"query-migrate\"}, {\"name\": "
                 "\"query-balloon\"}], \"id\": \"libvirt-2\"}", NULL, true);

541

542
    DO_TEST_PARSE("almost nothing", "[]", NULL);
543 544
    DO_TEST_PARSE_FAIL("nothing", "");

545
    DO_TEST_PARSE("number without garbage", "[ 234545 ]", "[234545]");
546 547
    DO_TEST_PARSE_FAIL("number with garbage", "[ 2345b45 ]");

548
    DO_TEST_PARSE("float without garbage", "[ 1.024e19 ]", "[1.024e19]");
549 550
    DO_TEST_PARSE_FAIL("float with garbage", "[ 0.0314159ee+100 ]");

551 552 553
    DO_TEST_PARSE("unsigned minus one", "[ 18446744073709551615 ]", "[18446744073709551615]");
    DO_TEST_PARSE("another big number", "[ 9223372036854775808 ]", "[9223372036854775808]");

554 555
    DO_TEST_PARSE("string", "[ \"The meaning of life\" ]",
                  "[\"The meaning of life\"]");
556 557
    DO_TEST_PARSE_FAIL("unterminated string", "[ \"The meaning of lif ]");

558 559 560
    DO_TEST_PARSE("integer", "1", NULL);
    DO_TEST_PARSE("boolean", "true", NULL);
    DO_TEST_PARSE("null", "null", NULL);
561 562 563 564

    DO_TEST_PARSE("escaping symbols", "[\"\\\"\\t\\n\\\\\"]", NULL);
    DO_TEST_PARSE("escaped strings", "[\"{\\\"blurb\\\":\\\"test\\\"}\"]", NULL);

E
Eric Blake 已提交
565
    DO_TEST_PARSE_FAIL("incomplete keyword", "tr");
566
    DO_TEST_PARSE_FAIL("overdone keyword", "[ truest ]");
E
Eric Blake 已提交
567
    DO_TEST_PARSE_FAIL("unknown keyword", "huh");
E
Eric Blake 已提交
568
    DO_TEST_PARSE_FAIL("comments", "[ /* nope */\n1 // not this either\n]");
E
Eric Blake 已提交
569 570
    DO_TEST_PARSE_FAIL("trailing garbage", "[] []");
    DO_TEST_PARSE_FAIL("list without array", "1, 1");
571
    DO_TEST_PARSE_FAIL("parser abuse", "1] [2");
E
Eric Blake 已提交
572
    DO_TEST_PARSE_FAIL("invalid UTF-8", "\"\x80\"");
573 574

    DO_TEST_PARSE_FAIL("object with numeric keys", "{ 1:1, 2:1, 3:2 }");
575 576 577
    DO_TEST_PARSE_FAIL("unterminated object", "{ \"1\":1, \"2\":1, \"3\":2");
    DO_TEST_PARSE_FAIL("unterminated array of objects",
                       "[ {\"name\": \"John\"}, {\"name\": \"Paul\"}, ");
578 579
    DO_TEST_PARSE_FAIL("array of an object with an array as a key",
                       "[ {[\"key1\", \"key2\"]: \"value\"} ]");
580
    DO_TEST_PARSE_FAIL("object with unterminated key", "{ \"key:7 }");
E
Eric Blake 已提交
581
    DO_TEST_PARSE_FAIL("duplicate key", "{ \"a\": 1, \"a\": 1 }");
582

583 584 585 586 587 588 589 590 591 592 593 594 595 596
    DO_TEST_FULL("lookup on array", Lookup,
                 "[ 1 ]", NULL, false);
    DO_TEST_FULL("lookup on string", Lookup,
                 "\"str\"", NULL, false);
    DO_TEST_FULL("lookup on integer", Lookup,
                 "1", NULL, false);
    DO_TEST_FULL("lookup with missing key", Lookup,
                 "{ }", NULL, false);
    DO_TEST_FULL("lookup with wrong type", Lookup,
                 "{ \"a\": 1, \"b\": \"str\", \"c\": [], \"d\": {} }",
                 NULL, false);
    DO_TEST_FULL("lookup with correct type", Lookup,
                 "{ \"a\": {}, \"b\": 1, \"c\": \"str\", \"d\": [] }",
                 NULL, true);
597 598
    DO_TEST_FULL("create object with nested json in attribute", EscapeObj,
                 NULL, NULL, true);
599 600
    DO_TEST_FULL("stealing of attributes while creating objects",
                 ObjectFormatSteal, NULL, NULL, true);
601

602
#define DO_TEST_DEFLATTEN(name, pass) \
603
    DO_TEST_FULL(name, Deflatten, NULL, NULL, pass)
604 605 606

    DO_TEST_DEFLATTEN("unflattened", true);
    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);
615

616 617 618
    return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

619
VIR_TEST_MAIN(mymain)