blob: 8aaed200cba861df3050eeb0febf51f0e75fe9f5 [file] [log] [blame]
/*
* Copyright 2015-2016 IBM Corporation
*
* Licensed 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 system.basic;
import static common.WskCli.Item.Action;
import static common.WskCli.Item.Activation;
import static common.WskCli.Item.Rule;
import static common.WskCli.Item.Trigger;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.google.code.tempusfugit.concurrency.ParallelRunner;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import common.TestUtils;
import common.WskCli;
/**
* Tests for rules using command line interface
*/
@RunWith(ParallelRunner.class)
public class CLIRuleTests {
private static final Boolean usePythonCLI = false;
private static final WskCli wsk = new WskCli(usePythonCLI);
private static final int RULE_DELAY = 30;
private static final int DELAY = 90;
// NEGATIVE_DELAY is used for tests when checking that something doesn't
// show up in activations
private static final int NEGATIVE_DELAY = 30;
@BeforeClass
public static void setUp() throws Exception {
}
/**
* rule test with one trigger and one action
*/
@Test
public void rule1to1() throws Exception {
try {
wsk.sanitize(Rule, "R_121");
wsk.sanitize(Action, "A_121");
wsk.sanitize(Trigger, "T_121");
wsk.createAction("A_121", TestUtils.getCatalogFilename("samples/wc.js"));
wsk.createTrigger("T_121");
wsk.createRule("R_121", "T_121", "A_121");
long beforeTrigger = System.currentTimeMillis();
wsk.trigger("T_121", "bob 121");
String expected = "The message 'bob 121' has";
List<String> activationIds = wsk.waitForActivations("A_121", 1, beforeTrigger, DELAY);
assertTrue("Not enough activation ids found", activationIds != null);
// the most recent id
String activationId = activationIds.get(0);
assertTrue("Expected message not found: " + expected, wsk.logsForActivationContain(activationId, expected, DELAY));
} finally {
wsk.delete(Rule, "R_121");
wsk.delete(Action, "A_121");
wsk.delete(Trigger, "T_121");
}
}
/**
* rule test with one trigger and one action (action has space in name)
*/
@Test
public void rule1to1WithSpaceInActionName() throws Exception {
try {
wsk.sanitize(Rule, "R_121s");
wsk.sanitize(Action, "A_121s A_121s");
wsk.sanitize(Trigger, "T_121s");
wsk.createAction("A_121s A_121s", TestUtils.getCatalogFilename("samples/wc.js"));
wsk.createTrigger("T_121s");
wsk.createRule("R_121s", "T_121s", "A_121s A_121s");
long beforeTrigger = System.currentTimeMillis();
wsk.trigger("T_121s", "bob 121");
String expected = "The message 'bob 121' has";
List<String> activationIds = wsk.waitForActivations("A_121s A_121s", 1, beforeTrigger, DELAY);
assertTrue("Not enough activation ids found", activationIds != null);
// the most recent id
String activationId = activationIds.get(0);
assertTrue("Expected message not found: " + expected, wsk.logsForActivationContain(activationId, expected, DELAY));
} finally {
wsk.delete(Rule, "R_121s");
wsk.delete(Action, "A_121s A_121s");
wsk.delete(Trigger, "T_121s");
}
}
/**
* rule test with two triggers and one action
*/
@Test
public void rule2to1() throws Exception {
try {
wsk.sanitize(Action, "A_221");
wsk.sanitize(Trigger, "T1_221");
wsk.sanitize(Trigger, "T2_221");
wsk.sanitize(Rule, "R1_221");
wsk.sanitize(Rule, "R2_221");
wsk.createAction("A_221", TestUtils.getCatalogFilename("samples/wc.js"));
wsk.createTrigger("T1_221");
wsk.createTrigger("T2_221");
wsk.createRule("R1_221", "T1_221", "A_221");
wsk.createRule("R2_221", "T2_221", "A_221");
long beforeTrigger = System.currentTimeMillis();
wsk.trigger("T2_221", "i'll be back");
wsk.trigger("T1_221", "terminator");
String expected1 = "The message 'terminator' has";
assertTrue("Expected message not found: " + expected1, wsk.logsForActionContain("A_221", expected1, beforeTrigger, DELAY));
String expected2 = "The message 'i'll be back' has";
assertTrue("Expected message not found: " + expected1, wsk.logsForActionContain("A_221", expected2, beforeTrigger, DELAY));
} finally {
wsk.delete(Action, "A_221");
wsk.delete(Trigger, "T1_221");
wsk.delete(Trigger, "T2_221");
wsk.delete(Rule, "R1_221");
wsk.delete(Rule, "R2_221");
}
}
/**
* rule test with one trigger and two actions
*/
@Test
public void rule1to2() throws Exception {
try {
wsk.sanitize(Action, "A1_122");
wsk.sanitize(Action, "A2_122");
wsk.sanitize(Trigger, "T1_122");
wsk.sanitize(Rule, "R1_122");
wsk.sanitize(Rule, "R2_122");
wsk.createAction("A1_122", TestUtils.getCatalogFilename("samples/wc.js"));
wsk.createAction("A2_122", TestUtils.getCatalogFilename("samples/hello.js"));
wsk.createTrigger("T1_122");
wsk.createRule("R1_122", "T1_122", "A1_122");
wsk.createRule("R2_122", "T1_122", "A2_122");
long beforeTrigger = System.currentTimeMillis();
wsk.trigger("T1_122", "put a fork in it");
String expected1 = "The message 'put a fork in it' has";
assertTrue("Expected message not found: " + expected1, wsk.logsForActionContain("A1_122", expected1, beforeTrigger, DELAY));
String expected2 = "hello put a fork in it";
assertTrue("Expected message not found: " + expected2, wsk.logsForActionContain("A2_122", expected2, beforeTrigger, DELAY));
} finally {
wsk.delete(Action, "A1_122");
wsk.delete(Action, "A2_122");
wsk.delete(Trigger, "T1_122");
wsk.delete(Rule, "R1_122");
wsk.delete(Rule, "R2_122");
}
}
/**
* rule test with two triggers and two actions
*/
@Test
public void rule2to2() throws Exception {
long startMilli = System.currentTimeMillis();
try {
wsk.sanitize(Action, "A1_222");
wsk.sanitize(Action, "A2_222");
wsk.sanitize(Trigger, "T1_222");
wsk.sanitize(Trigger, "T2_222");
wsk.sanitize(Rule, "Alpha");
wsk.sanitize(Rule, "Beta");
wsk.sanitize(Rule, "Gamma");
wsk.sanitize(Rule, "Delta");
long endMilli = System.currentTimeMillis();
System.out.format("rule2to2: %.1f seconds to sanitize\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
wsk.createAction("A1_222", TestUtils.getCatalogFilename("samples/wc.js"));
wsk.createAction("A2_222", TestUtils.getCatalogFilename("samples/hello.js"));
wsk.createTrigger("T1_222");
wsk.createTrigger("T2_222");
wsk.createRule("Alpha", "T1_222", "A1_222");
wsk.createRule("Beta", "T1_222", "A2_222");
wsk.createRule("Gamma", "T2_222", "A1_222");
wsk.createRule("Delta", "T2_222", "A2_222");
endMilli = System.currentTimeMillis();
System.out.format("rule2to2: %.1f seconds to create actions and rules\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
long beforeTrigger = System.currentTimeMillis();
wsk.trigger("T1_222", "XXX");
wsk.trigger("T2_222", "YYY");
endMilli = System.currentTimeMillis();
System.out.format("rule2to2: %.1f seconds to trigger\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
List<String> activations = wsk.waitForActivations("A1_222", 2, beforeTrigger, DELAY);
assertTrue("Not enough activation ids found", activations != null);
String expected1 = "The message 'XXX' has";
assertTrue("Expected message not found: " + expected1, wsk.logsForActionContain("A1_222", expected1, beforeTrigger, DELAY));
String expected2 = "The message 'YYY' has";
assertTrue("Expected message not found: " + expected2, wsk.logsForActionContain("A1_222", expected2, beforeTrigger, DELAY));
endMilli = System.currentTimeMillis();
System.out.format("rule2to2: %.1f seconds for first check\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
expected1 = "hello XXX";
expected2 = "hello YYY";
assertTrue("Expected message not found: " + expected1, wsk.logsForActionContain("A2_222", expected1, beforeTrigger, DELAY));
assertTrue("Expected message not found: " + expected2, wsk.logsForActionContain("A2_222", expected2, beforeTrigger, DELAY));
endMilli = System.currentTimeMillis();
System.out.format("rule2to2: %.1f seconds for second check\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
} finally {
wsk.delete(Action, "A1_222");
wsk.delete(Action, "A2_222");
wsk.delete(Trigger, "T1_222");
wsk.delete(Trigger, "T2_222");
wsk.delete(Rule, "Alpha");
wsk.delete(Rule, "Beta");
wsk.delete(Rule, "Gamma");
wsk.delete(Rule, "Delta");
long endMilli = System.currentTimeMillis();
System.out.format("rule2to2: %.1f seconds for cleanup\n", (endMilli - startMilli) / 1000.0);
}
}
/**
* rule test to make sure deleting a rule also disables it.
*/
@Test
public void ruleDisable() throws Exception {
long startMilli = System.currentTimeMillis();
try {
wsk.sanitize(Action, "A_321");
wsk.sanitize(Trigger, "T_321");
wsk.sanitize(Rule, "R_321");
long endMilli = System.currentTimeMillis();
System.out.format("ruleDisable: %.1f seconds to sanitize\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
wsk.createAction("A_321", TestUtils.getCatalogFilename("samples/wc.js"));
wsk.createTrigger("T_321");
wsk.createRule("R_321", "T_321", "A_321");
wsk.delete(Rule, "R_321");
endMilli = System.currentTimeMillis();
System.out.format("ruleDisable: %.1f seconds to create and delete rule/action\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
wsk.trigger("T_321", "ralph");
endMilli = System.currentTimeMillis();
System.out.format("ruleDisable: %.1f seconds to trigger\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
// retrieve activation ids; wait for at least one
List<String> activations = wsk.waitForActivations("A_321", 1, startMilli, NEGATIVE_DELAY);
assertTrue("Unexpected activation id found: ", activations == null || activations.size() == 0);
endMilli = System.currentTimeMillis();
System.out.format("ruleDisable: %.1f seconds to get activation\n", (endMilli - startMilli) / 1000.0);
startMilli = endMilli;
} finally {
wsk.delete(Action, "A_321");
wsk.delete(Trigger, "T_321");
wsk.sanitize(Rule, "R_321");
long endMilli = System.currentTimeMillis();
System.out.format("ruleDisable: %.1f seconds to cleanup\n", (endMilli - startMilli) / 1000.0);
}
}
/**
* rule test to check if a rule can be deleted and recreated with the same
* name.
*/
@Test
public void ruleRecreate() throws Exception {
try {
wsk.sanitize(Action, "A_421");
wsk.sanitize(Trigger, "T_421");
wsk.sanitize(Trigger, "T_422");
wsk.sanitize(Rule, "R_421");
wsk.createAction("A_421", TestUtils.getCatalogFilename("samples/wc.js"));
wsk.createTrigger("T_421");
wsk.createRule("R_421", "T_421", "A_421");
wsk.delete(Rule, "R_421");
wsk.createTrigger("T_422");
wsk.createRule("R_421", "T_422", "A_421");
long beforeTrigger = System.currentTimeMillis();
wsk.trigger("T_422", "david");
List<String> activations = wsk.waitForActivations("A_421", 1, beforeTrigger, NEGATIVE_DELAY);
if (activations == null || activations.size() == 0) {
assertFalse("Did not find any activations for A_421", true);
return;
}
String activationId = activations.get(0);
String expected = "The message 'david' has";
assertTrue("Expected message found: " + expected, wsk.logsForActivationContain(activationId, expected, DELAY));
} finally {
wsk.delete(Action, "A_421");
wsk.delete(Trigger, "T_421");
wsk.delete(Trigger, "T_422");
wsk.sanitize(Rule, "R_421");
}
}
/**
* rule test to check if a rule can be disable and enabled.
*/
@Test
public void ruleDisableEnable() throws Exception {
try {
wsk.sanitize(Action, "A_621");
wsk.sanitize(Trigger, "T_621");
wsk.sanitize(Rule, "R_621");
wsk.createAction("A_621", TestUtils.getCatalogFilename("samples/wc.js"));
wsk.createTrigger("T_621");
wsk.createRule("R_621", "T_621", "A_621");
wsk.disableRule("R_621", RULE_DELAY);
wsk.trigger("T_621", "batman");
wsk.enableRule("R_621", RULE_DELAY);
long beforeTrigger = System.currentTimeMillis();
wsk.trigger("T_621", "bruce wayne");
List<String> activations = wsk.waitForActivations("A_621", 1, beforeTrigger, DELAY);
assertTrue("Not enough activation ids found", activations != null);
String activationId = activations.get(0);
String expected = "The message 'bruce wayne' has";
assertTrue("Expected message not found: " + expected, wsk.logsForActivationContain(activationId, expected, DELAY));
String unexpected = "The message 'batman' has";
assertFalse("Unexpected message found: " + unexpected, wsk.logsForActivationContain(activationId, unexpected, NEGATIVE_DELAY));
} finally {
wsk.delete(Action, "A_621");
wsk.delete(Trigger, "T_621");
wsk.sanitize(Rule, "R_621");
}
}
/**
* Test for presence of activation records for trigger, rule, and action.
*/
@Test
public void activations() throws Exception {
int nameSuffix = ThreadLocalRandom.current().nextInt(Integer.MAX_VALUE);
String action = "ACT_A_" + nameSuffix;
String rule = "ACT_R_" + nameSuffix;
String trigger = "ACT_T_" + nameSuffix;
final class ActivationInfo {
public String activationId;
public String cause;
public ActivationInfo(String activationId, String cause) {
this.activationId = activationId;
this.cause = cause;
}
@Override
public String toString() {
return "ActivationInfo [activationId=" + activationId + ", cause=" + cause + "]";
}
}
try {
wsk.sanitize(Action, action);
wsk.sanitize(Trigger, trigger);
wsk.sanitize(Rule, rule);
wsk.createAction(action, TestUtils.getCatalogFilename("utils/date.js"));
wsk.createTrigger(trigger);
wsk.createRule(rule, trigger, action);
wsk.trigger(trigger, "bobby 121");
// Get activations
Set<String> entities = new HashSet<String>(Arrays.asList(new String[] { trigger, action, rule }));
Map<String, ActivationInfo> activations = TestUtils.waitfor(() -> {
String list = wsk.list(Activation);
String[] lines = list.split("\\r?\\n");
Map<String, ActivationInfo> infos = new HashMap<String, ActivationInfo>();
for (String line : lines) {
String[] words = line.split("\\s+");
if (words.length == 2) {
String entityName = words[1];
String activationId = words[0];
if (entities.contains(entityName)) {
String activation = wsk.get(Activation, activationId);
// remove "ok" line in stdout; leaving json
activation = activation.substring(activation.indexOf(System.getProperty("line.separator")) + 1);
JsonObject json = new JsonParser().parse(activation).getAsJsonObject();
String cause = json.get("cause") != null ? json.get("cause").getAsString() : "";
infos.put(entityName, new ActivationInfo(activationId, cause));
}
}
}
return infos.size() == 3 ? infos : null;
} , 8, 1, DELAY);
// Check that activations exist.
assertTrue("Activation not found for " + trigger, activations.containsKey(trigger));
assertTrue("Activation not found for " + rule, activations.containsKey(rule));
assertTrue("Activation not found for " + action, activations.containsKey(action));
// Check that activation cause is correct.
assertTrue("Wrong cause found for " + trigger, activations.get(trigger).cause.equals(""));
assertTrue("Wrong cause found for " + rule, activations.get(rule).cause.equals(activations.get(trigger).activationId));
// assertTrue("Wrong cause found for " + action, activations.get(action).cause.equals(activations.get(rule).activationId));
} finally {
wsk.delete(Rule, rule);
wsk.delete(Action, action);
wsk.delete(Trigger, trigger);
}
}
}