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 26 * @summary Testing start-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 36 import java.io.ByteArrayInputStream; 37 import java.io.ByteArrayOutputStream; 38 import java.io.InputStream; 39 import java.io.PrintStream; 40 import java.nio.charset.StandardCharsets; 41 import java.nio.file.Path; 42 import java.util.HashMap; 43 import java.util.Locale; 44 import java.util.function.Consumer; 45 46 import java.util.logging.Level; 47 import java.util.logging.Logger; 48 import org.testng.annotations.AfterMethod; 49 import org.testng.annotations.BeforeMethod; 50 import org.testng.annotations.Test; 51 import jdk.jshell.tool.JavaShellToolBuilder; 52 import static org.testng.Assert.assertEquals; 53 import static org.testng.Assert.assertFalse; 54 import static org.testng.Assert.assertTrue; 55 import static org.testng.Assert.fail; 56 57 @Test 58 public class StartOptionTest { 59 60 private ByteArrayOutputStream cmdout; 61 private ByteArrayOutputStream cmderr; 62 private ByteArrayOutputStream console; 63 private ByteArrayOutputStream userout; 64 private ByteArrayOutputStream usererr; 65 private InputStream cmdInStream; 66 67 private JavaShellToolBuilder builder() { 68 // turn on logging of launch failures 69 Logger.getLogger("jdk.jshell.execution").setLevel(Level.ALL); 70 return JavaShellToolBuilder 71 .builder() 72 .out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout)) 73 .err(new PrintStream(cmderr), new PrintStream(usererr)) 74 .in(cmdInStream, null) 75 .persistence(new HashMap<>()) 76 .env(new HashMap<>()) 77 .locale(Locale.ROOT); 78 } 79 80 private void runShell(String... args) { 81 try { 82 builder() 83 .run(args); 84 } catch (Exception ex) { 85 fail("Repl tool died with exception", ex); 86 } 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 start(Consumer<String> checkCmdOutput, 101 Consumer<String> checkUserOutput, Consumer<String> checkError, 102 String... args) throws Exception { 103 runShell(args); 104 check(cmdout, checkCmdOutput, "cmdout"); 105 check(cmderr, checkError, "cmderr"); 106 check(console, null, "console"); 107 check(userout, checkUserOutput, "userout"); 108 check(usererr, null, "usererr"); 109 } 110 111 protected void start(String expectedCmdOutput, String expectedError, String... args) throws Exception { 112 startWithUserOutput(expectedCmdOutput, "", expectedError, args); 113 } 114 115 private void startWithUserOutput(String expectedCmdOutput, String expectedUserOutput, 116 String expectedError, String... args) throws Exception { 117 start( 118 s -> assertEquals(s.trim(), expectedCmdOutput, "cmdout: "), 119 s -> assertEquals(s.trim(), expectedUserOutput, "userout: "), 120 s -> assertEquals(s.trim(), expectedError, "cmderr: "), 121 args); 122 } 123 124 @BeforeMethod 125 public void setUp() { 126 cmdout = new ByteArrayOutputStream(); 127 cmderr = new ByteArrayOutputStream(); 128 console = new ByteArrayOutputStream(); 129 userout = new ByteArrayOutputStream(); 130 usererr = new ByteArrayOutputStream(); 131 cmdInStream = new ByteArrayInputStream("/exit\n".getBytes()); 132 } 133 134 protected String writeToFile(String stuff) throws Exception { 135 Compiler compiler = new Compiler(); 136 Path p = compiler.getPath("doit.repl"); 137 compiler.writeToFile(p, stuff); 138 return p.toString(); 139 } 140 141 public void testCommandFile() throws Exception { 142 String fn = writeToFile("String str = \"Hello \"\n/list\nSystem.out.println(str + str)\n/exit\n"); 143 startWithUserOutput("1 : String str = \"Hello \";", "Hello Hello", "", "--no-startup", fn, "-s"); 144 } 145 146 public void testUsage() throws Exception { 147 for (String opt : new String[]{"-h", "--help"}) { 148 start(s -> { 149 assertTrue(s.split("\n").length >= 7, "Not enough usage lines: " + s); 150 assertTrue(s.startsWith("Usage: jshell <option>..."), "Unexpect usage start: " + s); 151 assertTrue(s.contains("--show-version"), "Expected help: " + s); 152 assertFalse(s.contains("Welcome"), "Unexpected start: " + s); 153 }, null, null, opt); 154 } 155 } 156 157 public void testHelpExtra() throws Exception { 158 for (String opt : new String[]{"-X", "--help-extra"}) { 159 start(s -> { 160 assertTrue(s.split("\n").length >= 5, "Not enough help-extra lines: " + s); 161 assertTrue(s.contains("--add-exports"), "Expected --add-exports: " + s); 162 assertTrue(s.contains("--execution"), "Expected --add-exports: " + s); 163 assertFalse(s.contains("Welcome"), "Unexpected start: " + s); 164 }, null, null, opt); 165 } 166 } 167 168 public void testUnknown() throws Exception { 169 start(null, null, 170 s -> assertEquals(s.trim(), "Unknown option: u"), "-unknown"); 171 start(null, null, 172 s -> assertEquals(s.trim(), "Unknown option: unknown"), "--unknown"); 173 } 174 175 /** 176 * Test that input is read with "-" and there is no extra output. 177 * @throws Exception 178 */ 179 public void testHypenFile() throws Exception { 180 cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes()); 181 startWithUserOutput("", "Hello", "", "-"); 182 cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes()); 183 startWithUserOutput("", "Hello", "", "-", "-"); 184 Compiler compiler = new Compiler(); 185 Path path = compiler.getPath("markload.jsh"); 186 compiler.writeToFile(path, "System.out.print(\"===\");"); 187 cmdInStream = new ByteArrayInputStream("System.out.print(\"Hello\");\n".getBytes()); 188 startWithUserOutput("", "===Hello===", "", path.toString(), "-", path.toString()); 189 // check that errors go to standard error 190 cmdInStream = new ByteArrayInputStream(") Foobar".getBytes()); 191 start( 192 s -> assertEquals(s.trim(), "", "cmdout: empty"), 193 s -> assertEquals(s.trim(), "", "userout: empty"), 194 s -> assertTrue(s.contains("illegal start of expression"), 195 "cmderr: illegal start of expression"), 196 "-"); 197 } 198 199 /** 200 * Test that non-existent load file sends output to stderr and does not start (no welcome). 201 * @throws Exception 202 */ 203 public void testUnknownLoadFile() throws Exception { 204 start("", "File 'UNKNOWN' for 'jshell' is not found.", "UNKNOWN"); 205 } 206 207 public void testStartup() throws Exception { 208 Compiler compiler = new Compiler(); 209 Path p = compiler.getPath("file.txt"); 210 compiler.writeToFile(p); 211 start("", "Argument to startup missing.", "--startup"); 212 start("", "Conflicting options: both --startup and --no-startup were used.", "--no-startup", "--startup", p.toString()); 213 start("", "Conflicting options: both --startup and --no-startup were used.", "--startup", p.toString(), "--no-startup"); 214 start("", "Argument to startup missing.", "--no-startup", "--startup"); 215 } 216 217 public void testStartupFailedOption() throws Exception { 218 start( 219 s -> assertEquals(s.trim(), "", "cmdout: "), 220 s -> assertEquals(s.trim(), "", "userout: "), 221 s -> assertTrue(s.contains("Unrecognized option: -hoge-foo-bar"), "cmderr: " + s), 222 "-R-hoge-foo-bar"); 223 } 224 225 public void testStartupUnknown() throws Exception { 226 start("", "File 'UNKNOWN' for '--startup' is not found.", "--startup", "UNKNOWN"); 227 start("", "File 'UNKNOWN' for '--startup' is not found.", "--startup", "DEFAULT", "--startup", "UNKNOWN"); 228 } 229 230 public void testClasspath() throws Exception { 231 for (String cp : new String[] {"--class-path"}) { 232 start("", "Only one --class-path option may be used.", cp, ".", "--class-path", "."); 233 start("", "Argument to class-path missing.", cp); 234 } 235 } 236 237 public void testUnknownModule() throws Exception { 238 start( 239 s -> assertEquals(s.trim(), "", "cmdout: "), 240 s -> assertEquals(s.trim(), "", "userout: "), 241 s -> assertTrue(s.contains("rror") && s.contains("unKnown"), "cmderr: " + s), 242 "--add-modules", "unKnown"); 243 } 244 245 public void testFeedbackOptionConflict() throws Exception { 246 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", 247 "--feedback", "concise", "--feedback", "verbose"); 248 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "concise", "-s"); 249 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "verbose", "-q"); 250 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "--feedback", "concise", "-v"); 251 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-v", "--feedback", "concise"); 252 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-v"); 253 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-s", "-v"); 254 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-v", "-q"); 255 start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-s"); 256 } 257 258 public void testNegFeedbackOption() throws Exception { 259 start("", "Argument to feedback missing.", "--feedback"); 260 start("", "Does not match any current feedback mode: blorp -- --feedback blorp", "--feedback", "blorp"); 261 } 262 263 public void testVersion() throws Exception { 264 start( 265 s -> { 266 assertTrue(s.startsWith("jshell"), "unexpected version: " + s); 267 assertFalse(s.contains("Welcome"), "Unexpected start: " + s); 268 }, 269 null, null, 270 "--version"); 271 } 272 273 public void testShowVersion() throws Exception { 274 runShell("--show-version"); 275 check(cmdout, 276 s -> { 277 assertTrue(s.startsWith("jshell"), "unexpected version: " + s); 278 assertTrue(s.contains("Welcome"), "Expected start (but got no welcome): " + s); 279 }, 280 "cmdout"); 281 check(cmderr, null, "cmderr"); 282 check(console, 283 s -> assertTrue(s.trim().startsWith("jshell>"), "Expected prompt, got: " + s), 284 "console"); 285 check(userout, null, "userout"); 286 check(usererr, null, "usererr"); 287 } 288 289 @AfterMethod 290 public void tearDown() { 291 cmdout = null; 292 cmderr = null; 293 console = null; 294 userout = null; 295 usererr = null; 296 cmdInStream = null; 297 } 298 }