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 "jvm.h" |
26 | #include "memory/resourceArea.hpp" |
27 | #include "utilities/json.hpp" |
28 | #include "unittest.hpp" |
29 | |
30 | class 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 | |
45 | char* JSON_GTest::get_output() { |
46 | return output.as_string(); |
47 | } |
48 | |
49 | void 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 | |
61 | JSON_GTest::JSON_GTest(const char* text) : JSON(text, false, &output) { |
62 | prev = JSON_NONE; |
63 | parse(); |
64 | } |
65 | |
66 | TEST_VM(utilities, json_curly_braces) { |
67 | JSON_GTest::test("{}" , true); |
68 | } |
69 | |
70 | TEST_VM(utilities, json_brackets) { |
71 | JSON_GTest::test("[]" , true); |
72 | } |
73 | |
74 | TEST_VM(utilities, json_space_braces) { |
75 | JSON_GTest::test(" { } " , true); |
76 | } |
77 | |
78 | TEST_VM(utilities, json_space_bracketes) { |
79 | JSON_GTest::test(" [ ] " , true); |
80 | } |
81 | |
82 | TEST_VM(utilities, json_quoted_error) { |
83 | JSON_GTest::test("\"error\"" , false); |
84 | } |
85 | |
86 | TEST_VM(utilities, json_error_string) { |
87 | JSON_GTest::test("error" , false); |
88 | } |
89 | |
90 | TEST_VM(utilities, json_simple_integer) { |
91 | JSON_GTest::test("1" , false); |
92 | } |
93 | |
94 | TEST_VM(utilities, json_siple_float) { |
95 | JSON_GTest::test("1.2" , false); |
96 | } |
97 | |
98 | TEST_VM(utilities, json_simple_boolean_true) { |
99 | JSON_GTest::test("true" , false); |
100 | } |
101 | |
102 | TEST_VM(utilities, json_simple_boolean_false) { |
103 | JSON_GTest::test("false" , false); |
104 | } |
105 | |
106 | TEST_VM(utilities, json_simple_null) { |
107 | JSON_GTest::test("null" , false); |
108 | } |
109 | |
110 | TEST_VM(utilities, json_one_element_int_array) { |
111 | JSON_GTest::test("[ 1 ]" , true); |
112 | } |
113 | |
114 | TEST_VM(utilities, json_int_array) { |
115 | JSON_GTest::test("[ 1, ]" , true); |
116 | } |
117 | |
118 | TEST_VM(utilities, json_one_element_bool_array) { |
119 | JSON_GTest::test("[ true ]" , true); |
120 | } |
121 | |
122 | TEST_VM(utilities, json_bool_array) { |
123 | JSON_GTest::test("[ true, ]" , true); |
124 | } |
125 | |
126 | TEST_VM(utilities, json_one_element_false_array) { |
127 | JSON_GTest::test("[ false ]" , true); |
128 | } |
129 | |
130 | TEST_VM(utilities, json_false_bool_array) { |
131 | JSON_GTest::test("[ false, ]" , true); |
132 | } |
133 | |
134 | TEST_VM(utilities, json_one_null_array) { |
135 | JSON_GTest::test("[ null ]" , true); |
136 | } |
137 | |
138 | TEST_VM(utilities, json_null_array) { |
139 | JSON_GTest::test("[ null, ]" , true); |
140 | } |
141 | |
142 | TEST_VM(utilities, json_one_empty_string_array) { |
143 | JSON_GTest::test("[ \"\" ]" , true); |
144 | } |
145 | |
146 | TEST_VM(utilities, json_empty_string_array) { |
147 | JSON_GTest::test("[ \"\", ]" , true); |
148 | } |
149 | |
150 | TEST_VM(utilities, json_single_string_array) { |
151 | JSON_GTest::test("[ \"elem1\" ]" , true); |
152 | } |
153 | |
154 | TEST_VM(utilities, json_string_comma_arrray) { |
155 | JSON_GTest::test("[ \"elem1\", ]" , true); |
156 | } |
157 | |
158 | TEST_VM(utilities, json_two_strings_array) { |
159 | JSON_GTest::test("[ \"elem1\", \"elem2\" ]" , true); |
160 | } |
161 | |
162 | TEST_VM(utilities, json_two_strings_comma_array) { |
163 | JSON_GTest::test("[ \"elem1\", \"elem2\", ]" , true); |
164 | } |
165 | |
166 | TEST_VM(utilities, json_curly_braces_outside) { |
167 | JSON_GTest::test("[ \"elem1\" ] { }" , false); |
168 | } |
169 | |
170 | TEST_VM(utilities, json_element_in_array) { |
171 | JSON_GTest::test("[ elem1, \"elem2\" ]" , false); |
172 | } |
173 | |
174 | TEST_VM(utilities, json_incorrect_end_array) { |
175 | JSON_GTest::test("[ \"elem1\"" , false); |
176 | } |
177 | |
178 | TEST_VM(utilities, json_incorrect_string_end) { |
179 | JSON_GTest::test("[ \"elem1 ]" , false); |
180 | } |
181 | |
182 | TEST_VM(utilities, json_incorrect_end_of_two_elements_array) { |
183 | JSON_GTest::test("[ \"elem1\", \"elem2\"" , false); |
184 | } |
185 | |
186 | TEST_VM(utilities, json_incorrect_bool_true_array) { |
187 | JSON_GTest::test("[ truefoo ]" , false); |
188 | } |
189 | |
190 | TEST_VM(utilities, json_incorrect_bool_false_array) { |
191 | JSON_GTest::test("[ falsefoo ]" , false); |
192 | } |
193 | |
194 | TEST_VM(utilities, json_incorrect_null_array) { |
195 | JSON_GTest::test("[ nullfoo ]" , false); |
196 | } |
197 | |
198 | TEST_VM(utilities, json_key_pair) { |
199 | JSON_GTest::test("{ key : 1 }" , true); |
200 | } |
201 | |
202 | TEST_VM(utilities, json_key_pair_comma) { |
203 | JSON_GTest::test("{ key : 1, }" , true); |
204 | } |
205 | |
206 | TEST_VM(utilities, json_bool_true_key) { |
207 | JSON_GTest::test("{ key : true }" , true); |
208 | } |
209 | |
210 | TEST_VM(utilities, json_bool_true_key_comma) { |
211 | JSON_GTest::test("{ key : true, }" , true); |
212 | } |
213 | |
214 | TEST_VM(utilities, json_bool_false_key) { |
215 | JSON_GTest::test("{ key : false }" , true); |
216 | } |
217 | |
218 | TEST_VM(utilities, json_bool_false_key_comma) { |
219 | JSON_GTest::test("{ key : false, }" , true); |
220 | } |
221 | |
222 | TEST_VM(utilities, json_null_key) { |
223 | JSON_GTest::test("{ key : null }" , true); |
224 | } |
225 | |
226 | TEST_VM(utilities, json_null_key_comma) { |
227 | JSON_GTest::test("{ key : null, }" , true); |
228 | } |
229 | |
230 | TEST_VM(utilities, json_pair_of_empty_strings) { |
231 | JSON_GTest::test("{ \"\" : \"\" }" , true); |
232 | } |
233 | |
234 | TEST_VM(utilities, json_pair_of_empty_strings_comma) { |
235 | JSON_GTest::test("{ \"\" : \"\", }" , true); |
236 | } |
237 | |
238 | TEST_VM(utilities, json_pair_of_strings) { |
239 | JSON_GTest::test("{ \"key1\" : \"val1\" }" , true); |
240 | } |
241 | |
242 | TEST_VM(utilities, json_pair_of_strings_comma) { |
243 | JSON_GTest::test("{ \"key1\" : \"val1\", }" , true); |
244 | } |
245 | |
246 | TEST_VM(utilities, json_two_pairs_of_strings) { |
247 | JSON_GTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\" }" , true); |
248 | } |
249 | |
250 | TEST_VM(utilities, json_two_pairs_of_strings_comma) { |
251 | JSON_GTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\", }" , true); |
252 | } |
253 | |
254 | TEST_VM(utilities, json_array_outside) { |
255 | JSON_GTest::test("{ \"key\" : \"val\" } [ \"error\" ]" , false); |
256 | } |
257 | |
258 | TEST_VM(utilities, json_incorrect_object_end) { |
259 | JSON_GTest::test("{ \"key\" : \"val\" " , false); |
260 | } |
261 | |
262 | TEST_VM(utilities, json_empty_comment) { |
263 | JSON_GTest::test("/**/ { }" , true); |
264 | } |
265 | |
266 | TEST_VM(utilities, json_space_comment) { |
267 | JSON_GTest::test("/* */ { }" , true); |
268 | } |
269 | |
270 | TEST_VM(utilities, json_comment) { |
271 | JSON_GTest::test("/*foo*/ { }" , true); |
272 | } |
273 | |
274 | TEST_VM(utilities, json_star_comment) { |
275 | JSON_GTest::test("/* *foo */ { }" , true); |
276 | } |
277 | |
278 | TEST_VM(utilities, json_stars_comment) { |
279 | JSON_GTest::test("/* *foo* */ { }" , true); |
280 | } |
281 | |
282 | TEST_VM(utilities, json_special_comment) { |
283 | JSON_GTest::test("/* /*foo */ { }" , true); |
284 | } |
285 | |
286 | TEST_VM(utilities, json_comment_after) { |
287 | JSON_GTest::test("{ } /* foo */" , true); |
288 | } |
289 | |
290 | TEST_VM(utilities, json_comment_after_and_space) { |
291 | JSON_GTest::test("{ } /* foo */ " , true); |
292 | } |
293 | |
294 | TEST_VM(utilities, json_one_line_empty_comment_after) { |
295 | JSON_GTest::test("{ } //" , true); |
296 | } |
297 | |
298 | TEST_VM(utilities, json_one_line_space_comment_after) { |
299 | JSON_GTest::test("{ } // " , true); |
300 | } |
301 | |
302 | TEST_VM(utilities, json_one_line_comment_after) { |
303 | JSON_GTest::test("{ } // foo" , true); |
304 | } |
305 | |
306 | TEST_VM(utilities, json_incorrect_multiline_comment) { |
307 | JSON_GTest::test("/* * / { }" , false); |
308 | } |
309 | |
310 | TEST_VM(utilities, json_incorrect_multiline_comment_begin) { |
311 | JSON_GTest::test("/ * */ { }" , false); |
312 | } |
313 | |
314 | TEST_VM(utilities, json_oneline_comment_only) { |
315 | JSON_GTest::test("// { }" , false); |
316 | } |
317 | |
318 | TEST_VM(utilities, json_multiline_comment_only) { |
319 | JSON_GTest::test("/* { } */" , false); |
320 | } |
321 | |
322 | TEST_VM(utilities, json_multiline_comment_2) { |
323 | JSON_GTest::test("/* { } */ " , false); |
324 | } |
325 | |
326 | TEST_VM(utilities, json_incorrectly_commented_object) { |
327 | JSON_GTest::test("/* { } " , false); |
328 | } |
329 | |
330 | TEST_VM(utilities, json_missing_multiline_end) { |
331 | JSON_GTest::test("{ } /* " , false); |
332 | } |
333 | |
334 | TEST_VM(utilities, json_missing_multiline_slash) { |
335 | JSON_GTest::test("/* { } *" , false); |
336 | } |
337 | |
338 | TEST_VM(utilities, json_commented_object_end) { |
339 | JSON_GTest::test("{ /* } */" , false); |
340 | } |
341 | |
342 | TEST_VM(utilities, json_commented_array_end) { |
343 | JSON_GTest::test("[ /* ] */" , false); |
344 | } |
345 | |
346 | TEST_VM(utilities, json_missing_object_end) { |
347 | JSON_GTest::test("{ key : \"val\", /* } */" , false); |
348 | } |
349 | |
350 | TEST_VM(utilities, json_missing_array_end) { |
351 | JSON_GTest::test("[ \"val\", /* ] */" , false); |
352 | } |
353 | |
354 | TEST_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 | |
360 | TEST_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 | |
366 | TEST_VM(utilities, json_quoted_symbols) { |
367 | JSON_GTest::test("/*comment*/{\"ff1 fsd\":{\"☃\":{\"☃\":[\"☃\",\"☃\"]}," |
368 | "\"☃\":true},\"☃\":[\"☃\"],\"foo\":\"☃\",}" , true); |
369 | } |
370 | |
371 | TEST_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 | |
377 | TEST_VM(utilities, json_array_with_newline) { |
378 | JSON_GTest::test("[\n]" , true); |
379 | } |
380 | |
381 | TEST_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 | |
427 | void 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 | |
439 | bool 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 | |