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
26 * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162 8172102 8165405 8174796 8174797 8175304 8167554 8180508 8166232 8196133
27 * @summary Tests for Basic tests for REPL tool
28 * @modules jdk.compiler/com.sun.tools.javac.api
29 * jdk.compiler/com.sun.tools.javac.main
30 * jdk.jdeps/com.sun.tools.javap
31 * jdk.jshell/jdk.internal.jshell.tool
32 * @library /tools/lib
33 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
34 * @build KullaTesting TestingInputStream Compiler
35 * @run testng/timeout=600 ToolBasicTest
36 */
37
38 import java.io.File;
39 import java.io.IOException;
40 import java.io.PrintWriter;
41 import java.io.StringWriter;
42 import java.nio.file.Files;
43 import java.nio.file.Path;
44 import java.nio.file.Paths;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.List;
48 import java.util.Scanner;
49 import java.util.function.BiFunction;
50 import java.util.function.Consumer;
51 import java.util.function.Function;
52 import java.util.stream.Collectors;
53 import java.util.stream.Stream;
54
55 import org.testng.annotations.Test;
56
57 import static org.testng.Assert.assertEquals;
58 import static org.testng.Assert.assertTrue;
59 import static org.testng.Assert.fail;
60
61 @Test
62 public class ToolBasicTest extends ReplToolTesting {
63
64 public void elideStartUpFromList() {
65 test(
66 (a) -> assertCommandOutputContains(a, "123", "==> 123"),
67 (a) -> assertCommandCheckOutput(a, "/list", (s) -> {
68 int cnt;
69 try (Scanner scanner = new Scanner(s)) {
70 cnt = 0;
71 while (scanner.hasNextLine()) {
72 String line = scanner.nextLine();
73 if (!line.trim().isEmpty()) {
74 ++cnt;
75 }
76 }
77 }
78 assertEquals(cnt, 1, "Expected only one listed line");
79 })
80 );
81 }
82
83 public void elideStartUpFromSave() throws IOException {
84 Compiler compiler = new Compiler();
85 Path path = compiler.getPath("myfile");
86 test(
87 (a) -> assertCommandOutputContains(a, "123", "==> 123"),
88 (a) -> assertCommand(a, "/save " + path.toString(), "")
89 );
90 try (Stream<String> lines = Files.lines(path)) {
91 assertEquals(lines.count(), 1, "Expected only one saved line");
92 }
93 }
94
95 public void testInterrupt() {
96 ReplTest interrupt = (a) -> assertCommand(a, "\u0003", "");
97 for (String s : new String[] { "", "\u0003" }) {
98 test(false, new String[]{"--no-startup"},
99 (a) -> assertCommand(a, "int a = 2 +" + s, ""),
100 interrupt,
101 (a) -> assertCommand(a, "int a\u0003", ""),
102 (a) -> assertCommand(a, "int a = 2 + 2\u0003", ""),
103 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
104 (a) -> evaluateExpression(a, "int", "2", "2"),
105 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
106 (a) -> assertCommand(a, "void f() {", ""),
107 (a) -> assertCommand(a, "int q = 10;" + s, ""),
108 interrupt,
109 (a) -> assertCommand(a, "void f() {}\u0003", ""),
110 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
111 (a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
112 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
113 (a) -> assertCommand(a, "class A {" + s, ""),
114 interrupt,
115 (a) -> assertCommand(a, "class A {}\u0003", ""),
116 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
117 (a) -> assertClass(a, "interface A {}", "interface", "A"),
118 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
119 (a) -> assertCommand(a, "import java.util.stream." + s, ""),
120 interrupt,
121 (a) -> assertCommand(a, "import java.util.stream.\u0003", ""),
122 (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
123 (a) -> assertImport(a, "import java.util.stream.Stream", "", "java.util.stream.Stream"),
124 (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
125 );
126 }
127 }
128
129 private final Object lock = new Object();
130 private PrintWriter out;
131 private boolean isStopped;
132 private Thread t;
133 private void assertStop(boolean after, String cmd, String output) {
134 if (!after) {
135 isStopped = false;
136 StringWriter writer = new StringWriter();
137 out = new PrintWriter(writer);
138 setCommandInput(cmd + "\n");
139 t = new Thread(() -> {
140 try {
141 // no chance to know whether cmd is being evaluated
142 Thread.sleep(5000);
143 } catch (InterruptedException ignored) {
144 }
145 int i = 1;
146 int n = 30;
147 synchronized (lock) {
148 do {
149 setCommandInput("\u0003");
150 if (!isStopped) {
151 out.println("Not stopped. Try again: " + i);
152 try {
153 lock.wait(1000);
154 } catch (InterruptedException ignored) {
155 }
156 }
157 } while (i++ < n && !isStopped);
158 if (!isStopped) {
159 System.err.println(writer.toString());
160 fail("Evaluation was not stopped: '" + cmd + "'");
161 }
162 }
163 });
164 t.start();
165 } else {
166 synchronized (lock) {
167 out.println("Evaluation was stopped successfully: '" + cmd + "'");
168 isStopped = true;
169 lock.notify();
170 }
171 try {
172 t.join();
173 t = null;
174 } catch (InterruptedException ignored) {
175 }
176 assertOutput(getCommandOutput(), "", "command");
177 assertOutput(getCommandErrorOutput(), "", "command error");
178 assertOutput(getUserOutput().trim(), output, "user");
179 assertOutput(getUserErrorOutput(), "", "user error");
180 }
181 }
182
183 public void testStop() {
184 test(
185 (a) -> assertStop(a, "while (true) {}", ""),
186 (a) -> assertStop(a, "while (true) { try { Thread.sleep(100); } catch (InterruptedException ex) { } }", "")
187 );
188 }
189
190 public void testRerun() {
191 test(false, new String[] {"--no-startup"},
192 (a) -> assertCommand(a, "/0", "| No snippet with ID: 0"),
193 (a) -> assertCommand(a, "/5", "| No snippet with ID: 5")
194 );
195 String[] codes = new String[] {
196 "int a = 0;", // var
197 "class A {}", // class
198 "void f() {}", // method
199 "bool b;", // active failed
200 "void g() { h(); }", // active corralled
201 };
202 List<ReplTest> tests = new ArrayList<>();
203 for (String s : codes) {
204 tests.add((a) -> assertCommand(a, s, null));
205 }
206 // Test /1 through /5 -- assure references are correct
207 for (int i = 0; i < codes.length; ++i) {
208 final int finalI = i;
209 Consumer<String> check = (s) -> {
210 String[] ss = s.split("\n");
211 assertEquals(ss[0], codes[finalI]);
212 assertTrue(ss.length > 1, s);
213 };
214 tests.add((a) -> assertCommandCheckOutput(a, "/" + (finalI + 1), check));
215 }
216 // Test /-1 ... note that the snippets added by history must be stepped over
217 for (int i = 0; i < codes.length; ++i) {
218 final int finalI = i;
219 Consumer<String> check = (s) -> {
220 String[] ss = s.split("\n");
221 assertEquals(ss[0], codes[codes.length - finalI - 1]);
222 assertTrue(ss.length > 1, s);
223 };
224 tests.add((a) -> assertCommandCheckOutput(a, "/-" + (2 * finalI + 1), check));
225 }
226 tests.add((a) -> assertCommandCheckOutput(a, "/!", assertStartsWith("int a = 0;")));
227 test(false, new String[]{"--no-startup"},
228 tests.toArray(new ReplTest[tests.size()]));
229 }
230
231 public void test8142447() {
232 Function<String, BiFunction<String, Integer, ReplTest>> assertRerun = cmd -> (code, assertionCount) ->
233 (a) -> assertCommandCheckOutput(a, cmd, s -> {
234 String[] ss = s.split("\n");
235 assertEquals(ss[0], code);
236 loadVariable(a, "int", "assertionCount", Integer.toString(assertionCount), Integer.toString(assertionCount));
237 });
238 ReplTest assertVariables = (a) -> assertCommandCheckOutput(a, "/v", assertVariables());
239
240 Compiler compiler = new Compiler();
241 Path startup = compiler.getPath("StartupFileOption/startup.txt");
242 compiler.writeToFile(startup, "int assertionCount = 0;\n" + // id: s1
243 "void add(int n) { assertionCount += n; }");
244 test(new String[]{"--startup", startup.toString()},
245 (a) -> assertCommand(a, "add(1)", ""), // id: 1
246 (a) -> assertCommandCheckOutput(a, "add(ONE)", s -> assertEquals(s.split("\n")[0], "| Error:")), // id: e1
247 (a) -> assertVariable(a, "int", "ONE", "1", "1"),
248 assertRerun.apply("/1").apply("add(1)", 2), assertVariables,
249 assertRerun.apply("/e1").apply("add(ONE)", 3), assertVariables,
250 assertRerun.apply("/s1").apply("int assertionCount = 0;", 0), assertVariables
251 );
252
253 test(false, new String[] {"--no-startup"},
254 (a) -> assertCommand(a, "/s1", "| No snippet with ID: s1"),
255 (a) -> assertCommand(a, "/1", "| No snippet with ID: 1"),
256 (a) -> assertCommand(a, "/e1", "| No snippet with ID: e1")
257 );
258 }
259
260 public void testClasspathDirectory() {
261 Compiler compiler = new Compiler();
262 Path outDir = Paths.get("testClasspathDirectory");
263 compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
264 Path classpath = compiler.getPath(outDir);
265 test(
266 (a) -> assertCommand(a, "/env --class-path " + classpath,
267 "| Setting new options and restoring state."),
268 (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
269 );
270 test(new String[] { "--class-path", classpath.toString() },
271 (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
272 );
273 }
274
275 public void testEnvInStartUp() {
276 Compiler compiler = new Compiler();
277 Path outDir = Paths.get("testClasspathDirectory");
278 compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
279 Path classpath = compiler.getPath(outDir);
280 Path sup = compiler.getPath("startup.jsh");
281 compiler.writeToFile(sup,
282 "int xxx;\n" +
283 "/env -class-path " + classpath + "\n" +
284 "int aaa = 735;\n"
285 );
286 test(
287 (a) -> assertCommand(a, "/set start -retain " + sup, ""),
288 (a) -> assertCommand(a, "/reset",
289 "| Resetting state."),
290 (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A"),
291 (a) -> assertCommand(a, "aaa", "aaa ==> 735")
292 );
293 test(
294 (a) -> assertCommandOutputContains(a, "/env", "--class-path"),
295 (a) -> assertCommandOutputContains(a, "xxx", "cannot find symbol", "variable xxx"),
296 (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A"),
297 (a) -> assertCommand(a, "aaa", "aaa ==> 735")
298 );
299 }
300
301 private String makeSimpleJar() {
302 Compiler compiler = new Compiler();
303 Path outDir = Paths.get("testClasspathJar");
304 compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
305 String jarName = "test.jar";
306 compiler.jar(outDir, jarName, "pkg/A.class");
307 return compiler.getPath(outDir).resolve(jarName).toString();
308 }
309
310 public void testClasspathJar() {
311 String jarPath = makeSimpleJar();
312 test(
313 (a) -> assertCommand(a, "/env --class-path " + jarPath,
314 "| Setting new options and restoring state."),
315 (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
316 );
317 test(new String[] { "--class-path", jarPath },
318 (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
319 );
320 }
321
322 public void testClasspathUserHomeExpansion() {
323 String jarPath = makeSimpleJar();
324 String tilde = "~" + File.separator;
325 test(
326 (a) -> assertCommand(a, "/env --class-path " + tilde + "forblato",
327 "| File '" + Paths.get(System.getProperty("user.home"), "forblato").toString()
328 + "' for '--class-path' is not found."),
329 (a) -> assertCommand(a, "/env --class-path " + jarPath + File.pathSeparator
330 + tilde + "forblato",
331 "| File '" + Paths.get(System.getProperty("user.home"), "forblato").toString()
332 + "' for '--class-path' is not found.")
333 );
334 }
335
336 public void testBadClasspath() {
337 String jarPath = makeSimpleJar();
338 Compiler compiler = new Compiler();
339 Path t1 = compiler.getPath("whatever/thing.zip");
340 compiler.writeToFile(t1, "");
341 Path t2 = compiler.getPath("whatever/thing.jmod");
342 compiler.writeToFile(t2, "");
343 test(
344 (a) -> assertCommand(a, "/env --class-path " + t1.toString(),
345 "| Invalid '--class-path' argument: " + t1.toString()),
346 (a) -> assertCommand(a, "/env --class-path " + jarPath + File.pathSeparator + t1.toString(),
347 "| Invalid '--class-path' argument: " + t1.toString()),
348 (a) -> assertCommand(a, "/env --class-path " + t2.toString(),
349 "| Invalid '--class-path' argument: " + t2.toString())
350 );
351 }
352
353 private String makeBadSourceJar() {
354 Compiler compiler = new Compiler();
355 Path outDir = Paths.get("testClasspathJar");
356 Path src = compiler.getPath(outDir.resolve("pkg/A.java"));
357 compiler.writeToFile(src, "package pkg; /** \u0086 */public class A { public String toString() { return \"A\"; } }");
358 String jarName = "test.jar";
359 compiler.jar(outDir, jarName, "pkg/A.java");
360 return compiler.getPath(outDir).resolve(jarName).toString();
361 }
362
363 public void testBadSourceJarClasspath() {
364 String jarPath = makeBadSourceJar();
365 test(
366 (a) -> assertCommand(a, "/env --class-path " + jarPath,
367 "| Setting new options and restoring state."),
368 (a) -> assertCommandOutputStartsWith(a, "new pkg.A();",
369 "| Error:\n"
370 + "| cannot find symbol\n"
371 + "| symbol: class A")
372 );
373 test(new String[]{"--class-path", jarPath},
374 (a) -> assertCommandOutputStartsWith(a, "new pkg.A();",
375 "| Error:\n"
376 + "| cannot find symbol\n"
377 + "| symbol: class A")
378 );
379 }
380
381 public void testModulePath() {
382 Compiler compiler = new Compiler();
383 Path modsDir = Paths.get("mods");
384 Path outDir = Paths.get("mods", "org.astro");
385 compiler.compile(outDir, "package org.astro; public class World { public static String name() { return \"world\"; } }");
386 compiler.compile(outDir, "module org.astro { exports org.astro; }");
387 Path modsPath = compiler.getPath(modsDir);
388 test(new String[] { "--module-path", modsPath.toString(), "--add-modules", "org.astro" },
389 (a) -> assertCommand(a, "import org.astro.World;", ""),
390 (a) -> evaluateExpression(a, "String",
391 "String.format(\"Greetings %s!\", World.name());",
392 "\"Greetings world!\"")
393 );
394 }
395
396 public void testModulePathUserHomeExpansion() {
397 String tilde = "~" + File.separatorChar;
398 test(
399 (a) -> assertCommand(a, "/env --module-path " + tilde + "snardugol",
400 "| File '" + Paths.get(System.getProperty("user.home"), "snardugol").toString()
401 + "' for '--module-path' is not found.")
402 );
403 }
404
405 public void testBadModulePath() {
406 Compiler compiler = new Compiler();
407 Path t1 = compiler.getPath("whatever/thing.zip");
408 compiler.writeToFile(t1, "");
409 test(
410 (a) -> assertCommand(a, "/env --module-path " + t1.toString(),
411 "| Invalid '--module-path' argument: " + t1.toString())
412 );
413 }
414
415 public void testStartupFileOption() {
416 Compiler compiler = new Compiler();
417 Path startup = compiler.getPath("StartupFileOption/startup.txt");
418 compiler.writeToFile(startup, "class A { public String toString() { return \"A\"; } }");
419 test(new String[]{"--startup", startup.toString()},
420 (a) -> evaluateExpression(a, "A", "new A()", "A")
421 );
422 test(new String[]{"--no-startup"},
423 (a) -> assertCommandCheckOutput(a, "Pattern.compile(\"x+\")", assertStartsWith("| Error:\n| cannot find symbol"))
424 );
425 test(
426 (a) -> assertCommand(a, "Pattern.compile(\"x+\")", "$1 ==> x+", "", null, "", "")
427 );
428 }
429
430 public void testLoadingFromArgs() {
431 Compiler compiler = new Compiler();
432 Path path = compiler.getPath("loading.repl");
433 compiler.writeToFile(path, "int a = 10; double x = 20; double a = 10;");
434 test(new String[] { path.toString() },
435 (a) -> assertCommand(a, "x", "x ==> 20.0"),
436 (a) -> assertCommand(a, "a", "a ==> 10.0")
437 );
438 }
439
440 public void testReset() {
441 test(
442 (a) -> assertReset(a, "/res"),
443 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
444 (a) -> assertVariable(a, "int", "x"),
445 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
446 (a) -> assertMethod(a, "void f() { }", "()void", "f"),
447 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
448 (a) -> assertClass(a, "class A { }", "class", "A"),
449 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
450 (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
451 (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
452 (a) -> assertReset(a, "/reset"),
453 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
454 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
455 (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
456 (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
457 );
458 }
459
460 public void testOpen() {
461 Compiler compiler = new Compiler();
462 Path path = compiler.getPath("testOpen.repl");
463 compiler.writeToFile(path,
464 "int a = 10;\ndouble x = 20;\ndouble a = 10;\n" +
465 "class A { public String toString() { return \"A\"; } }\nimport java.util.stream.*;");
466 for (String s : new String[]{"/o", "/open"}) {
467 test(
468 (a) -> assertCommand(a, s + " " + path.toString(), ""),
469 (a) -> assertCommand(a, "a", "a ==> 10.0"),
470 (a) -> evaluateExpression(a, "A", "new A();", "A"),
471 (a) -> evaluateExpression(a, "long", "Stream.of(\"A\").count();", "1"),
472 (a) -> {
473 loadVariable(a, "double", "x", "20.0", "20.0");
474 loadVariable(a, "double", "a", "10.0", "10.0");
475 loadVariable(a, "A", "$7", "new A();", "A");
476 loadVariable(a, "long", "$8", "Stream.of(\"A\").count();", "1");
477 loadClass(a, "class A { public String toString() { return \"A\"; } }",
478 "class", "A");
479 loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
480 assertCommandCheckOutput(a, "/types", assertClasses());
481 },
482 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
483 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
484 (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
485 );
486 Path unknown = compiler.getPath("UNKNOWN.repl");
487 test(
488 (a) -> assertCommand(a, s + " " + unknown,
489 "| File '" + unknown + "' for '/open' is not found.")
490 );
491 }
492 }
493
494 public void testOpenResource() {
495 test(
496 (a) -> assertCommand(a, "/open PRINTING", ""),
497 (a) -> assertCommandOutputContains(a, "/list",
498 "void println", "System.out.printf"),
499 (a) -> assertCommand(a, "printf(\"%4.2f\", Math.PI)",
500 "", "", null, "3.14", "")
501 );
502 }
503
504 public void testSave() throws IOException {
505 Compiler compiler = new Compiler();
506 Path path = compiler.getPath("testSave.repl");
507 {
508 List<String> list = Arrays.asList(
509 "int a;",
510 "class A { public String toString() { return \"A\"; } }"
511 );
512 test(
513 (a) -> assertVariable(a, "int", "a"),
514 (a) -> assertCommand(a, "()", null, null, null, "", ""),
515 (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
516 (a) -> assertCommand(a, "/save " + path.toString(), "")
517 );
518 assertEquals(Files.readAllLines(path), list);
519 }
520 {
521 List<String> output = new ArrayList<>();
522 test(
523 (a) -> assertCommand(a, "int a;", null),
524 (a) -> assertCommand(a, "()", null, null, null, "", ""),
525 (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
526 (a) -> assertCommandCheckOutput(a, "/list -all", (out) ->
527 output.addAll(Stream.of(out.split("\n"))
528 .filter(str -> !str.isEmpty())
529 .map(str -> str.substring(str.indexOf(':') + 2))
530 .filter(str -> !str.startsWith("/"))
531 .collect(Collectors.toList()))),
532 (a) -> assertCommand(a, "/save -all " + path.toString(), "")
533 );
534 assertEquals(Files.readAllLines(path), output);
535 }
536 {
537 List<String> output = new ArrayList<>();
538 test(
539 (a) -> assertCommand(a, "int a;", null),
540 (a) -> assertCommand(a, "int b;", null),
541 (a) -> assertCommand(a, "int c;", null),
542 (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
543 (a) -> assertCommandCheckOutput(a, "/list b c a A", (out) ->
544 output.addAll(Stream.of(out.split("\n"))
545 .filter(str -> !str.isEmpty())
546 .map(str -> str.substring(str.indexOf(':') + 2))
547 .filter(str -> !str.startsWith("/"))
548 .collect(Collectors.toList()))),
549 (a) -> assertCommand(a, "/save 2-3 1 4 " + path.toString(), "")
550 );
551 assertEquals(Files.readAllLines(path), output);
552 }
553 {
554 List<String> output = new ArrayList<>();
555 test(
556 (a) -> assertVariable(a, "int", "a"),
557 (a) -> assertCommand(a, "()", null, null, null, "", ""),
558 (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
559 (a) -> assertCommandCheckOutput(a, "/history", (out) ->
560 output.addAll(Stream.of(out.split("\n"))
561 .filter(str -> !str.isEmpty())
562 .collect(Collectors.toList()))),
563 (a) -> assertCommand(a, "/save -history " + path.toString(), "")
564 );
565 output.add("/save -history " + path.toString());
566 assertEquals(Files.readAllLines(path), output);
567 }
568 }
569
570 public void testStartRetain() {
571 Compiler compiler = new Compiler();
572 Path startUpFile = compiler.getPath("startUp.txt");
573 test(
574 (a) -> assertVariable(a, "int", "a"),
575 (a) -> assertVariable(a, "double", "b", "10", "10.0"),
576 (a) -> assertMethod(a, "void f() {}", "()V", "f"),
577 (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
578 (a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
579 (a) -> assertCommand(a, "/set start -retain " + startUpFile.toString(), null)
580 );
581 Path unknown = compiler.getPath("UNKNOWN");
582 test(
583 (a) -> assertCommandOutputStartsWith(a, "/set start -retain " + unknown.toString(),
584 "| File '" + unknown + "' for '/set start' is not found.")
585 );
586 test(false, new String[0],
587 (a) -> {
588 loadVariable(a, "int", "a");
589 loadVariable(a, "double", "b", "10.0", "10.0");
590 loadMethod(a, "void f() {}", "()void", "f");
591 loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
592 assertCommandCheckOutput(a, "/types", assertClasses());
593 },
594 (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
595 (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
596 (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
597 );
598 }
599
600 public void testStartSave() throws IOException {
601 Compiler compiler = new Compiler();
602 Path startSave = compiler.getPath("startSave.txt");
603 test(a -> assertCommand(a, "/save -start " + startSave.toString(), null));
604 List<String> lines = Files.lines(startSave)
605 .filter(s -> !s.isEmpty())
606 .collect(Collectors.toList());
607 assertEquals(lines, START_UP);
608 }
609
610 public void testConstrainedUpdates() {
611 test(
612 a -> assertClass(a, "class XYZZY { }", "class", "XYZZY"),
613 a -> assertVariable(a, "XYZZY", "xyzzy"),
614 a -> assertCommandCheckOutput(a, "import java.util.stream.*",
615 (out) -> assertTrue(out.trim().isEmpty(), "Expected no output, got: " + out))
616 );
617 }
618
619 public void testRemoteExit() {
620 test(
621 a -> assertVariable(a, "int", "x"),
622 a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
623 a -> assertCommandOutputContains(a, "System.exit(5);", "terminated"),
624 a -> assertCommandCheckOutput(a, "/vars", s ->
625 assertTrue(s.trim().isEmpty(), s)),
626 a -> assertMethod(a, "void f() { }", "()void", "f"),
627 a -> assertCommandCheckOutput(a, "/methods", assertMethods())
628 );
629 }
630
631 public void testFeedbackNegative() {
632 test(a -> assertCommandCheckOutput(a, "/set feedback aaaa",
633 assertStartsWith("| Does not match any current feedback mode")));
634 }
635
636 public void testFeedbackSilent() {
637 for (String off : new String[]{"s", "silent"}) {
638 test(
639 a -> assertCommand(a, "/set feedback " + off, ""),
640 a -> assertCommand(a, "int a", ""),
641 a -> assertCommand(a, "void f() {}", ""),
642 a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| Error:")),
643 a -> assertCommandCheckOutput(a, "static void f() {}", assertStartsWith("| Warning:"))
644 );
645 }
646 }
647
648 public void testFeedbackNormal() {
649 Compiler compiler = new Compiler();
650 Path testNormalFile = compiler.getPath("testConciseNormal");
651 String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"};
652 String[] sources2 = new String[] {"int a //again", "void f() {int y = 4;}", "class A {} //again", "a = 10"};
653 String[] output = new String[] {
654 "a ==> 0",
655 "| created method f()",
656 "| created class A",
657 "a ==> 10"
658 };
659 compiler.writeToFile(testNormalFile, sources2);
660 for (String feedback : new String[]{"/set fe", "/set feedback"}) {
661 for (String feedbackState : new String[]{"n", "normal"}) {
662 test(
663 a -> assertCommand(a, feedback + " " + feedbackState, "| Feedback mode: normal"),
664 a -> assertCommand(a, sources[0], output[0]),
665 a -> assertCommand(a, sources[1], output[1]),
666 a -> assertCommand(a, sources[2], output[2]),
667 a -> assertCommand(a, sources[3], output[3]),
668 a -> assertCommand(a, "/o " + testNormalFile.toString(), "")
669 );
670 }
671 }
672 }
673
674 public void testVarsWithNotActive() {
675 test(
676 a -> assertVariable(a, "Blath", "x"),
677 a -> assertCommandOutputContains(a, "/var -all", "(not-active)")
678 );
679 }
680
681 public void testHistoryReference() {
682 test(false, new String[]{"--no-startup"},
683 a -> assertCommand(a, "System.err.println(99)", "", "", null, "", "99\n"),
684 a -> assertCommand(a, "/exit", "")
685 );
686 test(false, new String[]{"--no-startup"},
687 a -> assertCommand(a, "System.err.println(1)", "", "", null, "", "1\n"),
688 a -> assertCommand(a, "System.err.println(2)", "", "", null, "", "2\n"),
689 a -> assertCommand(a, "/-2", "System.err.println(1)", "", null, "", "1\n"),
690 a -> assertCommand(a, "/history",
691 "/debug 0\n" +
692 "System.err.println(1)\n" +
693 "System.err.println(2)\n" +
694 "System.err.println(1)\n" +
695 "/history\n"),
696 a -> assertCommand(a, "/history -all",
697 "/debug 0\n" +
698 "System.err.println(99)\n" +
699 "/exit\n" +
700 "/debug 0\n" +
701 "System.err.println(1)\n" +
702 "System.err.println(2)\n" +
703 "System.err.println(1)\n" +
704 "/history\n" +
705 "/history -all\n"),
706 a -> assertCommand(a, "/-2", "System.err.println(2)", "", null, "", "2\n"),
707 a -> assertCommand(a, "/!", "System.err.println(2)", "", null, "", "2\n"),
708 a -> assertCommand(a, "/2", "System.err.println(2)", "", null, "", "2\n"),
709 a -> assertCommand(a, "/1", "System.err.println(1)", "", null, "", "1\n")
710 );
711 }
712
713 public void testRerunIdRange() {
714 Compiler compiler = new Compiler();
715 Path startup = compiler.getPath("rangeStartup");
716 String[] startupSources = new String[] {
717 "boolean go = false",
718 "void println(String s) { if (go) System.out.println(s); }",
719 "void println(int i) { if (go) System.out.println(i); }",
720 "println(\"s4\")",
721 "println(\"s5\")",
722 "println(\"s6\")"
723 };
724 String[] sources = new String[] {
725 "frog",
726 "go = true",
727 "println(2)",
728 "println(3)",
729 "println(4)",
730 "querty"
731 };
732 compiler.writeToFile(startup, startupSources);
733 test(false, new String[]{"--startup", startup.toString()},
734 a -> assertCommandOutputStartsWith(a, sources[0], "| Error:"),
735 a -> assertCommand(a, sources[1], "go ==> true", "", null, "", ""),
736 a -> assertCommand(a, sources[2], "", "", null, "2\n", ""),
737 a -> assertCommand(a, sources[3], "", "", null, "3\n", ""),
738 a -> assertCommand(a, sources[4], "", "", null, "4\n", ""),
739 a -> assertCommandOutputStartsWith(a, sources[5], "| Error:"),
740 a -> assertCommand(a, "/3", "println(3)", "", null, "3\n", ""),
741 a -> assertCommand(a, "/s4", "println(\"s4\")", "", null, "s4\n", ""),
742 a -> assertCommandOutputStartsWith(a, "/e1", "frog\n| Error:"),
743 a -> assertCommand(a, "/2-4",
744 "println(2)\nprintln(3)\nprintln(4)",
745 "", null, "2\n3\n4\n", ""),
746 a -> assertCommand(a, "/s4-s6",
747 startupSources[3] + "\n" +startupSources[4] + "\n" +startupSources[5],
748 "", null, "s4\ns5\ns6\n", ""),
749 a -> assertCommand(a, "/s4-4", null,
750 "", null, "s4\ns5\ns6\n2\n3\n4\n", ""),
751 a -> assertCommandCheckOutput(a, "/e1-e2",
752 s -> {
753 assertTrue(s.trim().startsWith("frog\n| Error:"),
754 "Output: \'" + s + "' does not start with: " + "| Error:");
755 assertTrue(s.trim().lastIndexOf("| Error:") > 10,
756 "Output: \'" + s + "' does not have second: " + "| Error:");
757 }),
758 a -> assertCommand(a, "/4 s4 2",
759 "println(4)\nprintln(\"s4\")\nprintln(2)",
760 "", null, "4\ns4\n2\n", ""),
761 a -> assertCommand(a, "/s5 2-4 3",
762 "println(\"s5\")\nprintln(2)\nprintln(3)\nprintln(4)\nprintln(3)",
763 "", null, "s5\n2\n3\n4\n3\n", ""),
764 a -> assertCommand(a, "/2 ff", "| No such snippet: ff"),
765 a -> assertCommand(a, "/4-2", "| End of snippet range less than start: 4 - 2"),
766 a -> assertCommand(a, "/s5-s3", "| End of snippet range less than start: s5 - s3"),
767 a -> assertCommand(a, "/4-s5", "| End of snippet range less than start: 4 - s5")
768 );
769 }
770
771 @Test(enabled = false) // TODO 8158197
772 public void testHeadlessEditPad() {
773 String prevHeadless = System.getProperty("java.awt.headless");
774 try {
775 System.setProperty("java.awt.headless", "true");
776 test(
777 (a) -> assertCommandOutputStartsWith(a, "/edit printf", "| Cannot launch editor -- unexpected exception:")
778 );
779 } finally {
780 System.setProperty("java.awt.headless", prevHeadless==null? "false" : prevHeadless);
781 }
782 }
783
784 public void testAddExports() {
785 test(false, new String[]{"--no-startup"},
786 a -> assertCommandOutputStartsWith(a, "import jdk.internal.misc.VM;", "| Error:")
787 );
788 test(false, new String[]{"--no-startup",
789 "-R--add-exports", "-Rjava.base/jdk.internal.misc=ALL-UNNAMED",
790 "-C--add-exports", "-Cjava.base/jdk.internal.misc=ALL-UNNAMED"},
791 a -> assertImport(a, "import jdk.internal.misc.VM;", "", "jdk.internal.misc.VM"),
792 a -> assertCommand(a, "System.err.println(VM.isBooted())", "", "", null, "", "true\n")
793 );
794 test(false, new String[]{"--no-startup", "--add-exports", "java.base/jdk.internal.misc"},
795 a -> assertImport(a, "import jdk.internal.misc.VM;", "", "jdk.internal.misc.VM"),
796 a -> assertCommand(a, "System.err.println(VM.isBooted())", "", "", null, "", "true\n")
797 );
798 }
799
800 }
--- EOF ---