/* * 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() throws Exception { 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 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<Object>(); args.add(null); for (Object x : list) { args.set(0, x); closure.execute(session, args); } } }