1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krms.framework;
17
18 import static junit.framework.Assert.assertEquals;
19 import static junit.framework.Assert.assertTrue;
20 import static junit.framework.Assert.fail;
21
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30
31 import org.apache.commons.lang.StringUtils;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.kuali.rice.krms.api.engine.Term;
35 import org.kuali.rice.krms.api.engine.TermResolutionEngine;
36 import org.kuali.rice.krms.api.engine.TermResolutionException;
37 import org.kuali.rice.krms.api.engine.TermResolver;
38 import org.kuali.rice.krms.framework.engine.TermResolutionEngineImpl;
39 import org.springframework.util.CollectionUtils;
40
41
42 public class TermResolutionEngineTest {
43
44 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(TermResolutionEngineTest.class);
45
46 private TermResolutionEngine termResolutionEngine = null;
47
48 @Before
49 public void setUp() {
50 termResolutionEngine = new TermResolutionEngineImpl();
51 }
52
53 @Test
54 public void testNoResolution() {
55 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
56
57
58 testHelper.addGivens("A");
59
60 testHelper.logScenarioDescription();
61
62 testHelper.assertSuccess("A");
63 }
64
65 @Test
66 public void testSimpleResolution() {
67 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
68
69
70 testHelper.addGivens("A");
71
72
73 testHelper.addResolver("B", "A");
74
75 testHelper.logScenarioDescription();
76
77 testHelper.assertSuccess("B");
78 }
79
80 @Test
81 public void testTwoStepResolution() {
82 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
83
84
85 testHelper.addGivens("A");
86
87
88 testHelper.addResolver("B", "A");
89 testHelper.addResolver("C", "B");
90
91 testHelper.logScenarioDescription();
92
93 testHelper.assertSuccess("C");
94 }
95
96 @Test
97 public void testForkingResolution() {
98 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
99
100
101 testHelper.addGivens("A", "Z");
102
103
104 testHelper.addResolver("D", "B","C");
105 testHelper.addResolver("C", "Z");
106 testHelper.addResolver("B", "A");
107
108 testHelper.logScenarioDescription();
109
110 testHelper.assertSuccess("D");
111 }
112
113 @Test
114 public void testMultipleValidPaths() {
115 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
116
117
118 testHelper.addGivens("A", "Z");
119
120
121 testHelper.addResolver("D", "B","C");
122 testHelper.addResolver("C", "Z");
123 testHelper.addResolver("B", "A");
124 testHelper.addResolver("D", "A");
125
126 testHelper.logScenarioDescription();
127
128 testHelper.assertSuccess("D");
129 }
130
131 @Test
132 public void testDiamond() {
133 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
134
135
136 testHelper.addGivens("A");
137
138
139 testHelper.addResolver("D", "B","C");
140 testHelper.addResolver("C", "A");
141 testHelper.addResolver("B", "A");
142
143 testHelper.logScenarioDescription();
144
145 testHelper.assertSuccess("D");
146
147 }
148
149 @Test
150 public void testComplexPath() {
151 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
152
153
154 testHelper.addGivens("Q","R","S");
155
156
157 testHelper.addResolver("A", "B","F");
158 testHelper.addResolver("A", "Z");
159 testHelper.addResolver("B", "D");
160 testHelper.addResolver("B", "C");
161 testHelper.addResolver("C", "S");
162 testHelper.addResolver("D", "E");
163 testHelper.addResolver("E", "S");
164 testHelper.addResolver("F", "G","Q");
165 testHelper.addResolver("G", "R");
166
167 testHelper.logScenarioDescription();
168
169 testHelper.assertSuccess("A");
170
171 }
172
173 @Test
174 public void testCycle() {
175 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
176
177
178
179
180
181 testHelper.addResolver("D", "C");
182 testHelper.addResolver("C", "D");
183
184 testHelper.logScenarioDescription();
185
186 testHelper.assertException("D");
187
188 }
189
190
191 @Test
192 public void testUnreachableTerm() {
193 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
194
195
196
197
198
199 testHelper.addResolver("D", "C");
200 testHelper.addResolver("C", "B");
201
202 testHelper.logScenarioDescription();
203
204 testHelper.assertException("D");
205
206 }
207
208 @Test
209 public void testRedHerringPath() {
210 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
211
212
213 testHelper.addGivens("Q");
214
215
216 testHelper.addResolver("A", "B");
217
218 testHelper.addResolver("B", "C");
219
220 testHelper.addResolver("B", "D");
221 testHelper.addResolver("D", "Q");
222
223 testHelper.logScenarioDescription();
224
225 testHelper.assertSuccess("A");
226 }
227
228 @Test
229 public void testResolveParamaterizedTerm() {
230 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
231
232
233 testHelper.addGivens("Q");
234
235
236 testHelper.addResolver(1, "A", new String[] {"param"}, "B");
237 testHelper.addResolver("B", "Q");
238
239 testHelper.logScenarioDescription();
240
241 Map<String,String> params = new HashMap();
242 params.put("param", "value");
243 testHelper.assertSuccess(testHelper.getTerm("A", params));
244
245
246 testHelper.assertException(new Term("A"));
247
248 }
249
250 @Test
251 public void testIntermediateParamaterizedTerm() {
252 TestScenarioHelper testHelper = new TestScenarioHelper(termResolutionEngine);
253
254
255 testHelper.addGivens("Q");
256
257
258 testHelper.addResolver(1, "A", new String[] {"foo"}, "B");
259 testHelper.addResolver(1, "B", new String[] {"bar"}, "Q");
260
261 testHelper.logScenarioDescription();
262
263 Map<String,String> params = new HashMap();
264 params.put("foo", "foovalue");
265
266
267 testHelper.assertException(testHelper.getTerm("A", params));
268 }
269
270 private static class WhiteBoxTermResolutionEngineImpl extends TermResolutionEngineImpl {
271
272
273 @Override
274 public List<TermResolverKey> buildTermResolutionPlan(String termName) {
275 return super.buildTermResolutionPlan(termName);
276 }
277 }
278
279
280 @Test
281 public void testShortestPath() {
282
283 WhiteBoxTermResolutionEngineImpl whiteBoxTermResolutionService = new WhiteBoxTermResolutionEngineImpl();
284 TestScenarioHelper testHelper = new TestScenarioHelper(whiteBoxTermResolutionService);
285
286
287 testHelper.addGivens("Q");
288
289
290
291 testHelper.addResolver(3, "A", "Q");
292
293
294 testHelper.addResolver("A", "B");
295 testHelper.addResolver("B", "C");
296 testHelper.addResolver("C", "D");
297 testHelper.addResolver("D", "Q");
298
299 testHelper.logScenarioDescription();
300
301 List<?> plan = whiteBoxTermResolutionService.buildTermResolutionPlan("A");
302 LOG.info("resolutionPlan: " + StringUtils.join(plan, ", ") + " <-- should be length 1!");
303 assertTrue("didn't choose the shortest resolution path (of length 1)", plan.size() == 1);
304 }
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333 private static class TermResolverMock<T> implements TermResolver<T> {
334 private String output;
335 private Set<String> params;
336 private T result;
337 private Set<String> prereqs;
338 private int cost;
339 private boolean isExploder = false;
340
341 public TermResolverMock(String output, T result, int cost, String ... prereqs) {
342 this(output, null, result, cost, prereqs);
343 }
344
345 public TermResolverMock(String output, Set<String> params, T result, int cost, String ... prereqs) {
346 this.output = output;
347 this.params = Collections.unmodifiableSet(params);
348 this.result = result;
349 this.prereqs = new HashSet<String>(Arrays.asList(prereqs));
350 this.cost = cost;
351 }
352
353 @Override
354 public int getCost() {
355 return cost;
356 }
357
358 @Override
359 public String getOutput() {
360 return output;
361 }
362
363 @Override
364 public Set<String> getPrerequisites() {
365 return prereqs;
366 }
367
368 @Override
369 public Set<String> getParameterNames() {
370 return params;
371 }
372
373 public void setIsExploder(boolean isExploder) {
374 this.isExploder = isExploder;
375 }
376
377 @Override
378 public T resolve(Map<String, Object> resolvedPrereqs, Map<String, String> parameters) {
379
380 if (isExploder) {
381 throw new RuntimeException("I'm the exploder, coo coo catchoo");
382 }
383
384
385 for (String prereq : prereqs) {
386 Object result = resolvedPrereqs.get(prereq);
387 if (result == null) fail("got back null for prereq " + prereq);
388 }
389
390 LOG.info("resolving " + output);
391 return result;
392 }
393
394 @Override
395 public String toString() {
396 String paramStr = "";
397 if (!CollectionUtils.isEmpty(params)) {
398 paramStr = "+(" + StringUtils.join(params, ",") + ")";
399 }
400 return getClass().getSimpleName()+"[ "+output+paramStr+ " <- " + StringUtils.join(prereqs.iterator(), ",") + " ]";
401 }
402
403 }
404
405
406 private static class TestScenarioHelper {
407
408 private final TermResolutionEngine ars;
409
410 private List<String> givens = new LinkedList<String>();
411 private List<String> resolvers = new LinkedList<String>();
412
413 public TestScenarioHelper(TermResolutionEngine tre) {
414 this.ars = tre;
415 }
416
417 public void addGivens(String ... names) {
418 for (String name : names) {
419 ars.addTermValue(new Term(name, null), getResult(name));
420 givens.add(name);
421 }
422 }
423
424 public String getResult(String name) {
425 return getResult(new Term(name, null));
426 }
427
428 public String getResult(Term term) {
429 return term.getName() +"-result";
430 }
431
432 public Term getTerm(String name, Map<String,String> params) {
433 return new Term(name, params);
434 }
435
436 public void addResolver(String out, String ... prereqs) {
437 addResolver(1, out, prereqs);
438 }
439
440 public void addResolver(int cost, String out, String ... prereqs) {
441 addResolver(1, out, null, prereqs);
442 }
443
444 public void addResolver(int cost, String out, String[] params, String ... prereqs) {
445 String [] prereqTerms = new String [prereqs.length];
446
447 for (int i=0; i<prereqs.length; i++) prereqTerms[i] = prereqs[i];
448
449 Set<String> paramSet = Collections.emptySet();
450 if (params != null) paramSet = new HashSet<String>(Arrays.asList(params));
451
452 ars.addTermResolver(new TermResolverMock<Object>(out, paramSet, getResult(out), cost, prereqTerms));
453 resolvers.add("(" + out + " <- " + StringUtils.join(prereqs, ",") + ")");
454 }
455
456 public void logScenarioDescription() {
457 StringBuilder sb = new StringBuilder();
458
459 sb.append("givens: " + StringUtils.join(givens.iterator(), ", ") + "\n\n");
460 sb.append("resolvers:\n----------------------\n");
461 if (resolvers == null || resolvers.size() == 0) {
462 sb.append("none");
463 } else {
464 sb.append(StringUtils.join(resolvers.iterator(), "\n"));
465 }
466 sb.append("\n");
467
468 LOG.info("Test Scenario:\n\n" + sb.toString());
469 }
470
471 public void assertSuccess(String toResolve) {
472 assertSuccess(new Term(toResolve, null));
473 }
474
475 public void assertSuccess(Term toResolve) {
476 LOG.info("Testing resolution of " + toResolve);
477 try {
478 assertEquals(getResult(toResolve), ars.resolveTerm(toResolve));
479 LOG.info("Success!");
480 } catch (TermResolutionException e) {
481 fail("Should resolve the termName w/o exceptions");
482 }
483 }
484
485 public void assertException(String toResolve) {
486 assertException(new Term(toResolve, null));
487 }
488
489 public void assertException(Term toResolve) {
490 LOG.info("Testing resolution of " + toResolve);
491 try {
492 ars.resolveTerm(toResolve);
493 fail("Should throw TermResolutionException");
494 } catch (TermResolutionException e) {
495 LOG.info("Success! threw " + e);
496
497 }
498 }
499 }
500
501 }