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