/* * Copyright 2008 JBoss Inc * * 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. * * Created on Feb 5, 2008 */ package org.drools.integrationtests; import java.io.InputStreamReader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.Vector; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; import junit.framework.TestCase; import org.drools.Cheese; import org.drools.Child; import org.drools.GrandParent; import org.drools.KnowledgeBase; import org.drools.KnowledgeBaseConfiguration; import org.drools.KnowledgeBaseFactory; import org.drools.Order; import org.drools.Parent; import org.drools.RuleBase; import org.drools.RuleBaseFactory; import org.drools.StatefulSession; import org.drools.StatelessSession; import org.drools.StockTick; import org.drools.builder.KnowledgeBuilder; import org.drools.builder.KnowledgeBuilderFactory; import org.drools.builder.ResourceType; import org.drools.compiler.DroolsParserException; import org.drools.compiler.PackageBuilder; import org.drools.conf.EventProcessingOption; import org.drools.event.rule.AgendaEventListener; import org.drools.event.rule.ObjectRetractedEvent; import org.drools.event.rule.WorkingMemoryEventListener; import org.drools.io.ResourceFactory; import org.drools.rule.Package; import org.drools.runtime.StatefulKnowledgeSession; import org.drools.runtime.rule.WorkingMemoryEntryPoint; import org.mockito.Mockito; import static org.mockito.Mockito.*; /** * This is a test case for multi-thred issues * * @author etirelli */ public class MultithreadTest extends TestCase { public void test() { } // FIXME // /** // * @inheritDoc // * // * @see junit.framework.TestCase#setUp() // */ // protected void setUp() throws Exception { // super.setUp(); // } // // /** // * @inheritDoc // * // * @see junit.framework.TestCase#tearDown() // */ // protected void tearDown() throws Exception { // super.tearDown(); // } // // public void testRuleBaseConcurrentCompilation() { // final int THREAD_COUNT = 30; // try { // boolean success = true; // final PackageBuilder builder = new PackageBuilder(); // builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_MultithreadRulebaseSharing.drl" ) ) ); // RuleBase ruleBase = RuleBaseFactory.newRuleBase(); // ruleBase.addPackage( builder.getPackage() ); // ruleBase = SerializationHelper.serializeObject( ruleBase ); // final Thread[] t = new Thread[THREAD_COUNT]; // final RulebaseRunner[] r = new RulebaseRunner[THREAD_COUNT]; // for ( int i = 0; i < t.length; i++ ) { // r[i] = new RulebaseRunner( i, // ruleBase ); // t[i] = new Thread( r[i], // "thread-" + i ); // t[i].start(); // } // for ( int i = 0; i < t.length; i++ ) { // t[i].join(); // if ( r[i].getStatus() == RulebaseRunner.Status.FAIL ) { // success = false; // } // } // if ( !success ) { // fail( "Multithread test failed. Look at the stack traces for details. " ); // } // } catch ( Exception e ) { // e.printStackTrace(); // fail( "Should not raise any exception: " + e.getMessage() ); // } // } // // public static class RulebaseRunner // implements // Runnable { // // private static final int ITERATIONS = 300; // private final int id; // private final RuleBase rulebase; // private Status status; // // public RulebaseRunner(final int id, // final RuleBase rulebase) { // this.id = id; // this.rulebase = rulebase; // this.status = Status.SUCCESS; // } // // public void run() { // try { // StatefulSession session2 = this.rulebase.newStatefulSession(); // // for ( int k = 0; k < ITERATIONS; k++ ) { // GrandParent gp = new GrandParent( "bob" ); // Parent parent = new Parent( "mark" ); // parent.setGrandParent( gp ); // // Child child = new Child( "mike" ); // child.setParent( parent ); // // session2.insert( gp ); // session2.insert( parent ); // session2.insert( child ); // } // // session2.fireAllRules(); // session2.dispose(); // // } catch ( Exception e ) { // this.status = Status.FAIL; // System.out.println( Thread.currentThread().getName() + " failed: " + e.getMessage() ); // e.printStackTrace(); // } // } // // public static enum Status { // SUCCESS, FAIL // } // // /** // * @return the id // */ // public int getId() { // return id; // } // // /** // * @return the status // */ // public Status getStatus() { // return status; // } // // } // // public void testExpectedFires() { // try { // final PackageBuilder packageBuilder = new PackageBuilder(); // packageBuilder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_MultithreadFiringCheck.drl" ) ) ); // final RuleBase ruleBase = RuleBaseFactory.newRuleBase(); // ruleBase.addPackage( packageBuilder.getPackage() ); // final Queue errorList = new ConcurrentLinkedQueue(); // final Thread t[] = new Thread[50]; // for ( int i = 0; i < t.length; i++ ) { // final int count = i; // t[i] = new Thread( new Runnable() { // public void run() { // try { // final int iterations = count * 15 + 3000; // final List results = new ArrayList(); // final StatefulSession session2 = ruleBase.newStatefulSession(); // session2.setGlobal( "results", // results ); // session2.insert( new Integer( -1 ) ); // for ( int k = 0; k < iterations; k++ ) { // session2.insert( new Integer( k ) ); // if ( k + 1 != session2.getAgenda().agendaSize() ) { // errorList.add( "THREAD-" + count + " ERROR: expected agenda size=" + (k + 1) + " but was " + session2.getAgenda().agendaSize() ); // } // } // session2.fireAllRules(); // session2.dispose(); // if ( results.size() != iterations ) { // errorList.add( "THREAD-" + count + " ERROR: expected fire count=" + iterations + " but was " + results.size() ); // } // } catch ( Exception e ) { // errorList.add( "THREAD-" + count + " EXCEPTION: " + e.getMessage() ); // e.printStackTrace(); // } // } // } ); // t[i].start(); // } // for ( int i = 0; i < t.length; i++ ) { // t[i].join(); // } // assertTrue( "Errors during execution: " + errorList.toString(), // errorList.isEmpty() ); // } catch ( Exception e ) { // e.printStackTrace(); // fail( "No exception should have been raised: " + e.getMessage() ); // } // } // // public void testMultithreadDateStringConstraints() { // try { // final int THREAD_COUNT = 10; // final PackageBuilder packageBuilder = new PackageBuilder(); // packageBuilder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_MultithreadDateStringConstraints.drl" ) ) ); // final RuleBase ruleBase = RuleBaseFactory.newRuleBase(); // ruleBase.addPackage( packageBuilder.getPackage() ); // final Vector errors = new Vector(); // // final Thread t[] = new Thread[THREAD_COUNT]; // for ( int j = 0; j < 10; j++ ) { // for ( int i = 0; i < t.length; i++ ) { // t[i] = new Thread() { // public void run() { // try { // final int ITERATIONS = 300; // StatefulSession session = ruleBase.newStatefulSession(); // List results = new ArrayList(); // session.setGlobal( "results", // results ); // for ( int k = 0; k < ITERATIONS; k++ ) { // session.insert( new Order() ); // } // session.fireAllRules(); // session.dispose(); // if ( results.size() != ITERATIONS ) { // errors.add( "Rules did not fired correctly. Expected: " + ITERATIONS + ". Actual: " + results.size() ); // } // } catch ( Exception ex ) { // ex.printStackTrace(); // errors.add( ex ); // } // } // // }; // t[i].start(); // } // for ( int i = 0; i < t.length; i++ ) { // t[i].join(); // } // } // if ( !errors.isEmpty() ) { // fail( " Errors occured during execution " ); // } // } catch ( Exception e ) { // e.printStackTrace(); // fail( "Should not raise exception" ); // } // } // // class Runner // implements // Runnable { // private final long TIME_SPAN; // private final StatelessSession session; // private final AtomicInteger count; // // public Runner(long BASE_TIME, // StatelessSession session, // final AtomicInteger count) { // this.TIME_SPAN = BASE_TIME; // this.session = session; // this.count = count; // } // // public void run() { // //System.out.println( Thread.currentThread().getName() + " starting..." ); // try { // count.incrementAndGet(); // long time = System.currentTimeMillis(); // while ( (System.currentTimeMillis() - time) < TIME_SPAN ) { // //System.out.println( Thread.currentThread().getName() + ": added package at " + (System.currentTimeMillis() - time) ); // for ( int j = 0; j < 100; j++ ) { // session.execute( getFacts() ); // } // //System.out.println( Thread.currentThread().getName() + ": executed rules at " + (System.currentTimeMillis() - time) ); // } // } catch ( Exception ex ) { // ex.printStackTrace(); // } // if ( count.decrementAndGet() == 0 ) { // synchronized ( MultithreadTest.this ) { // MultithreadTest.this.notifyAll(); // } // } // //System.out.println( Thread.currentThread().getName() + " exiting..." ); // } // // private Cheese[] getFacts() { // final int SIZE = 100; // Cheese[] facts = new Cheese[SIZE]; // // for ( int i = 0; i < facts.length; i++ ) { // facts[i] = new Cheese(); // facts[i].setPrice( i ); // facts[i].setOldPrice( i ); // } // return facts; // } // } // // public void testSharedPackagesThreadDeadLock() throws Exception { // final int THREADS = Integer.parseInt( System.getProperty( "test.threads", // "10" ) ); // final long BASE_TIME = Integer.parseInt( System.getProperty( "test.time", // "15" ) ) * 1000; // // final AtomicInteger count = new AtomicInteger( 0 ); // // final Package[] pkgs = buildPackages(); // for ( int i = 0; i < THREADS; i++ ) { // RuleBase ruleBase = createRuleBase( pkgs ); // StatelessSession session = createSession( ruleBase ); // new Thread( new Runner( BASE_TIME, // session, // count ) ).start(); // } // synchronized ( this ) { // wait(); // } // } // // private RuleBase createRuleBase(Package[] pkgs) { // RuleBase ruleBase = RuleBaseFactory.newRuleBase(); // for ( Package pkg : pkgs ) { // ruleBase.addPackage( pkg ); // } // return ruleBase; // } // // private StatelessSession createSession(RuleBase ruleBase) { // StatelessSession session = ruleBase.newStatelessSession(); // return session; // } // // private Package[] buildPackages() throws Exception { // final String KEY = "REPLACE"; // final int SIZE = 100; // final Package[] pkgs = new Package[SIZE]; // final String DRL = "package org.drools\n" + " no-loop true\n" + " dialect \"java\"\n" + "rule \"" + KEY + "\"\n" + "salience 1\n" + "when\n" + " $fact:Cheese(price == " + KEY + ", oldPrice not in (11,5))\n" + // thread-lock // "then\n" + " //$fact.excludeProduct(" + KEY + ", 1, null, null);\n" + "end\n"; // System.out.print( "Building " + pkgs.length + " packages" ); // for ( int i = 0; i < pkgs.length; i++ ) { // pkgs[i] = getPackage( DRL.replaceAll( KEY, // Integer.toString( i ) ) ); // System.out.print( "." ); // } // System.out.println(); // return pkgs; // } // // private static Package getPackage(String drl) throws Exception { // PackageBuilder pkgBuilder = new PackageBuilder(); // pkgBuilder.addPackageFromDrl( new StringReader( drl ) ); // if ( pkgBuilder.hasErrors() ) { // StringBuilder sb = new StringBuilder(); // for ( Object obj : pkgBuilder.getErrors() ) { // if ( sb.length() > 0 ) { // sb.append( '\n' ); // } // sb.append( obj ); // } // throw new DroolsParserException( sb.toString() ); // } // return pkgBuilder.getPackage(); // } // // public void testEventExpiration() { // String rule = // "package org.drools\n" + // "declare StockTick @role(event) @expires(0s) end\n" + // "rule test no-loop true\n" + // "when\n" + // " $f : StockTick() from entry-point EntryPoint\n" + // "then\n" + // " //System.out.println($f);\n" + // "end"; // // final StatefulKnowledgeSession session; // final WorkingMemoryEntryPoint entryPoint; // // KnowledgeBaseConfiguration kbaseConf = KnowledgeBaseFactory // .newKnowledgeBaseConfiguration(); // kbaseConf.setOption(EventProcessingOption.STREAM); // // KnowledgeBuilder builder = KnowledgeBuilderFactory // .newKnowledgeBuilder(); // // builder.add(ResourceFactory.newReaderResource(new StringReader(rule)), // ResourceType.DRL); // // if (builder.hasErrors()) { // throw new RuntimeException(builder.getErrors().toString()); // } // // final KnowledgeBase knowledgeBase = KnowledgeBaseFactory // .newKnowledgeBase(kbaseConf); // // knowledgeBase.addKnowledgePackages(builder.getKnowledgePackages()); // // session = knowledgeBase.newStatefulKnowledgeSession(); // WorkingMemoryEventListener wmel = Mockito.mock( WorkingMemoryEventListener.class ); // session.addEventListener( wmel ); // // entryPoint = session // .getWorkingMemoryEntryPoint("EntryPoint"); // // new Thread(new Runnable() { // public void run() { // session.fireUntilHalt(); // } // }).start(); // // for (int x = 0; x < 10000; x++) { // entryPoint.insert(new StockTick(x, "RHT", 10, 10+x)); // Thread.yield(); // } // // session.halt(); // session.fireAllRules(); // // // facts are being expired // verify( wmel, atLeastOnce() ).objectRetracted( any( ObjectRetractedEvent.class ) ); // } }