/* * Copyright 2017 Red Hat, Inc. and/or its affiliates. * * 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 org.drools.testcoverage.functional; import org.assertj.core.api.Assertions; import org.drools.template.parser.DecisionTableParseException; import org.drools.testcoverage.common.listener.OrderListener; import org.drools.testcoverage.common.listener.TrackingAgendaEventListener; import org.drools.testcoverage.common.model.Person; import org.drools.testcoverage.common.model.Sample; import org.drools.testcoverage.common.model.Subject; import org.drools.testcoverage.common.util.KieBaseUtil; import org.drools.testcoverage.common.util.KieUtil; import org.drools.testcoverage.common.util.ResourceUtil; import org.drools.testcoverage.common.util.TestConstants; import org.junit.Test; import org.kie.api.KieBase; import org.kie.api.definition.KiePackage; import org.kie.api.definition.type.FactType; import org.kie.api.io.Resource; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.rule.FactHandle; import org.kie.internal.builder.DecisionTableInputType; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Tests all features which can be used in decision tables. */ public class DecisionTableTest { @Test public void testSimpleXLS() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("sample.xls", getClass(), DecisionTableInputType.XLS); testSimpleDecisionTable(decisionTable); } @Test public void testSimpleCSV() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("sample.csv", getClass(), DecisionTableInputType.CSV); testSimpleDecisionTable(decisionTable); } private void testSimpleDecisionTable(final Resource decisionTable) { final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); final KieSession session = kbase.newKieSession(); final Person person = new Person("Paul"); person.setId(1); Assertions.assertThat(person.getName()).isEqualTo("Paul"); Assertions.assertThat(person.getId()).isEqualTo(1); session.insert(person); session.fireAllRules(); Assertions.assertThat(person.getName()).isEqualTo("Paul"); Assertions.assertThat(person.getId()).isEqualTo(2); session.dispose(); } @Test public void testMultipleTableXLS() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("multiple_tables.xls", getClass(), DecisionTableInputType.XLS); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); Assertions.assertThat(2).isEqualTo(kbase.getKiePackages().size()); final KieSession session = kbase.newKieSession(); // testing person object from the first table final Person person = new Person("Paul"); person.setId(1); Assertions.assertThat(person.getName()).isEqualTo("Paul"); Assertions.assertThat(person.getId()).isEqualTo(1); // testing second person, he should be renamed by rules in the second // table final Person person2 = new Person("Helmut von Seireit"); person2.setId(1000); Assertions.assertThat(person2.getName()).isEqualTo("Helmut von Seireit"); Assertions.assertThat(person2.getId()).isEqualTo(1000); session.insert(person); session.insert(person2); session.fireAllRules(); Assertions.assertThat(person.getName()).isEqualTo("Paul"); Assertions.assertThat(person.getId()).isEqualTo(2); Assertions.assertThat(person2.getName()).isEqualTo("Wilhelm von Seireit"); Assertions.assertThat(person2.getId()).isEqualTo(1000); session.dispose(); } /** * test for various evaluations, file sample_eval_dt.xls need to rewrite xls * table and maybe add some classes to be able to do the test */ @Test public void testEvalTable() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("eval_dt.xls", getClass(), DecisionTableInputType.XLS); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); Assertions.assertThat(2).isEqualTo(kbase.getKiePackages().size()); KieSession session = kbase.newKieSession(); final TrackingAgendaEventListener rulesFired = new TrackingAgendaEventListener(); session.addEventListener(rulesFired); rulesFired.clear(); // eval test 1 final Subject mary = new Subject("Mary"); mary.setDummy(1); session.insert(mary); session.fireAllRules(); Assertions.assertThat(rulesFired.isRuleFired("evalTest1")).isTrue(); Assertions.assertThat(rulesFired.isRuleFired("evalTest2")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest3")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest4")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("simpleBindingTest")).isFalse(); session.dispose(); // eval test 2 session = kbase.newKieSession(); session.addEventListener(rulesFired); rulesFired.clear(); final Subject inge = new Subject("Inge"); inge.setAge(7); inge.setSex("F"); final Subject jochen = new Subject("Jochen"); jochen.setAge(9); jochen.setSex("M"); session.insert(inge); session.insert(jochen); session.fireAllRules(); Assertions.assertThat(rulesFired.isRuleFired("evalTest1")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest2")).isTrue(); Assertions.assertThat(rulesFired.isRuleFired("evalTest3")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest4")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("simpleBindingTest")).isFalse(); session.dispose(); // eval test 3, will run four times, there are four combinations session = kbase.newKieSession(); session.addEventListener(rulesFired); rulesFired.clear(); final Subject karl = new Subject("Karl"); karl.setSex("male"); final Subject egon = new Subject("Egon"); egon.setSex("male"); session.insert(karl); session.insert(egon); session.fireAllRules(); Assertions.assertThat(rulesFired.isRuleFired("evalTest1")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest2")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest3")).isTrue(); Assertions.assertThat(rulesFired.isRuleFired("evalTest4")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("simpleBindingTest")).isFalse(); session.dispose(); // eval test 4 session = kbase.newKieSession(); session.addEventListener(rulesFired); rulesFired.clear(); final Subject gerda = new Subject("Gerda"); gerda.setSex("female"); gerda.setAge(9); gerda.setDummy(-10); session.insert(gerda); session.fireAllRules(); Assertions.assertThat(rulesFired.isRuleFired("evalTest1")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest2")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest3")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest4")).isTrue(); Assertions.assertThat(rulesFired.isRuleFired("simpleBindingTest")).isFalse(); session.dispose(); // eval test 5 - simple binding session = kbase.newKieSession(); session.addEventListener(rulesFired); rulesFired.clear(); final List<Sample> results = new ArrayList<Sample>(); session.setGlobal("results", results); final Sample sample = new Sample(); session.insert(sample); session.fireAllRules(); Assertions.assertThat(rulesFired.isRuleFired("evalTest1")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest2")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest3")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("evalTest4")).isFalse(); Assertions.assertThat(rulesFired.isRuleFired("simpleBindingTest")).isTrue(); session.dispose(); } /** * test for advanced rule settings (no-loop, saliences, ...), file * sample_advanced_dt.xls * * covers also bugfix for Bug724257 (agenda group not added from dtable to * .drl) */ @Test public void testAdvancedTable() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("advanced_dt.xls", getClass(), DecisionTableInputType.XLS); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); KieSession session = kbase.newKieSession(); final OrderListener listener = new OrderListener(); session.addEventListener(listener); final Subject lili = new Subject("Lili"); lili.setAge(100); final Sample sample = new Sample(); session.insert(lili); session.insert(sample); session.fireAllRules(); // just 4 rules should fire Assertions.assertThat(listener.size()).isEqualTo(4); // rules have to be fired in expected order final String[] expected = new String[] { "HelloWorld_11", "namedRule", "b1", "another rule" }; for (int i = 0; i < 4; i++) { Assertions.assertThat(listener.get(i)).isEqualTo(expected[i]); } session.dispose(); } @Test public void testPushQueryWithFactDeclaration() throws IllegalAccessException, InstantiationException { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("queries.xls", getClass(), DecisionTableInputType.XLS); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); final FactType locationType = kbase.getFactType(TestConstants.PACKAGE_FUNCTIONAL, "Location"); final KieSession ksession = kbase.newKieSession(); final TrackingAgendaEventListener listener = new TrackingAgendaEventListener(); ksession.addEventListener(listener); final Person peter = new Person("Peter"); peter.setLikes("steak"); final Object steakLocation = locationType.newInstance(); locationType.set(steakLocation, "thing", "steak"); locationType.set(steakLocation, "location", "table"); final Object tableLocation = locationType.newInstance(); locationType.set(tableLocation, "thing", "table"); locationType.set(tableLocation, "location", "office"); ksession.insert(peter); final FactHandle steakHandle = ksession.insert(steakLocation); final FactHandle tableHandle = ksession.insert(tableLocation); ksession.insert("push"); ksession.fireAllRules(); Assertions.assertThat(listener.isRuleFired("testPushQueryRule")).isTrue(); Assertions.assertThat(listener.isRuleFired("testPullQueryRule")).isFalse(); listener.clear(); // when location is changed of what Peter likes, push query should fire // rule final Object steakLocation2 = locationType.newInstance(); locationType.set(steakLocation2, "thing", "steak"); locationType.set(steakLocation2, "location", "desk"); final Object deskLocation = locationType.newInstance(); locationType.set(deskLocation, "thing", "desk"); locationType.set(deskLocation, "location", "office"); ksession.insert(steakLocation2); ksession.insert(deskLocation); ksession.delete(steakHandle); ksession.delete(tableHandle); ksession.fireAllRules(); Assertions.assertThat(listener.isRuleFired("testPushQueryRule")).isTrue(); Assertions.assertThat(listener.isRuleFired("testPullQueryRule")).isFalse(); listener.clear(); final Person paul = new Person("Paul"); paul.setLikes("steak"); ksession.insert(paul); ksession.fireAllRules(); Assertions.assertThat(listener.isRuleFired("testPushQueryRule")).isTrue(); Assertions.assertThat(listener.isRuleFired("testPullQueryRule")).isFalse(); listener.clear(); ksession.dispose(); } @Test public void testPullQueryWithFactDeclaration() throws IllegalAccessException, InstantiationException { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("queries.xls", getClass(), DecisionTableInputType.XLS); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); final FactType locationType = kbase.getFactType(TestConstants.PACKAGE_FUNCTIONAL, "Location"); final KieSession ksession = kbase.newKieSession(); final TrackingAgendaEventListener listener = new TrackingAgendaEventListener(); ksession.addEventListener(listener); final Person peter = new Person("Peter"); peter.setLikes("steak"); final Object steakLocation = locationType.newInstance(); locationType.set(steakLocation, "thing", "steak"); locationType.set(steakLocation, "location", "table"); final Object tableLocation = locationType.newInstance(); locationType.set(tableLocation, "thing", "table"); locationType.set(tableLocation, "location", "office"); ksession.insert(peter); final FactHandle steakHandle = ksession.insert(steakLocation); final FactHandle tableHandle = ksession.insert(tableLocation); ksession.insert("pull"); ksession.fireAllRules(); Assertions.assertThat(listener.isRuleFired("testPullQueryRule")).isTrue(); Assertions.assertThat(listener.isRuleFired("testPushQueryRule")).isFalse(); listener.clear(); // when location is changed of what Peter likes, pull query should // ignore it final Object steakLocation2 = locationType.newInstance(); locationType.set(steakLocation2, "thing", "steak"); locationType.set(steakLocation2, "location", "desk"); final Object deskLocation = locationType.newInstance(); locationType.set(deskLocation, "thing", "desk"); locationType.set(deskLocation, "location", "office"); ksession.insert(steakLocation2); ksession.insert(deskLocation); ksession.delete(steakHandle); ksession.delete(tableHandle); ksession.fireAllRules(); Assertions.assertThat(listener.isRuleFired("testPullQueryRule")).isFalse(); Assertions.assertThat(listener.isRuleFired("testPushQueryRule")).isFalse(); listener.clear(); final Person paul = new Person("Paul"); paul.setLikes("steak"); ksession.insert(paul); ksession.fireAllRules(); Assertions.assertThat(listener.isRuleFired("testPullQueryRule")).isTrue(); Assertions.assertThat(listener.isRuleFired("testPushQueryRule")).isFalse(); listener.clear(); ksession.dispose(); } /** * Test sequential turned on, it overrides all user defined saliences. */ @Test public void testSequential() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("sequential.csv", getClass(), DecisionTableInputType.CSV); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); final KieSession ksession = kbase.newKieSession(); final OrderListener listener = new OrderListener(); ksession.addEventListener(listener); ksession.insert("something"); ksession.fireAllRules(); Assertions.assertThat(listener.size()).as("Wrong number of rules fired").isEqualTo(3); final String[] expected = { "Rule1", "Rule2", "Rule3" }; for (int i = 0; i < 3; i++) { Assertions.assertThat(listener.get(i)).isEqualTo(expected[i]); } } @Test public void testLockOnActive() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("agenda-group.csv", getClass(), DecisionTableInputType.CSV); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); final KieSession ksession = kbase.newKieSession(); final OrderListener listener = new OrderListener(); ksession.addEventListener(listener); ksession.insert("lockOnActive"); ksession.fireAllRules(); Assertions.assertThat(listener.size()).isEqualTo(3); final String[] expected = { "a", "a2", "a3" }; for (int i = 0; i < listener.size(); i++) { Assertions.assertThat(listener.get(i)).isEqualTo(expected[i]); } } /** * Agenda group rule with auto focus can fire a give focus to agenda group * without focus set on whole agenda group. */ @Test public void testAutoFocus() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("agenda-group.csv", getClass(), DecisionTableInputType.CSV); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); final KieSession ksession = kbase.newKieSession(); final OrderListener listener = new OrderListener(); ksession.addEventListener(listener); // first test - we try to fire rule in agenda group which has auto focus // disable, we won't succeed final FactHandle withoutAutoFocus = ksession.insert("withoutAutoFocus"); ksession.fireAllRules(); Assertions.assertThat(listener.size()).isEqualTo(0); // second test - we try to fire rule in agenda group with auto focus // enabled // it fires and it's defined consequence causes to fire second rule // which has no auto focus ksession.insert("autoFocus"); ksession.delete(withoutAutoFocus); ksession.fireAllRules(); Assertions.assertThat(listener.size()).isEqualTo(2); final String[] expected = {"b2", "b1"}; for (int i = 0; i < listener.size(); i++) { Assertions.assertThat(listener.get(i)).isEqualTo(expected[i]); } } @Test public void testActivationGroup() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("agenda-group.csv", getClass(), DecisionTableInputType.CSV); final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); final KieSession ksession = kbase.newKieSession(); final TrackingAgendaEventListener listener = new TrackingAgendaEventListener(); ksession.addEventListener(listener); // only one rule from activation group may fire ksession.insert("activationGroup"); ksession.fireAllRules(); Assertions.assertThat(listener.isRuleFired("c1")).isFalse(); Assertions.assertThat(listener.isRuleFired("c2")).isTrue(); Assertions.assertThat(listener.isRuleFired("c3")).isFalse(); } @Test(expected = DecisionTableParseException.class) public void testEmptyConditionInXLS() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("emptyCondition.xls", getClass(), DecisionTableInputType.XLS); KieUtil.getKieBuilderFromResources(true, decisionTable); } @Test(expected = DecisionTableParseException.class) public void testEmptyActionInCSV() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("emptyAction.csv", getClass(), DecisionTableInputType.CSV); KieUtil.getKieBuilderFromResources(true, decisionTable); } @Test public void testCSVWithDateAttributes() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("sample_dates.csv", getClass(), DecisionTableInputType.CSV); testDecisionTableWithDateAttributes(decisionTable); } @Test public void testXLSWithDateAttributes() { final Resource decisionTable = ResourceUtil.getDecisionTableResourceFromClasspath("sample_dates.xls", getClass(), DecisionTableInputType.XLS); testDecisionTableWithDateAttributes(decisionTable); } private void testDecisionTableWithDateAttributes(final Resource decisionTable) { final KieBase kbase = KieBaseUtil.getKieBaseFromResources(true, decisionTable); final ArrayList<String> names = new ArrayList<String>(); final Collection<KiePackage> pkgs = kbase.getKiePackages(); for (KiePackage kp : pkgs) { names.add(kp.getName()); } Assertions.assertThat(names.contains(TestConstants.PACKAGE_FUNCTIONAL)).isTrue(); Assertions.assertThat(names.contains(TestConstants.PACKAGE_TESTCOVERAGE_MODEL)).isTrue(); final KiePackage kiePackage = (KiePackage) pkgs.toArray()[names.indexOf(TestConstants.PACKAGE_FUNCTIONAL)]; Assertions.assertThat(kiePackage.getRules().size()).isEqualTo(3); } }