/** * Copyright (c) 1997, 2015 by ProSyst Software GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.automation.core.internal; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.smarthome.automation.Action; import org.eclipse.smarthome.automation.Condition; import org.eclipse.smarthome.automation.Rule; import org.eclipse.smarthome.automation.Trigger; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter.Type; import org.eclipse.smarthome.config.core.ConfigDescriptionParameterBuilder; import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.config.core.FilterCriteria; import org.eclipse.smarthome.config.core.ParameterOption; import org.junit.Assert; import org.junit.Test; /** * Test adding, retrieving and updating rules from the RuleEngine * * @author Marin Mitev - initial version * @author Thomas Höfer - Added config description parameter unit */ public class RuleEngineTest { private RuleEngine createRuleEngine() { RuleEngine ruleEngine = new RuleEngine(); ruleEngine.setModuleTypeRegistry(new ModuleTypeRegistryMockup()); return ruleEngine; } /** * test adding and retrieving rules * */ @Test public void testAddRetrieveRules() { RuleEngine ruleEngine = createRuleEngine(); Rule rule0 = new Rule(ruleEngine.getUniqueId()); ruleEngine.addRule(rule0, true); Collection<RuntimeRule> rules = ruleEngine.getRuntimeRules(); Assert.assertNotNull("null returned instead of rules list", rules); Assert.assertEquals("empty rules list is returned", 1, rules.size()); Assert.assertEquals("Returned rule with wrong UID", "rule_1", rules.iterator().next().getUID()); Rule rule1 = createRule(); ruleEngine.addRule(rule1, true); rules = ruleEngine.getRuntimeRules(); Assert.assertEquals("rules list should contain 2 rules", 2, rules.size()); RuntimeRule rule1Get = ruleEngine.getRuntimeRule("rule1"); Assert.assertEquals("Returned rule with wrong UID", "rule1", rule1Get.getUID()); Rule rule2 = createRule(); ruleEngine.addRule(rule2, true); rules = ruleEngine.getRuntimeRules(); Assert.assertEquals("rules list should contain 2 rules", 2, rules.size()); Assert.assertEquals("rules list should contain 2 rules", rule1Get, ruleEngine.getRuntimeRule("rule1")); } /** * test auto map connections of the rule * */ @Test public void testAutoMapRuleConnections() { RuleEngine ruleEngine = createRuleEngine(); Rule rule = createAutoMapRule(); // check condition connections Map<String, String> conditionInputs = rule.getConditions().get(0).getInputs(); Assert.assertEquals("Number of user define condition inputs", 1, conditionInputs.size()); Assert.assertTrue("Check user define condition connection", "triggerId.triggerOutput".equals(conditionInputs.get("conditionInput"))); // check action connections Map<String, String> actionInputs = rule.getActions().get(0).getInputs(); Assert.assertEquals("Number of user define action inputs", 2, actionInputs.size()); Assert.assertTrue("Check user define action connections for input actionInput", "triggerId.triggerOutput".equals(actionInputs.get("actionInput"))); Assert.assertTrue("Check user define action connections for input in6", "triggerId.triggerOutput".equals(actionInputs.get("in6"))); // do connections auto mapping ruleEngine.addRule(rule, true); RuntimeRule ruleGet = ruleEngine.getRuntimeRule("AutoMapRule"); Assert.assertEquals("Returned rule with wrong UID", "AutoMapRule", ruleGet.getUID()); // check condition connections conditionInputs = ruleGet.getConditions().get(0).getInputs(); Assert.assertEquals("Number of user define condition inputs", 2, conditionInputs.size()); Assert.assertTrue("Check user define condition connection", "triggerId.triggerOutput".equals(conditionInputs.get("conditionInput"))); Assert.assertTrue("Auto map condition intput in2[tagA, tagB] to trigger output out3[tagA, tagB, tagC]", "triggerId.out3".equals(conditionInputs.get("in2"))); // check action connections actionInputs = ruleGet.getActions().get(0).getInputs(); Assert.assertEquals("Number of user define action inputs", 4, actionInputs.size()); Assert.assertTrue("Check user define action connections for input actionInput", "triggerId.triggerOutput".equals(actionInputs.get("actionInput"))); Assert.assertTrue("Check user define action connections for input in6 is not changed by the auto mapping", "triggerId.triggerOutput".equals(actionInputs.get("in6"))); Assert.assertTrue("Auto map action intput in5[tagA, tagB, tagC] to trigger output out3[tagA, tagB, tagC]", "triggerId.out3".equals(actionInputs.get("in5"))); Assert.assertTrue("Auto map action intput in5[tagD, tagE] to action output out5[tagD, tagE]", "actionId.out5".equals(actionInputs.get("in4"))); } /** * test editing rule tags * */ @Test public void testRuleTags() { RuleEngine ruleEngine = createRuleEngine(); Rule rule1 = new Rule("ruleWithTag1"); Set<String> ruleTags = new LinkedHashSet<String>(); ruleTags.add("tag1"); rule1.setTags(ruleTags); ruleEngine.addRule(rule1, true); Rule rule2 = new Rule("ruleWithTags12"); ruleTags = new LinkedHashSet<String>(); ruleTags.add("tag1"); ruleTags.add("tag2"); rule2.setTags(ruleTags); ruleEngine.addRule(rule2, true); RuntimeRule rule1Get = ruleEngine.getRuntimeRule("ruleWithTag1"); Assert.assertNotNull("Cannot find rule by UID", rule1Get); Assert.assertNotNull("rule.getTags is null", rule1Get.getTags()); Assert.assertEquals("rule.getTags is empty", 1, rule1Get.getTags().size()); RuntimeRule rule2Get = ruleEngine.getRuntimeRule("ruleWithTags12"); Assert.assertNotNull("Cannot find rule by UID", rule2Get); Assert.assertNotNull("rule.getTags is null", rule2Get.getTags()); Assert.assertEquals("rule.getTags is empty", 2, rule2Get.getTags().size()); } /** * test rule configurations with null * */ @Test public void testRuleConfigNull() { RuleEngine ruleEngine = createRuleEngine(); Rule rule3 = new Rule("rule3"); rule3.setTriggers(createTriggers("typeUID")); rule3.setConditions(createConditions("typeUID")); rule3.setActions(createActions("typeUID")); ruleEngine.addRule(rule3, true); RuntimeRule rule3Get = ruleEngine.getRuntimeRule("rule3"); Assert.assertNotNull("Rule configuration is null", rule3Get.getConfiguration()); } /** * test rule configurations with real values * */ @Test public void testRuleConfigValue() { RuleEngine ruleEngine = createRuleEngine(); List<ConfigDescriptionParameter> configDescriptions = createConfigDescriptions(); Configuration configurations = new Configuration(); configurations.put("config1", 5); Rule rule4 = new Rule("rule4"); rule4.setTriggers(createTriggers("typeUID")); rule4.setConditions(createConditions("typeUID")); rule4.setActions(createActions("typeUID")); rule4.setConfigurationDescriptions(configDescriptions); rule4.setConfiguration(configurations); ruleEngine.addRule(rule4, true); RuntimeRule rule4Get = ruleEngine.getRuntimeRule("rule4"); Configuration rule4cfg = rule4Get.getConfiguration(); List<ConfigDescriptionParameter> rule4cfgD = rule4Get.getConfigurationDescriptions(); Assert.assertNotNull("Rule configuration is null", rule4cfg); Assert.assertTrue("Missing config property in rule copy", rule4cfg.containsKey("config1")); Assert.assertEquals("Wrong config value", new BigDecimal(5), rule4cfg.get("config1")); Assert.assertNotNull("Rule configuration description is null", rule4cfgD); Assert.assertEquals("Missing config description in rule copy", 1, rule4cfgD.size()); ConfigDescriptionParameter rule4cfgDP = rule4cfgD.iterator().next(); Assert.assertEquals("Wrong default value in config description", "3", rule4cfgDP.getDefault()); Assert.assertEquals("Wrong context value in config description", "context1", rule4cfgDP.getContext()); Assert.assertNotNull("Null options in config description", rule4cfgDP.getOptions()); Assert.assertEquals("Wrong option value in config description", "1", rule4cfgDP.getOptions().get(0).getValue()); Assert.assertEquals("Wrong option label in config description", "one", rule4cfgDP.getOptions().get(0).getLabel()); } /** * test rule actions * */ @Test public void testRuleActions() { RuleEngine ruleEngine = createRuleEngine(); Rule rule1 = createRule(); List<Action> actions = rule1.getActions(); ruleEngine.addRule(rule1, true); RuntimeRule rule1Get = ruleEngine.getRuntimeRule("rule1"); List<Action> actionsGet = rule1Get.getActions(); Assert.assertNotNull("Null actions list", actionsGet); Assert.assertEquals("Empty actions list", 1, actionsGet.size()); Assert.assertEquals("Returned actions list should not be a copy", actionsGet, rule1Get.getActions()); actions.add(new Action("actionId2", "typeUID2", null, null)); ruleEngine.updateRule(rule1, true); rule1Get = ruleEngine.getRuntimeRule("rule1"); List<Action> actionsGet2 = rule1Get.getActions(); Assert.assertNotNull("Null actions list", actionsGet2); Assert.assertEquals("Action was not added to the rule's list of actions", 2, actionsGet2.size()); Assert.assertNotNull("Rule action with wrong id is returned", rule1Get.getModule("actionId2")); actions.add(new Action("actionId3", "typeUID3", null, null)); ruleEngine.updateRule(rule1, true);// ruleEngine.update will update the RuntimeRule.moduleMap with the new // module rule1Get = ruleEngine.getRuntimeRule("rule1"); List<Action> actionsGet3 = rule1Get.getActions(); Assert.assertNotNull("Null actions list", actionsGet3); Assert.assertEquals("Action was not added to the rule's list of actions", 3, actionsGet3.size()); Assert.assertNotNull("Rule modules map was not updated", ruleEngine.getRuntimeRule("rule1").getModule("actionId3")); } /** * test rule triggers * */ @Test public void testRuleTriggers() { RuleEngine ruleEngine = createRuleEngine(); Rule rule1 = createRule(); List<Trigger> triggers = rule1.getTriggers(); ruleEngine.addRule(rule1, true); RuntimeRule rule1Get = ruleEngine.getRuntimeRule("rule1"); List<Trigger> triggersGet = rule1Get.getTriggers(); Assert.assertNotNull("Null triggers list", triggersGet); Assert.assertEquals("Empty triggers list", 1, triggersGet.size()); Assert.assertEquals("Returned triggers list should not be a copy", triggersGet, rule1Get.getTriggers()); triggers.add(new Trigger("triggerId2", "typeUID2", null)); ruleEngine.updateRule(rule1, true);// ruleEngine.update will update the RuntimeRule.moduleMap with the new // module RuntimeRule rule2Get = ruleEngine.getRuntimeRule("rule1"); List<Trigger> triggersGet2 = rule2Get.getTriggers(); Assert.assertNotNull("Null triggers list", triggersGet2); Assert.assertEquals("Trigger was not added to the rule's list of triggers", 2, triggersGet2.size()); Assert.assertEquals("Returned triggers list should not be a copy", triggersGet2, rule2Get.getTriggers()); Assert.assertNotNull("Rule trigger with wrong id is returned: " + triggersGet2, rule2Get.getModule("triggerId2")); } /** * test rule condition */ @Test public void testRuleConditions() { RuleEngine ruleEngine = createRuleEngine(); Rule rule1 = createRule(); List<Condition> conditions = rule1.getConditions(); ruleEngine.addRule(rule1, true); RuntimeRule rule1Get = ruleEngine.getRuntimeRule("rule1"); List<Condition> conditionsGet = rule1Get.getConditions(); Assert.assertNotNull("Null conditions list", conditionsGet); Assert.assertEquals("Empty conditions list", 1, conditionsGet.size()); Assert.assertEquals("Returned conditions list should not be a copy", conditionsGet, rule1Get.getConditions()); conditions.add(new Condition("conditionId2", "typeUID2", null, null)); ruleEngine.updateRule(rule1, true);// ruleEngine.update will update the RuntimeRule.moduleMap with the new // module RuntimeRule rule2Get = ruleEngine.getRuntimeRule("rule1"); List<Condition> conditionsGet2 = rule2Get.getConditions(); Assert.assertNotNull("Null conditions list", conditionsGet2); Assert.assertEquals("Condition was not added to the rule's list of conditions", 2, conditionsGet2.size()); Assert.assertEquals("Returned conditions list should not be a copy", conditionsGet2, rule2Get.getConditions()); Assert.assertNotNull("Rule condition with wrong id is returned: " + conditionsGet2, rule2Get.getModule("conditionId2")); } private Rule createRule() { Rule rule = new Rule("rule1"); rule.setTriggers(createTriggers("typeUID")); rule.setConditions(createConditions("typeUID")); rule.setActions(createActions("typeUID")); return rule; } private Rule createAutoMapRule() { Rule rule = new Rule("AutoMapRule"); rule.setTriggers(createTriggers(ModuleTypeRegistryMockup.TRIGGER_TYPE)); rule.setConditions(createConditions(ModuleTypeRegistryMockup.CONDITION_TYPE)); rule.setActions(createActions(ModuleTypeRegistryMockup.ACTION_TYPE)); return rule; } private List<Trigger> createTriggers(String type) { List<Trigger> triggers = new ArrayList<Trigger>(); Configuration configurations = new Configuration(); configurations.put("a", "x"); configurations.put("b", "y"); configurations.put("c", "z"); triggers.add(new Trigger("triggerId", type, configurations)); return triggers; } private List<Condition> createConditions(String type) { List<Condition> conditions = new ArrayList<Condition>(); Configuration configurations = new Configuration(); configurations.put("a", "x"); configurations.put("b", "y"); configurations.put("c", "z"); Map<String, String> inputs = new HashMap<String, String>(11); String ouputModuleId = "triggerId"; String outputName = "triggerOutput"; String inputName = "conditionInput"; inputs.put(inputName, ouputModuleId + "." + outputName); conditions.add(new Condition("conditionId", type, configurations, inputs)); return conditions; } private List<Action> createActions(String type) { List<Action> actions = new ArrayList<Action>(); Configuration configurations = new Configuration(); configurations.put("a", "x"); configurations.put("b", "y"); configurations.put("c", "z"); Map<String, String> inputs = new HashMap<String, String>(11); String ouputModuleId = "triggerId"; String outputName = "triggerOutput"; String inputName = "actionInput"; inputs.put(inputName, ouputModuleId + "." + outputName); inputs.put("in6", ouputModuleId + "." + outputName); actions.add(new Action("actionId", type, configurations, inputs)); return actions; } private List<ConfigDescriptionParameter> createConfigDescriptions() { List<ConfigDescriptionParameter> configDescriptions = new ArrayList<ConfigDescriptionParameter>(); List<ParameterOption> options = new ArrayList<ParameterOption>(); options.add(new ParameterOption("1", "one")); options.add(new ParameterOption("2", "two")); String groupName = null; Boolean advanced = false; Boolean limitToOptions = true; Integer multipleLimit = 0; String label = "label1"; String pattern = null; String context = "context1"; String description = "description1"; BigDecimal min = null; BigDecimal max = null; BigDecimal step = null; Boolean required = true; Boolean multiple = false; Boolean readOnly = false; String typeStr = ConfigDescriptionParameter.Type.INTEGER.name(); String defValue = "3"; List<FilterCriteria> filter = new ArrayList<FilterCriteria>(); String configPropertyName = "config1"; ConfigDescriptionParameter cfgDP = ConfigDescriptionParameterBuilder .create(configPropertyName, Type.valueOf(typeStr)).withMaximum(max).withMinimum(min).withStepSize(step) .withPattern(pattern).withRequired(required).withReadOnly(readOnly).withMultiple(multiple) .withContext(context).withDefault(defValue).withLabel(label).withDescription(description) .withOptions(options).withFilterCriteria(filter).withGroupName(groupName).withAdvanced(advanced) .withLimitToOptions(limitToOptions).withMultipleLimit(multipleLimit).build(); configDescriptions.add(cfgDP); return configDescriptions; } }