qemu/tests/check-qjson.c
<<
>>
Prefs
   1/*
   2 * Copyright IBM, Corp. 2009
   3 * Copyright (c) 2013, 2015 Red Hat Inc.
   4 *
   5 * Authors:
   6 *  Anthony Liguori   <aliguori@us.ibm.com>
   7 *  Markus Armbruster <armbru@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 */
  13#include "qemu/osdep.h"
  14
  15#include "qapi/qmp/types.h"
  16#include "qapi/qmp/qjson.h"
  17#include "qemu-common.h"
  18
  19static void escaped_string(void)
  20{
  21    int i;
  22    struct {
  23        const char *encoded;
  24        const char *decoded;
  25        int skip;
  26    } test_cases[] = {
  27        { "\"\\b\"", "\b" },
  28        { "\"\\f\"", "\f" },
  29        { "\"\\n\"", "\n" },
  30        { "\"\\r\"", "\r" },
  31        { "\"\\t\"", "\t" },
  32        { "\"/\"", "/" },
  33        { "\"\\/\"", "/", .skip = 1 },
  34        { "\"\\\\\"", "\\" },
  35        { "\"\\\"\"", "\"" },
  36        { "\"hello world \\\"embedded string\\\"\"",
  37          "hello world \"embedded string\"" },
  38        { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
  39        { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
  40        { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
  41        { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
  42        { "'\\b'", "\b", .skip = 1 },
  43        { "'\\f'", "\f", .skip = 1 },
  44        { "'\\n'", "\n", .skip = 1 },
  45        { "'\\r'", "\r", .skip = 1 },
  46        { "'\\t'", "\t", .skip = 1 },
  47        { "'\\/'", "/", .skip = 1 },
  48        { "'\\\\'", "\\", .skip = 1 },
  49        {}
  50    };
  51
  52    for (i = 0; test_cases[i].encoded; i++) {
  53        QObject *obj;
  54        QString *str;
  55
  56        obj = qobject_from_json(test_cases[i].encoded);
  57
  58        g_assert(obj != NULL);
  59        g_assert(qobject_type(obj) == QTYPE_QSTRING);
  60        
  61        str = qobject_to_qstring(obj);
  62        g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
  63
  64        if (test_cases[i].skip == 0) {
  65            str = qobject_to_json(obj);
  66            g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
  67            qobject_decref(obj);
  68        }
  69
  70        QDECREF(str);
  71    }
  72}
  73
  74static void simple_string(void)
  75{
  76    int i;
  77    struct {
  78        const char *encoded;
  79        const char *decoded;
  80    } test_cases[] = {
  81        { "\"hello world\"", "hello world" },
  82        { "\"the quick brown fox jumped over the fence\"",
  83          "the quick brown fox jumped over the fence" },
  84        {}
  85    };
  86
  87    for (i = 0; test_cases[i].encoded; i++) {
  88        QObject *obj;
  89        QString *str;
  90
  91        obj = qobject_from_json(test_cases[i].encoded);
  92
  93        g_assert(obj != NULL);
  94        g_assert(qobject_type(obj) == QTYPE_QSTRING);
  95        
  96        str = qobject_to_qstring(obj);
  97        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
  98
  99        str = qobject_to_json(obj);
 100        g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
 101
 102        qobject_decref(obj);
 103        
 104        QDECREF(str);
 105    }
 106}
 107
 108static void single_quote_string(void)
 109{
 110    int i;
 111    struct {
 112        const char *encoded;
 113        const char *decoded;
 114    } test_cases[] = {
 115        { "'hello world'", "hello world" },
 116        { "'the quick brown fox \\' jumped over the fence'",
 117          "the quick brown fox ' jumped over the fence" },
 118        {}
 119    };
 120
 121    for (i = 0; test_cases[i].encoded; i++) {
 122        QObject *obj;
 123        QString *str;
 124
 125        obj = qobject_from_json(test_cases[i].encoded);
 126
 127        g_assert(obj != NULL);
 128        g_assert(qobject_type(obj) == QTYPE_QSTRING);
 129        
 130        str = qobject_to_qstring(obj);
 131        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 132
 133        QDECREF(str);
 134    }
 135}
 136
 137static void utf8_string(void)
 138{
 139    /*
 140     * FIXME Current behavior for invalid UTF-8 sequences is
 141     * incorrect.  This test expects current, incorrect results.
 142     * They're all marked "bug:" below, and are to be replaced by
 143     * correct ones as the bugs get fixed.
 144     *
 145     * The JSON parser rejects some invalid sequences, but accepts
 146     * others without correcting the problem.
 147     *
 148     * We should either reject all invalid sequences, or minimize
 149     * overlong sequences and replace all other invalid sequences by a
 150     * suitable replacement character.  A common choice for
 151     * replacement is U+FFFD.
 152     *
 153     * Problem: we can't easily deal with embedded U+0000.  Parsing
 154     * the JSON string "this \\u0000" is fun" yields "this \0 is fun",
 155     * which gets misinterpreted as NUL-terminated "this ".  We should
 156     * consider using overlong encoding \xC0\x80 for U+0000 ("modified
 157     * UTF-8").
 158     *
 159     * Most test cases are scraped from Markus Kuhn's UTF-8 decoder
 160     * capability and stress test at
 161     * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
 162     */
 163    static const struct {
 164        const char *json_in;
 165        const char *utf8_out;
 166        const char *json_out;   /* defaults to @json_in */
 167        const char *utf8_in;    /* defaults to @utf8_out */
 168    } test_cases[] = {
 169        /*
 170         * Bug markers used here:
 171         * - bug: not corrected
 172         *   JSON parser fails to correct invalid sequence(s)
 173         * - bug: rejected
 174         *   JSON parser rejects invalid sequence(s)
 175         *   We may choose to define this as feature
 176         * - bug: want "..."
 177         *   JSON parser produces incorrect result, this is the
 178         *   correct one, assuming replacement character U+FFFF
 179         *   We may choose to reject instead of replace
 180         */
 181
 182        /* 1  Some correct UTF-8 text */
 183        {
 184            /* a bit of German */
 185            "\"Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
 186            " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.\"",
 187            "Falsches \xC3\x9C" "ben von Xylophonmusik qu\xC3\xA4lt"
 188            " jeden gr\xC3\xB6\xC3\x9F" "eren Zwerg.",
 189            "\"Falsches \\u00DCben von Xylophonmusik qu\\u00E4lt"
 190            " jeden gr\\u00F6\\u00DFeren Zwerg.\"",
 191        },
 192        {
 193            /* a bit of Greek */
 194            "\"\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5\"",
 195            "\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5",
 196            "\"\\u03BA\\u1F79\\u03C3\\u03BC\\u03B5\"",
 197        },
 198        /* 2  Boundary condition test cases */
 199        /* 2.1  First possible sequence of a certain length */
 200        /* 2.1.1  1 byte U+0000 */
 201        {
 202            "\"\\u0000\"",
 203            "",                 /* bug: want overlong "\xC0\x80" */
 204            "\"\\u0000\"",
 205            "\xC0\x80",
 206        },
 207        /* 2.1.2  2 bytes U+0080 */
 208        {
 209            "\"\xC2\x80\"",
 210            "\xC2\x80",
 211            "\"\\u0080\"",
 212        },
 213        /* 2.1.3  3 bytes U+0800 */
 214        {
 215            "\"\xE0\xA0\x80\"",
 216            "\xE0\xA0\x80",
 217            "\"\\u0800\"",
 218        },
 219        /* 2.1.4  4 bytes U+10000 */
 220        {
 221            "\"\xF0\x90\x80\x80\"",
 222            "\xF0\x90\x80\x80",
 223            "\"\\uD800\\uDC00\"",
 224        },
 225        /* 2.1.5  5 bytes U+200000 */
 226        {
 227            "\"\xF8\x88\x80\x80\x80\"",
 228            NULL,               /* bug: rejected */
 229            "\"\\uFFFD\"",
 230            "\xF8\x88\x80\x80\x80",
 231        },
 232        /* 2.1.6  6 bytes U+4000000 */
 233        {
 234            "\"\xFC\x84\x80\x80\x80\x80\"",
 235            NULL,               /* bug: rejected */
 236            "\"\\uFFFD\"",
 237            "\xFC\x84\x80\x80\x80\x80",
 238        },
 239        /* 2.2  Last possible sequence of a certain length */
 240        /* 2.2.1  1 byte U+007F */
 241        {
 242            "\"\x7F\"",
 243            "\x7F",
 244            "\"\\u007F\"",
 245        },
 246        /* 2.2.2  2 bytes U+07FF */
 247        {
 248            "\"\xDF\xBF\"",
 249            "\xDF\xBF",
 250            "\"\\u07FF\"",
 251        },
 252        /*
 253         * 2.2.3  3 bytes U+FFFC
 254         * The last possible sequence is actually U+FFFF.  But that's
 255         * a noncharacter, and already covered by its own test case
 256         * under 5.3.  Same for U+FFFE.  U+FFFD is the last character
 257         * in the BMP, and covered under 2.3.  Because of U+FFFD's
 258         * special role as replacement character, it's worth testing
 259         * U+FFFC here.
 260         */
 261        {
 262            "\"\xEF\xBF\xBC\"",
 263            "\xEF\xBF\xBC",
 264            "\"\\uFFFC\"",
 265        },
 266        /* 2.2.4  4 bytes U+1FFFFF */
 267        {
 268            "\"\xF7\xBF\xBF\xBF\"",
 269            NULL,               /* bug: rejected */
 270            "\"\\uFFFD\"",
 271            "\xF7\xBF\xBF\xBF",
 272        },
 273        /* 2.2.5  5 bytes U+3FFFFFF */
 274        {
 275            "\"\xFB\xBF\xBF\xBF\xBF\"",
 276            NULL,               /* bug: rejected */
 277            "\"\\uFFFD\"",
 278            "\xFB\xBF\xBF\xBF\xBF",
 279        },
 280        /* 2.2.6  6 bytes U+7FFFFFFF */
 281        {
 282            "\"\xFD\xBF\xBF\xBF\xBF\xBF\"",
 283            NULL,               /* bug: rejected */
 284            "\"\\uFFFD\"",
 285            "\xFD\xBF\xBF\xBF\xBF\xBF",
 286        },
 287        /* 2.3  Other boundary conditions */
 288        {
 289            /* last one before surrogate range: U+D7FF */
 290            "\"\xED\x9F\xBF\"",
 291            "\xED\x9F\xBF",
 292            "\"\\uD7FF\"",
 293        },
 294        {
 295            /* first one after surrogate range: U+E000 */
 296            "\"\xEE\x80\x80\"",
 297            "\xEE\x80\x80",
 298            "\"\\uE000\"",
 299        },
 300        {
 301            /* last one in BMP: U+FFFD */
 302            "\"\xEF\xBF\xBD\"",
 303            "\xEF\xBF\xBD",
 304            "\"\\uFFFD\"",
 305        },
 306        {
 307            /* last one in last plane: U+10FFFD */
 308            "\"\xF4\x8F\xBF\xBD\"",
 309            "\xF4\x8F\xBF\xBD",
 310            "\"\\uDBFF\\uDFFD\""
 311        },
 312        {
 313            /* first one beyond Unicode range: U+110000 */
 314            "\"\xF4\x90\x80\x80\"",
 315            "\xF4\x90\x80\x80",
 316            "\"\\uFFFD\"",
 317        },
 318        /* 3  Malformed sequences */
 319        /* 3.1  Unexpected continuation bytes */
 320        /* 3.1.1  First continuation byte */
 321        {
 322            "\"\x80\"",
 323            "\x80",             /* bug: not corrected */
 324            "\"\\uFFFD\"",
 325        },
 326        /* 3.1.2  Last continuation byte */
 327        {
 328            "\"\xBF\"",
 329            "\xBF",             /* bug: not corrected */
 330            "\"\\uFFFD\"",
 331        },
 332        /* 3.1.3  2 continuation bytes */
 333        {
 334            "\"\x80\xBF\"",
 335            "\x80\xBF",         /* bug: not corrected */
 336            "\"\\uFFFD\\uFFFD\"",
 337        },
 338        /* 3.1.4  3 continuation bytes */
 339        {
 340            "\"\x80\xBF\x80\"",
 341            "\x80\xBF\x80",     /* bug: not corrected */
 342            "\"\\uFFFD\\uFFFD\\uFFFD\"",
 343        },
 344        /* 3.1.5  4 continuation bytes */
 345        {
 346            "\"\x80\xBF\x80\xBF\"",
 347            "\x80\xBF\x80\xBF", /* bug: not corrected */
 348            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 349        },
 350        /* 3.1.6  5 continuation bytes */
 351        {
 352            "\"\x80\xBF\x80\xBF\x80\"",
 353            "\x80\xBF\x80\xBF\x80", /* bug: not corrected */
 354            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 355        },
 356        /* 3.1.7  6 continuation bytes */
 357        {
 358            "\"\x80\xBF\x80\xBF\x80\xBF\"",
 359            "\x80\xBF\x80\xBF\x80\xBF", /* bug: not corrected */
 360            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 361        },
 362        /* 3.1.8  7 continuation bytes */
 363        {
 364            "\"\x80\xBF\x80\xBF\x80\xBF\x80\"",
 365            "\x80\xBF\x80\xBF\x80\xBF\x80", /* bug: not corrected */
 366            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 367        },
 368        /* 3.1.9  Sequence of all 64 possible continuation bytes */
 369        {
 370            "\"\x80\x81\x82\x83\x84\x85\x86\x87"
 371            "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
 372            "\x90\x91\x92\x93\x94\x95\x96\x97"
 373            "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
 374            "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
 375            "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
 376            "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
 377            "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\"",
 378             /* bug: not corrected */
 379            "\x80\x81\x82\x83\x84\x85\x86\x87"
 380            "\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F"
 381            "\x90\x91\x92\x93\x94\x95\x96\x97"
 382            "\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F"
 383            "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7"
 384            "\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF"
 385            "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7"
 386            "\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF",
 387            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 388            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 389            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 390            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 391            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 392            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 393            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 394            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\""
 395        },
 396        /* 3.2  Lonely start characters */
 397        /* 3.2.1  All 32 first bytes of 2-byte sequences, followed by space */
 398        {
 399            "\"\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
 400            "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
 401            "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
 402            "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF \"",
 403            NULL,               /* bug: rejected */
 404            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
 405            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
 406            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
 407            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
 408            "\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 "
 409            "\xC8 \xC9 \xCA \xCB \xCC \xCD \xCE \xCF "
 410            "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 "
 411            "\xD8 \xD9 \xDA \xDB \xDC \xDD \xDE \xDF ",
 412        },
 413        /* 3.2.2  All 16 first bytes of 3-byte sequences, followed by space */
 414        {
 415            "\"\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
 416            "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF \"",
 417            /* bug: not corrected */
 418            "\xE0 \xE1 \xE2 \xE3 \xE4 \xE5 \xE6 \xE7 "
 419            "\xE8 \xE9 \xEA \xEB \xEC \xED \xEE \xEF ",
 420            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD "
 421            "\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
 422        },
 423        /* 3.2.3  All 8 first bytes of 4-byte sequences, followed by space */
 424        {
 425            "\"\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 \"",
 426            NULL,               /* bug: rejected */
 427            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
 428            "\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 ",
 429        },
 430        /* 3.2.4  All 4 first bytes of 5-byte sequences, followed by space */
 431        {
 432            "\"\xF8 \xF9 \xFA \xFB \"",
 433            NULL,               /* bug: rejected */
 434            "\"\\uFFFD \\uFFFD \\uFFFD \\uFFFD \"",
 435            "\xF8 \xF9 \xFA \xFB ",
 436        },
 437        /* 3.2.5  All 2 first bytes of 6-byte sequences, followed by space */
 438        {
 439            "\"\xFC \xFD \"",
 440            NULL,               /* bug: rejected */
 441            "\"\\uFFFD \\uFFFD \"",
 442            "\xFC \xFD ",
 443        },
 444        /* 3.3  Sequences with last continuation byte missing */
 445        /* 3.3.1  2-byte sequence with last byte missing (U+0000) */
 446        {
 447            "\"\xC0\"",
 448            NULL,               /* bug: rejected */
 449            "\"\\uFFFD\"",
 450            "\xC0",
 451        },
 452        /* 3.3.2  3-byte sequence with last byte missing (U+0000) */
 453        {
 454            "\"\xE0\x80\"",
 455            "\xE0\x80",           /* bug: not corrected */
 456            "\"\\uFFFD\"",
 457        },
 458        /* 3.3.3  4-byte sequence with last byte missing (U+0000) */
 459        {
 460            "\"\xF0\x80\x80\"",
 461            "\xF0\x80\x80",     /* bug: not corrected */
 462            "\"\\uFFFD\"",
 463        },
 464        /* 3.3.4  5-byte sequence with last byte missing (U+0000) */
 465        {
 466            "\"\xF8\x80\x80\x80\"",
 467            NULL,                   /* bug: rejected */
 468            "\"\\uFFFD\"",
 469            "\xF8\x80\x80\x80",
 470        },
 471        /* 3.3.5  6-byte sequence with last byte missing (U+0000) */
 472        {
 473            "\"\xFC\x80\x80\x80\x80\"",
 474            NULL,                        /* bug: rejected */
 475            "\"\\uFFFD\"",
 476            "\xFC\x80\x80\x80\x80",
 477        },
 478        /* 3.3.6  2-byte sequence with last byte missing (U+07FF) */
 479        {
 480            "\"\xDF\"",
 481            "\xDF",             /* bug: not corrected */
 482            "\"\\uFFFD\"",
 483        },
 484        /* 3.3.7  3-byte sequence with last byte missing (U+FFFF) */
 485        {
 486            "\"\xEF\xBF\"",
 487            "\xEF\xBF",           /* bug: not corrected */
 488            "\"\\uFFFD\"",
 489        },
 490        /* 3.3.8  4-byte sequence with last byte missing (U+1FFFFF) */
 491        {
 492            "\"\xF7\xBF\xBF\"",
 493            NULL,               /* bug: rejected */
 494            "\"\\uFFFD\"",
 495            "\xF7\xBF\xBF",
 496        },
 497        /* 3.3.9  5-byte sequence with last byte missing (U+3FFFFFF) */
 498        {
 499            "\"\xFB\xBF\xBF\xBF\"",
 500            NULL,                 /* bug: rejected */
 501            "\"\\uFFFD\"",
 502            "\xFB\xBF\xBF\xBF",
 503        },
 504        /* 3.3.10  6-byte sequence with last byte missing (U+7FFFFFFF) */
 505        {
 506            "\"\xFD\xBF\xBF\xBF\xBF\"",
 507            NULL,                        /* bug: rejected */
 508            "\"\\uFFFD\"",
 509            "\xFD\xBF\xBF\xBF\xBF",
 510        },
 511        /* 3.4  Concatenation of incomplete sequences */
 512        {
 513            "\"\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
 514            "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF\"",
 515            NULL,               /* bug: rejected */
 516            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 517            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 518            "\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80"
 519            "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF",
 520        },
 521        /* 3.5  Impossible bytes */
 522        {
 523            "\"\xFE\"",
 524            NULL,               /* bug: rejected */
 525            "\"\\uFFFD\"",
 526            "\xFE",
 527        },
 528        {
 529            "\"\xFF\"",
 530            NULL,               /* bug: rejected */
 531            "\"\\uFFFD\"",
 532            "\xFF",
 533        },
 534        {
 535            "\"\xFE\xFE\xFF\xFF\"",
 536            NULL,                 /* bug: rejected */
 537            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 538            "\xFE\xFE\xFF\xFF",
 539        },
 540        /* 4  Overlong sequences */
 541        /* 4.1  Overlong '/' */
 542        {
 543            "\"\xC0\xAF\"",
 544            NULL,               /* bug: rejected */
 545            "\"\\uFFFD\"",
 546            "\xC0\xAF",
 547        },
 548        {
 549            "\"\xE0\x80\xAF\"",
 550            "\xE0\x80\xAF",     /* bug: not corrected */
 551            "\"\\uFFFD\"",
 552        },
 553        {
 554            "\"\xF0\x80\x80\xAF\"",
 555            "\xF0\x80\x80\xAF",  /* bug: not corrected */
 556            "\"\\uFFFD\"",
 557        },
 558        {
 559            "\"\xF8\x80\x80\x80\xAF\"",
 560            NULL,                        /* bug: rejected */
 561            "\"\\uFFFD\"",
 562            "\xF8\x80\x80\x80\xAF",
 563        },
 564        {
 565            "\"\xFC\x80\x80\x80\x80\xAF\"",
 566            NULL,                               /* bug: rejected */
 567            "\"\\uFFFD\"",
 568            "\xFC\x80\x80\x80\x80\xAF",
 569        },
 570        /*
 571         * 4.2  Maximum overlong sequences
 572         * Highest Unicode value that is still resulting in an
 573         * overlong sequence if represented with the given number of
 574         * bytes.  This is a boundary test for safe UTF-8 decoders.
 575         */
 576        {
 577            /* \U+007F */
 578            "\"\xC1\xBF\"",
 579            NULL,               /* bug: rejected */
 580            "\"\\uFFFD\"",
 581            "\xC1\xBF",
 582        },
 583        {
 584            /* \U+07FF */
 585            "\"\xE0\x9F\xBF\"",
 586            "\xE0\x9F\xBF",     /* bug: not corrected */
 587            "\"\\uFFFD\"",
 588        },
 589        {
 590            /*
 591             * \U+FFFC
 592             * The actual maximum would be U+FFFF, but that's a
 593             * noncharacter.  Testing U+FFFC seems more useful.  See
 594             * also 2.2.3
 595             */
 596            "\"\xF0\x8F\xBF\xBC\"",
 597            "\xF0\x8F\xBF\xBC",   /* bug: not corrected */
 598            "\"\\uFFFD\"",
 599        },
 600        {
 601            /* \U+1FFFFF */
 602            "\"\xF8\x87\xBF\xBF\xBF\"",
 603            NULL,                        /* bug: rejected */
 604            "\"\\uFFFD\"",
 605            "\xF8\x87\xBF\xBF\xBF",
 606        },
 607        {
 608            /* \U+3FFFFFF */
 609            "\"\xFC\x83\xBF\xBF\xBF\xBF\"",
 610            NULL,                               /* bug: rejected */
 611            "\"\\uFFFD\"",
 612            "\xFC\x83\xBF\xBF\xBF\xBF",
 613        },
 614        /* 4.3  Overlong representation of the NUL character */
 615        {
 616            /* \U+0000 */
 617            "\"\xC0\x80\"",
 618            NULL,               /* bug: rejected */
 619            "\"\\u0000\"",
 620            "\xC0\x80",
 621        },
 622        {
 623            /* \U+0000 */
 624            "\"\xE0\x80\x80\"",
 625            "\xE0\x80\x80",     /* bug: not corrected */
 626            "\"\\uFFFD\"",
 627        },
 628        {
 629            /* \U+0000 */
 630            "\"\xF0\x80\x80\x80\"",
 631            "\xF0\x80\x80\x80",   /* bug: not corrected */
 632            "\"\\uFFFD\"",
 633        },
 634        {
 635            /* \U+0000 */
 636            "\"\xF8\x80\x80\x80\x80\"",
 637            NULL,                        /* bug: rejected */
 638            "\"\\uFFFD\"",
 639            "\xF8\x80\x80\x80\x80",
 640        },
 641        {
 642            /* \U+0000 */
 643            "\"\xFC\x80\x80\x80\x80\x80\"",
 644            NULL,                               /* bug: rejected */
 645            "\"\\uFFFD\"",
 646            "\xFC\x80\x80\x80\x80\x80",
 647        },
 648        /* 5  Illegal code positions */
 649        /* 5.1  Single UTF-16 surrogates */
 650        {
 651            /* \U+D800 */
 652            "\"\xED\xA0\x80\"",
 653            "\xED\xA0\x80",     /* bug: not corrected */
 654            "\"\\uFFFD\"",
 655        },
 656        {
 657            /* \U+DB7F */
 658            "\"\xED\xAD\xBF\"",
 659            "\xED\xAD\xBF",     /* bug: not corrected */
 660            "\"\\uFFFD\"",
 661        },
 662        {
 663            /* \U+DB80 */
 664            "\"\xED\xAE\x80\"",
 665            "\xED\xAE\x80",     /* bug: not corrected */
 666            "\"\\uFFFD\"",
 667        },
 668        {
 669            /* \U+DBFF */
 670            "\"\xED\xAF\xBF\"",
 671            "\xED\xAF\xBF",     /* bug: not corrected */
 672            "\"\\uFFFD\"",
 673        },
 674        {
 675            /* \U+DC00 */
 676            "\"\xED\xB0\x80\"",
 677            "\xED\xB0\x80",     /* bug: not corrected */
 678            "\"\\uFFFD\"",
 679        },
 680        {
 681            /* \U+DF80 */
 682            "\"\xED\xBE\x80\"",
 683            "\xED\xBE\x80",     /* bug: not corrected */
 684            "\"\\uFFFD\"",
 685        },
 686        {
 687            /* \U+DFFF */
 688            "\"\xED\xBF\xBF\"",
 689            "\xED\xBF\xBF",     /* bug: not corrected */
 690            "\"\\uFFFD\"",
 691        },
 692        /* 5.2  Paired UTF-16 surrogates */
 693        {
 694            /* \U+D800\U+DC00 */
 695            "\"\xED\xA0\x80\xED\xB0\x80\"",
 696            "\xED\xA0\x80\xED\xB0\x80", /* bug: not corrected */
 697            "\"\\uFFFD\\uFFFD\"",
 698        },
 699        {
 700            /* \U+D800\U+DFFF */
 701            "\"\xED\xA0\x80\xED\xBF\xBF\"",
 702            "\xED\xA0\x80\xED\xBF\xBF", /* bug: not corrected */
 703            "\"\\uFFFD\\uFFFD\"",
 704        },
 705        {
 706            /* \U+DB7F\U+DC00 */
 707            "\"\xED\xAD\xBF\xED\xB0\x80\"",
 708            "\xED\xAD\xBF\xED\xB0\x80", /* bug: not corrected */
 709            "\"\\uFFFD\\uFFFD\"",
 710        },
 711        {
 712            /* \U+DB7F\U+DFFF */
 713            "\"\xED\xAD\xBF\xED\xBF\xBF\"",
 714            "\xED\xAD\xBF\xED\xBF\xBF", /* bug: not corrected */
 715            "\"\\uFFFD\\uFFFD\"",
 716        },
 717        {
 718            /* \U+DB80\U+DC00 */
 719            "\"\xED\xAE\x80\xED\xB0\x80\"",
 720            "\xED\xAE\x80\xED\xB0\x80", /* bug: not corrected */
 721            "\"\\uFFFD\\uFFFD\"",
 722        },
 723        {
 724            /* \U+DB80\U+DFFF */
 725            "\"\xED\xAE\x80\xED\xBF\xBF\"",
 726            "\xED\xAE\x80\xED\xBF\xBF", /* bug: not corrected */
 727            "\"\\uFFFD\\uFFFD\"",
 728        },
 729        {
 730            /* \U+DBFF\U+DC00 */
 731            "\"\xED\xAF\xBF\xED\xB0\x80\"",
 732            "\xED\xAF\xBF\xED\xB0\x80", /* bug: not corrected */
 733            "\"\\uFFFD\\uFFFD\"",
 734        },
 735        {
 736            /* \U+DBFF\U+DFFF */
 737            "\"\xED\xAF\xBF\xED\xBF\xBF\"",
 738            "\xED\xAF\xBF\xED\xBF\xBF", /* bug: not corrected */
 739            "\"\\uFFFD\\uFFFD\"",
 740        },
 741        /* 5.3  Other illegal code positions */
 742        /* BMP noncharacters */
 743        {
 744            /* \U+FFFE */
 745            "\"\xEF\xBF\xBE\"",
 746            "\xEF\xBF\xBE",     /* bug: not corrected */
 747            "\"\\uFFFD\"",
 748        },
 749        {
 750            /* \U+FFFF */
 751            "\"\xEF\xBF\xBF\"",
 752            "\xEF\xBF\xBF",     /* bug: not corrected */
 753            "\"\\uFFFD\"",
 754        },
 755        {
 756            /* U+FDD0 */
 757            "\"\xEF\xB7\x90\"",
 758            "\xEF\xB7\x90",     /* bug: not corrected */
 759            "\"\\uFFFD\"",
 760        },
 761        {
 762            /* U+FDEF */
 763            "\"\xEF\xB7\xAF\"",
 764            "\xEF\xB7\xAF",     /* bug: not corrected */
 765            "\"\\uFFFD\"",
 766        },
 767        /* Plane 1 .. 16 noncharacters */
 768        {
 769            /* U+1FFFE U+1FFFF U+2FFFE U+2FFFF ... U+10FFFE U+10FFFF */
 770            "\"\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
 771            "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
 772            "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
 773            "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
 774            "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
 775            "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
 776            "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
 777            "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
 778            "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
 779            "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
 780            "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
 781            "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
 782            "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
 783            "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
 784            "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
 785            "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF\"",
 786            /* bug: not corrected */
 787            "\xF0\x9F\xBF\xBE\xF0\x9F\xBF\xBF"
 788            "\xF0\xAF\xBF\xBE\xF0\xAF\xBF\xBF"
 789            "\xF0\xBF\xBF\xBE\xF0\xBF\xBF\xBF"
 790            "\xF1\x8F\xBF\xBE\xF1\x8F\xBF\xBF"
 791            "\xF1\x9F\xBF\xBE\xF1\x9F\xBF\xBF"
 792            "\xF1\xAF\xBF\xBE\xF1\xAF\xBF\xBF"
 793            "\xF1\xBF\xBF\xBE\xF1\xBF\xBF\xBF"
 794            "\xF2\x8F\xBF\xBE\xF2\x8F\xBF\xBF"
 795            "\xF2\x9F\xBF\xBE\xF2\x9F\xBF\xBF"
 796            "\xF2\xAF\xBF\xBE\xF2\xAF\xBF\xBF"
 797            "\xF2\xBF\xBF\xBE\xF2\xBF\xBF\xBF"
 798            "\xF3\x8F\xBF\xBE\xF3\x8F\xBF\xBF"
 799            "\xF3\x9F\xBF\xBE\xF3\x9F\xBF\xBF"
 800            "\xF3\xAF\xBF\xBE\xF3\xAF\xBF\xBF"
 801            "\xF3\xBF\xBF\xBE\xF3\xBF\xBF\xBF"
 802            "\xF4\x8F\xBF\xBE\xF4\x8F\xBF\xBF",
 803            "\"\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 804            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 805            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD"
 806            "\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\\uFFFD\"",
 807        },
 808        {}
 809    };
 810    int i;
 811    QObject *obj;
 812    QString *str;
 813    const char *json_in, *utf8_out, *utf8_in, *json_out;
 814
 815    for (i = 0; test_cases[i].json_in; i++) {
 816        json_in = test_cases[i].json_in;
 817        utf8_out = test_cases[i].utf8_out;
 818        utf8_in = test_cases[i].utf8_in ?: test_cases[i].utf8_out;
 819        json_out = test_cases[i].json_out ?: test_cases[i].json_in;
 820
 821        obj = qobject_from_json(json_in);
 822        if (utf8_out) {
 823            g_assert(obj);
 824            g_assert(qobject_type(obj) == QTYPE_QSTRING);
 825            str = qobject_to_qstring(obj);
 826            g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
 827        } else {
 828            g_assert(!obj);
 829        }
 830        qobject_decref(obj);
 831
 832        obj = QOBJECT(qstring_from_str(utf8_in));
 833        str = qobject_to_json(obj);
 834        if (json_out) {
 835            g_assert(str);
 836            g_assert_cmpstr(qstring_get_str(str), ==, json_out);
 837        } else {
 838            g_assert(!str);
 839        }
 840        QDECREF(str);
 841        qobject_decref(obj);
 842
 843        /*
 844         * Disabled, because qobject_from_json() is buggy, and I can't
 845         * be bothered to add the expected incorrect results.
 846         * FIXME Enable once these bugs have been fixed.
 847         */
 848        if (0 && json_out != json_in) {
 849            obj = qobject_from_json(json_out);
 850            g_assert(obj);
 851            g_assert(qobject_type(obj) == QTYPE_QSTRING);
 852            str = qobject_to_qstring(obj);
 853            g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
 854        }
 855    }
 856}
 857
 858static void vararg_string(void)
 859{
 860    int i;
 861    struct {
 862        const char *decoded;
 863    } test_cases[] = {
 864        { "hello world" },
 865        { "the quick brown fox jumped over the fence" },
 866        {}
 867    };
 868
 869    for (i = 0; test_cases[i].decoded; i++) {
 870        QObject *obj;
 871        QString *str;
 872
 873        obj = qobject_from_jsonf("%s", test_cases[i].decoded);
 874
 875        g_assert(obj != NULL);
 876        g_assert(qobject_type(obj) == QTYPE_QSTRING);
 877        
 878        str = qobject_to_qstring(obj);
 879        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 880
 881        QDECREF(str);
 882    }
 883}
 884
 885static void simple_number(void)
 886{
 887    int i;
 888    struct {
 889        const char *encoded;
 890        int64_t decoded;
 891        int skip;
 892    } test_cases[] = {
 893        { "0", 0 },
 894        { "1234", 1234 },
 895        { "1", 1 },
 896        { "-32", -32 },
 897        { "-0", 0, .skip = 1 },
 898        { },
 899    };
 900
 901    for (i = 0; test_cases[i].encoded; i++) {
 902        QObject *obj;
 903        QInt *qint;
 904
 905        obj = qobject_from_json(test_cases[i].encoded);
 906        g_assert(obj != NULL);
 907        g_assert(qobject_type(obj) == QTYPE_QINT);
 908
 909        qint = qobject_to_qint(obj);
 910        g_assert(qint_get_int(qint) == test_cases[i].decoded);
 911        if (test_cases[i].skip == 0) {
 912            QString *str;
 913
 914            str = qobject_to_json(obj);
 915            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
 916            QDECREF(str);
 917        }
 918
 919        QDECREF(qint);
 920    }
 921}
 922
 923static void float_number(void)
 924{
 925    int i;
 926    struct {
 927        const char *encoded;
 928        double decoded;
 929        int skip;
 930    } test_cases[] = {
 931        { "32.43", 32.43 },
 932        { "0.222", 0.222 },
 933        { "-32.12313", -32.12313 },
 934        { "-32.20e-10", -32.20e-10, .skip = 1 },
 935        { },
 936    };
 937
 938    for (i = 0; test_cases[i].encoded; i++) {
 939        QObject *obj;
 940        QFloat *qfloat;
 941
 942        obj = qobject_from_json(test_cases[i].encoded);
 943        g_assert(obj != NULL);
 944        g_assert(qobject_type(obj) == QTYPE_QFLOAT);
 945
 946        qfloat = qobject_to_qfloat(obj);
 947        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
 948
 949        if (test_cases[i].skip == 0) {
 950            QString *str;
 951
 952            str = qobject_to_json(obj);
 953            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
 954            QDECREF(str);
 955        }
 956
 957        QDECREF(qfloat);
 958    }
 959}
 960
 961static void vararg_number(void)
 962{
 963    QObject *obj;
 964    QInt *qint;
 965    QFloat *qfloat;
 966    int value = 0x2342;
 967    long long value_ll = 0x2342342343LL;
 968    double valuef = 2.323423423;
 969
 970    obj = qobject_from_jsonf("%d", value);
 971    g_assert(obj != NULL);
 972    g_assert(qobject_type(obj) == QTYPE_QINT);
 973
 974    qint = qobject_to_qint(obj);
 975    g_assert(qint_get_int(qint) == value);
 976
 977    QDECREF(qint);
 978
 979    obj = qobject_from_jsonf("%lld", value_ll);
 980    g_assert(obj != NULL);
 981    g_assert(qobject_type(obj) == QTYPE_QINT);
 982
 983    qint = qobject_to_qint(obj);
 984    g_assert(qint_get_int(qint) == value_ll);
 985
 986    QDECREF(qint);
 987
 988    obj = qobject_from_jsonf("%f", valuef);
 989    g_assert(obj != NULL);
 990    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
 991
 992    qfloat = qobject_to_qfloat(obj);
 993    g_assert(qfloat_get_double(qfloat) == valuef);
 994
 995    QDECREF(qfloat);
 996}
 997
 998static void keyword_literal(void)
 999{
1000    QObject *obj;
1001    QBool *qbool;
1002    QObject *null;
1003    QString *str;
1004
1005    obj = qobject_from_json("true");
1006    g_assert(obj != NULL);
1007    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1008
1009    qbool = qobject_to_qbool(obj);
1010    g_assert(qbool_get_bool(qbool) == true);
1011
1012    str = qobject_to_json(obj);
1013    g_assert(strcmp(qstring_get_str(str), "true") == 0);
1014    QDECREF(str);
1015
1016    QDECREF(qbool);
1017
1018    obj = qobject_from_json("false");
1019    g_assert(obj != NULL);
1020    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1021
1022    qbool = qobject_to_qbool(obj);
1023    g_assert(qbool_get_bool(qbool) == false);
1024
1025    str = qobject_to_json(obj);
1026    g_assert(strcmp(qstring_get_str(str), "false") == 0);
1027    QDECREF(str);
1028
1029    QDECREF(qbool);
1030
1031    obj = qobject_from_jsonf("%i", false);
1032    g_assert(obj != NULL);
1033    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1034
1035    qbool = qobject_to_qbool(obj);
1036    g_assert(qbool_get_bool(qbool) == false);
1037
1038    QDECREF(qbool);
1039
1040    /* Test that non-zero values other than 1 get collapsed to true */
1041    obj = qobject_from_jsonf("%i", 2);
1042    g_assert(obj != NULL);
1043    g_assert(qobject_type(obj) == QTYPE_QBOOL);
1044
1045    qbool = qobject_to_qbool(obj);
1046    g_assert(qbool_get_bool(qbool) == true);
1047
1048    QDECREF(qbool);
1049
1050    obj = qobject_from_json("null");
1051    g_assert(obj != NULL);
1052    g_assert(qobject_type(obj) == QTYPE_QNULL);
1053
1054    null = qnull();
1055    g_assert(null == obj);
1056
1057    qobject_decref(obj);
1058    qobject_decref(null);
1059}
1060
1061typedef struct LiteralQDictEntry LiteralQDictEntry;
1062typedef struct LiteralQObject LiteralQObject;
1063
1064struct LiteralQObject
1065{
1066    int type;
1067    union {
1068        int64_t qint;
1069        const char *qstr;
1070        LiteralQDictEntry *qdict;
1071        LiteralQObject *qlist;
1072    } value;
1073};
1074
1075struct LiteralQDictEntry
1076{
1077    const char *key;
1078    LiteralQObject value;
1079};
1080
1081#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
1082#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
1083#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
1084#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
1085
1086typedef struct QListCompareHelper
1087{
1088    int index;
1089    LiteralQObject *objs;
1090    int result;
1091} QListCompareHelper;
1092
1093static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
1094
1095static void compare_helper(QObject *obj, void *opaque)
1096{
1097    QListCompareHelper *helper = opaque;
1098
1099    if (helper->result == 0) {
1100        return;
1101    }
1102
1103    if (helper->objs[helper->index].type == QTYPE_NONE) {
1104        helper->result = 0;
1105        return;
1106    }
1107
1108    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
1109}
1110
1111static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
1112{
1113    if (lhs->type != qobject_type(rhs)) {
1114        return 0;
1115    }
1116
1117    switch (lhs->type) {
1118    case QTYPE_QINT:
1119        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
1120    case QTYPE_QSTRING:
1121        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
1122    case QTYPE_QDICT: {
1123        int i;
1124
1125        for (i = 0; lhs->value.qdict[i].key; i++) {
1126            QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
1127
1128            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
1129                return 0;
1130            }
1131        }
1132
1133        return 1;
1134    }
1135    case QTYPE_QLIST: {
1136        QListCompareHelper helper;
1137
1138        helper.index = 0;
1139        helper.objs = lhs->value.qlist;
1140        helper.result = 1;
1141        
1142        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
1143
1144        return helper.result;
1145    }
1146    default:
1147        break;
1148    }
1149
1150    return 0;
1151}
1152
1153static void simple_dict(void)
1154{
1155    int i;
1156    struct {
1157        const char *encoded;
1158        LiteralQObject decoded;
1159    } test_cases[] = {
1160        {
1161            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
1162            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1163                        { "foo", QLIT_QINT(42) },
1164                        { "bar", QLIT_QSTR("hello world") },
1165                        { }
1166                    })),
1167        }, {
1168            .encoded = "{}",
1169            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1170                        { }
1171                    })),
1172        }, {
1173            .encoded = "{\"foo\": 43}",
1174            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
1175                        { "foo", QLIT_QINT(43) },
1176                        { }
1177                    })),
1178        },
1179        { }
1180    };
1181
1182    for (i = 0; test_cases[i].encoded; i++) {
1183        QObject *obj;
1184        QString *str;
1185
1186        obj = qobject_from_json(test_cases[i].encoded);
1187        g_assert(obj != NULL);
1188        g_assert(qobject_type(obj) == QTYPE_QDICT);
1189
1190        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1191
1192        str = qobject_to_json(obj);
1193        qobject_decref(obj);
1194
1195        obj = qobject_from_json(qstring_get_str(str));
1196        g_assert(obj != NULL);
1197        g_assert(qobject_type(obj) == QTYPE_QDICT);
1198
1199        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1200        qobject_decref(obj);
1201        QDECREF(str);
1202    }
1203}
1204
1205/*
1206 * this generates json of the form:
1207 * a(0,m) = [0, 1, ..., m-1]
1208 * a(n,m) = {
1209 *            'key0': a(0,m),
1210 *            'key1': a(1,m),
1211 *            ...
1212 *            'key(n-1)': a(n-1,m)
1213 *          }
1214 */
1215static void gen_test_json(GString *gstr, int nest_level_max,
1216                          int elem_count)
1217{
1218    int i;
1219
1220    g_assert(gstr);
1221    if (nest_level_max == 0) {
1222        g_string_append(gstr, "[");
1223        for (i = 0; i < elem_count; i++) {
1224            g_string_append_printf(gstr, "%d", i);
1225            if (i < elem_count - 1) {
1226                g_string_append_printf(gstr, ", ");
1227            }
1228        }
1229        g_string_append(gstr, "]");
1230        return;
1231    }
1232
1233    g_string_append(gstr, "{");
1234    for (i = 0; i < nest_level_max; i++) {
1235        g_string_append_printf(gstr, "'key%d': ", i);
1236        gen_test_json(gstr, i, elem_count);
1237        if (i < nest_level_max - 1) {
1238            g_string_append(gstr, ",");
1239        }
1240    }
1241    g_string_append(gstr, "}");
1242}
1243
1244static void large_dict(void)
1245{
1246    GString *gstr = g_string_new("");
1247    QObject *obj;
1248
1249    gen_test_json(gstr, 10, 100);
1250    obj = qobject_from_json(gstr->str);
1251    g_assert(obj != NULL);
1252
1253    qobject_decref(obj);
1254    g_string_free(gstr, true);
1255}
1256
1257static void simple_list(void)
1258{
1259    int i;
1260    struct {
1261        const char *encoded;
1262        LiteralQObject decoded;
1263    } test_cases[] = {
1264        {
1265            .encoded = "[43,42]",
1266            .decoded = QLIT_QLIST(((LiteralQObject[]){
1267                        QLIT_QINT(43),
1268                        QLIT_QINT(42),
1269                        { }
1270                    })),
1271        },
1272        {
1273            .encoded = "[43]",
1274            .decoded = QLIT_QLIST(((LiteralQObject[]){
1275                        QLIT_QINT(43),
1276                        { }
1277                    })),
1278        },
1279        {
1280            .encoded = "[]",
1281            .decoded = QLIT_QLIST(((LiteralQObject[]){
1282                        { }
1283                    })),
1284        },
1285        {
1286            .encoded = "[{}]",
1287            .decoded = QLIT_QLIST(((LiteralQObject[]){
1288                        QLIT_QDICT(((LiteralQDictEntry[]){
1289                                    {},
1290                                        })),
1291                        {},
1292                            })),
1293        },
1294        { }
1295    };
1296
1297    for (i = 0; test_cases[i].encoded; i++) {
1298        QObject *obj;
1299        QString *str;
1300
1301        obj = qobject_from_json(test_cases[i].encoded);
1302        g_assert(obj != NULL);
1303        g_assert(qobject_type(obj) == QTYPE_QLIST);
1304
1305        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1306
1307        str = qobject_to_json(obj);
1308        qobject_decref(obj);
1309
1310        obj = qobject_from_json(qstring_get_str(str));
1311        g_assert(obj != NULL);
1312        g_assert(qobject_type(obj) == QTYPE_QLIST);
1313
1314        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1315        qobject_decref(obj);
1316        QDECREF(str);
1317    }
1318}
1319
1320static void simple_whitespace(void)
1321{
1322    int i;
1323    struct {
1324        const char *encoded;
1325        LiteralQObject decoded;
1326    } test_cases[] = {
1327        {
1328            .encoded = " [ 43 , 42 ]",
1329            .decoded = QLIT_QLIST(((LiteralQObject[]){
1330                        QLIT_QINT(43),
1331                        QLIT_QINT(42),
1332                        { }
1333                    })),
1334        },
1335        {
1336            .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
1337            .decoded = QLIT_QLIST(((LiteralQObject[]){
1338                        QLIT_QINT(43),
1339                        QLIT_QDICT(((LiteralQDictEntry[]){
1340                                    { "h", QLIT_QSTR("b") },
1341                                    { }})),
1342                        QLIT_QLIST(((LiteralQObject[]){
1343                                    { }})),
1344                        QLIT_QINT(42),
1345                        { }
1346                    })),
1347        },
1348        {
1349            .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
1350            .decoded = QLIT_QLIST(((LiteralQObject[]){
1351                        QLIT_QINT(43),
1352                        QLIT_QDICT(((LiteralQDictEntry[]){
1353                                    { "h", QLIT_QSTR("b") },
1354                                    { "a", QLIT_QINT(32) },
1355                                    { }})),
1356                        QLIT_QLIST(((LiteralQObject[]){
1357                                    { }})),
1358                        QLIT_QINT(42),
1359                        { }
1360                    })),
1361        },
1362        { }
1363    };
1364
1365    for (i = 0; test_cases[i].encoded; i++) {
1366        QObject *obj;
1367        QString *str;
1368
1369        obj = qobject_from_json(test_cases[i].encoded);
1370        g_assert(obj != NULL);
1371        g_assert(qobject_type(obj) == QTYPE_QLIST);
1372
1373        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1374
1375        str = qobject_to_json(obj);
1376        qobject_decref(obj);
1377
1378        obj = qobject_from_json(qstring_get_str(str));
1379        g_assert(obj != NULL);
1380        g_assert(qobject_type(obj) == QTYPE_QLIST);
1381
1382        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
1383
1384        qobject_decref(obj);
1385        QDECREF(str);
1386    }
1387}
1388
1389static void simple_varargs(void)
1390{
1391    QObject *embedded_obj;
1392    QObject *obj;
1393    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
1394            QLIT_QINT(1),
1395            QLIT_QINT(2),
1396            QLIT_QLIST(((LiteralQObject[]){
1397                        QLIT_QINT(32),
1398                        QLIT_QINT(42),
1399                        {}})),
1400            {}}));
1401
1402    embedded_obj = qobject_from_json("[32, 42]");
1403    g_assert(embedded_obj != NULL);
1404
1405    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
1406    g_assert(obj != NULL);
1407
1408    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
1409
1410    qobject_decref(obj);
1411}
1412
1413static void empty_input(void)
1414{
1415    const char *empty = "";
1416
1417    QObject *obj = qobject_from_json(empty);
1418    g_assert(obj == NULL);
1419}
1420
1421static void unterminated_string(void)
1422{
1423    QObject *obj = qobject_from_json("\"abc");
1424    g_assert(obj == NULL);
1425}
1426
1427static void unterminated_sq_string(void)
1428{
1429    QObject *obj = qobject_from_json("'abc");
1430    g_assert(obj == NULL);
1431}
1432
1433static void unterminated_escape(void)
1434{
1435    QObject *obj = qobject_from_json("\"abc\\\"");
1436    g_assert(obj == NULL);
1437}
1438
1439static void unterminated_array(void)
1440{
1441    QObject *obj = qobject_from_json("[32");
1442    g_assert(obj == NULL);
1443}
1444
1445static void unterminated_array_comma(void)
1446{
1447    QObject *obj = qobject_from_json("[32,");
1448    g_assert(obj == NULL);
1449}
1450
1451static void invalid_array_comma(void)
1452{
1453    QObject *obj = qobject_from_json("[32,}");
1454    g_assert(obj == NULL);
1455}
1456
1457static void unterminated_dict(void)
1458{
1459    QObject *obj = qobject_from_json("{'abc':32");
1460    g_assert(obj == NULL);
1461}
1462
1463static void unterminated_dict_comma(void)
1464{
1465    QObject *obj = qobject_from_json("{'abc':32,");
1466    g_assert(obj == NULL);
1467}
1468
1469static void invalid_dict_comma(void)
1470{
1471    QObject *obj = qobject_from_json("{'abc':32,}");
1472    g_assert(obj == NULL);
1473}
1474
1475static void unterminated_literal(void)
1476{
1477    QObject *obj = qobject_from_json("nul");
1478    g_assert(obj == NULL);
1479}
1480
1481static char *make_nest(char *buf, size_t cnt)
1482{
1483    memset(buf, '[', cnt - 1);
1484    buf[cnt - 1] = '{';
1485    buf[cnt] = '}';
1486    memset(buf + cnt + 1, ']', cnt - 1);
1487    buf[2 * cnt] = 0;
1488    return buf;
1489}
1490
1491static void limits_nesting(void)
1492{
1493    enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
1494    char buf[2 * (max_nesting + 1) + 1];
1495    QObject *obj;
1496
1497    obj = qobject_from_json(make_nest(buf, max_nesting));
1498    g_assert(obj != NULL);
1499    qobject_decref(obj);
1500
1501    obj = qobject_from_json(make_nest(buf, max_nesting + 1));
1502    g_assert(obj == NULL);
1503}
1504
1505int main(int argc, char **argv)
1506{
1507    g_test_init(&argc, &argv, NULL);
1508
1509    g_test_add_func("/literals/string/simple", simple_string);
1510    g_test_add_func("/literals/string/escaped", escaped_string);
1511    g_test_add_func("/literals/string/utf8", utf8_string);
1512    g_test_add_func("/literals/string/single_quote", single_quote_string);
1513    g_test_add_func("/literals/string/vararg", vararg_string);
1514
1515    g_test_add_func("/literals/number/simple", simple_number);
1516    g_test_add_func("/literals/number/float", float_number);
1517    g_test_add_func("/literals/number/vararg", vararg_number);
1518
1519    g_test_add_func("/literals/keyword", keyword_literal);
1520
1521    g_test_add_func("/dicts/simple_dict", simple_dict);
1522    g_test_add_func("/dicts/large_dict", large_dict);
1523    g_test_add_func("/lists/simple_list", simple_list);
1524
1525    g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
1526
1527    g_test_add_func("/varargs/simple_varargs", simple_varargs);
1528
1529    g_test_add_func("/errors/empty_input", empty_input);
1530    g_test_add_func("/errors/unterminated/string", unterminated_string);
1531    g_test_add_func("/errors/unterminated/escape", unterminated_escape);
1532    g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
1533    g_test_add_func("/errors/unterminated/array", unterminated_array);
1534    g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
1535    g_test_add_func("/errors/unterminated/dict", unterminated_dict);
1536    g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
1537    g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
1538    g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
1539    g_test_add_func("/errors/unterminated/literal", unterminated_literal);
1540    g_test_add_func("/errors/limits/nesting", limits_nesting);
1541
1542    return g_test_run();
1543}
1544