ToolBasicTest.java revision 3339:73717a51063b
1230557Sjimharris/*
2230557Sjimharris * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3230557Sjimharris * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4230557Sjimharris *
5230557Sjimharris * This code is free software; you can redistribute it and/or modify it
6230557Sjimharris * under the terms of the GNU General Public License version 2 only, as
7230557Sjimharris * published by the Free Software Foundation.
8230557Sjimharris *
9230557Sjimharris * This code is distributed in the hope that it will be useful, but WITHOUT
10230557Sjimharris * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11230557Sjimharris * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12230557Sjimharris * version 2 for more details (a copy is included in the LICENSE file that
13230557Sjimharris * accompanied this code).
14230557Sjimharris *
15230557Sjimharris * You should have received a copy of the GNU General Public License version
16230557Sjimharris * 2 along with this work; if not, write to the Free Software Foundation,
17230557Sjimharris * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18230557Sjimharris *
19230557Sjimharris * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20230557Sjimharris * or visit www.oracle.com if you need additional information or have any
21230557Sjimharris * questions.
22230557Sjimharris */
23230557Sjimharris
24230557Sjimharris/*
25230557Sjimharris * @test
26230557Sjimharris * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955
27230557Sjimharris * @summary Tests for Basic tests for REPL tool
28230557Sjimharris * @requires os.family != "solaris"
29230557Sjimharris * @modules jdk.compiler/com.sun.tools.javac.api
30230557Sjimharris *          jdk.compiler/com.sun.tools.javac.main
31230557Sjimharris *          jdk.jdeps/com.sun.tools.javap
32230557Sjimharris *          jdk.jshell/jdk.internal.jshell.tool
33230557Sjimharris * @library /tools/lib
34230557Sjimharris * @ignore 8139873
35230557Sjimharris * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
36230557Sjimharris * @build KullaTesting TestingInputStream Compiler
37230557Sjimharris * @run testng/timeout=600 ToolBasicTest
38230557Sjimharris */
39230557Sjimharris
40230557Sjimharrisimport java.io.FileInputStream;
41230557Sjimharrisimport java.io.IOException;
42230557Sjimharrisimport java.io.PrintWriter;
43230557Sjimharrisimport java.io.StringWriter;
44230557Sjimharrisimport java.nio.file.Files;
45230557Sjimharrisimport java.nio.file.Path;
46230557Sjimharrisimport java.nio.file.Paths;
47230557Sjimharrisimport java.util.ArrayList;
48230557Sjimharrisimport java.util.Arrays;
49230557Sjimharrisimport java.util.List;
50230557Sjimharrisimport java.util.Locale;
51230557Sjimharrisimport java.util.Scanner;
52230557Sjimharrisimport java.util.function.BiFunction;
53230557Sjimharrisimport java.util.function.Consumer;
54230557Sjimharrisimport java.util.function.Function;
55230557Sjimharrisimport java.util.prefs.BackingStoreException;
56230557Sjimharrisimport java.util.prefs.Preferences;
57230557Sjimharrisimport java.util.stream.Collectors;
58230557Sjimharrisimport java.util.stream.Stream;
59230557Sjimharris
60230557Sjimharrisimport org.testng.annotations.Test;
61230557Sjimharris
62230557Sjimharrisimport static org.testng.Assert.assertEquals;
63230557Sjimharrisimport static org.testng.Assert.assertTrue;
64230557Sjimharrisimport static org.testng.Assert.fail;
65230557Sjimharris
66230557Sjimharris@Test
67230557Sjimharrispublic class ToolBasicTest extends ReplToolTesting {
68230557Sjimharris
69230557Sjimharris    public void elideStartUpFromList() {
70230557Sjimharris        test(
71230557Sjimharris                (a) -> assertCommandOutputContains(a, "123", "type int"),
72230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/list", (s) -> {
73230557Sjimharris                    int cnt;
74230557Sjimharris                    try (Scanner scanner = new Scanner(s)) {
75230557Sjimharris                        cnt = 0;
76230557Sjimharris                        while (scanner.hasNextLine()) {
77230557Sjimharris                            String line = scanner.nextLine();
78230557Sjimharris                            if (!line.trim().isEmpty()) {
79230557Sjimharris                                ++cnt;
80230557Sjimharris                            }
81230557Sjimharris                        }
82230557Sjimharris                    }
83230557Sjimharris                    assertEquals(cnt, 1, "Expected only one listed line");
84230557Sjimharris                })
85230557Sjimharris        );
86230557Sjimharris    }
87230557Sjimharris
88230557Sjimharris    public void elideStartUpFromSave() throws IOException {
89230557Sjimharris        Compiler compiler = new Compiler();
90230557Sjimharris        Path path = compiler.getPath("myfile");
91230557Sjimharris        test(
92230557Sjimharris                (a) -> assertCommandOutputContains(a, "123", "type int"),
93230557Sjimharris                (a) -> assertCommand(a, "/save " + path.toString(), "")
94230557Sjimharris        );
95230557Sjimharris        try (Stream<String> lines = Files.lines(path)) {
96230557Sjimharris            assertEquals(lines.count(), 1, "Expected only one saved line");
97230557Sjimharris        }
98230557Sjimharris    }
99230557Sjimharris
100230557Sjimharris    public void testInterrupt() {
101230557Sjimharris        ReplTest interrupt = (a) -> assertCommand(a, "\u0003", "");
102230557Sjimharris        for (String s : new String[] { "", "\u0003" }) {
103230557Sjimharris            test(false, new String[]{"-nostartup"},
104230557Sjimharris                    (a) -> assertCommand(a, "int a = 2 +" + s, ""),
105230557Sjimharris                    interrupt,
106230557Sjimharris                    (a) -> assertCommand(a, "int a\u0003", ""),
107230557Sjimharris                    (a) -> assertCommand(a, "int a = 2 + 2\u0003", ""),
108230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
109230557Sjimharris                    (a) -> evaluateExpression(a, "int", "2", "2"),
110230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
111230557Sjimharris                    (a) -> assertCommand(a, "void f() {", ""),
112230557Sjimharris                    (a) -> assertCommand(a, "int q = 10;" + s, ""),
113230557Sjimharris                    interrupt,
114230557Sjimharris                    (a) -> assertCommand(a, "void f() {}\u0003", ""),
115230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
116230557Sjimharris                    (a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
117230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
118230557Sjimharris                    (a) -> assertCommand(a, "class A {" + s, ""),
119230557Sjimharris                    interrupt,
120230557Sjimharris                    (a) -> assertCommand(a, "class A {}\u0003", ""),
121230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
122230557Sjimharris                    (a) -> assertClass(a, "interface A {}", "interface", "A"),
123230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
124230557Sjimharris                    (a) -> assertCommand(a, "import java.util.stream." + s, ""),
125230557Sjimharris                    interrupt,
126230557Sjimharris                    (a) -> assertCommand(a, "import java.util.stream.\u0003", ""),
127230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
128230557Sjimharris                    (a) -> assertImport(a, "import java.util.stream.Stream", "", "java.util.stream.Stream"),
129230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
130230557Sjimharris            );
131230557Sjimharris        }
132230557Sjimharris    }
133230557Sjimharris
134230557Sjimharris    private final Object lock = new Object();
135230557Sjimharris    private PrintWriter out;
136230557Sjimharris    private boolean isStopped;
137230557Sjimharris    private Thread t;
138230557Sjimharris    private void assertStop(boolean after, String cmd, String output) {
139230557Sjimharris        if (!after) {
140230557Sjimharris            isStopped = false;
141230557Sjimharris            StringWriter writer = new StringWriter();
142230557Sjimharris            out = new PrintWriter(writer);
143230557Sjimharris            setCommandInput(cmd + "\n");
144230557Sjimharris            t = new Thread(() -> {
145230557Sjimharris                try {
146230557Sjimharris                    // no chance to know whether cmd is being evaluated
147230557Sjimharris                    Thread.sleep(5000);
148230557Sjimharris                } catch (InterruptedException ignored) {
149230557Sjimharris                }
150230557Sjimharris                int i = 1;
151230557Sjimharris                int n = 30;
152230557Sjimharris                synchronized (lock) {
153230557Sjimharris                    do {
154230557Sjimharris                        setCommandInput("\u0003");
155230557Sjimharris                        if (!isStopped) {
156230557Sjimharris                            out.println("Not stopped. Try again: " + i);
157230557Sjimharris                            try {
158230557Sjimharris                                lock.wait(1000);
159230557Sjimharris                            } catch (InterruptedException ignored) {
160230557Sjimharris                            }
161230557Sjimharris                        }
162230557Sjimharris                    } while (i++ < n && !isStopped);
163230557Sjimharris                    if (!isStopped) {
164230557Sjimharris                        System.err.println(writer.toString());
165230557Sjimharris                        fail("Evaluation was not stopped: '" + cmd + "'");
166230557Sjimharris                    }
167230557Sjimharris                }
168230557Sjimharris            });
169230557Sjimharris            t.start();
170230557Sjimharris        } else {
171230557Sjimharris            synchronized (lock)  {
172230557Sjimharris                out.println("Evaluation was stopped successfully: '" + cmd + "'");
173230557Sjimharris                isStopped = true;
174230557Sjimharris                lock.notify();
175230557Sjimharris            }
176230557Sjimharris            try {
177230557Sjimharris                t.join();
178230557Sjimharris                t = null;
179230557Sjimharris            } catch (InterruptedException ignored) {
180230557Sjimharris            }
181230557Sjimharris            assertOutput(getCommandOutput(), "", "command");
182230557Sjimharris            assertOutput(getCommandErrorOutput(), "", "command error");
183230557Sjimharris            assertOutput(getUserOutput().trim(), output, "user");
184230557Sjimharris            assertOutput(getUserErrorOutput(), "", "user error");
185230557Sjimharris        }
186230557Sjimharris    }
187230557Sjimharris
188230557Sjimharris    public void testStop() {
189230557Sjimharris        test(
190230557Sjimharris                (a) -> assertStop(a, "while (true) {}", "Killed."),
191230557Sjimharris                (a) -> assertStop(a, "while (true) { try { Thread.sleep(100); } catch (InterruptedException ex) { } }", "Killed.")
192230557Sjimharris        );
193230557Sjimharris    }
194230557Sjimharris
195230557Sjimharris    @Test(enabled = false) // TODO 8130450
196230557Sjimharris    public void testRerun() {
197230557Sjimharris        test(false, new String[] {"-nostartup"},
198230557Sjimharris                (a) -> assertCommand(a, "/0", "|  No such command or snippet id: /0\n|  Type /help for help."),
199230557Sjimharris                (a) -> assertCommand(a, "/5", "|  No such command or snippet id: /5\n|  Type /help for help.")
200230557Sjimharris        );
201230557Sjimharris        String[] codes = new String[] {
202230557Sjimharris                "int a = 0;", // var
203230557Sjimharris                "class A {}", // class
204230557Sjimharris                "void f() {}", // method
205230557Sjimharris                "bool b;", // active failed
206230557Sjimharris                "void g() { h(); }", // active corralled
207230557Sjimharris        };
208230557Sjimharris        List<ReplTest> tests = new ArrayList<>();
209230557Sjimharris        for (String s : codes) {
210230557Sjimharris            tests.add((a) -> assertCommand(a, s, null));
211230557Sjimharris        }
212230557Sjimharris        for (int i = 0; i < codes.length; ++i) {
213230557Sjimharris            final int finalI = i;
214230557Sjimharris            Consumer<String> check = (s) -> {
215230557Sjimharris                String[] ss = s.split("\n");
216230557Sjimharris                assertEquals(ss[0], codes[finalI]);
217230557Sjimharris                assertTrue(ss.length > 1, s);
218230557Sjimharris            };
219230557Sjimharris            tests.add((a) -> assertCommandCheckOutput(a, "/" + (finalI + 1), check));
220230557Sjimharris        }
221230557Sjimharris        for (int i = 0; i < codes.length; ++i) {
222230557Sjimharris            final int finalI = i;
223230557Sjimharris            Consumer<String> check = (s) -> {
224230557Sjimharris                String[] ss = s.split("\n");
225230557Sjimharris                assertEquals(ss[0], codes[codes.length - finalI - 1]);
226230557Sjimharris                assertTrue(ss.length > 1, s);
227230557Sjimharris            };
228230557Sjimharris            tests.add((a) -> assertCommandCheckOutput(a, "/-" + (finalI + 1), check));
229230557Sjimharris        }
230230557Sjimharris        tests.add((a) -> assertCommandCheckOutput(a, "/!", assertStartsWith("void g() { h(); }")));
231230557Sjimharris        test(false, new String[]{"-nostartup"},
232230557Sjimharris                tests.toArray(new ReplTest[tests.size()]));
233230557Sjimharris    }
234230557Sjimharris
235230557Sjimharris    public void test8142447() {
236230557Sjimharris        Function<String, BiFunction<String, Integer, ReplTest>> assertRerun = cmd -> (code, assertionCount) ->
237230557Sjimharris                (a) -> assertCommandCheckOutput(a, cmd, s -> {
238230557Sjimharris                            String[] ss = s.split("\n");
239230557Sjimharris                            assertEquals(ss[0], code);
240230557Sjimharris                            loadVariable(a, "int", "assertionCount", Integer.toString(assertionCount), Integer.toString(assertionCount));
241230557Sjimharris                        });
242230557Sjimharris        ReplTest assertVariables = (a) -> assertCommandCheckOutput(a, "/v", assertVariables());
243230557Sjimharris
244230557Sjimharris        Compiler compiler = new Compiler();
245230557Sjimharris        Path startup = compiler.getPath("StartupFileOption/startup.txt");
246230557Sjimharris        compiler.writeToFile(startup, "int assertionCount = 0;\n" + // id: s1
247230557Sjimharris                "void add(int n) { assertionCount += n; }");
248230557Sjimharris        test(new String[]{"-startup", startup.toString()},
249230557Sjimharris                (a) -> assertCommand(a, "add(1)", ""), // id: 1
250230557Sjimharris                (a) -> assertCommandCheckOutput(a, "add(ONE)", s -> assertEquals(s.split("\n")[0], "|  Error:")), // id: e1
251230557Sjimharris                (a) -> assertVariable(a, "int", "ONE", "1", "1"),
252230557Sjimharris                assertRerun.apply("/1").apply("add(1)", 2), assertVariables,
253230557Sjimharris                assertRerun.apply("/e1").apply("add(ONE)", 3), assertVariables,
254230557Sjimharris                assertRerun.apply("/s1").apply("int assertionCount = 0;", 0), assertVariables
255230557Sjimharris        );
256230557Sjimharris
257230557Sjimharris        test(false, new String[] {"-nostartup"},
258230557Sjimharris                (a) -> assertCommand(a, "/s1", "|  No such command or snippet id: /s1\n|  Type /help for help."),
259230557Sjimharris                (a) -> assertCommand(a, "/1", "|  No such command or snippet id: /1\n|  Type /help for help."),
260230557Sjimharris                (a) -> assertCommand(a, "/e1", "|  No such command or snippet id: /e1\n|  Type /help for help.")
261230557Sjimharris        );
262230557Sjimharris    }
263230557Sjimharris
264230557Sjimharris    public void testClasspathDirectory() {
265230557Sjimharris        Compiler compiler = new Compiler();
266230557Sjimharris        Path outDir = Paths.get("testClasspathDirectory");
267230557Sjimharris        compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
268230557Sjimharris        Path classpath = compiler.getPath(outDir);
269230557Sjimharris        test(
270230557Sjimharris                (a) -> assertCommand(a, "/classpath " + classpath, String.format("|  Path '%s' added to classpath", classpath)),
271230557Sjimharris                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
272230557Sjimharris        );
273230557Sjimharris        test(new String[] { "-cp", classpath.toString() },
274230557Sjimharris                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
275230557Sjimharris        );
276230557Sjimharris        test(new String[] { "-classpath", classpath.toString() },
277230557Sjimharris                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
278230557Sjimharris        );
279230557Sjimharris    }
280230557Sjimharris
281230557Sjimharris    public void testClasspathJar() {
282230557Sjimharris        Compiler compiler = new Compiler();
283230557Sjimharris        Path outDir = Paths.get("testClasspathJar");
284230557Sjimharris        compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
285230557Sjimharris        String jarName = "test.jar";
286230557Sjimharris        compiler.jar(outDir, jarName, "pkg/A.class");
287230557Sjimharris        Path jarPath = compiler.getPath(outDir).resolve(jarName);
288230557Sjimharris        test(
289230557Sjimharris                (a) -> assertCommand(a, "/classpath " + jarPath, String.format("|  Path '%s' added to classpath", jarPath)),
290230557Sjimharris                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
291230557Sjimharris        );
292230557Sjimharris        test(new String[] { "-cp", jarPath.toString() },
293230557Sjimharris                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
294230557Sjimharris        );
295230557Sjimharris        test(new String[] { "-classpath", jarPath.toString() },
296230557Sjimharris                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
297230557Sjimharris        );
298230557Sjimharris    }
299230557Sjimharris
300230557Sjimharris    public void testStartupFileOption() {
301230557Sjimharris        try {
302230557Sjimharris            Compiler compiler = new Compiler();
303230557Sjimharris            Path startup = compiler.getPath("StartupFileOption/startup.txt");
304230557Sjimharris            compiler.writeToFile(startup, "class A { public String toString() { return \"A\"; } }");
305230557Sjimharris            test(new String[]{"-startup", startup.toString()},
306230557Sjimharris                    (a) -> evaluateExpression(a, "A", "new A()", "A")
307230557Sjimharris            );
308230557Sjimharris            test(new String[]{"-nostartup"},
309230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "printf(\"\")", assertStartsWith("|  Error:\n|  cannot find symbol"))
310230557Sjimharris            );
311230557Sjimharris            test((a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", ""));
312230557Sjimharris            test(Locale.ROOT, false, new String[]{"-startup", "UNKNOWN"}, "|  File 'UNKNOWN' for start-up is not found.");
313230557Sjimharris        } finally {
314230557Sjimharris            removeStartup();
315230557Sjimharris        }
316230557Sjimharris    }
317230557Sjimharris
318230557Sjimharris    public void testLoadingFromArgs() {
319230557Sjimharris        Compiler compiler = new Compiler();
320230557Sjimharris        Path path = compiler.getPath("loading.repl");
321230557Sjimharris        compiler.writeToFile(path, "int a = 10; double x = 20; double a = 10;");
322230557Sjimharris        test(new String[] { path.toString() },
323230557Sjimharris                (a) -> assertCommand(a, "x", "x ==> 20.0"),
324230557Sjimharris                (a) -> assertCommand(a, "a", "a ==> 10.0")
325230557Sjimharris        );
326230557Sjimharris        Path unknown = compiler.getPath("UNKNOWN.jar");
327230557Sjimharris        test(Locale.ROOT, true, new String[]{unknown.toString()},
328230557Sjimharris                "|  File " + unknown
329230557Sjimharris                + " is not found: " + unresolvableMessage(unknown));
330230557Sjimharris    }
331230557Sjimharris
332230557Sjimharris    public void testReset() {
333230557Sjimharris        test(
334230557Sjimharris                (a) -> assertReset(a, "/res"),
335230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
336230557Sjimharris                (a) -> assertVariable(a, "int", "x"),
337230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
338230557Sjimharris                (a) -> assertMethod(a, "void f() { }", "()void", "f"),
339230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
340230557Sjimharris                (a) -> assertClass(a, "class A { }", "class", "A"),
341230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
342230557Sjimharris                (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
343230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
344230557Sjimharris                (a) -> assertReset(a, "/reset"),
345230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
346230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
347230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
348230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
349230557Sjimharris        );
350230557Sjimharris    }
351230557Sjimharris
352230557Sjimharris    public void testOpen() {
353230557Sjimharris        Compiler compiler = new Compiler();
354230557Sjimharris        Path path = compiler.getPath("testOpen.repl");
355230557Sjimharris        compiler.writeToFile(path,
356230557Sjimharris                "int a = 10;\ndouble x = 20;\ndouble a = 10;\n" +
357230557Sjimharris                        "class A { public String toString() { return \"A\"; } }\nimport java.util.stream.*;");
358230557Sjimharris        for (String s : new String[]{"/o", "/open"}) {
359230557Sjimharris            test(
360230557Sjimharris                    (a) -> assertCommand(a, s + " " + path.toString(), ""),
361230557Sjimharris                    (a) -> assertCommand(a, "a", "a ==> 10.0"),
362230557Sjimharris                    (a) -> evaluateExpression(a, "A", "new A();", "A"),
363230557Sjimharris                    (a) -> evaluateExpression(a, "long", "Stream.of(\"A\").count();", "1"),
364230557Sjimharris                    (a) -> {
365230557Sjimharris                        loadVariable(a, "double", "x", "20.0", "20.0");
366230557Sjimharris                        loadVariable(a, "double", "a", "10.0", "10.0");
367230557Sjimharris                        loadVariable(a, "A", "$7", "new A();", "A");
368230557Sjimharris                        loadVariable(a, "long", "$8", "Stream.of(\"A\").count();", "1");
369230557Sjimharris                        loadClass(a, "class A { public String toString() { return \"A\"; } }",
370230557Sjimharris                                "class", "A");
371230557Sjimharris                        loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
372230557Sjimharris                        assertCommandCheckOutput(a, "/classes", assertClasses());
373230557Sjimharris                    },
374230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
375230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
376230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
377230557Sjimharris            );
378230557Sjimharris            Path unknown = compiler.getPath("UNKNOWN.repl");
379230557Sjimharris            test(
380230557Sjimharris                    (a) -> assertCommand(a, s + " " + unknown,
381230557Sjimharris                            "|  File '" + unknown + "' for '/open' is not found.")
382230557Sjimharris            );
383230557Sjimharris        }
384230557Sjimharris    }
385230557Sjimharris
386230557Sjimharris    public void testSave() throws IOException {
387230557Sjimharris        Compiler compiler = new Compiler();
388230557Sjimharris        Path path = compiler.getPath("testSave.repl");
389230557Sjimharris        List<String> list = Arrays.asList(
390230557Sjimharris                "int a;",
391230557Sjimharris                "class A { public String toString() { return \"A\"; } }"
392230557Sjimharris        );
393230557Sjimharris        test(
394230557Sjimharris                (a) -> assertVariable(a, "int", "a"),
395230557Sjimharris                (a) -> assertCommand(a, "()", null, null, null, "", ""),
396230557Sjimharris                (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
397230557Sjimharris                (a) -> assertCommand(a, "/save " + path.toString(), "")
398230557Sjimharris        );
399230557Sjimharris        assertEquals(Files.readAllLines(path), list);
400230557Sjimharris        {
401230557Sjimharris            List<String> output = new ArrayList<>();
402230557Sjimharris            test(
403230557Sjimharris                    (a) -> assertCommand(a, "int a;", null),
404230557Sjimharris                    (a) -> assertCommand(a, "()", null, null, null, "", ""),
405230557Sjimharris                    (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
406230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/list all", (out) ->
407230557Sjimharris                            output.addAll(Stream.of(out.split("\n"))
408230557Sjimharris                                    .filter(str -> !str.isEmpty())
409230557Sjimharris                                    .map(str -> str.substring(str.indexOf(':') + 2))
410230557Sjimharris                                    .filter(str -> !str.startsWith("/"))
411230557Sjimharris                                    .collect(Collectors.toList()))),
412230557Sjimharris                    (a) -> assertCommand(a, "/save all " + path.toString(), "")
413230557Sjimharris            );
414230557Sjimharris            assertEquals(Files.readAllLines(path), output);
415230557Sjimharris        }
416230557Sjimharris        List<String> output = new ArrayList<>();
417230557Sjimharris        test(
418230557Sjimharris                (a) -> assertVariable(a, "int", "a"),
419230557Sjimharris                (a) -> assertCommand(a, "()", null, null, null, "", ""),
420230557Sjimharris                (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
421230557Sjimharris                (a) -> assertCommandCheckOutput(a, "/history", (out) ->
422230557Sjimharris                        output.addAll(Stream.of(out.split("\n"))
423230557Sjimharris                                .filter(str -> !str.isEmpty())
424230557Sjimharris                                .collect(Collectors.toList()))),
425230557Sjimharris                (a) -> assertCommand(a, "/save history " + path.toString(), "")
426230557Sjimharris        );
427230557Sjimharris        output.add("/save history " + path.toString());
428230557Sjimharris        assertEquals(Files.readAllLines(path), output);
429230557Sjimharris    }
430230557Sjimharris
431230557Sjimharris    public void testStartSet() throws BackingStoreException {
432230557Sjimharris        try {
433230557Sjimharris            Compiler compiler = new Compiler();
434230557Sjimharris            Path startUpFile = compiler.getPath("startUp.txt");
435230557Sjimharris            test(
436230557Sjimharris                    (a) -> assertVariable(a, "int", "a"),
437230557Sjimharris                    (a) -> assertVariable(a, "double", "b", "10", "10.0"),
438230557Sjimharris                    (a) -> assertMethod(a, "void f() {}", "()V", "f"),
439230557Sjimharris                    (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
440230557Sjimharris                    (a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
441230557Sjimharris                    (a) -> assertCommand(a, "/set start " + startUpFile.toString(), null)
442230557Sjimharris            );
443230557Sjimharris            Path unknown = compiler.getPath("UNKNOWN");
444230557Sjimharris            test(
445230557Sjimharris                    (a) -> assertCommandOutputStartsWith(a, "/set start " + unknown.toString(),
446230557Sjimharris                            "|  File '" + unknown + "' for '/set start' is not found.")
447230557Sjimharris            );
448230557Sjimharris            test(false, new String[0],
449230557Sjimharris                    (a) -> {
450230557Sjimharris                        loadVariable(a, "int", "a");
451230557Sjimharris                        loadVariable(a, "double", "b", "10.0", "10.0");
452230557Sjimharris                        loadMethod(a, "void f() {}", "()void", "f");
453230557Sjimharris                        loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
454230557Sjimharris                        assertCommandCheckOutput(a, "/classes", assertClasses());
455230557Sjimharris                    },
456230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
457230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
458230557Sjimharris                    (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
459230557Sjimharris            );
460230557Sjimharris        } finally {
461230557Sjimharris            removeStartup();
462230557Sjimharris        }
463230557Sjimharris    }
464230557Sjimharris
465230557Sjimharris    private void removeStartup() {
466230557Sjimharris        Preferences preferences = Preferences.userRoot().node("tool/JShell");
467230557Sjimharris        if (preferences != null) {
468230557Sjimharris            preferences.remove("STARTUP");
469230557Sjimharris        }
470230557Sjimharris    }
471230557Sjimharris
472230557Sjimharris    public void testStartSave() throws IOException {
473230557Sjimharris        Compiler compiler = new Compiler();
474230557Sjimharris        Path startSave = compiler.getPath("startSave.txt");
475230557Sjimharris        test(a -> assertCommand(a, "/save start " + startSave.toString(), null));
476230557Sjimharris        List<String> lines = Files.lines(startSave)
477230557Sjimharris                .filter(s -> !s.isEmpty())
478230557Sjimharris                .collect(Collectors.toList());
479230557Sjimharris        assertEquals(lines, START_UP);
480230557Sjimharris    }
481230557Sjimharris
482230557Sjimharris    public void testConstrainedUpdates() {
483230557Sjimharris        test(
484230557Sjimharris                a -> assertClass(a, "class XYZZY { }", "class", "XYZZY"),
485230557Sjimharris                a -> assertVariable(a, "XYZZY", "xyzzy"),
486230557Sjimharris                a -> assertCommandCheckOutput(a, "import java.util.stream.*",
487230557Sjimharris                        (out) -> assertTrue(out.trim().isEmpty(), "Expected no output, got: " + out))
488230557Sjimharris        );
489230557Sjimharris    }
490230557Sjimharris
491230557Sjimharris    public void testRemoteExit() {
492230557Sjimharris        test(
493230557Sjimharris                a -> assertVariable(a, "int", "x"),
494230557Sjimharris                a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
495230557Sjimharris                a -> assertCommandOutputContains(a, "System.exit(5);", "terminated"),
496230557Sjimharris                a -> assertCommandCheckOutput(a, "/vars", s ->
497230557Sjimharris                        assertTrue(s.trim().isEmpty(), s)),
498230557Sjimharris                a -> assertMethod(a, "void f() { }", "()void", "f"),
499230557Sjimharris                a -> assertCommandCheckOutput(a, "/methods", assertMethods())
500230557Sjimharris        );
501230557Sjimharris    }
502230557Sjimharris
503230557Sjimharris    public void testFeedbackNegative() {
504230557Sjimharris        test(a -> assertCommandCheckOutput(a, "/set feedback aaaa",
505230557Sjimharris                assertStartsWith("|  Does not match any current feedback mode")));
506230557Sjimharris    }
507230557Sjimharris
508230557Sjimharris    public void testFeedbackSilent() {
509230557Sjimharris        for (String off : new String[]{"s", "silent"}) {
510230557Sjimharris            test(
511230557Sjimharris                    a -> assertCommand(a, "/set feedback " + off, ""),
512230557Sjimharris                    a -> assertCommand(a, "int a", ""),
513230557Sjimharris                    a -> assertCommand(a, "void f() {}", ""),
514230557Sjimharris                    a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("|  Error:")),
515230557Sjimharris                    a -> assertCommandCheckOutput(a, "public void f() {}", assertStartsWith("|  Warning:"))
516230557Sjimharris            );
517230557Sjimharris        }
518230557Sjimharris    }
519230557Sjimharris
520230557Sjimharris    public void testFeedbackNormal() {
521230557Sjimharris        Compiler compiler = new Compiler();
522230557Sjimharris        Path testNormalFile = compiler.getPath("testConciseNormal");
523230557Sjimharris        String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"};
524230557Sjimharris        String[] sources2 = new String[] {"int a //again", "void f() {int y = 4;}", "class A {} //again", "a = 10"};
525230557Sjimharris        String[] output = new String[] {
526230557Sjimharris                "a ==> 0",
527230557Sjimharris                "|  created method f()",
528230557Sjimharris                "|  created class A",
529230557Sjimharris                "a ==> 10"
530230557Sjimharris        };
531230557Sjimharris        compiler.writeToFile(testNormalFile, sources2);
532230557Sjimharris        for (String feedback : new String[]{"/set fe", "/set feedback"}) {
533230557Sjimharris            for (String feedbackState : new String[]{"n", "normal"}) {
534230557Sjimharris                test(
535230557Sjimharris                        a -> assertCommand(a, feedback + " " + feedbackState, "|  Feedback mode: normal"),
536230557Sjimharris                        a -> assertCommand(a, sources[0], output[0]),
537230557Sjimharris                        a -> assertCommand(a, sources[1], output[1]),
538230557Sjimharris                        a -> assertCommand(a, sources[2], output[2]),
539230557Sjimharris                        a -> assertCommand(a, sources[3], output[3]),
540230557Sjimharris                        a -> assertCommand(a, "/o " + testNormalFile.toString(), "")
541230557Sjimharris                );
542230557Sjimharris            }
543230557Sjimharris        }
544230557Sjimharris    }
545230557Sjimharris
546230557Sjimharris    public void testHistoryReference() {
547230557Sjimharris        test(false, new String[]{"-nostartup"},
548230557Sjimharris                a -> assertCommand(a, "System.err.println(1)", "", "", null, "", "1\n"),
549230557Sjimharris                a -> assertCommand(a, "System.err.println(2)", "", "", null, "", "2\n"),
550230557Sjimharris                a -> assertCommand(a, "/-2", "System.err.println(1)", "", null, "", "1\n"),
551230557Sjimharris                a -> assertCommand(a, "/history",
552230557Sjimharris                                                    "/debug 0\n" +
553230557Sjimharris                                                    "System.err.println(1)\n" +
554230557Sjimharris                                                    "System.err.println(2)\n" +
555230557Sjimharris                                                    "System.err.println(1)\n" +
556230557Sjimharris                                                    "/history\n"),
557230557Sjimharris                a -> assertCommand(a, "/-2", "System.err.println(2)", "", null, "", "2\n"),
558230557Sjimharris                a -> assertCommand(a, "/!", "System.err.println(2)", "", null, "", "2\n"),
559230557Sjimharris                a -> assertCommand(a, "/2", "System.err.println(2)", "", null, "", "2\n"),
560230557Sjimharris                a -> assertCommand(a, "/1", "System.err.println(1)", "", null, "", "1\n")
561230557Sjimharris        );
562230557Sjimharris    }
563230557Sjimharris
564230557Sjimharris    private String unresolvableMessage(Path p) {
565230557Sjimharris        try {
566230557Sjimharris            new FileInputStream(p.toFile());
567230557Sjimharris            throw new AssertionError("Expected exception did not occur.");
568230557Sjimharris        } catch (IOException ex) {
569230557Sjimharris            return ex.getMessage();
570230557Sjimharris        }
571230557Sjimharris    }
572230557Sjimharris}
573230557Sjimharris