/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.compiler.integrationtests.sequential; import org.drools.compiler.Cheese; import org.drools.compiler.CommonTestMethodBase; import org.drools.compiler.Message; import org.drools.compiler.Person; import org.drools.compiler.compiler.DroolsParserException; import org.drools.compiler.integrationtests.DynamicRulesTest; import org.drools.compiler.phreak.A; import org.drools.core.util.IoUtils; import org.junit.Before; import org.junit.Test; 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.Results; import org.kie.api.event.rule.AfterMatchFiredEvent; import org.kie.api.event.rule.AgendaEventListener; import org.kie.api.event.rule.AgendaGroupPoppedEvent; import org.kie.api.event.rule.AgendaGroupPushedEvent; import org.kie.api.event.rule.BeforeMatchFiredEvent; import org.kie.api.event.rule.MatchCancelledEvent; import org.kie.api.event.rule.MatchCreatedEvent; import org.kie.api.event.rule.ObjectDeletedEvent; import org.kie.api.event.rule.ObjectInsertedEvent; import org.kie.api.event.rule.ObjectUpdatedEvent; import org.kie.api.event.rule.RuleFlowGroupActivatedEvent; import org.kie.api.event.rule.RuleFlowGroupDeactivatedEvent; import org.kie.api.event.rule.RuleRuntimeEventListener; import org.kie.api.io.ResourceType; import org.kie.api.runtime.KieContainer; import org.kie.api.runtime.StatelessKieSession; import org.kie.internal.KnowledgeBase; import org.kie.internal.KnowledgeBaseFactory; import org.kie.internal.command.CommandFactory; import org.kie.internal.conf.SequentialOption; import org.kie.internal.runtime.StatelessKnowledgeSession; import org.kie.internal.utils.KieHelper; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class SequentialTest extends CommonTestMethodBase { private KieBaseConfiguration kconf; @Before public void setup() { kconf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); kconf.setOption( SequentialOption.YES ); } @Test public void testSequentialPlusPhreakOperationComplex() throws Exception { String str = ""; str += "package org.drools.compiler.test\n"; str +="import " + A.class.getCanonicalName() + "\n"; str +="global " + List.class.getCanonicalName() + " list\n"; // Focus is done as g1, g2, g1 to demonstrate that groups will not re-activate str +="rule r0 when\n"; str +="then\n"; str +=" drools.getKnowledgeRuntime().getAgenda().getAgendaGroup( 'g1' ).setFocus();\n"; str +=" drools.getKnowledgeRuntime().getAgenda().getAgendaGroup( 'g2' ).setFocus();\n"; str +=" drools.getKnowledgeRuntime().getAgenda().getAgendaGroup( 'g1' ).setFocus();\n"; str +="end\n"; str +="rule r1 agenda-group 'g1' when\n"; str +=" a : A( object > 0 )\n"; str +="then\n"; str +=" list.add( drools.getRule().getName() );\n"; str +=" modify(a) { setObject( 3 ) };\n"; str +="end\n"; // r1_x is here to show they do not react when g2.r9 changes A o=2, // i.e. checking that re-activating g1 won't cause it to pick up previous non evaluated rules. // this is mostly checking that the no linking doesn't interfere with the expected results. str +="rule r1_x agenda-group 'g1' when\n"; str +=" a : A( object == 2 )\n"; str +="then\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; // r1_y is here to show it does not react when A is changed to o=5 in r3 str +="rule r1_y agenda-group 'g1' when\n"; str +=" a : A( object == 5 )\n"; str +="then\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; str +="rule r2 agenda-group 'g1' when\n"; str +=" a : A( object < 3 )\n"; str +="then\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; str +="rule r3 agenda-group 'g1' when\n"; str +=" a : A(object >= 3 )\n"; str +="then\n"; str +=" modify(a) { setObject( 5 ) };\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; // Checks that itself, f3 and r1_y do not react as they are higher up str +="rule r4 agenda-group 'g1' when\n"; str +=" a : A(object >= 3 )\n"; str +="then\n"; str +=" modify(a) { setObject( 5 ) };\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; // Checks that while this at one point matches, it does not match by the time g2 is entered // nor does it react when r9 changes a o=2 str +="rule r6 agenda-group 'g2' when\n"; str +=" a : A(object < 5 )\n"; str +="then\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; str +="rule r7 agenda-group 'g2' when\n"; str +=" a : A(object >= 3 )\n"; str +="then\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; str +="rule r8 agenda-group 'g2' when\n"; str +=" a : A(object >= 5 )\n"; str +="then\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; // This changes A o=2 to check if g1.r1_x incorrect reacts when g1 is re-entered str +="rule r9 agenda-group 'g2' when\n"; str +=" a : A(object >= 5 )\n"; str +="then\n"; str +=" modify(a) { setObject( 2 ) };\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString(kconf, str); StatelessKnowledgeSession ksession = createStatelessKnowledgeSession( kbase ); final List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.execute( CommandFactory.newInsertElements(Arrays.asList( new Object[]{new A(1)} )) ); assertEquals( 6, list.size() ); assertEquals( "r1", list.get(0)); assertEquals( "r3", list.get(1)); assertEquals( "r4", list.get(2)); assertEquals( "r7", list.get(3)); assertEquals( "r8", list.get(4)); assertEquals( "r9", list.get(5)); } @Test public void testSequentialPlusPhreakRevisitOriginallyEmptyGroup() throws Exception { String str = ""; str += "package org.drools.compiler.test\n"; str +="import " + A.class.getCanonicalName() + "\n"; str +="global " + List.class.getCanonicalName() + " list\n"; // Focus is done as g1, g2, g1 to demonstrate that groups will not re-activate str +="rule r0 when\n"; str +="then\n"; str +=" drools.getKnowledgeRuntime().getAgenda().getAgendaGroup( 'g1' ).setFocus();\n"; str +=" drools.getKnowledgeRuntime().getAgenda().getAgendaGroup( 'g2' ).setFocus();\n"; str +=" drools.getKnowledgeRuntime().getAgenda().getAgendaGroup( 'g1' ).setFocus();\n"; str +="end\n"; // r1_x is here to show they do not react when g2.r9 changes A o=2, // i.e. checking that re-activating g1 won't cause it to pick up previous non evaluated rules. // this is mostly checking that the none linking doesn't interfere with the expected results. // additional checks this works if g1 never had any Matches on the first visit str +="rule r1_x agenda-group 'g1' when\n"; str +=" a : A( object == 2 )\n"; str +="then\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; // This changes A o=2 to check if g1.r1_x incorrect reacts when g1 is re-entered str +="rule r9 agenda-group 'g2' when\n"; str +=" a : A(object >= 5 )\n"; str +="then\n"; str +=" modify(a) { setObject( 2 ) };\n"; str +=" list.add( drools.getRule().getName() );\n"; str +="end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString(kconf, str); StatelessKnowledgeSession ksession = createStatelessKnowledgeSession( kbase ); final List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.execute( CommandFactory.newInsertElements(Arrays.asList( new Object[]{new A(5)} )) ); assertEquals( 1, list.size() ); assertEquals( "r9", list.get(0)); } @Test public void testBasicOperation() throws Exception { KnowledgeBase kbase = loadKnowledgeBase(kconf, "simpleSequential.drl"); StatelessKnowledgeSession ksession = createStatelessKnowledgeSession( kbase ); final List list = new ArrayList(); ksession.setGlobal( "list", list ); final Person p1 = new Person( "p1", "stilton" ); final Person p2 = new Person( "p2", "cheddar" ); final Person p3 = new Person( "p3", "stilton" ); final Cheese stilton = new Cheese( "stilton", 15 ); final Cheese cheddar = new Cheese( "cheddar", 15 ); ksession.execute( CommandFactory.newInsertElements( Arrays.asList( new Object[]{p1, stilton, p2, cheddar, p3} ) ) ); assertEquals( 3, list.size() ); } @Test public void testSalience() throws Exception { KnowledgeBase kbase = loadKnowledgeBase(kconf, "simpleSalience.drl"); StatelessKnowledgeSession ksession = createStatelessKnowledgeSession( kbase ); final List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.execute( new Person( "pob") ); assertEquals( 3, list.size() ); assertEquals( "rule 3", list.get( 0 )); assertEquals( "rule 2", list.get( 1 ) ); assertEquals( "rule 1", list.get( 2 ) ); } @Test public void testKnowledgeRuntimeAccess() throws Exception { String str = ""; str += "package org.drools.compiler.test\n"; str +="import org.drools.compiler.Message\n"; str +="rule \"Hello World\"\n"; str +="when\n"; str +=" Message( )\n"; str +="then\n"; str +=" System.out.println( drools.getKieRuntime() );\n"; str +="end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString(kconf, str); StatelessKnowledgeSession ksession = createStatelessKnowledgeSession( kbase ); ksession.execute( new Message( "help" ) ); } @Test public void testEvents() throws Exception { String str = ""; str += "package org.drools.compiler.test\n"; str +="import org.drools.compiler.Message\n"; str +="rule \"Hello World\"\n"; str +="when\n"; str +=" Message( )\n"; str +="then\n"; str +=" System.out.println( drools.getKieRuntime() );\n"; str +="end\n"; KnowledgeBase kbase = loadKnowledgeBaseFromString(kconf, str); StatelessKnowledgeSession ksession = createStatelessKnowledgeSession( kbase ); final List list = new ArrayList(); ksession.addEventListener( new AgendaEventListener() { public void matchCancelled( MatchCancelledEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void matchCreated( MatchCreatedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void afterMatchFired( AfterMatchFiredEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void agendaGroupPopped( AgendaGroupPoppedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void agendaGroupPushed( AgendaGroupPushedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void beforeMatchFired( BeforeMatchFiredEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void beforeRuleFlowGroupActivated( RuleFlowGroupActivatedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void afterRuleFlowGroupActivated( RuleFlowGroupActivatedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void beforeRuleFlowGroupDeactivated( RuleFlowGroupDeactivatedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void afterRuleFlowGroupDeactivated( RuleFlowGroupDeactivatedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } } ); ksession.addEventListener( new RuleRuntimeEventListener() { public void objectInserted( ObjectInsertedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void objectDeleted( ObjectDeletedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } public void objectUpdated( ObjectUpdatedEvent event ) { assertNotNull( event.getKieRuntime() ); list.add( event ); } } ); ksession.execute( new Message( "help" ) ); assertEquals( 4, list.size() ); } // JBRULES-1567 - ArrayIndexOutOfBoundsException in sequential execution after calling RuleBase.addPackage(..) @Test public void testSequentialWithRulebaseUpdate() throws Exception { KnowledgeBase kbase = loadKnowledgeBase(kconf, "simpleSalience.drl"); StatelessKnowledgeSession ksession = createStatelessKnowledgeSession( kbase ); final List list = new ArrayList(); ksession.setGlobal( "list", list ); ksession.execute(new Person("pob")); kbase.addKnowledgePackages(loadKnowledgePackagesFromString( new String( IoUtils.readBytesFromInputStream( DynamicRulesTest.class.getResource("test_Dynamic3.drl").openStream() ) ) ) ); ksession = kbase.newStatelessKnowledgeSession(); ksession.setGlobal( "list", list ); Person person = new Person("bop"); ksession.execute(person); assertEquals( 7, list.size() ); assertEquals( "rule 3", list.get( 0 )); assertEquals( "rule 2", list.get( 1 )); assertEquals( "rule 1", list.get( 2 )); assertEquals( "rule 3", list.get( 3 ) ); assertEquals( "rule 2", list.get( 4 ) ); assertEquals( "rule 1", list.get( 5 ) ); assertEquals( person, list.get( 6 )); } @Test public void testProfileSequential() throws Exception { runTestProfileManyRulesAndFacts( true, "Sequential mode", 0, "sequentialProfile.drl" ); runTestProfileManyRulesAndFacts( true, "Sequential mode", 0, "sequentialProfile.drl" ); System.gc(); Thread.sleep( 100 ); } @Test public void testProfileRETE() throws Exception { runTestProfileManyRulesAndFacts( false, "Normal RETE mode", 0, "sequentialProfile.drl" ); runTestProfileManyRulesAndFacts( false, "Normal RETE mode", 0, "sequentialProfile.drl" ); System.gc(); Thread.sleep( 100 ); } @Test public void testNumberofIterationsSeq() throws Exception { //test throughput runTestProfileManyRulesAndFacts( true, "SEQUENTIAL", 2000, "sequentialProfile.drl" ); } @Test public void testNumberofIterationsRETE() throws Exception { //test throughput runTestProfileManyRulesAndFacts( false, "RETE", 2000, "sequentialProfile.drl" ); } @Test public void testPerfJDT() throws Exception { runTestProfileManyRulesAndFacts( true, "JDT", 2000, "sequentialProfile.drl" ); } @Test public void testPerfMVEL() throws Exception { runTestProfileManyRulesAndFacts( true, "MVEL", 2000, "sequentialProfileMVEL.drl" ); } private void runTestProfileManyRulesAndFacts(boolean sequentialMode, String message, int timetoMeasureIterations, String file) throws DroolsParserException, IOException, Exception { KieBaseConfiguration kconf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); if ( sequentialMode ) { kconf.setOption( SequentialOption.YES ); } else { kconf.setOption( SequentialOption.NO ); } KnowledgeBase kbase = loadKnowledgeBase(kconf, file); StatelessKnowledgeSession ksession = createStatelessKnowledgeSession( kbase ); final List list = new ArrayList(); ksession.setGlobal( "list", list ); Object[] data = new Object[50000]; for ( int i = 0; i < data.length; i++ ) { if ( i % 2 == 0 ) { final Person p = new Person( "p" + i, "stilton" ); data[i] = p; } else { data[i] = new Cheese( "cheddar", i ); } } if ( timetoMeasureIterations == 0 ) { //one shot measure long start = System.currentTimeMillis(); ksession.execute( CommandFactory.newInsertElements(Arrays.asList(data))); System.out.println( "Time for " + message + ":" + (System.currentTimeMillis() - start) ); assertTrue( list.size() > 0 ); } else { //lots of shots //test throughput long start = System.currentTimeMillis(); long end = start + timetoMeasureIterations; int count = 0; while ( System.currentTimeMillis() < end ) { StatelessKnowledgeSession sess2 = createStatelessKnowledgeSession( kbase ); List list2 = new ArrayList(); sess2.setGlobal( "list", list2 ); sess2.execute( CommandFactory.newInsertElements(Arrays.asList(data))); //session.execute( data ); count++; } System.out.println( "Iterations in for " + message + " : " + count ); } } @Test(timeout = 10000L) public void testSequentialWithNoLoop() throws Exception { // BZ-1228098 String str = "package org.drools.compiler.test\n" + "import \n" + Message.class.getCanonicalName() + ";" + "rule R1 no-loop when\n" + " $s : String( )" + " $m : Message( )\n" + "then\n" + " modify($m) { setMessage($s) };\n" + "end\n"; KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); kfs.write("src/main/resources/r0.drl", str); KieBuilder kieBuilder = ks.newKieBuilder( kfs ).buildAll(); Results results = kieBuilder.getResults(); if (results.hasMessages( org.kie.api.builder.Message.Level.ERROR)) { throw new RuntimeException(results.getMessages().toString()); } KieContainer kieContainer = ks.newKieContainer( ks.getRepository().getDefaultReleaseId() ); KieBaseConfiguration kieBaseConf = ks.newKieBaseConfiguration(); kieBaseConf.setOption( SequentialOption.YES ); StatelessKieSession sequentialKsession = kieContainer.newKieBase( kieBaseConf ).newStatelessKieSession(); List result = (List) sequentialKsession.execute( CommandFactory.newInsertElements(Arrays.asList("test", new Message()))); assertEquals( 2, result.size() ); StatelessKieSession ksession = kieContainer.getKieBase().newStatelessKieSession(); result = (List) ksession.execute( CommandFactory.newInsertElements(Arrays.asList("test", new Message()))); assertEquals( 2, result.size() ); } @Test public void testSharedSegment() throws Exception { // BZ-1228313 String str = "package org.drools.compiler.test\n" + "import \n" + Message.class.getCanonicalName() + ";" + "rule R1 when\n" + " $s : String()\n" + " $m : Message()\n" + " $i : Integer( this < $s.length )\n" + "then\n" + " modify($m) { setMessage($s) };\n" + "end\n" + "\n" + "rule R2 when\n" + " $s : String()\n" + " $m : Message()\n" + " $i : Integer( this > $s.length )\n" + "then\n" + "end\n"; StatelessKieSession ksession = new KieHelper().addContent( str, ResourceType.DRL ) .build( SequentialOption.YES ) .newStatelessKieSession(); ksession.execute( CommandFactory.newInsertElements(Arrays.asList("test", new Message(), 3, 5))); } }