001: /*
002: * Copyright 2006 JBoss Inc
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.drools.reteoo;
018:
019: import java.beans.IntrospectionException;
020:
021: import junit.framework.Assert;
022:
023: import org.drools.Cheese;
024: import org.drools.DroolsTestCase;
025: import org.drools.FactException;
026: import org.drools.RuleBaseConfiguration;
027: import org.drools.RuleBaseFactory;
028: import org.drools.common.DefaultBetaConstraints;
029: import org.drools.common.DefaultFactHandle;
030: import org.drools.common.PropagationContextImpl;
031: import org.drools.rule.Rule;
032: import org.drools.spi.BetaNodeFieldConstraint;
033: import org.drools.spi.MockConstraint;
034: import org.drools.spi.PropagationContext;
035:
036: /**
037: * @author etirelli
038: *
039: */
040: public class ExistsNodeTest extends DroolsTestCase {
041: Rule rule;
042: PropagationContext context;
043: ReteooWorkingMemory workingMemory;
044: MockObjectSource objectSource;
045: MockTupleSource tupleSource;
046: MockTupleSink sink;
047: ExistsNode node;
048: RightInputAdapterNode ria;
049: BetaMemory memory;
050: MockConstraint constraint = new MockConstraint();
051:
052: /**
053: * Setup the BetaNode used in each of the tests
054: * @throws IntrospectionException
055: */
056: public void setUp() throws IntrospectionException {
057: this .rule = new Rule("test-rule");
058: this .context = new PropagationContextImpl(0,
059: PropagationContext.ASSERTION, null, null);
060: this .workingMemory = new ReteooWorkingMemory(1,
061: (ReteooRuleBase) RuleBaseFactory.newRuleBase());
062:
063: final RuleBaseConfiguration configuration = new RuleBaseConfiguration();
064:
065: // string1Declaration is bound to pattern 3
066: this .node = new ExistsNode(
067: 15,
068: new MockTupleSource(5),
069: new MockObjectSource(8),
070: new DefaultBetaConstraints(
071: new BetaNodeFieldConstraint[] { this .constraint },
072: configuration));
073:
074: this .sink = new MockTupleSink();
075: this .node.addTupleSink(this .sink);
076:
077: this .memory = (BetaMemory) this .workingMemory
078: .getNodeMemory(this .node);
079: }
080:
081: /**
082: * Test assertion with both Objects and Tuples
083: *
084: * @throws AssertionException
085: */
086: public void testExistsStandard() throws FactException {
087: // assert tuple
088: final Cheese cheddar = new Cheese("cheddar", 10);
089: final DefaultFactHandle f0 = (DefaultFactHandle) this .workingMemory
090: .insert(cheddar);
091:
092: final ReteTuple tuple1 = new ReteTuple(f0);
093:
094: this .node.assertTuple(tuple1, this .context, this .workingMemory);
095:
096: // no matching objects, so should not propagate
097: assertLength(0, this .sink.getAsserted());
098:
099: assertLength(0, this .sink.getRetracted());
100:
101: // assert will match, so should propagate
102: final Cheese brie = new Cheese("brie", 10);
103: final DefaultFactHandle f1 = (DefaultFactHandle) this .workingMemory
104: .insert(brie);
105:
106: this .node.assertObject(f1, this .context, this .workingMemory);
107:
108: // check a single assertion
109: assertLength(1, this .sink.getAsserted());
110:
111: assertLength(0, this .sink.getRetracted());
112:
113: assertEquals(new ReteTuple(f0), ((Object[]) this .sink
114: .getAsserted().get(0))[0]);
115:
116: // assert tuple, will have matches, so propagate
117: final DefaultFactHandle f2 = (DefaultFactHandle) this .workingMemory
118: .insert(new Cheese("gouda", 10));
119: final ReteTuple tuple2 = new ReteTuple(f2);
120: this .node.assertTuple(tuple2, this .context, this .workingMemory);
121:
122: // check propagations
123: assertLength(2, this .sink.getAsserted());
124:
125: assertLength(0, this .sink.getRetracted());
126:
127: // check memory sizes
128: assertEquals(2, this .memory.getTupleMemory().size());
129: assertEquals(1, this .memory.getFactHandleMemory().size());
130:
131: // When this is retracter both tuples should be retracted
132: this .node.retractObject(f1, this .context, this .workingMemory);
133:
134: // check retracts
135: assertLength(2, this .sink.getAsserted());
136:
137: assertLength(2, this .sink.getRetracted());
138: }
139:
140: /**
141: * Test assertion with both Objects and Tuples
142: *
143: * @throws AssertionException
144: */
145: public void testExistsWithConstraints() throws FactException {
146: this .constraint.isAllowed = false;
147:
148: // assert tuple
149: final Cheese cheddar = new Cheese("cheddar", 10);
150: final DefaultFactHandle f0 = (DefaultFactHandle) this .workingMemory
151: .insert(cheddar);
152:
153: final ReteTuple tuple1 = new ReteTuple(f0);
154:
155: this .node.assertTuple(tuple1, this .context, this .workingMemory);
156:
157: // no matching objects, so don't propagate
158: assertLength(0, this .sink.getAsserted());
159:
160: assertLength(0, this .sink.getRetracted());
161:
162: // assert will not match, so activation should stay propagated
163: final Cheese brie = new Cheese("brie", 10);
164: final DefaultFactHandle f1 = (DefaultFactHandle) this .workingMemory
165: .insert(brie);
166:
167: this .node.assertObject(f1, this .context, this .workingMemory);
168:
169: // no matches, so no propagations still
170: assertLength(0, this .sink.getAsserted());
171:
172: assertLength(0, this .sink.getRetracted());
173:
174: // assert tuple, will have matches, so do assert propagation
175: final DefaultFactHandle f2 = (DefaultFactHandle) this .workingMemory
176: .insert(new Cheese("gouda", 10));
177: final ReteTuple tuple2 = new ReteTuple(f2);
178: this .node.assertTuple(tuple2, this .context, this .workingMemory);
179:
180: assertLength(0, this .sink.getAsserted());
181:
182: assertLength(0, this .sink.getRetracted());
183: }
184:
185: /**
186: * Tests memory consistency after insert/update/retract calls
187: *
188: * @throws AssertionException
189: */
190: public void testExistsMemoryManagement() throws FactException {
191: try {
192: // assert tuple
193: final Cheese cheddar = new Cheese("cheddar", 10);
194: final DefaultFactHandle f0 = (DefaultFactHandle) this .workingMemory
195: .insert(cheddar);
196: final ReteTuple tuple1 = new ReteTuple(f0);
197:
198: this .node.assertTuple(tuple1, this .context,
199: this .workingMemory);
200:
201: // assert will match, so should propagate
202: final Cheese brie = new Cheese("brie", 10);
203: final DefaultFactHandle f1 = (DefaultFactHandle) this .workingMemory
204: .insert(brie);
205:
206: // Initially, no objects in right memory
207: assertEquals(0, this .memory.getFactHandleMemory().size());
208: this .node
209: .assertObject(f1, this .context, this .workingMemory);
210:
211: // Now, needs to have 1 object in right memory
212: assertEquals(1, this .memory.getFactHandleMemory().size());
213:
214: // simulate modify
215: this .node.retractObject(f1, this .context,
216: this .workingMemory);
217: this .node
218: .assertObject(f1, this .context, this .workingMemory);
219: // Memory should not change
220: assertEquals(1, this .memory.getFactHandleMemory().size());
221:
222: // When this is retracter both tuples should assert
223: this .node.retractObject(f1, this .context,
224: this .workingMemory);
225: assertEquals(0, this .memory.getFactHandleMemory().size());
226:
227: // check memory sizes
228: assertEquals(1, this .memory.getTupleMemory().size());
229:
230: // simulate modify
231: this .node.retractTuple(tuple1, this .context,
232: this .workingMemory);
233: this .node.assertTuple(tuple1, this .context,
234: this .workingMemory);
235: assertEquals(1, this .memory.getTupleMemory().size());
236: this .node.retractTuple(tuple1, this .context,
237: this .workingMemory);
238: assertEquals(0, this .memory.getTupleMemory().size());
239: } catch (final Exception e) {
240: Assert
241: .fail("No exception should be raised in this procedure, but got: "
242: + e.toString());
243: }
244: }
245:
246: }
|