/* * 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.persistence.timer.integrationtests; import static org.drools.persistence.util.PersistenceUtil.DROOLS_PERSISTENCE_UNIT_NAME; import static org.drools.persistence.util.PersistenceUtil.createEnvironment; import static org.drools.persistence.util.PersistenceUtil.setupWithPoolingDataSource; import static org.drools.persistence.util.PersistenceUtil.tearDown; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.concurrent.TimeUnit; import org.drools.core.ClockType; import org.drools.core.time.SessionPseudoClock; import org.infinispan.manager.DefaultCacheManager; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.kie.api.KieBase; import org.kie.api.KieBaseConfiguration; import org.kie.api.conf.EventProcessingOption; import org.kie.api.definition.type.FactType; import org.kie.api.io.Resource; import org.kie.api.io.ResourceType; import org.kie.api.runtime.EnvironmentName; import org.kie.api.runtime.KieSessionConfiguration; import org.kie.api.runtime.conf.ClockTypeOption; import org.kie.api.time.SessionClock; import org.kie.internal.KnowledgeBase; import org.kie.internal.KnowledgeBaseFactory; import org.kie.internal.builder.KnowledgeBuilder; import org.kie.internal.builder.KnowledgeBuilderError; import org.kie.internal.builder.KnowledgeBuilderErrors; import org.kie.internal.builder.KnowledgeBuilderFactory; import org.kie.internal.definition.KnowledgePackage; import org.kie.internal.io.ResourceFactory; import org.kie.internal.persistence.infinispan.InfinispanKnowledgeService; import org.kie.internal.runtime.StatefulKnowledgeSession; public class TimerAndCalendarTest { private DefaultCacheManager cm; @Test public void testTimerRuleAfterIntReloadSession() throws Exception { KieBaseConfiguration kbaseConf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); kbaseConf.setOption(EventProcessingOption.STREAM); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(kbaseConf); StatefulKnowledgeSession ksession = createSession( kbase ); // must advance time or it won't save. SessionPseudoClock clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 300, TimeUnit.MILLISECONDS ); // if we do not call 'ksession.fireAllRules()', this test will run successfully. ksession.fireAllRules(); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 300, TimeUnit.MILLISECONDS ); ksession = disposeAndReloadSession( ksession, kbase ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 300, TimeUnit.MILLISECONDS ); // build timer rule, if the rule is fired, the list size will increase every 500ms String timerRule = "package org.drools.test\n" + "global java.util.List list \n" + "rule TimerRule \n" + " timer (int:1000 500) \n" + "when \n" + "then \n" + " list.add(list.size()); \n" + " end"; Resource resource = ResourceFactory.newByteArrayResource(timerRule.getBytes()); Collection<KnowledgePackage> kpackages = buildKnowledgePackage( resource, ResourceType.DRL ); kbase.addKnowledgePackages( kpackages ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 10, TimeUnit.MILLISECONDS ); ksession.fireAllRules(); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 10, TimeUnit.MILLISECONDS ); ksession = disposeAndReloadSession( ksession, kbase ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 10, TimeUnit.MILLISECONDS ); List<Integer> list = Collections.synchronizedList( new ArrayList<Integer>() ); ksession.setGlobal( "list", list ); Assert.assertEquals( 0, list.size() ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 1700, TimeUnit.MILLISECONDS ); ksession.fireAllRules(); Assert.assertEquals( 1, list.size() ); ksession = disposeAndReloadSession( ksession, kbase ); ksession.setGlobal( "list", list ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 1000, TimeUnit.MILLISECONDS ); ksession.fireAllRules(); // if the rule is fired, the list size will greater than one. Assert.assertEquals( 2, list.size() ); } @Test public void testTimerRuleAfterCronReloadSession() throws Exception { KieBaseConfiguration kbaseConf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); kbaseConf.setOption(EventProcessingOption.STREAM); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(kbaseConf); StatefulKnowledgeSession ksession = createSession( kbase ); // must advance time or it won't save. SessionPseudoClock clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 300, TimeUnit.MILLISECONDS ); // if we do not call 'ksession.fireAllRules()', this test will run successfully. ksession.fireAllRules(); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 300, TimeUnit.MILLISECONDS ); ksession = disposeAndReloadSession( ksession, kbase ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 300, TimeUnit.MILLISECONDS ); // build timer rule, if the rule is fired, the list size will increase every 300ms String timerRule = "package org.drools.test\n" + "global java.util.List list \n" + "rule TimerRule \n" + " timer (cron: * * * * * ?) \n" + "when \n" + "then \n" + " list.add(list.size()); \n" + " end"; Resource resource = ResourceFactory.newByteArrayResource( timerRule.getBytes() ); Collection<KnowledgePackage> kpackages = buildKnowledgePackage( resource, ResourceType.DRL ); kbase.addKnowledgePackages( kpackages ); List<Integer> list = Collections.synchronizedList( new ArrayList<Integer>() ); ksession.setGlobal( "list", list ); ksession.setGlobal( "list", list ); clock.advanceTime( 10, TimeUnit.MILLISECONDS ); ksession.fireAllRules(); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 10, TimeUnit.MILLISECONDS ); ksession = disposeAndReloadSession( ksession, kbase ); ksession.setGlobal( "list", list ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 10, TimeUnit.SECONDS ); ksession.fireAllRules(); Assert.assertEquals( 1, list.size() ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 3, TimeUnit.SECONDS ); ksession.fireAllRules(); Assert.assertEquals( 2, list.size() ); ksession = disposeAndReloadSession( ksession, kbase ); ksession.setGlobal( "list", list ); clock = (SessionPseudoClock) ksession.<SessionClock>getSessionClock(); clock.advanceTime( 2, TimeUnit.SECONDS ); ksession.fireAllRules(); // if the rule is fired, the list size will greater than one. Assert.assertEquals( 3, list.size() ); } @Test public void testEventExpires() throws Exception { String timerRule = "package org.drools.test\n" + "declare TestEvent \n" + " @role( event )\n" + " @expires( 10s )\n" + "end\n" + "" + "rule TimerRule \n" + " when \n" + " TestEvent( ) from entry-point \"Test\"\n" + " then \n" + "end"; KieBaseConfiguration kbconf = KnowledgeBaseFactory.newKnowledgeBaseConfiguration(); kbconf.setOption( EventProcessingOption.STREAM ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( kbconf ); Resource resource = ResourceFactory.newByteArrayResource( timerRule.getBytes() ); Collection<KnowledgePackage> kpackages = buildKnowledgePackage( resource, ResourceType.DRL ); kbase.addKnowledgePackages( kpackages ); StatefulKnowledgeSession ksession = createSession( kbase ); FactType type = kbase.getFactType( "org.drools.test", "TestEvent" ); Assert.assertNotNull( "could not get type", type ); ksession = disposeAndReloadSession( ksession, kbase ); ksession.getEntryPoint( "Test" ).insert( type.newInstance() ); ksession.fireAllRules(); ksession = disposeAndReloadSession( ksession, kbase ); ksession = disposeAndReloadSession( ksession, kbase ); } private HashMap<String, Object> context; @Before public void before() throws Exception { context = setupWithPoolingDataSource(DROOLS_PERSISTENCE_UNIT_NAME); cm = (DefaultCacheManager) context.get(EnvironmentName.ENTITY_MANAGER_FACTORY); } @After public void after() throws Exception { tearDown(context); } private StatefulKnowledgeSession createSession(KieBase kbase) { final KieSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); conf.setOption( ClockTypeOption.get( ClockType.PSEUDO_CLOCK.getId() ) ); StatefulKnowledgeSession ksession = InfinispanKnowledgeService.newStatefulKnowledgeSession( kbase, conf, createEnvironment(context) ); return ksession; } private StatefulKnowledgeSession disposeAndReloadSession(StatefulKnowledgeSession ksession, KieBase kbase) { long ksessionId = ksession.getIdentifier(); ksession.dispose(); final KieSessionConfiguration conf = KnowledgeBaseFactory.newKnowledgeSessionConfiguration(); conf.setOption( ClockTypeOption.get( ClockType.PSEUDO_CLOCK.getId() ) ); StatefulKnowledgeSession newksession = InfinispanKnowledgeService.loadStatefulKnowledgeSession( ksessionId, kbase, conf, createEnvironment(context) ); return newksession; } private Collection<KnowledgePackage> buildKnowledgePackage(Resource resource, ResourceType resourceType) { KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( resource, resourceType ); KnowledgeBuilderErrors errors = kbuilder.getErrors(); if ( errors != null && errors.size() > 0 ) { for ( KnowledgeBuilderError error : errors ) { System.err.println( "Error: " + error.getMessage() ); } Assert.fail( "KnowledgeBase did not build" ); } Collection<KnowledgePackage> packages = kbuilder.getKnowledgePackages(); return packages; } }