/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/langtools/jdk/jshell/ToolBasicTest.java
943 строки
43 KB
Christian Stein
8373097: Save command should create missing parent directories
17 дек 2025, 10:18
17 дек 2025, 10:18
e9b4696
Код
Авторство
О чём код?
/* * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @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 8199912 8211694 8223688 8254196 8295984 * @summary Tests for Basic tests for REPL tool * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.jdeps/com.sun.tools.javap * jdk.jshell/jdk.internal.jshell.tool * @library /tools/lib * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask * @build KullaTesting TestingInputStream Compiler * @run junit/timeout=600 ToolBasicTest * @key intermittent */ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Scanner; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import com.sun.net.httpserver.HttpServer; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; public class ToolBasicTest extends ReplToolTesting { @Test public void elideStartUpFromList() { test((a) -> assertCommandOutputContains(a, "123", "==> 123"), (a) -> assertCommandCheckOutput(a, "/list", (s) -> { int cnt; try (Scanner scanner = new Scanner(s)) { cnt = 0; while (scanner.hasNextLine()) { String line = scanner.nextLine(); if (!line.trim().isEmpty()) { ++cnt; } } } assertEquals(1, cnt, "Expected only one listed line"); }) ); } @Test public void elideStartUpFromSave() throws IOException { Compiler compiler = new Compiler(); Path path = compiler.getPath("myfile"); test( (a) -> assertCommandOutputContains(a, "123", "==> 123"), (a) -> assertCommand(a, "/save " + path.toString(), "") ); try (Stream<String> lines = Files.lines(path)) { assertEquals(1, lines.count(), "Expected only one saved line"); } } @Test public void testInterrupt() { ReplTest interrupt = (a) -> assertCommand(a, "\u0003", ""); for (String s : new String[] { "", "\u0003" }) { test(false, new String[]{"--no-startup"}, (a) -> assertCommand(a, "int a = 2 +" + s, ""), interrupt, (a) -> assertCommand(a, "int a\u0003", ""), (a) -> assertCommand(a, "int a = 2 + 2\u0003", ""), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> evaluateExpression(a, "int", "2", "2"), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommand(a, "void f() {", ""), (a) -> assertCommand(a, "int q = 10;" + s, ""), interrupt, (a) -> assertCommand(a, "void f() {}\u0003", ""), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertCommand(a, "class A {" + s, ""), interrupt, (a) -> assertCommand(a, "class A {}\u0003", ""), (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertClass(a, "interface A {}", "interface", "A"), (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertCommand(a, "import java.util.stream." + s, ""), interrupt, (a) -> assertCommand(a, "import java.util.stream.\u0003", ""), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()), (a) -> assertImport(a, "import java.util.stream.Stream", "", "java.util.stream.Stream"), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()) ); } } @Test public void testCtrlD() { test(false, new String[]{"--no-startup"}, a -> { if (!a) { closeCommandInput(); } else { throw new IllegalStateException(); } } ); } private final Object lock = new Object(); private PrintWriter out; private boolean isStopped; private Thread t; private void assertStop(boolean after, String cmd, String output) { if (!after) { isStopped = false; StringWriter writer = new StringWriter(); out = new PrintWriter(writer); setCommandInput(cmd + "\n"); t = new Thread(() -> { int i = 1; int n = 30; synchronized (lock) { do { setCommandInput("\u0003"); if (!isStopped) { out.println("Not stopped. Try again: " + i); try { lock.wait(1000); } catch (InterruptedException ignored) { } } } while (i++ < n && !isStopped); if (!isStopped) { System.err.println(writer.toString()); fail("Evaluation was not stopped: '" + cmd + "'"); } } }); t.start(); } else { synchronized (lock) { out.println("Evaluation was stopped successfully: '" + cmd + "'"); isStopped = true; lock.notify(); } try { t.join(); t = null; } catch (InterruptedException ignored) { } assertOutput(getCommandOutput(), "", "command"); assertOutput(getCommandErrorOutput(), "", "command error"); assertOutput(getUserOutput().trim(), output, "user"); assertOutput(getUserErrorOutput(), "", "user error"); } } @Test public void testStop() { test( (a) -> assertStop(a, "while (true) {}", ""), (a) -> assertStop(a, "while (true) { try { Thread.sleep(100); } catch (InterruptedException ex) { } }", "") ); } @Test public void testRerun() { test(false, new String[] {"--no-startup"}, (a) -> assertCommand(a, "/0", "| No snippet with ID: 0"), (a) -> assertCommand(a, "/5", "| No snippet with ID: 5") ); String[] codes = new String[] { "int a = 0;", // var "class A {}", // class "void f() {}", // method "bool b;", // active failed "void g() { h(); }", // active corralled }; List<ReplTest> tests = new ArrayList<>(); for (String s : codes) { tests.add((a) -> assertCommand(a, s, null)); } // Test /1 through /5 -- assure references are correct for (int i = 0; i < codes.length; ++i) { final int finalI = i; Consumer<String> check = (s) -> { String[] ss = s.split("\n"); assertEquals(codes[finalI], ss[0]); assertTrue(ss.length > 1, s); }; tests.add((a) -> assertCommandCheckOutput(a, "/" + (finalI + 1), check)); } // Test /-1 ... note that the snippets added by history must be stepped over for (int i = 0; i < codes.length; ++i) { final int finalI = i; Consumer<String> check = (s) -> { String[] ss = s.split("\n"); assertEquals(codes[codes.length - finalI - 1], ss[0]); assertTrue(ss.length > 1, s); }; tests.add((a) -> assertCommandCheckOutput(a, "/-" + (2 * finalI + 1), check)); } tests.add((a) -> assertCommandCheckOutput(a, "/!", assertStartsWith("int a = 0;"))); test(false, new String[]{"--no-startup"}, tests.toArray(new ReplTest[tests.size()])); } @Test public void test8142447() { Function<String, BiFunction<String, Integer, ReplTest>> assertRerun = cmd -> (code, assertionCount) -> (a) -> assertCommandCheckOutput(a, cmd, s -> { String[] ss = s.split("\n"); assertEquals(code, ss[0]); loadVariable(a, "int", "assertionCount", Integer.toString(assertionCount), Integer.toString(assertionCount)); }); ReplTest assertVariables = (a) -> assertCommandCheckOutput(a, "/v", assertVariables()); Compiler compiler = new Compiler(); Path startup = compiler.getPath("StartupFileOption/startup.txt"); compiler.writeToFile(startup, "int assertionCount = 0;\n" + // id: s1 "void add(int n) { assertionCount += n; }"); test(new String[]{"--startup", startup.toString()}, (a) -> assertCommand(a, "add(1)", ""), // id: 1 (a) -> assertCommandCheckOutput(a, "add(ONE)", s -> assertEquals("| Error:", s.split("\n")[0])), // id: e1 (a) -> assertVariable(a, "int", "ONE", "1", "1"), assertRerun.apply("/1").apply("add(1)", 2), assertVariables, assertRerun.apply("/e1").apply("add(ONE)", 3), assertVariables, assertRerun.apply("/s1").apply("int assertionCount = 0;", 0), assertVariables ); test(false, new String[] {"--no-startup"}, (a) -> assertCommand(a, "/s1", "| No snippet with ID: s1"), (a) -> assertCommand(a, "/1", "| No snippet with ID: 1"), (a) -> assertCommand(a, "/e1", "| No snippet with ID: e1") ); } @Test public void testClasspathDirectory() { Compiler compiler = new Compiler(); Path outDir = Paths.get("testClasspathDirectory"); compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }"); Path classpath = compiler.getPath(outDir); test( (a) -> assertCommand(a, "/env --class-path " + classpath, "| Setting new options and restoring state."), (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A") ); test(new String[] { "--class-path", classpath.toString() }, (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A") ); } @Test public void testEnvInStartUp() { Compiler compiler = new Compiler(); Path outDir = Paths.get("testClasspathDirectory"); compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }"); Path classpath = compiler.getPath(outDir); Path sup = compiler.getPath("startup.jsh"); compiler.writeToFile(sup, "int xxx;\n" + "/env -class-path " + classpath + "\n" + "int aaa = 735;\n" ); test( (a) -> assertCommand(a, "/set start -retain " + sup, ""), (a) -> assertCommand(a, "/reset", "| Resetting state."), (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A"), (a) -> assertCommand(a, "aaa", "aaa ==> 735") ); test( (a) -> assertCommandOutputContains(a, "/env", "--class-path"), (a) -> assertCommandOutputContains(a, "xxx", "cannot find symbol", "variable xxx"), (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A"), (a) -> assertCommand(a, "aaa", "aaa ==> 735") ); } private String makeSimpleJar() { Compiler compiler = new Compiler(); Path outDir = Paths.get("testClasspathJar"); compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }"); String jarName = "test.jar"; compiler.jar(outDir, jarName, "pkg/A.class"); return compiler.getPath(outDir).resolve(jarName).toString(); } @Test public void testClasspathJar() { String jarPath = makeSimpleJar(); test( (a) -> assertCommand(a, "/env --class-path " + jarPath, "| Setting new options and restoring state."), (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A") ); test(new String[] { "--class-path", jarPath }, (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A") ); } @Test public void testClasspathUserHomeExpansion() { String jarPath = makeSimpleJar(); String tilde = "~" + File.separator; test( (a) -> assertCommand(a, "/env --class-path " + tilde + "forblato", "| File '" + Paths.get(System.getProperty("user.home"), "forblato").toString() + "' for '--class-path' is not found."), (a) -> assertCommand(a, "/env --class-path " + jarPath + File.pathSeparator + tilde + "forblato", "| File '" + Paths.get(System.getProperty("user.home"), "forblato").toString() + "' for '--class-path' is not found.") ); } @Test public void testBadClasspath() { String jarPath = makeSimpleJar(); Compiler compiler = new Compiler(); Path t1 = compiler.getPath("whatever/thing.zip"); compiler.writeToFile(t1, ""); Path t2 = compiler.getPath("whatever/thing.jmod"); compiler.writeToFile(t2, ""); test( (a) -> assertCommand(a, "/env --class-path " + t1.toString(), "| Invalid '--class-path' argument: " + t1.toString()), (a) -> assertCommand(a, "/env --class-path " + jarPath + File.pathSeparator + t1.toString(), "| Invalid '--class-path' argument: " + t1.toString()), (a) -> assertCommand(a, "/env --class-path " + t2.toString(), "| Invalid '--class-path' argument: " + t2.toString()) ); } private String makeBadSourceJar() { Compiler compiler = new Compiler(); Path outDir = Paths.get("testClasspathJar"); Path src = compiler.getPath(outDir.resolve("pkg/A.java")); compiler.writeToFile(src, "package pkg; /** \u0086 */public class A { public String toString() { return \"A\"; } }"); String jarName = "test.jar"; compiler.jar(outDir, jarName, "pkg/A.java"); return compiler.getPath(outDir).resolve(jarName).toString(); } @Test public void testBadSourceJarClasspath() { String jarPath = makeBadSourceJar(); test( (a) -> assertCommand(a, "/env --class-path " + jarPath, "| Setting new options and restoring state."), (a) -> assertCommandOutputStartsWith(a, "new pkg.A();", "| Error:\n" + "| cannot find symbol\n" + "| symbol: class A") ); test(new String[]{"--class-path", jarPath}, (a) -> assertCommandOutputStartsWith(a, "new pkg.A();", "| Error:\n" + "| cannot find symbol\n" + "| symbol: class A") ); } @Test public void testModulePath() { Compiler compiler = new Compiler(); Path modsDir = Paths.get("mods"); Path outDir = Paths.get("mods", "org.astro"); compiler.compile(outDir, "package org.astro; public class World { public static String name() { return \"world\"; } }"); compiler.compile(outDir, "module org.astro { exports org.astro; }"); Path modsPath = compiler.getPath(modsDir); test(new String[] { "--module-path", modsPath.toString(), "--add-modules", "org.astro" }, (a) -> assertCommand(a, "import org.astro.World;", ""), (a) -> evaluateExpression(a, "String", "String.format(\"Greetings %s!\", World.name());", "\"Greetings world!\"") ); } @Test public void testModulePathUserHomeExpansion() { String tilde = "~" + File.separatorChar; test( (a) -> assertCommand(a, "/env --module-path " + tilde + "snardugol", "| File '" + Paths.get(System.getProperty("user.home"), "snardugol").toString() + "' for '--module-path' is not found.") ); } @Test public void testBadModulePath() { Compiler compiler = new Compiler(); Path t1 = compiler.getPath("whatever/thing.zip"); compiler.writeToFile(t1, ""); test( (a) -> assertCommand(a, "/env --module-path " + t1.toString(), "| Invalid '--module-path' argument: " + t1.toString()) ); } @Test public void testStartupFileOption() { Compiler compiler = new Compiler(); Path startup = compiler.getPath("StartupFileOption/startup.txt"); compiler.writeToFile(startup, "class A { public String toString() { return \"A\"; } }"); test(new String[]{"--startup", startup.toString()}, (a) -> evaluateExpression(a, "A", "new A()", "A") ); test(new String[]{"--no-startup"}, (a) -> assertCommandCheckOutput(a, "Pattern.compile(\"x+\")", assertStartsWith("| Error:\n| cannot find symbol")) ); test( (a) -> assertCommand(a, "Pattern.compile(\"x+\")", "$1 ==> x+", "", null, "", "") ); } @Test public void testLoadingFromArgs() { Compiler compiler = new Compiler(); Path path = compiler.getPath("loading.repl"); compiler.writeToFile(path, "int a = 10; double x = 20; double a = 10;"); test(new String[] { path.toString() }, (a) -> assertCommand(a, "x", "x ==> 20.0"), (a) -> assertCommand(a, "a", "a ==> 10.0") ); } @Test public void testReset() { test( (a) -> assertReset(a, "/res"), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertVariable(a, "int", "x"), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertMethod(a, "void f() { }", "()void", "f"), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertClass(a, "class A { }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()), (a) -> assertReset(a, "/reset"), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertCommandCheckOutput(a, "/types", assertClasses()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()) ); } @Test public void testOpen() { Compiler compiler = new Compiler(); Path path = compiler.getPath("testOpen.repl"); compiler.writeToFile(path, "int a = 10;\ndouble x = 20;\ndouble a = 10;\n" + "class A { public String toString() { return \"A\"; } }\nimport java.util.stream.*;"); for (String s : new String[]{"/o", "/open"}) { test( (a) -> assertCommand(a, s + " " + path.toString(), ""), (a) -> assertCommand(a, "a", "a ==> 10.0"), (a) -> evaluateExpression(a, "A", "new A();", "A"), (a) -> evaluateExpression(a, "long", "Stream.of(\"A\").count();", "1"), (a) -> { loadVariable(a, "double", "x", "20.0", "20.0"); loadVariable(a, "double", "a", "10.0", "10.0"); loadVariable(a, "A", "$7", "new A();", "A"); loadVariable(a, "long", "$8", "Stream.of(\"A\").count();", "1"); loadClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"); loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*"); assertCommandCheckOutput(a, "/types", assertClasses()); }, (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()) ); Path unknown = compiler.getPath("UNKNOWN.repl"); test( (a) -> assertCommand(a, s + " " + unknown, "| File '" + unknown + "' for '/open' is not found.") ); } } @Test public void testOpenLocalFileUrl() { Compiler compiler = new Compiler(); Path path = compiler.getPath("testOpen.repl"); compiler.writeToFile(path, "int a = 10;int b = 20;int c = a + b;\n"); for (String s : new String[]{"/o", "/open"}) { test( (a) -> assertCommand(a, s + " " + path.toUri(), ""), (a) -> assertCommand(a, "a", "a ==> 10"), (a) -> assertCommand(a, "b", "b ==> 20"), (a) -> assertCommand(a, "c", "c ==> 30") ); } } @Test public void testOpenFileOverHttp() throws IOException { var script = "int a = 10;int b = 20;int c = a + b;"; var localhostAddress = new InetSocketAddress(InetAddress.getLoopbackAddress().getHostAddress(), 0); var httpServer = HttpServer.create(localhostAddress, 0); try { httpServer.createContext("/script", exchange -> { exchange.sendResponseHeaders(200, script.length()); try (var output = exchange.getResponseBody()) { output.write(script.getBytes()); } }); httpServer.setExecutor(null); httpServer.start(); var urlAddress = "http:/" + httpServer.getAddress().toString() + "/script"; for (String s : new String[]{"/o", "/open"}) { test( (a) -> assertCommand(a, s + " " + urlAddress, ""), (a) -> assertCommand(a, "a", "a ==> 10"), (a) -> assertCommand(a, "b", "b ==> 20"), (a) -> assertCommand(a, "c", "c ==> 30") ); } test(new String[] {urlAddress}, "File '" + urlAddress + "' for 'jshell' is not found.\n"); } finally { httpServer.stop(0); } } @Test public void testOpenResource() { test(new String[]{"-R", "-Duser.language=en", "-R", "-Duser.country=US"}, (a) -> assertCommand(a, "/open PRINTING", ""), (a) -> assertCommandOutputContains(a, "/list", "void println", "System.out.printf"), (a) -> assertCommand(a, "printf(\"%4.2f\", Math.PI)", "", "", null, "3.14", "") ); } @Test public void testSave() throws IOException { Compiler compiler = new Compiler(); Path path = compiler.getPath("testSave.repl"); { Path pathWithDirectories = compiler.getPath("what/ever/testSave.repl"); List<String> list = Arrays.asList( "int a;", "class A { public String toString() { return \"A\"; } }" ); test( (a) -> assertVariable(a, "int", "a"), (a) -> assertCommand(a, "()", null, null, null, "", ""), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommand(a, "/save " + path.toString(), ""), (a) -> assertCommand(a, "/save " + pathWithDirectories.toString(), "") ); assertEquals(list, Files.readAllLines(path)); assertEquals(list, Files.readAllLines(pathWithDirectories)); } { List<String> output = new ArrayList<>(); test( (a) -> assertCommand(a, "int a;", null), (a) -> assertCommand(a, "()", null, null, null, "", ""), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/list -all", (out) -> output.addAll(Stream.of(out.split("\n")) .filter(str -> !str.isEmpty()) .map(str -> str.substring(str.indexOf(':') + 2)) .filter(str -> !str.startsWith("/")) .collect(Collectors.toList()))), (a) -> assertCommand(a, "/save -all " + path.toString(), "") ); assertEquals(output, Files.readAllLines(path)); } { List<String> output = new ArrayList<>(); test( (a) -> assertCommand(a, "int a;", null), (a) -> assertCommand(a, "int b;", null), (a) -> assertCommand(a, "int c;", null), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/list b c a A", (out) -> output.addAll(Stream.of(out.split("\n")) .filter(str -> !str.isEmpty()) .map(str -> str.substring(str.indexOf(':') + 2)) .filter(str -> !str.startsWith("/")) .collect(Collectors.toList()))), (a) -> assertCommand(a, "/save 2-3 1 4 " + path.toString(), "") ); assertEquals(output, Files.readAllLines(path)); } { List<String> output = new ArrayList<>(); test( (a) -> assertVariable(a, "int", "a"), (a) -> assertCommand(a, "()", null, null, null, "", ""), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/history", (out) -> output.addAll(Stream.of(out.split("\n")) .filter(str -> !str.isEmpty()) .collect(Collectors.toList()))), (a) -> assertCommand(a, "/save -history " + path.toString(), "") ); output.add("/save -history " + path.toString()); assertEquals(output, Files.readAllLines(path)); } } @Test public void testStartRetain() { Compiler compiler = new Compiler(); Path startUpFile = compiler.getPath("startUp.txt"); test( (a) -> assertVariable(a, "int", "a"), (a) -> assertVariable(a, "double", "b", "10", "10.0"), (a) -> assertMethod(a, "void f() {}", "()V", "f"), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertCommand(a, "/save " + startUpFile.toString(), null), (a) -> assertCommand(a, "/set start -retain " + startUpFile.toString(), null) ); Path unknown = compiler.getPath("UNKNOWN"); test( (a) -> assertCommandOutputStartsWith(a, "/set start -retain " + unknown.toString(), "| File '" + unknown + "' for '/set start' is not found.") ); test(false, new String[0], (a) -> { loadVariable(a, "int", "a"); loadVariable(a, "double", "b", "10.0", "10.0"); loadMethod(a, "void f() {}", "()void", "f"); loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*"); assertCommandCheckOutput(a, "/types", assertClasses()); }, (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()) ); } @Test public void testStartSave() throws IOException { Compiler compiler = new Compiler(); Path startSave = compiler.getPath("startSave.txt"); test(a -> assertCommand(a, "/save -start " + startSave.toString(), null)); List<String> lines = Files.lines(startSave) .filter(s -> !s.isEmpty()) .collect(Collectors.toList()); assertEquals(START_UP, lines); } @Test public void testConstrainedUpdates() { test( a -> assertClass(a, "class XYZZY { }", "class", "XYZZY"), a -> assertVariable(a, "XYZZY", "xyzzy"), a -> assertCommandCheckOutput(a, "import java.util.stream.*", (out) -> assertTrue(out.trim().isEmpty(), "Expected no output, got: " + out)) ); } @Test public void testRemoteExit() { test( a -> assertVariable(a, "int", "x"), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), a -> assertCommandOutputContains(a, "System.exit(5);", "terminated"), a -> assertCommandCheckOutput(a, "/vars", s -> assertTrue(s.trim().isEmpty(), s)), a -> assertMethod(a, "void f() { }", "()void", "f"), a -> assertCommandCheckOutput(a, "/methods", assertMethods()) ); } @Test public void testFeedbackNegative() { test(a -> assertCommandCheckOutput(a, "/set feedback aaaa", assertStartsWith("| Does not match any current feedback mode"))); } @Test public void testFeedbackSilent() { for (String off : new String[]{"s", "silent"}) { test( a -> assertCommand(a, "/set feedback " + off, ""), a -> assertCommand(a, "int a", ""), a -> assertCommand(a, "void f() {}", ""), a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| Error:")) ); } } @Test public void testFeedbackNormal() { Compiler compiler = new Compiler(); Path testNormalFile = compiler.getPath("testConciseNormal"); String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"}; String[] sources2 = new String[] {"int a //again", "void f() {int y = 4;}", "class A {} //again", "a = 10"}; String[] output = new String[] { "a ==> 0", "| created method f()", "| created class A", "a ==> 10" }; compiler.writeToFile(testNormalFile, sources2); for (String feedback : new String[]{"/set fe", "/set feedback"}) { for (String feedbackState : new String[]{"n", "normal"}) { test( a -> assertCommand(a, feedback + " " + feedbackState, "| Feedback mode: normal"), a -> assertCommand(a, sources[0], output[0]), a -> assertCommand(a, sources[1], output[1]), a -> assertCommand(a, sources[2], output[2]), a -> assertCommand(a, sources[3], output[3]), a -> assertCommand(a, "/o " + testNormalFile.toString(), "") ); } } } @Test public void testVarsWithNotActive() { test( a -> assertVariable(a, "Blath", "x"), a -> assertCommandOutputContains(a, "/var -all", "(not-active)") ); } @Test public void testHistoryReference() { test(false, new String[]{"--no-startup"}, a -> assertCommand(a, "System.err.println(99)", "", "", null, "", "99\n"), a -> assertCommand(a, "/exit", "") ); test(false, new String[]{"--no-startup"}, a -> assertCommand(a, "System.err.println(1)", "", "", null, "", "1\n"), a -> assertCommand(a, "System.err.println(2)", "", "", null, "", "2\n"), a -> assertCommand(a, "/-2", "System.err.println(1)", "", null, "", "1\n"), a -> assertCommand(a, "/history", "/debug 0\n" + "System.err.println(1)\n" + "System.err.println(2)\n" + "System.err.println(1)\n" + "/history\n"), a -> assertCommand(a, "/history -all", "/debug 0\n" + "System.err.println(99)\n" + "/exit\n" + "/debug 0\n" + "System.err.println(1)\n" + "System.err.println(2)\n" + "System.err.println(1)\n" + "/history\n" + "/history -all\n"), a -> assertCommand(a, "/-2", "System.err.println(2)", "", null, "", "2\n"), a -> assertCommand(a, "/!", "System.err.println(2)", "", null, "", "2\n"), a -> assertCommand(a, "/2", "System.err.println(2)", "", null, "", "2\n"), a -> assertCommand(a, "/1", "System.err.println(1)", "", null, "", "1\n") ); } @Test public void testRerunIdRange() { Compiler compiler = new Compiler(); Path startup = compiler.getPath("rangeStartup"); String[] startupSources = new String[] { "boolean go = false", "void println(String s) { if (go) System.out.println(s); }", "void println(int i) { if (go) System.out.println(i); }", "println(\"s4\")", "println(\"s5\")", "println(\"s6\")" }; String[] sources = new String[] { "frog", "go = true", "println(2)", "println(3)", "println(4)", "querty" }; compiler.writeToFile(startup, startupSources); test(false, new String[]{"--startup", startup.toString()}, a -> assertCommandOutputStartsWith(a, sources[0], "| Error:"), a -> assertCommand(a, sources[1], "go ==> true", "", null, "", ""), a -> assertCommand(a, sources[2], "", "", null, "2\n", ""), a -> assertCommand(a, sources[3], "", "", null, "3\n", ""), a -> assertCommand(a, sources[4], "", "", null, "4\n", ""), a -> assertCommandOutputStartsWith(a, sources[5], "| Error:"), a -> assertCommand(a, "/3", "println(3)", "", null, "3\n", ""), a -> assertCommand(a, "/s4", "println(\"s4\")", "", null, "s4\n", ""), a -> assertCommandOutputStartsWith(a, "/e1", "frog\n| Error:"), a -> assertCommand(a, "/2-4", "println(2)\nprintln(3)\nprintln(4)", "", null, "2\n3\n4\n", ""), a -> assertCommand(a, "/s4-s6", startupSources[3] + "\n" +startupSources[4] + "\n" +startupSources[5], "", null, "s4\ns5\ns6\n", ""), a -> assertCommand(a, "/s4-4", null, "", null, "s4\ns5\ns6\n2\n3\n4\n", ""), a -> assertCommandCheckOutput(a, "/e1-e2", s -> { assertTrue(s.trim().startsWith("frog\n| Error:"), "Output: \'" + s + "' does not start with: " + "| Error:"); assertTrue(s.trim().lastIndexOf("| Error:") > 10, "Output: \'" + s + "' does not have second: " + "| Error:"); }), a -> assertCommand(a, "/4 s4 2", "println(4)\nprintln(\"s4\")\nprintln(2)", "", null, "4\ns4\n2\n", ""), a -> assertCommand(a, "/s5 2-4 3", "println(\"s5\")\nprintln(2)\nprintln(3)\nprintln(4)\nprintln(3)", "", null, "s5\n2\n3\n4\n3\n", ""), a -> assertCommand(a, "/2 ff", "| No such snippet: ff"), a -> assertCommand(a, "/4-2", "| End of snippet range less than start: 4 - 2"), a -> assertCommand(a, "/s5-s3", "| End of snippet range less than start: s5 - s3"), a -> assertCommand(a, "/4-s5", "| End of snippet range less than start: 4 - s5") ); } @Test // TODO 8158197 @Disabled public void testHeadlessEditPad() { String prevHeadless = System.getProperty("java.awt.headless"); try { System.setProperty("java.awt.headless", "true"); test( (a) -> assertCommandOutputStartsWith(a, "/edit printf", "| Cannot launch editor -- unexpected exception:") ); } finally { System.setProperty("java.awt.headless", prevHeadless==null? "false" : prevHeadless); } } @Test public void testAddExports() { test(false, new String[]{"--no-startup"}, a -> assertCommandOutputStartsWith(a, "import jdk.internal.misc.VM;", "| Error:") ); test(false, new String[]{"--no-startup", "-R--add-exports", "-Rjava.base/jdk.internal.misc=ALL-UNNAMED", "-C--add-exports", "-Cjava.base/jdk.internal.misc=ALL-UNNAMED"}, a -> assertImport(a, "import jdk.internal.misc.VM;", "", "jdk.internal.misc.VM"), a -> assertCommand(a, "System.err.println(VM.isBooted())", "", "", null, "", "true\n") ); test(false, new String[]{"--no-startup", "--add-exports", "java.base/jdk.internal.misc"}, a -> assertImport(a, "import jdk.internal.misc.VM;", "", "jdk.internal.misc.VM"), a -> assertCommand(a, "System.err.println(VM.isBooted())", "", "", null, "", "true\n") ); } @Test public void testRedeclareVariableNoInit() { test( a -> assertCommand(a, "Integer a;", "a ==> null"), a -> assertCommand(a, "a instanceof Integer;", "$2 ==> false"), a -> assertCommand(a, "a = 1;", "a ==> 1"), a -> assertCommand(a, "Integer a;", "a ==> null"), a -> assertCommand(a, "a instanceof Integer;", "$5 ==> false"), a -> assertCommand(a, "a", "a ==> null") ); } @Test public void testWarningUnchecked() { //8223688 test(false, new String[]{"--no-startup"}, a -> assertCommand(a, "abstract class A<T> { A(T t){} }", "| created class A"), a -> assertCommandCheckOutput(a, "new A(\"\") {}", s -> { assertStartsWith("| Warning:"); assertTrue(s.contains("unchecked call")); assertFalse(s.contains("Exception")); }) ); } @Test public void testIndent() { //8223688 prefsMap.remove("INDENT"); test(false, new String[]{"--no-startup"}, a -> assertCommand(a, "/set indent", "| /set indent 4"), a -> assertCommand(a, "/set indent 2", "| Indent level set to: 2"), a -> assertCommand(a, "/set indent", "| /set indent 2"), a -> assertCommand(a, "/set indent broken", "| Invalid indent level: broken"), a -> assertCommandOutputContains(a, "/set", "| /set indent 2") ); } @Test public void testSystemExitStartUp() { Compiler compiler = new Compiler(); Path startup = compiler.getPath("SystemExitStartUp/startup.txt"); compiler.writeToFile(startup, "int i1 = 0;\n" + "System.exit(0);\n" + "int i2 = 0;\n"); test(Locale.ROOT, true, new String[]{"--startup", startup.toString()}, "State engine terminated.", (a) -> assertCommand(a, "i2", "i2 ==> 0"), (a) -> assertCommandOutputContains(a, "i1", "Error:", "variable i1") ); } }