/**
* Copyright 2010 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.
*/
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 static org.mockito.Mockito.mock;
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.definition.rule.Rule;
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 );
}
/**
* 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 );
// 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 );
// 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 );
// 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 );
// 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
this.workingMemory.getNodeMemory( node );
// test no propagations
assertEquals( 0,
sink.getAsserted().size() );
assertEquals( 0,
sink.getRetracted().size() );
}
/**
* 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" );
// an eval node always has at least a LIAN before it, so, tuples that reach it
// always have at least one tuple parent
final LeftTuple parentTuple = new LeftTuple( f0,
null,
true );
final LeftTuple tuple0 = new LeftTuple( parentTuple,
sink,
true );
// Tuple should pass and propagate
node.assertLeftTuple( tuple0,
this.context,
this.workingMemory );
// make sure assertions were propagated
assertEquals( 1,
sink.getAsserted().size() );
RuleRemovalContext removalContext = new RuleRemovalContext( mock( Rule.class ));
InternalWorkingMemory[] workingMemories = new InternalWorkingMemory[]{this.workingMemory};
// This use to throw ClassCastException JBRULES-1719
node.remove( removalContext,
this.ruleBase.getReteooBuilder(),
sink,
workingMemories );
}
}