001: package org.drools.reteoo;
002:
003: /*
004: * Copyright 2005 JBoss Inc
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
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.BetaConstraints;
029: import org.drools.common.DefaultBetaConstraints;
030: import org.drools.common.DefaultFactHandle;
031: import org.drools.common.EmptyBetaConstraints;
032: import org.drools.common.PropagationContextImpl;
033: import org.drools.rule.Rule;
034: import org.drools.spi.BetaNodeFieldConstraint;
035: import org.drools.spi.MockConstraint;
036: import org.drools.spi.PropagationContext;
037:
038: public class NotNodeTest extends DroolsTestCase {
039: Rule rule;
040: PropagationContext context;
041: ReteooWorkingMemory workingMemory;
042: MockObjectSource objectSource;
043: MockTupleSource tupleSource;
044: MockTupleSink sink;
045: NotNode node;
046: RightInputAdapterNode ria;
047: BetaMemory memory;
048: MockConstraint constraint = new MockConstraint();
049:
050: /**
051: * Setup the BetaNode used in each of the tests
052: * @throws IntrospectionException
053: */
054: public void setUp() throws IntrospectionException {
055: this .rule = new Rule("test-rule");
056: this .context = new PropagationContextImpl(0,
057: PropagationContext.ASSERTION, null, null);
058: this .workingMemory = new ReteooWorkingMemory(1,
059: (ReteooRuleBase) RuleBaseFactory.newRuleBase());
060:
061: final RuleBaseConfiguration configuration = new RuleBaseConfiguration();
062:
063: // string1Declaration is bound to pattern 3
064: this .node = new NotNode(
065: 15,
066: new MockTupleSource(5),
067: new MockObjectSource(8),
068: new DefaultBetaConstraints(
069: new BetaNodeFieldConstraint[] { this .constraint },
070: configuration));
071:
072: this .sink = new MockTupleSink();
073: this .node.addTupleSink(this .sink);
074:
075: // this.ria = new RightInputAdapterNode( 2,
076: // 0,
077: // this.node );
078: // this.ria.attach();
079: //
080: // this.sink = new MockObjectSink();
081: // this.ria.addObjectSink( this.sink );
082:
083: this .memory = (BetaMemory) this .workingMemory
084: .getNodeMemory(this .node);
085: }
086:
087: /**
088: * Test assertion with both Objects and Tuples
089: *
090: * @throws AssertionException
091: */
092: public void testNotStandard() throws FactException {
093: // assert tuple
094: final Cheese cheddar = new Cheese("cheddar", 10);
095: final DefaultFactHandle f0 = (DefaultFactHandle) this .workingMemory
096: .insert(cheddar);
097:
098: final ReteTuple tuple1 = new ReteTuple(f0);
099:
100: this .node.assertTuple(tuple1, this .context, this .workingMemory);
101:
102: // no matching objects, so should propagate
103: assertLength(1, this .sink.getAsserted());
104:
105: assertLength(0, this .sink.getRetracted());
106:
107: assertEquals(new ReteTuple(f0), ((Object[]) this .sink
108: .getAsserted().get(0))[0]);
109:
110: // assert will match, so propagated tuple should be retracted
111: final Cheese brie = new Cheese("brie", 10);
112: final DefaultFactHandle f1 = (DefaultFactHandle) this .workingMemory
113: .insert(brie);
114:
115: this .node.assertObject(f1, this .context, this .workingMemory);
116:
117: // check no as assertions, but should be one retraction
118: assertLength(1, this .sink.getAsserted());
119:
120: assertLength(1, this .sink.getRetracted());
121:
122: assertEquals(new ReteTuple(f0), ((Object[]) this .sink
123: .getRetracted().get(0))[0]);
124:
125: // assert tuple, will have matches, so no propagation
126: final DefaultFactHandle f2 = (DefaultFactHandle) this .workingMemory
127: .insert(new Cheese("gouda", 10));
128: final ReteTuple tuple2 = new ReteTuple(f2);
129: this .node.assertTuple(tuple2, this .context, this .workingMemory);
130:
131: // check no propagations
132: assertLength(1, this .sink.getAsserted());
133:
134: assertLength(1, this .sink.getRetracted());
135:
136: // check memory sizes
137: assertEquals(2, this .memory.getTupleMemory().size());
138: assertEquals(1, this .memory.getFactHandleMemory().size());
139:
140: // When this is retracter both tuples should assert
141: this .node.retractObject(f1, this .context, this .workingMemory);
142:
143: // check propagations
144: assertLength(3, this .sink.getAsserted());
145:
146: assertLength(1, this .sink.getRetracted());
147: }
148:
149: /**
150: * Test assertion with both Objects and Tuples
151: *
152: * @throws AssertionException
153: */
154: public void testNotWithConstraints() throws FactException {
155: this .constraint.isAllowed = false;
156:
157: // assert tuple
158: final Cheese cheddar = new Cheese("cheddar", 10);
159: final DefaultFactHandle f0 = (DefaultFactHandle) this .workingMemory
160: .insert(cheddar);
161:
162: final ReteTuple tuple1 = new ReteTuple(f0);
163:
164: this .node.assertTuple(tuple1, this .context, this .workingMemory);
165:
166: // no matching objects, so should propagate
167: assertLength(1, this .sink.getAsserted());
168:
169: assertLength(0, this .sink.getRetracted());
170:
171: assertEquals(new ReteTuple(f0), ((Object[]) this .sink
172: .getAsserted().get(0))[0]);
173:
174: // assert will not match, so activation should stay propagated
175: final Cheese brie = new Cheese("brie", 10);
176: final DefaultFactHandle f1 = (DefaultFactHandle) this .workingMemory
177: .insert(brie);
178:
179: this .node.assertObject(f1, this .context, this .workingMemory);
180:
181: // check no as assertions, but should be one retraction
182: assertLength(1, this .sink.getAsserted());
183:
184: assertLength(0, this .sink.getRetracted());
185:
186: // assert tuple, will have no matches, so do assert propagation
187: final DefaultFactHandle f2 = (DefaultFactHandle) this .workingMemory
188: .insert(new Cheese("gouda", 10));
189: final ReteTuple tuple2 = new ReteTuple(f2);
190: this .node.assertTuple(tuple2, this .context, this .workingMemory);
191:
192: // check no as assertions, but should be one retraction
193: assertLength(2, this .sink.getAsserted());
194:
195: assertLength(0, this .sink.getRetracted());
196: }
197:
198: /**
199: * Tests memory consistency after insert/update/retract calls
200: *
201: * @throws AssertionException
202: */
203: public void testNotMemoryManagement() throws FactException {
204: try {
205: // assert tuple
206: final Cheese cheddar = new Cheese("cheddar", 10);
207: final DefaultFactHandle f0 = (DefaultFactHandle) this .workingMemory
208: .insert(cheddar);
209: final ReteTuple tuple1 = new ReteTuple(f0);
210:
211: this .node.assertTuple(tuple1, this .context,
212: this .workingMemory);
213:
214: // assert will match, so propagated tuple should be retracted
215: final Cheese brie = new Cheese("brie", 10);
216: final DefaultFactHandle f1 = (DefaultFactHandle) this .workingMemory
217: .insert(brie);
218:
219: // Initially, no objects in right memory
220: assertEquals(0, this .memory.getFactHandleMemory().size());
221: this .node
222: .assertObject(f1, this .context, this .workingMemory);
223:
224: // Now, needs to have 1 object in right memory
225: assertEquals(1, this .memory.getFactHandleMemory().size());
226:
227: // simulate modify
228: this .node.retractObject(f1, this .context,
229: this .workingMemory);
230: this .node
231: .assertObject(f1, this .context, this .workingMemory);
232: // Memory should not change
233: assertEquals(1, this .memory.getFactHandleMemory().size());
234:
235: // When this is retracter both tuples should assert
236: this .node.retractObject(f1, this .context,
237: this .workingMemory);
238: assertEquals(0, this .memory.getFactHandleMemory().size());
239:
240: // check memory sizes
241: assertEquals(1, this .memory.getTupleMemory().size());
242:
243: // simulate modify
244: this .node.retractTuple(tuple1, this .context,
245: this .workingMemory);
246: this .node.assertTuple(tuple1, this .context,
247: this .workingMemory);
248: assertEquals(1, this .memory.getTupleMemory().size());
249: this .node.retractTuple(tuple1, this .context,
250: this .workingMemory);
251: assertEquals(0, this .memory.getTupleMemory().size());
252: } catch (final Exception e) {
253: Assert
254: .fail("No exception should be raised in this procedure, but got: "
255: + e.toString());
256: }
257: }
258:
259: public void testGetConstraints_ReturnsNullEvenWithEmptyBinder() {
260: final BetaConstraints nullConstraints = EmptyBetaConstraints
261: .getInstance();
262: final NotNode notNode = new NotNode(1, this .tupleSource,
263: this .objectSource, nullConstraints);
264: final BetaNodeFieldConstraint[] constraints = notNode
265: .getConstraints();
266: assertEquals(0, constraints.length);
267: }
268:
269: /**
270: * Test just tuple assertions
271: *
272: * @throws AssertionException
273: */
274: public void testAssertTupleSequentialMode() throws Exception {
275: RuleBaseConfiguration conf = new RuleBaseConfiguration();
276: conf.setSequential(true);
277:
278: this .workingMemory = new ReteooWorkingMemory(1,
279: (ReteooRuleBase) RuleBaseFactory.newRuleBase(conf));
280:
281: // override setup, so its working in sequential mode
282: this .node = new NotNode(
283: 15,
284: this .tupleSource,
285: this .objectSource,
286: new DefaultBetaConstraints(
287: new BetaNodeFieldConstraint[] { this .constraint },
288: conf));
289:
290: this .node.addTupleSink(this .sink);
291:
292: this .memory = (BetaMemory) this .workingMemory
293: .getNodeMemory(this .node);
294:
295: final DefaultFactHandle f0 = new DefaultFactHandle(0, "cheese");
296: final ReteTuple tuple0 = new ReteTuple(f0);
297:
298: this .node.assertObject(f0, this .context, this .workingMemory);
299:
300: // assert tuple
301: this .node.assertTuple(tuple0, this .context, this .workingMemory);
302:
303: assertEquals(0, this .sink.getAsserted().size());
304:
305: assertNull(this .memory.getTupleMemory());
306:
307: assertEquals(1, this.memory.getFactHandleMemory().size());
308:
309: }
310:
311: }
|