1 |
| package org.drools.smf; |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| |
16 |
| |
17 |
| |
18 |
| |
19 |
| |
20 |
| |
21 |
| |
22 |
| |
23 |
| |
24 |
| |
25 |
| |
26 |
| |
27 |
| |
28 |
| |
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| |
37 |
| |
38 |
| |
39 |
| |
40 |
| |
41 |
| |
42 |
| |
43 |
| import java.io.BufferedReader; |
44 |
| import java.io.InputStreamReader; |
45 |
| import java.net.URL; |
46 |
| import java.util.ArrayList; |
47 |
| import java.util.HashMap; |
48 |
| import java.util.HashSet; |
49 |
| import java.util.List; |
50 |
| import java.util.Map; |
51 |
| import java.util.Set; |
52 |
| |
53 |
| import junit.framework.TestCase; |
54 |
| |
55 |
| import org.drools.MockWorkingMemory; |
56 |
| import org.drools.WorkingMemory; |
57 |
| import org.drools.rule.Declaration; |
58 |
| import org.drools.rule.Rule; |
59 |
| import org.drools.rule.RuleSet; |
60 |
| import org.drools.spi.Condition; |
61 |
| import org.drools.spi.ConditionException; |
62 |
| import org.drools.spi.Consequence; |
63 |
| import org.drools.spi.ConsequenceException; |
64 |
| import org.drools.spi.Importer; |
65 |
| import org.drools.spi.MockTuple; |
66 |
| import org.drools.spi.ObjectType; |
67 |
| import org.drools.spi.RuleBaseContext; |
68 |
| import org.drools.spi.Tuple; |
69 |
| |
70 |
| |
71 |
| |
72 |
| |
73 |
| |
74 |
| |
75 |
| |
76 |
| |
77 |
| |
78 |
| |
79 |
| |
80 |
| |
81 |
| |
82 |
| |
83 |
| |
84 |
| |
85 |
| |
86 |
| |
87 |
| |
88 |
| |
89 |
| public abstract class SMFTestFrameWork extends TestCase |
90 |
| { |
91 |
| |
92 |
| private List tests; |
93 |
| |
94 |
| |
95 |
| private String testType; |
96 |
| |
97 |
| |
98 |
| private SemanticModule module; |
99 |
| |
100 |
| |
101 |
| private SemanticsRepository repository; |
102 |
| |
103 |
| private String newline = System.getProperty( "line.separator" ); |
104 |
| |
105 |
| private Importer importer; |
106 |
| |
107 |
| private RuleBaseContext ruleBaseContext; |
108 |
| |
109 |
6
| public SMFTestFrameWork(String name)
|
110 |
| { |
111 |
6
| super( name );
|
112 |
| |
113 |
6
| this.testType = name.substring( 4 ).toLowerCase( );
|
114 |
| } |
115 |
| |
116 |
| |
117 |
| |
118 |
| |
119 |
| |
120 |
6
| public void setUp(String semantic,
|
121 |
| Importer importer) throws Exception |
122 |
| { |
123 |
6
| if ( !"conditions".equals( testType ) && !"consequences".equals( testType ) )
|
124 |
| { |
125 |
0
| return;
|
126 |
| } |
127 |
| |
128 |
6
| ClassLoader cl = Thread.currentThread( ).getContextClassLoader( );
|
129 |
6
| URL semanticTests = cl.getResource( "data/" + semantic + "-" + testType + ".data" );
|
130 |
6
| BufferedReader in = new BufferedReader( new InputStreamReader( semanticTests.openStream( ) ) );
|
131 |
6
| StringBuffer buffer = new StringBuffer( );
|
132 |
6
| String blockMarker = "<!--drools-test--!>";
|
133 |
6
| String line;
|
134 |
6
| tests = new ArrayList( );
|
135 |
6
| while ( in.ready( ) )
|
136 |
| { |
137 |
253
| line = in.readLine( ) + newline;
|
138 |
253
| if ( line.startsWith( blockMarker ) )
|
139 |
| { |
140 |
81
| tests.add( buffer.toString( ) );
|
141 |
81
| buffer = new StringBuffer( );
|
142 |
| } |
143 |
| else |
144 |
| { |
145 |
172
| buffer.append( line );
|
146 |
| } |
147 |
| } |
148 |
6
| tests.add( buffer.toString( ) );
|
149 |
| |
150 |
6
| this.repository = DefaultSemanticsRepository.getInstance( );
|
151 |
6
| module = this.repository.lookupSemanticModule( "http://drools.org/semantics/" + semantic );
|
152 |
| |
153 |
6
| this.importer = importer;
|
154 |
| |
155 |
6
| this.ruleBaseContext = new RuleBaseContext( );
|
156 |
| |
157 |
| } |
158 |
| |
159 |
| |
160 |
| |
161 |
| |
162 |
3
| public void testConditions() throws Exception
|
163 |
| { |
164 |
| |
165 |
3
| int testNumber = 0;
|
166 |
3
| MockTuple tuple;
|
167 |
| |
168 |
3
| DefaultConfiguration cheeseConfiguration = new DefaultConfiguration( "test1" );
|
169 |
3
| cheeseConfiguration.setText( Cheese.class.getName( ) );
|
170 |
3
| ObjectTypeFactory objectTypeFactory = module.getObjectTypeFactory( "class" );
|
171 |
| |
172 |
3
| final RuleSet ruleSet = new RuleSet( "test RuleSet",
|
173 |
| this.ruleBaseContext ); |
174 |
3
| final Rule rule = new Rule( "Test Rule 1",
|
175 |
| ruleSet ); |
176 |
3
| rule.setImporter( new DefaultImporter( ) );
|
177 |
3
| ObjectType cheeseType = objectTypeFactory.newObjectType( rule,
|
178 |
| this.ruleBaseContext, |
179 |
| cheeseConfiguration ); |
180 |
| |
181 |
3
| tuple = new MockTuple( );
|
182 |
3
| rule.setImporter( new DefaultImporter( ) );
|
183 |
3
| tuple.setRule( rule );
|
184 |
3
| tuple.setWorkingMemory( new MockWorkingMemory( ) );
|
185 |
| |
186 |
| |
187 |
3
| assertTrue( testCondition( testNumber++,
|
188 |
| tuple, |
189 |
| rule ) ); |
190 |
3
| assertFalse( testCondition( testNumber++,
|
191 |
| tuple, |
192 |
| rule ) ); |
193 |
3
| assertTrue( testCondition( testNumber++,
|
194 |
| tuple, |
195 |
| rule ) ); |
196 |
3
| assertTrue( testCondition( testNumber++,
|
197 |
| tuple, |
198 |
| rule ) ); |
199 |
3
| assertTrue( testCondition( testNumber++,
|
200 |
| tuple, |
201 |
| rule ) ); |
202 |
| |
203 |
3
| Declaration camembertDecl = rule.addParameterDeclaration( "camembert",
|
204 |
| cheeseType ); |
205 |
3
| Declaration stiltonDecl = rule.addParameterDeclaration( "stilton",
|
206 |
| cheeseType ); |
207 |
3
| rule.setImporter( this.importer );
|
208 |
| |
209 |
3
| tuple.put( camembertDecl,
|
210 |
| new Cheese( "camembert" ) ); |
211 |
3
| assertTrue( testCondition( testNumber++,
|
212 |
| tuple, |
213 |
| rule ) ); |
214 |
3
| assertFalse( testCondition( testNumber++,
|
215 |
| tuple, |
216 |
| rule ) ); |
217 |
| |
218 |
| |
219 |
3
| tuple = new MockTuple( );
|
220 |
3
| rule.setImporter( this.importer );
|
221 |
3
| tuple.setRule( rule );
|
222 |
3
| tuple.setWorkingMemory( new MockWorkingMemory( ) );
|
223 |
3
| tuple.put( stiltonDecl,
|
224 |
| new Cheese( "stilton" ) ); |
225 |
3
| assertTrue( testCondition( testNumber++,
|
226 |
| tuple, |
227 |
| rule ) ); |
228 |
3
| assertFalse( testCondition( testNumber++,
|
229 |
| tuple, |
230 |
| rule ) ); |
231 |
| |
232 |
| |
233 |
3
| tuple = new MockTuple( );
|
234 |
3
| rule.setImporter( this.importer );
|
235 |
3
| tuple.setRule( rule );
|
236 |
3
| tuple.setWorkingMemory( new MockWorkingMemory( ) );
|
237 |
3
| tuple.put( stiltonDecl,
|
238 |
| new Cheese( "stilton" ) ); |
239 |
3
| tuple.put( camembertDecl,
|
240 |
| new Cheese( "camembert" ) ); |
241 |
3
| assertFalse( testCondition( testNumber++,
|
242 |
| tuple, |
243 |
| rule ) ); |
244 |
3
| assertTrue( testCondition( testNumber++,
|
245 |
| tuple, |
246 |
| rule ) ); |
247 |
3
| assertTrue( testCondition( testNumber++,
|
248 |
| tuple, |
249 |
| rule ) ); |
250 |
3
| assertFalse( testCondition( testNumber++,
|
251 |
| tuple, |
252 |
| rule ) ); |
253 |
| |
254 |
| |
255 |
3
| WorkingMemory workingMemory = new MockWorkingMemory( );
|
256 |
3
| workingMemory.setApplicationData( "bites",
|
257 |
| new Integer( 3 ) ); |
258 |
3
| workingMemory.setApplicationData( "favouriteCheese",
|
259 |
| new Cheese( "camembert" ) ); |
260 |
3
| tuple.setWorkingMemory( workingMemory );
|
261 |
| |
262 |
3
| HashMap applicationData = new HashMap( );
|
263 |
3
| applicationData.put( "bites",
|
264 |
| Integer.class ); |
265 |
3
| applicationData.put( "favouriteCheese",
|
266 |
| Cheese.class ); |
267 |
| |
268 |
3
| rule.setApplicationData( applicationData );
|
269 |
| |
270 |
3
| assertTrue( testCondition( testNumber++,
|
271 |
| tuple, |
272 |
| rule ) ); |
273 |
3
| assertFalse( testCondition( testNumber++,
|
274 |
| tuple, |
275 |
| rule ) ); |
276 |
3
| assertTrue( testCondition( testNumber++,
|
277 |
| tuple, |
278 |
| rule ) ); |
279 |
| |
280 |
| |
281 |
3
| tuple = new MockTuple( );
|
282 |
3
| rule.setImporter( this.importer );
|
283 |
3
| rule.setApplicationData( new HashMap( ) );
|
284 |
3
| tuple.setRule( rule );
|
285 |
3
| workingMemory = new MockWorkingMemory( );
|
286 |
3
| tuple.setWorkingMemory( workingMemory );
|
287 |
| |
288 |
3
| DefaultConfiguration stringConfiguration = new DefaultConfiguration( "test2" );
|
289 |
3
| stringConfiguration.setText( String.class.getName( ) );
|
290 |
3
| ObjectType stringType = objectTypeFactory.newObjectType( rule,
|
291 |
| this.ruleBaseContext, |
292 |
| stringConfiguration ); |
293 |
3
| Declaration favouriteCheeseDecl = rule.addParameterDeclaration( "favouriteCheese",
|
294 |
| stringType ); |
295 |
| |
296 |
3
| tuple.put( favouriteCheeseDecl,
|
297 |
| "camembert" ); |
298 |
3
| tuple.put( camembertDecl,
|
299 |
| new Cheese( "camembert" ) ); |
300 |
3
| assertTrue( testCondition( testNumber++,
|
301 |
| tuple, |
302 |
| rule ) ); |
303 |
3
| assertTrue( testCondition( testNumber++,
|
304 |
| tuple, |
305 |
| rule ) ); |
306 |
| |
307 |
| |
308 |
3
| assertTrue( testCondition( testNumber++,
|
309 |
| tuple, |
310 |
| rule ) ); |
311 |
| |
312 |
| |
313 |
3
| rule.setImporter( this.importer );
|
314 |
3
| tuple.setRule( rule );
|
315 |
3
| try
|
316 |
| { |
317 |
3
| testCondition( testNumber++,
|
318 |
| tuple, |
319 |
| rule ); |
320 |
0
| fail( "Condition should throw an exception" );
|
321 |
| } |
322 |
| catch ( ConditionException e ) |
323 |
| { |
324 |
3
| assertEquals( rule,
|
325 |
| e.getRule( ) ); |
326 |
3
| assertEquals( tests.get( testNumber - 1 ),
|
327 |
| e.getInfo( ) ); |
328 |
| } |
329 |
| |
330 |
| |
331 |
| |
332 |
| |
333 |
| |
334 |
3
| tuple = new MockTuple( );
|
335 |
3
| rule.setImporter( this.importer );
|
336 |
3
| tuple.setRule( rule );
|
337 |
3
| workingMemory = new MockWorkingMemory( );
|
338 |
3
| tuple.setWorkingMemory( workingMemory );
|
339 |
| |
340 |
3
| assertTrue( testCondition( testNumber++,
|
341 |
| tuple, |
342 |
| rule ) ); |
343 |
| } |
344 |
| |
345 |
| |
346 |
| |
347 |
| |
348 |
63
| private boolean testCondition(int testNumber,
|
349 |
| Tuple tuple, |
350 |
| Rule rule) throws Exception |
351 |
| { |
352 |
63
| ConditionFactory conditionFactory = module.getConditionFactory( "condition" );
|
353 |
63
| DefaultConfiguration conditionConfiguration = new DefaultConfiguration( "test" + testNumber );
|
354 |
63
| conditionConfiguration.setText( (String) tests.get( testNumber ) );
|
355 |
63
| Condition condition = conditionFactory.newCondition( rule,
|
356 |
| this.ruleBaseContext, |
357 |
| conditionConfiguration )[0]; |
358 |
63
| return condition.isAllowed( tuple );
|
359 |
| } |
360 |
| |
361 |
| |
362 |
| |
363 |
| |
364 |
3
| public void testConsequences() throws Exception
|
365 |
| { |
366 |
3
| MockTuple tuple;
|
367 |
| |
368 |
3
| DefaultConfiguration cheeseConfiguration = new DefaultConfiguration( "test1" );
|
369 |
3
| cheeseConfiguration.setText( Cheese.class.getName( ) );
|
370 |
3
| ObjectTypeFactory objectTypeFactory = module.getObjectTypeFactory( "class" );
|
371 |
| |
372 |
3
| final RuleSet ruleSet = new RuleSet( "test RuleSet",
|
373 |
| this.ruleBaseContext ); |
374 |
3
| Rule rule = new Rule( "Test Rule 1",
|
375 |
| ruleSet ); |
376 |
| |
377 |
3
| rule.setImporter( new DefaultImporter( ) );
|
378 |
3
| ObjectType cheeseType = objectTypeFactory.newObjectType( rule,
|
379 |
| this.ruleBaseContext, |
380 |
| cheeseConfiguration ); |
381 |
| |
382 |
3
| tuple = new MockTuple( );
|
383 |
3
| rule.setImporter( this.importer );
|
384 |
3
| tuple.setRule( rule );
|
385 |
3
| tuple.setWorkingMemory( new MockWorkingMemory( ) );
|
386 |
| |
387 |
| |
388 |
3
| testConsequence( 0,
|
389 |
| tuple, |
390 |
| rule ); |
391 |
| |
392 |
| |
393 |
| |
394 |
3
| Declaration camembertDecl = rule.addParameterDeclaration( "camembert",
|
395 |
| cheeseType ); |
396 |
3
| Declaration stiltonDecl = rule.addParameterDeclaration( "stilton",
|
397 |
| cheeseType ); |
398 |
| |
399 |
3
| Cheese camembert = new Cheese( "camembert" );
|
400 |
3
| Cheese stilton = new Cheese( "stilton" );
|
401 |
3
| tuple.put( camembertDecl,
|
402 |
| camembert ); |
403 |
3
| tuple.put( stiltonDecl,
|
404 |
| stilton ); |
405 |
| |
406 |
| |
407 |
| |
408 |
3
| testConsequence( 1,
|
409 |
| tuple, |
410 |
| rule ); |
411 |
| |
412 |
| |
413 |
| |
414 |
3
| assertEquals( 3,
|
415 |
| camembert.getBitesLeft( ) ); |
416 |
3
| assertEquals( 3,
|
417 |
| stilton.getBitesLeft( ) ); |
418 |
| |
419 |
3
| testConsequence( 2,
|
420 |
| tuple, |
421 |
| rule ); |
422 |
| |
423 |
3
| assertEquals( 2,
|
424 |
| camembert.getBitesLeft( ) ); |
425 |
3
| assertEquals( 1,
|
426 |
| stilton.getBitesLeft( ) ); |
427 |
| |
428 |
| |
429 |
3
| WorkingMemory workingMemory = new MockWorkingMemory( );
|
430 |
3
| workingMemory.setApplicationData( "bites",
|
431 |
| new Integer( 3 ) ); |
432 |
3
| workingMemory.setApplicationData( "cheeses",
|
433 |
| new HashMap( ) ); |
434 |
| |
435 |
3
| HashMap applicationData = new HashMap( );
|
436 |
3
| applicationData.put( "bites",
|
437 |
| Integer.class ); |
438 |
3
| applicationData.put( "cheeses",
|
439 |
| HashMap.class ); |
440 |
| |
441 |
3
| rule.setApplicationData( applicationData );
|
442 |
| |
443 |
3
| tuple.setWorkingMemory( workingMemory );
|
444 |
3
| testConsequence( 3,
|
445 |
| tuple, |
446 |
| rule ); |
447 |
3
| assertEquals( 1,
|
448 |
| camembert.getBitesLeft( ) ); |
449 |
3
| assertEquals( 0,
|
450 |
| stilton.getBitesLeft( ) ); |
451 |
3
| Map map = (Map) workingMemory.getApplicationData( "cheeses" );
|
452 |
3
| assertEquals( camembert,
|
453 |
| map.get( "favourite cheese" ) ); |
454 |
3
| assertEquals( 3,
|
455 |
| ((Integer) map.get( "bites" )).intValue( ) ); |
456 |
| |
457 |
| |
458 |
| |
459 |
3
| rule = new Rule( "Test Rule 1",
|
460 |
| ruleSet ); |
461 |
3
| rule.setImporter( this.importer );
|
462 |
3
| tuple.setRule( rule );
|
463 |
3
| try
|
464 |
| { |
465 |
3
| testConsequence( 6,
|
466 |
| tuple, |
467 |
| rule ); |
468 |
0
| fail( "Consequence should throw an exception" );
|
469 |
| } |
470 |
| catch ( ConsequenceException e ) |
471 |
| { |
472 |
3
| assertEquals( rule,
|
473 |
| e.getRule( ) ); |
474 |
| } |
475 |
| |
476 |
| |
477 |
| |
478 |
3
| tuple = new MockTuple( );
|
479 |
3
| rule = new Rule( "Test Rule 1",
|
480 |
| ruleSet ); |
481 |
3
| rule.setImporter( this.importer );
|
482 |
3
| tuple.setRule( rule );
|
483 |
3
| workingMemory = new MockWorkingMemory( );
|
484 |
3
| tuple.setWorkingMemory( workingMemory );
|
485 |
3
| try
|
486 |
| { |
487 |
3
| testConsequence( 7,
|
488 |
| tuple, |
489 |
| rule ); |
490 |
| } |
491 |
| catch ( ConsequenceException e ) |
492 |
| { |
493 |
0
| fail( "Consequence should execute without errors" );
|
494 |
| } |
495 |
| } |
496 |
| |
497 |
| |
498 |
| |
499 |
| |
500 |
18
| private void testConsequence(int testNumber,
|
501 |
| Tuple tuple, |
502 |
| Rule rule) throws Exception |
503 |
| { |
504 |
18
| ConsequenceFactory consequenceFactory = module.getConsequenceFactory( "consequence" );
|
505 |
18
| DefaultConfiguration consequenceConfiguration = new DefaultConfiguration( "test" + testNumber );
|
506 |
18
| consequenceConfiguration.setText( (String) tests.get( testNumber ) );
|
507 |
18
| Consequence consequence = consequenceFactory.newConsequence( rule,
|
508 |
| this.ruleBaseContext, |
509 |
| consequenceConfiguration ); |
510 |
18
| consequence.invoke( tuple );
|
511 |
| } |
512 |
| |
513 |
2
| public static boolean conditionExceptionTest() throws Exception
|
514 |
| { |
515 |
2
| throw new Exception( "this is a condition exception" );
|
516 |
| } |
517 |
| |
518 |
2
| public static void consequenceExceptionTest() throws Exception
|
519 |
| { |
520 |
2
| throw new Exception( "this is a consequence exception" );
|
521 |
| } |
522 |
| |
523 |
| |
524 |
| |
525 |
| |
526 |
| public static class Cheese |
527 |
| { |
528 |
| private String name; |
529 |
| |
530 |
| private int bitesLeft = 3; |
531 |
| |
532 |
36
| public Cheese(String name)
|
533 |
| { |
534 |
36
| this.name = name;
|
535 |
| } |
536 |
| |
537 |
15
| public String getName()
|
538 |
| { |
539 |
15
| return this.name;
|
540 |
| } |
541 |
| |
542 |
18
| public void eatCheese()
|
543 |
| { |
544 |
18
| bitesLeft--;
|
545 |
| } |
546 |
| |
547 |
39
| public int getBitesLeft()
|
548 |
| { |
549 |
39
| return this.bitesLeft;
|
550 |
| } |
551 |
| |
552 |
18
| public boolean equals(Object object)
|
553 |
| { |
554 |
18
| if ( this == object )
|
555 |
| { |
556 |
3
| return true;
|
557 |
| } |
558 |
| |
559 |
15
| if ( object == null || getClass( ) != object.getClass( ) )
|
560 |
| { |
561 |
0
| return false;
|
562 |
| } |
563 |
| |
564 |
15
| return this.name.equals( ((Cheese) object).name );
|
565 |
| } |
566 |
| |
567 |
0
| public int hashCode()
|
568 |
| { |
569 |
0
| return this.name.hashCode( );
|
570 |
| } |
571 |
| } |
572 |
| } |