rev 48074 : 8189102: All tools should support -?, -h and --help
Reviewed-by: kvn, jjg, weijun, alanb, rfield, ksrini
1 /*
2 * Copyright (c) 2015, 2017, 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 /*
25 * @test 8151754 8080883 8160089 8170162 8166581 8172102 8171343 8178023 8186708 8179856 8185840 8190383
26 * @summary Testing startExCe-up options.
27 * @modules jdk.compiler/com.sun.tools.javac.api
28 * jdk.compiler/com.sun.tools.javac.main
29 * jdk.jdeps/com.sun.tools.javap
30 * jdk.jshell/jdk.internal.jshell.tool
31 * @library /tools/lib
32 * @build Compiler toolbox.ToolBox
33 * @run testng StartOptionTest
34 */
35 import java.io.ByteArrayInputStream;
36 import java.io.ByteArrayOutputStream;
37 import java.io.InputStream;
38 import java.io.PrintStream;
39 import java.nio.charset.StandardCharsets;
40 import java.nio.file.Path;
41 import java.util.HashMap;
42 import java.util.Locale;
43 import java.util.function.Consumer;
44
45 import java.util.logging.Level;
46 import java.util.logging.Logger;
47 import org.testng.annotations.AfterMethod;
48 import org.testng.annotations.BeforeMethod;
49 import org.testng.annotations.Test;
50 import jdk.jshell.tool.JavaShellToolBuilder;
51 import static org.testng.Assert.assertEquals;
52 import static org.testng.Assert.assertFalse;
53 import static org.testng.Assert.assertTrue;
54 import static org.testng.Assert.fail;
55
56 @Test
57 public class StartOptionTest {
58
59 protected ByteArrayOutputStream cmdout;
60 protected ByteArrayOutputStream cmderr;
61 protected ByteArrayOutputStream console;
62 protected ByteArrayOutputStream userout;
63 protected ByteArrayOutputStream usererr;
64 protected InputStream cmdInStream;
65
66 private JavaShellToolBuilder builder() {
67 // turn on logging of launch failures
68 Logger.getLogger("jdk.jshell.execution").setLevel(Level.ALL);
69 return JavaShellToolBuilder
70 .builder()
71 .out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout))
72 .err(new PrintStream(cmderr), new PrintStream(usererr))
73 .in(cmdInStream, null)
74 .persistence(new HashMap<>())
75 .env(new HashMap<>())
76 .locale(Locale.ROOT);
77 }
78
79 protected int runShell(String... args) {
80 try {
81 return builder()
82 .start(args);
83 } catch (Exception ex) {
84 fail("Repl tool died with exception", ex);
85 }
86 return -1; // for compiler
87 }
88
89 protected void check(ByteArrayOutputStream str, Consumer<String> checkOut, String label) {
90 byte[] bytes = str.toByteArray();
91 str.reset();
92 String out = new String(bytes, StandardCharsets.UTF_8);
93 if (checkOut != null) {
94 checkOut.accept(out);
95 } else {
96 assertEquals(out, "", label + ": Expected empty -- ");
97 }
98 }
99
100 protected void checkExit(int ec, Consumer<Integer> checkCode) {
101 if (checkCode != null) {
102 checkCode.accept(ec);
103 } else {
104 assertEquals(ec, 0, "Expected standard exit code (0), but found: " + ec);
105 }
106 }
107
108 // Start and check the resultant: exit code (Ex), command output (Co),
109 // user output (Uo), command error (Ce), and console output (Cn)
110 protected void startExCoUoCeCn(Consumer<Integer> checkExitCode,
111 Consumer<String> checkCmdOutput,
112 Consumer<String> checkUserOutput,
113 Consumer<String> checkError,
114 Consumer<String> checkConsole,
115 String... args) {
116 int ec = runShell(args);
117 checkExit(ec, checkExitCode);
118 check(cmdout, checkCmdOutput, "cmdout");
119 check(cmderr, checkError, "cmderr");
120 check(console, checkConsole, "console");
121 check(userout, checkUserOutput, "userout");
122 check(usererr, null, "usererr");
123 }
124
125 // Start with an exit code and command error check
126 protected void startExCe(int eec, Consumer<String> checkError, String... args) {
127 StartOptionTest.this.startExCoUoCeCn(
128 (Integer ec) -> assertEquals((int) ec, eec,
129 "Expected error exit code (" + eec + "), but found: " + ec),
130 null, null, checkError, null, args);
131 }
132
133 // Start with a command output check
134 protected void startCo(Consumer<String> checkCmdOutput, String... args) {
135 StartOptionTest.this.startExCoUoCeCn(null, checkCmdOutput, null, null, null, args);
136 }
137
138 private Consumer<String> assertOrNull(String expected, String label) {
139 return expected == null
140 ? null
141 : s -> assertEquals(s.trim(), expected.trim(), label);
142 }
143
144 // Start and check the resultant: exit code (Ex), command output (Co),
145 // user output (Uo), command error (Ce), and console output (Cn)
146 protected void startExCoUoCeCn(int expectedExitCode,
147 String expectedCmdOutput,
148 String expectedUserOutput,
149 String expectedError,
150 String expectedConsole,
151 String... args) {
152 startExCoUoCeCn(
153 expectedExitCode == 0
154 ? null
155 : (Integer i) -> assertEquals((int) i, expectedExitCode,
156 "Expected exit code (" + expectedExitCode + "), but found: " + i),
157 assertOrNull(expectedCmdOutput, "cmdout: "),
158 assertOrNull(expectedUserOutput, "userout: "),
159 assertOrNull(expectedError, "cmderr: "),
160 assertOrNull(expectedConsole, "console: "),
161 args);
162 }
163
164 // Start with an expected exit code and command error
165 protected void startExCe(int ec, String expectedError, String... args) {
166 startExCoUoCeCn(ec, null, null, expectedError, null, args);
167 }
168
169 // Start with an expected command output
170 protected void startCo(String expectedCmdOutput, String... args) {
171 startExCoUoCeCn(0, expectedCmdOutput, null, null, null, args);
172 }
173
174 // Start with an expected user output
175 protected void startUo(String expectedUserOutput, String... args) {
176 startExCoUoCeCn(0, null, expectedUserOutput, null, null, args);
177 }
178
179 @BeforeMethod
180 public void setUp() {
181 cmdout = new ByteArrayOutputStream();
182 cmderr = new ByteArrayOutputStream();
183 console = new ByteArrayOutputStream();
184 userout = new ByteArrayOutputStream();
185 usererr = new ByteArrayOutputStream();
186 setIn("/exit\n");
187 }
188
189 protected String writeToFile(String stuff) {
190 Compiler compiler = new Compiler();
191 Path p = compiler.getPath("doit.repl");
192 compiler.writeToFile(p, stuff);
193 return p.toString();
194 }
195
196 // Set the input from a String
197 protected void setIn(String s) {
198 cmdInStream = new ByteArrayInputStream(s.getBytes());
199 }
200
201 // Test load files
202 public void testCommandFile() {
203 String fn = writeToFile("String str = \"Hello \"\n" +
204 "/list\n" +
205 "System.out.println(str + str)\n" +
206 "/exit\n");
207 startExCoUoCeCn(0,
208 "1 : String str = \"Hello \";\n",
209 "Hello Hello",
210 null,
211 null,
212 "--no-startup", fn, "-s");
213 }
214
215 // Test that the usage message is printed
216 public void testUsage() {
217 for (String opt : new String[]{"-h", "--help"}) {
218 startCo(s -> {
219 assertTrue(s.split("\n").length >= 7, "Not enough usage lines: " + s);
220 assertTrue(s.startsWith("Usage: jshell <option>..."), "Unexpect usage start: " + s);
221 assertTrue(s.contains("--show-version"), "Expected help: " + s);
222 assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
223 }, opt);
224 }
225 }
226
227 // Test the --help-extra message
228 public void testHelpExtra() {
229 for (String opt : new String[]{"-X", "--help-extra"}) {
230 startCo(s -> {
231 assertTrue(s.split("\n").length >= 5, "Not enough help-extra lines: " + s);
232 assertTrue(s.contains("--add-exports"), "Expected --add-exports: " + s);
233 assertTrue(s.contains("--execution"), "Expected --add-exports: " + s);
234 assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
235 }, opt);
236 }
237 }
238
239 // Test handling of bogus options
240 public void testUnknown() {
241 startExCe(1, "Unknown option: u", "-unknown");
242 startExCe(1, "Unknown option: unknown", "--unknown");
243 }
244
245 // Test that input is read with "-" and there is no extra output.
246 public void testHypenFile() {
247 setIn("System.out.print(\"Hello\");\n");
248 startUo("Hello", "-");
249 setIn("System.out.print(\"Hello\");\n");
250 startUo("Hello", "-", "-");
251 String fn = writeToFile("System.out.print(\"===\");");
252 setIn("System.out.print(\"Hello\");\n");
253 startUo("===Hello===", fn, "-", fn);
254 // check that errors go to standard error
255 setIn(") Foobar");
256 startExCe(0, s -> assertTrue(s.contains("illegal start of expression"),
257 "cmderr: illegal start of expression"),
258 "-");
259 }
260
261 // Test that user specified exit codes are propagated
262 public void testExitCode() {
263 setIn("/exit 57\n");
264 startExCoUoCeCn(57, null, null, null, "-> /exit 57", "-s");
265 setIn("int eight = 8\n" +
266 "/exit eight + \n" +
267 " eight\n");
268 startExCoUoCeCn(16, null, null, null,
269 "-> int eight = 8\n" +
270 "-> /exit eight + \n" +
271 ">> eight",
272 "-s");
273 }
274
275 // Test that non-existent load file sends output to stderr and does not startExCe (no welcome).
276 public void testUnknownLoadFile() {
277 startExCe(1, "File 'UNKNOWN' for 'jshell' is not found.", "UNKNOWN");
278 }
279
280 // Test bad usage of the --startup option
281 public void testStartup() {
282 String fn = writeToFile("");
283 startExCe(1, "Argument to startup missing.", "--startup");
284 startExCe(1, "Conflicting options: both --startup and --no-startup were used.", "--no-startup", "--startup", fn);
285 startExCe(1, "Conflicting options: both --startup and --no-startup were used.", "--startup", fn, "--no-startup");
286 startExCe(1, "Argument to startup missing.", "--no-startup", "--startup");
287 }
288
289 // Test an option that causes the back-end to fail is propagated
290 public void testStartupFailedOption() {
291 startExCe(1, s -> assertTrue(s.contains("Unrecognized option: -hoge-foo-bar"), "cmderr: " + s),
292 "-R-hoge-foo-bar");
293 }
294
295 // Test the use of non-existant files with the --startup option
296 public void testStartupUnknown() {
297 startExCe(1, "File 'UNKNOWN' for '--startup' is not found.", "--startup", "UNKNOWN");
298 startExCe(1, "File 'UNKNOWN' for '--startup' is not found.", "--startup", "DEFAULT", "--startup", "UNKNOWN");
299 }
300
301 // Test bad usage of --class-path option
302 public void testClasspath() {
303 for (String cp : new String[]{"--class-path"}) {
304 startExCe(1, "Only one --class-path option may be used.", cp, ".", "--class-path", ".");
305 startExCe(1, "Argument to class-path missing.", cp);
306 }
307 }
308
309 // Test bogus module on --add-modules option
310 public void testUnknownModule() {
311 startExCe(1, s -> assertTrue(s.contains("rror") && s.contains("unKnown"), "cmderr: " + s),
312 "--add-modules", "unKnown");
313 }
314
315 // Test that muliple feedback options fail
316 public void testFeedbackOptionConflict() {
317 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.",
318 "--feedback", "concise", "--feedback", "verbose");
319 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "concise", "-s");
320 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "verbose", "-q");
321 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "concise", "-v");
322 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-v", "--feedback", "concise");
323 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-v");
324 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-s", "-v");
325 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-v", "-q");
326 startExCe(1, "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-s");
327 }
328
329 // Test bogus arguments to the --feedback option
330 public void testNegFeedbackOption() {
331 startExCe(1, "Argument to feedback missing.", "--feedback");
332 startExCe(1, "Does not match any current feedback mode: blorp -- --feedback blorp", "--feedback", "blorp");
333 }
334
335 // Test --version
336 public void testVersion() {
337 startCo(s -> {
338 assertTrue(s.startsWith("jshell"), "unexpected version: " + s);
339 assertFalse(s.contains("Welcome"), "Unexpected start: " + s);
340 },
341 "--version");
342 }
343
344 // Test --show-version
345 public void testShowVersion() {
346 startExCoUoCeCn(null,
347 s -> {
348 assertTrue(s.startsWith("jshell"), "unexpected version: " + s);
349 assertTrue(s.contains("Welcome"), "Expected start (but got no welcome): " + s);
350 },
351 null,
352 null,
353 s -> assertTrue(s.trim().startsWith("jshell>"), "Expected prompt, got: " + s),
354 "--show-version");
355 }
356
357 @AfterMethod
358 public void tearDown() {
359 cmdout = null;
360 cmderr = null;
361 console = null;
362 userout = null;
363 usererr = null;
364 cmdInStream = null;
365 }
366 }
--- EOF ---