1 #include <assert.h> 2 #include <stddef.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include "json.h" 8 #include "json_tokener.h" 9 #include "json_visit.h" 10 11 static void test_basic_parse(void); 12 static void test_utf8_parse(void); 13 static void test_verbose_parse(void); 14 static void test_incremental_parse(void); 15 16 int main(void) 17 { 18 MC_SET_DEBUG(1); 19 20 static const char separator[] = "=================================="; 21 test_basic_parse(); 22 puts(separator); 23 test_utf8_parse(); 24 puts(separator); 25 test_verbose_parse(); 26 puts(separator); 27 test_incremental_parse(); 28 puts(separator); 29 30 return 0; 31 } 32 33 static json_c_visit_userfunc clear_serializer; 34 static void do_clear_serializer(json_object *jso); 35 36 static void single_incremental_parse(const char *test_string, int clear_serializer) 37 { 38 int ii; 39 int chunksize = atoi(getenv("TEST_PARSE_CHUNKSIZE")); 40 struct json_tokener *tok; 41 enum json_tokener_error jerr; 42 json_object *all_at_once_obj, *new_obj; 43 const char *all_at_once_str, *new_str; 44 45 assert(chunksize > 0); 46 all_at_once_obj = json_tokener_parse(test_string); 47 if (clear_serializer) 48 do_clear_serializer(all_at_once_obj); 49 all_at_once_str = json_object_to_json_string(all_at_once_obj); 50 51 tok = json_tokener_new(); 52 int test_string_len = strlen(test_string) + 1; // Including '\0' ! 53 for (ii = 0; ii < test_string_len; ii += chunksize) 54 { 55 int len_to_parse = chunksize; 56 if (ii + chunksize > test_string_len) 57 len_to_parse = test_string_len - ii; 58 59 if (getenv("TEST_PARSE_DEBUG") != NULL) 60 printf(" chunk: %.*s\n", len_to_parse, &test_string[ii]); 61 new_obj = json_tokener_parse_ex(tok, &test_string[ii], len_to_parse); 62 jerr = json_tokener_get_error(tok); 63 if (jerr != json_tokener_continue || new_obj) 64 break; 65 } 66 if (clear_serializer && new_obj) 67 do_clear_serializer(new_obj); 68 new_str = json_object_to_json_string(new_obj); 69 70 if (strcmp(all_at_once_str, new_str) != 0) 71 { 72 printf("ERROR: failed to parse (%s) in %d byte chunks: %s != %s\n", test_string, 73 chunksize, all_at_once_str, new_str); 74 } 75 json_tokener_free(tok); 76 if (all_at_once_obj) 77 json_object_put(all_at_once_obj); 78 if (new_obj) 79 json_object_put(new_obj); 80 } 81 82 static void single_basic_parse(const char *test_string, int clear_serializer) 83 { 84 json_object *new_obj; 85 86 new_obj = json_tokener_parse(test_string); 87 if (clear_serializer) 88 do_clear_serializer(new_obj); 89 printf("new_obj.to_string(%s)=%s\n", test_string, json_object_to_json_string(new_obj)); 90 json_object_put(new_obj); 91 92 if (getenv("TEST_PARSE_CHUNKSIZE") != NULL) 93 single_incremental_parse(test_string, clear_serializer); 94 } 95 static void test_basic_parse() 96 { 97 single_basic_parse("\"\003\"", 0); 98 single_basic_parse("/* hello */\"foo\"", 0); 99 single_basic_parse("// hello\n\"foo\"", 0); 100 single_basic_parse("\"foo\"blue", 0); 101 single_basic_parse("\'foo\'", 0); 102 single_basic_parse("\"\\u0041\\u0042\\u0043\"", 0); 103 single_basic_parse("\"\\u4e16\\u754c\\u00df\"", 0); 104 single_basic_parse("\"\\u4E16\"", 0); 105 single_basic_parse("\"\\u4e1\"", 0); 106 single_basic_parse("\"\\u4e1@\"", 0); 107 single_basic_parse("\"\\ud840\\u4e16\"", 0); 108 single_basic_parse("\"\\ud840\"", 0); 109 single_basic_parse("\"\\udd27\"", 0); 110 // Test with a "short" high surrogate 111 single_basic_parse("[9,'\\uDAD", 0); 112 single_basic_parse("null", 0); 113 single_basic_parse("NaN", 0); 114 single_basic_parse("-NaN", 0); /* non-sensical, returns null */ 115 116 single_basic_parse("Inf", 0); /* must use full string, returns null */ 117 single_basic_parse("inf", 0); /* must use full string, returns null */ 118 single_basic_parse("Infinity", 0); 119 single_basic_parse("infinity", 0); 120 single_basic_parse("-Infinity", 0); 121 single_basic_parse("-infinity", 0); 122 single_basic_parse("{ \"min\": Infinity, \"max\": -Infinity}", 0); 123 124 single_basic_parse("Infinity!", 0); 125 single_basic_parse("Infinitynull", 0); 126 single_basic_parse("InfinityXXXX", 0); 127 single_basic_parse("-Infinitynull", 0); 128 single_basic_parse("-InfinityXXXX", 0); 129 single_basic_parse("Infinoodle", 0); 130 single_basic_parse("InfinAAA", 0); 131 single_basic_parse("-Infinoodle", 0); 132 single_basic_parse("-InfinAAA", 0); 133 134 single_basic_parse("True", 0); 135 single_basic_parse("False", 0); 136 137 /* not case sensitive */ 138 single_basic_parse("tRue", 0); 139 single_basic_parse("fAlse", 0); 140 single_basic_parse("nAn", 0); 141 single_basic_parse("iNfinity", 0); 142 143 single_basic_parse("12", 0); 144 single_basic_parse("12.3", 0); 145 146 /* Even though, when using json_tokener_parse() there's no way to 147 * know when there is more data after the parsed object, 148 * an object is successfully returned anyway (in some cases) 149 */ 150 151 single_basic_parse("12.3.4", 0); 152 single_basic_parse("2015-01-15", 0); 153 single_basic_parse("12.3xxx", 0); 154 single_basic_parse("12.3{\"a\":123}", 0); 155 single_basic_parse("12.3\n", 0); 156 single_basic_parse("12.3 ", 0); 157 158 single_basic_parse("{\"FoO\" : -12.3E512}", 0); 159 single_basic_parse("{\"FoO\" : -12.3e512}", 0); 160 single_basic_parse("{\"FoO\" : -12.3E51.2}", 0); /* non-sensical, returns null */ 161 single_basic_parse("{\"FoO\" : -12.3E512E12}", 0); /* non-sensical, returns null */ 162 single_basic_parse("[\"\\n\"]", 0); 163 single_basic_parse("[\"\\nabc\\n\"]", 0); 164 single_basic_parse("[null]", 0); 165 single_basic_parse("[]", 0); 166 single_basic_parse("[false]", 0); 167 single_basic_parse("[\"abc\",null,\"def\",12]", 0); 168 single_basic_parse("{}", 0); 169 single_basic_parse("{ \"foo\": \"bar\" }", 0); 170 single_basic_parse("{ \'foo\': \'bar\' }", 0); 171 single_basic_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }", 0); 172 single_basic_parse("{ \"foo\": [null, \"foo\"] }", 0); 173 single_basic_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, " 174 "\"arr\": [ 1, 2, 3, null, 5 ] }", 175 0); 176 single_basic_parse("{ \"abc\": \"blue\nred\\ngreen\" }", 0); 177 178 // Clear serializer for these tests so we see the actual parsed value. 179 single_basic_parse("null", 1); 180 single_basic_parse("false", 1); 181 single_basic_parse("[0e]", 1); 182 single_basic_parse("[0e+]", 1); 183 single_basic_parse("[0e+-1]", 1); 184 single_basic_parse("\"hello world!\"", 1); 185 186 // uint64/int64 range test 187 single_basic_parse("[9223372036854775806]", 1); 188 single_basic_parse("[9223372036854775807]", 1); 189 single_basic_parse("[9223372036854775808]", 1); 190 single_basic_parse("[-9223372036854775807]", 1); 191 single_basic_parse("[-9223372036854775808]", 1); 192 single_basic_parse("[-9223372036854775809]", 1); 193 single_basic_parse("[18446744073709551614]", 1); 194 single_basic_parse("[18446744073709551615]", 1); 195 single_basic_parse("[18446744073709551616]", 1); 196 } 197 198 static void test_utf8_parse() 199 { 200 // json_tokener_parse doesn't support checking for byte order marks. 201 // It's the responsibility of the caller to detect and skip a BOM. 202 // Both of these checks return null. 203 char *utf8_bom = "\xEF\xBB\xBF"; 204 char *utf8_bom_and_chars = "\xEF\xBB\xBF{}"; 205 single_basic_parse(utf8_bom, 0); 206 single_basic_parse(utf8_bom_and_chars, 0); 207 } 208 209 // Clear the re-serialization information that the tokener 210 // saves to ensure that the output reflects the actual 211 // values we parsed, rather than just the original input. 212 static void do_clear_serializer(json_object *jso) 213 { 214 json_c_visit(jso, 0, clear_serializer, NULL); 215 } 216 217 static int clear_serializer(json_object *jso, int flags, json_object *parent_jso, 218 const char *jso_key, size_t *jso_index, void *userarg) 219 { 220 if (jso) 221 json_object_set_serializer(jso, NULL, NULL, NULL); 222 return JSON_C_VISIT_RETURN_CONTINUE; 223 } 224 225 static void test_verbose_parse() 226 { 227 json_object *new_obj; 228 enum json_tokener_error error = json_tokener_success; 229 230 new_obj = json_tokener_parse_verbose("{ foo }", &error); 231 assert(error == json_tokener_error_parse_object_key_name); 232 assert(new_obj == NULL); 233 234 new_obj = json_tokener_parse("{ foo }"); 235 assert(new_obj == NULL); 236 237 new_obj = json_tokener_parse("foo"); 238 assert(new_obj == NULL); 239 new_obj = json_tokener_parse_verbose("foo", &error); 240 assert(new_obj == NULL); 241 242 /* b/c the string starts with 'f' parsing return a boolean error */ 243 assert(error == json_tokener_error_parse_boolean); 244 245 puts("json_tokener_parse_verbose() OK"); 246 } 247 248 struct incremental_step 249 { 250 const char *string_to_parse; 251 int length; 252 int char_offset; 253 enum json_tokener_error expected_error; 254 int reset_tokener; /* Set to 1 to call json_tokener_reset() after parsing */ 255 int tok_flags; /* JSON_TOKENER_* flags to pass to json_tokener_set_flags() */ 256 } incremental_steps[] = { 257 258 /* Check that full json messages can be parsed, both w/ and w/o a reset */ 259 {"{ \"foo\": 123 }", -1, -1, json_tokener_success, 0}, 260 {"{ \"foo\": 456 }", -1, -1, json_tokener_success, 1}, 261 {"{ \"foo\": 789 }", -1, -1, json_tokener_success, 1}, 262 263 /* Check the comment parse*/ 264 {"/* hello */{ \"foo\"", -1, -1, json_tokener_continue, 0}, 265 {"/* hello */:/* hello */", -1, -1, json_tokener_continue, 0}, 266 {"\"bar\"/* hello */", -1, -1, json_tokener_continue, 0}, 267 {"}/* hello */", -1, -1, json_tokener_success, 1}, 268 {"/ hello ", -1, 1, json_tokener_error_parse_comment, 1}, 269 {"/* hello\"foo\"", -1, -1, json_tokener_continue, 1}, 270 {"/* hello*\"foo\"", -1, -1, json_tokener_continue, 1}, 271 {"// hello\"foo\"", -1, -1, json_tokener_continue, 1}, 272 273 /* Check a basic incremental parse */ 274 {"{ \"foo", -1, -1, json_tokener_continue, 0}, 275 {"\": {\"bar", -1, -1, json_tokener_continue, 0}, 276 {"\":13}}", -1, -1, json_tokener_success, 1}, 277 278 /* Check the UTF-16 surrogate pair handling in various ways. 279 * Note: \ud843\udd1e is u+1D11E, Musical Symbol G Clef 280 * Your terminal may not display these correctly, in particular 281 * PuTTY doesn't currently show this character. 282 */ 283 /* parse one char at every time */ 284 {"\"\\", -1, -1, json_tokener_continue, 0}, 285 {"u", -1, -1, json_tokener_continue, 0}, 286 {"d", -1, -1, json_tokener_continue, 0}, 287 {"8", -1, -1, json_tokener_continue, 0}, 288 {"3", -1, -1, json_tokener_continue, 0}, 289 {"4", -1, -1, json_tokener_continue, 0}, 290 {"\\", -1, -1, json_tokener_continue, 0}, 291 {"u", -1, -1, json_tokener_continue, 0}, 292 {"d", -1, -1, json_tokener_continue, 0}, 293 {"d", -1, -1, json_tokener_continue, 0}, 294 {"1", -1, -1, json_tokener_continue, 0}, 295 {"e\"", -1, -1, json_tokener_success, 1}, 296 /* parse two char at every time */ 297 {"\"\\u", -1, -1, json_tokener_continue, 0}, 298 {"d8", -1, -1, json_tokener_continue, 0}, 299 {"34", -1, -1, json_tokener_continue, 0}, 300 {"\\u", -1, -1, json_tokener_continue, 0}, 301 {"dd", -1, -1, json_tokener_continue, 0}, 302 {"1e\"", -1, -1, json_tokener_success, 1}, 303 /* check the low surrogate pair */ 304 {"\"\\ud834", -1, -1, json_tokener_continue, 0}, 305 {"\\udd1e\"", -1, -1, json_tokener_success, 1}, 306 {"\"\\ud834\\", -1, -1, json_tokener_continue, 0}, 307 {"udd1e\"", -1, -1, json_tokener_success, 1}, 308 {"\"\\ud834\\u", -1, -1, json_tokener_continue, 0}, 309 {"dd1e\"", -1, -1, json_tokener_success, 1}, 310 {"\"fff \\ud834\\ud", -1, -1, json_tokener_continue, 0}, 311 {"d1e bar\"", -1, -1, json_tokener_success, 1}, 312 {"\"fff \\ud834\\udd", -1, -1, json_tokener_continue, 0}, 313 {"1e bar\"", -1, -1, json_tokener_success, 1}, 314 315 /* \ud83d\ude00 is U+1F600, Grinning Face 316 * Displays fine in PuTTY, though you may need "less -r" 317 */ 318 {"\"fff \\ud83d\\ude", -1, -1, json_tokener_continue, 0}, 319 {"00 bar\"", -1, -1, json_tokener_success, 1}, 320 321 /* Check that json_tokener_reset actually resets */ 322 {"{ \"foo", -1, -1, json_tokener_continue, 1}, 323 {": \"bar\"}", -1, 0, json_tokener_error_parse_unexpected, 1}, 324 325 /* Check incremental parsing with trailing characters */ 326 {"{ \"foo", -1, -1, json_tokener_continue, 0}, 327 {"\": {\"bar", -1, -1, json_tokener_continue, 0}, 328 {"\":13}}XXXX", 10, 6, json_tokener_success, 0}, 329 {"XXXX", 4, 0, json_tokener_error_parse_unexpected, 1}, 330 331 /* Check that trailing characters can change w/o a reset */ 332 {"{\"x\": 123 }\"X\"", -1, 11, json_tokener_success, 0}, 333 {"\"Y\"", -1, -1, json_tokener_success, 1}, 334 335 /* Trailing characters should cause a failure in strict mode */ 336 {"{\"foo\":9}{\"bar\":8}", -1, 9, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, 337 338 /* ... unless explicitly allowed. */ 339 {"{\"foo\":9}{\"bar\":8}", -1, 9, json_tokener_success, 0, 340 JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS}, 341 {"{\"b\":8}ignored garbage", -1, 7, json_tokener_success, 1, 342 JSON_TOKENER_STRICT | JSON_TOKENER_ALLOW_TRAILING_CHARS}, 343 344 /* To stop parsing a number we need to reach a non-digit, e.g. a \0 */ 345 {"1", 1, 1, json_tokener_continue, 0}, 346 /* This should parse as the number 12, since it continues the "1" */ 347 {"2", 2, 1, json_tokener_success, 0}, 348 {"12{", 3, 2, json_tokener_success, 1}, 349 /* Parse number in strict mode */ 350 {"[02]", -1, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, 351 352 {"0e+0", 5, 4, json_tokener_success, 1}, 353 {"[0e+0]", -1, -1, json_tokener_success, 1}, 354 355 /* The behavior when missing the exponent varies slightly */ 356 {"0e", 2, 2, json_tokener_continue, 1}, 357 {"0e", 3, 2, json_tokener_success, 1}, 358 {"0e", 3, 2, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT}, 359 {"[0e]", -1, -1, json_tokener_success, 1}, 360 {"[0e]", -1, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, 361 362 {"0e+", 3, 3, json_tokener_continue, 1}, 363 {"0e+", 4, 3, json_tokener_success, 1}, 364 {"0e+", 4, 3, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT}, 365 {"[0e+]", -1, -1, json_tokener_success, 1}, 366 {"[0e+]", -1, 4, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, 367 368 {"0e-", 3, 3, json_tokener_continue, 1}, 369 {"0e-", 4, 3, json_tokener_success, 1}, 370 {"0e-", 4, 3, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT}, 371 {"[0e-]", -1, -1, json_tokener_success, 1}, 372 {"[0e-]", -1, 4, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, 373 374 /* You might expect this to fail, but it won't because 375 it's a valid partial parse; note the char_offset: */ 376 {"0e+-", 5, 3, json_tokener_success, 1}, 377 {"0e+-", 5, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, 378 {"[0e+-]", -1, 4, json_tokener_error_parse_number, 1}, 379 380 /* Similar tests for other kinds of objects: */ 381 /* These could all return success immediately, since regardless of 382 what follows the false/true/null token we *will* return a json object, 383 but it currently doesn't work that way. hmm... */ 384 {"false", 5, 5, json_tokener_continue, 1}, 385 {"false", 6, 5, json_tokener_success, 1}, 386 {"true", 4, 4, json_tokener_continue, 1}, 387 {"true", 5, 4, json_tokener_success, 1}, 388 {"null", 4, 4, json_tokener_continue, 1}, 389 {"null", 5, 4, json_tokener_success, 1}, 390 391 {"Infinity", 9, 8, json_tokener_success, 1}, 392 {"infinity", 9, 8, json_tokener_success, 1}, 393 {"-infinity", 10, 9, json_tokener_success, 1}, 394 {"infinity", 9, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, 395 {"-infinity", 10, 1, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, 396 397 {"inf", 3, 3, json_tokener_continue, 0}, 398 {"inity", 6, 5, json_tokener_success, 1}, 399 {"-inf", 4, 4, json_tokener_continue, 0}, 400 {"inity", 6, 5, json_tokener_success, 1}, 401 402 {"i", 1, 1, json_tokener_continue, 0}, 403 {"n", 1, 1, json_tokener_continue, 0}, 404 {"f", 1, 1, json_tokener_continue, 0}, 405 {"i", 1, 1, json_tokener_continue, 0}, 406 {"n", 1, 1, json_tokener_continue, 0}, 407 {"i", 1, 1, json_tokener_continue, 0}, 408 {"t", 1, 1, json_tokener_continue, 0}, 409 {"y", 1, 1, json_tokener_continue, 0}, 410 {"", 1, 0, json_tokener_success, 1}, 411 412 {"-", 1, 1, json_tokener_continue, 0}, 413 {"inf", 3, 3, json_tokener_continue, 0}, 414 {"ini", 3, 3, json_tokener_continue, 0}, 415 {"ty", 3, 2, json_tokener_success, 1}, 416 417 {"-", 1, 1, json_tokener_continue, 0}, 418 {"i", 1, 1, json_tokener_continue, 0}, 419 {"nfini", 5, 5, json_tokener_continue, 0}, 420 {"ty", 3, 2, json_tokener_success, 1}, 421 422 {"-i", 2, 2, json_tokener_continue, 0}, 423 {"nfinity", 8, 7, json_tokener_success, 1}, 424 425 {"InfinityX", 10, 8, json_tokener_success, 0}, 426 {"X", 1, 0, json_tokener_error_parse_unexpected, 1}, 427 428 {"Infinity1234", 13, 8, json_tokener_success, 0}, 429 {"1234", 5, 4, json_tokener_success, 1}, 430 431 {"Infinity9999", 8, 8, json_tokener_continue, 0}, 432 433 /* returns the Infinity loaded up by the previous call: */ 434 {"1234", 5, 0, json_tokener_success, 0}, 435 {"1234", 5, 4, json_tokener_success, 1}, 436 437 /* offset=1 because "n" is the start of "null". hmm... */ 438 {"noodle", 7, 1, json_tokener_error_parse_null, 1}, 439 /* offset=2 because "na" is the start of "nan". hmm... */ 440 {"naodle", 7, 2, json_tokener_error_parse_null, 1}, 441 /* offset=2 because "tr" is the start of "true". hmm... */ 442 {"track", 6, 2, json_tokener_error_parse_boolean, 1}, 443 {"fail", 5, 2, json_tokener_error_parse_boolean, 1}, 444 445 /* Although they may initially look like they should fail, 446 * the next few tests check that parsing multiple sequential 447 * json objects in the input works as expected 448 */ 449 {"null123", 8, 4, json_tokener_success, 0}, 450 {&"null123"[4], 4, 3, json_tokener_success, 1}, 451 {"nullx", 6, 4, json_tokener_success, 0}, 452 {&"nullx"[4], 2, 0, json_tokener_error_parse_unexpected, 1}, 453 {"{\"a\":1}{\"b\":2}", 15, 7, json_tokener_success, 0}, 454 {&"{\"a\":1}{\"b\":2}"[7], 8, 7, json_tokener_success, 1}, 455 456 /* 457 * Though this may seem invalid at first glance, it 458 * parses as three separate numbers, 2015, -1 and -15 459 * Of course, simply pasting together a stream of arbitrary 460 * positive numbers won't work, since there'll be no way to 461 * tell where in e.g. "2015015" the next number stats, so 462 * a reliably parsable stream must not include json_type_int 463 * or json_type_double objects without some other delimiter. 464 * e.g. whitespace 465 */ 466 {&"2015-01-15"[0], 11, 4, json_tokener_success, 1}, 467 {&"2015-01-15"[4], 7, 3, json_tokener_success, 1}, 468 {&"2015-01-15"[7], 4, 3, json_tokener_success, 1}, 469 {&"2015 01 15"[0], 11, 5, json_tokener_success, 1}, 470 {&"2015 01 15"[4], 7, 4, json_tokener_success, 1}, 471 {&"2015 01 15"[7], 4, 3, json_tokener_success, 1}, 472 473 /* Strings have a well defined end point, so we can stop at the quote */ 474 {"\"blue\"", -1, -1, json_tokener_success, 0}, 475 476 /* Check each of the escape sequences defined by the spec */ 477 {"\"\\\"\"", -1, -1, json_tokener_success, 0}, 478 {"\"\\\\\"", -1, -1, json_tokener_success, 0}, 479 {"\"\\b\"", -1, -1, json_tokener_success, 0}, 480 {"\"\\f\"", -1, -1, json_tokener_success, 0}, 481 {"\"\\n\"", -1, -1, json_tokener_success, 0}, 482 {"\"\\r\"", -1, -1, json_tokener_success, 0}, 483 {"\"\\t\"", -1, -1, json_tokener_success, 0}, 484 {"\"\\/\"", -1, -1, json_tokener_success, 0}, 485 // Escaping a forward slash is optional 486 {"\"/\"", -1, -1, json_tokener_success, 0}, 487 /* Check wrong escape sequences */ 488 {"\"\\a\"", -1, 2, json_tokener_error_parse_string, 1}, 489 490 /* Check '\'' in strict model */ 491 {"\'foo\'", -1, 0, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, 492 493 /* Parse array/object */ 494 {"[1,2,3]", -1, -1, json_tokener_success, 0}, 495 {"[1,2,3}", -1, 6, json_tokener_error_parse_array, 1}, 496 {"{\"a\"}", -1, 4, json_tokener_error_parse_object_key_sep, 1}, 497 {"{\"a\":1]", -1, 6, json_tokener_error_parse_object_value_sep, 1}, 498 {"{\"a\"::1}", -1, 5, json_tokener_error_parse_unexpected, 1}, 499 {"{\"a\":}", -1, 5, json_tokener_error_parse_unexpected, 1}, 500 {"{\"a\":1,\"a\":2}", -1, -1, json_tokener_success, 1}, 501 {"\"a\":1}", -1, 3, json_tokener_success, 1}, 502 {"{\"a\":1", -1, -1, json_tokener_continue, 1}, 503 {"[,]", -1, 1, json_tokener_error_parse_unexpected, 1}, 504 {"[,1]", -1, 1, json_tokener_error_parse_unexpected, 1}, 505 506 /* This behaviour doesn't entirely follow the json spec, but until we have 507 * a way to specify how strict to be we follow Postel's Law and be liberal 508 * in what we accept (up to a point). 509 */ 510 {"[1,2,3,]", -1, -1, json_tokener_success, 0}, 511 {"[1,2,,3,]", -1, 5, json_tokener_error_parse_unexpected, 0}, 512 513 {"[1,2,3,]", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, 514 {"{\"a\":1,}", -1, 7, json_tokener_error_parse_unexpected, 1, JSON_TOKENER_STRICT}, 515 516 // utf-8 test 517 // acsll encoding 518 {"\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22", -1, -1, json_tokener_success, 1, 519 JSON_TOKENER_VALIDATE_UTF8}, 520 {"\x22\x31\x32\x33\x61\x73\x63\x24\x25\x26\x22", -1, -1, json_tokener_success, 1}, 521 // utf-8 encoding 522 {"\x22\xe4\xb8\x96\xe7\x95\x8c\x22", -1, -1, json_tokener_success, 1, 523 JSON_TOKENER_VALIDATE_UTF8}, 524 {"\x22\xe4\xb8", -1, 3, json_tokener_error_parse_utf8_string, 0, JSON_TOKENER_VALIDATE_UTF8}, 525 {"\x96\xe7\x95\x8c\x22", -1, 0, json_tokener_error_parse_utf8_string, 1, 526 JSON_TOKENER_VALIDATE_UTF8}, 527 {"\x22\xe4\xb8\x96\xe7\x95\x8c\x22", -1, -1, json_tokener_success, 1}, 528 {"\x22\xcf\x80\xcf\x86\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8}, 529 {"\x22\xf0\xa5\x91\x95\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8}, 530 // wrong utf-8 encoding 531 {"\x22\xe6\x9d\x4e\x22", -1, 3, json_tokener_error_parse_utf8_string, 1, 532 JSON_TOKENER_VALIDATE_UTF8}, 533 {"\x22\xe6\x9d\x4e\x22", -1, 5, json_tokener_success, 1}, 534 // GBK encoding 535 {"\x22\xc0\xee\xc5\xf4\x22", -1, 2, json_tokener_error_parse_utf8_string, 1, 536 JSON_TOKENER_VALIDATE_UTF8}, 537 {"\x22\xc0\xee\xc5\xf4\x22", -1, 6, json_tokener_success, 1}, 538 // char after space 539 {"\x20\x20\x22\xe4\xb8\x96\x22", -1, -1, json_tokener_success, 1, JSON_TOKENER_VALIDATE_UTF8}, 540 {"\x20\x20\x81\x22\xe4\xb8\x96\x22", -1, 2, json_tokener_error_parse_utf8_string, 1, 541 JSON_TOKENER_VALIDATE_UTF8}, 542 {"\x5b\x20\x81\x31\x5d", -1, 2, json_tokener_error_parse_utf8_string, 1, 543 JSON_TOKENER_VALIDATE_UTF8}, 544 // char in state inf 545 {"\x49\x6e\x66\x69\x6e\x69\x74\x79", 9, 8, json_tokener_success, 1}, 546 {"\x49\x6e\x66\x81\x6e\x69\x74\x79", -1, 3, json_tokener_error_parse_utf8_string, 1, 547 JSON_TOKENER_VALIDATE_UTF8}, 548 // char in escape unicode 549 {"\x22\x5c\x75\x64\x38\x35\x35\x5c\x75\x64\x63\x35\x35\x22", 15, 14, json_tokener_success, 1, 550 JSON_TOKENER_VALIDATE_UTF8}, 551 {"\x22\x5c\x75\x64\x38\x35\x35\xc0\x75\x64\x63\x35\x35\x22", -1, 8, 552 json_tokener_error_parse_utf8_string, 1, JSON_TOKENER_VALIDATE_UTF8}, 553 {"\x22\x5c\x75\x64\x30\x30\x33\x31\xc0\x22", -1, 9, json_tokener_error_parse_utf8_string, 1, 554 JSON_TOKENER_VALIDATE_UTF8}, 555 // char in number 556 {"\x31\x31\x81\x31\x31", -1, 2, json_tokener_error_parse_utf8_string, 1, 557 JSON_TOKENER_VALIDATE_UTF8}, 558 // char in object 559 {"\x7b\x22\x31\x81\x22\x3a\x31\x7d", -1, 3, json_tokener_error_parse_utf8_string, 1, 560 JSON_TOKENER_VALIDATE_UTF8}, 561 562 {NULL, -1, -1, json_tokener_success, 0}, 563 }; 564 565 static void test_incremental_parse() 566 { 567 json_object *new_obj; 568 enum json_tokener_error jerr; 569 struct json_tokener *tok; 570 const char *string_to_parse; 571 int ii; 572 int num_ok, num_error; 573 574 num_ok = 0; 575 num_error = 0; 576 577 printf("Starting incremental tests.\n"); 578 printf("Note: quotes and backslashes seen in the output here are literal values passed\n"); 579 printf(" to the parse functions. e.g. this is 4 characters: \"\\f\"\n"); 580 581 string_to_parse = "{ \"foo"; /* } */ 582 printf("json_tokener_parse(%s) ... ", string_to_parse); 583 new_obj = json_tokener_parse(string_to_parse); 584 if (new_obj == NULL) 585 puts("got error as expected"); 586 587 /* test incremental parsing in various forms */ 588 tok = json_tokener_new(); 589 for (ii = 0; incremental_steps[ii].string_to_parse != NULL; ii++) 590 { 591 int this_step_ok = 0; 592 struct incremental_step *step = &incremental_steps[ii]; 593 int length = step->length; 594 size_t expected_char_offset; 595 596 json_tokener_set_flags(tok, step->tok_flags); 597 598 if (length == -1) 599 length = (int)strlen(step->string_to_parse); 600 if (step->char_offset == -1) 601 expected_char_offset = length; 602 else 603 expected_char_offset = step->char_offset; 604 605 printf("json_tokener_parse_ex(tok, %-12s, %3d) ... ", step->string_to_parse, 606 length); 607 new_obj = json_tokener_parse_ex(tok, step->string_to_parse, length); 608 609 jerr = json_tokener_get_error(tok); 610 if (step->expected_error != json_tokener_success) 611 { 612 if (new_obj != NULL) 613 printf("ERROR: invalid object returned: %s\n", 614 json_object_to_json_string(new_obj)); 615 else if (jerr != step->expected_error) 616 printf("ERROR: got wrong error: %s\n", 617 json_tokener_error_desc(jerr)); 618 else if (json_tokener_get_parse_end(tok) != expected_char_offset) 619 printf("ERROR: wrong char_offset %zu != expected %zu\n", 620 json_tokener_get_parse_end(tok), expected_char_offset); 621 else 622 { 623 printf("OK: got correct error: %s\n", 624 json_tokener_error_desc(jerr)); 625 this_step_ok = 1; 626 } 627 } 628 else 629 { 630 if (new_obj == NULL && 631 !(step->length >= 4 && strncmp(step->string_to_parse, "null", 4) == 0)) 632 printf("ERROR: expected valid object, instead: %s\n", 633 json_tokener_error_desc(jerr)); 634 else if (json_tokener_get_parse_end(tok) != expected_char_offset) 635 printf("ERROR: wrong char_offset %zu != expected %zu\n", 636 json_tokener_get_parse_end(tok), expected_char_offset); 637 else 638 { 639 printf("OK: got object of type [%s]: %s\n", 640 json_type_to_name(json_object_get_type(new_obj)), 641 json_object_to_json_string(new_obj)); 642 this_step_ok = 1; 643 } 644 } 645 646 if (new_obj) 647 json_object_put(new_obj); 648 649 if (step->reset_tokener & 1) 650 json_tokener_reset(tok); 651 652 if (this_step_ok) 653 num_ok++; 654 else 655 num_error++; 656 } 657 658 json_tokener_free(tok); 659 660 printf("End Incremental Tests OK=%d ERROR=%d\n", num_ok, num_error); 661 } 662
This page was automatically generated by LXR 0.3.1. • OpenWrt