/* * Copyright 2015 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. * * 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.compiler.integrationtests; import org.drools.compiler.Cheese; import org.drools.compiler.CommonTestMethodBase; import org.junit.Test; import org.kie.api.io.ResourceType; import org.kie.internal.KnowledgeBase; import org.kie.internal.builder.KnowledgeBuilder; import org.kie.internal.builder.KnowledgeBuilderFactory; import org.kie.internal.io.ResourceFactory; import org.kie.internal.runtime.StatefulKnowledgeSession; import java.util.ArrayList; import java.util.List; public class BranchTest extends CommonTestMethodBase { @Test public void testNamedConsequences() { List<String> results = executeTestWithCondition("do[t1]"); assertEquals( 2, results.size() ); assertTrue( results.contains( "cheddar" ) ); assertTrue( results.contains( "stilton" ) ); } private List<String> executeTestWithCondition(String conditionElement) { String drl = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " " + conditionElement + "\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; return executeTestWithDRL(drl); } private List<String> executeTestWithDRL(String drl) { KnowledgeBase kbase = loadKnowledgeBaseFromString(drl); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<String> results = new ArrayList<String>(); ksession.setGlobal( "results", results ); Cheese stilton = new Cheese( "stilton", 5 ); Cheese cheddar = new Cheese( "cheddar", 7 ); Cheese brie = new Cheese( "brie", 5 ); ksession.insert( stilton ); ksession.insert( cheddar ); ksession.insert( brie ); ksession.fireAllRules(); return results; } @Test public void testNonCompilingBreakingConsequences() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " break[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource(str.getBytes()), ResourceType.DRL ); assertTrue(kbuilder.hasErrors()); } @Test public void testNonCompilingDuplicatedNamedConsequence() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " do[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource(str.getBytes()), ResourceType.DRL ); assertTrue(kbuilder.hasErrors()); } @Test public void testOutOfScopeNamedConsequences() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " do[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $b.getType() );\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource(str.getBytes()), ResourceType.DRL ); assertTrue(kbuilder.hasErrors()); } @Test public void testAllowedIfDo() { List<String> results = executeTestWithCondition("if ( price < 10 ) do[t1]"); assertEquals( 2, results.size() ); assertTrue( results.contains( "cheddar" ) ); assertTrue( results.contains( "stilton" ) ); } @Test public void testNotAllowedIfDo() { List<String> results = executeTestWithCondition("if ( price > 10 ) do[t1]"); assertEquals( 1, results.size() ); assertTrue( results.contains( "cheddar" ) ); } @Test public void testAllowedIfBreak() { List<String> results = executeTestWithCondition("if ( price < 10 ) break[t1]"); assertEquals( 1, results.size() ); assertTrue( results.contains( "stilton" ) ); } @Test public void testNotAllowedIfBreak() { List<String> results = executeTestWithCondition("if ( price > 10 ) break[t1]"); assertEquals( 1, results.size() ); assertTrue( results.contains( "cheddar" ) ); } @Test public void testNamedConsequencesOutsideOR() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " ( $a: Cheese ( type == \"stilton\" )\n" + " or\n" + " $a: Cheese ( type == \"gorgonzola\" ) )\n" + " do[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 2, results.size() ); assertTrue( results.contains( "cheddar" ) ); assertTrue( results.contains( "stilton" ) ); } @Test public void testNamedConsequencesInsideOR1() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " ( $a: Cheese ( type == \"stilton\" ) do[t1]\n" + " or\n" + " $b: Cheese ( type == \"gorgonzola\" ) )\n" + " $c: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $c.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 2, results.size() ); assertTrue( results.contains( "cheddar" ) ); assertTrue( results.contains( "stilton" ) ); } @Test public void testNamedConsequencesInsideOR2() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " ( $a: Cheese ( type == \"stilton\" )\n" + " or\n" + " $b: Cheese ( type == \"gorgonzola\" ) do[t1] )\n" + " $c: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $c.getType() );\n" + "then[t1]\n" + " results.add( $b.getType() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 1, results.size() ); assertTrue( results.contains( "cheddar" ) ); } @Test public void testOutOfScopeNamedConsequencesWithOr1() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " ( $a: Cheese ( type == \"stilton\" )\n" + " or\n" + " $b: Cheese ( type == \"gorgonzola\" ) do[t1] )\n" + " $c: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $c.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource(str.getBytes()), ResourceType.DRL ); assertTrue(kbuilder.hasErrors()); } @Test public void testOutOfScopeNamedConsequencesWithOr2() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " ( $a: Cheese ( type == \"stilton\" )\n" + " or\n" + " $b: Cheese ( type == \"gorgonzola\" ) do[t1] )\n" + " $c: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $c.getType() );\n" + "then[t1]\n" + " results.add( $c.getType() );\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource(str.getBytes()), ResourceType.DRL ); assertTrue(kbuilder.hasErrors()); } @Test public void testNonCompilingIFAfterOR() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " ( $a: Cheese ( type == \"stilton\" )\n" + " or\n" + " $a: Cheese ( type == \"gorgonzola\" ) )\n" + " if ( price > 10 ) do[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource(str.getBytes()), ResourceType.DRL ); assertTrue(kbuilder.hasErrors()); } @Test public void testMultipleIfAfterEval() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( )\n" + " eval( $a.getType().equals(\"stilton\") )\n" + " if ( $a.getPrice() > 10 ) do[t1]\n" + " if ( $a.getPrice() < 10 ) do[t2]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType().toUpperCase() );\n" + "then[t2]\n" + " results.add( $a.getType() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 2, results.size() ); assertTrue( results.contains( "cheddar" ) ); assertTrue( results.contains( "stilton" ) ); } @Test public void testInheritance() { String str = "dialect \"mvel\"\n" + "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R0 when\n" + " $a: Cheese ( )\n" + "then\n" + "end\n" + "\n" + "rule R1 extends R0 when\n" + " eval( $a.getType().equals(\"stilton\") )\n" + " if ( $a.getPrice() > 10 ) do[t1]\n" + " if ( $a.getPrice() < 10 ) do[t2]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.type );\n" + "then[t1]\n" + " results.add( $a.type.toUpperCase() );\n" + "then[t2]\n" + " results.add( $a.type );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 2, results.size() ); assertTrue( results.contains( "cheddar" ) ); assertTrue( results.contains( "stilton" ) ); } @Test public void testIfElse1() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price > 10 ) do[t1] else do[t2]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "then[t2]\n" + " results.add( $a.getType().toUpperCase() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 2, results.size() ); assertTrue( results.contains( "cheddar" ) ); assertTrue( results.contains( "STILTON" ) ); } @Test public void testIfElse2() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price < 10 ) do[t1] else do[t2]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t2]\n" + " results.add( $a.getType() );\n" + "then[t1]\n" + " results.add( $a.getType().toUpperCase() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 2, results.size() ); assertTrue( results.contains( "cheddar" ) ); assertTrue( results.contains( "STILTON" ) ); } @Test public void testIfElseBreak() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price > 10 ) do[t1] else break[t2]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "then[t2]\n" + " results.add( $a.getType().toUpperCase() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 1, results.size() ); assertTrue( results.contains( "STILTON" ) ); } @Test public void testMVELBreak() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 dialect \"mvel\" when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " $b: Cheese ( type == \"cheddar\" )\n" + " if ( 200 < 400 ) break[t1]\n" + "then\n" + " results.add( $b.type );\n" + "then[t1]\n" + " results.add( $a.type.toUpperCase() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); System.out.println( results ); assertEquals( 1, results.size() ); assertTrue( results.contains( "STILTON" ) ); } @Test public void testMVELNoBreak() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 dialect \"mvel\" when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " $b: Cheese ( type == \"cheddar\" )\n" + " if ( 200 > 400 ) break[t1]\n" + "then\n" + " results.add( $b.type );\n" + "then[t1]\n" + " results.add( $a.type.toUpperCase() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); System.out.println( results ); assertEquals( 1, results.size() ); assertTrue( results.contains( "cheddar" ) ); } @Test public void testWrongConsequenceName() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 dialect \"mvel\" when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " $b: Cheese ( type == \"cheddar\" )\n" + " if ( 200 < 400 ) break[t2]\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t1]\n" + " results.add( $a.getType().toUpperCase() );\n" + "end\n"; KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder(); builder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL); assertTrue ( builder.hasErrors() ); } @Test public void testNestedIfElseBreak() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( type.startsWith(\"a\") ) do[t0] else if ( price > 10 ) do[t1] else break[t2]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $b.getType() );\n" + "then[t0]\n" + " results.add( \"WRONG!\" );\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "then[t2]\n" + " results.add( $a.getType().toUpperCase() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 1, results.size() ); assertTrue( results.contains( "STILTON" ) ); } @Test public void testIfWithModify() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price > 10 ) break[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " modify( $a ) { setPrice(15) };\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 1, results.size() ); assertTrue( results.contains( "stilton" ) ); } @Test(expected=RuntimeException.class) public void testEndlessIfWithModify() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price > 10 ) do[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " modify( $a ) { setPrice(15) };\n" + " results.add( \"modify\" );\n" + " if (results.size() > 10) throw new RuntimeException();\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + " if (results.size() > 10) throw new RuntimeException();\n" + "end\n"; List<String> results = executeTestWithDRL(str); } @Test public void testIfWithModify2() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price < 10 ) break[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " results.add( $a.getType() );\n" + "then[t1]\n" + " modify( $a ) { setPrice(15) };\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 1, results.size() ); assertTrue( results.contains( "stilton" ) ); } @Test public void testIfWithModify3() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\", price < 10 )\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " modify( $a ) { setPrice(15) };\n" + "end\n" + "rule R2 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price > 10 ) break[t1]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 1, results.size() ); assertTrue( results.contains( "stilton" ) ); } @Test public void testIfElseWithModify() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price < 10 ) do[t1] else break[t2]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " modify( $a ) { setPrice(15) };\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "then[t2]\n" + " results.add( $a.getType().toUpperCase() );\n" + "end\n"; List<String> results = executeTestWithDRL(str); assertEquals( 2, results.size() ); assertTrue( results.contains( "STILTON" ) ); } @Test(expected=RuntimeException.class) public void testEndlessIfElseWithModify() { String str = "import org.drools.compiler.Cheese;\n " + "global java.util.List results;\n" + "\n" + "rule R1 when\n" + " $a: Cheese ( type == \"stilton\" )\n" + " if ( price < 10 ) do[t1] else do[t2]\n" + " $b: Cheese ( type == \"cheddar\" )\n" + "then\n" + " modify( $a ) { setPrice(15) };\n" + " results.add( \"modify\" );\n" + " if (results.size() > 10) throw new RuntimeException();\n" + "then[t1]\n" + " results.add( $a.getType() );\n" + "then[t2]\n" + " results.add( $a.getType().toUpperCase() );\n" + " if (results.size() > 10) throw new RuntimeException();\n" + "end\n"; List<String> results = executeTestWithDRL(str); } }