Path: blob/master/test/langtools/jdk/jshell/CommandCompletionTest.java
40931 views
/*1* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8144095 8164825 8169818 8153402 8165405 8177079 8178013 8167554 816623226* @summary Test Command Completion27* @modules jdk.compiler/com.sun.tools.javac.api28* jdk.compiler/com.sun.tools.javac.main29* jdk.jdeps/com.sun.tools.javap30* jdk.jshell/jdk.internal.jshell.tool31* @library /tools/lib32* @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask33* @build ReplToolTesting TestingInputStream Compiler34* @run testng CommandCompletionTest35*/3637import java.io.IOException;38import java.nio.file.FileSystems;39import java.nio.file.Files;40import java.nio.file.Path;41import java.nio.file.Paths;42import java.util.Arrays;43import java.util.Collections;44import java.util.List;45import java.util.Locale;46import java.util.function.Predicate;47import java.util.stream.Collectors;48import java.util.stream.Stream;49import java.util.stream.StreamSupport;5051import org.testng.annotations.Test;52import jdk.internal.jshell.tool.JShellTool;53import jdk.internal.jshell.tool.JShellToolBuilder;54import jdk.jshell.SourceCodeAnalysis.Suggestion;55import static org.testng.Assert.assertEquals;56import static org.testng.Assert.assertTrue;57import static org.testng.Assert.fail;5859public class CommandCompletionTest extends ReplToolTesting {606162private JShellTool repl;6364@Override65protected void testRawRun(Locale locale, String[] args) {66repl = ((JShellToolBuilder) builder(locale))67.rawTool();68try {69repl.start(args);70} catch (Exception ex) {71fail("Repl tool died with exception", ex);72}73}7475public void assertCompletion(boolean after, String code, boolean isSmart, String... expected) {76if (!after) {77setCommandInput("\n");78} else {79assertCompletion(code, isSmart, expected);80}81}8283public void assertCompletion(String code, boolean isSmart, String... expected) {84List<String> completions = computeCompletions(code, isSmart);85assertEquals(completions, Arrays.asList(expected), "Command: " + code + ", output: " +86completions.toString());87}8889private List<String> computeCompletions(String code, boolean isSmart) {90int cursor = code.indexOf('|');91code = code.replace("|", "");92assertTrue(cursor > -1, "'|' not found: " + code);93List<Suggestion> completions =94repl.commandCompletionSuggestions(code, cursor, new int[] {-1}); //XXX: ignoring anchor for now95return completions.stream()96.filter(s -> isSmart == s.matchesType())97.map(s -> s.continuation())98.distinct()99.collect(Collectors.toList());100}101102@Test103public void testCommand() {104testNoStartUp(105a -> assertCompletion(a, "/deb|", false),106a -> assertCompletion(a, "/re|", false, "/reload ", "/reset "),107a -> assertCompletion(a, "/h|", false, "/help ", "/history ")108);109}110111@Test112public void testList() {113test(false, new String[] {"--no-startup"},114a -> assertCompletion(a, "/l|", false, "/list "),115a -> assertCompletion(a, "/list |", false, "-all", "-history", "-start "),116a -> assertCompletion(a, "/list -h|", false, "-history"),117a -> assertCompletion(a, "/list q|", false),118a -> assertVariable(a, "int", "xray"),119a -> assertCompletion(a, "/list |", false, "-all", "-history", "-start ", "1 ", "xray "),120a -> assertCompletion(a, "/list x|", false, "xray "),121a -> assertCompletion(a, "/list xray |", false)122);123}124125@Test126public void testHistory() {127test(false, new String[] {"--no-startup"},128a -> assertCompletion(a, "/hi|", false, "/history "),129a -> assertCompletion(a, "/history |", false, "-all")130);131}132133@Test134public void testDrop() {135test(false, new String[] {"--no-startup"},136a -> assertCompletion(a, "/d|", false, "/drop "),137a -> assertClass(a, "class cTest {}", "class", "cTest"),138a -> assertMethod(a, "int mTest() { return 0; }", "()I", "mTest"),139a -> assertVariable(a, "int", "fTest"),140a -> assertCompletion(a, "/drop |", false, "1 ", "2 ", "3 ", "cTest ", "fTest ", "mTest "),141a -> assertCompletion(a, "/drop f|", false, "fTest ")142);143}144145@Test146public void testEdit() {147test(false, new String[]{"--no-startup"},148a -> assertCompletion(a, "/e|", false, "/edit ", "/env ", "/exit "),149a -> assertCompletion(a, "/ed|", false, "/edit "),150a -> assertClass(a, "class cTest {}", "class", "cTest"),151a -> assertMethod(a, "int mTest() { return 0; }", "()I", "mTest"),152a -> assertVariable(a, "int", "fTest"),153a -> assertCompletion(a, "/edit |", false,154"-all" , "-start " , "1 ", "2 ", "3 ", "cTest ", "fTest ", "mTest "),155a -> assertCompletion(a, "/edit cTest |", false,156"2 ", "3 ", "fTest ", "mTest "),157a -> assertCompletion(a, "/edit 1 fTest |", false,158"2 ", "mTest "),159a -> assertCompletion(a, "/edit f|", false, "fTest "),160a -> assertCompletion(a, "/edit mTest f|", false, "fTest ")161);162}163164@Test165public void testHelp() {166testNoStartUp(167a -> assertCompletion(a, "/help |", false,168"/! ", "/-<n> ", "/<id> ", "/? ", "/drop ",169"/edit ", "/env ", "/exit ",170"/help ", "/history ", "/imports ",171"/list ", "/methods ", "/open ", "/reload ", "/reset ",172"/save ", "/set ", "/types ", "/vars ", "context ",173"id ", "intro ", "keys ", "rerun ", "shortcuts "),174a -> assertCompletion(a, "/? |", false,175"/! ", "/-<n> ", "/<id> ", "/? ", "/drop ",176"/edit ", "/env ", "/exit ",177"/help ", "/history ", "/imports ",178"/list ", "/methods ", "/open ", "/reload ", "/reset ",179"/save ", "/set ", "/types ", "/vars ", "context ",180"id ", "intro ", "keys ", "rerun ", "shortcuts "),181a -> assertCompletion(a, "/help /s|", false,182"/save ", "/set "),183a -> assertCompletion(a, "/help /set |", false,184"editor", "feedback", "format", "indent", "mode", "prompt", "start", "truncation"),185a -> assertCompletion(a, "/help set |", false,186"editor", "feedback", "format", "indent", "mode", "prompt", "start", "truncation"),187a -> assertCompletion(a, "/help /edit |", false),188a -> assertCompletion(a, "/help dr|", false,189"drop ")190);191}192193@Test194public void testReload() {195String[] ropts = new String[] { "-add-exports ", "-add-modules ",196"-class-path ", "-module-path ", "-quiet ", "-restore " };197String[] dropts = new String[] { "--add-exports ", "--add-modules ",198"--class-path ", "--module-path ", "--quiet ", "--restore " };199testNoStartUp(200a -> assertCompletion(a, "/reloa |", false, ropts),201a -> assertCompletion(a, "/relo |", false, ropts),202a -> assertCompletion(a, "/reload -|", false, ropts),203a -> assertCompletion(a, "/reload --|", false, dropts),204a -> assertCompletion(a, "/reload -restore |", false, ropts),205a -> assertCompletion(a, "/reload -restore --|", false, dropts),206a -> assertCompletion(a, "/reload -rest|", false, "-restore "),207a -> assertCompletion(a, "/reload --r|", false, "--restore "),208a -> assertCompletion(a, "/reload -q|", false, "-quiet "),209a -> assertCompletion(a, "/reload -add|", false, "-add-exports ", "-add-modules "),210a -> assertCompletion(a, "/reload -class-path . -quiet |", false, ropts)211);212}213214@Test215public void testEnv() {216String[] ropts = new String[] { "-add-exports ", "-add-modules ",217"-class-path ", "-module-path " };218String[] dropts = new String[] { "--add-exports ", "--add-modules ",219"--class-path ", "--module-path " };220testNoStartUp(221a -> assertCompletion(a, "/env |", false, ropts),222a -> assertCompletion(a, "/env -|", false, ropts),223a -> assertCompletion(a, "/env --|", false, dropts),224a -> assertCompletion(a, "/env --a|", false, "--add-exports ", "--add-modules "),225a -> assertCompletion(a, "/env -add-|", false, "-add-exports ", "-add-modules "),226a -> assertCompletion(a, "/env -class-path . |", false, ropts),227a -> assertCompletion(a, "/env -class-path . --|", false, dropts)228);229}230231@Test232public void testReset() {233String[] ropts = new String[] { "-add-exports ", "-add-modules ",234"-class-path ", "-module-path " };235String[] dropts = new String[] { "--add-exports ", "--add-modules ",236"--class-path ", "--module-path " };237testNoStartUp(238a -> assertCompletion(a, "/reset |", false, ropts),239a -> assertCompletion(a, "/res -m|", false, "-module-path "),240a -> assertCompletion(a, "/res -module-|", false, "-module-path "),241a -> assertCompletion(a, "/res --m|", false, "--module-path "),242a -> assertCompletion(a, "/res --module-|", false, "--module-path "),243a -> assertCompletion(a, "/reset -add|", false, "-add-exports ", "-add-modules "),244a -> assertCompletion(a, "/rese -class-path . |", false, ropts),245a -> assertCompletion(a, "/rese -class-path . --|", false, dropts)246);247}248249@Test250public void testVarsMethodsTypes() {251testNoStartUp(252a -> assertCompletion(a, "/v|", false, "/vars "),253a -> assertCompletion(a, "/m|", false, "/methods "),254a -> assertCompletion(a, "/t|", false, "/types "),255a -> assertClass(a, "class cTest {}", "class", "cTest"),256a -> assertMethod(a, "int mTest() { return 0; }", "()I", "mTest"),257a -> assertVariable(a, "int", "fTest"),258a -> assertCompletion(a, "/vars |", false, "-all", "-start ", "3 ", "fTest "),259a -> assertCompletion(a, "/meth |", false, "-all", "-start ", "2 ", "mTest "),260a -> assertCompletion(a, "/typ |", false, "-all", "-start ", "1 ", "cTest "),261a -> assertCompletion(a, "/var f|", false, "fTest ")262);263}264265@Test266public void testOpen() throws IOException {267Compiler compiler = new Compiler();268testNoStartUp(269a -> assertCompletion(a, "/o|", false, "/open ")270);271List<String> p1 = listFiles(Paths.get(""));272getRootDirectories().forEach(s -> p1.add(s.toString()));273Collections.sort(p1);274testNoStartUp(275a -> assertCompletion(a, "/open |", false, p1.toArray(new String[p1.size()]))276);277Path classDir = compiler.getClassDir();278List<String> p2 = listFiles(classDir);279testNoStartUp(280a -> assertCompletion(a, "/open " + classDir + "/|", false, p2.toArray(new String[p2.size()]))281);282}283284@Test285public void testSave() throws IOException {286Compiler compiler = new Compiler();287testNoStartUp(288a -> assertCompletion(a, "/s|", false, "/save ", "/set ")289);290List<String> p1 = listFiles(Paths.get(""));291Collections.addAll(p1, "-all ", "-history ", "-start ");292getRootDirectories().forEach(s -> p1.add(s.toString()));293Collections.sort(p1);294testNoStartUp(295a -> assertCompletion(a, "/save |", false, p1.toArray(new String[p1.size()]))296);297Path classDir = compiler.getClassDir();298List<String> p2 = listFiles(classDir);299testNoStartUp(300a -> assertCompletion(a, "/save " + classDir + "/|",301false, p2.toArray(new String[p2.size()])),302a -> assertCompletion(a, "/save -all " + classDir + "/|",303false, p2.toArray(new String[p2.size()]))304);305}306307@Test308public void testClassPath() throws IOException {309Compiler compiler = new Compiler();310Path outDir = compiler.getPath("testClasspathCompletion");311Files.createDirectories(outDir);312Files.createDirectories(outDir.resolve("dir"));313createIfNeeded(outDir.resolve("test.jar"));314createIfNeeded(outDir.resolve("test.zip"));315compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");316String jarName = "test.jar";317compiler.jar(outDir, jarName, "pkg/A.class");318compiler.getPath(outDir).resolve(jarName);319List<String> paths = listFiles(outDir, CLASSPATH_FILTER);320String[] pathArray = paths.toArray(new String[paths.size()]);321testNoStartUp(322a -> assertCompletion(a, "/env -class-path " + outDir + "/|", false, pathArray),323a -> assertCompletion(a, "/env --class-path " + outDir + "/|", false, pathArray),324a -> assertCompletion(a, "/env -clas " + outDir + "/|", false, pathArray),325a -> assertCompletion(a, "/env --class-p " + outDir + "/|", false, pathArray),326a -> assertCompletion(a, "/env --module-path . --class-p " + outDir + "/|", false, pathArray)327);328}329330@Test331public void testUserHome() throws IOException {332List<String> completions;333Path home = Paths.get(System.getProperty("user.home"));334try (Stream<Path> content = Files.list(home)) {335completions = content.filter(CLASSPATH_FILTER)336.map(file -> file.getFileName().toString() + (Files.isDirectory(file) ? "/" : ""))337.sorted()338.collect(Collectors.toList());339}340testNoStartUp(341a -> assertCompletion(a, "/env --class-path ~/|", false, completions.toArray(new String[completions.size()]))342);343}344345@Test346public void testSet() throws IOException {347List<String> p1 = listFiles(Paths.get(""));348getRootDirectories().forEach(s -> p1.add(s.toString()));349Collections.sort(p1);350351String[] modes = {"concise ", "normal ", "silent ", "verbose "};352String[] options = {"-command", "-delete", "-quiet"};353String[] modesWithOptions = Stream.concat(Arrays.stream(options), Arrays.stream(modes)).sorted().toArray(String[]::new);354test(false, new String[] {"--no-startup"},355a -> assertCompletion(a, "/se|", false, "/set "),356a -> assertCompletion(a, "/set |", false, "editor ", "feedback ", "format ", "indent ", "mode ", "prompt ", "start ", "truncation "),357358// /set editor359a -> assertCompletion(a, "/set e|", false, "editor "),360a -> assertCompletion(a, "/set editor |", false, p1.toArray(new String[p1.size()])),361362// /set feedback363a -> assertCompletion(a, "/set fe|", false, "feedback "),364a -> assertCompletion(a, "/set fe |", false, modes),365366// /set format367a -> assertCompletion(a, "/set fo|", false, "format "),368a -> assertCompletion(a, "/set fo |", false, modes),369370// /set mode371a -> assertCompletion(a, "/set mo|", false, "mode "),372a -> assertCompletion(a, "/set mo |", false),373a -> assertCompletion(a, "/set mo newmode |", false, modesWithOptions),374a -> assertCompletion(a, "/set mo newmode -|", false, options),375a -> assertCompletion(a, "/set mo newmode -command |", false),376a -> assertCompletion(a, "/set mo newmode normal |", false, options),377378// /set prompt379a -> assertCompletion(a, "/set pro|", false, "prompt "),380a -> assertCompletion(a, "/set pro |", false, modes),381382// /set start383a -> assertCompletion(a, "/set st|", false, "start "),384a -> assertCompletion(a, "/set st |", false, p1.toArray(new String[p1.size()])),385386// /set truncation387a -> assertCompletion(a, "/set tr|", false, "truncation "),388a -> assertCompletion(a, "/set tr |", false, modes)389);390}391392private void createIfNeeded(Path file) throws IOException {393if (!Files.exists(file))394Files.createFile(file);395}396private List<String> listFiles(Path path) throws IOException {397return listFiles(path, ACCEPT_ALL);398}399400private List<String> listFiles(Path path, Predicate<? super Path> filter) throws IOException {401try (Stream<Path> stream = Files.list(path)) {402return stream.filter(filter)403.map(p -> p.getFileName().toString() + (Files.isDirectory(p) ? "/" : ""))404.sorted()405.collect(Collectors.toList());406}407}408409private static final Predicate<? super Path> ACCEPT_ALL =410(file) -> !file.endsWith(".") && !file.endsWith("..");411412private static final Predicate<? super Path> CLASSPATH_FILTER =413(file) -> ACCEPT_ALL.test(file) &&414(Files.isDirectory(file) ||415file.getFileName().toString().endsWith(".jar") ||416file.getFileName().toString().endsWith(".zip"));417418private static Iterable<? extends Path> getRootDirectories() {419return StreamSupport.stream(FileSystems.getDefault()420.getRootDirectories()421.spliterator(),422false)423.filter(p -> Files.exists(p))424.collect(Collectors.toList());425}426}427428429