| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.felix.gogo.runtime; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.StringWriter; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.regex.Pattern; |
| |
| import org.apache.felix.service.command.Process; |
| import org.apache.felix.gogo.runtime.Parser.Pipeline; |
| import org.apache.felix.gogo.runtime.Parser.Program; |
| import org.apache.felix.gogo.runtime.Parser.Sequence; |
| import org.apache.felix.gogo.runtime.Parser.Statement; |
| import org.apache.felix.service.command.CommandSession; |
| import org.apache.felix.service.command.Function; |
| import org.junit.Test; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.fail; |
| |
| public class TestParser extends AbstractParserTest |
| { |
| int beentheredonethat = 0; |
| |
| @Test |
| public void testError() { |
| Context context = new Context(); |
| context.addCommand("gogo", new Function() { |
| @Override |
| public Object execute(CommandSession session, List<Object> arguments) throws Exception { |
| throw new Error(arguments.get(0).toString()); |
| }}, "error"); |
| |
| try { |
| context.execute("error bar"); |
| fail("Expected an exception"); |
| } catch (Throwable t) { |
| assertEquals("java.util.concurrent.ExecutionException: java.lang.Error: bar", t.toString()); |
| } |
| } |
| |
| @Test |
| public void testEvaluatation() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| c.addCommand("capture", this); |
| |
| assertEquals("a", c.execute("echo a | capture")); |
| assertEquals("a", c.execute("(echo a) | capture")); |
| assertEquals("a", c.execute("((echo a)) | capture")); |
| } |
| |
| @Test |
| public void testUnknownCommand() throws Exception |
| { |
| Context c = new Context(); |
| try |
| { |
| c.execute("echo"); |
| fail("Execution should have failed due to missing command"); |
| } |
| catch (IllegalArgumentException e) |
| { |
| // expected |
| } |
| } |
| |
| @Test |
| public void testSpecialValues() throws Exception |
| { |
| Context c = new Context(); |
| assertEquals(false, c.execute("false")); |
| assertEquals(true, c.execute("true")); |
| assertEquals(null, c.execute("null")); |
| } |
| |
| @Test |
| public void testQuotes() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| c.set("c", "a"); |
| |
| assertEquals("a b", c.execute("echo a b")); |
| assertEquals("a b", c.execute("echo 'a b'")); |
| assertEquals("a b", c.execute("echo \"a b\"")); |
| assertEquals("a b", c.execute("echo a b")); |
| assertEquals("a b", c.execute("echo 'a b'")); |
| assertEquals("a b", c.execute("echo \"a b\"")); |
| assertEquals("a b", c.execute("echo $c b")); |
| assertEquals("$c b", c.execute("echo '$c b'")); |
| assertEquals("a b", c.execute("echo \"$c b\"")); |
| assertEquals("a b", c.execute("echo ${c} b")); |
| assertEquals("${c} b", c.execute("echo '${c} b'")); |
| assertEquals("a b", c.execute("echo \"${c} b\"")); |
| assertEquals("aa", c.execute("echo $c$c")); |
| assertEquals("a ;a", c.execute("echo a\\ \\;a")); |
| assertEquals("baabab", c.execute("echo b${c}${c}b${c}b")); |
| |
| c.set("d", "a b "); |
| assertEquals("a b ", c.execute("echo \"$d\"")); |
| } |
| |
| @Test |
| public void testScope() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| assertEquals("$a", c.execute("test:echo \\$a")); |
| assertEquals("file://poo", c.execute("test:echo file://poo")); |
| } |
| |
| @Test |
| public void testPipe() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| c.addCommand("capture", this); |
| c.addCommand("grep", this); |
| c.addCommand("echoout", this); |
| c.execute("myecho = { echoout $args }"); |
| |
| // Disable file name generation to avoid escaping 'd.*' |
| c.currentDir(null); |
| |
| assertEquals("def", c.execute("echo def|grep d.*|capture")); |
| assertEquals("def", c.execute("echoout def|grep d.*|capture")); |
| assertEquals("def", c.execute("myecho def|grep d.*|capture")); |
| assertEquals("def", c.execute("(echoout abc; echoout def; echoout ghi)|grep d.*|capture")); |
| assertEquals("", c.execute("echoout def; echoout ghi | grep d.* | capture")); |
| assertEquals("hello world", c.execute("echo hello world|capture")); |
| assertEquals("defghi", c.execute("(echoout abc; echoout def; echoout ghi)|grep 'def|ghi'|capture")); |
| } |
| |
| @Test |
| public void testAssignment() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| c.addCommand("grep", this); |
| assertEquals("a", c.execute("a = a; echo ${$a}")); |
| |
| assertEquals("hello", c.execute("echo hello")); |
| assertEquals("hello", c.execute("a = (echo hello)")); |
| //assertEquals("a", c.execute("a = a; echo $(echo a)")); // #p2 - no eval in var expansion |
| assertEquals("3", c.execute("a=3; echo $a")); |
| assertEquals("3", c.execute("a = 3; echo $a")); |
| assertEquals("a", c.execute("a = a; echo ${$a}")); |
| } |
| |
| @Test |
| public void testComment() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| assertEquals("1", c.execute("echo 1 // hello")); |
| } |
| |
| @Test |
| public void testClosure() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| c.addCommand("capture", this); |
| |
| assertEquals("a", c.execute("e = { echo $1 } ; e a b")); |
| assertEquals("b", c.execute("e = { echo $2 } ; e a b")); |
| assertEquals("b", c.execute("e = { eval $args } ; e echo b")); |
| assertEquals("ca b", c.execute("e = { echo c$args } ; e a b")); |
| assertEquals("c a b", c.execute("e = { echo c $args } ; e a b")); |
| assertEquals("ca b", c.execute("e = { echo c$args } ; e 'a b'")); |
| } |
| |
| @Test |
| public void testArray() throws Exception |
| { |
| Context c = new Context(); |
| c.set("echo", true); |
| assertEquals("http://www.aqute.biz?com=2&biz=1", |
| c.execute("['http://www.aqute.biz?com=2&biz=1'] get 0")); |
| assertEquals("{a=2, b=3}", c.execute("[a=2 b=3]").toString()); |
| assertEquals(3L, c.execute("[a=2 b=3] get b")); |
| assertEquals("[3, 4]", c.execute("[1 2 [3 4] 5 6] get 2").toString()); |
| assertEquals(5, c.execute("[1 2 [3 4] 5 6] size")); |
| } |
| |
| @Test |
| public void testParentheses() |
| { |
| Parser parser = new Parser("(a|b)|(d|f)"); |
| Program p = parser.program(); |
| assertEquals("a|b", ((Sequence) ((Statement) ((Pipeline) p.tokens().get(0)).tokens().get(0)).tokens().get(0)).program().toString()); |
| |
| parser = new Parser("grep (d.*)|grep (d|f)"); |
| p = parser.program(); |
| assertEquals("d.*", ((Sequence)((Statement) ((Pipeline) p.tokens().get(0)).tokens().get(0)).tokens().get(1)).program().toString()); |
| } |
| |
| @Test |
| public void testEcho() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| c.execute("echo peter"); |
| } |
| |
| public void grep(String match) throws IOException |
| { |
| Pattern p = Pattern.compile(match); |
| BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in)); |
| String s = rdr.readLine(); |
| while (s != null) |
| { |
| if (p.matcher(s).find()) |
| { |
| System.out.println(s); |
| } |
| s = rdr.readLine(); |
| } |
| } |
| |
| public String capture() throws IOException |
| { |
| StringWriter sw = new StringWriter(); |
| BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in)); |
| String s = rdr.readLine(); |
| while (s != null) |
| { |
| sw.write(s); |
| s = rdr.readLine(); |
| } |
| return sw.toString(); |
| } |
| |
| @Test |
| public void testVars() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| |
| assertEquals("", c.execute("echo ${very.likely.that.this.does.not.exist}")); |
| assertNotNull(c.execute("echo ${java.shell.name}")); |
| assertEquals("a", c.execute("a = a; echo ${a}")); |
| } |
| |
| @Test |
| public void testFunny() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("echo", this); |
| assertEquals("a", c.execute("echo a") + ""); |
| assertEquals("a", c.execute("eval (echo echo) a") + ""); |
| //assertEquals("a", c.execute("((echo echo) echo) (echo a)") + ""); |
| assertEquals("3", c.execute("[a=2 (echo b)=(echo 3)] get b").toString()); |
| } |
| |
| public CharSequence echo(Object args[]) |
| { |
| if (args == null) |
| { |
| return ""; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| for (Object arg : args) |
| { |
| if (arg != null) |
| { |
| if (sb.length() > 0) |
| sb.append(' '); |
| sb.append(arg); |
| } |
| } |
| return sb.toString(); |
| } |
| |
| public void echoout(Object args[]) |
| { |
| System.out.println(echo(args)); |
| } |
| |
| @Test |
| public void testContext() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("ls", this); |
| beentheredonethat = 0; |
| c.execute("ls"); |
| assertEquals(1, beentheredonethat); |
| |
| beentheredonethat = 0; |
| c.execute("ls 10"); |
| assertEquals(10, beentheredonethat); |
| |
| beentheredonethat = 0; |
| c.execute("ls a b c d e f g h i j"); |
| assertEquals(10, beentheredonethat); |
| |
| beentheredonethat = 0; |
| Integer result = (Integer) c.execute("ls (ls 5)"); |
| assertEquals(10, beentheredonethat); |
| assertEquals((Integer) 5, result); |
| } |
| |
| public void ls() |
| { |
| beentheredonethat++; |
| System.out.println("ls(): Yes!"); |
| } |
| |
| public int ls(int onoff) |
| { |
| beentheredonethat += onoff; |
| System.out.println("ls(int) " + onoff); |
| return onoff; |
| } |
| |
| public void ls(Object args[]) |
| { |
| beentheredonethat = args.length; |
| System.out.print("ls(Object[]) ["); |
| for (Object i : args) |
| { |
| System.out.print(i + " "); |
| } |
| System.out.println("]"); |
| } |
| |
| @Test |
| public void testProgram() |
| { |
| Program x = new Parser("abc def|ghi jkl;mno pqr|stu vwx").program(); |
| Pipeline p0 = (Pipeline) x.tokens().get(0); |
| Statement s00 = (Statement) p0.tokens().get(0); |
| assertEquals("|", p0.tokens().get(1).toString()); |
| Statement s01 = (Statement) p0.tokens().get(2); |
| assertEquals(";", x.tokens().get(1).toString()); |
| Pipeline p1 = (Pipeline) x.tokens().get(2); |
| Statement s10 = (Statement) p1.tokens().get(0); |
| assertEquals("|", p1.tokens().get(1).toString()); |
| Statement s11 = (Statement) p1.tokens().get(2); |
| assertEquals("abc", s00.tokens().get(0).toString()); |
| assertEquals("def", s00.tokens().get(1).toString()); |
| assertEquals("ghi", s01.tokens().get(0).toString()); |
| assertEquals("jkl", s01.tokens().get(1).toString()); |
| assertEquals("mno", s10.tokens().get(0).toString()); |
| assertEquals("pqr", s10.tokens().get(1).toString()); |
| assertEquals("stu", s11.tokens().get(0).toString()); |
| assertEquals("vwx", s11.tokens().get(1).toString()); |
| } |
| |
| @Test |
| public void testStatements() |
| { |
| Program x = new Parser("abc def|ghi jkl|mno pqr").program(); |
| Pipeline p0 = (Pipeline) x.tokens().get(0); |
| Statement s00 = (Statement) p0.tokens().get(0); |
| Statement s01 = (Statement) p0.tokens().get(2); |
| Statement s02 = (Statement) p0.tokens().get(4); |
| assertEquals("abc", s00.tokens().get(0).toString()); |
| assertEquals("def", s00.tokens().get(1).toString()); |
| assertEquals("ghi", s01.tokens().get(0).toString()); |
| assertEquals("jkl", s01.tokens().get(1).toString()); |
| assertEquals("mno", s02.tokens().get(0).toString()); |
| assertEquals("pqr", s02.tokens().get(1).toString()); |
| } |
| |
| @Test |
| public void testPipeRedir() |
| { |
| Program x = new Parser("abc def|&ghi").program(); |
| Pipeline p0 = (Pipeline) x.tokens().get(0); |
| Statement s00 = (Statement) p0.tokens().get(0); |
| assertEquals("|&", p0.tokens().get(1).toString()); |
| Statement s01 = (Statement) p0.tokens().get(2); |
| assertEquals("abc", s00.tokens().get(0).toString()); |
| assertEquals("def", s00.tokens().get(1).toString()); |
| assertEquals("ghi", s01.tokens().get(0).toString()); |
| } |
| |
| @Test |
| public void testPipeAndOr() |
| { |
| Program x = new Parser("abc|def&&ghi || jkl").program(); |
| Pipeline p0 = (Pipeline) x.tokens().get(0); |
| Statement s00 = (Statement) p0.tokens().get(0); |
| assertEquals("|", p0.tokens().get(1).toString()); |
| Statement s01 = (Statement) p0.tokens().get(2); |
| assertEquals("&&", x.tokens().get(1).toString()); |
| Statement s1 = (Statement) x.tokens().get(2); |
| assertEquals("||", x.tokens().get(3).toString()); |
| Statement s2 = (Statement) x.tokens().get(4); |
| assertEquals("abc", s00.tokens().get(0).toString()); |
| assertEquals("def", s01.tokens().get(0).toString()); |
| assertEquals("ghi", s1.tokens().get(0).toString()); |
| assertEquals("jkl", s2.tokens().get(0).toString()); |
| } |
| |
| @Test |
| public void testBackground() { |
| Program x = new Parser("echo foo&echo bar").program(); |
| Statement s0 = (Statement) x.tokens().get(0); |
| assertEquals("&", x.tokens().get(1).toString()); |
| Statement s1 = (Statement) x.tokens().get(2); |
| assertEquals("echo", s0.tokens().get(0).toString()); |
| assertEquals("foo", s0.tokens().get(1).toString()); |
| assertEquals("echo", s1.tokens().get(0).toString()); |
| assertEquals("bar", s1.tokens().get(1).toString()); |
| } |
| |
| @Test |
| public void testRedir() { |
| Program x = new Parser("echo foo&>bar").program(); |
| Statement s0 = (Statement) x.tokens().get(0); |
| assertEquals("echo", s0.tokens().get(0).toString()); |
| assertEquals("foo", s0.tokens().get(1).toString()); |
| assertEquals("&>", s0.redirections().get(0).toString()); |
| assertEquals("bar", s0.redirections().get(1).toString()); |
| |
| x = new Parser("echo foo1>bar").program(); |
| s0 = (Statement) x.tokens().get(0); |
| assertEquals("echo", s0.tokens().get(0).toString()); |
| assertEquals("foo1", s0.tokens().get(1).toString()); |
| assertEquals(">", s0.redirections().get(0).toString()); |
| assertEquals("bar", s0.redirections().get(1).toString()); |
| |
| x = new Parser("echo foo 1>bar").program(); |
| s0 = (Statement) x.tokens().get(0); |
| assertEquals("echo", s0.tokens().get(0).toString()); |
| assertEquals("foo", s0.tokens().get(1).toString()); |
| assertEquals("1>", s0.redirections().get(0).toString()); |
| assertEquals("bar", s0.redirections().get(1).toString()); |
| } |
| |
| @Test |
| public void testClosingSquareBracket() |
| { |
| expectSyntaxError("{ a } }"); |
| expectSyntaxError("a }"); |
| expectSyntaxError("}"); |
| expectSyntaxError("{ a } ]"); |
| expectSyntaxError("a ]"); |
| expectSyntaxError("]"); |
| } |
| |
| private void expectSyntaxError(String txt) { |
| try { |
| new Parser(txt).program(); |
| fail("Expected a SyntaxError to be thrown"); |
| } catch (SyntaxError e) { |
| // ok |
| } |
| } |
| |
| @Test |
| public void testSimpleValue() |
| { |
| Program p = new Parser( |
| "abc def.ghi http://www.osgi.org?abc=\\&x=1 [1,2,3] {{{{{{{xyz}}}}}}} (immediate) {'{{{{{'} {\\{} 'abc{}'") |
| .program(); |
| List<Token> x = ((Statement) p.tokens().get(0)).tokens(); |
| assertEquals("abc", x.get(0).toString()); |
| assertEquals("def.ghi", x.get(1).toString()); |
| assertEquals("http://www.osgi.org?abc=\\&x=1", x.get(2).toString()); |
| assertEquals("[1,2,3]", x.get(3).toString()); |
| assertEquals("{{{{{{{xyz}}}}}}}", x.get(4).toString()); |
| assertEquals("(immediate)", x.get(5).toString()); |
| assertEquals("{'{{{{{'}", x.get(6).toString()); |
| assertEquals("{\\{}", x.get(7).toString()); |
| assertEquals("'abc{}'", x.get(8).toString()); |
| } |
| |
| @Test |
| public void testIsTty() throws Exception |
| { |
| Context c = new Context(); |
| c.addCommand("istty", this); |
| c.addCommand("echo", this); |
| assertEquals(true, c.execute("istty 1")); |
| assertEquals(false, c.execute("$(istty 1)")); |
| } |
| |
| public boolean istty(CommandSession session, int fd) |
| { |
| return Process.Utils.current().isTty(fd); |
| } |
| |
| void each(CommandSession session, Collection<Object> list, Function closure) |
| throws Exception |
| { |
| List<Object> args = new ArrayList<>(); |
| args.add(null); |
| for (Object x : list) |
| { |
| args.set(0, x); |
| closure.execute(session, args); |
| } |
| } |
| |
| } |