1/* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24#include "precompiled.hpp" 25#include "memory/resourceArea.hpp" 26#include "prims/jvm.h" 27#include "utilities/json.hpp" 28#include "unittest.hpp" 29 30class JSON_GTest : public JSON { 31 public: 32 static void test(const char* json, bool valid); 33 char* get_output(); 34 35 private: 36 JSON_GTest(const char* text); 37 stringStream output; 38 39 void log(uint level, const char* format, ...) ATTRIBUTE_PRINTF(3, 4); 40 41 bool callback(JSON_TYPE t, JSON_VAL* v, uint level); 42 JSON_TYPE prev; 43}; 44 45char* JSON_GTest::get_output() { 46 return output.as_string(); 47} 48 49void JSON_GTest::test(const char* text, bool should_pass) { 50 ResourceMark rm; 51 JSON_GTest json(text); 52 if (should_pass) { 53 ASSERT_TRUE(json.valid()) << "failed on a valid json string" 54 << std::endl << "debug output:" << std::endl << json.get_output(); 55 } else { 56 ASSERT_FALSE(json.valid()) << "succeeded on an invalid json string" 57 << std::endl << "debug output:" << std::endl << json.get_output(); 58 } 59} 60 61JSON_GTest::JSON_GTest(const char* text) : JSON(text, false, &output) { 62 prev = JSON_NONE; 63 parse(); 64} 65 66TEST_VM(utilities, json_curly_braces) { 67 JSON_GTest::test("{}", true); 68} 69 70TEST_VM(utilities, json_brackets) { 71 JSON_GTest::test("[]", true); 72} 73 74TEST_VM(utilities, json_space_braces) { 75 JSON_GTest::test(" { } ", true); 76} 77 78TEST_VM(utilities, json_space_bracketes) { 79 JSON_GTest::test(" [ ] ", true); 80} 81 82TEST_VM(utilities, json_quoted_error) { 83 JSON_GTest::test("\"error\"", false); 84} 85 86TEST_VM(utilities, json_error_string) { 87 JSON_GTest::test("error", false); 88} 89 90TEST_VM(utilities, json_simple_integer) { 91 JSON_GTest::test("1", false); 92} 93 94TEST_VM(utilities, json_siple_float) { 95 JSON_GTest::test("1.2", false); 96} 97 98TEST_VM(utilities, json_simple_boolean_true) { 99 JSON_GTest::test("true", false); 100} 101 102TEST_VM(utilities, json_simple_boolean_false) { 103 JSON_GTest::test("false", false); 104} 105 106TEST_VM(utilities, json_simple_null) { 107 JSON_GTest::test("null", false); 108} 109 110TEST_VM(utilities, json_one_element_int_array) { 111 JSON_GTest::test("[ 1 ]", true); 112} 113 114TEST_VM(utilities, json_int_array) { 115 JSON_GTest::test("[ 1, ]", true); 116} 117 118TEST_VM(utilities, json_one_element_bool_array) { 119 JSON_GTest::test("[ true ]", true); 120} 121 122TEST_VM(utilities, json_bool_array) { 123 JSON_GTest::test("[ true, ]", true); 124} 125 126TEST_VM(utilities, json_one_element_false_array) { 127 JSON_GTest::test("[ false ]", true); 128} 129 130TEST_VM(utilities, json_false_bool_array) { 131 JSON_GTest::test("[ false, ]", true); 132} 133 134TEST_VM(utilities, json_one_null_array) { 135 JSON_GTest::test("[ null ]", true); 136} 137 138TEST_VM(utilities, json_null_array) { 139 JSON_GTest::test("[ null, ]", true); 140} 141 142TEST_VM(utilities, json_one_empty_string_array) { 143 JSON_GTest::test("[ \"\" ]", true); 144} 145 146TEST_VM(utilities, json_empty_string_array) { 147 JSON_GTest::test("[ \"\", ]", true); 148} 149 150TEST_VM(utilities, json_single_string_array) { 151 JSON_GTest::test("[ \"elem1\" ]", true); 152} 153 154TEST_VM(utilities, json_string_comma_arrray) { 155 JSON_GTest::test("[ \"elem1\", ]", true); 156} 157 158TEST_VM(utilities, json_two_strings_array) { 159 JSON_GTest::test("[ \"elem1\", \"elem2\" ]", true); 160} 161 162TEST_VM(utilities, json_two_strings_comma_array) { 163 JSON_GTest::test("[ \"elem1\", \"elem2\", ]", true); 164} 165 166TEST_VM(utilities, json_curly_braces_outside) { 167 JSON_GTest::test("[ \"elem1\" ] { }", false); 168} 169 170TEST_VM(utilities, json_element_in_array) { 171 JSON_GTest::test("[ elem1, \"elem2\" ]", false); 172} 173 174TEST_VM(utilities, json_incorrect_end_array) { 175 JSON_GTest::test("[ \"elem1\"", false); 176} 177 178TEST_VM(utilities, json_incorrect_string_end) { 179 JSON_GTest::test("[ \"elem1 ]", false); 180} 181 182TEST_VM(utilities, json_incorrect_end_of_two_elements_array) { 183 JSON_GTest::test("[ \"elem1\", \"elem2\"", false); 184} 185 186TEST_VM(utilities, json_incorrect_bool_true_array) { 187 JSON_GTest::test("[ truefoo ]", false); 188} 189 190TEST_VM(utilities, json_incorrect_bool_false_array) { 191 JSON_GTest::test("[ falsefoo ]", false); 192} 193 194TEST_VM(utilities, json_incorrect_null_array) { 195 JSON_GTest::test("[ nullfoo ]", false); 196} 197 198TEST_VM(utilities, json_key_pair) { 199 JSON_GTest::test("{ key : 1 }", true); 200} 201 202TEST_VM(utilities, json_key_pair_comma) { 203 JSON_GTest::test("{ key : 1, }", true); 204} 205 206TEST_VM(utilities, json_bool_true_key) { 207 JSON_GTest::test("{ key : true }", true); 208} 209 210TEST_VM(utilities, json_bool_true_key_comma) { 211 JSON_GTest::test("{ key : true, }", true); 212} 213 214TEST_VM(utilities, json_bool_false_key) { 215 JSON_GTest::test("{ key : false }", true); 216} 217 218TEST_VM(utilities, json_bool_false_key_comma) { 219 JSON_GTest::test("{ key : false, }", true); 220} 221 222TEST_VM(utilities, json_null_key) { 223 JSON_GTest::test("{ key : null }", true); 224} 225 226TEST_VM(utilities, json_null_key_comma) { 227 JSON_GTest::test("{ key : null, }", true); 228} 229 230TEST_VM(utilities, json_pair_of_empty_strings) { 231 JSON_GTest::test("{ \"\" : \"\" }", true); 232} 233 234TEST_VM(utilities, json_pair_of_empty_strings_comma) { 235 JSON_GTest::test("{ \"\" : \"\", }", true); 236} 237 238TEST_VM(utilities, json_pair_of_strings) { 239 JSON_GTest::test("{ \"key1\" : \"val1\" }", true); 240} 241 242TEST_VM(utilities, json_pair_of_strings_comma) { 243 JSON_GTest::test("{ \"key1\" : \"val1\", }", true); 244} 245 246TEST_VM(utilities, json_two_pairs_of_strings) { 247 JSON_GTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\" }", true); 248} 249 250TEST_VM(utilities, json_two_pairs_of_strings_comma) { 251 JSON_GTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\", }", true); 252} 253 254TEST_VM(utilities, json_array_outside) { 255 JSON_GTest::test("{ \"key\" : \"val\" } [ \"error\" ]", false); 256} 257 258TEST_VM(utilities, json_incorrect_object_end) { 259 JSON_GTest::test("{ \"key\" : \"val\" ", false); 260} 261 262TEST_VM(utilities, json_empty_comment) { 263 JSON_GTest::test("/**/ { }", true); 264} 265 266TEST_VM(utilities, json_space_comment) { 267 JSON_GTest::test("/* */ { }", true); 268} 269 270TEST_VM(utilities, json_comment) { 271 JSON_GTest::test("/*foo*/ { }", true); 272} 273 274TEST_VM(utilities, json_star_comment) { 275 JSON_GTest::test("/* *foo */ { }", true); 276} 277 278TEST_VM(utilities, json_stars_comment) { 279 JSON_GTest::test("/* *foo* */ { }", true); 280} 281 282TEST_VM(utilities, json_special_comment) { 283 JSON_GTest::test("/* /*foo */ { }", true); 284} 285 286TEST_VM(utilities, json_comment_after) { 287 JSON_GTest::test("{ } /* foo */", true); 288} 289 290TEST_VM(utilities, json_comment_after_and_space) { 291 JSON_GTest::test("{ } /* foo */ ", true); 292} 293 294TEST_VM(utilities, json_one_line_empty_comment_after) { 295 JSON_GTest::test("{ } //", true); 296} 297 298TEST_VM(utilities, json_one_line_space_comment_after) { 299 JSON_GTest::test("{ } // ", true); 300} 301 302TEST_VM(utilities, json_one_line_comment_after) { 303 JSON_GTest::test("{ } // foo", true); 304} 305 306TEST_VM(utilities, json_incorrect_multiline_comment) { 307 JSON_GTest::test("/* * / { }", false); 308} 309 310TEST_VM(utilities, json_incorrect_multiline_comment_begin) { 311 JSON_GTest::test("/ * */ { }", false); 312} 313 314TEST_VM(utilities, json_oneline_comment_only) { 315 JSON_GTest::test("// { }", false); 316} 317 318TEST_VM(utilities, json_multiline_comment_only) { 319 JSON_GTest::test("/* { } */", false); 320} 321 322TEST_VM(utilities, json_multiline_comment_2) { 323 JSON_GTest::test("/* { } */ ", false); 324} 325 326TEST_VM(utilities, json_incorrectly_commented_object) { 327 JSON_GTest::test("/* { } ", false); 328} 329 330TEST_VM(utilities, json_missing_multiline_end) { 331 JSON_GTest::test("{ } /* ", false); 332} 333 334TEST_VM(utilities, json_missing_multiline_slash) { 335 JSON_GTest::test("/* { } *", false); 336} 337 338TEST_VM(utilities, json_commented_object_end) { 339 JSON_GTest::test("{ /* } */", false); 340} 341 342TEST_VM(utilities, json_commented_array_end) { 343 JSON_GTest::test("[ /* ] */", false); 344} 345 346TEST_VM(utilities, json_missing_object_end) { 347 JSON_GTest::test("{ key : \"val\", /* } */", false); 348} 349 350TEST_VM(utilities, json_missing_array_end) { 351 JSON_GTest::test("[ \"val\", /* ] */", false); 352} 353 354TEST_VM(utilities, json_key_values_1) { 355 JSON_GTest::test("/* comment */{ key1 : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\"," 356 "{ \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\"" 357 " : true }, \"key6\" : [ \"���\" ], key7 : \"val\",}", true); 358} 359 360TEST_VM(utilities, json_key_values_2) { 361 JSON_GTest::test("/* comment */ { \"key1\" : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\"," 362 "{ \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\"" 363 " : true }, \"key6\" : [ \"���\" ], key7 : \"val\",}", true); 364} 365 366TEST_VM(utilities, json_quoted_symbols) { 367 JSON_GTest::test("/*comment*/{\"ff1 fsd\":{\"���\":{\"���\":[\"���\",\"���\"]}," 368 "\"���\":true},\"���\":[\"���\"],\"foo\":\"���\",}", true); 369} 370 371TEST_VM(utilities, json_incorrect_key) { 372 JSON_GTest::test("/* comment */ { key1 error : { \"���\" : { \"���\" : [ \"���\"," 373 " \"���\" ] }, \"���\" : true }, \"baz\" : [ \"���\" ], foo : \"���\",}", 374 false); // first key needs to be quoted since it contains a space 375} 376 377TEST_VM(utilities, json_array_with_newline) { 378 JSON_GTest::test("[\n]", true); 379} 380 381TEST_VM(utilities, json_directives_file) { 382 JSON_GTest::test( 383 "[" "\n" 384 " {" 385 " // pattern to match against class+method+signature" "\n" 386 " // leading and trailing wildcard (*) allowed" "\n" 387 " match: \"foo.bar.*\"," "\n" 388 " " "\n" 389 " // override defaults for specified compiler" "\n" 390 " // we may differentiate between levels too. TBD." "\n" 391 " c1: {" "\n" 392 " //override c1 presets " "\n" 393 " array_bounds_check_removal: false" "\n" 394 " }," "\n" 395 "" "\n" 396 " c2: {" "\n" 397 " // control inlining of method" "\n" 398 " // + force inline, - dont inline" "\n" 399 " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" 400 " }," "\n" 401 "" "\n" 402 " // directives outside a specific preset applies to all compilers" "\n" 403 " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" 404 " print_assembly: true," "\n" 405 " verify_oopmaps: true," "\n" 406 " max_loop_unrolling: 5" "\n" 407 " }," "\n" 408 " {" "\n" 409 " // matching several patterns require an array" "\n" 410 " match: [\"baz.*\",\"frob*\"]," "\n" 411 "" "\n" 412 " // only enable c1 for this directive" "\n" 413 " // all enabled by default. Command disables all not listed" "\n" 414 " enable: \"c1\"," "\n" 415 "" "\n" 416 " // applies to all compilers" "\n" 417 " // + force inline, - dont inline" "\n" 418 " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" 419 " print_inlining: true," "\n" 420 "" "\n" 421 " // force matching compiles to be blocking/syncronous" "\n" 422 " blocking_compile: true" "\n" 423 " }," "\n" 424 "]" "\n", true); 425} 426 427void JSON_GTest::log(uint indent, const char* format, ...) { 428 if (prev != JSON_KEY) { 429 for (uint i = 0; i < indent; i++) { 430 _st->print(" "); 431 } 432 } 433 va_list args; 434 va_start(args, format); 435 _st->vprint(format, args); 436 va_end(args); 437} 438 439bool JSON_GTest::callback(JSON_TYPE t, JSON_VAL* v, uint rlevel) { 440 switch (t) { 441 case JSON_OBJECT_BEGIN: 442 log(rlevel, "{\n"); 443 prev = JSON_NONE; // Only care about JSON_KEY, to indent correctly 444 return true; 445 446 case JSON_OBJECT_END: 447 log(rlevel, "},\n"); 448 prev = JSON_NONE; 449 return true; 450 451 case JSON_ARRAY_BEGIN: 452 log(rlevel, "[\n"); 453 prev = JSON_NONE; 454 return true; 455 456 case JSON_ARRAY_END: 457 log(rlevel, "],\n"); 458 prev = JSON_NONE; 459 return true; 460 461 case JSON_KEY: 462 for (uint i = 0; i < rlevel; i++) { 463 _st->print(" "); 464 } 465 _st->print("<key>"); 466 for (size_t i = 0; i < v->str.length; i++) { 467 u_char c = v->str.start[i]; 468 if (c == 0) { 469 return false; 470 } 471 _st->print("%c", c); 472 } 473 _st->print(" : "); 474 prev = JSON_KEY; 475 return true; 476 477 case JSON_STRING: 478 if (prev != JSON_KEY) { 479 for (uint i = 0; i < rlevel; i++) { 480 _st->print(" "); 481 } 482 } 483 _st->print("<str>"); 484 for (size_t i = 0; i < v->str.length; i++) { 485 u_char c = v->str.start[i]; 486 if (c == 0) { 487 return false; 488 } 489 _st->print("%c", c); 490 } 491 _st->print(",\n"); 492 prev = JSON_NONE; 493 return true; 494 495 case JSON_NUMBER_INT: 496 log(rlevel, "<int>%" PRId64 ",\n", v->int_value); 497 prev = JSON_NONE; 498 return true; 499 500 case JSON_NUMBER_FLOAT: 501 log(rlevel, "<double>%lf,\n", v->double_value); 502 prev = JSON_NONE; 503 return true; 504 505 case JSON_TRUE: 506 log(rlevel, "<true>,\n"); 507 prev = JSON_NONE; 508 return true; 509 510 case JSON_FALSE: 511 log(rlevel, "<false>,\n"); 512 prev = JSON_NONE; 513 return true; 514 515 case JSON_NULL: 516 log(rlevel, "<null>,\n"); 517 prev = JSON_NONE; 518 return true; 519 520 default: 521 error(INTERNAL_ERROR, "unknown JSON type"); 522 return false; 523 } 524} 525