ToolBasicTest.java revision 3725:f7187b5fe9e2
1/*
2 * Copyright (c) 2015, 2016, 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
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
38import java.io.IOException;
39import java.io.PrintWriter;
40import java.io.StringWriter;
41import java.nio.file.Files;
42import java.nio.file.Path;
43import java.nio.file.Paths;
44import java.util.ArrayList;
45import java.util.Arrays;
46import java.util.List;
47import java.util.Locale;
48import java.util.Scanner;
49import java.util.function.BiFunction;
50import java.util.function.Consumer;
51import java.util.function.Function;
52import java.util.prefs.BackingStoreException;
53import java.util.prefs.Preferences;
54import java.util.stream.Collectors;
55import java.util.stream.Stream;
56
57import org.testng.annotations.Test;
58
59import static org.testng.Assert.assertEquals;
60import static org.testng.Assert.assertTrue;
61import static org.testng.Assert.fail;
62
63@Test
64public class ToolBasicTest extends ReplToolTesting {
65
66    public void elideStartUpFromList() {
67        test(
68                (a) -> assertCommandOutputContains(a, "123", "==> 123"),
69                (a) -> assertCommandCheckOutput(a, "/list", (s) -> {
70                    int cnt;
71                    try (Scanner scanner = new Scanner(s)) {
72                        cnt = 0;
73                        while (scanner.hasNextLine()) {
74                            String line = scanner.nextLine();
75                            if (!line.trim().isEmpty()) {
76                                ++cnt;
77                            }
78                        }
79                    }
80                    assertEquals(cnt, 1, "Expected only one listed line");
81                })
82        );
83    }
84
85    public void elideStartUpFromSave() throws IOException {
86        Compiler compiler = new Compiler();
87        Path path = compiler.getPath("myfile");
88        test(
89                (a) -> assertCommandOutputContains(a, "123", "==> 123"),
90                (a) -> assertCommand(a, "/save " + path.toString(), "")
91        );
92        try (Stream<String> lines = Files.lines(path)) {
93            assertEquals(lines.count(), 1, "Expected only one saved line");
94        }
95    }
96
97    public void testInterrupt() {
98        ReplTest interrupt = (a) -> assertCommand(a, "\u0003", "");
99        for (String s : new String[] { "", "\u0003" }) {
100            test(false, new String[]{"--no-startup"},
101                    (a) -> assertCommand(a, "int a = 2 +" + s, ""),
102                    interrupt,
103                    (a) -> assertCommand(a, "int a\u0003", ""),
104                    (a) -> assertCommand(a, "int a = 2 + 2\u0003", ""),
105                    (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
106                    (a) -> evaluateExpression(a, "int", "2", "2"),
107                    (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
108                    (a) -> assertCommand(a, "void f() {", ""),
109                    (a) -> assertCommand(a, "int q = 10;" + s, ""),
110                    interrupt,
111                    (a) -> assertCommand(a, "void f() {}\u0003", ""),
112                    (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
113                    (a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
114                    (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
115                    (a) -> assertCommand(a, "class A {" + s, ""),
116                    interrupt,
117                    (a) -> assertCommand(a, "class A {}\u0003", ""),
118                    (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
119                    (a) -> assertClass(a, "interface A {}", "interface", "A"),
120                    (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
121                    (a) -> assertCommand(a, "import java.util.stream." + s, ""),
122                    interrupt,
123                    (a) -> assertCommand(a, "import java.util.stream.\u0003", ""),
124                    (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
125                    (a) -> assertImport(a, "import java.util.stream.Stream", "", "java.util.stream.Stream"),
126                    (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
127            );
128        }
129    }
130
131    private final Object lock = new Object();
132    private PrintWriter out;
133    private boolean isStopped;
134    private Thread t;
135    private void assertStop(boolean after, String cmd, String output) {
136        if (!after) {
137            isStopped = false;
138            StringWriter writer = new StringWriter();
139            out = new PrintWriter(writer);
140            setCommandInput(cmd + "\n");
141            t = new Thread(() -> {
142                try {
143                    // no chance to know whether cmd is being evaluated
144                    Thread.sleep(5000);
145                } catch (InterruptedException ignored) {
146                }
147                int i = 1;
148                int n = 30;
149                synchronized (lock) {
150                    do {
151                        setCommandInput("\u0003");
152                        if (!isStopped) {
153                            out.println("Not stopped. Try again: " + i);
154                            try {
155                                lock.wait(1000);
156                            } catch (InterruptedException ignored) {
157                            }
158                        }
159                    } while (i++ < n && !isStopped);
160                    if (!isStopped) {
161                        System.err.println(writer.toString());
162                        fail("Evaluation was not stopped: '" + cmd + "'");
163                    }
164                }
165            });
166            t.start();
167        } else {
168            synchronized (lock)  {
169                out.println("Evaluation was stopped successfully: '" + cmd + "'");
170                isStopped = true;
171                lock.notify();
172            }
173            try {
174                t.join();
175                t = null;
176            } catch (InterruptedException ignored) {
177            }
178            assertOutput(getCommandOutput(), "", "command");
179            assertOutput(getCommandErrorOutput(), "", "command error");
180            assertOutput(getUserOutput().trim(), output, "user");
181            assertOutput(getUserErrorOutput(), "", "user error");
182        }
183    }
184
185    public void testStop() {
186        test(
187                (a) -> assertStop(a, "while (true) {}", ""),
188                (a) -> assertStop(a, "while (true) { try { Thread.sleep(100); } catch (InterruptedException ex) { } }", "")
189        );
190    }
191
192    public void testRerun() {
193        test(false, new String[] {"--no-startup"},
194                (a) -> assertCommand(a, "/0", "|  No such command or snippet id: /0\n|  Type /help for help."),
195                (a) -> assertCommand(a, "/5", "|  No such command or snippet id: /5\n|  Type /help for help.")
196        );
197        String[] codes = new String[] {
198                "int a = 0;", // var
199                "class A {}", // class
200                "void f() {}", // method
201                "bool b;", // active failed
202                "void g() { h(); }", // active corralled
203        };
204        List<ReplTest> tests = new ArrayList<>();
205        for (String s : codes) {
206            tests.add((a) -> assertCommand(a, s, null));
207        }
208        // Test /1 through /5 -- assure references are correct
209        for (int i = 0; i < codes.length; ++i) {
210            final int finalI = i;
211            Consumer<String> check = (s) -> {
212                String[] ss = s.split("\n");
213                assertEquals(ss[0], codes[finalI]);
214                assertTrue(ss.length > 1, s);
215            };
216            tests.add((a) -> assertCommandCheckOutput(a, "/" + (finalI + 1), check));
217        }
218        // Test /-1 ... note that the snippets added by history must be stepped over
219        for (int i = 0; i < codes.length; ++i) {
220            final int finalI = i;
221            Consumer<String> check = (s) -> {
222                String[] ss = s.split("\n");
223                assertEquals(ss[0], codes[codes.length - finalI - 1]);
224                assertTrue(ss.length > 1, s);
225            };
226            tests.add((a) -> assertCommandCheckOutput(a, "/-" + (2 * finalI + 1), check));
227        }
228        tests.add((a) -> assertCommandCheckOutput(a, "/!", assertStartsWith("int a = 0;")));
229        test(false, new String[]{"--no-startup"},
230                tests.toArray(new ReplTest[tests.size()]));
231    }
232
233    public void test8142447() {
234        Function<String, BiFunction<String, Integer, ReplTest>> assertRerun = cmd -> (code, assertionCount) ->
235                (a) -> assertCommandCheckOutput(a, cmd, s -> {
236                            String[] ss = s.split("\n");
237                            assertEquals(ss[0], code);
238                            loadVariable(a, "int", "assertionCount", Integer.toString(assertionCount), Integer.toString(assertionCount));
239                        });
240        ReplTest assertVariables = (a) -> assertCommandCheckOutput(a, "/v", assertVariables());
241
242        Compiler compiler = new Compiler();
243        Path startup = compiler.getPath("StartupFileOption/startup.txt");
244        compiler.writeToFile(startup, "int assertionCount = 0;\n" + // id: s1
245                "void add(int n) { assertionCount += n; }");
246        test(new String[]{"--startup", startup.toString()},
247                (a) -> assertCommand(a, "add(1)", ""), // id: 1
248                (a) -> assertCommandCheckOutput(a, "add(ONE)", s -> assertEquals(s.split("\n")[0], "|  Error:")), // id: e1
249                (a) -> assertVariable(a, "int", "ONE", "1", "1"),
250                assertRerun.apply("/1").apply("add(1)", 2), assertVariables,
251                assertRerun.apply("/e1").apply("add(ONE)", 3), assertVariables,
252                assertRerun.apply("/s1").apply("int assertionCount = 0;", 0), assertVariables
253        );
254
255        test(false, new String[] {"--no-startup"},
256                (a) -> assertCommand(a, "/s1", "|  No such command or snippet id: /s1\n|  Type /help for help."),
257                (a) -> assertCommand(a, "/1", "|  No such command or snippet id: /1\n|  Type /help for help."),
258                (a) -> assertCommand(a, "/e1", "|  No such command or snippet id: /e1\n|  Type /help for help.")
259        );
260    }
261
262    public void testClasspathDirectory() {
263        Compiler compiler = new Compiler();
264        Path outDir = Paths.get("testClasspathDirectory");
265        compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
266        Path classpath = compiler.getPath(outDir);
267        test(
268                (a) -> assertCommand(a, "/classpath " + classpath, String.format("|  Path '%s' added to classpath", classpath)),
269                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
270        );
271        test(new String[] { "--class-path", classpath.toString() },
272                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
273        );
274    }
275
276    public void testClasspathJar() {
277        Compiler compiler = new Compiler();
278        Path outDir = Paths.get("testClasspathJar");
279        compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
280        String jarName = "test.jar";
281        compiler.jar(outDir, jarName, "pkg/A.class");
282        Path jarPath = compiler.getPath(outDir).resolve(jarName);
283        test(
284                (a) -> assertCommand(a, "/classpath " + jarPath, String.format("|  Path '%s' added to classpath", jarPath)),
285                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
286        );
287        test(new String[] { "--class-path", jarPath.toString() },
288                (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
289        );
290    }
291
292    public void testModulePath() {
293        Compiler compiler = new Compiler();
294        Path modsDir = Paths.get("mods");
295        Path outDir = Paths.get("mods", "org.astro");
296        compiler.compile(outDir, "package org.astro; public class World { public static String name() { return \"world\"; } }");
297        compiler.compile(outDir, "module org.astro { exports org.astro; }");
298        Path modsPath = compiler.getPath(modsDir);
299        test(new String[] { "--module-path", modsPath.toString(), "--add-modules", "org.astro" },
300                (a) -> assertCommand(a, "import org.astro.World;", ""),
301                (a) -> evaluateExpression(a, "String",
302                        "String.format(\"Greetings %s!\", World.name());",
303                        "\"Greetings world!\"")
304        );
305    }
306
307    public void testStartupFileOption() {
308        try {
309            Compiler compiler = new Compiler();
310            Path startup = compiler.getPath("StartupFileOption/startup.txt");
311            compiler.writeToFile(startup, "class A { public String toString() { return \"A\"; } }");
312            test(new String[]{"--startup", startup.toString()},
313                    (a) -> evaluateExpression(a, "A", "new A()", "A")
314            );
315            test(new String[]{"--no-startup"},
316                    (a) -> assertCommandCheckOutput(a, "printf(\"\")", assertStartsWith("|  Error:\n|  cannot find symbol"))
317            );
318            test(
319                    (a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", "")
320            );
321        } finally {
322            removeStartup();
323        }
324    }
325
326    public void testLoadingFromArgs() {
327        Compiler compiler = new Compiler();
328        Path path = compiler.getPath("loading.repl");
329        compiler.writeToFile(path, "int a = 10; double x = 20; double a = 10;");
330        test(new String[] { path.toString() },
331                (a) -> assertCommand(a, "x", "x ==> 20.0"),
332                (a) -> assertCommand(a, "a", "a ==> 10.0")
333        );
334        Path unknown = compiler.getPath("UNKNOWN.jar");
335        test(Locale.ROOT, true, new String[]{unknown.toString()},
336                "|  File '" + unknown
337                + "' for 'jshell' is not found.");
338    }
339
340    public void testReset() {
341        test(
342                (a) -> assertReset(a, "/res"),
343                (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
344                (a) -> assertVariable(a, "int", "x"),
345                (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
346                (a) -> assertMethod(a, "void f() { }", "()void", "f"),
347                (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
348                (a) -> assertClass(a, "class A { }", "class", "A"),
349                (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
350                (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
351                (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
352                (a) -> assertReset(a, "/reset"),
353                (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
354                (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
355                (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
356                (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
357        );
358    }
359
360    public void testOpen() {
361        Compiler compiler = new Compiler();
362        Path path = compiler.getPath("testOpen.repl");
363        compiler.writeToFile(path,
364                "int a = 10;\ndouble x = 20;\ndouble a = 10;\n" +
365                        "class A { public String toString() { return \"A\"; } }\nimport java.util.stream.*;");
366        for (String s : new String[]{"/o", "/open"}) {
367            test(
368                    (a) -> assertCommand(a, s + " " + path.toString(), ""),
369                    (a) -> assertCommand(a, "a", "a ==> 10.0"),
370                    (a) -> evaluateExpression(a, "A", "new A();", "A"),
371                    (a) -> evaluateExpression(a, "long", "Stream.of(\"A\").count();", "1"),
372                    (a) -> {
373                        loadVariable(a, "double", "x", "20.0", "20.0");
374                        loadVariable(a, "double", "a", "10.0", "10.0");
375                        loadVariable(a, "A", "$7", "new A();", "A");
376                        loadVariable(a, "long", "$8", "Stream.of(\"A\").count();", "1");
377                        loadClass(a, "class A { public String toString() { return \"A\"; } }",
378                                "class", "A");
379                        loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
380                        assertCommandCheckOutput(a, "/types", assertClasses());
381                    },
382                    (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
383                    (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
384                    (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
385            );
386            Path unknown = compiler.getPath("UNKNOWN.repl");
387            test(
388                    (a) -> assertCommand(a, s + " " + unknown,
389                            "|  File '" + unknown + "' for '/open' is not found.")
390            );
391        }
392    }
393
394    public void testSave() throws IOException {
395        Compiler compiler = new Compiler();
396        Path path = compiler.getPath("testSave.repl");
397        List<String> list = Arrays.asList(
398                "int a;",
399                "class A { public String toString() { return \"A\"; } }"
400        );
401        test(
402                (a) -> assertVariable(a, "int", "a"),
403                (a) -> assertCommand(a, "()", null, null, null, "", ""),
404                (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
405                (a) -> assertCommand(a, "/save " + path.toString(), "")
406        );
407        assertEquals(Files.readAllLines(path), list);
408        {
409            List<String> output = new ArrayList<>();
410            test(
411                    (a) -> assertCommand(a, "int a;", null),
412                    (a) -> assertCommand(a, "()", null, null, null, "", ""),
413                    (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
414                    (a) -> assertCommandCheckOutput(a, "/list -all", (out) ->
415                            output.addAll(Stream.of(out.split("\n"))
416                                    .filter(str -> !str.isEmpty())
417                                    .map(str -> str.substring(str.indexOf(':') + 2))
418                                    .filter(str -> !str.startsWith("/"))
419                                    .collect(Collectors.toList()))),
420                    (a) -> assertCommand(a, "/save -all " + path.toString(), "")
421            );
422            assertEquals(Files.readAllLines(path), output);
423        }
424        List<String> output = new ArrayList<>();
425        test(
426                (a) -> assertVariable(a, "int", "a"),
427                (a) -> assertCommand(a, "()", null, null, null, "", ""),
428                (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
429                (a) -> assertCommandCheckOutput(a, "/history", (out) ->
430                        output.addAll(Stream.of(out.split("\n"))
431                                .filter(str -> !str.isEmpty())
432                                .collect(Collectors.toList()))),
433                (a) -> assertCommand(a, "/save -history " + path.toString(), "")
434        );
435        output.add("/save -history " + path.toString());
436        assertEquals(Files.readAllLines(path), output);
437    }
438
439    public void testStartRetain() throws BackingStoreException {
440        try {
441            Compiler compiler = new Compiler();
442            Path startUpFile = compiler.getPath("startUp.txt");
443            test(
444                    (a) -> assertVariable(a, "int", "a"),
445                    (a) -> assertVariable(a, "double", "b", "10", "10.0"),
446                    (a) -> assertMethod(a, "void f() {}", "()V", "f"),
447                    (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
448                    (a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
449                    (a) -> assertCommand(a, "/set start -retain " + startUpFile.toString(), null)
450            );
451            Path unknown = compiler.getPath("UNKNOWN");
452            test(
453                    (a) -> assertCommandOutputStartsWith(a, "/set start -retain " + unknown.toString(),
454                            "|  File '" + unknown + "' for '/set start' is not found.")
455            );
456            test(false, new String[0],
457                    (a) -> {
458                        loadVariable(a, "int", "a");
459                        loadVariable(a, "double", "b", "10.0", "10.0");
460                        loadMethod(a, "void f() {}", "()void", "f");
461                        loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
462                        assertCommandCheckOutput(a, "/types", assertClasses());
463                    },
464                    (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
465                    (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
466                    (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
467            );
468        } finally {
469            removeStartup();
470        }
471    }
472
473    private void removeStartup() {
474        Preferences preferences = Preferences.userRoot().node("tool/JShell");
475        if (preferences != null) {
476            preferences.remove("STARTUP");
477        }
478    }
479
480    public void testStartSave() throws IOException {
481        Compiler compiler = new Compiler();
482        Path startSave = compiler.getPath("startSave.txt");
483        test(a -> assertCommand(a, "/save -start " + startSave.toString(), null));
484        List<String> lines = Files.lines(startSave)
485                .filter(s -> !s.isEmpty())
486                .collect(Collectors.toList());
487        assertEquals(lines, START_UP);
488    }
489
490    public void testConstrainedUpdates() {
491        test(
492                a -> assertClass(a, "class XYZZY { }", "class", "XYZZY"),
493                a -> assertVariable(a, "XYZZY", "xyzzy"),
494                a -> assertCommandCheckOutput(a, "import java.util.stream.*",
495                        (out) -> assertTrue(out.trim().isEmpty(), "Expected no output, got: " + out))
496        );
497    }
498
499    public void testRemoteExit() {
500        test(
501                a -> assertVariable(a, "int", "x"),
502                a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
503                a -> assertCommandOutputContains(a, "System.exit(5);", "terminated"),
504                a -> assertCommandCheckOutput(a, "/vars", s ->
505                        assertTrue(s.trim().isEmpty(), s)),
506                a -> assertMethod(a, "void f() { }", "()void", "f"),
507                a -> assertCommandCheckOutput(a, "/methods", assertMethods())
508        );
509    }
510
511    public void testFeedbackNegative() {
512        test(a -> assertCommandCheckOutput(a, "/set feedback aaaa",
513                assertStartsWith("|  Does not match any current feedback mode")));
514    }
515
516    public void testFeedbackSilent() {
517        for (String off : new String[]{"s", "silent"}) {
518            test(
519                    a -> assertCommand(a, "/set feedback " + off, ""),
520                    a -> assertCommand(a, "int a", ""),
521                    a -> assertCommand(a, "void f() {}", ""),
522                    a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("|  Error:")),
523                    a -> assertCommandCheckOutput(a, "public void f() {}", assertStartsWith("|  Warning:"))
524            );
525        }
526    }
527
528    public void testFeedbackNormal() {
529        Compiler compiler = new Compiler();
530        Path testNormalFile = compiler.getPath("testConciseNormal");
531        String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"};
532        String[] sources2 = new String[] {"int a //again", "void f() {int y = 4;}", "class A {} //again", "a = 10"};
533        String[] output = new String[] {
534                "a ==> 0",
535                "|  created method f()",
536                "|  created class A",
537                "a ==> 10"
538        };
539        compiler.writeToFile(testNormalFile, sources2);
540        for (String feedback : new String[]{"/set fe", "/set feedback"}) {
541            for (String feedbackState : new String[]{"n", "normal"}) {
542                test(
543                        a -> assertCommand(a, feedback + " " + feedbackState, "|  Feedback mode: normal"),
544                        a -> assertCommand(a, sources[0], output[0]),
545                        a -> assertCommand(a, sources[1], output[1]),
546                        a -> assertCommand(a, sources[2], output[2]),
547                        a -> assertCommand(a, sources[3], output[3]),
548                        a -> assertCommand(a, "/o " + testNormalFile.toString(), "")
549                );
550            }
551        }
552    }
553
554    public void testVarsWithNotActive() {
555        test(
556                a -> assertVariable(a, "Blath", "x"),
557                a -> assertCommandOutputContains(a, "/var -all", "(not-active)")
558        );
559    }
560
561    public void testHistoryReference() {
562        test(false, new String[]{"--no-startup"},
563                a -> assertCommand(a, "System.err.println(1)", "", "", null, "", "1\n"),
564                a -> assertCommand(a, "System.err.println(2)", "", "", null, "", "2\n"),
565                a -> assertCommand(a, "/-2", "System.err.println(1)", "", null, "", "1\n"),
566                a -> assertCommand(a, "/history",
567                                                    "/debug 0\n" +
568                                                    "System.err.println(1)\n" +
569                                                    "System.err.println(2)\n" +
570                                                    "System.err.println(1)\n" +
571                                                    "/history\n"),
572                a -> assertCommand(a, "/-2", "System.err.println(2)", "", null, "", "2\n"),
573                a -> assertCommand(a, "/!", "System.err.println(2)", "", null, "", "2\n"),
574                a -> assertCommand(a, "/2", "System.err.println(2)", "", null, "", "2\n"),
575                a -> assertCommand(a, "/1", "System.err.println(1)", "", null, "", "1\n")
576        );
577    }
578
579    @Test(enabled = false) // TODO 8158197
580    public void testHeadlessEditPad() {
581        String prevHeadless = System.getProperty("java.awt.headless");
582        try {
583            System.setProperty("java.awt.headless", "true");
584            test(
585                (a) -> assertCommandOutputStartsWith(a, "/edit printf", "|  Cannot launch editor -- unexpected exception:")
586            );
587        } finally {
588            System.setProperty("java.awt.headless", prevHeadless==null? "false" : prevHeadless);
589        }
590    }
591
592    public void testAddExports() {
593        test(false, new String[]{"--no-startup"},
594                a -> assertCommandOutputStartsWith(a, "import jdk.internal.misc.VM;", "|  Error:")
595        );
596        test(false, new String[]{"--no-startup",
597            "-R--add-exports", "-Rjava.base/jdk.internal.misc=ALL-UNNAMED",
598            "-C--add-exports", "-Cjava.base/jdk.internal.misc=ALL-UNNAMED"},
599                a -> assertImport(a, "import jdk.internal.misc.VM;", "", "jdk.internal.misc.VM"),
600                a -> assertCommand(a, "System.err.println(VM.isBooted())", "", "", null, "", "true\n")
601        );
602        test(false, new String[]{"--no-startup", "--add-exports", "java.base/jdk.internal.misc"},
603                a -> assertImport(a, "import jdk.internal.misc.VM;", "", "jdk.internal.misc.VM"),
604                a -> assertCommand(a, "System.err.println(VM.isBooted())", "", "", null, "", "true\n")
605        );
606    }
607
608}
609