1 /*
2 * Copyright (c) 2014, 2021, 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 package compiler.rtm.cli;
25
26 import jdk.test.lib.process.ExitCode;
27 import jdk.test.lib.Platform;
28 import jdk.test.lib.cli.CommandLineOptionTest;
29
30 import java.util.function.BooleanSupplier;
31
32 /**
33 * Base for all RTM-related CLI tests.
34 */
35 public abstract class RTMGenericCommandLineOptionTest {
36
37 protected static final String RTM_INSTR_ERROR
38 = "RTM instructions are not available on this CPU";
39 protected static final String RTM_UNSUPPORTED_VM_ERROR
40 = "RTM locking optimization is not supported in this VM";
41 protected static final String RTM_FOR_STACK_LOCKS_WARNING
42 = "UseRTMForStackLocks flag should be off when UseRTMLocking "
43 + "flag is off";
44 protected static final String RTM_COUNT_INCR_WARNING
45 = "must be a power of 2, resetting it to 64";
46
47 protected final String optionName;
48 protected final String errorMessage;
49 protected final String experimentalOptionError;
50 protected final boolean isExperimental;
51 protected final boolean isBoolean;
52 protected final String defaultValue;
53 protected final String[] optionValues;
54
55 /**
56 * Constructs new genetic RTM CLI test, for option {@code optionName} which
57 * has default value {@code defaultValue}. Test cases will use option's
58 * values passed via {@code optionValues} for verification of correct
59 * option processing.
60 *
61 * Test constructed using this ctor will be started on any cpu regardless
62 * it's architecture and supported/unsupported features.
63 *
64 * @param optionName name of option to be tested
65 * @param isBoolean {@code true} if option is binary
66 * @param isExperimental {@code true} if option is experimental
67 * @param defaultValue default value of tested option
68 * @param optionValues different option values
69 */
70 public RTMGenericCommandLineOptionTest(
71 String optionName, boolean isBoolean, boolean isExperimental,
72 String defaultValue, String... optionValues) {
73 this.optionName = optionName;
74 this.isExperimental = isExperimental;
75 this.isBoolean = isBoolean;
76 this.defaultValue = defaultValue;
77 this.optionValues = optionValues;
78 this.errorMessage = CommandLineOptionTest.
79 getUnrecognizedOptionErrorMessage(optionName);
80 this.experimentalOptionError = CommandLineOptionTest.
81 getExperimentalOptionErrorMessage(optionName);
82 }
83
84 public void runTestCases() throws Throwable {
85 if (Platform.isX86() || Platform.isX64()) {
86 if (Platform.isServer()) {
87 runX86SupportedVMTestCases();
88 } else {
89 runX86UnsupportedVMTestCases();
90 }
91 } else {
92 runNonX86TestCases();
93 }
94 }
95
96 /**
97 * Runs test cases on X86 CPU if VM supports RTM locking.
98 * @throws Throwable
99 */
100 protected void runX86SupportedVMTestCases() throws Throwable {
101 runGenericX86TestCases();
102 }
103
104 /**
105 * Runs test cases on X86 CPU if VM does not support RTM locking.
106 * @throws Throwable
107 */
108 protected void runX86UnsupportedVMTestCases() throws Throwable {
109 runGenericX86TestCases();
110 }
111
112 /**
113 * Runs test cases on non-X86 CPU.
114 * @throws Throwable
115 */
116 protected void runNonX86TestCases() throws Throwable {
117 CommandLineOptionTest.verifySameJVMStartup(
118 new String[] { errorMessage }, null,
119 String.format("Option '%s' should be unknown on non-X86CPUs.%n"
120 + "JVM startup should fail", optionName), "", ExitCode.FAIL,
121 prepareOptionValue(defaultValue));
122 }
123
124 /**
125 * Runs generic X86 test cases.
126 * @throws Throwable
127 */
128 protected void runGenericX86TestCases() throws Throwable {
129 verifyJVMStartup();
130 verifyOptionValues();
131 }
132
133 protected void verifyJVMStartup() throws Throwable {
134 String optionValue = prepareOptionValue(defaultValue);
135 String shouldFailMessage = String.format("VM option '%s' is "
136 + "experimental.%nVM startup expected to fail without "
137 + "-XX:+UnlockExperimentalVMOptions option", optionName);
138 String shouldPassMessage = String.format("VM option '%s' is "
139 + "experimental%nVM startup should pass with "
140 + "-XX:+UnlockExperimentalVMOptions option", optionName);
141 if (isExperimental) {
142 // verify that option is experimental
143 CommandLineOptionTest.verifySameJVMStartup(
144 new String[] { experimentalOptionError },
145 new String[] { errorMessage }, shouldFailMessage,
146 shouldFailMessage, ExitCode.FAIL, optionValue);
147 // verify that it could be passed if experimental options
148 // are unlocked
149 CommandLineOptionTest.verifySameJVMStartup(null,
150 new String[] {
151 experimentalOptionError,
152 errorMessage
153 },
154 shouldPassMessage,
155 "JVM should start without any warnings or errors",
156 ExitCode.OK,
157 CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
158 optionValue);
159 } else {
160 // verify that option could be passed
161 CommandLineOptionTest.verifySameJVMStartup(null,
162 new String[]{errorMessage},
163 String.format("VM startup shuld pass with '%s' option",
164 optionName),
165 "JVM should start without any warnings or errors",
166 ExitCode.OK, optionValue);
167 }
168 }
169
170 protected void verifyOptionValues() throws Throwable {
171 // verify default value
172 if (isExperimental) {
173 CommandLineOptionTest.verifyOptionValueForSameVM(optionName,
174 defaultValue,
175 String.format("Option '%s' is expected to have '%s' "
176 + "default value", optionName, defaultValue),
177 CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS);
178 } else {
179 CommandLineOptionTest.verifyOptionValueForSameVM(optionName,
180 defaultValue,
181 String.format("Option '%s' is expected to have '%s' "
182 + "default value", optionName, defaultValue));
183 }
184 // verify other specified option values
185 if (optionValues == null) {
186 return;
187 }
188
189 for (String value : optionValues) {
190 if (isExperimental) {
191 CommandLineOptionTest.verifyOptionValueForSameVM(optionName,
192 value,
193 String.format("Option '%s' is set to have '%s' value",
194 optionName, value),
195 CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
196 prepareOptionValue(value));
197 } else {
198 CommandLineOptionTest.verifyOptionValueForSameVM(optionName,
199 value,
200 String.format("Option '%s' is set to have '%s' value",
201 optionName, value), prepareOptionValue(value));
202 }
203 }
204 }
205
206 protected String prepareOptionValue(String value) {
207 if (isBoolean) {
208 return CommandLineOptionTest.prepareBooleanFlag(optionName,
209 Boolean.valueOf(value));
210 } else {
211 return String.format("-XX:%s=%s", optionName, value);
212 }
213 }
214 }