1/*
2 * Copyright (c) 2016, 2018, 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
26#include <locale.h>
27
28#include "compiler/directivesParser.hpp"
29#include "runtime/interfaceSupport.inline.hpp"
30#include "runtime/thread.hpp"
31#include "unittest.hpp"
32
33class DirectivesParserTest : public ::testing::Test{
34 protected:
35 const char* const _locale;
36 ResourceMark rm;
37 stringStream stream;
38 // These tests require the "C" locale to correctly parse decimal values
39 DirectivesParserTest() : _locale(setlocale(LC_NUMERIC, NULL)) {
40 setlocale(LC_NUMERIC, "C");
41 }
42 ~DirectivesParserTest() {
43 setlocale(LC_NUMERIC, _locale);
44 }
45
46 void test_negative(const char* text) {
47 JavaThread* THREAD = JavaThread::current();
48 ThreadInVMfromNative ThreadInVMfromNative(THREAD);
49 DirectivesParser cd(text, &stream, false);
50 cd.clean_tmp();
51 EXPECT_FALSE(cd.valid()) << "text: " << std::endl << text << std::endl << stream.as_string();
52 }
53
54 void test_positive(const char* text) {
55 JavaThread* THREAD = JavaThread::current();
56 ThreadInVMfromNative ThreadInVMfromNative(THREAD);
57 DirectivesParser cd(text, &stream, false);
58 cd.clean_tmp();
59 EXPECT_TRUE(cd.valid()) << "text: " << std::endl << text << std::endl << stream.as_string();
60 }
61};
62
63TEST_VM_F(DirectivesParserTest, empty_object) {
64 test_negative("{}");
65}
66
67TEST_VM_F(DirectivesParserTest, empty_array) {
68 test_positive("[]");
69}
70
71TEST_VM_F(DirectivesParserTest, empty_object_in_array) {
72 test_negative("[{}]");
73}
74
75TEST_VM_F(DirectivesParserTest, empty_objects_in_array) {
76 test_negative("[{},{}]");
77}
78
79TEST_VM_F(DirectivesParserTest, empty_objects) {
80 test_negative("{},{}");
81}
82
83TEST_VM_F(DirectivesParserTest, simple_match) {
84 test_positive(
85 "[" "\n"
86 " {" "\n"
87 " match: \"foo/bar.*\"," "\n"
88 " inline : \"+java/util.*\"," "\n"
89 " PrintAssembly: true," "\n"
90 " BreakAtExecute: true," "\n"
91 " }" "\n"
92 "]" "\n");
93
94}
95
96TEST_VM_F(DirectivesParserTest, nesting_arrays) {
97 test_negative(
98 "[" "\n"
99 " [" "\n"
100 " {" "\n"
101 " match: \"foo/bar.*\"," "\n"
102 " inline : \"+java/util.*\"," "\n"
103 " PrintAssembly: true," "\n"
104 " BreakAtExecute: true," "\n"
105 " }" "\n"
106 " ]" "\n"
107 "]" "\n");
108}
109
110TEST_VM_F(DirectivesParserTest, c1_block) {
111 test_positive(
112 "[" "\n"
113 " {" "\n"
114 " match: \"foo/bar.*\"," "\n"
115 " c1: {"
116 " PrintInlining: false," "\n"
117 " }" "\n"
118 " }" "\n"
119 "]" "\n");
120}
121
122TEST_VM_F(DirectivesParserTest, c2_block) {
123 test_positive(
124 "[" "\n"
125 " {" "\n"
126 " match: \"foo/bar.*\"," "\n"
127 " c2: {" "\n"
128 " PrintInlining: false," "\n"
129 " }" "\n"
130 " }" "\n"
131 "]" "\n");
132}
133
134TEST_VM_F(DirectivesParserTest, boolean_array) {
135 test_negative(
136 "[" "\n"
137 " {" "\n"
138 " match: \"foo/bar.*\"," "\n"
139 " PrintInlining: [" "\n"
140 " true," "\n"
141 " false" "\n"
142 " ]," "\n"
143 " }" "\n"
144 "]" "\n");
145}
146
147TEST_VM_F(DirectivesParserTest, multiple_objects) {
148 test_positive(
149 "[" "\n"
150 " {"
151 " // pattern to match against class+method+signature" "\n"
152 " // leading and trailing wildcard (*) allowed" "\n"
153 " match: \"foo/bar.*\"," "\n"
154 "" "\n"
155 " // override defaults for specified compiler" "\n"
156 " // we may differentiate between levels too. TBD." "\n"
157 " c1: {" "\n"
158 " //override c1 presets " "\n"
159 " DumpReplay: false," "\n"
160 " BreakAtCompile: true," "\n"
161 " }," "\n"
162 "" "\n"
163 " c2: {" "\n"
164 " // control inlining of method" "\n"
165 " // + force inline, - dont inline" "\n"
166 " inline : \"+java/util.*\"," "\n"
167 " PrintInlining: true," "\n"
168 " }," "\n"
169 "" "\n"
170 " // directives outside a specific preset applies to all compilers" "\n"
171 " inline : [ \"+java/util.*\", \"-com/sun.*\"]," "\n"
172 " BreakAtExecute: true," "\n"
173 " Log: true," "\n"
174 " }," "\n"
175 " {" "\n"
176 " // matching several patterns require an array" "\n"
177 " match: [\"baz.*\",\"frob.*\"]," "\n"
178 "" "\n"
179 " // applies to all compilers" "\n"
180 " // + force inline, - dont inline" "\n"
181 " inline : [ \"+java/util.*\", \"-com/sun.*\" ]," "\n"
182 " PrintInlining: true," "\n"
183 "" "\n"
184 " // force matching compiles to be blocking/syncronous" "\n"
185 " PrintNMethods: true" "\n"
186 " }," "\n"
187 "]" "\n");
188}
189
190// Test max stack depth
191TEST_VM_F(DirectivesParserTest, correct_max_stack_depth) {
192 test_positive(
193 "[" "\n" // depth 1: type_dir_array
194 " {" "\n" // depth 2: type_directives
195 " match: \"*.*\"," // match required
196 " c1:" "\n" // depth 3: type_c1
197 " {" "\n"
198 " inline:" "\n" // depth 4: type_inline
199 " [" "\n" // depth 5: type_value_array
200 " \"foo\"," "\n"
201 " \"bar\"," "\n"
202 " ]" "\n" // depth 3: pop type_value_array and type_inline keys
203 " }" "\n" // depth 2: pop type_c1 key
204 " }" "\n" // depth 1: pop type_directives key
205 "]" "\n"); // depth 0: pop type_dir_array key
206}
207
208// Test max stack depth
209TEST_VM_F(DirectivesParserTest, incorrect_max_stack_depth) {
210 test_negative("[{c1:{c1:{c1:{c1:{c1:{c1:{c1:{}}}}}}}}]");
211}
212