qemu/tests/check-qdict.c
<<
>>
Prefs
   1/*
   2 * QDict unit-tests.
   3 *
   4 * Copyright (C) 2009 Red Hat Inc.
   5 *
   6 * Authors:
   7 *  Luiz Capitulino <lcapitulino@redhat.com>
   8 *
   9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  10 * See the COPYING.LIB file in the top-level directory.
  11 */
  12#include "qemu/osdep.h"
  13
  14#include "qapi/qmp/qint.h"
  15#include "qapi/qmp/qdict.h"
  16#include "qapi/qmp/qstring.h"
  17#include "qapi/error.h"
  18#include "qemu-common.h"
  19
  20/*
  21 * Public Interface test-cases
  22 *
  23 * (with some violations to access 'private' data)
  24 */
  25
  26static void qdict_new_test(void)
  27{
  28    QDict *qdict;
  29
  30    qdict = qdict_new();
  31    g_assert(qdict != NULL);
  32    g_assert(qdict_size(qdict) == 0);
  33    g_assert(qdict->base.refcnt == 1);
  34    g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
  35
  36    // destroy doesn't exit yet
  37    g_free(qdict);
  38}
  39
  40static void qdict_put_obj_test(void)
  41{
  42    QInt *qi;
  43    QDict *qdict;
  44    QDictEntry *ent;
  45    const int num = 42;
  46
  47    qdict = qdict_new();
  48
  49    // key "" will have tdb hash 12345
  50    qdict_put_obj(qdict, "", QOBJECT(qint_from_int(num)));
  51
  52    g_assert(qdict_size(qdict) == 1);
  53    ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
  54    qi = qobject_to_qint(ent->value);
  55    g_assert(qint_get_int(qi) == num);
  56
  57    // destroy doesn't exit yet
  58    QDECREF(qi);
  59    g_free(ent->key);
  60    g_free(ent);
  61    g_free(qdict);
  62}
  63
  64static void qdict_destroy_simple_test(void)
  65{
  66    QDict *qdict;
  67
  68    qdict = qdict_new();
  69    qdict_put_obj(qdict, "num", QOBJECT(qint_from_int(0)));
  70    qdict_put_obj(qdict, "str", QOBJECT(qstring_from_str("foo")));
  71
  72    QDECREF(qdict);
  73}
  74
  75static void qdict_get_test(void)
  76{
  77    QInt *qi;
  78    QObject *obj;
  79    const int value = -42;
  80    const char *key = "test";
  81    QDict *tests_dict = qdict_new();
  82
  83    qdict_put(tests_dict, key, qint_from_int(value));
  84
  85    obj = qdict_get(tests_dict, key);
  86    g_assert(obj != NULL);
  87
  88    qi = qobject_to_qint(obj);
  89    g_assert(qint_get_int(qi) == value);
  90
  91    QDECREF(tests_dict);
  92}
  93
  94static void qdict_get_int_test(void)
  95{
  96    int ret;
  97    const int value = 100;
  98    const char *key = "int";
  99    QDict *tests_dict = qdict_new();
 100
 101    qdict_put(tests_dict, key, qint_from_int(value));
 102
 103    ret = qdict_get_int(tests_dict, key);
 104    g_assert(ret == value);
 105
 106    QDECREF(tests_dict);
 107}
 108
 109static void qdict_get_try_int_test(void)
 110{
 111    int ret;
 112    const int value = 100;
 113    const char *key = "int";
 114    QDict *tests_dict = qdict_new();
 115
 116    qdict_put(tests_dict, key, qint_from_int(value));
 117
 118    ret = qdict_get_try_int(tests_dict, key, 0);
 119    g_assert(ret == value);
 120
 121    QDECREF(tests_dict);
 122}
 123
 124static void qdict_get_str_test(void)
 125{
 126    const char *p;
 127    const char *key = "key";
 128    const char *str = "string";
 129    QDict *tests_dict = qdict_new();
 130
 131    qdict_put(tests_dict, key, qstring_from_str(str));
 132
 133    p = qdict_get_str(tests_dict, key);
 134    g_assert(p != NULL);
 135    g_assert(strcmp(p, str) == 0);
 136
 137    QDECREF(tests_dict);
 138}
 139
 140static void qdict_get_try_str_test(void)
 141{
 142    const char *p;
 143    const char *key = "key";
 144    const char *str = "string";
 145    QDict *tests_dict = qdict_new();
 146
 147    qdict_put(tests_dict, key, qstring_from_str(str));
 148
 149    p = qdict_get_try_str(tests_dict, key);
 150    g_assert(p != NULL);
 151    g_assert(strcmp(p, str) == 0);
 152
 153    QDECREF(tests_dict);
 154}
 155
 156static void qdict_defaults_test(void)
 157{
 158    QDict *dict, *copy;
 159
 160    dict = qdict_new();
 161    copy = qdict_new();
 162
 163    qdict_set_default_str(dict, "foo", "abc");
 164    qdict_set_default_str(dict, "foo", "def");
 165    g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "abc");
 166    qdict_set_default_str(dict, "bar", "ghi");
 167
 168    qdict_copy_default(copy, dict, "foo");
 169    g_assert_cmpstr(qdict_get_str(copy, "foo"), ==, "abc");
 170    qdict_set_default_str(copy, "bar", "xyz");
 171    qdict_copy_default(copy, dict, "bar");
 172    g_assert_cmpstr(qdict_get_str(copy, "bar"), ==, "xyz");
 173
 174    QDECREF(copy);
 175    QDECREF(dict);
 176}
 177
 178static void qdict_haskey_not_test(void)
 179{
 180    QDict *tests_dict = qdict_new();
 181    g_assert(qdict_haskey(tests_dict, "test") == 0);
 182
 183    QDECREF(tests_dict);
 184}
 185
 186static void qdict_haskey_test(void)
 187{
 188    const char *key = "test";
 189    QDict *tests_dict = qdict_new();
 190
 191    qdict_put(tests_dict, key, qint_from_int(0));
 192    g_assert(qdict_haskey(tests_dict, key) == 1);
 193
 194    QDECREF(tests_dict);
 195}
 196
 197static void qdict_del_test(void)
 198{
 199    const char *key = "key test";
 200    QDict *tests_dict = qdict_new();
 201
 202    qdict_put(tests_dict, key, qstring_from_str("foo"));
 203    g_assert(qdict_size(tests_dict) == 1);
 204
 205    qdict_del(tests_dict, key);
 206
 207    g_assert(qdict_size(tests_dict) == 0);
 208    g_assert(qdict_haskey(tests_dict, key) == 0);
 209
 210    QDECREF(tests_dict);
 211}
 212
 213static void qobject_to_qdict_test(void)
 214{
 215    QDict *tests_dict = qdict_new();
 216    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
 217
 218    QDECREF(tests_dict);
 219}
 220
 221static void qdict_iterapi_test(void)
 222{
 223    int count;
 224    const QDictEntry *ent;
 225    QDict *tests_dict = qdict_new();
 226
 227    g_assert(qdict_first(tests_dict) == NULL);
 228
 229    qdict_put(tests_dict, "key1", qint_from_int(1));
 230    qdict_put(tests_dict, "key2", qint_from_int(2));
 231    qdict_put(tests_dict, "key3", qint_from_int(3));
 232
 233    count = 0;
 234    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
 235        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
 236        count++;
 237    }
 238
 239    g_assert(count == qdict_size(tests_dict));
 240
 241    /* Do it again to test restarting */
 242    count = 0;
 243    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
 244        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
 245        count++;
 246    }
 247
 248    g_assert(count == qdict_size(tests_dict));
 249
 250    QDECREF(tests_dict);
 251}
 252
 253static void qdict_flatten_test(void)
 254{
 255    QList *list1 = qlist_new();
 256    QList *list2 = qlist_new();
 257    QDict *dict1 = qdict_new();
 258    QDict *dict2 = qdict_new();
 259    QDict *dict3 = qdict_new();
 260
 261    /*
 262     * Test the flattening of
 263     *
 264     * {
 265     *     "e": [
 266     *         42,
 267     *         [
 268     *             23,
 269     *             66,
 270     *             {
 271     *                 "a": 0,
 272     *                 "b": 1
 273     *             }
 274     *         ]
 275     *     ],
 276     *     "f": {
 277     *         "c": 2,
 278     *         "d": 3,
 279     *     },
 280     *     "g": 4
 281     * }
 282     *
 283     * to
 284     *
 285     * {
 286     *     "e.0": 42,
 287     *     "e.1.0": 23,
 288     *     "e.1.1": 66,
 289     *     "e.1.2.a": 0,
 290     *     "e.1.2.b": 1,
 291     *     "f.c": 2,
 292     *     "f.d": 3,
 293     *     "g": 4
 294     * }
 295     */
 296
 297    qdict_put(dict1, "a", qint_from_int(0));
 298    qdict_put(dict1, "b", qint_from_int(1));
 299
 300    qlist_append_obj(list1, QOBJECT(qint_from_int(23)));
 301    qlist_append_obj(list1, QOBJECT(qint_from_int(66)));
 302    qlist_append_obj(list1, QOBJECT(dict1));
 303    qlist_append_obj(list2, QOBJECT(qint_from_int(42)));
 304    qlist_append_obj(list2, QOBJECT(list1));
 305
 306    qdict_put(dict2, "c", qint_from_int(2));
 307    qdict_put(dict2, "d", qint_from_int(3));
 308    qdict_put_obj(dict3, "e", QOBJECT(list2));
 309    qdict_put_obj(dict3, "f", QOBJECT(dict2));
 310    qdict_put(dict3, "g", qint_from_int(4));
 311
 312    qdict_flatten(dict3);
 313
 314    g_assert(qdict_get_int(dict3, "e.0") == 42);
 315    g_assert(qdict_get_int(dict3, "e.1.0") == 23);
 316    g_assert(qdict_get_int(dict3, "e.1.1") == 66);
 317    g_assert(qdict_get_int(dict3, "e.1.2.a") == 0);
 318    g_assert(qdict_get_int(dict3, "e.1.2.b") == 1);
 319    g_assert(qdict_get_int(dict3, "f.c") == 2);
 320    g_assert(qdict_get_int(dict3, "f.d") == 3);
 321    g_assert(qdict_get_int(dict3, "g") == 4);
 322
 323    g_assert(qdict_size(dict3) == 8);
 324
 325    QDECREF(dict3);
 326}
 327
 328static void qdict_array_split_test(void)
 329{
 330    QDict *test_dict = qdict_new();
 331    QDict *dict1, *dict2;
 332    QInt *int1;
 333    QList *test_list;
 334
 335    /*
 336     * Test the split of
 337     *
 338     * {
 339     *     "1.x": 0,
 340     *     "4.y": 1,
 341     *     "0.a": 42,
 342     *     "o.o": 7,
 343     *     "0.b": 23,
 344     *     "2": 66
 345     * }
 346     *
 347     * to
 348     *
 349     * [
 350     *     {
 351     *         "a": 42,
 352     *         "b": 23
 353     *     },
 354     *     {
 355     *         "x": 0
 356     *     },
 357     *     66
 358     * ]
 359     *
 360     * and
 361     *
 362     * {
 363     *     "4.y": 1,
 364     *     "o.o": 7
 365     * }
 366     *
 367     * (remaining in the old QDict)
 368     *
 369     * This example is given in the comment of qdict_array_split().
 370     */
 371
 372    qdict_put(test_dict, "1.x", qint_from_int(0));
 373    qdict_put(test_dict, "4.y", qint_from_int(1));
 374    qdict_put(test_dict, "0.a", qint_from_int(42));
 375    qdict_put(test_dict, "o.o", qint_from_int(7));
 376    qdict_put(test_dict, "0.b", qint_from_int(23));
 377    qdict_put(test_dict, "2", qint_from_int(66));
 378
 379    qdict_array_split(test_dict, &test_list);
 380
 381    dict1 = qobject_to_qdict(qlist_pop(test_list));
 382    dict2 = qobject_to_qdict(qlist_pop(test_list));
 383    int1 = qobject_to_qint(qlist_pop(test_list));
 384
 385    g_assert(dict1);
 386    g_assert(dict2);
 387    g_assert(int1);
 388    g_assert(qlist_empty(test_list));
 389
 390    QDECREF(test_list);
 391
 392    g_assert(qdict_get_int(dict1, "a") == 42);
 393    g_assert(qdict_get_int(dict1, "b") == 23);
 394
 395    g_assert(qdict_size(dict1) == 2);
 396
 397    QDECREF(dict1);
 398
 399    g_assert(qdict_get_int(dict2, "x") == 0);
 400
 401    g_assert(qdict_size(dict2) == 1);
 402
 403    QDECREF(dict2);
 404
 405    g_assert(qint_get_int(int1) == 66);
 406
 407    QDECREF(int1);
 408
 409    g_assert(qdict_get_int(test_dict, "4.y") == 1);
 410    g_assert(qdict_get_int(test_dict, "o.o") == 7);
 411
 412    g_assert(qdict_size(test_dict) == 2);
 413
 414    QDECREF(test_dict);
 415
 416    /*
 417     * Test the split of
 418     *
 419     * {
 420     *     "0": 42,
 421     *     "1": 23,
 422     *     "1.x": 84
 423     * }
 424     *
 425     * to
 426     *
 427     * [
 428     *     42
 429     * ]
 430     *
 431     * and
 432     *
 433     * {
 434     *     "1": 23,
 435     *     "1.x": 84
 436     * }
 437     *
 438     * That is, test whether splitting stops if there is both an entry with key
 439     * of "%u" and other entries with keys prefixed "%u." for the same index.
 440     */
 441
 442    test_dict = qdict_new();
 443
 444    qdict_put(test_dict, "0", qint_from_int(42));
 445    qdict_put(test_dict, "1", qint_from_int(23));
 446    qdict_put(test_dict, "1.x", qint_from_int(84));
 447
 448    qdict_array_split(test_dict, &test_list);
 449
 450    int1 = qobject_to_qint(qlist_pop(test_list));
 451
 452    g_assert(int1);
 453    g_assert(qlist_empty(test_list));
 454
 455    QDECREF(test_list);
 456
 457    g_assert(qint_get_int(int1) == 42);
 458
 459    QDECREF(int1);
 460
 461    g_assert(qdict_get_int(test_dict, "1") == 23);
 462    g_assert(qdict_get_int(test_dict, "1.x") == 84);
 463
 464    g_assert(qdict_size(test_dict) == 2);
 465
 466    QDECREF(test_dict);
 467}
 468
 469static void qdict_array_entries_test(void)
 470{
 471    QDict *dict = qdict_new();
 472
 473    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);
 474
 475    qdict_put(dict, "bar", qint_from_int(0));
 476    qdict_put(dict, "baz.0", qint_from_int(0));
 477    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);
 478
 479    qdict_put(dict, "foo.1", qint_from_int(0));
 480    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
 481    qdict_put(dict, "foo.0", qint_from_int(0));
 482    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 2);
 483    qdict_put(dict, "foo.bar", qint_from_int(0));
 484    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
 485    qdict_del(dict, "foo.bar");
 486
 487    qdict_put(dict, "foo.2.a", qint_from_int(0));
 488    qdict_put(dict, "foo.2.b", qint_from_int(0));
 489    qdict_put(dict, "foo.2.c", qint_from_int(0));
 490    g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 3);
 491    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
 492
 493    QDECREF(dict);
 494
 495    dict = qdict_new();
 496    qdict_put(dict, "1", qint_from_int(0));
 497    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
 498    qdict_put(dict, "0", qint_from_int(0));
 499    g_assert_cmpint(qdict_array_entries(dict, ""), ==, 2);
 500    qdict_put(dict, "bar", qint_from_int(0));
 501    g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
 502    qdict_del(dict, "bar");
 503
 504    qdict_put(dict, "2.a", qint_from_int(0));
 505    qdict_put(dict, "2.b", qint_from_int(0));
 506    qdict_put(dict, "2.c", qint_from_int(0));
 507    g_assert_cmpint(qdict_array_entries(dict, ""), ==, 3);
 508
 509    QDECREF(dict);
 510}
 511
 512static void qdict_join_test(void)
 513{
 514    QDict *dict1, *dict2;
 515    bool overwrite = false;
 516    int i;
 517
 518    dict1 = qdict_new();
 519    dict2 = qdict_new();
 520
 521    /* Test everything once without overwrite and once with */
 522    do
 523    {
 524        /* Test empty dicts */
 525        qdict_join(dict1, dict2, overwrite);
 526
 527        g_assert(qdict_size(dict1) == 0);
 528        g_assert(qdict_size(dict2) == 0);
 529
 530        /* First iteration: Test movement */
 531        /* Second iteration: Test empty source and non-empty destination */
 532        qdict_put(dict2, "foo", qint_from_int(42));
 533
 534        for (i = 0; i < 2; i++) {
 535            qdict_join(dict1, dict2, overwrite);
 536
 537            g_assert(qdict_size(dict1) == 1);
 538            g_assert(qdict_size(dict2) == 0);
 539
 540            g_assert(qdict_get_int(dict1, "foo") == 42);
 541        }
 542
 543        /* Test non-empty source and destination without conflict */
 544        qdict_put(dict2, "bar", qint_from_int(23));
 545
 546        qdict_join(dict1, dict2, overwrite);
 547
 548        g_assert(qdict_size(dict1) == 2);
 549        g_assert(qdict_size(dict2) == 0);
 550
 551        g_assert(qdict_get_int(dict1, "foo") == 42);
 552        g_assert(qdict_get_int(dict1, "bar") == 23);
 553
 554        /* Test conflict */
 555        qdict_put(dict2, "foo", qint_from_int(84));
 556
 557        qdict_join(dict1, dict2, overwrite);
 558
 559        g_assert(qdict_size(dict1) == 2);
 560        g_assert(qdict_size(dict2) == !overwrite);
 561
 562        g_assert(qdict_get_int(dict1, "foo") == overwrite ? 84 : 42);
 563        g_assert(qdict_get_int(dict1, "bar") == 23);
 564
 565        if (!overwrite) {
 566            g_assert(qdict_get_int(dict2, "foo") == 84);
 567        }
 568
 569        /* Check the references */
 570        g_assert(qdict_get(dict1, "foo")->refcnt == 1);
 571        g_assert(qdict_get(dict1, "bar")->refcnt == 1);
 572
 573        if (!overwrite) {
 574            g_assert(qdict_get(dict2, "foo")->refcnt == 1);
 575        }
 576
 577        /* Clean up */
 578        qdict_del(dict1, "foo");
 579        qdict_del(dict1, "bar");
 580
 581        if (!overwrite) {
 582            qdict_del(dict2, "foo");
 583        }
 584    }
 585    while (overwrite ^= true);
 586
 587    QDECREF(dict1);
 588    QDECREF(dict2);
 589}
 590
 591static void qdict_crumple_test_recursive(void)
 592{
 593    QDict *src, *dst, *rule, *vnc, *acl, *listen;
 594    QObject *child, *res;
 595    QList *rules;
 596
 597    src = qdict_new();
 598    qdict_put(src, "vnc.listen.addr", qstring_from_str("127.0.0.1"));
 599    qdict_put(src, "vnc.listen.port", qstring_from_str("5901"));
 600    qdict_put(src, "vnc.acl.rules.0.match", qstring_from_str("fred"));
 601    qdict_put(src, "vnc.acl.rules.0.policy", qstring_from_str("allow"));
 602    qdict_put(src, "vnc.acl.rules.1.match", qstring_from_str("bob"));
 603    qdict_put(src, "vnc.acl.rules.1.policy", qstring_from_str("deny"));
 604    qdict_put(src, "vnc.acl.default", qstring_from_str("deny"));
 605    qdict_put(src, "vnc.acl..name", qstring_from_str("acl0"));
 606    qdict_put(src, "vnc.acl.rule..name", qstring_from_str("acl0"));
 607
 608    res = qdict_crumple(src, &error_abort);
 609
 610    g_assert_cmpint(qobject_type(res), ==, QTYPE_QDICT);
 611
 612    dst = qobject_to_qdict(res);
 613
 614    g_assert_cmpint(qdict_size(dst), ==, 1);
 615
 616    child = qdict_get(dst, "vnc");
 617    g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
 618    vnc = qobject_to_qdict(child);
 619
 620    child = qdict_get(vnc, "listen");
 621    g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
 622    listen = qobject_to_qdict(child);
 623    g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr"));
 624    g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port"));
 625
 626    child = qdict_get(vnc, "acl");
 627    g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
 628    acl = qobject_to_qdict(child);
 629
 630    child = qdict_get(acl, "rules");
 631    g_assert_cmpint(qobject_type(child), ==, QTYPE_QLIST);
 632    rules = qobject_to_qlist(child);
 633    g_assert_cmpint(qlist_size(rules), ==, 2);
 634
 635    rule = qobject_to_qdict(qlist_pop(rules));
 636    g_assert_cmpint(qdict_size(rule), ==, 2);
 637    g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match"));
 638    g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy"));
 639    QDECREF(rule);
 640
 641    rule = qobject_to_qdict(qlist_pop(rules));
 642    g_assert_cmpint(qdict_size(rule), ==, 2);
 643    g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match"));
 644    g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy"));
 645    QDECREF(rule);
 646
 647    /* With recursive crumpling, we should see all names unescaped */
 648    g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name"));
 649    child = qdict_get(vnc, "acl");
 650    g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
 651    acl = qdict_get_qdict(vnc, "acl");
 652    g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name"));
 653
 654    QDECREF(src);
 655    QDECREF(dst);
 656}
 657
 658static void qdict_crumple_test_empty(void)
 659{
 660    QDict *src, *dst;
 661
 662    src = qdict_new();
 663
 664    dst = (QDict *)qdict_crumple(src, &error_abort);
 665
 666    g_assert_cmpint(qdict_size(dst), ==, 0);
 667
 668    QDECREF(src);
 669    QDECREF(dst);
 670}
 671
 672static void qdict_crumple_test_bad_inputs(void)
 673{
 674    QDict *src;
 675    Error *error = NULL;
 676
 677    src = qdict_new();
 678    /* rule.0 can't be both a string and a dict */
 679    qdict_put(src, "rule.0", qstring_from_str("fred"));
 680    qdict_put(src, "rule.0.policy", qstring_from_str("allow"));
 681
 682    g_assert(qdict_crumple(src, &error) == NULL);
 683    g_assert(error != NULL);
 684    error_free(error);
 685    error = NULL;
 686    QDECREF(src);
 687
 688    src = qdict_new();
 689    /* rule can't be both a list and a dict */
 690    qdict_put(src, "rule.0", qstring_from_str("fred"));
 691    qdict_put(src, "rule.a", qstring_from_str("allow"));
 692
 693    g_assert(qdict_crumple(src, &error) == NULL);
 694    g_assert(error != NULL);
 695    error_free(error);
 696    error = NULL;
 697    QDECREF(src);
 698
 699    src = qdict_new();
 700    /* The input should be flat, ie no dicts or lists */
 701    qdict_put(src, "rule.a", qdict_new());
 702    qdict_put(src, "rule.b", qstring_from_str("allow"));
 703
 704    g_assert(qdict_crumple(src, &error) == NULL);
 705    g_assert(error != NULL);
 706    error_free(error);
 707    error = NULL;
 708    QDECREF(src);
 709
 710    src = qdict_new();
 711    /* List indexes must not have gaps */
 712    qdict_put(src, "rule.0", qstring_from_str("deny"));
 713    qdict_put(src, "rule.3", qstring_from_str("allow"));
 714
 715    g_assert(qdict_crumple(src, &error) == NULL);
 716    g_assert(error != NULL);
 717    error_free(error);
 718    error = NULL;
 719    QDECREF(src);
 720
 721    src = qdict_new();
 722    /* List indexes must be in %zu format */
 723    qdict_put(src, "rule.0", qstring_from_str("deny"));
 724    qdict_put(src, "rule.+1", qstring_from_str("allow"));
 725
 726    g_assert(qdict_crumple(src, &error) == NULL);
 727    g_assert(error != NULL);
 728    error_free(error);
 729    error = NULL;
 730    QDECREF(src);
 731}
 732
 733/*
 734 * Errors test-cases
 735 */
 736
 737static void qdict_put_exists_test(void)
 738{
 739    int value;
 740    const char *key = "exists";
 741    QDict *tests_dict = qdict_new();
 742
 743    qdict_put(tests_dict, key, qint_from_int(1));
 744    qdict_put(tests_dict, key, qint_from_int(2));
 745
 746    value = qdict_get_int(tests_dict, key);
 747    g_assert(value == 2);
 748
 749    g_assert(qdict_size(tests_dict) == 1);
 750
 751    QDECREF(tests_dict);
 752}
 753
 754static void qdict_get_not_exists_test(void)
 755{
 756    QDict *tests_dict = qdict_new();
 757    g_assert(qdict_get(tests_dict, "foo") == NULL);
 758
 759    QDECREF(tests_dict);
 760}
 761
 762/*
 763 * Stress test-case
 764 *
 765 * This is a lot big for a unit-test, but there is no other place
 766 * to have it.
 767 */
 768
 769static void remove_dots(char *string)
 770{
 771    char *p = strchr(string, ':');
 772    if (p)
 773        *p = '\0';
 774}
 775
 776static QString *read_line(FILE *file, char *key)
 777{
 778    char value[128];
 779
 780    if (fscanf(file, "%127s%127s", key, value) == EOF) {
 781        return NULL;
 782    }
 783    remove_dots(key);
 784    return qstring_from_str(value);
 785}
 786
 787#define reset_file(file)    fseek(file, 0L, SEEK_SET)
 788
 789static void qdict_stress_test(void)
 790{
 791    size_t lines;
 792    char key[128];
 793    FILE *test_file;
 794    QDict *qdict;
 795    QString *value;
 796    const char *test_file_path = "qdict-test-data.txt";
 797
 798    test_file = fopen(test_file_path, "r");
 799    g_assert(test_file != NULL);
 800
 801    // Create the dict
 802    qdict = qdict_new();
 803    g_assert(qdict != NULL);
 804
 805    // Add everything from the test file
 806    for (lines = 0;; lines++) {
 807        value = read_line(test_file, key);
 808        if (!value)
 809            break;
 810
 811        qdict_put(qdict, key, value);
 812    }
 813    g_assert(qdict_size(qdict) == lines);
 814
 815    // Check if everything is really in there
 816    reset_file(test_file);
 817    for (;;) {
 818        const char *str1, *str2;
 819
 820        value = read_line(test_file, key);
 821        if (!value)
 822            break;
 823
 824        str1 = qstring_get_str(value);
 825
 826        str2 = qdict_get_str(qdict, key);
 827        g_assert(str2 != NULL);
 828
 829        g_assert(strcmp(str1, str2) == 0);
 830
 831        QDECREF(value);
 832    }
 833
 834    // Delete everything
 835    reset_file(test_file);
 836    for (;;) {
 837        value = read_line(test_file, key);
 838        if (!value)
 839            break;
 840
 841        qdict_del(qdict, key);
 842        QDECREF(value);
 843
 844        g_assert(qdict_haskey(qdict, key) == 0);
 845    }
 846    fclose(test_file);
 847
 848    g_assert(qdict_size(qdict) == 0);
 849    QDECREF(qdict);
 850}
 851
 852int main(int argc, char **argv)
 853{
 854    g_test_init(&argc, &argv, NULL);
 855
 856    g_test_add_func("/public/new", qdict_new_test);
 857    g_test_add_func("/public/put_obj", qdict_put_obj_test);
 858    g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
 859
 860    /* Continue, but now with fixtures */
 861    g_test_add_func("/public/get", qdict_get_test);
 862    g_test_add_func("/public/get_int", qdict_get_int_test);
 863    g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
 864    g_test_add_func("/public/get_str", qdict_get_str_test);
 865    g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
 866    g_test_add_func("/public/defaults", qdict_defaults_test);
 867    g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
 868    g_test_add_func("/public/haskey", qdict_haskey_test);
 869    g_test_add_func("/public/del", qdict_del_test);
 870    g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
 871    g_test_add_func("/public/iterapi", qdict_iterapi_test);
 872    g_test_add_func("/public/flatten", qdict_flatten_test);
 873    g_test_add_func("/public/array_split", qdict_array_split_test);
 874    g_test_add_func("/public/array_entries", qdict_array_entries_test);
 875    g_test_add_func("/public/join", qdict_join_test);
 876
 877    g_test_add_func("/errors/put_exists", qdict_put_exists_test);
 878    g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
 879
 880    g_test_add_func("/public/crumple/recursive",
 881                    qdict_crumple_test_recursive);
 882    g_test_add_func("/public/crumple/empty",
 883                    qdict_crumple_test_empty);
 884    g_test_add_func("/public/crumple/bad_inputs",
 885                    qdict_crumple_test_bad_inputs);
 886
 887    /* The Big one */
 888    if (g_test_slow()) {
 889        g_test_add_func("/stress/test", qdict_stress_test);
 890    }
 891
 892    return g_test_run();
 893}
 894