/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.test.shell.bjorne;
import java.util.Set;
import javax.naming.NamingException;
import org.jnode.shell.CommandCompletions;
import org.jnode.shell.Completable;
import org.jnode.shell.ShellSyntaxException;
import org.jnode.shell.ShellUtils;
import org.jnode.shell.alias.AliasManager;
import org.jnode.shell.bjorne.BjorneInterpreter;
import org.jnode.shell.help.CompletionException;
import org.jnode.shell.syntax.ArgumentSyntax;
import org.jnode.shell.syntax.EmptySyntax;
import org.jnode.shell.syntax.OptionSyntax;
import org.jnode.shell.syntax.RepeatSyntax;
import org.jnode.shell.syntax.SequenceSyntax;
import org.jnode.shell.syntax.SyntaxBundle;
import org.jnode.shell.syntax.SyntaxManager;
import org.jnode.test.shell.Cassowary;
import org.jnode.test.shell.syntax.TestShell;
import org.junit.Assert;
import org.junit.Test;
/**
* Tests for completion in the bjorne interpreter. Some of the sample commands
* are nonsensical ... but that's OK because we're only interested in completion
* behavior.
*
* @author crawley@jnode.org
*/
public class BjorneCompletionTest {
static TestShell shell;
static {
try {
Cassowary.initEnv();
shell = new TestShell();
ShellUtils.getShellManager().registerShell(shell);
AliasManager am = shell.getAliasManager();
am.add("gc", "org.jnode.command.system.GcCommand");
am.add("cpuid", "org.jnode.test.shell.MyCpuIDCommand");
am.add("set", "org.jnode.command.system.SetCommand");
am.add("dir", "org.jnode.test.shell.MyDirCommand");
am.add("duh", "org.jnode.test.shell.MyDuhCommand");
am.add("cat", "org.jnode.test.shell.MyCatCommand");
am.add("echo", "org.jnode.test.shell.MyEchoCommand");
am.add("alias", "org.jnode.test.shell.MyAliasCommand");
SyntaxManager sm = shell.getSyntaxManager();
sm.add(new SyntaxBundle("set", new SequenceSyntax(new ArgumentSyntax("key"),
new ArgumentSyntax("value"))));
sm.add(new SyntaxBundle("duh", new ArgumentSyntax("path")));
sm.add(new SyntaxBundle("echo", new RepeatSyntax(new ArgumentSyntax("text"))));
sm.add(new SyntaxBundle("cpuid", new SequenceSyntax()));
sm.add(new SyntaxBundle("alias", new EmptySyntax(null,
"Print all available aliases and corresponding classnames"),
new SequenceSyntax(null, "Set an aliases for given classnames",
new ArgumentSyntax("alias"), new ArgumentSyntax("classname")),
new OptionSyntax("remove", 'r', null, "Remove an alias")));
} catch (NamingException ex) {
throw new RuntimeException(ex);
}
}
@Test
public void testSimpleCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("echo hi", "TE");
}
@Test
public void testListCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("echo hi ; echo", "TETT");
}
@Test
public void testAndCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("echo hi && echo", "TETT");
}
@Test
public void testPipeCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("echo hi | echo", "TETT");
}
@Test
public void testPipe2Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("echo hi |\necho", "TETT");
}
@Test
public void testSourceCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("source /", "TT");
}
@Test
public void testIfCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then echo hi ; fi", "TTTTTETT");
}
@Test
public void testIf2Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if\ncpuid ; then echo hi ; fi", "TTTTTETT");
}
@Test
public void testIf3Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid\nthen echo hi ; fi", "TTTTETT");
}
@Test
public void testIf4Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then\necho hi ; fi", "TTTTTETT");
}
@Test
public void testIf5Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then\necho hi\nfi", "TTTTTET");
}
@Test
public void testIfElseCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then echo hi ; else echo ho ; fi", "TTTTTETTTETT");
}
@Test
public void testIfElse2Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then echo hi ; else\necho ho ; fi", "TTTTTETTTETT");
}
@Test
public void testIfElse3Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then echo hi ; else echo ho\nfi", "TTTTTETTTET");
}
@Test
public void testIfElifCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then echo hi ; elif cpuid ; then echo ho ; fi",
"TTTTTETTTTTTETT");
}
@Test
public void testIfElif2Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then echo hi ; elif\ncpuid ; then echo ho ; fi",
"TTTTTETTTTTTETT");
}
@Test
public void testIfElif3Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then echo hi ; elif cpuid\nthen echo ho ; fi",
"TTTTTETTTTTETT");
}
@Test
public void testIfElif4Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("if cpuid ; then echo hi ; elif cpuid ; then\necho ho ; fi",
"TTTTTETTTTTTETT");
}
@Test
public void testWhileCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("while cpuid ; do echo hi ; done", "TTTTTETT");
}
@Test
public void testWhile2Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("while\ncpuid ; do echo hi ; done", "TTTTTETT");
}
@Test
public void testWhile3Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("while cpuid\ndo echo hi ; done", "TTTTETT");
}
@Test
public void testWhile4Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("while cpuid ; do\necho hi ; done", "TTTTTETT");
}
@Test
public void testWhile5Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("while cpuid ; do echo hi\ndone", "TTTTTET");
}
@Test
public void testForCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("for X in 1 2 3 ; do echo hi ; done", "TFTEEETTTETT");
}
@Test
public void testFor2Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("for X in 1 2 3\ndo echo hi ; done", "TFTEEETTETT");
}
@Test
public void testFor3Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("for X in 1 2 3 ; do\necho hi ; done", "TFTEEETTTETT");
}
@Test
public void testFor4Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("for X in 1 2 3 ; do echo hi\ndone", "TFTEEETTTET");
}
@Test
public void testCaseCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("case 3 in ( 1 | 2 ) echo hi ;; 3 ) echo bye ; esac", "TFTTFTFTTETETTETT");
}
@Test
public void testCase2Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("case 3\nin ( 1 | 2 ) echo hi ;; 3 ) echo bye ; esac", "TFTTFTFTTETETTETT");
}
@Test
public void testCase3Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("case 3 in\n( 1 | 2 ) echo hi ;; 3 ) echo bye ; esac", "TFTTFTFTTETETTETT");
}
@Test
public void testCase4Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("case 3 in ( 1 | 2 )\necho hi ;; 3 ) echo bye ; esac", "TFTTFTFTTETETTETT");
}
@Test
public void testCase5Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("case 3 in ( 1 | 2 ) echo hi\n;; 3 ) echo bye ; esac", "TFTTFTFTTETETTETT");
}
@Test
public void testCase6Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("case 3 in ( 1 | 2 ) echo hi ;;\n3 ) echo bye ; esac", "TFTTFTFTTETETTETT");
}
@Test
public void testCase7Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("case 3 in ( 1 | 2 ) echo hi ;; 3 )\necho bye ; esac", "TFTTFTFTTETETTETT");
}
@Test
public void testCase8Command() throws ShellSyntaxException, CompletionException {
doCompletionTest("case 3 in ( 1 | 2 ) echo hi ;; 3 ) echo bye\nesac", "TFTTFTFTTETETTET");
}
@Test
public void testBadCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("cpuid hi", "TE");
}
@Test
public void testBad2Command() throws ShellSyntaxException, CompletionException {
try {
doCompletionTest("if fi ;", "T??");
} catch (CompletionException ex) {
Assert.assertEquals("Cannot find an alias or load a command class for 'fi'",
ex.getMessage());
}
}
@Test
public void testRedirCommand() throws ShellSyntaxException, CompletionException {
doCompletionTest("echo hi > /", "TETZ");
}
private void doCompletionTest(String input, String flags)
throws ShellSyntaxException, CompletionException {
BjorneInterpreter interpreter = new BjorneInterpreter();
for (int i = 0; i <= input.length(); i++) {
String partial = input.substring(0, i);
int inWord = 0;
int wordStart = 0;
for (int j = 0; j < i; j++) {
if (Character.isWhitespace(partial.charAt(j))) {
inWord++;
wordStart = j + 1;
}
}
String lastWord = partial.substring(wordStart);
Completable completable = interpreter.parsePartial(shell, partial);
CommandCompletions completions = new CommandCompletions();
completable.complete(completions, shell);
Set<String> completionWords = completions.getCompletions();
switch (flags.charAt(inWord)) {
case 'T':
// Expect completions
Assert.assertTrue("got no completions: " + diag(partial, completions),
completionWords.size() > 0);
break;
case 'F':
// Expect no completions
Assert.assertTrue("got unexpected completions: " + diag(partial, completions),
completionWords.size() == 0);
break;
case 'E':
// Expect completions if the last char is ' ', otherwise not
if (wordStart >= partial.length()) {
Assert.assertTrue("got no completions: " + diag(partial, completions),
completionWords.size() > 0);
} else {
Assert.assertTrue(
"got unexpected completions: " + diag(partial, completions),
completionWords.size() == 0);
}
break;
case 'Z':
// Expect completions if the last char is NOT ' '
if (wordStart >= partial.length()) {
//
} else {
Assert.assertTrue("got no completions: " + diag(partial, completions),
completionWords.size() > 0);
}
break;
case '?':
// Maybe completions, maybe not
}
for (String completionWord : completionWords) {
if (!completionWord.startsWith(lastWord)) {
Assert.fail("completion(s) don't start with '" + lastWord + "': " +
diag(partial, completions));
}
}
}
}
private String diag(String partial, CommandCompletions completions) {
return "partial = '" + partial + "', completions = " + completions;
}
}