blob: 753e8338199ae4a99f91287030d8d6df29fb6a37 [file] [log] [blame]
/*
* 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.sling.pipes.internal;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.pipes.AbstractPipeTest;
import org.apache.sling.pipes.ExecutionResult;
import org.apache.sling.pipes.PipeBuilder;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.apache.sling.testing.mock.sling.servlet.MockRequestPathInfo;
import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletResponse;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.apache.sling.pipes.internal.CommandExecutorImpl.PARAMS_SEPARATOR;
import static org.apache.sling.pipes.internal.CommandUtil.keyValuesToArray;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonString;
import javax.servlet.ServletException;
public class CommandExecutorImplTest extends AbstractPipeTest {
CommandExecutorImpl commands;
@Before
public void setup() throws PersistenceException {
super.setup();
context = new SlingContext(ResourceResolverType.JCR_OAK);
context.load().json("/initial-content/content/fruits.json", PATH_FRUITS);
commands = new CommandExecutorImpl();
commands.plumber = plumber;
}
@Test
public void getSublist() {
assertArrayEquals(new String[]{"check", "this"}, commands.getSpaceSeparatedTokens("check this").toArray());
assertArrayEquals(new String[]{"and", "now","check this"}, commands.getSpaceSeparatedTokens("and now \"check this\"").toArray());
}
@Test
public void testParseTokens() {
List<CommandExecutorImpl.Token> tokens = commands.parseTokens("some isolated items");
assertEquals("there should be 1 token", 1, tokens.size());
CommandExecutorImpl.Token token = tokens.get(0);
assertEquals("pipe key should be 'some'", "some", token.pipeKey);
assertEquals("pipe args should be isolated, items", Arrays.asList("isolated", "items"), token.args);
}
@Test
public void testParseTokensWithQuotes() {
String tokenString = "first arg | second firstarg secondarg @ name second | third blah";
List<CommandExecutorImpl.Token> tokens = commands.parseTokens(tokenString);
assertEquals("there should be 3 tokens", 3, tokens.size());
assertEquals("keys check", Arrays.asList("first","second", "third"), tokens.stream().map(t -> t.pipeKey).collect(Collectors.toList()));
assertEquals("params check", "second", tokens.get(1).options.name);
}
@Test
public void testParseJson() {
String tokenString = "json [{\"title\":\"this is the first\", \"path\":\"/content/nested/two\"}, {\"title\":\"this is the second\", \"path\":\"/content/nested/three\"}]";
List<CommandExecutorImpl.Token> tokens = commands.parseTokens(tokenString);
assertEquals("there should be 1 token", 1, tokens.size());
assertEquals("there should be 1 arg", 1, tokens.get(0).args.size());
}
@Test
public void testQuotedTokens() {
List<CommandExecutorImpl.Token> tokens = commands.parseTokens("some isolated items \"with quotes\"");
assertEquals("there should be 1 token", 1, tokens.size());
CommandExecutorImpl.Token token = tokens.get(0);
assertEquals("pipe args should be isolated, items", Arrays.asList("isolated", "items", "with quotes"), token.args);
}
@Test
public void testKeyValueToArray() {
assertArrayEquals("1", new String[]{"one","two","three","four"}, keyValuesToArray(Arrays.asList("one=two","three=four")));
assertArrayEquals("2", new String[]{"one","two","three","${four}"}, keyValuesToArray(Arrays.asList("one=two","three=${four}")));
assertArrayEquals("3", new String[]{"${one == 'check'? 'three':'four'}","two"}, keyValuesToArray((Arrays.asList("${one == 'check'? 'three':'four'}=two"))));
assertArrayEquals("4", new String[]{"a_b-c","two"}, keyValuesToArray((Arrays.asList("a_b-c=two"))));
assertArrayEquals("5", new String[]{"one","two","three","${four == 'blah' ? 'five' : 'six'}"},
keyValuesToArray(Arrays.asList("one=two","three=${four == 'blah' ? 'five' : 'six'}")));
assertArrayEquals("6", new String[]{"jcr:content/singer","${'ringo' == one ? false : true}"}, keyValuesToArray(Arrays.asList("jcr:content/singer=${'ringo' == one ? false : true}")));
}
@Test
public void testSimpleExpression() throws Exception {
PipeBuilder builder = commands.parse(context.resourceResolver(),"echo /content/fruits");
assertTrue("there should be a resource", builder.build().getOutput().hasNext());
}
@Test
public void testSimpleChainedConf() throws Exception {
PipeBuilder builder = commands.parse(context.resourceResolver(),"echo /content/fruits | write some=test key=value");
assertNotNull("there should be a resource", builder.run());
ValueMap props = context.currentResource(PATH_FRUITS).getValueMap();
assertEquals("there should some=test", "test", props.get("some"));
assertEquals("there should key=value", "value", props.get("key"));
}
@Test
public void testOptions() {
String expected = "works";
String optionString = "name works @ path works @ expr works @ with one=works two=works @ outputs one=works two=works";
CommandExecutorImpl.Options options = commands.getOptions(optionString.split(PARAMS_SEPARATOR));
assertEquals("check name", expected, options.name);
assertEquals("check expr", expected, options.expr);
assertEquals("check path", expected, options.path);
Map bindings = new HashMap();
CommandUtil.writeToMap(bindings, true, options.with);
assertEquals("check with first", expected, bindings.get("one"));
assertEquals("check with second", expected, bindings.get("two"));
assertNotNull("a writer should have been created", options.outputs);
}
@Test
public void testOptionsListsWithOneItem() {
String expected = "works";
String optionString = "with one=works @ outputs one=works";
CommandExecutorImpl.Options options = commands.getOptions(optionString.split(PARAMS_SEPARATOR));
Map bindings = new HashMap();
CommandUtil.writeToMap(bindings, true, options.with);
assertEquals("check with first", expected, bindings.get("one"));
assertNotNull("a writer should have been created", options.outputs);
}
@Test
public void testChainedConfWithInternalOptions() throws Exception {
PipeBuilder builder = commands.parse(context.resourceResolver(),
"echo /content/fruits @ name fruits | write some=${path.fruits} key=value");
assertNotNull("there should be a resource", builder.run());
ValueMap props = context.currentResource(PATH_FRUITS).getValueMap();
assertEquals("there should some=/content/fruits", PATH_FRUITS, props.get("some"));
assertEquals("there should key=value", "value", props.get("key"));
}
@Test
public void testNonBreakingSpaces() throws InvocationTargetException, IllegalAccessException {
ExecutionResult result = execute("echo /content | mkdir test @ name child");
assertEquals(1, result.size());
}
@Test
public void adaptToDemoTest() throws Exception {
String url = "'http://99-bottles-of-beer.net/lyrics.html'";
String cmd = "egrep " + url + " @ name bottles @ with pattern=(?<number>\\d(\\d)?) | mkdir /var/bottles/${bottles.number}";
PipeBuilder builder = commands.parse(context.resourceResolver(), cmd);
ContainerPipe pipe = (ContainerPipe)builder.build();
ValueMap regexp = pipe.getResource().getChild("conf/bottles").getValueMap();
assertEquals("we expect expr to be the url", url, regexp.get("expr"));
}
@Test
public void testExecuteWithWriter() throws Exception {
PipeBuilder builder = plumber.newPipe(context.resourceResolver()).echo("/content/${node}").$("nt:base");
String path = builder.build().getResource().getPath();
ExecutionResult result = commands.execute(context.resourceResolver(), path, "outputs title=two['jcr:title'] desc=two['jcr:description']", "with node=fruits");
assertNotNull(result);
}
String testRawServlet(Map<String,Object> params) throws IOException {
MockSlingHttpServletRequest request = context.request();
MockSlingHttpServletResponse response = context.response();
request.setParameterMap(params);
MockRequestPathInfo pathInfo = (MockRequestPathInfo)request.getRequestPathInfo();
pathInfo.setExtension("json");
request.setMethod("POST");
commands.doPost(request, response);
if (response.getStatus() != 200) {
System.out.println(response.getOutputAsString());
}
assertEquals(200, response.getStatus());
return response.getOutputAsString();
}
JsonObject testServlet(Map<String,Object> params) throws ServletException, IOException {
return (JsonObject) JsonUtil.parse(testRawServlet(params));
}
@Test
public void testHelp() throws ServletException, IOException {
Map<String, Object> params = new HashMap<>();
params.put(CommandExecutorImpl.REQ_PARAM_HELP, "blah");
String response = testRawServlet(params);
assertTrue(StringUtils.isNotBlank(response));
}
@Test
public void testSimpleCommandServlet() throws IOException, ServletException {
Map<String, Object> params = new HashMap<>();
params.put(CommandExecutorImpl.REQ_PARAM_CMD, "echo /content | mkdir foo | write type=bar");
JsonObject response = testServlet(params);
assertEquals(1, response.getJsonNumber("size").intValue());
assertEquals("/content/foo", response.getJsonArray("items").getString(0));
}
@Test
public void testMultipeLineGetCommandLine() throws IOException, ServletException {
Map<String, Object> params = new HashMap<>();
params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/commandsFormats"
+ ".txt"), "UTF-8"));
MockSlingHttpServletRequest request = context.request();
request.setParameterMap(params);
request.setMethod("POST");
List<String> cmdList = commands.getCommandList(context.request());
assertEquals(5, cmdList.size());
for (int i = 0; i < 3; i ++) {
assertEquals("echo /content | $ /apps/pipes-it/fruit | children nt:unstructured", cmdList.get(i));
}
assertEquals ("echo /content | write one=foo nested/two=foo nested/three=foo", cmdList.get(3));
assertEquals("echo /content | json [{\"title\":\"this is the first\", \"path\":\"/content/nested/two\"}, {\"title\":\"this is the second\", \"path\":\"/content/nested/three\"}] @ name test | echo ${test.path}", cmdList.get(4));
}
String[] getItemsArray(JsonObject response) {
JsonArray jsonItems = response.getJsonArray("items");
List<String> items = jsonItems.stream().map(o -> ((JsonString)o).getString()).collect(Collectors.toList());
return items.toArray(new String[jsonItems.size()]);
}
@Test
public void testChainedCommand() throws IOException, ServletException {
Map<String, Object> params = new HashMap<>();
params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/chainedCommand"
+ ".txt"), "UTF-8"));
JsonObject response = testServlet(params);
assertEquals(5, response.getJsonNumber("size").intValue());
assertArrayEquals(new String[]{ "/content/fruits/banana/isnota/pea","/content/fruits/banana/isnota/carrot",
"/content/fruits/apple/isnota/pea","/content/fruits/apple/isnota/plum",
"/content/fruits/apple/isnota/carrot"}, getItemsArray(response));
}
@Test
public void testFileCommandServlet() throws IOException, ServletException {
Map<String, Object> params = new HashMap<>();
params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/testcommand"
+ ".txt"), "UTF-8"));
JsonObject response = testServlet(params);
assertEquals(5, response.getJsonNumber("size").intValue());
assertArrayEquals(new String[]{"/content/beatles/john", "/content/beatles/paul", "/content/beatles/georges",
"/content/beatles/ringo", "/content/beatles/ringo/jcr:content"}, getItemsArray(response));
}
}