package org.drools.reteoo;
/*
* Copyright 2005 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.
*/
import org.drools.DroolsTestCase;
import org.drools.FactException;
import org.drools.RuleBaseFactory;
import org.drools.common.DefaultFactHandle;
import org.drools.common.InternalWorkingMemory;
import org.drools.common.PropagationContextImpl;
import org.drools.reteoo.EvalConditionNode.EvalMemory;
import org.drools.reteoo.builder.BuildContext;
import org.drools.spi.PropagationContext;
public class EvalConditionNodeTest extends DroolsTestCase {
private PropagationContext context;
private ReteooWorkingMemory workingMemory;
private ReteooRuleBase ruleBase;
private BuildContext buildContext;
public EvalConditionNodeTest(final String name) {
super( name );
}
public void setUp() {
this.ruleBase = ( ReteooRuleBase ) RuleBaseFactory.newRuleBase();
this.buildContext = new BuildContext( ruleBase, ((ReteooRuleBase)ruleBase).getReteooBuilder().getIdGenerator() );
this.context = new PropagationContextImpl( 0,
PropagationContext.ASSERTION,
null,
null,
null );
this.workingMemory = ( ReteooWorkingMemory ) this.ruleBase.newStatefulSession();
}
public void testAttach() throws Exception {
final MockTupleSource source = new MockTupleSource( 12 );
final EvalConditionNode node = new EvalConditionNode( 18,
source,
new MockEvalCondition( true ),
buildContext );
assertEquals( 18,
node.getId() );
assertEquals( 0,
source.getAttached() );
node.attach();
assertEquals( 1,
source.getAttached() );
}
public void testMemory() {
final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
(ReteooRuleBase) RuleBaseFactory.newRuleBase() );
final MockTupleSource source = new MockTupleSource( 12 );
final EvalConditionNode node = new EvalConditionNode( 18,
source,
new MockEvalCondition( true ),
buildContext );
final EvalMemory memory = (EvalMemory) workingMemory.getNodeMemory( node );
assertNotNull( memory.tupleMemory );
}
/**
* If a eval allows an incoming Object, then the Object MUST be
* propagated. This tests that the memory is updated
*
* @throws FactException
*/
public void testAssertedAllowed() throws FactException {
final MockEvalCondition eval = new MockEvalCondition( true );
// Create a test node that always returns false
final EvalConditionNode node = new EvalConditionNode( 1,
new MockTupleSource( 15 ),
eval,
buildContext );
final MockLeftTupleSink sink = new MockLeftTupleSink();
node.addTupleSink( sink );
// Create the Tuple
final DefaultFactHandle f0 = new DefaultFactHandle( 0,
"stilton" );
final LeftTuple tuple0 = new LeftTuple( f0, sink,
true );
// Tuple should pass and propagate
node.assertLeftTuple( tuple0,
this.context,
this.workingMemory );
// Create the Tuple
final DefaultFactHandle f1 = new DefaultFactHandle( 1,
"cheddar" );
final LeftTuple tuple1 = new LeftTuple( f1, sink,
true );
// Tuple should pass and propagate
node.assertLeftTuple( tuple1,
this.context,
this.workingMemory );
// Check memory was populated
final EvalMemory memory = (EvalMemory) this.workingMemory.getNodeMemory( node );
assertEquals( 2,
memory.tupleMemory.size() );
assertTrue( memory.tupleMemory.contains( tuple0 ) );
assertTrue( memory.tupleMemory.contains( tuple1 ) );
// make sure assertions were propagated
assertEquals( 2,
sink.getAsserted().size() );
}
public void testAssertedAllowedThenRetract() throws FactException {
final MockEvalCondition eval = new MockEvalCondition( true );
// Create a test node that always returns false
final EvalConditionNode node = new EvalConditionNode( 1,
new MockTupleSource( 15 ),
eval,
buildContext );
final MockLeftTupleSink sink = new MockLeftTupleSink();
node.addTupleSink( sink );
// Create the Tuple
final DefaultFactHandle f0 = new DefaultFactHandle( 0,
"stilton" );
final LeftTuple tuple0 = new LeftTuple( f0, sink,
true );
// Tuple should pass and propagate
node.assertLeftTuple( tuple0,
this.context,
this.workingMemory );
// we create and retract two tuples, checking the linkedtuples is null for JBRULES-246 "NPE on retract()"
// Create the Tuple
final DefaultFactHandle f1 = new DefaultFactHandle( 1,
"cheddar" );
final LeftTuple tuple1 = new LeftTuple( f1, sink,
true );
// Tuple should pass and propagate
node.assertLeftTuple( tuple1,
this.context,
this.workingMemory );
// Check memory was populated
final EvalMemory memory = (EvalMemory) this.workingMemory.getNodeMemory( node );
assertEquals( 2,
memory.tupleMemory.size() );
assertTrue( memory.tupleMemory.contains( tuple0 ) );
assertTrue( memory.tupleMemory.contains( tuple1 ) );
// make sure assertions were propagated
assertEquals( 2,
sink.getAsserted().size() );
// Now test that the fact is retracted correctly
node.retractLeftTuple( tuple0,
this.context,
this.workingMemory );
// Now test that the fact is retracted correctly
assertEquals( 1,
memory.tupleMemory.size() );
assertTrue( memory.tupleMemory.contains( tuple1 ) );
// make sure retractions were propagated
assertEquals( 1,
sink.getRetracted().size() );
// Now test that the fact is retracted correctly
node.retractLeftTuple( tuple1,
this.context,
this.workingMemory );
// Now test that the fact is retracted correctly
assertEquals( 0,
memory.tupleMemory.size() );
// make sure retractions were propagated
assertEquals( 2,
sink.getRetracted().size() );
}
public void testAssertedNotAllowed() throws FactException {
final MockEvalCondition eval = new MockEvalCondition( false );
// Create a test node that always returns false
final EvalConditionNode node = new EvalConditionNode( 1,
new MockTupleSource( 15 ),
eval,
buildContext );
final MockLeftTupleSink sink = new MockLeftTupleSink();
node.addTupleSink( sink );
// Create the Tuple
final DefaultFactHandle f0 = new DefaultFactHandle( 0,
"stilton" );
final LeftTuple tuple0 = new LeftTuple( f0, sink,
true );
// Tuple should fail and not propagate
node.assertLeftTuple( tuple0,
this.context,
this.workingMemory );
// Create the Tuple
final DefaultFactHandle f1 = new DefaultFactHandle( 1,
"cheddar" );
final LeftTuple tuple1 = new LeftTuple( f1, sink,
true );
// Tuple should fail and not propagate
node.assertLeftTuple( tuple1,
this.context,
this.workingMemory );
// Check memory was not populated
final EvalMemory memory = (EvalMemory) this.workingMemory.getNodeMemory( node );
assertEquals( 0,
memory.tupleMemory.size() );
// test no propagations
assertEquals( 0,
sink.getAsserted().size() );
assertEquals( 0,
sink.getRetracted().size() );
}
public void testUpdateWithMemory() throws FactException {
// If no child nodes have children then we need to re-process the left
// and right memories
// as a joinnode does not store the resulting tuples
final ReteooWorkingMemory workingMemory = new ReteooWorkingMemory( 1,
(ReteooRuleBase) RuleBaseFactory.newRuleBase() );
// Creat the object source so we can detect the alphaNode telling it to
// propate its contents
//final MockTupleSource source = new MockTupleSource( 1 );
/* Create a test node that always returns true */
final EvalConditionNode node = new EvalConditionNode( 1,
new MockTupleSource( 15 ),
new MockEvalCondition( true ),
buildContext );
// Add the first tuple sink and assert a tuple and object
// The sink has no memory
final MockLeftTupleSink sink1 = new MockLeftTupleSink( 2 );
node.addTupleSink( sink1 );
final DefaultFactHandle f0 = new DefaultFactHandle( 0,
"string0" );
final LeftTuple tuple1 = new LeftTuple( f0, sink1,
true );
node.assertLeftTuple( tuple1,
this.context,
workingMemory );
assertLength( 1,
sink1.getAsserted() );
// Add the new sink, this should be updated from the re-processed
// joinnode memory
final MockLeftTupleSink sink2 = new MockLeftTupleSink( 3 );
node.addTupleSink( sink2 );
assertLength( 0,
sink2.getAsserted() );
node.updateSink( sink2,
this.context,
workingMemory );
assertLength( 1,
sink2.getAsserted() );
}
/**
* If a eval allows an incoming Object, then the Object MUST be
* propagated. This tests that the memory is updated
*
* @throws FactException
*/
public void testDoRemove() throws FactException {
final MockEvalCondition eval = new MockEvalCondition( true );
final EvalConditionNode parent = new EvalConditionNode( 1,
new MockTupleSource( 15 ),
eval,
buildContext );
// Create a test node that always returns false
final EvalConditionNode node = new EvalConditionNode( 2,
parent,
eval,
buildContext );
parent.addTupleSink( node );
final MockLeftTupleSink sink = new MockLeftTupleSink();
node.addTupleSink( sink );
// Create the Tuple
final DefaultFactHandle f0 = new DefaultFactHandle( 0,
"stilton" );
final LeftTuple tuple0 = new LeftTuple( f0, sink,
true );
// Tuple should pass and propagate
node.assertLeftTuple( tuple0,
this.context,
this.workingMemory );
// Check memory was populated
EvalMemory memory = (EvalMemory) this.workingMemory.getNodeMemory( node );
assertEquals( 1,
memory.tupleMemory.size() );
assertTrue( memory.tupleMemory.contains( tuple0 ) );
// make sure assertions were propagated
assertEquals( 1,
sink.getAsserted().size() );
RuleRemovalContext removalContext = new RuleRemovalContext();
InternalWorkingMemory[] workingMemories = new InternalWorkingMemory[] { this.workingMemory};
// This use to throw ClassCastException JBRULES-1719
node.remove( removalContext, this.ruleBase.getReteooBuilder(), sink, workingMemories);
memory = (EvalMemory) this.workingMemory.getNodeMemory( node );
assertEquals( 0,
memory.tupleMemory.size() );
assertFalse( memory.tupleMemory.contains( tuple0 ) );
}
}