1 /* 2 * Copyright (c) 2017, 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 /** 25 * @test 26 * @bug 8177076 8185426 8189595 8188072 8221759 27 * @modules 28 * jdk.compiler/com.sun.tools.javac.api 29 * jdk.compiler/com.sun.tools.javac.main 30 * jdk.jshell/jdk.internal.jshell.tool 31 * jdk.jshell/jdk.internal.jshell.tool.resources:open 32 * jdk.jshell/jdk.jshell:open 33 * @library /tools/lib 34 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask 35 * @build Compiler UITesting 36 * @build ToolTabSnippetTest 37 * @run testng/timeout=300 ToolTabSnippetTest 38 */ 39 40 import java.io.IOException; 41 import java.lang.reflect.Field; 42 import java.nio.file.Files; 43 import java.nio.file.Path; 44 import java.nio.file.Paths; 45 import java.util.Arrays; 46 import java.util.concurrent.CountDownLatch; 47 import java.util.jar.JarEntry; 48 import java.util.jar.JarOutputStream; 49 50 import jdk.internal.jshell.tool.ConsoleIOContextTestSupport; 51 import org.testng.annotations.Test; 52 53 @Test 54 public class ToolTabSnippetTest extends UITesting { 55 ToolTabSnippetTest()56 public ToolTabSnippetTest() { 57 super(true); 58 } 59 testExpression()60 public void testExpression() throws Exception { 61 Path classes = prepareZip(); 62 doRunTest((inputSink, out) -> { 63 inputSink.write("/env -class-path " + classes.toString() + "\n"); 64 waitOutput(out, resource("jshell.msg.set.restore") + "\n\\u001B\\[\\?2004h" + PROMPT); 65 inputSink.write("import jshelltest.*;\n"); 66 waitOutput(out, "\n\\u001B\\[\\?2004l\\u001B\\[\\?2004h" + PROMPT); 67 68 //-> <tab> 69 inputSink.write(TAB); 70 waitOutput(out, getMessage("jshell.console.completion.all.completions.number", "[0-9]+")); 71 inputSink.write(TAB); 72 waitOutput(out, ".*String.*StringBuilder.*" + 73 REDRAW_PROMPT + ""); 74 75 //new JShellTes<tab> 76 inputSink.write("new JShellTes" + TAB); 77 waitOutput(out, "\nJShellTest\\( JShellTestAux\\( " + 78 REDRAW_PROMPT + "new JShellTest"); 79 80 //new JShellTest<tab> 81 inputSink.write(TAB); 82 waitOutput(out, "JShellTest\\( JShellTestAux\\( \n" + 83 "\n" + 84 resource("jshell.console.completion.current.signatures") + "\n" + 85 "jshelltest.JShellTest\n" + 86 "\n" + 87 resource("jshell.console.see.documentation") + 88 REDRAW_PROMPT + "new JShellTest"); 89 inputSink.write(TAB); 90 waitOutput(out, "\\u001B\\[1mjshelltest.JShellTest\\u001B\\[0m\n" + 91 "JShellTest 0" + 92 REDRAW_PROMPT + "new JShellTest"); 93 inputSink.write(TAB); 94 waitOutput(out, "JShellTest\\( JShellTestAux\\( \n" + 95 "\n" + 96 resource("jshell.console.completion.current.signatures") + "\n" + 97 "jshelltest.JShellTest\n" + 98 "\n" + 99 resource("jshell.console.see.documentation") + 100 REDRAW_PROMPT + "new JShellTest"); 101 102 //new JShellTest(<tab> 103 inputSink.write("(" + TAB); 104 waitOutput(out, "\\(\n" + 105 resource("jshell.console.completion.current.signatures") + "\n" + 106 "JShellTest\\(String str\\)\n" + 107 "JShellTest\\(String str, int i\\)\n" + 108 "\n" + 109 resource("jshell.console.see.documentation") + 110 REDRAW_PROMPT + "new JShellTest\\("); 111 inputSink.write(TAB); 112 waitOutput(out, "\\u001B\\[1mJShellTest\\(String str\\)\\u001B\\[0m\n" + 113 "JShellTest 1\n" + 114 "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" + 115 "\n" + 116 resource("jshell.console.see.next.page") + 117 REDRAW_PROMPT + "new JShellTest\\("); 118 inputSink.write(TAB); 119 waitOutput(out, "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" + 120 "\n" + 121 resource("jshell.console.see.next.javadoc") + 122 REDRAW_PROMPT + "new JShellTest\\("); 123 inputSink.write(TAB); 124 waitOutput(out, "\\u001B\\[1mJShellTest\\(String str, int i\\)\\u001B\\[0m\n" + 125 "JShellTest 2\n" + 126 "\n" + 127 getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + 128 REDRAW_PROMPT + "new JShellTest\\("); 129 inputSink.write(TAB); 130 waitOutput(out, ".*String.*StringBuilder.*" + 131 REDRAW_PROMPT + "new JShellTest\\("); 132 133 inputSink.write(INTERRUPT + "String str = \"\";\nnew JShellTest("); 134 waitOutput(out, PROMPT + "new JShellTest\\("); 135 136 inputSink.write(TAB); 137 waitOutput(out, "\n" + 138 "str \n" + 139 "\n" + 140 resource("jshell.console.completion.current.signatures") + "\n" + 141 "JShellTest\\(String str\\)\n" + 142 "JShellTest\\(String str, int i\\)\n" + 143 "\n" + 144 resource("jshell.console.see.documentation") + 145 REDRAW_PROMPT + "new JShellTest\\("); 146 inputSink.write(TAB); 147 waitOutput(out, "\\u001B\\[1mJShellTest\\(String str\\)\\u001B\\[0m\n" + 148 "JShellTest 1\n" + 149 "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" + 150 "\n" + 151 resource("jshell.console.see.next.page") + 152 REDRAW_PROMPT + "new JShellTest\\("); 153 inputSink.write(TAB); 154 waitOutput(out, "1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n1\n" + 155 "\n" + 156 resource("jshell.console.see.next.javadoc") + 157 REDRAW_PROMPT + "new JShellTest\\("); 158 inputSink.write(TAB); 159 waitOutput(out, "\\u001B\\[1mJShellTest\\(String str, int i\\)\\u001B\\[0m\n" + 160 "JShellTest 2\n" + 161 "\n" + 162 getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + 163 REDRAW_PROMPT + "new JShellTest\\("); 164 inputSink.write(TAB); 165 waitOutput(out, ".*String.*StringBuilder.*" + 166 REDRAW_PROMPT + "new JShellTest\\("); 167 168 inputSink.write(INTERRUPT + "JShellTest t = new JShellTest" + TAB); 169 waitOutput(out, PROMPT + "JShellTest t = new JShellTest\n" + 170 "JShellTest\\( \n" + 171 "\n" + 172 resource("jshell.console.completion.current.signatures") + "\n" + 173 "jshelltest.JShellTest\n" + 174 "\n" + 175 resource("jshell.console.completion.all.completions") + 176 REDRAW_PROMPT + "JShellTest t = new JShellTest"); 177 inputSink.write(TAB); 178 waitOutput(out, "JShellTest\\( JShellTestAux\\( \n" + 179 "\n" + 180 resource("jshell.console.see.documentation") + 181 REDRAW_PROMPT + "JShellTest t = new JShellTest"); 182 183 inputSink.write(INTERRUPT + "JShellTest t = new " + TAB); 184 waitOutput(out, PROMPT + "JShellTest t = new \n" + 185 "JShellTest\\( \n" + 186 "\n" + 187 getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + 188 REDRAW_PROMPT + "JShellTest t = new "); 189 inputSink.write(TAB); 190 waitOutput(out, ".*String.*StringBuilder.*" + 191 REDRAW_PROMPT + "JShellTest t = new "); 192 193 inputSink.write(INTERRUPT + "class JShelX{}\n"); 194 inputSink.write("new JShel" + TAB); 195 waitOutput(out, PROMPT + "new JShel\n" + 196 "JShelX\\(\\) JShellTest\\( JShellTestAux\\( " + 197 REDRAW_PROMPT + "new JShel"); 198 199 //no crash: 200 inputSink.write(INTERRUPT + "new Stringbuil" + TAB); 201 waitOutput(out, PROMPT + "new Stringbuil" + BELL); 202 203 //no crash: 8188072 204 inputSink.write(INTERRUPT + "for (int:" + TAB); 205 waitOutput(out, PROMPT + "for \\(int:\n" + 206 getMessage("jshell.console.completion.all.completions.number", "[0-9]+") + 207 REDRAW_PROMPT + "for \\(int:"); 208 }); 209 } 210 testCleaningCompletionTODO()211 public void testCleaningCompletionTODO() throws Exception { 212 doRunTest((inputSink, out) -> { 213 CountDownLatch testCompleteComputationStarted = new CountDownLatch(1); 214 CountDownLatch testCompleteComputationContinue = new CountDownLatch(1); 215 ConsoleIOContextTestSupport.IMPL = new ConsoleIOContextTestSupport() { 216 @Override 217 protected void willComputeCompletionCallback() { 218 if (testCompleteComputationStarted != null) { 219 testCompleteComputationStarted.countDown(); 220 } 221 if (testCompleteComputationContinue != null) { 222 try { 223 testCompleteComputationContinue.await(); 224 } catch (InterruptedException ex) { 225 throw new IllegalStateException(ex); 226 } 227 } 228 } 229 }; 230 //-> <tab> 231 inputSink.write(TAB); 232 testCompleteComputationStarted.await(); 233 //-> <tab><tab> 234 inputSink.write(TAB + TAB); 235 testCompleteComputationContinue.countDown(); 236 waitOutput(out, PROMPT); 237 //-> <tab> 238 inputSink.write(TAB); 239 waitOutput(out, PROMPT); 240 ConsoleIOContextTestSupport.IMPL = null; 241 }); 242 } 243 testNoRepeat()244 public void testNoRepeat() throws Exception { 245 doRunTest((inputSink, out) -> { 246 inputSink.write("String xyzAA;\n"); 247 waitOutput(out, PROMPT); 248 249 //xyz<tab> 250 inputSink.write("String s = xyz" + TAB); 251 waitOutput(out, "^String s = xyzAA"); 252 inputSink.write("."); 253 waitOutput(out, "^\\."); 254 255 inputSink.write(INTERRUPT); 256 waitOutput(out, PROMPT); 257 258 inputSink.write("double xyzAB;\n"); 259 waitOutput(out, PROMPT); 260 261 //xyz<tab> 262 inputSink.write("String s = xyz" + TAB); 263 String allCompletions = 264 resource("jshell.console.completion.all.completions"); 265 waitOutput(out, ".*xyzAA.*" + allCompletions + ".*\u0005String s = xyzA"); 266 }); 267 } 268 testCrash8221759()269 public void testCrash8221759() throws Exception { 270 doRunTest((inputSink, out) -> { 271 inputSink.write("java.io.File.path" + TAB); 272 waitOutput(out, "java.io.File.path\n" + 273 "pathSeparator pathSeparatorChar " + 274 REDRAW_PROMPT + "java.io.File.pathSeparator"); 275 }); 276 } 277 prepareZip()278 private Path prepareZip() { 279 String clazz1 = 280 "package jshelltest;\n" + 281 "/**JShellTest 0" + 282 " */\n" + 283 "public class JShellTest {\n" + 284 " /**JShellTest 1\n" + 285 " * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" + 286 " * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" + 287 " * <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1 <p>1\n" + 288 " */\n" + 289 " public JShellTest(String str) {}\n" + 290 " /**JShellTest 2" + 291 " */\n" + 292 " public JShellTest(String str, int i) {}\n" + 293 "}\n"; 294 295 String clazz2 = 296 "package jshelltest;\n" + 297 "/**JShellTestAux 0" + 298 " */\n" + 299 "public class JShellTestAux {\n" + 300 " /**JShellTest 1" + 301 " */\n" + 302 " public JShellTestAux(String str) { }\n" + 303 " /**JShellTest 2" + 304 " */\n" + 305 " public JShellTestAux(String str, int i) { }\n" + 306 "}\n"; 307 308 Path srcZip = Paths.get("src.zip"); 309 310 try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(srcZip))) { 311 out.putNextEntry(new JarEntry("jshelltest/JShellTest.java")); 312 out.write(clazz1.getBytes()); 313 out.putNextEntry(new JarEntry("jshelltest/JShellTestAux.java")); 314 out.write(clazz2.getBytes()); 315 } catch (IOException ex) { 316 throw new IllegalStateException(ex); 317 } 318 319 compiler.compile(clazz1, clazz2); 320 321 try { 322 Field availableSources = Class.forName("jdk.jshell.SourceCodeAnalysisImpl").getDeclaredField("availableSourcesOverride"); 323 availableSources.setAccessible(true); 324 availableSources.set(null, Arrays.asList(srcZip)); 325 } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException | ClassNotFoundException ex) { 326 throw new IllegalStateException(ex); 327 } 328 329 return compiler.getClassDir(); 330 } 331 //where: 332 private final Compiler compiler = new Compiler(); 333 334 } 335