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