/* * Copyright 2005 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.compiler.integrationtests; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Serializable; import java.io.StringReader; import java.math.BigDecimal; import java.net.URL; import java.net.URLClassLoader; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.drools.compiler.Address; import org.drools.compiler.Cheese; import org.drools.compiler.CommonTestMethodBase; import org.drools.compiler.Message; import org.drools.compiler.Person; import org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl; import org.drools.compiler.builder.impl.KnowledgeBuilderImpl; import org.drools.compiler.compiler.DrlParser; import org.drools.compiler.compiler.DroolsParserException; import org.drools.compiler.lang.descr.PackageDescr; import org.drools.compiler.lang.descr.PatternDescr; import org.drools.compiler.lang.descr.RuleDescr; import org.drools.compiler.rule.builder.dialect.mvel.MVELDialectConfiguration; import org.drools.core.ClassObjectFilter; import org.drools.core.InitialFact; import org.drools.core.RuleBaseConfiguration; import org.drools.core.WorkingMemory; import org.drools.core.base.ClassObjectType; import org.drools.core.common.DefaultFactHandle; import org.drools.core.common.InternalAgenda; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.common.Memory; import org.drools.core.common.NodeMemories; import org.drools.core.common.TupleSets; import org.drools.core.conflict.SalienceConflictResolver; import org.drools.core.definitions.impl.KnowledgePackageImpl; import org.drools.core.definitions.rule.impl.RuleImpl; import org.drools.core.facttemplates.FactTemplate; import org.drools.core.facttemplates.FactTemplateImpl; import org.drools.core.facttemplates.FieldTemplate; import org.drools.core.facttemplates.FieldTemplateImpl; import org.drools.core.impl.InternalKnowledgeBase; import org.drools.core.impl.KnowledgeBaseImpl; import org.drools.core.io.impl.ByteArrayResource; import org.drools.core.reteoo.AlphaNode; import org.drools.core.reteoo.BetaMemory; import org.drools.core.reteoo.JoinNode; import org.drools.core.reteoo.LeftInputAdapterNode; import org.drools.core.reteoo.LeftTuple; import org.drools.core.reteoo.ObjectTypeNode; import org.drools.core.reteoo.Rete; import org.drools.core.reteoo.ReteComparator; import org.drools.core.reteoo.ReteDumper; import org.drools.core.reteoo.RightTuple; import org.drools.core.reteoo.SegmentMemory; import org.drools.core.spi.KnowledgeHelper; import org.drools.core.spi.Salience; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.kie.api.KieBase; import org.kie.api.KieBaseConfiguration; import org.kie.api.KieServices; import org.kie.api.builder.KieBuilder; import org.kie.api.builder.KieFileSystem; import org.kie.api.builder.KieModule; import org.kie.api.builder.ReleaseId; import org.kie.api.builder.Results; import org.kie.api.conf.DeclarativeAgendaOption; import org.kie.api.conf.EventProcessingOption; import org.kie.api.definition.rule.Rule; import org.kie.api.definition.type.FactType; import org.kie.api.definition.type.Modifies; import org.kie.api.definition.type.Position; import org.kie.api.definition.type.PropertyReactive; import org.kie.api.event.kiebase.DefaultKieBaseEventListener; import org.kie.api.event.kiebase.KieBaseEventListener; import org.kie.api.event.rule.AfterMatchFiredEvent; import org.kie.api.event.rule.AgendaEventListener; import org.kie.api.event.rule.DebugAgendaEventListener; import org.kie.api.event.rule.DefaultAgendaEventListener; import org.kie.api.event.rule.MatchCancelledEvent; import org.kie.api.event.rule.MatchCreatedEvent; import org.kie.api.io.ResourceType; import org.kie.api.marshalling.Marshaller; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.KieSessionConfiguration; import org.kie.api.runtime.StatelessKieSession; import org.kie.api.runtime.rule.Agenda; import org.kie.api.runtime.rule.FactHandle; import org.kie.api.runtime.rule.Match; import org.kie.internal.KnowledgeBase; import org.kie.internal.KnowledgeBaseFactory; import org.kie.internal.builder.KnowledgeBuilder; import org.kie.internal.builder.KnowledgeBuilderConfiguration; import org.kie.internal.builder.KnowledgeBuilderFactory; import org.kie.internal.builder.KnowledgeBuilderResult; import org.kie.internal.builder.KnowledgeBuilderResults; import org.kie.internal.builder.ResultSeverity; import org.kie.internal.builder.conf.LanguageLevelOption; import org.kie.internal.event.rule.RuleEventListener; import org.kie.internal.event.rule.RuleEventManager; import org.kie.internal.io.ResourceFactory; import org.kie.internal.marshalling.MarshallerFactory; import org.kie.internal.runtime.StatefulKnowledgeSession; import org.kie.internal.runtime.conf.ForceEagerActivationOption; import org.kie.internal.utils.KieHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static java.util.Arrays.asList; import static org.drools.compiler.TestUtil.assertDrlHasCompilationError; import static org.junit.Assume.assumeTrue; /** * Run all the tests with the ReteOO engine implementation */ public class Misc2Test extends CommonTestMethodBase { private static final Logger logger = LoggerFactory.getLogger( Misc2Test.class ); @Test public void testUpdateWithNonEffectiveActivations() throws Exception { // JBRULES-3604 String str = "package inheritance\n" + "\n" + "import org.drools.compiler.Address\n" + "\n" + "rule \"Parent\"\n" + " enabled false\n" + " when \n" + " $a : Address(suburb == \"xyz\")\n" + " then \n" + " System.out.println( $a ); \n" + "end \n" + "rule \"Child\" extends \"Parent\" \n" + " when \n" + " $b : Address( this == $a, street == \"123\")\n" + " then \n" + " System.out.println( $b ); \n" + "end"; KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder(); builder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); if ( builder.hasErrors() ) { throw new RuntimeException( builder.getErrors().toString() ); } KnowledgeBase knowledgeBase = KnowledgeBaseFactory.newKnowledgeBase(); knowledgeBase.addKnowledgePackages( builder.getKnowledgePackages() ); StatefulKnowledgeSession ksession = knowledgeBase.newStatefulKnowledgeSession(); Address address = new Address(); address.setSuburb( "xyz" ); FactHandle addressHandle = ksession.insert( address ); int rulesFired = ksession.fireAllRules(); assertEquals( 0, rulesFired ); address.setStreet( "123" ); ksession.update( addressHandle, address ); rulesFired = ksession.fireAllRules(); System.out.println( rulesFired ); assertEquals( 1, rulesFired ); ksession.dispose(); } @Test public void testNPEOnMutableGlobal() throws Exception { // BZ-1019473 String str = "package org.drools.compiler\n" + "global java.util.List context\n" + "rule B\n" + " when\n" + " Message( message == \"b\" )\n" + " $s : String() from context\n" + " then\n" + " System.out.println($s);\n" + "end"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write( ResourceFactory.newByteArrayResource( str.getBytes() ).setTargetPath( "org/drools/compiler/rules.drl" ) ); KieBuilder kbuilder = KieServices.Factory.get().newKieBuilder( kfs ); kbuilder.buildAll(); assertEquals( 0, kbuilder.getResults().getMessages().size() ); ks.newKieContainer( kbuilder.getKieModule().getReleaseId() ).getKieBase(); KieSession ksession = ks.newKieContainer( kbuilder.getKieModule().getReleaseId() ).newKieSession(); assertNotNull( ksession ); List<String> context = new ArrayList<String>(); ksession.setGlobal( "context", context ); FactHandle b = ksession.insert( new Message( "b" ) ); ksession.delete( b ); int fired = ksession.fireAllRules( 1 ); assertEquals( 0, fired ); ksession.dispose(); } @Test public void testClassNotFoundAfterDeserialization() throws Exception { // JBRULES-3670 String drl = "package completely.other.deal;\n" + "\n" + "declare Person\n" + " firstName : String\n" + " lastName : String\n" + "end\n" + "\n" + "rule \"now use it B\"\n" + " when\n" + " Person( $christianName, $surname; )\n" + " then\n" + " insert( new Person( $christianName, null ) );\n" + "end"; KieBase kbase1 = new KieHelper().addContent( drl, ResourceType.DRL ).build(); KieBase kbase2 = SerializationHelper.serializeObject( kbase1, ( (InternalKnowledgeBase) kbase1 ).getRootClassLoader() ); assertTrue( ReteComparator.areEqual( kbase1, kbase2 ) ); } @Test public void testAnalyzeConditionWithVariableRegExp() throws Exception { // JBRULES-3659 String str = "dialect \"mvel\"\n" + "\n" + "declare Person\n" + " name : String\n" + "end\n" + "declare Stuff\n" + " regexp : String\n" + "end\n" + "\n" + "rule \"Test Regex\"\n" + " salience 100\n" + " when\n" + " then\n" + " insert (new Stuff(\"Test\"));\n" + " insert (new Person(\"Test\"));\n" + "end\n" + "\n" + "rule \"Test Equality\"\n" + " salience 10\n" + " when\n" + " Stuff( $regexp : regexp )\n" + " Person( name matches $regexp )\n" + " //Person( name matches \"Test\" )\n" + " then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testShareAlphaNodesRegardlessDoubleOrSingleQuotes() { // JBRULES-3640 String str = "declare RecordA\n" + " id : long\n" + "end\n" + "\n" + "declare RecordB\n" + " id : long\n" + "role : String\n" + "end\n" + "\n" + "rule \"insert data 1\"\n" + " salience 10\n" + " when\n" + " then\n" + " insert (new RecordA(100));\n" + " insert (new RecordB(100, \"1\"));\n" + " insert (new RecordB(100, \"2\"));\n" + "end\n" + "\n" + "rule \"test 1\"\n" + " when\n" + " a : RecordA( )\n" + " b : RecordB( id == b.id, role == '1' )\n" + " then\n" + "end\n" + "\n" + "rule \"test 2\"\n" + " when\n" + " a : RecordA( )\n" + " b : RecordB( id == b.id, role == \"1\" )\n" + " then\n" + "end\n" + "\n" + "rule \"test 3\"\n" + " when\n" + " a : RecordA( )\n" + " b : RecordB( id == b.id, role == \"2\" )\n" + " then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 4, ksession.fireAllRules() ); } @Test public void testEvalBeforeNot() { String str = "package org.drools.compiler.integration; \n" + "import " + A.class.getCanonicalName() + ";\n" + "global java.util.List list;\n" + "\n" + "rule r1\n" + " salience 10\n" + " when\n" + " eval( list.size() == 0 ) \n" + " not A( )" + " then\n" + " System.out.println('xxx');\n" + "end\n" + "\n"; System.out.println( str ); KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); } @Test public void testKnowledgeBaseEventSupportLeak() throws Exception { // JBRULES-3666 KnowledgeBase kbase = getKnowledgeBase(); KieBaseEventListener listener = new DefaultKieBaseEventListener(); kbase.addEventListener( listener ); kbase.addEventListener( listener ); assertEquals( 1, ( (KnowledgeBaseImpl) kbase ).getKieBaseEventListeners().size() ); kbase.removeEventListener( listener ); assertEquals( 0, ( (KnowledgeBaseImpl) kbase ).getKieBaseEventListeners().size() ); } @Test public void testReuseAgendaAfterException() throws Exception { // JBRULES-3677 String str = "import org.drools.compiler.Person;\n" + "global java.util.List results;" + "rule R1\n" + "ruleflow-group \"test\"\n" + "when\n" + " Person( $age : age ) \n" + "then\n" + " if ($age > 40) throw new RuntimeException(\"Too old\");\n" + " results.add(\"OK\");" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<String> res = new ArrayList<String>(); ksession.setGlobal( "results", res ); AgendaEventListener agendaEventListener = new AgendaEventListener() { public void matchCreated( org.kie.api.event.rule.MatchCreatedEvent event ) { } public void matchCancelled( org.kie.api.event.rule.MatchCancelledEvent event ) { } public void beforeMatchFired( org.kie.api.event.rule.BeforeMatchFiredEvent event ) { } public void afterMatchFired( org.kie.api.event.rule.AfterMatchFiredEvent event ) { } public void agendaGroupPopped( org.kie.api.event.rule.AgendaGroupPoppedEvent event ) { } public void agendaGroupPushed( org.kie.api.event.rule.AgendaGroupPushedEvent event ) { } public void beforeRuleFlowGroupActivated( org.kie.api.event.rule.RuleFlowGroupActivatedEvent event ) { } public void afterRuleFlowGroupActivated( org.kie.api.event.rule.RuleFlowGroupActivatedEvent event ) { ksession.fireAllRules(); } public void beforeRuleFlowGroupDeactivated( org.kie.api.event.rule.RuleFlowGroupDeactivatedEvent event ) { } public void afterRuleFlowGroupDeactivated( org.kie.api.event.rule.RuleFlowGroupDeactivatedEvent event ) { } }; ksession.addEventListener( agendaEventListener ); FactHandle fact1 = ksession.insert( new Person( "Mario", 38 ) ); ( (InternalAgenda) ksession.getAgenda() ).activateRuleFlowGroup( "test" ); ksession.fireAllRules(); assertEquals( 1, res.size() ); res.clear(); ksession.delete( fact1 ); FactHandle fact2 = ksession.insert( new Person( "Mario", 48 ) ); try { ( (InternalAgenda) ksession.getAgenda() ).activateRuleFlowGroup( "test" ); ksession.fireAllRules(); fail( "should throw an Exception" ); } catch (Exception e) { } ksession.delete( fact2 ); assertEquals( 0, res.size() ); // try to reuse the ksession after the Exception FactHandle fact3 = ksession.insert( new Person( "Mario", 38 ) ); ( (InternalAgenda) ksession.getAgenda() ).activateRuleFlowGroup( "test" ); ksession.fireAllRules(); assertEquals( 1, res.size() ); ksession.delete( fact3 ); ksession.dispose(); } @Test public void testBooleanPropertyStartingWithEmpty() { // JBRULES-3690 String str = "declare Fact\n" + " emptyx : boolean\n" + "end\n" + "\n" + "rule \"R1\"\n" + " when\n" + " Fact(emptyx == false)" + " then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); } @Test public void testMVELForLoop() throws Exception { // JBRULES-3717 String str = "rule demo\n" + "dialect \"mvel\"\n" + "when\n" + "then\n" + " for ( int i = 1; i <= 3; i++ ) {\n" + " insert( \"foo\" + i );\n" + " }\n" + "end"; KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder(); builder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); if ( builder.hasErrors() ) { throw new RuntimeException( builder.getErrors().toString() ); } } @Test public void testBigDecimalComparison() throws Exception { // JBRULES-3715 String str = "import org.drools.compiler.Person;\n" + "rule \"Big Decimal Comparison\"\n" + " dialect \"mvel\"\n" + "when\n" + " Person( bigDecimal == 0.0B )\n" + "then\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Person p = new Person( "Mario", 38 ); p.setBigDecimal( new BigDecimal( "0" ) ); ksession.insert( p ); assertEquals( 1, ksession.fireAllRules() ); ksession.dispose(); } @Test(timeout = 5000) public void testInfiniteLoopCausedByInheritance() throws Exception { // DROOLS-13 String str = "declare Parent\n" + " active : boolean\n" + "end\n" + " \n" + "declare Child extends Parent\n" + "end\n" + " \n" + "rule \"Init\"\n" + "when\n" + "then\n" + " insert( new Child( false ) );\n" + "end\n" + " \n" + "rule \"Print\"\n" + "when\n" + " $g : Child( active == true )\n" + "then\n" + "end\n" + " \n" + " \n" + "rule \"Switch\"\n" + "when\n" + " $item : Parent( active == false )\n" + "then\n" + " modify ( $item ) {\n" + " setActive( true );\n" + " }\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); } @Test public void testIntSorting() { // DROOLS-15 String str = "global java.util.List list\n" + "rule R\n" + "dialect \"mvel\"\n" + "when\n" + " $number : Number()\n" + " not Number(intValue < $number.intValue)\n" + "then\n" + " list.add($number);\n" + " delete($number);\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.insert( 5 ); ksession.insert( 6 ); ksession.insert( 4 ); ksession.insert( 1 ); ksession.insert( 2 ); ksession.fireAllRules(); assertEquals( asList( 1, 2, 4, 5, 6 ), list ); } @Test public void testIntSorting2() { // DROOLS-15 String str = "global java.util.List list\n" + "rule R\n" + "dialect \"mvel\"\n" + "when\n" + " $number : Number()\n" + " not Number(intValue > $number.intValue)\n" + "then\n" + " list.add($number);\n" + " delete($number);\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.insert( 3 ); ksession.insert( 7 ); ksession.insert( 4 ); ksession.insert( 5 ); ksession.insert( 2 ); ksession.insert( 1 ); ksession.insert( 6 ); ksession.fireAllRules(); assertEquals( asList( 7, 6, 5, 4, 3, 2, 1 ), list ); } @Test(timeout = 10000) public void testPropertyReactiveOnAlphaNodeFollowedByAccumulate() { // DROOLS-16 String str = "package org.drools.pmml.pmml_4_1.test;\n" + "\n" + "declare Charge\n" + " context : String\n" + " index : String = \"-1\"\n" + " source : String = \"-1\"\n" + " value : double\n" + "end\n" + "\n" + "declare Neuron\n" + "@propertyReactive\n" + " context : String @key\n" + " index : String @key\n" + " layerIndex : int\n" + " bias : double\n" + " fanIn : int\n" + " value : double\n" + " dvalue : double\n" + " normalized : boolean\n" + "end\n" + "\n" + "rule \"LinkSynapses\"\n" + "when\n" + "then\n" + " Charge c = new Charge();\n" + " c.setContext( \"MockCold\" );\n" + " c.setSource( \"0\" );\n" + " c.setIndex( \"1\" );\n" + " c.setValue( 0.43 );\n" + " insert(c);\n" + "end\n" + "\n" + "rule \"NeuralFire_MockCold_Layer0\"\n" + "when\n" + " $neur : Neuron( context == \"MockCold\",\n" + " layerIndex == 0\n" + " )\n" + " accumulate( $c : Charge( context == \"MockCold\", index == $neur.index, $in : value ),\n" + " $list : collectList( $c ),\n" + " $val : sum( $in );\n" + " $list.size() == $neur.fanIn )\n" + "then\n" + " double x = 1.0; // $neur.getBias() + $val.doubleValue();\n" + " modify ( $neur ) {\n" + " setValue( x );\n" + " }\n" + "end\n" + "\n" + "rule \"BuildNeurons_MockCold_Layer0\"\n" + "when\n" + "then\n" + " insert( new Neuron( \"MockCold\",\n" + " \"1\",\n" + " 0,\n" + " 1.0,\n" + " 1,\n" + " 0.0,\n" + " 0.0,\n" + " true\n" + " ) );\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 3, ksession.fireAllRules() ); } @Test public void testPropertyReactiveAccumulateModification() { // DROOLS-16 String str = "package org.drools.compiler.test;\n" + "\n" + "declare Neuron\n" + "@propertyReactive\n" + " id : int\n" + " value : double\n" + "end\n" + "\n" + "declare Charge\n" + " nId : int\n" + " val : double\n" + "end\n" + "\n" + "rule \"Log 2\"\n" + "salience 9999\n" + "when\n" + " $n : Object();\n" + "then\n" + "end\n" + "rule \"Update\"\n" + "salience -9999\n" + "when\n" + " $c : Charge( val == 1.0 );\n" + "then\n" + " modify ( $c ) { " + " setVal( 2.0 ); \n" + " } \n" + "end\n" + "\n" + "rule \"Init\"\n" + "when\n" + "then\n" + " insert( new Neuron( 0, 0.0 ) );\n" + " insert( new Charge( 0, 1.0 ) );\n" + "end\n" + "\n" + "rule \"Modify\"\n" + "salience -100\n" + "when\n" + " $n : Neuron( )\n" + " accumulate( Charge( $v : val ), $x : sum( $v ) )\n" + "then\n" + " modify ( $n ) {\n" + " setValue( $x.doubleValue() );\n" + " }\n" + "end\n" + "\n" + "rule \"Watch\"\n" + "when\n" + " $n : Neuron() @watch( value )" + "then\n" + "end\n" + "\n" + "query getNeuron\n" + " Neuron( $value : value )\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); assertEquals( 2.0, ksession.getQueryResults( "getNeuron" ).iterator().next().get( "$value" ) ); } @Test public void testMvelAssignmentToPublicField() { String str = "import " + Misc2Test.Foo.class.getCanonicalName() + "\n" + "rule R\n" + "dialect \"mvel\"\n" + "when\n" + " $foo : Foo()\n" + "then\n" + " $foo.x = 1;\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Foo foo1 = new Foo(); Foo foo2 = new Foo(); ksession.insert( foo1 ); ksession.insert( foo2 ); ksession.fireAllRules(); assertEquals( 1, foo1.x ); assertEquals( 1, foo2.x ); } @Test public void testMvelInvokeAsList() { String str = "import java.util.List;\n" + "import java.util.Arrays;\n" + "import java.util.ArrayList;\n" + "\n" + "declare Project\n" + "@typesafe (false)\n" + " list1 : List\n" + " list2 : List\n" + "end\n" + "\n" + "rule kickoff\n" + "salience 999999\n" + "when\n" + "then\n" + " insert( new Project() );\n" + " insert( new Project() ); // necessary to trigger the exception\n" + "end\n" + "\n" + "rule \" Config rule \"\n" + "dialect \"mvel\"\n" + "no-loop true\n" + "when\n" + " P : Project()\n" + "then\n" + " modify(P) {\n" + " list1 = Arrays.asList(10, 15, 20, 25),\n" + " list2 = Arrays.asList(11, 2, 3, 4, 5, 10, 9, 8, 7)\n" + " };\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); } @Test public void testDynamicAddRule() { // DROOLS-17 String str = "import " + Misc2Test.A.class.getCanonicalName() + "\n" + "rule r1 when\n" + " $a : A( f1 == 1 )\n" + "then\n" + "end\n" + "\n" + "rule r2 when\n" + " $a : A( f2 == 1 )\n" + "then\n" + "end\n" + "\n" + "rule r3 when\n" + " $a : A( f3 == 1 )" + "then\n" + "end"; String str2 = "import " + Misc2Test.A.class.getCanonicalName() + "\n" + "rule r4 when\n" + " $a : A( f2 == 1, f4 == 1 )" + "then\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); FactHandle fh = ksession.insert( new A( 1, 1, 1, 1 ) ); ksession.fireAllRules(); kbase.addKnowledgePackages( loadKnowledgePackagesFromString( str2 ) ); ksession.fireAllRules(); // this second insert forces the regeneration of the otnIds ksession.insert( new A( 2, 2, 2, 2 ) ); LeftTuple leftTuple = ( (DefaultFactHandle) fh ).getFirstLeftTuple(); ObjectTypeNode.Id letTupleOtnId = leftTuple.getInputOtnId(); leftTuple = leftTuple.getHandleNext(); while ( leftTuple != null ) { assertTrue( letTupleOtnId.before( leftTuple.getInputOtnId() ) ); letTupleOtnId = leftTuple.getInputOtnId(); leftTuple = leftTuple.getHandleNext(); } } @PropertyReactive public static class A { private int f1; private int f2; private int f3; private int f4; public A() { } public A( int f1, int f2, int f3, int f4 ) { this.f1 = f1; this.f2 = f2; this.f3 = f3; this.f4 = f4; } public int getF1() { return f1; } public void setF1( int f1 ) { this.f1 = f1; } public int getF2() { return f2; } public void setF2( int f2 ) { this.f2 = f2; } public int getF3() { return f3; } public void setF3( int f3 ) { this.f3 = f3; } public int getF4() { return f4; } public void setF4( int f4 ) { this.f4 = f4; } @Override public String toString() { return "A[f1=" + f1 + ", f2=" + f2 + ", f3=" + f3 + ", f4=" + f4 + "]"; } } @Test public void testNumberCoercionOnNonGenericMap() { // JBRULES-3708 String str = "package com.ilesteban.jit;\n" + "\n" + "import java.util.Map;\n" + "import java.util.EnumMap;\n" + "import " + Misc2Test.Parameter.class.getCanonicalName() + "\n" + "import " + Misc2Test.DataSample.class.getCanonicalName() + "\n" + "import " + DataSample.class.getCanonicalName() + "\n" + "\n" + "declare TestObject\n" + " data : java.util.Map\n" + "end\n" + "\n" + "rule \"Rule 1\"\n" + "when\n" + " $d: DataSample()\n" + "then\n" + " //create a new object copying the Map<Parameter, Double> to a Map<Object, Object>\n" + " insert( new TestObject($d.getValues()));\n" + "end\n" + "\n" + "rule \"Rule 2\"\n" + "when\n" + " TestObject(data[Parameter.PARAM_A] > 3)\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Map<Parameter, Double> values = new EnumMap<Parameter, Double>( Parameter.class ); values.put( Parameter.PARAM_A, 4.0 ); DataSample data = new DataSample(); data.setValues( values ); ksession.insert( data ); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testPropertyReactivityWithNestedAccessorsInModify() { // JBRULES-3691 String str = "package com.ilesteban.rulenotbeingfired;\n" + "\n" + "import java.util.Map;\n" + "import java.util.EnumMap;\n" + "import " + Misc2Test.Parameter.class.getCanonicalName() + "\n" + "import " + Misc2Test.DataSample.class.getCanonicalName() + "\n" + "\n" + "declare Recommendation\n" + " parameter : Parameter\n" + " value : double\n" + "end\n" + "\n" + "rule \"Init\" salience 100\n" + "when\n" + "then\n" + " insert(new Recommendation(Parameter.PARAM_A, 1.0));" + "end\n" + "rule \"Rule 1\"\n" + "when\n" + " $d: DataSample()\n" + " $re: Recommendation ($p: parameter, $v: value)\n" + "then\n" + " System.out.println(drools.getRule().getName());\n" + " modify($d){\n" + " addValue($re.getParameter(), $re.getValue())\n" + " }\n" + "end\n" + "\n" + "rule \"Data with messages\"\n" + "salience -100\n" + "when\n" + " $d: DataSample(notEmpty == true)\n" + "then\n" + " System.out.println(drools.getRule().getName());\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new DataSample() ); assertEquals( 3, ksession.fireAllRules() ); } public enum Parameter {PARAM_A, PARAM_B} @PropertyReactive public static class DataSample { private Map<Parameter, Double> values = new EnumMap<Parameter, Double>( Parameter.class ); public Map<Parameter, Double> getValues() { return values; } public void setValues( Map<Parameter, Double> values ) { this.values = values; } @Modifies({"values", "notEmpty"}) public void addValue( Parameter p, double value ) { this.values.put( p, value ); } public boolean isNotEmpty() { return !this.values.isEmpty(); } } @Test public void testMvelResolvingGenericVariableDeclaredInParentClass() { // JBRULES-3684 String str = "import " + Misc2Test.AbstractBase.class.getCanonicalName() + "\n" + "import " + Misc2Test.StringConcrete.class.getCanonicalName() + "\n" + "rule \"test\"\n" + "dialect \"mvel\"\n" + "when\n" + "$S : StringConcrete()\n" + "then\n" + "$S.getFoo().concat(\"this works with java dialect\");\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); } public static abstract class AbstractBase<T> { protected T foo; public T getFoo() { return foo; } } public static class StringConcrete extends AbstractBase<String> { public StringConcrete() { this.foo = new String(); } } @Test public void testMvelParsingParenthesisInString() { // JBRULES-3698 String str = "rule \"Test Rule\"\n" + "dialect \"mvel\"\n" + "when\n" + "then\n" + "String s = new String(\"write something with ) a paren\");\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); } public static enum Answer {YES, NO} public static class AnswerGiver { public Answer getAnswer() { return Answer.YES; } } @Test public void testCompilationMustFailComparingAClassLiteral() { // DROOLS-20 String str = "import Misc2Test.Answer\n" + "import Misc2Test.AnswerGiver\n" + "rule \"Test Rule\"\n" + "when\n" + " AnswerGiver(Answer == Answer.YES)\n" + "then\n" + "end"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertTrue( kbuilder.hasErrors() ); } @Test public void testDeclaredTypeExtendingInnerClass() { // DROOLS-27 String str = "import " + Misc2Test.StaticPerson.class.getCanonicalName() + "\n" + "declare StaticPerson end\n" + "declare Student extends StaticPerson end\n" + "rule Init when\n" + "then\n" + " Student s = new Student();\n" + " s.setName( \"Mark\" );\n" + " insert( s );\n" + "end\n" + "rule Check when\n" + " StaticPerson( name == \"Mark\")\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 2, ksession.fireAllRules() ); } public static class StaticPerson { private String name; public String getName() { return name; } public void setName( String name ) { this.name = name; } } @Test public void testAllowEqualityBetweenObjectAndPrimitiveInt() { // DROOLS-20 String str = "declare Bean\n" + " items : int\n" + "end\n" + "\n" + "rule \"O\"\n" + "when\n" + "then\n" + " insert( new Bean( 2 ) );\n" + "end\n" + "\n" + "rule \"X\"\n" + "when\n" + " Bean( $num : items ) \n" + " accumulate( $o : Object(),\n" + " $list : collectList( $o );\n" + " $list.size == $num" + " )\n" + "then\n" + " System.out.println( \"Success!\" );\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 1, ksession.fireAllRules() ); } @Test public void testJitConstraintWithOperationOnBigDecimal() { // DROOLS-32 String str = "import " + Misc2Test.Model.class.getCanonicalName() + "\n" + "import java.math.BigDecimal;\n" + "\n" + "rule \"minCost\" dialect \"mvel\" \n" + "when\n" + " $product : Model(price < (cost + 0.10B))\n" + "then\n" + " modify ($product) { price = $product.cost + 0.10B }\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); final Model model = new Model(); model.setCost( new BigDecimal( "2.43" ) ); model.setPrice( new BigDecimal( "2.43" ) ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( model ); int fired = ksession.fireAllRules( 2 ); if ( fired > 1 ) throw new RuntimeException( "loop" ); } public static class Model { private BigDecimal cost; private BigDecimal price; public BigDecimal getCost() { return cost; } public void setCost( BigDecimal cost ) { this.cost = cost; } public BigDecimal getPrice() { return price; } public void setPrice( BigDecimal price ) { this.price = price; } } @Test public void testJitComparable() { // DROOLS-37 String str = "import " + Misc2Test.IntegerWrapperImpl.class.getCanonicalName() + "\n" + "\n" + "rule \"minCost\"\n" + "when\n" + " $a : IntegerWrapperImpl()\n" + " IntegerWrapperImpl( this < $a )\n" + "then\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new IntegerWrapperImpl( 2 ) ); ksession.insert( new IntegerWrapperImpl( 3 ) ); assertEquals( 1, ksession.fireAllRules() ); } interface IntegerWraper { int getInt(); } public static abstract class AbstractIntegerWrapper implements IntegerWraper, Comparable<IntegerWraper> { } public static class IntegerWrapperImpl extends AbstractIntegerWrapper { private final int i; public IntegerWrapperImpl( int i ) { this.i = i; } public int compareTo( IntegerWraper o ) { return getInt() - o.getInt(); } public int getInt() { return i; } } @Test public void testJitComparableNoGeneric() { // DROOLS-37 BZ-1233976 String str = "import " + ComparableInteger.class.getCanonicalName() + "\n" + "\n" + "rule \"minCost\"\n" + "when\n" + " $a : ComparableInteger()\n" + " ComparableInteger( this < $a )\n" + "then\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new ComparableInteger( 2 ) ); ksession.insert( new ComparableInteger( 3 ) ); assertEquals( 1, ksession.fireAllRules() ); } public static class ComparableInteger implements Comparable { private final int i; public ComparableInteger( int i ) { this.i = i; } public int compareTo( Object o ) { return getInt() - ( (ComparableInteger) o ).getInt(); } public int getInt() { return i; } } @Test public void testJitComparable2() { // DROOLS-469 String str = "import " + Misc2Test.IntegerWrapperImpl2.class.getCanonicalName() + "\n" + "\n" + "rule \"minCost\"\n" + "when\n" + " $a : IntegerWrapperImpl2()\n" + " IntegerWrapperImpl2( this < $a )\n" + "then\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new IntegerWrapperImpl2( 2 ) ); ksession.insert( new IntegerWrapperImpl2( 3 ) ); assertEquals( 1, ksession.fireAllRules() ); } interface IntegerWraper2 extends Comparable<IntegerWraper2> { int getInt(); } public static abstract class AbstractIntegerWrapper2 implements IntegerWraper2 { } public static class IntegerWrapperImpl2 extends AbstractIntegerWrapper2 { private final int i; public IntegerWrapperImpl2( int i ) { this.i = i; } public int compareTo( IntegerWraper2 o ) { return getInt() - o.getInt(); } public int getInt() { return i; } } @Test public void testEqualityOfDifferentTypes() { // DROOLS-42 String str = "declare Person\n" + " name: String\n" + "end\n" + "declare Customer\n" + "extends Person\n" + " rating: int\n" + "end\n" + "declare Employee\n" + "extends Person\n" + " wage: int\n" + "end\n" + "\n" + "rule initphone\n" + "salience 100\n" + "when\n" + "then\n" + " insert( new Customer( \"Joe\", 100 ) );\n" + " insert( new Employee( \"Paul\", 2100 ) );\n" + "end\n" + "\n" + "rule match\n" + "when\n" + " $c: Customer()\n" + " $e: Employee( this != $c )\n" + "then\n" + " System.out.println( \"c/e \" + $c + \" \" + $e );\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); } @Test public void testUnificationInRule() { // DROOLS-45 String str = "declare A\n" + "end\n" + "\n" + "declare B\n" + " inner : A\n" + "end\n" + "\n" + "rule \"Init\"\n" + "when\n" + "then\n" + " A a = new A();\n" + " insert( a );\n" + " insert( new B( a ) );\n" + "end\n" + "\n" + "rule \"Check\"\n" + "when\n" + " B( $in := inner )\n" + " $in := A()\n" + "then\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testDeclarationsScopeUsingOR() { // DROOLS-44 String str = "declare A\n" + " a1 : String\n" + "end\n" + "\n" + "declare B\n" + " b1 : String\n" + "end\n" + "\n" + "rule Init salience 10 when \n" + "then\n" + " insert( new A( \"A\" ) );\n" + " insert( new B( null ) );\n" + "end\n" + "\n" + "rule R when \n" + " A ( $a1 : a1 != null )\n" + " (or\n" + " (and\n" + " B( $b1 : b1 != null )\n" + " eval( $a1.compareTo( $b1 ) < 0 )\n" + " )\n" + " (and\n" + " B( b1 == null )\n" + " eval( $a1.compareTo(\"B\") < 0 )\n" + " )\n" + " )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testDeclarationsScopeUsingOR2() { // DROOLS-44 String str = "declare A\n" + " a1 : String\n" + "end\n" + "\n" + "declare B\n" + " b1 : String\n" + "end\n" + "\n" + "rule Init salience 10 when \n" + "then\n" + " insert( new A( \"A\" ) );\n" + " insert( new B( \"B\" ) );\n" + "end\n" + "\n" + "rule R when \n" + " A ( $a1 : a1 != null )\n" + " (or\n" + " B( $b1 : b1 != null )\n" + " B( $b1 : b1 == null )\n" + " )\n" + " eval( $a1.compareTo( $b1 ) < 0 )\n" + "then\n" + " System.out.println( $b1 );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testDeclarationsScopeUsingOR3() { // DROOLS-44 String str = "declare A\n" + " a1 : String\n" + "end\n" + "\n" + "declare B\n" + " b1 : String\n" + "end\n" + "\n" + "rule Init salience 10 when \n" + "then\n" + " insert( new A( \"A\" ) );\n" + " insert( new B( null ) );\n" + "end\n" + "\n" + "rule R when \n" + " (or \n" + " A ( $a1 : a1 != null )\n" + " A ( $a1 : a1 != null ) ) \n" + " (or\n" + " (and\n" + " B( $b1 : b1 != null )\n" + " eval( $a1.compareTo( $b1 ) < 0 )\n" + " )\n" + " (and\n" + " B( b1 == null )\n" + " eval( $a1.compareTo(\"B\") < 0 )\n" + " )\n" + " )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 3, ksession.fireAllRules() ); } @Test public void testDeclarationsScopeUsingOR4() { // DROOLS-44 String str = "declare A\n" + " a1 : String\n" + "end\n" + "\n" + "declare B\n" + " b1 : String\n" + "end\n" + "\n" + "rule R when \n" + " A ( $a1 : a1 != null )\n" + " (or\n" + " (and\n" + " B( $b1 : b1 != null )\n" + " eval( $a1.compareTo( $b1 ) < 0 )\n" + " )\n" + " (and\n" + " B( b1 == null )\n" + " eval( $a1.compareTo( $b1 ) < 0 )\n" + " )\n" + " )\n" + "then\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertTrue( kbuilder.hasErrors() ); } @Test public void testQueryAfterEvalInsideOR() { // DROOLS-54 String str = "package pakko\n" + "\n" + "declare Holder\n" + " str : String\n" + "end\n" + "\n" + "declare Bean\n" + " val : String\n" + "end\n" + "\n" + "declare Mock end \n" + "\n" + "rule \"Init\"\n" + "when\n" + "then\n" + " insert( new Bean( \"xyz\" ) );\n" + " insert( new Holder( \"xyz\" ) );\n" + " insert( new Mock() );\n" + "end\n" + "\n" + "query mock( Mock $m ) $m := Mock() end\n" + "\n" + "rule \"Check\"\n" + "when\n" + " $b : Bean( $t : val )\n" + " ( Holder( $t ; ) or eval( $t.startsWith( \"abc\" ) ) )\n" + " mock( $m ; ) \n" + "then\n" + " System.out.println( $m );\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testPackageVisibility() { // DROOLS-61 String str = "package org.drools.integrationtests;\n" + "rule \"getX\"\n" + "when\n" + " $x: PackageProtected( )\n" + "then\n" + " System.out.println( $x );\n" + "end"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertTrue( kbuilder.hasErrors() ); } @Test public void testNullValueInFrom() { // DROOLS-71 String str = "global java.util.List list\n" + "\n" + "rule R\n" + "when\n" + " $i : Integer( ) from list\n" + "then\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); list.add( 1 ); list.add( null ); list.add( 2 ); ksession.fireAllRules(); } @Test public void testNumberInQuotes() throws Exception { // DROOLS-68 String str = "declare A\n" + " a1 : String\n" + "end\n" + "declare B\n" + " b1 : String\n" + "end\n" + "\n" + "rule Init salience 10 when \n" + "then\n" + " insert( new A( \"40\" ) );\n" + " insert( new A( \"2abc\" ) );\n" + " insert( new B( \"300\" ) );\n" + "end\n" + "\n" + "rule R1 when\n" + " A( $a1 : a1 ) \n" + " B( b1 > $a1 ) \n" + "then\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testStringCoercionComparison() { // DROOLS-167 String str = "import " + Person.class.getName() + ";\n" + "rule R1 when\n" + " $p : Person( name < \"90201304122000000000000017\" )\n" + "then end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new Person( "90201304122000000000000015", 38 ) ); assertEquals( 1, ksession.fireAllRules() ); } @Test public void testAvoidUnwantedSemicolonWhenDelimitingExpression() { // DROOLS-86 String str = "global java.util.List l\n" + "rule rule1 \n" + " dialect \"mvel\" \n" + "when \n" + "then \n" + " String s = \"http://onefineday.123\";\n" + " l.add(s);\n" + "end \n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<String> l = new ArrayList<String>(); ksession.setGlobal( "l", l ); ksession.fireAllRules(); assertEquals( "http://onefineday.123", l.get( 0 ) ); } @Test public void testJitCastOfPrimitiveType() { // DROOLS-79 String str = "rule R when\n" + " Number(longValue < (Long)7)\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new Long( 6 ) ); assertEquals( 1, ksession.fireAllRules() ); } @Test public void testSelfChangingRuleSet() { // DROOLS-92 String str = "package org.drools.compiler.integrationtests;\n" + "" + "import org.drools.compiler.integrationtests.Misc2Test.Foo2; \n" + "" + "global java.util.List list; \n" + "\n" + "rule \"Prep\" \n" + "when \n" + " $packs : java.util.Collection() \n" + "then \n" + " ((org.drools.core.impl.InternalKnowledgeBase)drools.getKieRuntime().getKieBase()).addKnowledgePackages( $packs );" + "end \n" + "" + "rule \"Self-change\"\n" + "when\n" + " String( this == \"go\" )\n" + "then\n" + " ((org.drools.core.impl.InternalKnowledgeBase)drools.getKieRuntime().getKieBase()).removeRule( \"org.drools.compiler.integrationtests\", \"React\" ); \n" + "end\n" + "\n" + "\n" + "rule \"Insert\"\n" + "when\n" + " $i : Integer()\n" + "then\n" + " Foo2 foo = new Foo2();\n " + " foo.setX( $i ); \n" + " insert( foo );\n" + "end\n" + "" + ""; String str2 = "package org.drools.compiler.integrationtests;\n" + "" + "import org.drools.compiler.integrationtests.Misc2Test.Foo2; \n" + "global java.util.List list;\n " + "rule \"React\"\n" + "when\n" + " $b : Foo2( x < 10 )\n" + "then\n" + " System.out.println( \" Foo2 is in \" + $b.getX() );" + " list.add( $b ); \n" + "end\n"; KnowledgeBuilder knowledgeBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); knowledgeBuilder.add( new ByteArrayResource( str2.getBytes() ), ResourceType.DRL ); System.out.println( knowledgeBuilder.getErrors() ); KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.insert( knowledgeBuilder.getKnowledgePackages() ); ksession.insert( new Integer( 1 ) ); ksession.fireAllRules(); ksession.insert( "go" ); ksession.fireAllRules(); ksession.insert( new Integer( 2 ) ); ksession.fireAllRules(); assertEquals( 1, list.size() ); } @Test public void testMatchIntegers() { // DROOLS-94 String str = "global java.util.List list; \n" + "rule R when\n" + " $i : Integer( this == 1 )\n" + "then\n" + " list.add( $i );\n" + "end\n" + "rule S when\n" + " $i : Integer( this == 2 )\n" + "then\n" + " list.add( $i );\n" + "end\n" + "rule T when\n" + " $i : Integer( this == 3 )\n" + "then\n" + " list.add( $i );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.insert( new Integer( 1 ) ); ksession.fireAllRules(); } public static class SimpleEvent { private long duration; public long getDuration() { return duration; } public void setDuration( long duration ) { this.duration = duration; } } @Test public void testDurationAnnotation() { // DROOLS-94 String str = "package org.drools.compiler.integrationtests;\n" + "import org.drools.compiler.integrationtests.Misc2Test.SimpleEvent\n" + "declare SimpleEvent\n" + " @role(event)\n" + " @duration(duration)\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); } @Test public void testDurationAnnotationOnKie() { // DROOLS-94 String str = "package org.drools.compiler.integrationtests;\n" + "import org.drools.compiler.integrationtests.Misc2Test.SimpleEvent\n" + "declare SimpleEvent\n" + " @role(event)\n" + " @duration(duration)\n" + "end\n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); ks.newKieBuilder( kfs ).buildAll(); KieSession ksession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); } @Test public void testDurationAnnotationWithError() { // DROOLS-94 String str = "package org.drools.compiler.integrationtests;\n" + "import org.drools.compiler.integrationtests.Misc2Test.SimpleEvent\n" + "declare SimpleEvent\n" + " @role(event)\n" + " @duration(duratio)\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertTrue( kbuilder.hasErrors() ); } @Test public void testPhreakWithConcurrentUpdates() { // DROOLS-7 String str = "import org.drools.compiler.Person\n" + "rule R when\n" + " $s : String()\n" + " $i : Integer()\n" + " not Person( age == $i, name.startsWith($s) )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( 30 ); ksession.insert( 31 ); ksession.insert( "B" ); ksession.insert( "D" ); Person pA = new Person( "AAA", 30 ); Person pB = new Person( "BBB", 30 ); Person pC = new Person( "CCC", 31 ); Person pD = new Person( "DDD", 31 ); FactHandle fhB = ksession.insert( pB ); FactHandle fhD = ksession.insert( pD ); FactHandle fhA = ksession.insert( pA ); FactHandle fhC = ksession.insert( pC ); ksession.fireAllRules(); pB.setAge( 31 ); pB.setName( "DBB" ); ksession.update( fhB, pB ); pD.setAge( 30 ); pD.setName( "BDD" ); ksession.update( fhD, pD ); assertEquals( 0, ksession.fireAllRules() ); pB.setAge( 30 ); pB.setName( "BBB" ); ksession.update( fhB, pB ); pD.setAge( 31 ); pD.setName( "DDD" ); ksession.update( fhD, pD ); assertEquals( 0, ksession.fireAllRules() ); } @Test public void testPhreakWith2Nots() { // DROOLS-7 String str = "import org.drools.compiler.Person\n" + "global java.util.List list;\n" + "rule R when\n" + " Person( $age : age, $name : name )\n" + " not Person( name == $name, age == $age + 1 )\n" + " not Person( name == $name, age == $age - 1 )\n" + "then\n" + " list.add($age);\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); Person p1 = new Person( "AAA", 31 ); Person p2 = new Person( "AAA", 34 ); Person p3 = new Person( "AAA", 33 ); FactHandle fh1 = ksession.insert( p1 ); FactHandle fh3 = ksession.insert( p3 ); FactHandle fh2 = ksession.insert( p2 ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 31, (int) list.get( 0 ) ); list.clear(); p1.setAge( 35 ); ksession.update( fh1, p1 ); p3.setAge( 31 ); ksession.update( fh3, p3 ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 31, (int) list.get( 0 ) ); } @Test public void testPhreakTMS() { // DROOLS-7 String str = "import org.drools.compiler.Person\n" + "import org.drools.compiler.Cheese\n" + "rule R when\n" + " Person( $age : age, $name : name == \"A\" )\n" + " not Person( age == $age + 1 )\n" + "then\n" + " insertLogical(new Cheese(\"gorgonzola\", 10));\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Person p1 = new Person( "A", 31 ); FactHandle fh1 = ksession.insert( p1 ); ksession.fireAllRules(); assertEquals( 1, ksession.getObjects( new ClassObjectFilter( Cheese.class ) ).size() ); Person p2 = new Person( "A", 32 ); FactHandle fh2 = ksession.insert( p2 ); ksession.fireAllRules(); assertEquals( 1, ksession.getObjects( new ClassObjectFilter( Cheese.class ) ).size() ); } @Test public void testHelloWorld() throws Exception { // DROOLS-145 String drl = "package org.drools.test\n" + "declare Message\n" + " message : String\n" + "end\n" + "rule R1 when\n" + " $m : Message( message == \"Hello World\" )\n" + "then\n" + "end\n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", drl ); KieBuilder builder = ks.newKieBuilder( kfs ).buildAll(); assertEquals( 0, builder.getResults().getMessages().size() ); ks.getRepository().addKieModule( builder.getKieModule() ); KieSession ksession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); FactType messageType = ksession.getKieBase().getFactType( "org.drools.test", "Message" ); Object message = messageType.newInstance(); messageType.set( message, "message", "Hello World" ); ksession.insert( message ); assertEquals( 1, ksession.fireAllRules() ); KieSession ksession2 = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); FactType messageType2 = ksession2.getKieBase().getFactType( "org.drools.test", "Message" ); Object message2 = messageType2.newInstance(); messageType2.set( message2, "message", "Hello World" ); ksession2.insert( message2 ); assertEquals( 1, ksession2.fireAllRules() ); } public static class Lecture { private final String id; private int day; private int index; private boolean available; public Lecture( String id, int day, int index ) { this( id, day, index, true ); } public Lecture( String id, int day, int index, boolean available ) { this.id = id; this.day = day; this.index = index; this.available = available; } public String getId() { return id; } public int getDay() { return day; } public Lecture setDay( int day ) { this.day = day; return this; } public int getIndex() { return index; } public Lecture setIndex( int index ) { this.index = index; return this; } public boolean isAvailable() { return available; } public Lecture setAvailable( boolean available ) { this.available = available; return this; } @Override public String toString() { return id + " - " + "day = " + getDay() + "; index = " + getIndex(); } } @Test public void testPhreakInnerJoinNot() { // DROOLS-7 String str = "import org.drools.compiler.integrationtests.Misc2Test.Lecture\n" + "global java.util.List list;\n" + "rule \"curriculumCompactness\"\n" + " when\n" + " $lecture : Lecture(\n" + " $day : day, $index : index\n" + " )\n" + " not Lecture(\n" + " day == $day, index == ($index + 1)\n" + " )\n" + " then\n" + " list.add($lecture.getId());\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); ksession.setGlobal( "list", list ); Lecture lA = new Lecture( "A", 0, 4 ); Lecture lB = new Lecture( "B", 2, 2 ); Lecture lC = new Lecture( "C", 2, 1 ); FactHandle fhA = ksession.insert( lA ); FactHandle fhB = ksession.insert( lB ); FactHandle fhC = ksession.insert( lC ); ksession.fireAllRules(); // C gets blocked by B assertEquals( 2, list.size() ); assertTrue( list.containsAll( asList( "A", "B" ) ) ); list.clear(); ksession.update( fhB, lB.setDay( 0 ).setIndex( 4 ) ); ksession.update( fhC, lC.setDay( 0 ).setIndex( 3 ) ); ksession.fireAllRules(); // B is still a valid blocker for C assertEquals( 1, list.size() ); assertTrue( list.contains( "B" ) ); list.clear(); ksession.update( fhB, lB.setDay( 2 ).setIndex( 2 ) ); ksession.fireAllRules(); // C doesn't find A as blocker assertEquals( 1, list.size() ); assertTrue( list.contains( "B" ) ); } @Test public void testPhreakAccumulate() { // DROOLS-7 String str = "import org.drools.compiler.integrationtests.Misc2Test.Lecture\n" + "global java.util.List list;\n" + "rule \"R1\"\n" + " when\n" + " $lecture : Lecture(\n" + " $day : day, $index : index\n" + " )\n" + " not Lecture(\n" + " day == $day, index == ($index + 1)\n" + " )\n" + " then\n" + " list.add($lecture.getId());\n" + "end\n" + "rule \"R2\"\n" + " when\n" + " $availableLectures : Number(intValue > 0) from accumulate(\n" + " $lecture : Lecture(\n" + " available == true\n" + " ),\n" + " count($lecture)\n" + " )\n\n" + " then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); ksession.setGlobal( "list", list ); Lecture lA = new Lecture( "A", 0, 4, true ); Lecture lB = new Lecture( "B", 2, 2, true ); Lecture lC = new Lecture( "C", 2, 1, true ); FactHandle fhA = ksession.insert( lA ); FactHandle fhB = ksession.insert( lB ); FactHandle fhC = ksession.insert( lC ); ksession.fireAllRules(); assertEquals( 2, list.size() ); assertTrue( list.containsAll( asList( "A", "B" ) ) ); list.clear(); ksession.update( fhB, lB.setAvailable( false ) ); ksession.fireAllRules(); ksession.update( fhB, lB.setDay( 0 ).setIndex( 3 ) ); ksession.fireAllRules(); assertEquals( 2, list.size() ); assertTrue( list.containsAll( asList( "B", "C" ) ) ); list.clear(); } @Test public void testQueryAndRetract() { // DROOLS-7 String str = "global java.util.List list\n" + "\n" + "query q (String $s)\n" + " String( this == $s )\n" + "end" + "\n" + "rule R1 when\n" + " $x : String( this == \"x\" )\n" + " ?q( \"x\"; )\n" + "then\n" + " delete( \"x\" );\n" + "end\n"; KieSession ksession = new KieHelper().addContent(str, ResourceType.DRL).build().newKieSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ( (RuleEventManager) ksession ).addEventListener( new RuleEventListener() { @Override public void onDeleteMatch( Match match ) { list.add("test"); } } ); ksession.insert( "x" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); } @Test(timeout = 5000) public void testPhreakNoLoop() { // DROOLS-7 String str = "declare Person \n" + " name : String\n" + " age : int\n" + "end\n" + "\n" + "rule Init when \n" + "then\n" + " insert( new Person( \"Mario\", 39 ) );\n" + "end\n" + "\n" + "rule R no-loop when\n" + " $p: Person( name == \"Mario\" )\n" + " not String( this == \"go\" )\n" + "then\n" + " modify( $p ) { setAge( 40 ) };\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testAddSameResourceTwice() { // DROOLS-180 String str = "rule R when\n" + " $s : String()\n" + "then\n" + "end\n"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertTrue( kbuilder.hasResults( ResultSeverity.INFO, ResultSeverity.WARNING, ResultSeverity.ERROR ) ); } @Test public void testTwoTimers() { // BZ-980385 String str = "import java.util.Date\n" + "import java.util.List\n" + "\n" + "global List dates\n" + "\n" + "rule \"intervalRule\"\n" + " timer(int: 200ms 100ms)\n" + "when\n" + " String(this == \"intervalRule\")\n" + "then\n" + " Date date = new Date();\n" + " dates.add(date);\n" + "end\n" + "\n" + "\n" + "// this rule stops timer\n" + "rule \"stopIntervalRule\"\n" + " timer(int: 320ms)\n" + "when\n" + " $s : String(this == \"intervalRule\")\n" + "then\n" + " delete($s);\n" + "end\n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); assertEquals( 0, ks.newKieBuilder( kfs ).buildAll().getResults().getMessages().size() ); KieSession ksession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); } @Test public void testUnsupportedPolymorphicDeclaration() { // DROOLS-162 String drl = "package org.drools.test; \n" + "" + "declare Foo end \n" + "declare Bar end \n" + "" + "" + "rule X when\n" + " $x : Foo() " + " or " + " $x : Bar() \n" + "then\n" + " System.out.println( $x ); \n" + "end\n" + "" + "rule Init\n" + "when\n" + "then\n" + " insert( new Foo() ); \n" + " insert( new Bar() ); \n" + "end"; KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder(); kb.add( new ByteArrayResource( drl.getBytes() ), ResourceType.DRL ); assertTrue( kb.hasErrors() ); } @Test public void testLegacySalienceResolver() { // DROOLS-159 String drl = "package org.drools.test; \n" + "" + "global java.util.List list; \n " + "" + "rule X salience 10 \n" + "then\n" + " list.add( 1 ); \n" + "end\n" + "" + "rule Y salience 5 \n" + "then\n" + " list.add( 2 ); \n" + "end\n" + ""; KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder(); kb.add( new ByteArrayResource( drl.getBytes() ), ResourceType.DRL ); assertFalse( kb.hasErrors() ); KieBaseConfiguration kbconf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); ( (RuleBaseConfiguration) kbconf ).setConflictResolver( SalienceConflictResolver.getInstance() ); KnowledgeBase knowledgeBase = KnowledgeBaseFactory.newKnowledgeBase( kbconf ); knowledgeBase.addKnowledgePackages( kb.getKnowledgePackages() ); StatefulKnowledgeSession knowledgeSession = knowledgeBase.newStatefulKnowledgeSession(); List list = new ArrayList(); knowledgeSession.setGlobal( "list", list ); knowledgeSession.fireAllRules(); assertEquals( Arrays.asList( 1, 2 ), list ); } @Test public void testUnaryNegation() { // DROOLS-177 String str = "rule R when\n" + " Integer( $a: intValue )\n" + " Integer( intValue > $a, intValue == -$a )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( 3 ); ksession.insert( -3 ); assertEquals( 1, ksession.fireAllRules() ); } public static class Conversation { private final int id; private String family; private int timeslot; public Conversation( int id ) { this.id = id; } public Conversation( int id, String family, int timeslot ) { this.id = id; this.family = family; this.timeslot = timeslot; } public int getId() { return id; } public String getFamily() { return family; } public void setFamily( String family ) { this.family = family; } public int getTimeslot() { return timeslot; } public void setTimeslot( int timeslot ) { this.timeslot = timeslot; } public String toString() { return "Conversation #" + getId() + " with " + getFamily() + " @ " + getTimeslot(); } } @Test public void testNotNodeUpdateBlocker() { String str = "import org.drools.compiler.integrationtests.Misc2Test.Conversation;\n" + "global java.util.List list;" + "\n" + "rule \"familyEnd\" when\n" + " $conversation : Conversation(\n" + " family != null, $family: family, \n" + " $timeslot: timeslot)\n" + "\n" + " not Conversation(\n" + " family == $family, \n" + " timeslot > $timeslot);\n" + "then\n" + " list.add($conversation);\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Conversation> conversations = new ArrayList<Conversation>(); ksession.setGlobal( "list", conversations ); Conversation c0 = new Conversation( 0, "Fusco", 2 ); Conversation c1 = new Conversation( 1, "Fusco", 3 ); Conversation c2 = new Conversation( 2, "Fusco", 4 ); FactHandle fh0 = ksession.insert( c0 ); FactHandle fh1 = ksession.insert( c1 ); FactHandle fh2 = ksession.insert( c2 ); ksession.fireAllRules(); assertEquals( 1, conversations.size() ); conversations.clear(); c2.setTimeslot( 0 ); ksession.update( fh2, c2 ); ksession.fireAllRules(); c2.setTimeslot( 4 ); ksession.update( fh2, c2 ); ksession.fireAllRules(); conversations.clear(); c0.setTimeslot( 3 ); ksession.update( fh0, c0 ); ksession.fireAllRules(); c0.setTimeslot( 2 ); ksession.update( fh0, c0 ); ksession.fireAllRules(); conversations.clear(); c2.setTimeslot( 1 ); ksession.update( fh2, c2 ); ksession.fireAllRules(); assertEquals( 1, conversations.size() ); } @Test public void testFailedStaticImport() { // DROOLS-155 String drl = "package org.drools.test; \n" + "" + "import function org.does.not.exist.Foo; \n" + "" + "" + "rule X when\n" + "then\n" + "end"; KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder(); kb.add( new ByteArrayResource( drl.getBytes() ), ResourceType.DRL ); assertTrue( kb.hasErrors() ); } @Test public void testNamedConsequence() { List<String> firedRules = new ArrayList<String>(); String str = "import " + Foo.class.getCanonicalName() + "\n" + "import " + Foo2.class.getCanonicalName() + "\n" + "global java.util.List fired;\n" + "rule \"weird foo\"\n" + " when\n" + " \n" + " $foo: Foo($x: x)\n" + " if( $foo.getX() != 1 ) break[needThis]\n" + " $foo2: Foo2(x == $x);\n" + " then\n" + " fired.add(\"We made it!\");\n" + " then[needThis]\n" + " modify($foo){\n" + " setX(1)\n" + " };\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.setGlobal( "fired", firedRules ); ksession.insert( new Foo() ); ksession.insert( new Foo2( 1 ) ); ksession.fireAllRules(); assertEquals( 1, firedRules.size() ); } @Test public void testNamedConsequenceWithNot() { List<String> firedRules = new ArrayList<String>(); String str = "import " + Foo.class.getCanonicalName() + "\n" + "import " + Foo2.class.getCanonicalName() + "\n" + "global java.util.List fired;\n" + "rule \"weird foo\"\n" + " when\n" + " $foo: Foo($x: x)\n" + " if( $foo.getX() != 1 ) break[needThis] \n" + " not( Foo(x == 2) ) \n" + " $foo2: Foo2(x == $x)\n" + " then\n" + " fired.add(\"We made it!\");\n" + " then[needThis]\n" + " modify($foo){\n" + " setX(1)\n" + " };\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.setGlobal( "fired", firedRules ); ksession.insert( new Foo() ); ksession.insert( new Foo2( 1 ) ); ksession.fireAllRules(); assertEquals( 1, firedRules.size() ); } public static class Foo { public int x; public int getX() { return x; } public void setX( int x ) { this.x = x; } } public static class Foo2 { @Position(0) public int x; public Foo2() { } public Foo2( int x ) { this.x = x; } public int getX() { return x; } public void setX( int x ) { this.x = x; } } @Test public void testBetaNodeInSubnetworkInStreamMode() { // BZ-995408 String str = "import " + Foo.class.getCanonicalName() + "\n" + "\n" + "global java.util.List context;\n" + "\n" + "declare Foo\n" + " @role( event )\n" + "end\n" + "\n" + "rule \"Rule A\"\n" + "when\n" + " $f : Foo( )\n" + " not ( Integer() from context )\n" + "then\n" + " $f.setX( 2 );\n" + "end"; KieBaseConfiguration kBaseConf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); kBaseConf.setOption( EventProcessingOption.STREAM ); KnowledgeBase kbase = loadKnowledgeBaseFromString( kBaseConf, str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.setGlobal( "context", new ArrayList() {{ add( new Long( 0 ) ); }} ); Foo foo = new Foo(); foo.setX( 1 ); ksession.insert( foo ); ksession.fireAllRules(); assertEquals( 2, foo.getX() ); } @Test public void testIsAWith2KContainers() { // BZ-996056 String str = "import org.drools.compiler.Person\n" + "\n" + "global java.util.List students\n" + "\n" + "declare trait Student\n" + " school : String\n" + "end\n" + "\n" + "rule \"create student\" \n" + " when\n" + " $student : Person( age < 26, this not isA Student )\n" + " then\n" + " Student s = don( $student, Student.class );\n" + " s.setSchool(\"Masaryk University\");\n" + " update( $student );\n" + "end\n" + "\n" + "rule \"found student\"\n" + " salience 10\n" + " when\n" + " student : Person( this isA Student )\n" + " then\n" + " students.add(student);\n" + "end"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write( "src/main/resources/isA.drl", str ); KieBuilder kbuilder = ks.newKieBuilder( kfs ); kbuilder.buildAll(); assertEquals( 0, kbuilder.getResults().getMessages().size() ); ks.newKieContainer( kbuilder.getKieModule().getReleaseId() ).getKieBase(); KieSession ksession = ks.newKieContainer( kbuilder.getKieModule().getReleaseId() ).newKieSession(); assertNotNull( ksession ); List students = new ArrayList(); ksession.setGlobal( "students", students ); ksession.insert( new Person( "tom", 20 ) ); ksession.fireAllRules(); assertEquals( 1, students.size() ); } @Test public void testAutomaticallySwitchFromReteOOToPhreak() { String str = "rule R when then end\n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write( "src/main/resources/rule.drl", str ); KieBuilder kbuilder = ks.newKieBuilder( kfs ); kbuilder.buildAll(); assertEquals( 0, kbuilder.getResults().getMessages().size() ); KieBase kbase = ks.newKieContainer( kbuilder.getKieModule().getReleaseId() ).getKieBase(); KieSession ksession = kbase.newKieSession(); ksession.fireAllRules(); } @Test public void testListnersOnStatlessKieSession() { // DROOLS-141 // BZ-999491 String str = "rule R when\n" + " String()\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatelessKieSession ksession = kbase.newStatelessKnowledgeSession(); final List<String> firings = new ArrayList<String>(); AgendaEventListener agendaEventListener = new AgendaEventListener() { public void matchCreated( org.kie.api.event.rule.MatchCreatedEvent event ) { } public void matchCancelled( org.kie.api.event.rule.MatchCancelledEvent event ) { } public void beforeMatchFired( org.kie.api.event.rule.BeforeMatchFiredEvent event ) { } public void afterMatchFired( org.kie.api.event.rule.AfterMatchFiredEvent event ) { firings.add( "Fired!" ); } public void agendaGroupPopped( org.kie.api.event.rule.AgendaGroupPoppedEvent event ) { } public void agendaGroupPushed( org.kie.api.event.rule.AgendaGroupPushedEvent event ) { } public void beforeRuleFlowGroupActivated( org.kie.api.event.rule.RuleFlowGroupActivatedEvent event ) { } public void afterRuleFlowGroupActivated( org.kie.api.event.rule.RuleFlowGroupActivatedEvent event ) { } public void beforeRuleFlowGroupDeactivated( org.kie.api.event.rule.RuleFlowGroupDeactivatedEvent event ) { } public void afterRuleFlowGroupDeactivated( org.kie.api.event.rule.RuleFlowGroupDeactivatedEvent event ) { } }; ksession.addEventListener( agendaEventListener ); ksession.execute( "1" ); ksession.execute( "2" ); assertEquals( 2, firings.size() ); ksession.removeEventListener( agendaEventListener ); ksession.execute( "3" ); assertEquals( 2, firings.size() ); } @Test public void testKsessionSerializationWithInsertLogical() { List<String> firedRules = new ArrayList<String>(); String str = "import java.util.Date;\n" + "import org.drools.compiler.integrationtests.Misc2Test.Promotion;\n" + "\n" + "declare Person\n" + " name : String\n" + " dateOfBirth : Date\n" + "end\n" + "\n" + "declare Employee extends Person\n" + " job : String\n" + "end\n" + "\n" + "rule \"Insert Alice\"\n" + " when\n" + " then\n" + " Employee alice = new Employee(\"Alice\", new Date(1973, 7, 2), \"Vet\");\n" + " insert(alice);\n" + " System.out.println(\"Insert Alice\");\n" + "end\n" + "\n" + "rule \"Insert Bob\"\n" + " when\n" + " Person(name == \"Alice\")\n" + " then\n" + " Person bob = new Person(\"Bob\", new Date(1973, 7, 2));\n" + " insertLogical(bob);\n" + " System.out.println(\"InsertLogical Bob\");\n" + "end\n" + "\n" + "rule \"Insert Claire\"\n" + " when\n" + " Person(name == \"Bob\")\n" + " then\n" + " Employee claire = new Employee(\"Claire\", new Date(1973, 7, 2), \"Student\");\n" + " insert(claire);\n" + " System.out.println(\"Insert Claire\");\n" + "end\n" + "\n" + "rule \"Promote\"\n" + " when\n" + " p : Promotion(n : name, j : job)\n" + " e : Employee(name == n)\n" + " then\n" + " modify(e) {\n" + " setJob(j)\n" + " }\n" + " delete(p);\n" + " System.out.printf(\"Promoted %s to %s%n\", n, j);\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); // insertLogical Person(Bob) // Serialize and Deserialize try { Marshaller marshaller = MarshallerFactory.newMarshaller( kbase ); ByteArrayOutputStream baos = new ByteArrayOutputStream(); marshaller.marshall( baos, ksession ); marshaller = MarshallerFactory.newMarshaller( kbase ); ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() ); baos.close(); ksession = (StatefulKnowledgeSession) marshaller.unmarshall( bais ); bais.close(); } catch (Exception e) { e.printStackTrace(); fail( "unexpected exception :" + e.getMessage() ); } ksession.insert( new Promotion( "Claire", "Scientist" ) ); int result = ksession.fireAllRules(); assertEquals( 1, result ); } public static class Promotion { private String name; private String job; public Promotion( String name, String job ) { this.setName( name ); this.setJob( job ); } public String getName() { return this.name; } public void setName( String name ) { this.name = name; } public String getJob() { return this.job; } public void setJob( String job ) { this.job = job; } } @Test public void testImportExceptional() throws java.lang.Exception { // DROOLS-253 imported Exception would have qualified as the default Exception thrown by the RHS String str = "import org.acme.healthcare.Exception;\n" + "" + "global java.util.List list;" + "\n" + "" + "rule \"Init\" when\n" + "then\n" + " list.add( 1 ); \n" + "end\n" + ""; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( Arrays.asList( 1 ), list ); } @Test public void testMapAccessorWithCustomOp() { // DROOLS-216 String str = "import java.util.Map;\n" + "global java.util.List list;\n" + "rule R when\n" + " Map( this[\"x\"] str[startsWith] \"T\" )\n" + " Map( this[\"x\"] soundslike \"Test\" )\n" + "then\n" + " list.add( 1 );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); ksession.setGlobal( "list", list ); Map<String, String> map = new HashMap<String, String>(); map.put( "x", "Test" ); ksession.insert( map ); ksession.fireAllRules(); assertEquals( Arrays.asList( 1 ), list ); } @Test public void testMapAccessorWithBoundVar() { // DROOLS-217 String str = "import java.util.Map;\n" + "global java.util.List list;\n" + "rule R when\n" + " Map( $val1 : this[\"x\"], $val1 str[startsWith] \"T\" )\n" + " Map( $val2 : this[\"x\"], $val2 soundslike \"Test\" )\n" + "then\n" + " list.add( 1 );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); ksession.setGlobal( "list", list ); Map<String, String> map = new HashMap<String, String>(); map.put( "x", "Test" ); ksession.insert( map ); ksession.fireAllRules(); assertEquals( Arrays.asList( 1 ), list ); } @Test(timeout = 10000) public void testAgendaGroupSalience() { // BZ-999360 String str = "global java.util.List ruleList\n" + "\n" + "rule first\n" + "salience 2\n" + "when\n" + "then\n" + " ruleList.add(\"first\");\n" + " drools.getKnowledgeRuntime().getAgenda().getAgendaGroup(\"agenda\").setFocus();\n" + "end\n" + "\n" + "rule second\n" + "agenda-group \"agenda\"\n" + "when\n" + " $s : String( this == 'fireRules' )\n" + "then\n" + " ruleList.add(\"second\");\n" + "end\n" + "\n" + "rule third\n" + "salience 1\n" + "when\n" + " $s : String( this == 'fireRules' )\n" + "then\n" + " ruleList.add(\"third\");\n" + "end\n"; KieBaseConfiguration kconf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); kconf.setOption( DeclarativeAgendaOption.ENABLED ); KnowledgeBase kbase = loadKnowledgeBaseFromString( kconf, str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ArrayList<String> ruleList = new ArrayList<String>(); ksession.setGlobal( "ruleList", ruleList ); ksession.insert( "fireRules" ); ksession.fireAllRules(); assertEquals( ruleList.get( 0 ), "first" ); assertEquals( ruleList.get( 1 ), "second" ); assertEquals( ruleList.get( 2 ), "third" ); } @Test public void test3IdenticalForall() { // BZ-999851 String str = "rule \"Rule with forall_1\"\n" + "when\n" + " forall ($obj : Object()\n" + " Object(this == $obj)\n" + " )\n" + "then\n" + "end\n" + "\n" + "rule \"Rule with forall_2\"\n" + "when\n" + " forall ($obj : Object()\n" + " Object(this == $obj)\n" + " )\n" + "then\n" + "end\n" + "\n" + "rule \"Rule with forall_3\"\n" + "when\n" + " forall ($obj : Object()\n" + " Object(this == $obj)\n" + " )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); } @Test public void testSegmentInitialization() { // BZ-1011993 String str = "import " + Misc2Test.Resource.class.getCanonicalName() + "\n" + "import " + Misc2Test.ResourceRequirement.class.getCanonicalName() + "\n" + "import " + Misc2Test.Allocation.class.getCanonicalName() + "\n" + "rule R" + " when\n" + " $resource : Resource($capacity : capacity)\n" + " $used : Number(intValue > $capacity) from accumulate(\n" + " ResourceRequirement(resource == $resource,\n" + " $executionMode : executionMode)\n" + " and Allocation(executionMode == $executionMode),\n" + " sum($executionMode)\n" + " )\n" + " then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new ResourceRequirement( new Resource( 2 ), 3 ) ); ksession.insert( new Allocation( 3 ) ); ksession.fireAllRules(); } public static class Resource { private final int capacity; public Resource( int capacity ) { this.capacity = capacity; } public int getCapacity() { return capacity; } } public static class ResourceRequirement { private final Resource resource; private final int executionMode; public ResourceRequirement( Resource resource, int executionMode ) { this.resource = resource; this.executionMode = executionMode; } public Resource getResource() { return resource; } public int getExecutionMode() { return executionMode; } } public static class Allocation { private final int executionMode; public Allocation( int executionMode ) { this.executionMode = executionMode; } public int getExecutionMode() { return executionMode; } } public static interface FooIntf { public boolean isSafe(); public void setSafe( boolean safe ); } public static class BarKlass implements FooIntf { public boolean isSafe() { return true; } public void setSafe( boolean safe ) { } } @Test public void testMvelJittingWithTraitProxies() throws Exception { // DROOLS-291 String drl = "package org.drools.test; \n" + "" + "import org.drools.compiler.integrationtests.Misc2Test.FooIntf; \n" + "import org.drools.compiler.integrationtests.Misc2Test.BarKlass; \n" + "" + "declare BarKlass end \n" + "declare FooIntf end \n" + "" + "declare trait ExtFoo extends FooIntf end \n" + "" + "declare Kore @Traitable safe : boolean end \n" + "" + "rule \"Test2\" when FooIntf( safe == true ) then end \n" + "" + "rule \"In1\" when $s : String() then don( new Kore( true ), ExtFoo.class ); end \n" + "rule \"In2\" when $s : Integer() then insert( new BarKlass() ); end \n" + "" + ""; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ks = kb.newStatefulKnowledgeSession(); for ( int j = 0; j < 21; j++ ) { ks.insert( "x" + j ); ks.fireAllRules(); } // wait for jitting Thread.sleep( 100 ); ks.insert( 0 ); ks.fireAllRules(); } @Test public void testReportErrorOnWrongDateEffective() { // BZ-1013545 String drl = // ensure no Locale can parse the Date "rule X date-effective \"9-asbrdfh-1974\" when\n" + " $s : String() " + "then\n" + "end\n"; KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder(); kb.add( new ByteArrayResource( drl.getBytes() ), ResourceType.DRL ); assertTrue( kb.hasErrors() ); } @Test public void testDeleteInFromNode() { String drl = "global java.util.Map context\n" + "\n" + "rule A\n" + " when\n" + " $i : Integer()\n" + " then\n" + " context.remove(\"key\");\n" + "end\n" + "\n" + "rule B\n" + " when\n" + " $s : String() from context.get(\"key\")\n" + " then\n" + " System.out.println($s);" + "end\n"; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ks = kb.newStatefulKnowledgeSession(); Map<String, String> context = new HashMap<String, String>(); context.put( "key", "value" ); ks.setGlobal( "context", context ); ks.insert( 1 ); ks.fireAllRules(); context.put( "key", "value" ); //ks.insert(2); ks.fireAllRules(); } @Test public void testSortWithNot() { // DROOLS-200 String str = "import java.util.*; \n" + "" + "global java.util.List list;" + "\n" + "" + "declare Bean \n" + " value : Integer @key \n" + " mark : boolean = false \n" + "end \n" + "" + "declare Holder\n" + " map : Map \n" + "end \n" + "" + "rule \"Init\" when\n" + "then\n" + " insert( new Holder( new HashMap() ) ); \n" + " insert( new Bean( 10 ) );\n" + " insert( new Bean( 30 ) );\n" + " insert( new Bean( 20 ) );\n" + " insert( new Bean( 50 ) );\n" + " insert( new Bean( 40 ) );\n" + "end\n" + "" + "rule Sort when \n" + " $h : Holder( $map : map ) \n" + " $b : Bean( ! $map.containsKey( value ), $v : value ) \n" + " not Bean( ! $map.containsKey( value ), value > $v ) \n" + "then \n" + " list.add( $v ); \n" + " System.out.println( \"Marking \" + $v ); \n" + " modify ( $h ) { getMap().put( $v, $b ); } \n" + "end \n" + ""; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( Arrays.asList( 50, 40, 30, 20, 10 ), list ); } @Test public void testExistsOr() { // DROOLS-254 String drl = "package org.drools.test;\n" + "\n" + "global java.util.List list;\n" + "\n" + "declare Foo val : String end \n" + "" + "rule Init when $s : String() then delete( $s ); insert( new Foo( $s ) ); end \n" + "" + "rule \"Check Pos\"\n" + "when\n" + " exists ( Foo( val == \"1\" ) or Foo( val == \"2\" ) )\n" + "then\n" + " list.add( \"+\" );\n" + "end\n" + "\n" + "rule \"Check Neg\"\n" + "when\n" + " not ( not Foo( val == \"1\" ) and not Foo( val == \"2\" ) )\n" + "then\n" + " list.add( \"-\" );\n" + "end\n" + "\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.insert( "2" ); ksession.insert( "3" ); ksession.insert( "1" ); ksession.insert( "4" ); ksession.insert( "5" ); ksession.insert( "7" ); ksession.fireAllRules(); ksession.insert( "1" ); ksession.insert( "5" ); ksession.insert( "7" ); ksession.fireAllRules(); ksession.insert( "6" ); ksession.insert( "2" ); ksession.insert( "2" ); ksession.fireAllRules(); System.out.println( list ); assertEquals( 11, ksession.getObjects().size() ); assertEquals( 2, list.size() ); assertTrue( list.contains( "+" ) ); assertTrue( list.contains( "-" ) ); } @Test public void testFactLeak() throws InterruptedException { //DROOLS-131 String drl = "package org.drools.test; \n" + "global java.util.List list; \n" + "" + "" + "rule Intx when\n" + " $x : Integer() from entry-point \"x\" \n" + "then\n" + " list.add( $x ); \n" + "end"; int N = 1100; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); final StatefulKnowledgeSession ks = kb.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); ks.setGlobal( "list", list ); new Thread() { public void run() { ks.fireUntilHalt(); } }.start(); for ( int j = 0; j < N; j++ ) { ks.getEntryPoint( "x" ).insert( new Integer( j ) ); } Thread.sleep( 1000 ); ks.halt(); assertEquals( N, list.size() ); } @Test public void testFactStealing() throws Exception { String drl = "package org.drools.test; \n" + "import org.drools.compiler.Person; \n " + "global java.util.List list; \n" + "\n" + "\n" + "rule Sleep \n " + "salience 1000 \n" + "when then \n" + " System.out.println( Thread.currentThread().getName() + \"Zlip\" ); \n" + " Thread.sleep( 100 ); \n" + "end \n" + "" + "rule FireAtWill\n" + "when \n" + " $p : Person( $n : name ) \n" + "then \n" + " System.out.println( Thread.currentThread().getName() + \" Ill continue later \" ); \n" + " Thread.sleep( 100 ); \n" + " System.out.println( Thread.currentThread().getName() + \" Hello >> \" + $n );\n" + " list.add( $n ); \n" + "end\n" + "\n" + "rule ImDone\n" + "timer( expr:0 )\n" + "when\n" + " $p : Person()\n" + "then\n" + " System.out.println( Thread.currentThread().getName() + \"Take out \" + $p ); \n" + " delete( $p );\n" + " System.out.println( Thread.currentThread().getName() + \"Taken out \" + $p ); \n" + " if ( list.isEmpty() ) { list.add( $p.getName() ); } \n" + "end\n" + "\n"; KnowledgeBuilder knowledgeBuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); knowledgeBuilder.add( new ByteArrayResource( drl.getBytes() ), ResourceType.DRL ); if ( knowledgeBuilder.hasErrors() ) { fail( knowledgeBuilder.getErrors().toString() ); } KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( knowledgeBuilder.getKnowledgePackages() ); StatefulKnowledgeSession knowledgeSession = kbase.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); knowledgeSession.setGlobal( "list", list ); knowledgeSession.insert( new Person( "mark", 67 ) ); knowledgeSession.fireAllRules(); Thread.sleep( 500 ); assertEquals( 1, list.size() ); assertTrue( list.contains( "mark" ) ); } public static class SQLTimestamped { private Timestamp start; public Timestamp getStart() { return start; } public void setStart( Timestamp start ) { this.start = start; } public SQLTimestamped() { start = new Timestamp( new Date().getTime() ); } } @Test public void testEventWithSQLTimestamp() throws InterruptedException { // DROOLS-10 String str = "import org.drools.compiler.integrationtests.Misc2Test.SQLTimestamped;\n" + "" + "global java.util.List list;" + "\n" + "declare SQLTimestamped @role(event) @timestamp(start) end \n" + "" + "rule \"Init\" when\n" + " $s1 : SQLTimestamped() \n" + " $s2 : SQLTimestamped( this != $s1, this after $s1 ) \n" + "then\n" + " list.add( \"ok\" ); \n" + "end\n" + ""; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ArrayList list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.insert( new SQLTimestamped() ); Thread.sleep( 100 ); ksession.insert( new SQLTimestamped() ); ksession.fireAllRules(); assertEquals( Arrays.asList( "ok" ), list ); } public static class Foo3 { public boolean getX() { return true; } public String isX() { return "x"; } public boolean isY() { return true; } public String getZ() { return "ok"; } public boolean isZ() { return true; } } @Test public void testIsGetClash() { // DROOLS-18 String str = "import org.drools.compiler.integrationtests.Misc2Test.Foo3;\n" + "" + "global java.util.List list;" + "\n" + "" + "rule \"Init\" when\n" + " $x : Foo3( x == true, y == true, z == \"ok\", isZ() == true ) \n" + "then\n" + " list.add( \"ok\" ); \n" + "end\n" + ""; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); if ( kbuilder.hasErrors() ) { fail( kbuilder.getErrors().toString() ); } assertEquals( 2, kbuilder.getResults( ResultSeverity.WARNING ).size() ); for ( KnowledgeBuilderResult res : kbuilder.getResults( ResultSeverity.WARNING ) ) { System.out.println( res.getMessage() ); } } @Test public void testCollectAccumulate() { // DROOLS-173 String drl = "import java.util.ArrayList\n" + "\n" + "global java.util.Map map; \n" + "" + " declare Item\n" + " code: int\n" + " price: int\n" + " present: boolean\n" + " end\n" + "\n" + " rule \"Init\"\n" + " when\n" + " then\n" + " insert(new Item(1,40,false));\n" + " insert(new Item(2,40,false));\n" + " insert(new Item(3,40,false));\n" + " insert(new Item(4,40,false));\n" + " end\n" + "\n" + " rule \"CollectAndAccumulateRule\"\n" + " when\n" + " //At least two items that aren't presents\n" + " objList: ArrayList(size>=2) from collect( Item(present==false))\n" + " //Total price bigger than 100\n" + " price: Number(intValue>=100) from accumulate( Item($w:price, present==false), sum($w))\n" + " then\n" + "\n" + " System.out.println(\"Sum: \"+price);\n" + " System.out.println(\"Items size: \"+objList.size());\n" + " " + " map.put( objList.size(), price ); \n" + " \n" + " //Look for the minor price item\n" + " Item min = null;\n" + " for(Object obj: objList){\n" + " if (min!=null){\n" + " min = (min.getPrice()>((Item)obj).getPrice())?(Item)obj:min;\n" + " }\n" + " else {\n" + " min = (Item)obj;\n" + " }\n" + " }\n" + " \n" + " //And make it a present\n" + " if (min!=null){\n" + " modify(min){setPresent(true)};\n" + " }\n" + " end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Map map = new HashMap(); ksession.setGlobal( "map", map ); ksession.fireAllRules(); assertEquals( 2, map.size() ); assertEquals( 160, map.get( 4 ) ); assertEquals( 120, map.get( 3 ) ); } public static interface TradeBooking { public TradeHeader getTrade(); } public static interface TradeHeader { public void setAction( String s ); public String getAction(); } public static class TradeHeaderImpl implements TradeHeader { private String action; public String getAction() { return action; } public void setAction( String action ) { this.action = action; } @Override public boolean equals( Object o ) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; TradeHeaderImpl that = (TradeHeaderImpl) o; if ( action != null ? !action.equals( that.action ) : that.action != null ) return false; return true; } @Override public int hashCode() { return action != null ? action.hashCode() : 0; } } public static class TradeBookingImpl implements TradeBooking { private TradeHeader header; public TradeBookingImpl( TradeHeader h ) { this.header = h; } public TradeHeader getTrade() { return header; } @Override public boolean equals( Object o ) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; TradeBookingImpl that = (TradeBookingImpl) o; if ( header != null ? !header.equals( that.header ) : that.header != null ) return false; return true; } @Override public int hashCode() { return header != null ? header.hashCode() : 0; } } @Test public void testLockOnActive1() { // the modify changes the hashcode of TradeHeader // this forces the 'from' to think it's new. This results in an insert and a delete propagation from the 'from' // With Property Reactivity enabled by default this also required adding a @watch(*) annotation String drl = "" + "package org.drools.test; \n" + "import org.drools.compiler.integrationtests.Misc2Test.TradeBooking;\n" + "import org.drools.compiler.integrationtests.Misc2Test.TradeHeader;\n" + "rule \"Rule1\" \n" + "salience 1 \n" + "when\n" + " $booking: TradeBooking() @watch(*) \n" + " $trade: TradeHeader() from $booking.getTrade()\n" + " not String()\n" + "then\n" + " $trade.setAction(\"New\");\n" + " modify($booking) {}\n" + " insert (\"run\");\n" + "end;\n" + "\n" + "rule \"Rule2\"\n" + "lock-on-active true\n" + "when\n" + " $booking: TradeBooking( ) @watch(*) \n" + " $trade: Object( ) from $booking.getTrade()\n" + "then\n" + "end"; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ks = kb.newStatefulKnowledgeSession(); ReteDumper.dumpRete(kb); final List created = new ArrayList(); final List cancelled = new ArrayList(); final List fired = new ArrayList(); ks.addEventListener( new DefaultAgendaEventListener() { public void matchCreated( MatchCreatedEvent event ) { created.add( event.getMatch().getRule().getName() ); } public void matchCancelled( MatchCancelledEvent event ) { cancelled.add( event.getMatch().getRule().getName() ); } public void afterMatchFired( AfterMatchFiredEvent event ) { fired.add( event.getMatch().getRule().getName() ); } } ); ks.fireAllRules(); TradeBooking tb = new TradeBookingImpl( new TradeHeaderImpl() ); ks.insert( tb ); assertEquals( 1, ks.fireAllRules() ); assertEquals( 3, created.size() ); assertEquals( 2, cancelled.size() ); assertEquals( 1, fired.size() ); assertEquals( "Rule2", created.get( 0 ) ); assertEquals( "Rule1", created.get( 1 ) ); assertEquals( "Rule2", created.get( 2 ) ); assertEquals( "Rule2", cancelled.get( 0 ) ); assertEquals( "Rule2", cancelled.get( 1 ) ); assertEquals( "Rule1", fired.get( 0 ) ); } @Test public void testLockOnActive2() { // the modify changes the hashcode of TradeHeader // this forces the 'from' to think it's new. This results in an insert and a delete propagation from the 'from' // With Property Reactivity enabled by default this also required adding a @watch(*) annotation String drl = "" + "package org.drools.test; \n" + "import org.drools.compiler.integrationtests.Misc2Test.TradeBooking;\n" + "import org.drools.compiler.integrationtests.Misc2Test.TradeHeader;\n" + "rule \"Rule1\" \n" + "lock-on-active true\n" + "salience 1 \n" + "when\n" + " $booking: TradeBooking() @watch(*) \n" + " $trade: TradeHeader() from $booking.getTrade()\n" + "then\n" + " $trade.setAction(\"New\");\n" + " modify($booking) {}\n" + "end;\n" + "\n" + "rule \"Rule2\"\n" + "when\n" + " $booking: TradeBooking( ) @watch(*) \n" + " $trade: Object( ) from $booking.getTrade()\n" + "then\n" + "end"; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ks = kb.newStatefulKnowledgeSession(); final List created = new ArrayList(); final List cancelled = new ArrayList(); final List fired = new ArrayList(); ks.addEventListener( new DefaultAgendaEventListener() { public void matchCreated( MatchCreatedEvent event ) { created.add( event.getMatch().getRule().getName() ); } public void matchCancelled( MatchCancelledEvent event ) { cancelled.add( event.getMatch().getRule().getName() ); } public void afterMatchFired( AfterMatchFiredEvent event ) { fired.add( event.getMatch().getRule().getName() ); } } ); ks.fireAllRules(); TradeBooking tb = new TradeBookingImpl( new TradeHeaderImpl() ); ks.insert( tb ); assertEquals( 2, ks.fireAllRules() ); assertEquals( 3, created.size() ); assertEquals( 1, cancelled.size() ); assertEquals( 2, fired.size() ); assertEquals( "Rule1", created.get( 0 ) ); assertEquals( "Rule1", created.get( 1 ) ); assertEquals( "Rule2", created.get( 2 ) ); assertEquals( "Rule1", cancelled.get( 0 ) ); assertEquals( "Rule1", fired.get( 0 ) ); assertEquals( "Rule2", fired.get( 1 ) ); } @Test public void testLockOnActiveWithModify() { String drl = "" + "package org.drools.test; \n" + "import org.drools.compiler.Person; \n" + "" + "rule \"Rule1\" \n" + "@Propagation(EAGER) \n" + "salience 1 \n" + "lock-on-active true\n" + "when\n" + " $p: Person()\n" + "then\n" + " System.out.println( \"Rule1\" ); \n" + " modify( $p ) { setAge( 44 ); }\n" + "end;\n" + "\n" + "rule \"Rule2\"\n" + "@Propagation(EAGER) \n" + "lock-on-active true\n" + "when\n" + " $p: Person() \n" + " String() from $p.getName() \n" + "then\n" + " System.out.println( \"Rule2\" + $p ); " + " modify ( $p ) { setName( \"john\" ); } \n" + "end"; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ks = kb.newStatefulKnowledgeSession(); ks.addEventListener( new DebugAgendaEventListener() ); ks.fireAllRules(); Person p = new Person( "mark", 76 ); ks.insert( p ); ks.fireAllRules(); assertEquals( 44, p.getAge() ); assertEquals( "john", p.getName() ); } @Test public void testLockOnActiveWithModifyNoEager() { // DROOLS-280 String drl = "" + "package org.drools.test; \n" + "import org.drools.compiler.Person; \n" + "" + "rule \"Rule1\" \n" + "salience 1 \n" + "lock-on-active true\n" + "when\n" + " $p: Person()\n" + "then\n" + " System.out.println( \"Rule1\" ); \n" + " modify( $p ) { setAge( 44 ); }\n" + "end;\n" + "\n" + "rule \"Rule2\"\n" + "lock-on-active true\n" + "when\n" + " $p: Person() \n" + " String() from $p.getName() \n" + "then\n" + " System.out.println( \"Rule2\" + $p ); " + " modify ( $p ) { setName( \"john\" ); } \n" + "end"; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ks = kb.newStatefulKnowledgeSession(); ks.addEventListener( new DebugAgendaEventListener() ); ks.fireAllRules(); Person p = new Person( "mark", 76 ); ks.insert( p ); ks.fireAllRules(); assertEquals( 44, p.getAge() ); assertEquals( "john", p.getName() ); } @Test public void testPrimitiveGlobals() { String drl = "package org.drools.compiler.integrationtests\n" + "\n" + "global int foo;\n" + "\n" + ""; KnowledgeBuilder kb = KnowledgeBuilderFactory.newKnowledgeBuilder(); kb.add( new ByteArrayResource( drl.getBytes() ), ResourceType.DRL ); System.out.println( kb.getErrors() ); assertTrue( kb.hasErrors() ); } @Test public void testClashingRules() { //DROOLS-287 String drl = "package org.drools.test; \n" + "" + "rule \"Rule_>_all\"" + "when then end \n" + "" + "rule \"Rule_<_all\"" + "when then end \n" + ""; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); } @Test public void testDontFailOnDuplicatedRuleWithDeclaredTypeError() { String rule1 = "rule \"Some Rule\"\n" + "when\n" + " $s: String()\n" + "then\n" + "end"; String rule2 = "declare DClass\n" + " prop : String\n" + "end\n" + "rule \"Some Rule\"\n" + "when\n" + " $d: DClass()\n" + "then\n" + "end"; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( rule1.getBytes() ), ResourceType.DRL ); kbuilder.add( ResourceFactory.newByteArrayResource( rule2.getBytes() ), ResourceType.DRL ); //the default behavior of kbuilder is not to fail because of duplicated //rules. if ( kbuilder.hasErrors() ) { fail( kbuilder.getErrors().toString() ); } //We must have 1 INFO result. KnowledgeBuilderResults infos = kbuilder.getResults( ResultSeverity.INFO ); Assert.assertNotNull( infos ); Assert.assertEquals( 1, infos.size() ); } @Test public void testBindingComplexExpression() { // DROOLS-43 String drl = "package org.drools.test;\n" + "\n" + "global java.util.List list;\n" + "\n" + "declare Foo \n" + " a : int \n" + " b : int \n" + "end \n" + "" + "rule Init when then insert( new Foo( 3, 4 ) ); end \n" + "" + "rule \"Expr\"\n" + "when\n" + " $c := Integer() from new Integer( 4 ) \n" + " Foo( $a : a + b == 7 && a == 3 && $b : b > 0, $c := b - a == 1 ) \n" + "then\n" + " list.add( $a );\n" + " list.add( $b );\n" + " list.add( $c );\n" + "end\n" + "\n"; KnowledgeBuilderConfiguration kbConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); kbConf.setOption( LanguageLevelOption.DRL6 ); KnowledgeBase kbase = loadKnowledgeBaseFromString( kbConf, drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertTrue( !list.isEmpty() ); assertEquals( 3, list.size() ); assertEquals( 3, list.get( 0 ) ); assertEquals( 4, list.get( 1 ) ); assertEquals( 4, list.get( 2 ) ); } @Test public void testBindingComplexExpressionWithDRL5() { // DROOLS-43 String drl = "package org.drools.test;\n" + "\n" + "global java.util.List list;\n" + "\n" + "declare Foo \n" + " a : int \n" + " b : int \n" + "end \n" + "" + "rule Init when then insert( new Foo( 3, 4 ) ); end \n" + "" + "rule \"Expr\"\n" + "when\n" + " $c := Integer() from new Integer( 4 ) \n" + " Foo( $a : a + b == 7 && a == 3 && $b : b > 0, $c := b - a == 1 ) \n" + "then\n" + " list.add( $a );\n" + " list.add( $b );\n" + " list.add( $c );\n" + "end\n" + "\n"; KnowledgeBuilderConfiguration kbConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); kbConf.setOption( LanguageLevelOption.DRL5 ); KnowledgeBase kbase = loadKnowledgeBaseFromString( kbConf, drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertTrue( !list.isEmpty() ); assertEquals( 3, list.size() ); assertEquals( 3, list.get( 0 ) ); assertEquals( 4, list.get( 1 ) ); assertEquals( 4, list.get( 2 ) ); } @Test public void testEvalConstraintWithMvelOperator() { String drl = "rule \"yeah\" " + "\tdialect \"mvel\"\n when " + "Foo( eval( field soundslike \"water\" ) )" + " then " + "end"; DrlParser drlParser = new DrlParser(); PackageDescr packageDescr; try { packageDescr = drlParser.parse( true, drl ); } catch (DroolsParserException e) { throw new RuntimeException( e ); } RuleDescr r = packageDescr.getRules().get( 0 ); PatternDescr pd = (PatternDescr) r.getLhs().getDescrs().get( 0 ); assertEquals( 1, pd.getConstraint().getDescrs().size() ); } @Test public void testManyAccumulatesWithSubnetworks() { String drl = "package org.drools.compiler.tests; \n" + "" + "declare FunctionResult\n" + " father : Applied\n" + "end\n" + "\n" + "declare Field\n" + " applied : Applied\n" + "end\n" + "\n" + "declare Applied\n" + "end\n" + "\n" + "\n" + "rule \"Seed\"\n" + "when\n" + "then\n" + " Applied app = new Applied();\n" + " Field fld = new Field();\n" + "\n" + " insert( app );\n" + " insert( fld );\n" + "end\n" + "\n" + "\n" + "\n" + "\n" + "rule \"complexSubNetworks\"\n" + "when\n" + " $fld : Field( $app : applied )\n" + " $a : Applied( this == $app )\n" + " accumulate (\n" + " $res : FunctionResult( father == $a ),\n" + " $args : collectList( $res )\n" + " )\n" + " accumulate (\n" + " $res : FunctionResult( father == $a ),\n" + " $deps : collectList( $res )\n" + " )\n" + " accumulate (\n" + " $x : String()\n" + " and\n" + " not String( this == $x ),\n" + " $exprFieldList : collectList( $x )\n" + " )\n" + "then\n" + "end\n" + "\n"; KnowledgeBuilderConfiguration kbConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); KnowledgeBase kbase = loadKnowledgeBaseFromString( kbConf, drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); int num = ksession.fireAllRules(); // only one rule should fire, but the partial propagation of the asserted facts should not cause a runtime NPE assertEquals( 1, num ); } @Test public void testLinkRiaNodesWithSubSubNetworks() { String drl = "package org.drools.compiler.tests; \n" + "" + "import java.util.*; \n" + "" + "global List list; \n" + "" + "declare MyNode\n" + "end\n" + "" + "rule Init\n" + "when\n" + "then\n" + " insert( new MyNode() );\n" + " insert( new MyNode() );\n" + "end\n" + "" + "" + "rule \"Init tree nodes\"\n" + "salience -10\n" + "when\n" + " accumulate (\n" + " MyNode(),\n" + " $x : count( 1 )\n" + " )\n" + " accumulate (\n" + " $n : MyNode()\n" + " and\n" + " accumulate (\n" + " $val : Double( ) from Arrays.asList( 1.0, 2.0, 3.0 ),\n" + " $rc : count( $val );\n" + " $rc == 3 \n" + " ),\n" + " $y : count( $n )\n" + " )\n" + "then\n" + " list.add( $x ); \n" + " list.add( $y ); \n" + " System.out.println( $x ); \n" + " System.out.println( $y ); \n" + "end\n"; KnowledgeBuilderConfiguration kbConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); KnowledgeBase kbase = loadKnowledgeBaseFromString( kbConf, drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Long> list = new ArrayList<Long>(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 2, list.size() ); assertEquals( 2, list.get( 0 ).intValue() ); assertEquals( 2, list.get( 1 ).intValue() ); } @Test public void testDynamicSalienceUpdate() { String drl = "package org.drools.compiler.tests; \n" + "" + "import java.util.*; \n" + "" + "global List list; \n" + "" + "declare Foo value : long end \n" + "" + "rule Nop \n" + " salience( $l ) \n" + "when\n" + " Foo( $l : value ) \n" + "then\n" + " System.out.println( \"Never Foo \" + $l ); " + " list.add( $l ); \n" + "end\n" + "" + "rule Insert \n" + " salience 100 \n" + "when \n" + " $l : Long() \n" + "then \n" + " System.out.println( \"Insert Foo \" + $l ); " + " insertLogical( new Foo( $l ) ); \n" + "end \n" + "" + "rule Clean \n" + " salience 50 \n" + "when \n" + " $s : String() \n" + " $l : Long() \n" + "then \n" + " System.out.println( \"delete \" + $l ); " + " delete( $l ); \n" + "end \n"; KnowledgeBuilderConfiguration kbConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); KnowledgeBase kbase = loadKnowledgeBaseFromString( kbConf, drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.insert( 1L ); ksession.insert( 2L ); ksession.insert( "go" ); ksession.fireAllRules(); assertTrue( list.isEmpty() ); ksession.dispose(); } @Test public void testInitialFactLeaking() { // DROOLS-239 String drl = "global java.util.List list;\n" + "rule R when\n" + " $o : Object()\n" + "then\n" + " list.add(1);\n" + "end\n"; KnowledgeBuilderConfiguration kbConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); KnowledgeBase kbase = loadKnowledgeBaseFromString( kbConf, drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 0, list.size() ); ksession.insert( "1" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); ksession.insert( 1 ); ksession.fireAllRules(); assertEquals( 2, list.size() ); ksession.dispose(); } @Test public void testNoLoopWithNamedConsequences() { // DROOLS-327 String drl = "import org.drools.compiler.Message\n" + "rule \"Hello World\" no-loop\n" + " when\n" + " m : Message( myMessage : message )\n" + " if (status == 0) do[sayHello]\n" + " then\n" + " System.out.println( myMessage );\n" + " m.setMessage( \"Goodbye cruel world\" );\n" + " m.setStatus( Message.GOODBYE );\n" + " update( m );\n" + " then[sayHello]\n" + " System.out.println(\"Hello, I'm here!\");\n" + "end\n"; KnowledgeBuilderConfiguration kbConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(); KnowledgeBase kbase = loadKnowledgeBaseFromString( kbConf, drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new Message( "Hello World" ) ); ksession.fireAllRules(); } @Test public void testInsertModifyInteractionsWithLockOnActive() { String drl = "package org.drools.compiler.integrationtests;\n" + "import org.drools.compiler.Message;\n" + "global Message m2;\n" + "rule r1 lock-on-active\n" + " when\n" + " m: Message()\n" + " then\n" + " modify( m ){ setMessage2( 'msg2' ) };\n" + " m2 = new Message( 'msg1' );\n" + " kcontext.getKnowledgeRuntime().setGlobal( 'm2', m2 ); \n" + " insert( m2 );\n" + "end\n" + "rule r2 lock-on-active salience 1000\n" + " when\n" + " m : Message()\n" + " then\n" + " modify( m ){ setMessage3( 'msg3' ) };\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Message m1 = new Message( "msg1" ); ksession.insert( m1 ); assertEquals( 2, ksession.fireAllRules() ); Message m2 = (Message) ksession.getGlobal( "m2" ); assertEquals( "msg1", m1.getMessage() ); assertEquals( "msg2", m1.getMessage2() ); assertEquals( "msg3", m1.getMessage3() ); assertEquals( "msg1", m2.getMessage() ); assertEquals( "Two", m2.getMessage2() ); // r1 does not fire for m2 assertEquals( "Three", m2.getMessage3() ); } @Test(timeout = 10000) public void testWumpus1() { String drl = "import org.drools.compiler.integrationtests.Misc2Test.Hero;\n" + "import org.drools.compiler.integrationtests.Misc2Test.StepForwardCommand;\n" + "global java.util.List list; \n " + "\n" + "\n" + "rule StepLeft when\n" + " $h : Hero( goingRight == false )\n" + " $sc : StepForwardCommand()\n" + "then\n" + " modify ( $h ) { setPos( $h.getPos()-1 ) };\n" + " list.add( 'StepLeft' );\n" + "end\n" + "\n" + "rule StepRight when\n" + " $h : Hero( goingRight == true )\n" + " $sc : StepForwardCommand()\n" + "then\n" + " modify ( $h ) { setPos( $h.getPos()+1 ) };\n" + " list.add( 'StepRight' );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); Hero hero = new Hero( 1 ); ksession.insert( hero ); ksession.fireAllRules(); ksession.insert( new StepForwardCommand() ); assertEquals( 1, ksession.fireAllRules() ); assertEquals( 2, hero.getPos() ); } @Test(timeout = 10000) public void testWumpus2() { String drl = "import org.drools.compiler.integrationtests.Misc2Test.Hero;\n" + "import org.drools.compiler.integrationtests.Misc2Test.StepForwardCommand;\n" + "import org.drools.compiler.integrationtests.Misc2Test.ChangeDirectionCommand;\n" + "global java.util.List list; \n " + "\n" + "\n" + "rule StepLeft when\n" + " $sc : StepForwardCommand()\n" + " $h : Hero( goingRight == false )\n" + "then\n" + " modify ( $h ) { setPos( $h.getPos()-1 ) };\n" + " list.add( 'StepLeft' );\n" + "end\n" + "\n" + "rule StepRight when\n" + " $sc : StepForwardCommand()\n" + " $h : Hero( goingRight == true )\n" + "then\n" + " modify ( $h ) { setPos( $h.getPos()+1 ) };\n" + " list.add( 'StepRight' );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); Hero hero = new Hero( 1 ); ksession.insert( hero ); ksession.fireAllRules(); ksession.insert( new StepForwardCommand() ); assertEquals( 1, ksession.fireAllRules() ); assertEquals( 2, hero.getPos() ); } @Test(timeout = 10000) public void testWumpus3() { String drl = "import org.drools.compiler.integrationtests.Misc2Test.Hero;\n" + "import org.drools.compiler.integrationtests.Misc2Test.StepForwardCommand;\n" + "import org.drools.compiler.integrationtests.Misc2Test.ChangeDirectionCommand;\n" + "global java.util.List list; \n " + "\n" + "rule RotateLeft when\n" + " $h : Hero( goingRight == true )\n" + " $dc : ChangeDirectionCommand()\n" + "then\n" + " retract ( $dc ); \n" + " modify ( $h ) { setGoingRight( false ) };\n" + " list.add( 'RotateLeft' );\n" + "end\n" + "\n" + "\n" + "rule StepLeft when\n" + " $h : Hero( goingRight == false )\n" + " $sc : StepForwardCommand()\n" + "then\n" + " retract ( $sc ); \n" + " modify ( $h ) { setPos( $h.getPos()-1 ) };\n" + " list.add( 'StepLeft' );\n" + "end\n" + "\n" + "rule StepRight when\n" + " $h : Hero( goingRight == true )\n" + " $sc : StepForwardCommand()\n" + "then\n" + " retract ( $sc );\n" + " modify ( $h ) { setPos( $h.getPos()+1 ) };\n" + " list.add( 'StepRight' );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); Hero hero = new Hero( 1 ); ksession.insert( hero ); ksession.fireAllRules(); ksession.insert( new StepForwardCommand() ); ksession.fireAllRules(); assertEquals( 2, hero.getPos() ); ksession.insert( new ChangeDirectionCommand() ); ksession.fireAllRules(); ksession.insert( new StepForwardCommand() ); ksession.fireAllRules(); assertEquals( 1, hero.getPos() ); } @Test(timeout = 10000) public void testWumpus4() { String drl = "import org.drools.compiler.integrationtests.Misc2Test.Hero;\n" + "import org.drools.compiler.integrationtests.Misc2Test.StepForwardCommand;\n" + "import org.drools.compiler.integrationtests.Misc2Test.ChangeDirectionCommand;\n" + "global java.util.List list; \n " + "\n" + "rule RotateLeft when\n" + " $dc : ChangeDirectionCommand()\n" + " $h : Hero( goingRight == true )\n" + "then\n" + " retract ( $dc ); \n" + " modify ( $h ) { setGoingRight( false ) };\n" + " list.add( 'RotateLeft' );\n" + "end\n" + "\n" + "\n" + "rule StepLeft when\n" + " $sc : StepForwardCommand()\n" + " $h : Hero( goingRight == false )\n" + "then\n" + " retract ( $sc ); \n" + " modify ( $h ) { setPos( $h.getPos()-1 ) };\n" + " list.add( 'StepLeft' );\n" + "end\n" + "\n" + "rule StepRight when\n" + " $sc : StepForwardCommand()\n" + " $h : Hero( goingRight == true )\n" + "then\n" + " retract ( $sc );\n" + " modify ( $h ) { setPos( $h.getPos()+1 ) };\n" + " list.add( 'StepRight' );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); Hero hero = new Hero( 1 ); ksession.insert( hero ); ksession.fireAllRules(); ksession.insert( new StepForwardCommand() ); ksession.fireAllRules(); assertEquals( 2, hero.getPos() ); ksession.insert( new ChangeDirectionCommand() ); ksession.fireAllRules(); ksession.insert( new StepForwardCommand() ); ksession.fireAllRules(); assertEquals( 1, hero.getPos() ); } @PropertyReactive public static class Hero { private int pos = 1; private boolean goingRight = true; public Hero( int pos ) { this.pos = pos; } public int getPos() { return pos; } public void setPos( int pos ) { this.pos = pos; } public boolean isGoingRight() { return goingRight; } public void setGoingRight( boolean goingRight ) { this.goingRight = goingRight; } } public static class ChangeDirectionCommand { } public static class StepForwardCommand { } @Test public void testDynamicSalience() { // DROOLS-334 String drl = "import org.drools.compiler.integrationtests.Misc2Test.SimpleMessage\n" + "\n" + "rule R1\n" + " salience ( $index )\n" + " when\n" + " $m : SimpleMessage( status == SimpleMessage.Status.ENRICHED, $index : index)\n" + " Number() from accumulate ( SimpleMessage(), count(1) )\n" + " then\n" + " System.out.println(\"R1: \" + $m);\n" + " modify($m) { setStatus(SimpleMessage.Status.FILTERED) }\n" + "end\n" + "\n" + "rule R2\n" + " salience( -$index )" + " when" + " $m : SimpleMessage( status == SimpleMessage.Status.FILTERED, $index : index)\n" + " then" + " delete( $m );" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); SimpleMessage[] msgs = new SimpleMessage[]{new SimpleMessage( 0 ), new SimpleMessage( 1 ), new SimpleMessage( 2 ), new SimpleMessage( 3 )}; for ( SimpleMessage msg : msgs ) { ksession.insert( msg ); } ksession.fireAllRules(); for ( SimpleMessage msg : msgs ) { assertEquals( SimpleMessage.Status.FILTERED, msg.getStatus() ); } assertEquals( 0, ksession.getFactCount() ); } public static class SimpleMessage { public enum Status {ENRICHED, TO_SEND, SENT, FILTERED} private final int index; private Status status = Status.ENRICHED; public SimpleMessage( int index ) { this.index = index; } public Status getStatus() { return status; } public void setStatus( Status status ) { this.status = status; } public int getIndex() { return index; } @Override public String toString() { return "SimpleMessage(" + index + "): " + status; } } @Test public void testCollectAndAccumulate() { // DROOLS-173 String drl = "import java.util.List\n" + "\n" + "global List list\n" + "\n" + " declare Item\n" + " code: int\n" + " price: int\n" + " present: boolean\n" + " end\n" + "\n" + " rule \"Init\"\n" + " when\n" + " then\n" + " insert(new Item(1,40,false));\n" + " insert(new Item(2,40,false));\n" + " insert(new Item(3,40,false));\n" + " insert(new Item(4,40,false));\n" + " end\n" + "\n" + " rule \"CollectAndAccumulateRule\"\n" + " when\n" + " //At least two items that aren't presents\n" + " objList: List(size>=2) from collect( Item(present==false))\n" + " //Total price bigger than 100\n" + " price: Number(intValue>=100) from accumulate( Item($w:price, present==false), sum($w))\n" + " then\n" + "\n" + " list.add(price);\n" + " list.add(objList.size());\n" + " \n" + " //Look for the minor price item\n" + " Item min = null;\n" + " for(Object obj: objList){\n" + " if (min!=null){\n" + " min = (min.getPrice()>((Item)obj).getPrice())?(Item)obj:min;\n" + " }\n" + " else {\n" + " min = (Item)obj;\n" + " }\n" + " }\n" + " \n" + " //And make it a present\n" + " if (min!=null){\n" + " modify(min){setPresent(true)};\n" + " }\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 4, list.size() ); assertEquals( 160, list.get( 0 ) ); assertEquals( 4, list.get( 1 ) ); assertEquals( 120, list.get( 2 ) ); assertEquals( 3, list.get( 3 ) ); } @Test public void testMatchingEventsInStreamMode() { // DROOLS-338 String drl = "import org.drools.compiler.integrationtests.Misc2Test.SimpleEvent\n" + "declare SimpleEvent\n" + " @role(event)\n" + "end\n" + "\n" + "rule \"RuleA\"\n" + "salience 5\n" + "when\n" + " $f : SimpleEvent( )\n" + "then\n" + " delete ($f);\n" + "end\n" + "\n" + "rule \"RuleB\"\n" + "when\n" + " $f : SimpleEvent( )\n" + "then\n" + "end\n"; KieBaseConfiguration kconf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); kconf.setOption( EventProcessingOption.STREAM ); KnowledgeBase kbase = loadKnowledgeBaseFromString( kconf, drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); final AtomicInteger i = new AtomicInteger( 0 ); ksession.addEventListener( new DefaultAgendaEventListener() { public void matchCreated( MatchCreatedEvent event ) { i.incrementAndGet(); } public void matchCancelled( MatchCancelledEvent event ) { i.decrementAndGet(); } } ); ksession.insert( new SimpleEvent() ); ksession.fireAllRules(); assertEquals( 1, i.get() ); } @Test public void testRuleDoesNotRefireOnNewSession() { // DROOLS-339 String drl = "\n" + "global java.util.List list\n" + "rule \"Insert Info\"\n" + "when\n" + "then\n" + " insert( \"aaa\" );\n" + " insert( new Integer( 12 ) );\n" + " insert( new Double( 4.0 ) );\n" + "end\n" + "\n" + "\n" + "rule \"React\"\n" + "when\n" + " Integer()\n" + " accumulate (\n" + " $n : Double( ) and\n" + " Double( ),\n" + " $x : count( $n )\n" + " )\n" + " String( )\n" + "then\n" + " list.add(\"working\");\n" + "end"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "working", list.get( 0 ) ); ksession.dispose(); ksession = kbase.newStatefulKnowledgeSession(); list.clear(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "working", list.get( 0 ) ); ksession.dispose(); } @Test public void testWildcardImportForTypeField() throws Exception { // DROOLS-348 String drl = "import java.util.*\n" + "declare MyType\n" + " l : List\n" + "end\n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", drl ); ks.newKieBuilder( kfs ).buildAll(); KieSession ksession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); } @Test public void testWildcardImportForTypeFieldOldApi() { // DROOLS-348 String drl = "import java.util.*\n" + "declare MyType\n" + " l : List\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); } @Test public void testTypeCheckInOr() { // BZ-1029911 String str = "import org.drools.compiler.*;\n" + "import java.util.*;\n" + "\n" + "rule \"rule test\"\n" + " dialect \"java\"\n" + " \n" + " when\n" + " scenario: ScenarioType( this == ScenarioType.Set.ADD || this == ScenarioType.Set.EDIT );\n" + " \n" + " then \n" + " System.out.println(\"Test\");\n" + "\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); } @Test public void testDynamicNegativeSalienceWithSpace() { // DROOLS-302 String str = "import org.drools.compiler.Person\n" + "rule R\n" + "salience - $age\n" + "when\n" + " Person( $age : age )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Person p1 = new Person( "A", 31 ); FactHandle fh1 = ksession.insert( p1 ); ksession.fireAllRules(); } @Test public void testJoinNoLoop() { // BZ-1034094 String str = "import org.drools.compiler.Person\n" + "rule R no-loop\n" + "when\n" + " String()\n" + " $p : Person( $age : age )\n" + "then\n" + " modify($p) { setAge( $age + 1 ) }\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Person mario = new Person( "Mario", 38 ); ksession.insert( "a" ); ksession.insert( "b" ); ksession.insert( mario ); ksession.fireAllRules(); assertEquals( 40, mario.getAge() ); } @Test public void testConstraintOnSerializable() { // DROOLS-372 String str = "import org.drools.compiler.integrationtests.Misc2Test.SerializableValue\n" + "rule R\n" + "when\n" + " SerializableValue( value == \"1\" )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.insert( new SerializableValue( "0" ) ); ksession.fireAllRules(); } public static class SerializableValue { private final Serializable value; public SerializableValue( Serializable value ) { this.value = value; } public Serializable getValue() { return value; } } @Test(timeout = 10000) public void testInfiniteLoopUpdatingWithRBTreeIndexing() { // BZ-1040032 String drl = "import org.drools.compiler.Person\n" + "rule R when\n" + " $p : Person()\n" + " exists Person( age > $p.age, name.contains($p.name.substring(0, 1)) )\n" + "then\n" + "end"; KnowledgeBase kb = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ks = kb.newStatefulKnowledgeSession(); Person[] ps = new Person[4]; FactHandle[] fhs = new FactHandle[4]; ps[0] = new Person( "a", 5 ); ps[1] = new Person( "b", 5 ); ps[2] = new Person( "d", 10 ); ps[3] = new Person( "a", 15 ); fhs[0] = ks.insert( ps[0] ); fhs[1] = ks.insert( ps[1] ); fhs[2] = ks.insert( ps[2] ); fhs[3] = ks.insert( ps[3] ); ps[0].setName( "c" ); ks.update( fhs[0], ps[0] ); ks.fireAllRules(); ps[2].setName( "b" ); ks.update( fhs[2], ps[2] ); ks.fireAllRules(); ps[2].setName( "d" ); ks.update( fhs[2], ps[2] ); ks.fireAllRules(); ps[1].setName( "c" ); ks.update( fhs[1], ps[1] ); ks.fireAllRules(); ps[3].setName( "d" ); ks.update( fhs[3], ps[3] ); ks.fireAllRules(); } public static class AA { int id; public AA( int i ) { this.id = i; } public boolean match( Long value ) { return true; } public boolean equals( Object o ) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; AA aa = (AA) o; if ( id != aa.id ) return false; return true; } public int hashCode() { return id; } } public static class BB { public Integer getValue() { return 42; } } @Test @Ignore public void testJitting() { // DROOLS-185 String str = " import org.drools.compiler.integrationtests.Misc2Test.AA; " + " import org.drools.compiler.integrationtests.Misc2Test.BB; " + " global java.util.List list; \n" + " " + " rule R \n " + " when \n" + " BB( $v : value ) \n" + " $a : AA( match( $v ) ) \n" + " then \n" + " list.add( $a ); \n" + " end \n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.insert( new BB() ); for ( int j = 0; j < 100; j++ ) { ksession.insert( new AA( j ) ); ksession.fireAllRules(); } assertEquals( 100, list.size() ); } @Test public void testQueryCorruption() { String drl = "package drl;\n" + "declare Anon " + " cld : String @key " + " sup : String @key " + "end " + "rule Init " + "when " + "then " + " insert( 'aa' ); " + " insert( 'bb' ); " + " insert( 'cc' ); " + " insertLogical( new Anon( 'aa', 'bb' ) ); " + " insertLogical( new Anon( 'cc', 'aa' ) ); " + "end " + "query unravel( String $g, String $c ) " + " ( " + " ( Anon( $g, $c ; ) and $c := String( this.contains( \"b\" ) ) ) " + " or " + " ( Anon( $g, $x ; ) and unravel( $x, $c ; ) ) " + " ) " + "end " + "rule Check " + "when " + " Anon( $e, $par ; ) " + " unravel( $par, $comp ; ) " + " ( Double() or eval( 1 == 1 ) ) " + "then\n" + "end\n" + "rule Mod " + "no-loop " + "when\n" + " $a : Anon( ) " + " ( Double() or eval( 1 == 1 ) ) " + "then " + " modify ( $a ) { } " + "end " + ""; KnowledgeBase kbase = loadKnowledgeBaseFromString( drl ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); } @Test public void testPackagingJarWithTypeDeclarations() throws Exception { // BZ-1054823 String drl1 = "package org.drools.compiler\n" + "import org.drools.compiler.Message\n" + "declare Message\n" + " @role (event)\n" + "end\n" + "rule R1 when\n" + " $m : Message()\n" + "then\n" + "end\n"; KieServices ks = KieServices.Factory.get(); // Create an in-memory jar for version 1.0.0 ReleaseId releaseId = ks.newReleaseId( "org.kie", "test-upgrade", "1.0.0" ); byte[] jar = createKJar( ks, releaseId, null, drl1 ); KieModule km = deployJar( ks, jar ); // Create a session and fire rules KieContainer kc = ks.newKieContainer( km.getReleaseId() ); KieSession ksession = kc.newKieSession(); ksession.insert( new Message( "Hello World" ) ); ksession.fireAllRules(); } @Test public void testStagedTupleLeak() throws Exception { // BZ-1056599 String str = "rule R1 when\n" + " $i : Integer()\n" + "then\n" + " insertLogical( $i.toString() );\n" + "end\n" + "\n" + "rule R2 when\n" + " $i : Integer()\n" + "then\n" + " delete( $i );\n" + "end\n" + "\n" + "rule R3 when\n" + " $l : Long()\n" + " $s : String( this == $l.toString() )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); for ( int i = 0; i < 10; i++ ) { ksession.insert( i ); ksession.fireAllRules(); } Rete rete = ( (KnowledgeBaseImpl) kbase ).getRete(); JoinNode joinNode = null; for ( ObjectTypeNode otn : rete.getObjectTypeNodes() ) { if ( String.class == otn.getObjectType().getValueType().getClassType() ) { joinNode = (JoinNode) otn.getObjectSinkPropagator().getSinks()[0]; break; } } assertNotNull( joinNode ); InternalWorkingMemory wm = (InternalWorkingMemory) ksession; BetaMemory memory = (BetaMemory) wm.getNodeMemory( joinNode ); TupleSets<RightTuple> stagedRightTuples = memory.getStagedRightTuples(); assertNull( stagedRightTuples.getDeleteFirst() ); assertNull( stagedRightTuples.getInsertFirst() ); } @Test public void testJittingConstraintWithArrayParams() throws Exception { // BZ-1057000 String str = "import org.drools.compiler.integrationtests.Misc2Test.Strings\n" + "\n" + "global java.util.List allList;\n" + "global java.util.List anyList;\n" + "\n" + "rule R_all when\n" + " Strings( containsAll(\"1\", \"2\") )\n" + "then\n" + " allList.add(\"1\");\n" + "end\n" + "\n" + "rule R_any when\n" + " Strings( containsAny(new String[] {\"1\", \"2\"}) )\n" + "then\n" + " anyList.add(\"1\");\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<String> allList = new ArrayList<String>(); ksession.setGlobal( "allList", allList ); List<String> anyList = new ArrayList<String>(); ksession.setGlobal( "anyList", anyList ); ksession.insert( new Strings( "1", "2", "3" ) ); ksession.insert( new Strings( "2", "3" ) ); ksession.fireAllRules(); assertEquals( 1, allList.size() ); assertEquals( 2, anyList.size() ); } public static class Strings { private final String[] strings; public Strings( String... strings ) { this.strings = strings; } public boolean containsAny( String[] array ) { for ( String candidate : array ) { for ( String s : strings ) { if ( candidate.equals( s ) ) { return true; } } } return false; } public boolean containsAll( String... array ) { int counter = 0; for ( String candidate : array ) { for ( String s : strings ) { if ( candidate.equals( s ) ) { counter++; break; } } } return counter == array.length; } } public static class ARef { public static int getSize( String s ) { return 0; } } public static class BRef extends ARef { public static int getSize( String s ) { return s.length(); } } @Test public void testJittingConstraintInvokingStaticMethod() throws Exception { // DROOLS-410 String str = "dialect \"mvel\"\n" + "import org.drools.compiler.integrationtests.Misc2Test.ARef\n" + "import org.drools.compiler.integrationtests.Misc2Test.BRef\n" + "\n" + "global java.util.List list;\n" + "\n" + "rule R when\n" + " $s : String( length == BRef.getSize(this) )\n" + "then\n" + " list.add($s);\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( "1234" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); } @Test public void testStagedLeftTupleLeak() throws Exception { // BZ-1058874 String str = "rule R1 when\n" + " String( this == \"this\" )\n" + " String( this == \"that\" )\n" + "then\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); for ( int i = 0; i < 10; i++ ) { FactHandle fh = ksession.insert( "this" ); ksession.fireAllRules(); ksession.delete( fh ); ksession.fireAllRules(); } Rete rete = ( (KnowledgeBaseImpl) kbase ).getRete(); LeftInputAdapterNode liaNode = null; for ( ObjectTypeNode otn : rete.getObjectTypeNodes() ) { if ( String.class == otn.getObjectType().getValueType().getClassType() ) { AlphaNode alphaNode = (AlphaNode) otn.getObjectSinkPropagator().getSinks()[0]; liaNode = (LeftInputAdapterNode) alphaNode.getObjectSinkPropagator().getSinks()[0]; break; } } assertNotNull( liaNode ); InternalWorkingMemory wm = (InternalWorkingMemory) ksession; LeftInputAdapterNode.LiaNodeMemory memory = (LeftInputAdapterNode.LiaNodeMemory) wm.getNodeMemory( liaNode ); TupleSets<LeftTuple> stagedLeftTuples = memory.getSegmentMemory().getStagedLeftTuples(); assertNull( stagedLeftTuples.getDeleteFirst() ); assertNull( stagedLeftTuples.getInsertFirst() ); } public static class EvallerBean { private final Evaller evaller = new Evaller( 1 ); public Evaller getEvaller() { return evaller; } } public static class Evaller { private final int size; public Evaller() { this( 0 ); } public Evaller( int size ) { this.size = size; } public boolean check( Object o ) { return true; } public static boolean checkStatic( Object o ) { return true; } public int size() { return size; } public int getSize() { return size; } } @Test public void testGlobalInConstraint() throws Exception { String str = "global " + Evaller.class.getCanonicalName() + " evaller;\n" + "global java.util.List list;\n" + "declare Foo end\n" + "rule Init when then insert( new Foo() ); end\n" + "rule R1 when\n" + " $s : Foo( evaller.check( this ) == true )\n" + "then\n" + " list.add( 42 );\n" + "end\n" + "rule R2 when\n" + " $s : Foo( evaller.check( this ) == false )\n" + "then\n" + " list.add( 43 );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.setGlobal( "evaller", new Evaller() ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 42, (int) list.get( 0 ) ); } @Test public void testStaticInConstraint() throws Exception { String str = "import " + Evaller.class.getCanonicalName() + ";\n" + "global java.util.List list;\n" + "declare Foo end\n" + "rule Init when then insert( new Foo() ); end\n" + "rule R1 when\n" + " $s : Foo( Evaller.checkStatic( this ) == true )\n" + "then\n" + " list.add( 42 );\n" + "end\n" + "rule R2 when\n" + " $s : Foo( Evaller.checkStatic( this ) == false )\n" + "then\n" + " list.add( 43 );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 42, (int) list.get( 0 ) ); } @Test public void testFieldPrecedenceOverGlobal() throws Exception { String str = "import " + EvallerBean.class.getCanonicalName() + ";\n" + "global " + Evaller.class.getCanonicalName() + " evaller;\n" + "global java.util.List list;\n" + "rule R1 when\n" + " $s : EvallerBean( evaller.size() == 1 )\n" + "then\n" + " list.add( 42 );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.setGlobal( "evaller", new Evaller() ); ksession.insert( new EvallerBean() ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 42, (int) list.get( 0 ) ); } @Test public void testFieldPrecedenceOverDeclaration() throws Exception { String str = "import " + Evaller.class.getCanonicalName() + ";\n" + "import " + EvallerBean.class.getCanonicalName() + ";\n" + "global java.util.List list;\n" + "rule R1 when\n" + " evaller : Evaller()\n" + " $s : EvallerBean( evaller.size() == 1 )\n" + "then\n" + " list.add( 42 );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.insert( new Evaller() ); ksession.insert( new EvallerBean() ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 42, (int) list.get( 0 ) ); } @Test public void testContainsOnString() { // DROOLS-388 String str = "global java.util.List list;\n" + "rule R1 when\n" + " $s : String( this contains 'bcd' )\n" + "then\n" + " list.add( $s );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.insert( "abcde" ); ksession.insert( "bcdef" ); ksession.insert( "cdefg" ); ksession.fireAllRules(); assertEquals( 2, list.size() ); assertTrue( list.containsAll( Arrays.asList( "abcde", "bcdef" ) ) ); } @Test public void testFunctionJitting() { // DROOLS-404 String str = "global java.util.List list;\n" + "declare Pippo end;\n" + "function boolean alwaysTrue() { return true; }" + "rule R1 when\n" + " $s : String( alwaysTrue() )\n" + "then\n" + " list.add( $s );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.insert( "abcde" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); } @Test public void testGlobalExtractor() { String str = "package org.test; " + "import java.util.*; " + "global java.util.List list; " + "global java.util.Date tat; " + "declare Foo @role(event) @timestamp( ts ) " + " tis : Date = new Date( 1000 ) " + " ts : Date = new Date( 0 ) " + "end " + "rule Init when then insert( new Foo() ); end " + "rule R1 when\n" + " $s : Foo( tis before tat )\n" + "then\n" + " list.add( $s );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.setGlobal( "tat", new Date( 2000 ) ); ksession.fireAllRules(); assertEquals( 1, list.size() ); } @Test public void testSharedNotWithLeftUpdateAndRightInsert() throws Exception { // BZ-1070092 String str = "import " + Foo.class.getCanonicalName() + ";\n" + "import " + Foo2.class.getCanonicalName() + ";\n" + "import " + Person.class.getCanonicalName() + ";\n" + "rule R1 when\n" + " f1 : Foo( )\n" + " Foo2( )\n" + " Person( age == f1.x )\n" + "then\n" + "end\n" + "rule R2 when\n" + " Foo( )\n" + " f2 : Foo2( )\n" + " not Person()\n" + "then\n" + " modify( f2 ) { x = 3 };\n" + " insert( new Person() );\n" + "end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString( str ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); Foo f1 = new Foo(); Foo2 f2 = new Foo2(); ksession.insert( f1 ); ksession.insert( f2 ); assertEquals( 2, ksession.fireAllRules() ); assertEquals( 3, f2.getX() ); } @Test public void testNestedNots1() { // DROOLS-444 String str = "package org.test; " + "rule negation_over_nested " + "when " + " not ( (String() and Integer()) " + " or " + " (String() and Integer())) " + "then " + " System.out.println(\"negation_over_nested\"); " + "end " + " " + "rule negation_distributed_partially_no_sharing " + "when " + " (not (String() and Long())) " + " and " + " (not (String() and Long())) " + "then " + " System.out.println(\"negation_distributed_partially_no_sharing\"); " + "end " + " " + "rule negation_distributed_partially_sharing " + "when " + " (not (String() and Integer())) " + " and " + " (not (String() and Integer())) " + "then " + " System.out.println(\"negation_distributed_partially_sharing\"); " + "end " + " " + "rule negation_distributed_fully " + "when " + " ((not String()) or (not Integer())) " + " and " + " ((not String()) or (not Integer())) " + "then " + " System.out.println(\"negation_distributed_fully\"); " + "end"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); ks.newKieBuilder( kfs ).buildAll(); KieSession ksession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); int n = ksession.fireAllRules(); assertEquals( 7, n ); } @Test public void testNestedNots2() { // DROOLS-444 String str = "package org.test; " + "rule shared_conjunct " + "when " + " (not (String() and Integer())) " + "then " + " System.out.println(\"shared_conjunct\"); " + "end " + "rule negation_over_nested " + "when " + " not ( (String() and Integer()) " + " or " + " (String() and Integer())) " + "then " + " System.out.println(\"negation_over_nested\"); " + "end " + " " + "rule negation_distributed_partially_no_sharing " + "when " + " (not (String() and Long())) " + " and " + " (not (String() and Long())) " + "then " + " System.out.println(\"negation_distributed_partially_no_sharing\"); " + "end " + " " + "rule negation_distributed_partially_sharing " + "when " + " (not (String() and Integer())) " + " and " + " (not (String() and Integer())) " + "then " + " System.out.println(\"negation_distributed_partially_sharing\"); " + "end " + " " + "rule negation_distributed_fully " + "when " + " ((not String()) or (not Integer())) " + " and " + " ((not String()) or (not Integer())) " + "then " + " System.out.println(\"negation_distributed_fully\"); " + "end"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); ks.newKieBuilder( kfs ).buildAll(); KieSession ksession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); int n = ksession.fireAllRules(); assertEquals( 8, n ); } @Test public void testNestedNots3() { // DROOLS-444 String str = "package org.test; " + "rule negation_distributed_partially_no_sharing " + "when " + " (not String()) " + " and " + " (not (Double() and Integer())) " + "then " + " System.out.println(\"firing\"); " + "end"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); ks.newKieBuilder( kfs ).buildAll(); KieSession ksession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); int n = ksession.fireAllRules(); assertEquals( 1, n ); } @Test public void testExtendingDate() { // BZ-1072629 String str = "import " + MyDate.class.getCanonicalName() + " \n" + "rule 'sample rule' \n" + "when \n" + " $date: MyDate() \n" + "then \n" + "$date.setDescription(\"test\"); \n" + "end \n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); Results results = ks.newKieBuilder( kfs ).buildAll().getResults(); assertEquals( 0, results.getMessages().size() ); } public static class MyDate extends Date { private String description; public String getDescription() { return this.description; } public void setDescription( final String desc ) { this.description = desc; } } @Test public void testEvalInSubnetwork() { // DROOLS-460 String str = "global java.util.List list;\n" + "\n" + "declare StatusEvent\n" + "@role(event)\n" + "timestamp : int\n" + "end\n" + "\n" + "rule R when\n" + "$i : Integer()\n" + "eval(true)\n" + "exists(\n" + "Integer(intValue > $i.intValue)\n" + "and eval(true)\n" + ")\n" + "then\n" + "list.add($i.intValue());\n" + "end"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); ks.newKieBuilder( kfs ).buildAll(); KieSession ksession = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ).newKieSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.insert( 0 ); ksession.fireAllRules(); ksession.insert( 1 ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 0, (int) list.get( 0 ) ); } @Test public void testRedeclaringRuleAttribute() { // BZ-1092084 String str = "rule R salience 10 salience 100 when then end\n"; assertDrlHasCompilationError( str, 1 ); } @Test public void testMultilineStatement() { // BZ-1092502 String str = "rule \"test\"\n" + "dialect \"mvel\"\n" + "when\n" + "then\n" + "System \n" + " .out \n" + " .println(\"hello\");\n" + "end\n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); Results results = ks.newKieBuilder( kfs ).buildAll().getResults(); assertEquals( 0, results.getMessages().size() ); } @Test public void testExtendsWithStrictModeOff() { // DROOLS-475 String str = "import java.util.HashMap;\n" + "dialect \"mvel\"\n" + "declare HashMap end\n" + "\n" + "declare Test extends HashMap end\n" + "\n" + "rule \"Insert\" salience 0\n" + "when\n" + "then\n" + "Test t = new Test();\n" + "t.Price = 10;\n" + "t.put(\"A\", \"a\");\n" + "t.OtherPrices = new HashMap();\n" + "t.OtherPrices.OldPrice = 8;\n" + "System.out.println(\"Inserting t=\"+t);\n" + "insert(t);\n" + "end\n" + "\n" + "rule \"Test HashMap\" salience -1\n" + "when\n" + "t: HashMap( Price < 11 )\n" + "then\n" + "t.Price = 11;\n" + "System.out.println(\"In Test HashMap\");\n" + "end\n" + "\n" + "rule \"Test Inherited\" salience -1\n" + "when\n" + "t: Test( Price < 100 )\n" + "then\n" + "t.Price = 12;\n" + "System.out.println(\"In Test Inherited!\");\n" + "end\n" + "\n" + "rule \"Print Result\" salience -5\n" + "when\n" + "t: Test()\n" + "then\n" + "System.out.println(\"Finally Price is =\"+t.Price);\n" + "//This as well doesn't print content as per toString() of HashMap is there a way to do that?\n" + "System.out.println(\"Finally t=\"+t);\n" + "end\n"; KnowledgeBuilderConfigurationImpl pkgBuilderCfg = new KnowledgeBuilderConfigurationImpl(); MVELDialectConfiguration mvelConf = (MVELDialectConfiguration) pkgBuilderCfg.getDialectConfiguration( "mvel" ); mvelConf.setStrict( false ); KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder( pkgBuilderCfg ); kbuilder.add( ResourceFactory.newByteArrayResource( str.getBytes() ), ResourceType.DRL ); assertFalse( kbuilder.hasErrors() ); } @Test public void testCompilationFailureWithDuplicatedAnnotation() { // BZ-1099896 String str = "declare EventA\n" + " @role(fact)\n" + " @role(event)\n" + "end\n"; assertDrlHasCompilationError( str, 1 ); } @Test public void testCrossNoLoopWithNodeSharing() throws Exception { // DROOLS-501 Propgation context is not set correctly when nodes are shared // This test was looping in 6.1.0-Beta4 String drl = "package org.drools.compiler.loop " + "rule 'Rule 1' " + " agenda-group 'Start' " + " no-loop " + " when " + " $thing1 : String() " + " $thing2 : Integer() " + " then\n" + " System.out.println( 'At 1' ); " + " update( $thing2 ); " + "end " + "rule 'Rule 2' " + " agenda-group 'End' " + " no-loop " + " when " + " $thing1 : String() " + " $thing2 : Integer() " + " then " + " System.out.println( 'At 2' ); " + " update( $thing2 ); " + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession session = helper.build().newKieSession(); session.insert( "hello" ); session.insert( new Integer( 42 ) ); // set the agenda groups in reverse order so that stack is preserved session.getAgenda().getAgendaGroup( "End" ).setFocus(); session.getAgenda().getAgendaGroup( "Start" ).setFocus(); int x = session.fireAllRules( 10 ); assertEquals( 2, x ); session.dispose(); } @Test public void testNotNodesUnlinking() throws Exception { // BZ-1101471 String drl = "import " + Trailer.class.getCanonicalName() + ";" + "global java.util.List trailerList;" + "rule R1\n" + "agenda-group 'Start'\n" + " when\n" + "$trailer : Trailer(status == Trailer.TypeStatus.WAITING);\n" + "not Trailer(status == Trailer.TypeStatus.LOADING); \n" + "not Trailer(status == Trailer.TypeStatus.SHIPPING);\n" + " then\n" + " System.out.println( \"[rfgroup1] find waiting trailer : \" + $trailer);\n" + " $trailer.setStatus(Trailer.TypeStatus.LOADING); \n" + " update($trailer);\n" + "end\n" + "\n" + "rule R2\n" + "agenda-group 'Start'\n" + " when\n" + "$trailer : Trailer(status == Trailer.TypeStatus.LOADING);\n" + " then\n" + " System.out.println( \"[rfgroup1] ship : \" + $trailer);\n" + " $trailer.setStatus(Trailer.TypeStatus.SHIPPING);\n" + " update($trailer);\n" + "end\n" + "\n" + "rule R3\n" + "agenda-group 'Start'\n" + " when\n" + "$trailer : Trailer(status == Trailer.TypeStatus.SHIPPING);\n" + " then\n" + " System.out.println( \"[rfgroup1] shipping done : \" + $trailer);\n" + " trailerList.add($trailer);\n" + " retract($trailer);\n" + "end\n" + "\n" + "rule R4\n" + "no-loop\n" + "agenda-group 'End'\n" + " when\n" + " then\n" + " System.out.println( \"[rfgroup2] insert new trailers\");\n" + " insert(new Trailer(Trailer.TypeStatus.WAITING));\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ArrayList<Trailer> trailerList = new ArrayList<Trailer>(); ksession.setGlobal( "trailerList", trailerList ); Trailer trailer1 = new Trailer( Trailer.TypeStatus.WAITING ); ksession.insert( trailer1 ); // set the agenda groups in reverse order so that stack is preserved ksession.getAgenda().getAgendaGroup( "Start" ).setFocus(); ksession.getAgenda().getAgendaGroup( "End" ).setFocus(); ksession.getAgenda().getAgendaGroup( "Start" ).setFocus(); ksession.fireAllRules(); assertEquals( 2, trailerList.size() ); } public static class Trailer { public enum TypeStatus {WAITING, LOADING, SHIPPING} private TypeStatus status; public Trailer( TypeStatus status ) { this.status = status; } public TypeStatus getStatus() { return status; } public void setStatus( TypeStatus status ) { this.status = status; } } public static class Host { } @Test public void testJITIncompatibleTypes() throws Exception { // BZ-1101295 String drl = "import " + Host.class.getCanonicalName() + ";\n" + "rule R when\n" + " $s: String()" + " Host($s == this)\n" + "then\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( new Host() ); ksession.insert( "host" ); ksession.fireAllRules(); } public static class TypeA { private int id = 1; public int getId() { return id; } } public static class TypeB { private int parentId = 1; private int id = 2; public int getParentId() { return parentId; } public int getId() { return id; } } public static class TypeC { private int parentId = 2; public int getParentId() { return parentId; } public int getValue() { return 1; } } public static class TypeD { private int parentId = 2; private int value; public int getParentId() { return parentId; } public int getValue() { return value; } public void setValue( int value ) { this.value = value; } } @Test public void testAccumulateWithNodeSharing() throws Exception { // DROOLS-487 String drl = "import " + TypeA.class.getCanonicalName() + ";\n" + "import " + TypeB.class.getCanonicalName() + ";\n" + "import " + TypeC.class.getCanonicalName() + ";\n" + "import " + TypeD.class.getCanonicalName() + ";\n" + "rule R1 when\n" + " $a : TypeA()\n" + " $b : TypeB( parentId == $a.id )\n" + " $d : TypeD( parentId == $b.id, value == 1 )\n" + "then\n" + "end\n" + "\n" + "rule R2 no-loop when\n" + " $a : TypeA()\n" + " $b : TypeB( parentId == $a.id )\n" + "then\n" + " update($b);" + "end\n" + "\n" + "rule R3 when\n" + " $a : TypeA()\n" + " $b : TypeB( parentId == $a.id )\n" + " $d : TypeD( parentId == $b.id )\n" + " $result : Number() from accumulate(\n" + " $b_acc : TypeB()\n" + " and\n" + " $c : TypeC( parentId == $b_acc.id, $value : value );\n" + " sum($value)\n" + " )\n" + "then\n" + " $d.setValue($result.intValue());\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( new TypeA() ); ksession.insert( new TypeB() ); ksession.insert( new TypeC() ); TypeD d = new TypeD(); ksession.insert( d ); ksession.fireAllRules(); assertEquals( 1, d.getValue() ); } public static class Reading { private final String type; private final int value; public Reading( String type, int value ) { this.type = type; this.value = value; } public String getType() { return type; } public int getValue() { return value; } } public static class Alarm { private String type; private String level; public String getLevel() { return level; } public void setLevel( String level ) { this.level = level; } public String getType() { return type; } public void setType( String type ) { this.type = type; } } @Test public void testDeletedEvalLeftTuple() throws Exception { // BZ-1106300 String drl = "import " + Reading.class.getCanonicalName() + ";\n" + "import " + Alarm.class.getCanonicalName() + ";\n" + "rule Normal when\n" + " Number( intValue <= 5) from accumulate( reading : Reading(), average( reading.getValue() ) )\n" + " alarm : Alarm ()\n" + "then\n" + " System.out.println(kcontext.getRule().getName());" + " delete( alarm );\n" + "end\n" + " \n" + "rule Abnormal when\n" + " Number( intValue > 5, intValue <= 10 ) from accumulate( reading : Reading(), average( reading.getValue() ) )\n" + " not Alarm ()\n" + "then\n" + " System.out.println(kcontext.getRule().getName());" + " Alarm alarm = new Alarm();\n" + " alarm.setType(\"t1\");\n" + " alarm.setLevel( \"ABNORMAL\" );\n" + " insert(alarm);\n" + "end\n" + "\n" + "rule Severe when\n" + " Number( intValue > 10) from accumulate( reading : Reading(), average( reading.getValue() ) )\n" + " not Alarm ()\n" + "then\n" + " System.out.println(kcontext.getRule().getName());" + " Alarm alarm = new Alarm();\n" + " alarm.setType(\"t1\");\n" + " alarm.setLevel( \"SEVERE\" );\n" + " insert(alarm);\n" + "end\n" + "\n" + "rule AbnormalToSevere when\n" + " Number( intValue > 10) from accumulate( reading : Reading(), average( reading.getValue() ) )\n" + " alarm : Alarm (level == \"ABNORMAL\")\n" + "then\n" + " System.out.println(kcontext.getRule().getName());" + " alarm.setLevel( \"SEVERE\" );\n" + " update(alarm);\n" + "end\n" + "\n" + "rule SevereToAbnormal when\n" + " $type : String()\n" + " accumulate( reading : Reading( type == $type ), $avg : average( reading.getValue() ) )\n" + " eval( $avg.intValue() > 5 && $avg.intValue() <= 10 )\n" + " alarm : Alarm (type == $type, level == \"SEVERE\")\n" + "then\n" + " System.out.println(kcontext.getRule().getName());" + " alarm.setLevel( \"ABNORMAL\" );\n" + " update(alarm);\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( "t1" ); ksession.insert( new Reading( "t1", 12 ) ); ksession.fireAllRules(); ksession.insert( new Reading( "t1", 0 ) ); ksession.fireAllRules(); ksession.insert( new Reading( "t1", 0 ) ); ksession.fireAllRules(); ksession.insert( new Reading( "t1", 16 ) ); ksession.fireAllRules(); ksession.insert( new Reading( "t1", 32 ) ); ksession.fireAllRules(); ksession.insert( new Reading( "t1", -6 ) ); ksession.fireAllRules(); } public static class C1 { private int counter = 0; private final List<C2> c2s = Arrays.asList( new C2(), new C2() ); public List<C2> getC2s() { return c2s; } public int getSize() { return getC2s().size(); } public int getCounter() { return counter; } public void setCounter( int counter ) { this.counter = counter; } } public static class C2 { private final List<C3> c3s = Arrays.asList( new C3( 1 ), new C3( 2 ) ); public List<C3> getC3s() { return c3s; } } public static class C3 { public final int value; public C3( int value ) { this.value = value; } public int getValue() { return value; } } @Test public void testDeleteFromLeftTuple() throws Exception { // DROOLS-518 String drl = "import " + C1.class.getCanonicalName() + ";\n" + "import " + C2.class.getCanonicalName() + ";\n" + "import " + C3.class.getCanonicalName() + ";\n" + "rule R when\n" + " $c1 : C1 ( $c2s : c2s, $c2 : c2s.get(counter), counter < size )\n" + " C2 ( $c3s : c3s, this == $c2 ) from $c2s\n" + " accumulate( C3 ( $value : value ) from $c3s;\n" + " $sum : sum($value)\n" + " )\n" + "then\n" + " $c1.setCounter($c1.getCounter() + 1);\n" + " update( $c1 );\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( new C1() ); ksession.fireAllRules(); } public interface I0 { String getValue(); } public interface I1 extends I0 { } public static class X implements I0 { @Override public String getValue() { return "x"; } } public static class Y extends X implements I1 { } public static class Z implements I1 { @Override public String getValue() { return "x"; } } @Test public void testMethodResolution() throws Exception { // DROOLS-509 String drl = "import " + I1.class.getCanonicalName() + ";\n" + "rule R1 when\n" + " I1 ( value == \"x\" )\n" + "then\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( new Y() ); ksession.fireAllRules(); ksession.insert( new Z() ); ksession.fireAllRules(); } @Test public void testCorrectErrorMessageOnDeclaredTypeCompilation() throws Exception { // DROOLS-543 String str = "rule R\n" + "salience 10\n" + "when\n" + " String()\n" + "then\n" + "System.out.println(\"Hi\");\n" + "end\n" + "declare A\n" + " a : SomeNonexistenClass @key\n" + " b : int @key\n" + "end\n" + "\n" + "declare C\n" + " d : int @key\n" + " e : int[]\n" + "end\n"; assertDrlHasCompilationError( str, 1 ); } @Test public void testFieldNameStartingWithUnderscore() throws Exception { // DROOLS-554 String str = "import " + Underscore.class.getCanonicalName() + ";\n" + "rule R when\n" + " Underscore( _id == \"test\" )\n" + "then\n" + "end\n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem().write( "src/main/resources/r1.drl", str ); Results results = ks.newKieBuilder( kfs ).buildAll().getResults(); assertEquals( 0, results.getMessages().size() ); } public static class Underscore { private String _id; public String get_id() { return _id; } public void set_id( String _id ) { this._id = _id; } } @Test public void testSharedQueryNode() throws Exception { // DROOLS-561 String drl = "query find( Integer $i, String $s )\n" + " $i := Integer( toString() == $s )\n" + "end\n" + "\n" + "rule R2 salience -1 when\n" + " $s : String()\n" + " ?find( i, $s; )\n" + "then\n" + "end\n" + "rule R1 when\n" + " $s : String()\n" + " ?find( i, $s; )\n" + " $i : Integer( this == 1 ) from i\n" + "then\n" + " delete( $s );\n" + "end\n"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( "1" ); ksession.insert( 1 ); ksession.fireAllRules(); } @Test public void testLeftTupleGetIndex() throws Exception { // DROOLS-570 String drl = "rule R1 when\n" + " $s : String()\n" + " (or Long(this == 1) Long(this == 2) )\n" + "then\n" + "end\n" + "rule R2 extends R1 when\n" + " $n : Number() from accumulate( Integer($value : this); sum($value) )\n" + "then\n" + " System.out.println($n);\n" + "end\n"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( "1" ); ksession.insert( 1L ); ksession.insert( 1 ); ksession.fireAllRules(); } @Test public void testStrOperatorInAccumulate() throws Exception { // DROOLS-574 String drl = "declare Message\n" + " text : String\n" + "end\n" + "\n" + "declare GroupByString\n" + " groupId : String\n" + " groups : String[]\n" + "end\n" + "\n" + "global java.util.List list\n" + "\n" + "rule \"init words of my interest\"\n" + "no-loop\n" + "when\n" + "then\n" + " GroupByString grp = new GroupByString();\n" + " grp.setGroupId(\"wordGroup\");\n" + " grp.setGroups(new String[]{\"hi\", \"hello\"});\n" + " insert(grp);\n" + " insert(new Message(\"hi all\"));\n" + " insert(new Message(\"hello world\"));\n" + " insert(new Message(\"bye\"));\n" + " insert(new Message(\"hello everybody\"));\n" + "end\n" + "\n" + "rule \"group by word and count if >=2 then \"\n" + "no-loop\n" + "when\n" + " $group : GroupByString( groupId == \"wordGroup\")\n" + " $word : String() from $group.groups\n" + " acc ( $msg : Message( text str[startsWith] $word );\n" + " $list : collectList( $msg ),\n" + " $count : count( $msg );\n" + " $count >= 1\n" + " )\n" + "then\n" + " list.add(\"group by \" + $word + \" count is \"+ $count);\n" + "end\n"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 2, list.size() ); assertTrue( list.contains( "group by hello count is 2" ) ); assertTrue( list.contains( "group by hi count is 1" ) ); } @Test public void testKeywordAsAttribute() throws Exception { // DROOLS-577 String drl = "package foo.bar;\n" + "declare Fired\n" + " rule: String\n" + "end\n" + "global java.util.List list\n" + "rule \"F060\" dialect \"mvel\"\n" + "when\n" + "then\n" + " Fired f = new Fired();\n" + " f.rule = \"F060\";\n" + " insert(f);\n" + "end\n" + " \n" + "rule \"F060b\" //this prints F060b: Fired( rule=F060 )\n" + " dialect \"mvel\"\n" + "when\n" + " $rule: Fired()\n" + "then\n" + " list.add( drools.getRule().getName() )\n" + "end\n" + " \n" + "rule \"F060c\" //doesn't work\n" + " dialect \"mvel\"\n" + "when\n" + " $rule: Fired( rule==\"F060\" )\n" + "then\n" + " list.add( drools.getRule().getName() )\n" + "end\n" + " \n" + "rule \"F060d\" //this prints F060d: Fired( rule=F060 )\n" + " dialect \"mvel\"\n" + "when\n" + " $rule: Fired()\n" + " eval( $rule.rule == \"F060\")\n" + "then\n" + " list.add( drools.getRule().getName() )\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); System.out.println( list ); assertEquals( 3, list.size() ); assertTrue( list.contains( "F060b" ) ); assertTrue( list.contains( "F060c" ) ); assertTrue( list.contains( "F060d" ) ); } @Test public void testRuleExtendsWithNamedConsequence() { // DROOLS-581 String drl = "package org.drools.test;\n" + "global java.util.List list;\n" + "rule Base\n" + "when\n" + " $i : Integer( ) do[x]\n" + "then\n" + "then[x]\n" + " list.add( $i );\n" + "end\n" + "rule Ext extends Base\n" + "when\n" + " $d : String()\n" + "then\n" + " list.add( $d );\n" + "end\n"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession kieSession = helper.build().newKieSession(); List<Integer> list = new ArrayList<Integer>(); kieSession.setGlobal( "list", list ); kieSession.insert( 10 ); kieSession.fireAllRules(); assertEquals( 2, list.size() ); assertEquals( 10, (int) list.get( 0 ) ); assertEquals( 10, (int) list.get( 1 ) ); } @Test public void testRuleExtendsWithOverriddenNamedConsequence() { // DROOLS-581 String drl = "package org.drools.test;\n" + "global java.util.List list;\n" + "rule Base\n" + "when\n" + " $i : Integer( ) do[x]\n" + "then\n" + "then[x] " + " list.add( $i );\n" + "end\n" + "rule Ext extends Base\n" + "when\n" + " $d : String()\n" + "then\n" + " list.add( $d );\n" + "then[x]\n" + " list.add( \"\" + $i );\n" + "end\n"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession kieSession = helper.build().newKieSession(); List list = new ArrayList(); kieSession.setGlobal( "list", list ); kieSession.insert( 10 ); kieSession.fireAllRules(); assertEquals( 2, list.size() ); assertEquals( 10, list.get( 0 ) ); assertEquals( "10", list.get( 1 ) ); } @Test public void testCustomDynamicSalience() { String drl = "package org.drools.test; " + "import " + Person.class.getName() + "; " + "global java.util.List list; " + "rule A " + "when " + " $person : Person( name == 'a' ) " + "then" + " list.add( $person.getAge() ); " + "end " + "rule B " + "when " + " $person : Person( name == 'b' ) " + "then" + " list.add( $person.getAge() ); " + "end " + ""; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession session = helper.build().newKieSession(); List<Integer> list = new ArrayList<Integer>(); session.setGlobal( "list", list ); for ( Rule r : session.getKieBase().getKiePackage( "org.drools.test" ).getRules() ) { ( (RuleImpl) r ).setSalience( new Salience() { @Override public int getValue( KnowledgeHelper khelper, Rule rule, WorkingMemory workingMemory ) { if ( khelper == null ) { return 0; } InternalFactHandle h = (InternalFactHandle) khelper.getMatch().getFactHandles().get( 0 ); return ( (Person) h.getObject() ).getAge(); } @Override public int getValue() { throw new IllegalStateException( "Should not have been called..." ); } @Override public boolean isDynamic() { return true; } } ); } session.insert( new Person( "a", 1 ) ); session.insert( new Person( "a", 5 ) ); session.insert( new Person( "a", 3 ) ); session.insert( new Person( "b", 4 ) ); session.insert( new Person( "b", 2 ) ); session.insert( new Person( "b", 6 ) ); session.fireAllRules(); assertEquals( Arrays.asList( 6, 5, 4, 3, 2, 1 ), list ); } @Test public void testNotWithSubNetwork() { String drl = "rule R when\n" + " $s : String( )\n" + " not (\n" + " Long( toString() == $s )\n" + " and\n" + " Integer( toString() == $s )\n" + " )\n" + "then\n" + " delete( $s );\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( "1" ); FactHandle iFH = ksession.insert( 1 ); FactHandle lFH = ksession.insert( 1L ); assertEquals( 0, ksession.fireAllRules() ); ksession.delete( iFH ); ksession.delete( lFH ); assertEquals( 1, ksession.fireAllRules() ); assertEquals( 0, ksession.getFactCount() ); } @Test public void testGenericsInRHSWithModify() { // DROOLS-493 String drl = "import java.util.Map;\n" + "import java.util.HashMap;\n" + "rule R no-loop when\n" + " $s : String( )\n" + "then\n" + " Map<String,String> a = new HashMap<String,String>();\n" + " modify( $s ) { };" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession ksession = helper.build().newKieSession(); ksession.insert( "1" ); ksession.fireAllRules(); } @Test public void testQueryWithAgendaGroup() { // DROOLS-601 String drl = "package org.drools.test; " + "global java.util.List list; " + "query foo( Integer $i ) " + " $i := Integer() " + "end " + "rule Detect " + "agenda-group 'one' " + "when " + " foo( $i ; ) " + "then " + " list.add( $i ); " + "end " + "rule OnceMore " + "agenda-group 'two' " + "no-loop " + "when " + " $i : Integer() " + "then " + " update( $i );" + "end " + ""; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession kieSession = helper.build().newKieSession(); List<Integer> list = new ArrayList<Integer>(); kieSession.setGlobal( "list", list ); FactHandle handle = kieSession.insert( 42 ); Agenda agenda = kieSession.getAgenda(); agenda.getAgendaGroup( "two" ).setFocus(); agenda.getAgendaGroup( "one" ).setFocus(); kieSession.fireAllRules(); assertEquals( Arrays.asList( 42 ), list ); kieSession.delete( handle ); kieSession.insert( 99 ); agenda.getAgendaGroup( "two" ).setFocus(); agenda.getAgendaGroup( "one" ).setFocus(); kieSession.fireAllRules(); assertEquals( Arrays.asList( 42, 99 ), list ); } @Test public void testQueryUsingQueryWithAgendaGroup() { // DROOLS-601 String drl = "package org.drools.test; " + "global java.util.List list; " + "query bar( String $s ) " + " $s := String() " + "end " + "query foo( Integer $i, String $s ) " + " bar( $s ; ) " + " $i := Integer( toString() == $s ) " + "end " + "rule Detect " + "agenda-group 'one' " + "when " + " foo( $i, $s ; ) " + "then " + " list.add( $i ); " + "end " + "rule UpdateInt " + "agenda-group 'two' " + "no-loop " + "when " + " $i : Integer() " + "then " + " update( $i );" + "end " + "rule UpdateString " + "agenda-group 'three' " + "no-loop " + "when " + " $s : String() " + "then " + " update( $s );" + "end " + ""; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession kieSession = helper.build().newKieSession(); List<Integer> list = new ArrayList<Integer>(); kieSession.setGlobal( "list", list ); FactHandle iFH = kieSession.insert( 42 ); FactHandle sFH = kieSession.insert( "42" ); Agenda agenda = kieSession.getAgenda(); agenda.getAgendaGroup( "three" ).setFocus(); agenda.getAgendaGroup( "two" ).setFocus(); agenda.getAgendaGroup( "one" ).setFocus(); kieSession.fireAllRules(); assertEquals( Arrays.asList( 42 ), list ); //kieSession.delete( iFH ); kieSession.delete( sFH ); kieSession.insert( 99 ); kieSession.insert( "99" ); agenda.getAgendaGroup( "three" ).setFocus(); agenda.getAgendaGroup( "two" ).setFocus(); agenda.getAgendaGroup( "one" ).setFocus(); kieSession.fireAllRules(); assertEquals( Arrays.asList( 42, 99 ), list ); } @Test public void testFactTemplates() { // DROOLS-600 String drl = "package com.testfacttemplate;" + " rule \"test rule\" " + " dialect \"mvel\" " + " when " + " $test : TestFactTemplate( status == 1 ) " + " then " + " System.out.println( \"Hello World\" ); " + " end "; KnowledgePackageImpl kPackage = new KnowledgePackageImpl( "com.testfacttemplate" ); FieldTemplate fieldTemplate = new FieldTemplateImpl( "status", 0, Integer.class ); FactTemplate factTemplate = new FactTemplateImpl( kPackage, "TestFactTemplate", new FieldTemplate[]{fieldTemplate} ); KnowledgeBuilder kBuilder = new KnowledgeBuilderImpl( kPackage ); StringReader rule = new StringReader( drl ); try { ( (KnowledgeBuilderImpl) kBuilder ).addPackageFromDrl( rule ); } catch (Exception e) { throw new RuntimeException( e ); } } @Test public void testBitwiseOperator() { // DROOLS-585 String drl = "global java.util.List list;\n" + "\n" + "rule R when\n" + " $i : Integer( (intValue() & 5) != 0 )\n" + "then\n" + " list.add($i);\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); KieSession kieSession = helper.build().newKieSession(); List<Integer> list = new ArrayList<Integer>(); kieSession.setGlobal( "list", list ); kieSession.insert( 3 ); kieSession.insert( 2 ); kieSession.insert( 6 ); kieSession.fireAllRules(); assertEquals( 2, list.size() ); assertTrue( list.containsAll( asList( 3, 6 ) ) ); } @Test public void testNotSubnetwork() { // DROOLS-623 String drl = "import " + TypeCC.class.getCanonicalName() + ";\n" + "import " + TypeDD.class.getCanonicalName() + ";\n" + " \n" + "rule R1 \n" + "when \n" + " $dd : TypeDD( value < 1 )\n" + "then \n" + " System.out.println(\"Rule R1 Fired\");\n" + " modify($dd) { setValue(1); }\n" + "end \n" + " \n" + "rule R2 when \n" + " String( ) \n" + " $cc : TypeCC( value < 1 )\n" + " not( \n" + " $cc_not : TypeCC( ) \n" + " and \n" + " $dd_not : TypeDD( value==0 ) \n" + " ) \n" + "then \n" + " System.out.println(\"Rule R2 Fired\");\n" + " modify($cc) { setValue($cc.getValue()+1); }\n" + "end; "; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); ksession.insert( "1" ); ksession.insert( "2" ); TypeCC cc = new TypeCC(); ksession.insert( cc ); ksession.insert( new TypeDD() ); ksession.fireAllRules(); System.out.println( "Rule R2 is fired count - " + cc.getValue() ); assertEquals( "Rule 2 should be fired once as we have firing rule as one of criteria checking rule only fire once", 1, cc.getValue() ); } public static class ValueContainer { private int value; public int getValue() { return value; } public void setValue( int value ) { this.value = value; } } public static class TypeCC extends ValueContainer { } public static class TypeDD extends ValueContainer { } @Test public void testClassAccumulator() { // DROOLS-626 String drl = "global java.util.List list\n" + "declare InitClass\n" + " clazz: Class\n" + "end\n" + "\n" + "rule \"init\" when\n" + "then\n" + " insert( new InitClass( String.class ) );\n" + " insert( new InitClass( Integer.class ) );\n" + "end\n" + "\n" + "rule \"make init classes\"\n" + "when\n" + " accumulate( InitClass( $clazz; ), $classes: collectList( $clazz ) )\n" + "then\n" + " list.addAll($classes);\n" + "end "; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<Class> list = new ArrayList<Class>(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 2, list.size() ); System.out.println( list ); assertTrue( list.containsAll( asList( String.class, Integer.class ) ) ); } @Test public void testSubnetworkAccumulate() { String drl = "import " + StringWrapper.class.getCanonicalName() + ";\n" + "global StringBuilder sb;" + "rule R when\n" + " $s : String()\n" + " Number( $i : intValue ) from accumulate ($sw : StringWrapper( $value : value ) " + " and eval( $sw.contains($s) ), " + " sum($value) )\n" + "then\n" + " sb.append($i);\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); StringBuilder sb = new StringBuilder(); ksession.setGlobal( "sb", sb ); ksession.insert( "test" ); StringWrapper sw = new StringWrapper(); FactHandle swFH = ksession.insert( sw ); ksession.fireAllRules(); sw.setWrapped( "test" ); ksession.update( swFH, sw ); ksession.fireAllRules(); sw.setWrapped( null ); ksession.update( swFH, sw ); ksession.fireAllRules(); sw.setWrapped( "test" ); ksession.update( swFH, sw ); ksession.fireAllRules(); sw.setWrapped( null ); ksession.update( swFH, sw ); ksession.fireAllRules(); sw.setWrapped( "test" ); ksession.update( swFH, sw ); ksession.fireAllRules(); assertEquals( "040404", sb.toString() ); } public interface TestString<T extends TestString> extends Comparable<TestString<?>> { } public static class StringWrapper implements TestString<StringWrapper> { private String wrapped; public StringWrapper() { } public StringWrapper(String wrapped) { this.wrapped = wrapped; } public String getWrapped() { return wrapped; } public void setWrapped( String wrapped ) { this.wrapped = wrapped; } public boolean contains( String s ) { return wrapped != null && wrapped.equals( s ); } public int getValue() { return wrapped != null ? wrapped.length() : 0; } @Override public int compareTo( TestString o ) { return wrapped.compareTo( ( (StringWrapper) o ).wrapped ); } } @Test public void testImportInner() throws Exception { // DROOLS-677 String drl = "package org.drools.test; " + "import " + Misc2Test.class.getName() + "; " + "declare Foo " + " bar : Misc2Test.AA " + "end " + ""; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); assertTrue( helper.verify().getMessages( org.kie.api.builder.Message.Level.ERROR ).isEmpty() ); } @Test //DROOLS-678 public void testAlphaIndexing() throws Exception { String drl = " package org.drools.test; " + " declare ObjectB " + " name : String " + " intValue : Integer " + " end " + " rule 'insert object' " + " when " + " then " + " insert( new ObjectB( null, 0 ) ); " + " end " + " rule 'rule 1' " + " when " + " ObjectB( intValue == 1 ) " + " then " + " end " + " rule 'rule 2' " + " when " + " ObjectB( intValue == 2 ) " + " then " + " end " + " rule 'rule 3' " + " when " + " $b : ObjectB( intValue == null ) " + " then\n" + " System.out.println( $b ); " + " end" + "\n"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); assertTrue( helper.verify().getMessages( org.kie.api.builder.Message.Level.ERROR ).isEmpty() ); KieSession ks = helper.build().newKieSession(); assertEquals( 1, ks.fireAllRules() ); } @Test public void testMvelConstraintErrorMessageOnAlpha() throws Exception { // DROOLS-687 String drl = " import org.drools.compiler.Person; " + " import org.drools.compiler.Address; " + " rule 'hello person' " + " when " + " Person( address.street == 'abbey' ) " + " then " + " end " + "\n"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); assertTrue( helper.verify().getMessages( org.kie.api.builder.Message.Level.ERROR ).isEmpty() ); KieSession ks = helper.build().newKieSession(); Person john = new Person( "John" ); // address is null try { ks.insert( john ); ks.fireAllRules(); fail( "Should throw an exception" ); } catch (Exception e) { assertTrue( e.getMessage().contains( "hello person" ) ); } } @Test public void testMvelConstraintErrorMessageOnBeta() throws Exception { // DROOLS-687 String drl = " import org.drools.compiler.Person; " + " import org.drools.compiler.Address; " + " rule 'hello person' " + " when " + " $s : String( ) " + " Person( address.street == $s ) " + " then " + " end " + "\n"; KieHelper helper = new KieHelper(); helper.addContent( drl, ResourceType.DRL ); assertTrue( helper.verify().getMessages( org.kie.api.builder.Message.Level.ERROR ).isEmpty() ); KieSession ks = helper.build().newKieSession(); Person john = new Person( "John" ); // address is null try { ks.insert( "abbey" ); ks.insert( john ); ks.fireAllRules(); fail( "Should throw an exception" ); } catch (Exception e) { assertTrue( e.getMessage().contains( "hello person" ) ); } } @Test public void testPassiveExists() { // DROOLS-699 String drl2 = "import " + List.class.getCanonicalName() + ";\n" + "\n\n" + "rule \"NotExists\"\n" + "when\n" + "$l1: List() \n" + "$l2: List() \n" + "exists( String() from $l1 ) \n" + "not( exists( String() ) )\n" + "then end\n"; KieSession ksession = new KieHelper().addContent( drl2, ResourceType.DRL ) .build() .newKieSession(); ksession.insert( asList( "Mario", "Mark" ) ); ksession.insert( asList( "Julie", "Leiti" ) ); assertEquals( 4, ksession.fireAllRules() ); } @Test public void testFromAfterOr() { // DROOLS-707 String drl2 = "rule \"Disaster Rule\"\n" + " when\n" + " eval(true) or ( eval(false) and Integer() )\n" + " $a : Integer()\n" + " Integer() from $a\n" + " then\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl2, ResourceType.DRL ) .build() .newKieSession(); ksession.insert( 1 ); assertEquals( 1, ksession.fireAllRules() ); } @Test public void testMalformedAccumulate() { // DROOLS-725 String str = "rule R when\n" + " Number() from accumulate(not Number(),\n" + " init( double total = 0; ),\n" + " action( ),\n" + " reverse( ),\n" + " result( new Double( total ) )\n" + " )\n" + "then end\n"; assertDrlHasCompilationError( str, 1 ); } @Test public void testDuplicateDeclarationInAccumulate1() { // DROOLS-727 String drl1 = "import java.util.*\n" + "rule \"Version 1 - crash\"\n" + " when\n" + " accumulate( Integer($int: intValue), $list: collectSet($int) )\n" + " List() from collect( Integer($list not contains intValue) )\n\n" + " accumulate( Integer($int: intValue), $list: collectSet($int) )\n" + " then\n" + "end\n"; assertDrlHasCompilationError( drl1, 1 ); } @Test public void testDuplicateDeclarationInAccumulate2() { // DROOLS-727 String drl1 = "import java.util.*\n" + "rule \"Version 2 - pass\"\n" + "when\n" + " $list: List() from collect( Integer() )\n\n" + " accumulate( Integer($int: intValue), $list: collectSet($int) )\n" + " List() from collect( Integer($list not contains intValue) )\n" + "then\n" + "end;\n"; assertDrlHasCompilationError( drl1, 1 ); } @Test public void testCompilationFailureOnNonExistingVariable() { // DROOLS-734 String drl1 = "import java.util.*\n" + "rule R\n" + "when\n" + " String(this after $event)\n" + "then\n" + "end;\n"; assertDrlHasCompilationError( drl1, 1 ); } @Test public void testJittedConstraintStringAndLong() { // DROOLS-740 String drl = " import org.drools.compiler.Person; " + " rule 'hello person' " + " when " + " Person( name == \"Elizabeth\" + new Long(2L) ) " + " then " + " end " + "\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); ksession.insert( new org.drools.compiler.Person( "Elizabeth2", 88 ) ); assertEquals( 1, ksession.fireAllRules() ); } @Test public void testKieBuilderWithClassLoader() { // DROOLS-763 String drl = "import com.billasurf.Person\n" + "\n" + "global java.util.List list\n" + "\n" + "rule R1 when\n" + " $i : Integer()\n" + "then\n" + " Person p = new Person();\n" + " p.setAge($i);\n" + " insert(p);\n" + "end\n" + "\n" + "rule R2 when\n" + " $p : Person()\n" + "then\n" + " list.add($p.getAge());\n" + "end\n"; URLClassLoader urlClassLoader = new URLClassLoader( new URL[]{this.getClass().getResource( "/billasurf.jar" )} ); KieSession ksession = new KieHelper().setClassLoader( urlClassLoader ) .addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.insert( 18 ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 18, (int) list.get( 0 ) ); } @Test public void testInsertAndDelete() { String drl = "global java.util.List list\n" + "\n" + "rule R when\n" + " $i : Integer()\n" + " $s : String()\n" + "then\n" + " delete($i);\n" + " list.add($s);\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( 1 ); ksession.insert( "a" ); ksession.insert( "b" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); } @Test public void testClearActivationGroupCommand() { // DROOLS-828 String drl = "package org.kie.test\n" + "global java.util.List list\n" + "rule \"Rule in first agenda group\" @Propagation(IMMEDIATE)\n" + "agenda-group \"first-agenda\"\n" + "salience 10\n" + "when\n" + "then\n" + "list.add(\"Rule in first agenda group executed\");\n" + "end\n" + "rule \"Rule without agenda group\" @Propagation(IMMEDIATE)\n" + "salience 100\n" + "when\n" + "then\n" + "list.add(\"Rule without agenda group executed\");\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); ksession.setGlobal( "list", new ArrayList<String>() ); ksession.getAgenda().getAgendaGroup( "first-agenda" ).setFocus(); ksession.getAgenda().getAgendaGroup( "first-agenda" ).clear(); ksession.fireAllRules(); ArrayList<String> list = (ArrayList<String>) ksession.getGlobal( "list" ); assertEquals( 1, list.size() ); assertEquals( "Rule without agenda group executed", list.get( 0 ) ); } @Test public void testClearActivationGroupCommandNoImmediatePropagation() { // DROOLS-865 String drl = "package org.kie.test\n" + "global java.util.List list\n" + "rule \"Rule in first agenda group\"\n" + "agenda-group \"first-agenda\"\n" + "salience 10\n" + "when\n" + "then\n" + "list.add(\"Rule in first agenda group executed\");\n" + "end\n" + "rule \"Rule without agenda group\"\n" + "salience 100\n" + "when\n" + "then\n" + "list.add(\"Rule without agenda group executed\");\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); ksession.setGlobal( "list", new ArrayList<String>() ); ksession.getAgenda().getAgendaGroup( "first-agenda" ).setFocus(); ksession.getAgenda().getAgendaGroup( "first-agenda" ).clear(); ksession.fireAllRules(); ArrayList<String> list = (ArrayList<String>) ksession.getGlobal( "list" ); assertEquals( 1, list.size() ); assertEquals( "Rule without agenda group executed", list.get( 0 ) ); } public static class $X { public static class $Y { private final int value; public $Y( int value ) { this.value = value; } public int getValue() { return value; } } } @Test public void testDoubleNestedClass() { // DROOLS-815 String drl = "import " + $X.$Y.class.getCanonicalName() + ";\n" + "global java.util.List list\n" + "rule R when\n" + " $X.$Y($v : value)\n" + "then\n" + " list.add($v);\n" + "end"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( new $X.$Y( 42 ) ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( 42, list.get( 0 ) ); } @Test public void testWrongNodeSharing() { // DROOLS-588 String drl1 = "package test1\n" + "import static " + Misc2Test.class.getCanonicalName() + ".parseInt;\n" + "global java.util.List list;\n" + "rule R when\n" + " String( parseInt(this) == 0 )\n" + "then\n" + " list.add(\"OK\");\n" + "end"; String drl2 = "package test2\n" + "import static java.lang.Integer.parseInt;\n" + "global java.util.List list;\n" + "rule R when\n" + " String( parseInt(this) == 0 )\n" + "then\n" + " list.add(\"NOT OK\");\n" + "end"; KieHelper helper = new KieHelper(); helper.addContent( drl1, ResourceType.DRL ); helper.addContent( drl2, ResourceType.DRL ); KieSession kieSession = helper.build().newKieSession(); List list = new ArrayList(); kieSession.setGlobal( "list", list ); kieSession.insert( "3" ); kieSession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "OK", list.get( 0 ) ); } public static int parseInt( String s ) { return 0; } @Test public void testJittedConstraintComparisonWithIncompatibleObjects() { // DROOLS-858 String drl = "package org.drools.compiler.integrationtests\n" + "import java.util.Map.Entry\n" + "import java.util.Map\n" + "import " + NonStringConstructorClass.class.getCanonicalName() + "\n" + "global java.util.List list\n" + "rule \"FailOnNonStringConstructor\"\n" + " when \n" + " $map : Map()\n" + " $simpleTestObject : NonStringConstructorClass (something==\"simpleTestObject\")\n" + " Entry (\n" + " getKey() == $simpleTestObject\n" + " ) from $map.entrySet()\n" + " then\n" + " list.add(\"Fired\");\n" + "end"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<Object> globalList = new ArrayList<Object>(); ksession.setGlobal( "list", globalList ); NonStringConstructorClass simpleTestObject = new NonStringConstructorClass(); simpleTestObject.setSomething( "simpleTestObject" ); Map<Object, Object> map = new HashMap<Object, Object>(); map.put( "someOtherValue", "someOtherValue" ); map.put( simpleTestObject, "someValue" ); List<Object> list = new ArrayList<Object>(); ksession.insert( map ); ksession.insert( simpleTestObject ); ksession.fireAllRules(); Assert.assertEquals( 1, globalList.size() ); } public static class NonStringConstructorClass { private String something; public String getSomething() { return something; } public void setSomething( String something ) { this.something = something; } @Override public String toString() { return "NonStringConstructorClass [something=" + something + "]"; } } @Test(timeout = 10000L) public void testFireUntilHaltWithForceEagerActivation() throws InterruptedException { String drl = "global java.util.List list\n" + "rule \"String detector\"\n" + " when\n" + " $s : String( )\n" + " then\n" + " list.add($s);\n" + "end"; KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration(); config.setOption( ForceEagerActivationOption.YES ); final KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession( config, null ); final Integer monitor = 42; int factsNr = 5; List<String> list = new NotifyingList<String>( factsNr, new Runnable() { @Override public void run() { synchronized (monitor) { monitor.notifyAll(); } } } ); ksession.setGlobal( "list", list ); // thread for firing until halt ExecutorService thread = Executors.newSingleThreadExecutor(); thread.submit( new Runnable() { @Override public void run() { ksession.fireUntilHalt(); } } ); for ( int i = 0; i < factsNr; i++ ) { ksession.insert( "" + i ); } // wait for rule to fire synchronized (monitor) { if ( list.size() < factsNr ) { monitor.wait(); } } assertEquals( factsNr, list.size() ); ksession.halt(); } public static class NotifyingList<T> extends ArrayList<T> { private final int limit; private final Runnable listener; public NotifyingList( int limit, Runnable listener ) { this.limit = limit; this.listener = listener; } @Override public boolean add( T t ) { boolean result = super.add( t ); if ( size() == limit ) { listener.run(); } return result; } } public class A1 { public B1 b = new B1(); } public class B1 { public int b1 = 1; public int b2 = 2; public int b3 = 3; } @Test public void testSkipHashingOfNestedProperties() { // DROOLS-870 String drl = "import " + A1.class.getCanonicalName() + "\n" + "global java.util.List list\n" + "rule One when\n" + " A1(b.b1 == 1)\n" + "then\n" + " list.add(\"1\");\n" + "end\n" + "\n" + "rule \"Two\" when\n" + " A1(b.b2 == 2)\n" + "then\n" + " list.add(\"2\");\n" + "end\n" + "\n" + "rule \"Three\" when\n" + " A1(b.b3 == 3)\n" + "then\n" + " list.add(\"3\");\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( new A1() ); ksession.fireAllRules(); assertEquals( 3, list.size() ); assertTrue( list.containsAll( asList( "1", "2", "3" ) ) ); } @Test public void testErrorReportWithWrongAccumulateFunction() { // DROOLS-872 String drl = "import " + Cheese.class.getCanonicalName() + "\n" + "rule R when\n" + " Cheese( $type : typo )\n" + " accumulate(\n" + " $c : Cheese( type == $type ),\n" + " $cheeses : collectList( $c ) );\n" + "then\n" + "end\n"; assertDrlHasCompilationError( drl, -1 ); } @Test public void testVariableMatchesField() throws Exception { // DROOLS-882 String drl = "declare RegEx\n" + " pattern : String\n" + "end\n" + "declare Fact\n" + " field : String\n" + "end\n" + "rule \"Variable matches field\"\n" + " when\n" + " Fact( $field : field )\n" + " RegEx( $field matches pattern )\n" + " then\n" + " insert(\"Matched \" + $field);\n" + "end\n" + "rule \"Boot\"\n" + " when\n" + " then\n" + " insert( new RegEx(\"foo.*\") );\n" + " insert( new Fact(\"foobar\") );\n" + " insert( new Fact(\"bar\") );\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); assertEquals( 2, ksession.fireAllRules() ); } @Test public void testEndMethod() throws Exception { // DROOLS-889 String drl = "import " + Pattern.class.getCanonicalName() + "\n" + "import " + Matcher.class.getCanonicalName() + "\n" + "global java.util.List list\n" + "rule \"Variable matches field\" when\n" + " $emailAddress :String(this matches \"^.*[_A-Za-z0-9-\\\\+]+(\\\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\\\.[A-Za-z0-9]+)*(\\\\.[A-Za-z]{2,}).*$\")\n" + "then\n" + " Pattern pattern=Pattern.compile(\"[_A-Za-z0-9-\\\\+]+(\\\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\\\.[A-Za-z0-9]+)*(\\\\.[A-Za-z]{2,})\");\n" + " Matcher matcher=pattern.matcher($emailAddress);\n" + " while(matcher.find()){\n" + " list.add($emailAddress.substring(matcher.start(),matcher.end()));\n" + " }\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( "mario.fusco@test.org" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "mario.fusco@test.org", list.get( 0 ) ); } public static class Parent { public String value; public String getValue() { return value; } public void setValue( String value ) { this.value = value; } } public static class ChildA extends Parent { } public static class ChildB extends Parent { } @Test public void testDifferentClassesWithOR() throws Exception { // DROOLS-897 String drl = "import " + ChildA.class.getCanonicalName() + "\n" + "import " + ChildB.class.getCanonicalName() + "\n" + "rule R when\n" + " (\n" + " ChildA(value == null, $entity : this) or \n" + " ChildB(value == null, $entity : this)\n" + " )\n" + "then\n" + " modify( $entity ) { setValue(\"Done!\"); }\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); ChildA childA = new ChildA(); ChildB childB = new ChildB(); ksession.insert( childA ); ksession.insert( childB ); ksession.fireAllRules(); assertEquals( "Done!", childA.getValue() ); assertEquals( "Done!", childB.getValue() ); } @Test public void testJittingCollectionCreation() { // DROOLS-900 String drl = "import " + Arrays.class.getCanonicalName() + "\n" + "global java.util.List list\n" + "rule R when\n" + " $s : String( Arrays.asList(\"a\", \"b\", \"c\").contains(this) )\n" + "then\n" + " list.add($s);\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( "a" ); ksession.insert( "d" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "a", list.get( 0 ) ); } @Test public void testJittingCollectionCreationInParenthesis() { // DROOLS-900 String drl = "import " + Arrays.class.getCanonicalName() + "\n" + "global java.util.List list\n" + "rule R when\n" + " $s : String( (Arrays.asList(\"a\", \"b\", \"c\")).contains(this) )\n" + "then\n" + " list.add($s);\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( "a" ); ksession.insert( "d" ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "a", list.get( 0 ) ); } @Test public void testBetaMemoryLeakOnFactDelete() { // DROOLS-913 String drl = "rule R1 when\n" + " $a : Integer(this == 1)\n" + " $b : String()\n" + " $c : Integer(this == 2)\n" + "then \n" + "end\n" + "rule R2 when\n" + " $a : Integer(this == 1)\n" + " $b : String()\n" + " $c : Integer(this == 3)\n" + "then \n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); FactHandle fh1 = ksession.insert( 1 ); FactHandle fh2 = ksession.insert( 3 ); FactHandle fh3 = ksession.insert( "test" ); ksession.fireAllRules(); ksession.delete( fh1 ); ksession.delete( fh2 ); ksession.delete( fh3 ); ksession.fireAllRules(); NodeMemories nodeMemories = ( (InternalWorkingMemory) ksession ).getNodeMemories(); for ( int i = 0; i < nodeMemories.length(); i++ ) { Memory memory = nodeMemories.peekNodeMemory( i ); if ( memory != null && memory.getSegmentMemory() != null ) { SegmentMemory segmentMemory = memory.getSegmentMemory(); System.out.println( memory ); LeftTuple deleteFirst = memory.getSegmentMemory().getStagedLeftTuples().getDeleteFirst(); if ( segmentMemory.getRootNode() instanceof JoinNode ) { BetaMemory bm = (BetaMemory) segmentMemory.getNodeMemories().getFirst(); assertEquals( 0, bm.getLeftTupleMemory().size() ); } System.out.println( deleteFirst ); assertNull( deleteFirst ); } } } @Test @Ignore public void testBetaMemoryLeakOnSegmentUnlinking() { // DROOLS-915 String drl = "rule R1 when\n" + " $a : Integer(this == 1)\n" + " $b : String()\n" + " $c : Integer(this == 2)\n" + " $d : Integer(this == 3)\n" + "then \n" + "end\n" + "rule R2 when\n" + " $a : Integer(this == 1)\n" + " $b : String()\n" + "then \n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); FactHandle fh1 = ksession.insert( 1 ); FactHandle fh2 = ksession.insert( 2 ); FactHandle fh3 = ksession.insert( 3 ); FactHandle fhtest = ksession.insert( "test" ); ksession.fireAllRules(); ksession.delete( fh3 ); ksession.fireAllRules(); ksession.delete( fh1 ); ksession.delete( fh2 ); ksession.delete( fhtest ); ksession.fireAllRules(); NodeMemories nodeMemories = ( (InternalWorkingMemory) ksession ).getNodeMemories(); for ( int i = 0; i < nodeMemories.length(); i++ ) { Memory memory = nodeMemories.peekNodeMemory( i ); if ( memory != null && memory.getSegmentMemory() != null ) { SegmentMemory segmentMemory = memory.getSegmentMemory(); System.out.println( memory ); LeftTuple deleteFirst = memory.getSegmentMemory().getStagedLeftTuples().getDeleteFirst(); System.out.println( deleteFirst ); assertNull( deleteFirst ); } } } @Test public void testFunctionInvokingFunction() throws Exception { // DROOLS-926 String drl = "function boolean isOdd(int i) {\n" + " return i % 2 == 1;\n" + "}\n" + "\n" + "function boolean isEven(int i) {\n" + " return !isOdd(i);\n" + "}\n" + "\n" + "global java.util.List list;\n" + "\n" + "rule R when\n" + " $i : Integer( isEven( this ) ) \n" + "then\n" + " list.add($i);\n" + "end\n"; final KieBase kbase = new KieHelper().addContent( drl, ResourceType.DRL ).build(); int parallelThreads = 10; ExecutorService executor = Executors.newFixedThreadPool( parallelThreads ); Collection<Callable<Boolean>> solvers = new ArrayList<Callable<Boolean>>(); for ( int i = 0; i < parallelThreads; ++i ) { solvers.add( new Callable<Boolean>() { @Override public Boolean call() throws Exception { KieSession ksession = kbase.newKieSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); for ( int i = 0; i < 100; i++ ) { ksession.insert( i ); } ksession.fireAllRules(); return list.size() == 50; } } ); } CompletionService<Boolean> ecs = new ExecutorCompletionService<Boolean>( executor ); for ( Callable<Boolean> s : solvers ) { ecs.submit( s ); } for ( int i = 0; i < parallelThreads; ++i ) { assertTrue( ecs.take().get() ); } } @Test public void testCompilationFailureWithNonExistingField() { // BZ-1271534 String drl = "rule R when\n" + " String( $var : lenght )\n" + "then\n" + "end\n"; assertDrlHasCompilationError( drl, 1 ); } @Test public void testKieBaseSerialization() throws Exception { // DROOLS-944 String drl = "import " + Container.class.getCanonicalName() + ";" + "rule R1 when\n" + " Container($offer : objects[\"1-CZ26IQW\"] != null)\n" + "then\n" + "end\n" + "\n" + "rule R2 when\n" + " Container($offer : objects[\"1-CZ26IR8\"] != null)\n" + "then\n" + "end\n"; KieBase kbase1 = new KieHelper().addContent( drl, ResourceType.DRL ).build(); KieBase kbase2 = SerializationHelper.serializeObject( kbase1, ( (InternalKnowledgeBase) kbase1 ).getRootClassLoader() ); assertTrue( ReteComparator.areEqual( kbase1, kbase2 ) ); } public static class Container { private Map<String, Object> objects = new HashMap<String, Object>(); public Map<String, Object> getObjects() { return objects; } public void setObjects( Map<String, Object> objects ) { this.objects = objects; } } @Test public void testPatternMatchingWithFakeImplicitCast() { // DROOLS-966 String drl = "rule R1 when\n" + " String( this == \"\\\"#\")\n" + "then \n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); ksession.insert( "\"#" ); assertEquals( 1, ksession.fireAllRules() ); } @Test public void testPatternMatchingWithFakeNullSafe() { // DROOLS-966 String drl = "rule R1 when\n" + " String( this == \"\\\"!.\")\n" + "then \n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); ksession.insert( "\"!." ); assertEquals( 1, ksession.fireAllRules() ); } @Test public void testLambdaInRHS() { checkJava8InRhs("i -> list.add(i)"); } @Test public void testMethodReferenceInRHS() { checkJava8InRhs("list::add"); } private void checkJava8InRhs(String expr) { assumeTrue(System.getProperty("java.version").startsWith( "1.8" )); // BZ-1199965 String drl = "global java.util.List list;\n" + "rule \"Example with Lambda expression\"\n" + " when\n" + " then\n" + " java.util.List<Integer> $list = java.util.Arrays.asList(1, 2, 3, 4);\n" + " $list.forEach(" + expr + ");\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<Integer> list = new ArrayList<Integer>(); ksession.setGlobal( "list", list ); ksession.fireAllRules(); assertEquals( 4, list.size() ); assertTrue( list.containsAll( Arrays.asList(1, 2, 3, 4) ) ); } @Test public void testCompareToOnInterface() { // DROOLS-1013 String drl = "import " + StringWrapper.class.getCanonicalName() + "\n" + "global java.util.List list;\n" + "rule R when\n" + " $s1 : StringWrapper()\n" + " $s2 : StringWrapper( this > $s1 )\n" + "then\n" + " list.add($s2.getWrapped());\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( new StringWrapper("aaa") ); ksession.insert( new StringWrapper("bbb") ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "bbb", list.get( 0 ) ); } @Test public void testFromEPDontRequireLeftInput() { // DROOLS-1014 String drl = "rule R when\n" + " $s1 : String() from entry-point \"xxx\"\n" + "then\n" + "end\n"; KieBase kbase = new KieHelper().addContent( drl, ResourceType.DRL ) .build(); Rete rete = ( (KnowledgeBaseImpl) kbase ).getRete(); LeftInputAdapterNode liaNode = null; for ( ObjectTypeNode otn : rete.getObjectTypeNodes() ) { Class<?> otnType = ( (ClassObjectType) otn.getObjectType() ).getClassType(); if ( String.class == otnType ) { assertEquals( 1, otn.getObjectSinkPropagator().size() ); } else if ( InitialFact.class.isAssignableFrom( otnType ) ) { assertEquals( 0, otn.getObjectSinkPropagator().size() ); } else { fail("There shouldn't be other OTNs"); } } } @Test public void testIn() { // DROOLS-1037 String drl = "import " + Person.class.getCanonicalName() + "\n" + "global java.util.List list;\n" + "rule R when\n" + " $p : Person( name == null || (name in (\"Alice\", \"Charlie\", \"David\"))==false )\n" + "then\n" + " list.add($p.getName());\n" + "end\n"; KieSession ksession = new KieHelper().addContent( drl, ResourceType.DRL ) .build() .newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( new Person("Bob") ); ksession.fireAllRules(); assertEquals( 1, list.size() ); assertEquals( "Bob", list.get( 0 ) ); } @Test public void testNonSerializableInEvaluatorWrapper() throws Exception { // BZ-1315143 String str = "package org.drools.compiler\n" + "rule B\n" + " when\n" + " $m1 : Message( $message1 : message, $date1 : birthday )\n" + " $m2 : Message( this != $m1, message != $message1, birthday after $date1 )\n" + " then\n" + "end"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write( ResourceFactory.newByteArrayResource( str.getBytes() ).setTargetPath( "org/drools/compiler/rules.drl" ) ); KieBuilder kbuilder = KieServices.Factory.get().newKieBuilder( kfs ); kbuilder.buildAll(); assertEquals( 0, kbuilder.getResults().getMessages().size() ); KieSession ksession1 = ks.newKieContainer( kbuilder.getKieModule().getReleaseId() ).newKieSession(); Message message1 = new Message(); message1.setMessage("Hello World"); message1.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("2015-12-15")); Message message2 = new Message(); message2.setMessage("Goodbye World"); message2.setBirthday(new SimpleDateFormat( "yyyy-MM-dd").parse( "2015-12-16" ) ); ksession1.insert(message1); ksession1.insert(message2); int fired1 = ksession1.fireAllRules(); assertEquals( 1, fired1 ); ksession1.dispose(); // Force deepClone KieSession ksession2 = ks.newKieContainer( kbuilder.getKieModule().getReleaseId() ).newKieSession(); Message message3 = new Message(); message3.setMessage("Hello World"); message3.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("2015-12-15")); Message message4 = new Message(); message4.setMessage("Goodbye World"); message4.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("2015-12-16")); ksession2.insert(message3); ksession2.insert(message4); int fired2 = ksession2.fireAllRules(); assertEquals( 1, fired2 ); ksession2.dispose(); } @Test public void testWrongNodeSharingWithSameHashCode() throws IllegalAccessException, InstantiationException { String drl = "import " + Person.class.getCanonicalName() + ";\n" + "rule R1 when\n" + " String()\n" + " $p: Person( name == \"ATL\", name != null)\n" + "then \n" + " $p.setHappy(true);\n" + "end\n" + "rule R2 when\n" + " String()\n" + " $p: Person( name == \"B5L\", name != null)\n" + "then \n" + " $p.setHappy(true);\n" + "end\n"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); kieSession.insert("test"); Person b5L = new Person("B5L"); kieSession.insert(b5L); assertFalse(b5L.isHappy()); kieSession.fireAllRules(); assertTrue(b5L.isHappy()); } @Test public void testWrongVariableNameWithSameDeclarationName() { // DROOLS-1064 String str = "declare Parameter end\n" + "rule R when\n" + " Parameter($b : $b == 0 )\n" + "then\n" + "end\n"; assertDrlHasCompilationError( str, -1 ); } @Test public void testComplexEvals() { // DROOLS-1139 String drl = "rule R1 when\n" + " $s : String()\n" + " Integer()\n" + " not( ( eval($s.length() < 2) and (eval(true) or eval(false))))\n" + "then \n" + "end\n"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); kieSession.insert( 42 ); kieSession.insert( "test" ); assertEquals(1, kieSession.fireAllRules()); } @Test public void testComplexEvals2() { // DROOLS-1139 String drl = "rule R1 when\n" + " $s : String()\n" + " Boolean()\n" + " $i : Integer()" + " and (eval($s.length() > 2)\n" + " or (eval(true) and eval(true)))\n" + " and (eval(true)\n" + " or ( eval($i > 2) and (eval(true))))\n\n" + "then \n" + "end\n"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); kieSession.insert( 42 ); kieSession.insert( "test" ); kieSession.insert( true ); assertEquals(4, kieSession.fireAllRules()); } @Test public void testDeletedRightTupleInChangedBucket() { // PLANNER-488 String drl = "import " + Person.class.getCanonicalName() + "\n" + "rule R when\n" + " Person( $name: name, $age: age )\n" + " not Person( happy, name == $name, age == $age-1 )\n" + "then\n" + "end"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); Person p1 = new Person( "C", 1, true ); Person p2 = new Person( "B", 1, true ); Person p3 = new Person( "B", 2, true ); Person p4 = new Person( "A", 2 ); FactHandle fh1 = kieSession.insert( p1 ); FactHandle fh2 = kieSession.insert( p2 ); FactHandle fh3 = kieSession.insert( p3 ); FactHandle fh4 = kieSession.insert( p4 ); kieSession.fireAllRules(); p4.setName( "B" ); p4.setHappy( true ); kieSession.update( fh4, p4 ); kieSession.fireAllRules(); p3.setName( "A" ); p3.setHappy( false ); kieSession.update( fh3, p3 ); p1.setName( "B" ); kieSession.update( fh1, p1 ); p2.setName( "C" ); kieSession.update( fh2, p2 ); kieSession.fireAllRules(); } @Test public void testJittingFunctionReturningAnInnerClass() { // DROOLS-1166 String drl = "import " + java.util.function.Function.class.getCanonicalName() + "\n" + "function Function<String, Integer> f() {\n" + " return new Function<String, Integer>() {\n" + " public Integer apply(String s) {\n" + " return s.length();\n" + " }\n" + " };\n" + "}\n" + "\n" + "rule R when\n" + " $s : String( f().apply(this) > 3 )\n" + "then\n" + "end\n"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); kieSession.insert( "test" ); assertEquals( 1, kieSession.fireAllRules() ); } @Test public void testQueryWithEnum() { // DROOLS-1181 String drl = "import " + AnswerGiver.class.getCanonicalName() + "\n" + "import " + Answer.class.getCanonicalName() + "\n" + "\n" + "declare TestThing end\n" + "\n" + "query TestQuery(Answer enumVal)\n" + " AnswerGiver( answer == enumVal )\n" + "end\n" + "\n" + "query MyQuery()\n" + " TestQuery(Answer.NO;)\n" + "end\n" + "\n" + "rule R when MyQuery() then end\n"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); kieSession.insert( new AnswerGiver() ); assertEquals( 0, kieSession.fireAllRules() ); } @Test public void testOrQueryWithEnum() { // DROOLS-1181 String drl = "import " + AnswerGiver.class.getCanonicalName() + "\n" + "import " + Answer.class.getCanonicalName() + "\n" + "\n" + "declare TestThing end\n" + "\n" + "query TestQuery(Answer enumVal)\n" + " AnswerGiver( answer == enumVal )\n" + "end\n" + "\n" + "query ORQuery()\n" + " (\n" + " TestQuery(Answer.YES;)\n" + " ) or (\n" + " TestQuery(Answer.YES;)\n" + " )\n" + "end\n" + "\n" + "rule R when ORQuery() then end\n"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); kieSession.insert( new AnswerGiver() ); assertEquals( 2, kieSession.fireAllRules() ); } @Test public void testModifyWithOr() { // DROOLS-1185 String drl = "import " + List.class.getCanonicalName() + "\n" + "import " + AtomicBoolean.class.getCanonicalName() + "\n" + "\n" + "rule R when\n" + " $l : List()\n" + " ( String() from $l\n" + " or\n" + " String() from $l )\n" + " $b : AtomicBoolean( get() )\n" + "then" + " modify($b) { set(false) }\n" + "end\n"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); kieSession.insert( asList("test") ); kieSession.insert( new AtomicBoolean( true ) ); assertEquals( 1, kieSession.fireAllRules() ); } @Test public void testNormalizeRuleName() { // DROOLS-1192 String drl = "rule \"rule(hello)\" when\n" + " Integer()\n" + "then\n" + "end\n"; KieSession kieSession = new KieHelper().addContent( drl, ResourceType.DRL ) .build().newKieSession(); kieSession.insert( 1 ); assertEquals( 1, kieSession.fireAllRules() ); } @Test public void testCCEAfterDeserialization() throws Exception { // DROOLS-1155 String drl = "function boolean checkLength(int length) { return true; }\n" + "rule R dialect \"mvel\" when\n" + " Boolean()" + " String( $length : length )\n" + " eval( checkLength($length) )\n" + " ( Integer( ) or eval( true ) )\n" + "then\n" + "end"; KieBase kbase1 = new KieHelper().addContent( drl, ResourceType.DRL ).build(); KieSession ksession1 = kbase1.newKieSession(); ksession1.insert( true ); ksession1.insert( "test" ); assertEquals(1, ksession1.fireAllRules()); KieBase kbase2 = SerializationHelper.serializeObject( kbase1, ( (InternalKnowledgeBase) kbase1 ).getRootClassLoader() ); KieSession ksession2 = kbase2.newKieSession(); ksession2.insert( true ); ksession2.insert( "test" ); assertEquals(1, ksession2.fireAllRules()); } @Test public void testWiringClassOnPackageMerge() throws Exception { String drl_init = "package init;\n" + "import org.kie.test.TestObject\n" + "rule RInit when\n" + "then\n" + " TestObject obj1 = new TestObject();\n" + " TestObject obj2 = new TestObject();" + " obj1.add(obj2);" + " insert(obj1);\n" + "end"; String drl1 = "package p1;\n" + "import org.kie.test.TestObject\n" + "global java.util.List list;\n" + "rule R1 when\n" + " $obj : TestObject( $objs : objects )\n" + " $s : Object() from $objs\n" + "then\n" + " list.add(\"R1\");\n" + "end"; String drl2 = "package p2;\n" + "import org.kie.test.TestObject\n" + "global java.util.List list;\n" + "rule R2 when\n" + " $obj : TestObject( $objs : objects )\n" + " $s : TestObject() from $objs\n" + "then\n" + " list.add(\"R2\");\n" + "end"; String javaSrc = "package org.kie.test;\n" + "import java.util.*;\n" + "\n" + "public class TestObject {\n" + " private final List<TestObject> objects = new ArrayList<TestObject>();\n" + "\n" + " public List<TestObject> getObjects() {\n" + " return objects;\n" + " }\n" + " public void add(TestObject obj) {\n" + " objects.add(obj);" + " }" + "}\n"; String path = "org/kie/test/MyRuleUnit"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.writeKModuleXML(ks.newKieModuleModel().toXML()) .write("src/main/resources/a.drl", drl_init) .write("src/main/resources/b.drl", drl1) .write("src/main/resources/c.drl", drl2) .write("src/main/java/org/kie/test/TestObject.java", javaSrc); ks.newKieBuilder( kfs ).buildAll(); KieContainer kcontainer = ks.newKieContainer(ks.getRepository().getDefaultReleaseId()); KieSession kSession = kcontainer.newKieSession(); List<String> list = new ArrayList<String>(); kSession.setGlobal( "list", list ); kSession.fireAllRules(); assertEquals( 2, list.size() ); assertTrue( list.contains( "R1" ) ); assertTrue( list.contains( "R2" ) ); } @Test public void testReorderRightMemoryOnIndexedField() { // DROOLS-1174 String rule = "import " + Misc2Test.Seat.class.getCanonicalName() + ";\n" + "\n" + "rule twoSameJobTypePerTable when\n" + " $job: String()\n" + " $table : Long()\n" + " not (\n" + " Seat( guestJob == $job, table == $table, $leftId : id )\n" + " and Seat( guestJob == $job, table == $table, id > $leftId )\n" + " )\n" + "then\n" + "end"; KieSession kieSession = new KieHelper().addContent(rule, ResourceType.DRL).build().newKieSession(); String doctor = "D"; String politician = "P"; Long table1 = 1L; Long table2 = 2L; Seat seat0 = new Seat(0, politician, table2); Seat seat1 = new Seat(1, politician, null); Seat seat2 = new Seat(2, politician, table2); Seat seat3 = new Seat(3, doctor, table1); Seat seat4 = new Seat(4, doctor, table1); kieSession.insert(seat0); FactHandle fh1 = kieSession.insert(seat1); FactHandle fh2 = kieSession.insert(seat2); FactHandle fh3 = kieSession.insert(seat3); kieSession.insert(seat4); kieSession.insert(politician); kieSession.insert(doctor); kieSession.insert(table1); kieSession.insert(table2); assertEquals(2, kieSession.fireAllRules()); kieSession.update(fh3, seat3); // no change but the update is necessary to reproduce the bug kieSession.update(fh2, seat2.setTable(null)); kieSession.update(fh1, seat1.setTable(table2)); assertEquals(0, kieSession.fireAllRules()); } public static class Seat { private final int id; private final String guestJob; private Long table; public Seat(int id, String guestJob, Long table) { this.id = id; this.guestJob = guestJob; this.table = table; } public String getGuestJob() { return guestJob; } public int getId() { return id; } public Long getTable() { return table; } public Seat setTable(Long table) { this.table = table; return this; } } @Test public void testChildLeftTuplesIterationOnLeftUpdate() { // DROOLS-1186 String drl = "import " + Shift.class.getCanonicalName() + "\n" + "rule R when\n" + " Shift( $end1: end, $employee: employee )\n" + " Shift( employee == $employee, start > $end1 )\n" + " not Shift( employee == $employee, start > $end1 )\n" + "then\n" + "end"; KieSession kieSession = new KieHelper().addContent(drl, ResourceType.DRL).build().newKieSession(); String o = "o"; String x = "x"; Shift shift1 = new Shift(10, 11, o); Shift shift2 = new Shift(20, 21, o); Shift shift3 = new Shift(30, 31, x); Shift shift4 = new Shift(40, 41, o); Shift shift5 = new Shift(50, 51, o); Shift shift6 = new Shift(60, 61, o); Shift shift7 = new Shift(70, 71, o); Shift shift8 = new Shift(80, 81, o); FactHandle fh1 = kieSession.insert(shift1); FactHandle fh2 = kieSession.insert(shift2); FactHandle fh3 = kieSession.insert(shift3); FactHandle fh4 = kieSession.insert(shift4); FactHandle fh5 = kieSession.insert(shift5); FactHandle fh6 = kieSession.insert(shift6); FactHandle fh7 = kieSession.insert(shift7); FactHandle fh8 = kieSession.insert(shift8); assertEquals( 0, kieSession.fireAllRules() ); kieSession.update(fh1, shift1.setEmployee(x)); kieSession.update(fh4, shift4); kieSession.update(fh8, shift8); kieSession.update(fh5, shift5.setEmployee(x)); kieSession.update(fh7, shift7); kieSession.update(fh2, shift2.setEmployee(x)); kieSession.update(fh6, shift6); kieSession.update(fh3, shift3.setEmployee(o)); assertEquals( 0, kieSession.fireAllRules() ); kieSession.update(fh8, shift8.setEmployee(x)); kieSession.update(fh4, shift4.setEmployee(x)); kieSession.update(fh7, shift7.setEmployee(x)); kieSession.update(fh6, shift6.setEmployee(x)); assertEquals( 0, kieSession.fireAllRules() ); } public static class Shift { private final int start; private final int end; private String employee; public Shift(int start, int end, String employee) { this.start = start; this.end = end; this.employee = employee; } public int getStart() { return start; } public int getEnd() { return end; } public String getEmployee() { return employee; } public Shift setEmployee(String employee) { this.employee = employee; return this; } @Override public String toString() { return "Shift " + employee + " from " + start + " to " + end; } } @Test public void test1187() { // DROOLS-1187 String drl = "import " + Misc2Test.Shift1187.class.getCanonicalName() + "\n" + "rule insertEmployeeConsecutiveWeekendAssignmentStart when\n" + " Shift1187(\n" + " weekend == true,\n" + " $employee : employee, employee != null,\n" + " $week : week\n" + " )\n" + " // The first working weekend has no working weekend before it\n" + " not Shift1187(\n" + " weekend == true,\n" + " employee == $employee,\n" + " week == ($week - 1)\n" + " )\n" + "then\n" + "end"; KieSession kieSession = new KieHelper().addContent(drl, ResourceType.DRL).build().newKieSession(); Shift1187 shift1 = new Shift1187(0, 4); Shift1187 shift2 = new Shift1187(1, 5); Shift1187 shift3 = new Shift1187(2, 6); Shift1187 shift4 = new Shift1187(2, 6); Shift1187 shift5 = new Shift1187(2, 0); Shift1187 shift6 = new Shift1187(3, 0); String employeeA = "Sarah"; String employeeB = "Susan"; String employeeC = "Fred"; shift4.setEmployee(employeeB); shift5.setEmployee(employeeA); FactHandle fh1 = kieSession.insert(shift1); FactHandle fh2 = kieSession.insert(shift2); FactHandle fh3 = kieSession.insert(shift3); FactHandle fh4 = kieSession.insert(shift4); FactHandle fh5 = kieSession.insert(shift5); FactHandle fh6 = kieSession.insert(shift6); assertEquals(2, kieSession.fireAllRules()); kieSession.update(fh6, shift6.setEmployee(employeeA)); kieSession.update(fh1, shift1.setEmployee(employeeA)); kieSession.update(fh2, shift2.setEmployee(employeeC)); assertEquals(1, kieSession.fireAllRules()); kieSession.update(fh4, shift4.setEmployee(employeeB)); kieSession.update(fh3, shift3.setEmployee(employeeB)); kieSession.update(fh5, shift5.setEmployee(employeeB)); kieSession.update(fh2, shift2.setEmployee(employeeA)); kieSession.update(fh4, shift4.setEmployee(employeeA)); kieSession.fireAllRules(); } public class Shift1187 { private final int week; private final int dayOfWeek; private String employee; public Shift1187(int week, int dayOfWeek) { this.dayOfWeek = dayOfWeek; this.week = week; } public String getEmployee() { return employee; } public Shift1187 setEmployee(String employee) { this.employee = employee; return this; } public int getWeek() { return week; } public boolean isWeekend() { if (employee == null) { return false; } return dayOfWeek == 6 || dayOfWeek == 0 || dayOfWeek == 5 && hasWeekendOnFriday(employee); } private boolean hasWeekendOnFriday(String employee) { return employee.startsWith("F"); } } @Test public void testReportFailingConstraintOnError() { // DROOLS-1071 String drl = "import " + Person.class.getCanonicalName() + "\n" + "rule R when\n" + " Person( name.startsWith(\"A\") )\n" + "then\n" + "end"; KieSession kieSession = new KieHelper().addContent(drl, ResourceType.DRL).build().newKieSession(); for (int i = 0; i < 100; i++) { kieSession.insert( new Person( "A"+i ) ); } kieSession.fireAllRules(); kieSession.insert( new Person( null ) ); try { kieSession.fireAllRules(); fail("Evaluation with null must throw a NPE"); } catch (Exception e) { assertTrue( e.getMessage().contains( "name.startsWith(\"A\")" ) ); } } public static class TestObject { private final Integer value; public TestObject(Integer value) { this.value = value; } public Integer getValue() { return value; } } @Test public void testNpeInLessThanComparison() { // RHBRMS-2462 String drl = "package com.sample\n" + "import " + TestObject.class.getCanonicalName() + ";\n" + "global java.util.List list\n" + "rule LessThanCompare when\n" + " TestObject( $value : value )" + " TestObject( value < $value )" + "then\n" + " list.add(drools.getRule().getName() + \":\" + $value);\n" + "end\n" + "\n" + "rule GreaterThanCompare when\n" + " TestObject( $value : value )\n" + " TestObject( $value > value )\n" + "then\n" + " list.add(drools.getRule().getName() + \":\" + $value);\n" + "end\n" + "\n" + "rule NotLessThanCompare when\n" + " TestObject( $value : value )" + " not ( TestObject( value < $value ) )" + "then\n" + " list.add(drools.getRule().getName() + \":\" + $value);\n" + "end\n" + "\n" + "rule NotGreaterThanCompare when\n" + " TestObject( $value : value )\n" + " not ( TestObject( $value > value ) )\n" + "then\n" + " list.add(drools.getRule().getName() + \":\" + $value);\n" + "end"; KieSession kSession = new KieHelper().addContent(drl, ResourceType.DRL).build().newKieSession(); List<String> list = new ArrayList<String>(); kSession.setGlobal( "list", list ); kSession.insert(new TestObject(null)); kSession.insert(new TestObject(5)); kSession.fireAllRules(); assertEquals( 4, list.size() ); assertTrue( list.contains( "NotLessThanCompare:5" ) ); assertTrue( list.contains( "NotLessThanCompare:null" ) ); assertTrue( list.contains( "NotGreaterThanCompare:5" ) ); assertTrue( list.contains( "NotGreaterThanCompare:null" ) ); assertFalse( list.contains( "LessThanCompare:5" ) ); assertFalse( list.contains( "LessThanCompare:null" ) ); assertFalse( list.contains( "GreaterThanCompare:5" ) ); assertFalse( list.contains( "GreaterThanCompare:null" ) ); } @Test public void testUnderscoreDoubleMultiplicationCastedToInt() { // DROOLS-1420 String str = "import org.drools.compiler.Cheese\n" + "global java.util.List list\n" + "rule R when\n" + " Cheese( $p : price)\n" + "then\n" + " int b = (int) ($p * 1_000.0);\n" + " list.add(\"\" + b);" + "end\n"; KieSession ksession = new KieHelper().addContent(str, ResourceType.DRL).build().newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( new Cheese( "gauda", 42 ) ); ksession.fireAllRules(); assertEquals(1, list.size()); assertEquals("42000", list.get(0)); } /** * This test deliberately creates a deadlock, failing the test with a timeout. * Helpful to test thread dump when a timeout occur on the JUnit listener. * See {@link org.kie.test.util.TestStatusListener#testFailure(org.junit.runner.notification.Failure)} * @throws Exception */ @Ignore("This test deliberately creates a deadlock, failing the test with a timeout.\n" + "Helpful to test thread dump when a timeout occur on the JUnit listener.\n" + "See org.kie.test.util.TestStatusListener#testFailure()") @Test(timeout=5_000L) public void testDeadlock() throws Exception { final Object see_also = org.kie.test.util.TestStatusListener.class; Object lock1 = 1L; Object lock2 = 2L; Runnable task1 = () -> { synchronized(lock1) { try { Thread.sleep(50); } catch (InterruptedException e) {} synchronized(lock2) { } } }; Runnable task2 = () -> { synchronized(lock2) { try { Thread.sleep(50); } catch (InterruptedException e) {} synchronized(lock1) { } } }; new Thread(task1).start(); task2.run(); } public static class ElementOperation { private AbstractElement element; public ElementOperation(AbstractElement element) { this.element = element; } public AbstractElement getElement() { return element; } } public static abstract class AbstractElement { } public static interface MyInterface { public void nothing(); } public static class MyElement extends AbstractElement implements MyInterface { @Override public void nothing() {} } @Test public void test01841522() { String str = "package com.sample\n" + "import " + ElementOperation.class.getCanonicalName() + ";\n" + "import " + AbstractElement.class.getCanonicalName() + ";\n" + "import " + MyInterface.class.getCanonicalName() + ";\n" + "global java.util.List list\n" + "rule R when\n" + " ElementOperation( $e : element ) \n" + " $my: MyInterface( ) from $e \n" + "then\n" + " list.add(\"\" );" + "end\n"; KieSession ksession = new KieHelper().addContent( str, ResourceType.DRL ).build().newKieSession(); List<String> list = new ArrayList<String>(); ksession.setGlobal( "list", list ); ksession.insert( new ElementOperation( new MyElement() ) ); ksession.fireAllRules(); assertEquals( 1, list.size() ); } @Test @Ignore("This test is supposed to cause a StackOverflow inside mvel but this not always happens") public void testStackOverflowInMvel() { // DROOLS-1542 String str1 = "import " + Person.class.getName() + ";\n" + "rule R1 when\n" + " $p : Person( "; StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10000; i ++) { sb.append("name == \"John-" + i + "\" || " ); } String str2 = " age == 20 )\n" + "then end\n"; String drl = str1 + sb.toString() + str2; KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newByteArrayResource( drl.getBytes() ), ResourceType.DRL ); assertTrue( kbuilder.getErrors().toString().contains( "StackOverflowError" ) ); } }