View Javadoc

1   package cz.cuni.amis.pogamut.sposh.engine;
2   
3   import cz.cuni.amis.pogamut.sposh.elements.*;
4   import static org.junit.Assert.assertEquals;
5   import static org.junit.Assert.assertTrue;
6   import static org.junit.Assert.fail;
7   
8   import java.io.BufferedReader;
9   import java.io.IOException;
10  import java.io.InputStream;
11  import java.io.InputStreamReader;
12  import java.io.StringReader;
13  import java.util.HashMap;
14  import java.util.Iterator;
15  
16  import org.junit.After;
17  import org.junit.AfterClass;
18  import org.junit.Before;
19  import org.junit.BeforeClass;
20  import org.junit.Test;
21  
22  import cz.cuni.amis.pogamut.sposh.engine.PoshEngine.EvaluationResult;
23  import cz.cuni.amis.pogamut.sposh.engine.PoshEngine.EvaluationResultInfo;
24  import cz.cuni.amis.pogamut.sposh.engine.timer.DebugTimer;
25  import cz.cuni.amis.pogamut.sposh.executor.ActionResult;
26  import cz.cuni.amis.pogamut.sposh.executor.IAction;
27  import cz.cuni.amis.pogamut.sposh.executor.ISense;
28  import cz.cuni.amis.pogamut.sposh.executor.IWorkExecutor;
29  import cz.cuni.amis.pogamut.sposh.executor.StateWorkExecutor;
30  import java.util.*;
31  import org.junit.Ignore;
32  
33  /**
34   * Tests covering {@link PoshEngine} and its execution.
35   *
36   * @author Honza
37   */
38  public class PoshEngineTest extends PlanTest {
39  
40      private IWorkExecutor createWorkExecutor() {
41          return new IWorkExecutor() {
42  
43              @Override
44              public ActionResult executeAction(String actionName, VariableContext ctx) {
45                  return null;
46              }
47  
48              @Override
49              public Object executeSense(String senseName, VariableContext ctx) {
50                  return null;
51              }
52          };
53      }
54  
55      @Test
56      public void testGoalFulfilled() throws IOException, ParseException {
57          System.out.println("\n === Test: " + getMethodName() + " ===");
58  
59          PoshPlan parsePlan = parsePlan("testplans/TestGoalFulfilled.lap");
60          PoshEngine poshEngine = new PoshEngine(parsePlan);
61          IWorkExecutor workExecuter = new TestWorkExecutor(
62                  new ITestPrimitive[]{
63                      new PrintPrimitive("succeed", true),
64                      new PrintPrimitive("fail", false)
65                  });
66  
67          EvaluationResult result = poshEngine.evaluatePlan(workExecuter).result;
68  
69          assertEquals(EvaluationResult.GOAL_SATISFIED, result);
70      }
71  
72      /**
73       * Test if primitive "dummyPrimitive" is evaluated and if has no variables
74       * in passed context.
75       *
76       * @throws IOException
77       * @throws ParseException
78       */
79      @Test
80      public void testParameterlessPrimitiveEvaluation() throws IOException, ParseException {
81          System.out.println("\n === Test: " + getMethodName() + " ===");
82  
83          PoshPlan parsePlan = parsePlan("testplans/TestPrimitiveEvaluation.lap");
84          PoshEngine poshEngine = new PoshEngine(parsePlan);
85  
86          ITestPrimitive dummyPrimitive = new PrintPrimitive("dummyPrimitive", ActionResult.FAILED) {
87  
88              @Override
89              public Object work(VariableContext ctx) {
90                  // test if context of primitive is empty as it should
91                  assertEquals(ctx.size(), 0);
92  
93                  return super.work(ctx);
94              }
95          };
96          IWorkExecutor workExecuter = new TestWorkExecutor(
97                  new ITestPrimitive[]{
98                      new PrintPrimitive("succeed", true),
99                      new PrintPrimitive("fail", false),
100                     dummyPrimitive
101                 });
102 
103         assertEquals(poshEngine.evaluatePlan(workExecuter).result, EvaluationResult.ELEMENT_FIRED);
104         if (dummyPrimitive.triggered() != 0) {
105             fail("Primitive was triggered, shouldn't be, expected only to add primitive to stack.");
106         }
107         assertEquals(poshEngine.evaluatePlan(workExecuter).result, EvaluationResult.ELEMENT_FIRED);
108         if (dummyPrimitive.triggered() != 1) {
109             fail("Primitive wasn't triggered.");
110         }
111     }
112 
113     @Test
114     public void testDEFrequencyFail() throws IOException, ParseException {
115         System.out.println("\n === Test: " + getMethodName() + " ===");
116 
117         DebugTimer timer = new DebugTimer();
118         PoshEngine poshEngine = new PoshEngine(
119                 parsePlan("testplans/TestDEFrequencyFail.lap"),
120                 timer);
121 
122         ITestPrimitive doNothingPrimitive = new PrintPrimitive("doNothing", ActionResult.FAILED);
123         IWorkExecutor workExecuter = new TestWorkExecutor(
124                 new ITestPrimitive[]{
125                     new PrintPrimitive("fail", false),
126                     doNothingPrimitive
127                 });
128 
129         // First one is to create the root "doNothing" element on the call stack ...
130         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
131         // .. and the second for actully firing it.
132         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
133         for (int i = 0; i < 3; ++i) {
134             assertEquals(EvaluationResult.NO_ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
135             assertEquals(EvaluationResult.NO_ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
136             timer.addTime(250);
137             if (doNothingPrimitive.triggered() != 1) {
138                 fail("DE wasn't triggered just once");
139             }
140         }
141         System.out.println("Adding 300 so it is over 1000ms");
142         timer.addTime(300);
143         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
144         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
145 
146         if (doNothingPrimitive.triggered() != 2) {
147             fail("DE wasn't triggered after freq limiter timeout");
148         }
149     }
150 
151     /**
152      * Test what happens if goal wasn't specified in the DC. Expected: consider
153      * missing goal as always failing.
154      */
155     @Test
156     public void testNoGoal() throws IOException, ParseException {
157         System.out.println("\n === Test: " + getMethodName() + " ===");
158 
159         PoshPlan parsePlan = parsePlan("testplans/TestNoGoal.lap");
160         PoshEngine poshEngine = new PoshEngine(parsePlan);
161 
162         ITestPrimitive dummyPrimitive = new PrintPrimitive("dummyPrimitive", ActionResult.FAILED);
163         IWorkExecutor workExecuter = new TestWorkExecutor(
164                 new ITestPrimitive[]{
165                     dummyPrimitive
166                 });
167 
168         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
169         if (dummyPrimitive.triggered() != 0) {
170             fail("Primitive was triggered, should only be added to stack.");
171         }
172         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
173 
174         if (dummyPrimitive.triggered() != 1) {
175             fail("Primitive wasn't triggered.");
176         }
177     }
178 
179     /**
180      * Test if de will execute the ap
181      */
182     @Test
183     public void testAPExecutor() throws IOException, ParseException {
184         System.out.println("\n === Test: " + getMethodName() + " ===");
185 
186         PoshPlan parsePlan = parsePlan("testplans/TestAPExecutor.lap");
187         PoshEngine poshEngine = new PoshEngine(parsePlan);
188 
189         ITestPrimitive[] actions = new ITestPrimitive[3];
190         int[] res = new int[]{0, 0, 0};
191 
192         for (int i = 0; i < actions.length; ++i) {
193             actions[i] = new PrintPrimitive("action" + i);
194         }
195 
196         IWorkExecutor workExecuter = new TestWorkExecutor(actions);
197 
198         // this evaluation will add testAP to callStack
199         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
200         checkPrimitives(actions, res);
201         // Enter testAP
202 //        assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter));
203         checkPrimitives(actions, res);
204 
205         for (int i = 0; i < actions.length; ++i) {
206             System.out.println(" * Firing action " + actions[i].getName());
207             // add action to call stack
208             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
209             checkPrimitives(actions, res);
210 
211             // execute the action
212             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
213             res[i] = 1;
214             checkPrimitives(actions, res);
215         }
216     }
217 
218     private void checkPrimitives(ITestPrimitive[] primitives, int[] results) {
219         for (int i = 0; i < primitives.length; ++i) {
220             if (primitives[i].triggered() != results[i]) {
221                 throw new IllegalStateException("Primitive " + primitives[i].getName() + " wasn't triggered " + results[i] + " times, but " + primitives[i].triggered());
222             }
223         }
224     }
225 
226     /**
227      * Test if constants passed from posh plan to primitives are what they are
228      * supposed to be.
229      *
230      * @throws IOException
231      * @throws ParseException
232      */
233     @Test
234     public void testPassedConstantsInPrimitive() throws IOException, ParseException {
235         System.out.println("\n === Test: " + getMethodName() + " ===");
236 
237         PoshPlan parsePlan = parsePlan("testplans/TestPrimitiveVariables.lap");
238         PoshEngine poshEngine = new PoshEngine(parsePlan);
239 
240         ITestPrimitive testVariable = new ITestPrimitive() {
241 
242             @Override
243             public String getName() {
244                 return "testVariable";
245             }
246 
247             @Override
248             public Object work(VariableContext ctx) {
249                 if (!"Snowhite".equals(ctx.getValue("$name"))) {
250                     throw new IllegalStateException("Variable $name is not snowhite, but " + ctx.getValue("$name"));
251                 }
252                 assertEquals(ctx.getValue("0"), 12.4);
253                 if (ctx.size() != 2) {
254                     throw new IllegalStateException("More than two variables passed (\"" + ctx.size() + "\").");
255                 }
256                 return null;
257             }
258 
259             @Override
260             public int triggered() {
261                 return 0;
262             }
263         };
264         IWorkExecutor workExecuter = new TestWorkExecutor(
265                 new ITestPrimitive[]{testVariable});
266 
267         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
268         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
269     }
270 
271     /**
272      * Test if order of actions will be OK in nested APs
273      */
274     @Test
275     public void testNestedAP() throws IOException, ParseException {
276         System.out.println("\n === Test: " + getMethodName() + " ===");
277 
278         PoshPlan parsePlan = parsePlan("testplans/TestNestedAP.lap");
279         PoshEngine poshEngine = new PoshEngine(parsePlan);
280 
281         int[] res = new int[]{0, 0, 0, 0};
282         ITestPrimitive[] actions = new ITestPrimitive[4];
283         for (int i = 0; i < actions.length; ++i) {
284             actions[i] = new PrintPrimitive("action" + i, ActionResult.FINISHED);
285         }
286 
287         IWorkExecutor workExecuter = new TestWorkExecutor(actions);
288 
289         // add outerAP to stack
290         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
291         checkPrimitives(actions, res);
292         // add action0 to stack
293         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
294         checkPrimitives(actions, res);
295         // fire action0
296         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
297         res[0]++;
298         checkPrimitives(actions, res);
299 
300         // add innerAP to stack
301         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
302         checkPrimitives(actions, res);
303         // add action1 to stack
304         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
305         checkPrimitives(actions, res);
306         // fire action1
307         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
308         res[1]++;
309         checkPrimitives(actions, res);
310 
311         // add action2 to stack
312         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
313         checkPrimitives(actions, res);
314         // fire action2
315         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
316         res[2]++;
317         checkPrimitives(actions, res);
318 
319         // return to outerAP, add action3 to stack
320         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
321         checkPrimitives(actions, res);
322 
323 
324         // add action3 to stack
325         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
326         checkPrimitives(actions, res);
327         // fire action3
328         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
329         res[3]++;
330         checkPrimitives(actions, res);
331     }
332 
333     /**
334      * Test what happens if action in inner ap of two nested APs fails. action2
335      * will fail
336      */
337     @Test
338     public void testNestedAPFailure() throws IOException, ParseException {
339         System.out.println("\n === Test: " + getMethodName() + " ===");
340 
341         PoshPlan parsePlan = parsePlan("testplans/TestNestedAPFailure.lap");
342         PoshEngine poshEngine = new PoshEngine(parsePlan);
343 
344         int[] res = new int[]{0, 0, 0, 0};
345         ITestPrimitive[] actions = new ITestPrimitive[4];
346         for (int i = 0; i < actions.length; ++i) {
347             if (i == 2) {
348                 actions[i] = new PrintPrimitive("action" + i, ActionResult.FAILED);
349             } else {
350                 actions[i] = new PrintPrimitive("action" + i, ActionResult.FINISHED);
351             }
352         }
353 
354         IWorkExecutor workExecuter = new TestWorkExecutor(actions);
355 
356         for (int loop = 0; loop < 4; loop++) {
357             // add outerAP to stack
358             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
359             checkPrimitives(actions, res);
360             // add action0 to stack
361             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
362             checkPrimitives(actions, res);
363             // fire action0
364             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
365             res[0]++;
366             checkPrimitives(actions, res);
367 
368             // add innerAP to stack
369             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
370             checkPrimitives(actions, res);
371             // add action1 to stack
372             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
373             checkPrimitives(actions, res);
374             // fire action1
375             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
376             res[1]++;
377             checkPrimitives(actions, res);
378 
379             // add action2 to stack
380             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
381             checkPrimitives(actions, res);
382             // fire action2
383             System.out.println("Action2 will fail, reset");
384             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
385             res[2]++; // it failed, but it was still fired
386             checkPrimitives(actions, res);
387 
388             // the stack of DE is now reseted
389             System.out.println("Stack has been reseted.");
390         }
391     }
392 
393     @Test
394     public void testSimpleC() throws IOException, ParseException {
395         System.out.println("\n === Test: " + getMethodName() + " ===");
396 
397         PoshPlan parsePlan = parsePlan("testplans/TestSimpleC.lap");
398         PoshEngine poshEngine = new PoshEngine(parsePlan);
399 
400         ITestPrimitive action = new PrintPrimitive("action");
401         IWorkExecutor workExecuter = new TestWorkExecutor(
402                 new ITestPrimitive[]{action});
403         
404         String[] paths = new String[]{
405             "/P:0/DC:0/DE:0",
406             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0",
407             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0",
408             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0/A:0",
409             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0",
410             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0",
411             "/P:0/DC:0/DE:0",
412             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0",
413             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0",
414             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0/A:0",
415             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0",
416             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0",
417         };
418         assertEngineProgress(poshEngine, workExecuter, paths);
419     }
420     
421     /**
422      * Is engine evaluation same as the supplied paths?
423      */
424     private void assertEngineProgress(PoshEngine engine, IWorkExecutor executor, String[] paths) {
425         Iterator<String> expectedIt = Arrays.asList(paths).iterator();
426         Iterator<LapPath> engineIt = Collections.<LapPath>emptyList().iterator();
427         while (expectedIt.hasNext()) {
428             String curPath = expectedIt.next();
429             if (!engineIt.hasNext()) {
430                 EvaluationResultInfo evaluationResult = engine.evaluatePlan(executor);
431                 assertEquals(EvaluationResult.ELEMENT_FIRED, evaluationResult.result);
432                 engineIt = engine.getEvaluatedPaths().iterator();
433             }
434             LapPath enginePath = engineIt.next();
435             assertEquals("Mismatched elements at path index " + Arrays.asList(paths).indexOf(curPath) + ", expected " + curPath + " but got " + enginePath.toString(), curPath, enginePath.toString());
436         }
437         assertFalse("Engine has extra paths", engineIt.hasNext());
438     }
439 
440     /**
441      * Print notice "Evaluated paths:" and after that print passed paths.
442      * @param paths Paths that are supposed to be printed.
443      */
444     private void printPaths(List<LapPath> paths) {
445         System.out.println("Evaluated paths:");
446         for (LapPath path : paths) {
447             System.out.println(path.toString());
448         }
449         System.out.println();
450     }
451 
452     // TODO: Retries in CEExecutor don't work because the executor is always unwinded. Remove them?
453     @Test
454     @Ignore
455     public void testSimpleCRetry() throws IOException, ParseException {
456         System.out.println("\n === Test: " + getMethodName() + " ===");
457 
458         PoshPlan parsePlan = parsePlan("testplans/TestSimpleCRetry.lap");
459         PoshEngine poshEngine = new PoshEngine(parsePlan);
460 
461         ITestPrimitive action = new PrintPrimitive("action");
462         IWorkExecutor workExecuter = new TestWorkExecutor(
463                 new ITestPrimitive[]{action});
464         
465         // fire DC, add testC to stack
466         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
467         if (action.triggered() != 0) {
468             fail("Action was fired.");
469         }
470         final int retries = 6;
471         for (int i = 0; i < retries; i++) {
472             System.out.println("i" + i);
473             // now in testC, add testCE to stack
474             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
475             if (action.triggered() != 0 + i) {
476                 fail("Action was fired.");
477             }
478             // enter testCE, add action to stack
479             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
480             if (action.triggered() != 0 + i) {
481                 fail("Action was fired.");
482             }
483             // fire action
484             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
485             if (action.triggered() != 1 + i) {
486                 fail("Action wasn't fired.");
487             }
488             // now in testCE, go up one level
489             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
490             if (action.triggered() != 1 + i) {
491                 fail("Action wasn't fired.");
492             }
493         }
494         // next execution of testC should fail.
495         // now in testC, being fired, but retry limit reached so the competence has failed
496         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
497 
498         // therefore the stack is reduced to zero
499         assertEquals(0, poshEngine.getStackForDE("testDE").size());
500     }
501 
502     /**
503      * Test if primitive correctly recieves mix of variables and constants
504      * passed from posh plan.
505      */
506     @Test
507     public void test011VarConstPassed2Primitive() throws IOException, ParseException {
508         System.out.println("\n === Test: " + getMethodName() + " ===");
509 
510         PoshPlan parsePlan = parsePlan("testplans/011VarConstPassed2Primitive.lap");
511         PoshEngine poshEngine = new PoshEngine(parsePlan);
512 
513         ITestPrimitive murder = new PrintPrimitive("murder") {
514 
515             /**
516              * Check that variable is contained in context
517              *
518              * @param contextName name of variable in context
519              */
520             private boolean variableInContext(VariableContext ctx, String contextName, String value) {
521                 Object contextValue = ctx.getValue(contextName);
522                 return value == null ? contextValue == null : value.equals(contextValue);
523             }
524 
525             private void assertVariableInContext(VariableContext ctx, String contextName, String value) {
526                 assertTrue("Variable \"" + contextName + "\" is not \"" + value + "\", but " + ctx.getValue(contextName),
527                         variableInContext(ctx, contextName, value));
528             }
529 
530             @Override
531             public Object work(VariableContext ctx) {
532                 if (ctx.size() != 5) {
533                     fail("Expected 5 variables, is " + ctx.size());
534                 }
535 
536                 assertVariableInContext(ctx, "0", "killAllHumans");
537                 assertEquals(ctx.getValue("1"), 12.6);
538                 assertVariableInContext(ctx, "2", "Tomorrow");
539                 assertVariableInContext(ctx, "$method", "brutal");
540                 assertVariableInContext(ctx, "$baka", "Sekal");
541 
542                 return super.work(ctx);
543             }
544         };
545         IWorkExecutor workExecuter = new TestWorkExecutor(
546                 new ITestPrimitive[]{
547                     new PrintPrimitive("succeed", true),
548                     new PrintPrimitive("fail", false),
549                     murder});
550 
551         // put testAP to stack
552         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
553         // put murder primitive
554         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
555         Iterator<StackElement> enumerator = poshEngine.getStackForDE("stay").iterator();
556 
557         while (enumerator.hasNext()) {
558             StackElement stackElement = enumerator.next();
559             VariableContext ctx = ((AbstractExecutor) stackElement.getExecutor()).ctx;
560 
561             System.out.println("Keys for " + stackElement.toString());
562             for (String key : ctx.getKeys()) {
563                 System.out.println(" - \"" + key + "\" " + ctx.getValue(key));
564             }
565         }
566 
567         // fire murder primitive
568         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(workExecuter).result);
569 
570         assertTrue(murder.triggered() == 1);
571     }
572 
573     /**
574      * Test that actions in AP are called in sequenmce and when one fails,
575      * process is restarted
576      *
577      * @throws IOException
578      * @throws ParseException
579      */
580     @Test
581     public void test012TestAPProcessing() throws IOException, ParseException {
582         System.out.println("\n === Test: " + getMethodName() + " ===");
583 
584         PoshPlan parsePlan = parsePlan("testplans/012TestAPProcessing.lap");
585         PoshEngine poshEngine = new PoshEngine(parsePlan);
586 
587         ITestPrimitive succeed = new PrintPrimitive("succeed", true);
588         ITestPrimitive fail = new PrintPrimitive("fail", false);
589         ITestPrimitive[] ok = new ITestPrimitive[]{
590             new PrintPrimitive("ok1", ActionResult.FINISHED),
591             new PrintPrimitive("ok2", ActionResult.FINISHED),
592             new PrintPrimitive("ok3", ActionResult.FINISHED)
593         };
594         ITestPrimitive fail1 = new PrintPrimitive("fail1", ActionResult.FAILED);
595         ITestPrimitive last = new PrintPrimitive("last", ActionResult.FINISHED);
596 
597         IWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
598                     succeed,
599                     fail,
600                     ok[0],
601                     ok[1],
602                     ok[2],
603                     fail1,
604                     last
605                 });
606 
607         // put testAP to stack
608         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
609 
610         for (int i = 0; i < 3; ++i) {
611             // put first ok[i] to stack
612             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
613             assertTrue(ok[i].triggered() == 0);
614             // fire first ok
615             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
616             assertTrue(ok[i].triggered() == 1);
617 
618             assertTrue(last.triggered() == 0);
619         }
620 
621         // put fail1 to stack
622         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
623         assertTrue(fail1.triggered() == 0);
624         assertTrue(last.triggered() == 0);
625         // fire fail1, should fail
626         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
627         assertTrue(fail1.triggered() == 1);
628         assertTrue(last.triggered() == 0);
629 
630         // ok, back to DC
631         // put testAP to stack
632         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
633 
634         // and now it should  restart back to start
635         for (int i = 0; i < 3; ++i) {
636             // put first ok[i] to stack
637             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
638             assertTrue("ok" + i + " was triggered " + ok[i].triggered() + " != 1", ok[i].triggered() == 1);
639             // fire first ok
640             assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
641             assertTrue("ok" + i + " was triggered " + ok[i].triggered() + " != 2", ok[i].triggered() == 2);
642 
643             assertTrue(last.triggered() == 0);
644         }
645 
646     }
647 
648     /**
649      * Test that primitives are triggered exactly how they should.
650      *
651      * @param engine engine that will be used for testing.
652      * @param executor executor from which list of primitives and how many times
653      * was primitive actually triggered.
654      * @param order two dimensional array, in each subarray is list of
655      * primitives that are supposed to be triggered in that loop.
656      */
657     private void testPrimitiveExecutionOrder(PoshEngine engine, TestWorkExecutor executor, String[][] order) {
658         // at the start, put map of primitive-# of fired into fired map.
659         HashMap<String, Integer> fired = new HashMap<String, Integer>();
660         for (String key : executor.getPrimitives().keySet()) {
661             fired.put(key, executor.getPrimitives().get(key).triggered());
662         }
663 
664 
665         for (int executionLoop = 0; executionLoop < order.length; ++executionLoop) {
666             System.out.print(">>> Loop " + executionLoop + " [");
667             for (String primitive : order[executionLoop]) {
668                 System.out.print(primitive + ", ");
669             }
670             System.out.println("]");
671             // evalue
672             assertEquals(EvaluationResult.ELEMENT_FIRED, engine.evaluatePlan(executor).result);
673 
674             // increase expected triggered count
675             for (String triggeredPrimitive : order[executionLoop]) {
676                 if (!fired.containsKey(triggeredPrimitive)) {
677                     fail("Primitive \"" + triggeredPrimitive + "\" is not in executor list of primitives.");
678                 }
679                 fired.put(triggeredPrimitive, fired.get(triggeredPrimitive) + 1);
680             }
681 
682             // check that everything is triggered according to expectations.
683             for (String key : executor.getPrimitives().keySet()) {
684                 int wasTriggeredCount = executor.getPrimitives().get(key).triggered();
685                 int supposedTriggerCount = fired.get(key);
686                 if (wasTriggeredCount != supposedTriggerCount) {
687                     fail("Primtives \"" + key + "\" is supposed to be triggered " + supposedTriggerCount + " times, but was " + wasTriggeredCount + " in loop " + executionLoop + "\n"
688                             + order[executionLoop]);
689                 }
690             }
691 
692         }
693     }
694 
695     /**
696      * We need better tools for evaluation. Repeat test 012 with new approach.
697      */
698     @Test
699     public void test012New() throws IOException, ParseException {
700         System.out.println("\n === Test: " + getMethodName() + " ===");
701 
702         PoshPlan parsePlan = parsePlan("testplans/012TestAPProcessing.lap");
703         PoshEngine poshEngine = new PoshEngine(parsePlan);
704 
705 
706         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
707                     new PrintPrimitive("succeed", true),
708                     new PrintPrimitive("fail", false),
709                     new PrintPrimitive("ok1", ActionResult.FINISHED),
710                     new PrintPrimitive("ok2", ActionResult.FINISHED),
711                     new PrintPrimitive("ok3", ActionResult.FINISHED),
712                     new PrintPrimitive("fail1", ActionResult.FAILED),
713                     new PrintPrimitive("last", ActionResult.FINISHED)
714                 });
715         // test order
716         String[][] primitivesOrder = {
717             // put testAP to stack
718             new String[]{"fail", "succeed"},
719             // put ok1 to top of stack
720             new String[]{"fail", "succeed"},
721             // ok1 will be fired
722             new String[]{"fail", "succeed", "ok1"},
723             // put ok2 to top of stack
724             new String[]{"fail", "succeed"},
725             // ok2 will be fired
726             new String[]{"fail", "succeed", "ok2"},
727             // ok3 to top of stack
728             new String[]{"fail", "succeed"},
729             // fire ok3
730             new String[]{"fail", "succeed", "ok3"},
731             // put fail1 to top of stack
732             new String[]{"fail", "succeed"},
733             // fire fail1 = reset stack, because testAP failed
734             new String[]{"fail", "succeed", "fail1"}
735         };
736 
737         // because stack is reseted after last fail, you can repeat multiple times
738         for (int i = 0; i < 10; i++) {
739             testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder);
740         }
741     }
742 
743     /**
744      * Test that DC will correctly switch between three DE
745      */
746     @Test
747     public void test013TestDC() throws IOException, ParseException {
748         System.out.println("\n === Test: " + getMethodName() + " ===");
749 
750         PoshPlan parsePlan = parsePlan("testplans/013DCSwitch.lap");
751         PoshEngine poshEngine = new PoshEngine(parsePlan);
752 
753         // ok are enabled according to phase, ok125 means ok in phase 1,2 and 5, otherwise fail.
754         PrintPrimitive ok125 = new PrintPrimitive("ok125", true);
755         PrintPrimitive ok3 = new PrintPrimitive("ok3", true);
756         PrintPrimitive ok1234 = new PrintPrimitive("ok1234", true);
757         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
758                     new PrintPrimitive("fail", false),
759                     ok125, ok3, ok1234,
760                     new PrintPrimitive("action1", ActionResult.FAILED),
761                     new PrintPrimitive("action2", ActionResult.FINISHED),
762                     new PrintPrimitive("action3", ActionResult.FINISHED)
763                 });
764 
765         String[][] primitivesOrder1 = { // phase 1
766             // put action1 to the stack
767             new String[]{"fail", "ok125"},
768             new String[]{"fail", "ok125", "action1"}
769         };
770         String[][] primitivesOrder2 = { // phase 2
771             new String[]{"fail", "ok125"},
772             new String[]{"fail", "ok125", "action1"}
773         };
774         String[][] primitivesOrder3 = { // phase 3
775             // put action2 to top of stack
776             new String[]{"fail", "ok125", "ok3"},
777             new String[]{"fail", "ok125", "ok3", "action2"}
778         };
779         String[][] primitivesOrder4 = { // phase 4
780             new String[]{"fail", "ok125", "ok3", "ok1234"},
781             new String[]{"fail", "ok125", "ok3", "ok1234", "action3"}
782         };
783         String[][] primitivesOrder5 = { // phase 5
784             new String[]{"fail", "ok125"},
785             new String[]{"fail", "ok125", "action1"}
786         };
787 
788         // phase 1
789         ok125.setReturnValue(true);
790         ok3.setReturnValue(false);
791         ok1234.setReturnValue(true);
792         testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder1);
793         // phase 2
794         ok125.setReturnValue(true);
795         ok3.setReturnValue(false);
796         ok1234.setReturnValue(true);
797         testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder2);
798         // phase 3
799         ok125.setReturnValue(false);
800         ok3.setReturnValue(true);
801         ok1234.setReturnValue(true);
802         testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder3);
803         // phase 4
804         ok125.setReturnValue(false);
805         ok3.setReturnValue(false);
806         ok1234.setReturnValue(true);
807         testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder4);
808         // phase 5
809         ok125.setReturnValue(true);
810         ok3.setReturnValue(false);
811         ok1234.setReturnValue(false);
812         testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder5);
813     }
814 
815     private class ValuePrimitive<T> implements ITestPrimitive {
816 
817         private String name;
818         private T value;
819         private int triggered = 0;
820 
821         public ValuePrimitive(String name, T initialValue) {
822             this.name = name;
823             this.value = initialValue;
824         }
825 
826         public void setValue(T value) {
827             this.value = value;
828         }
829 
830         @Override
831         public String getName() {
832             return name;
833         }
834 
835         @Override
836         public Object work(VariableContext ctx) {
837             ++triggered;
838             return value;
839         }
840 
841         @Override
842         public int triggered() {
843             return triggered;
844         }
845     }
846 
847     @Test
848     public void test014Comparison() throws IOException, ParseException {
849         System.out.println("\n === Test: " + getMethodName() + " ===");
850 
851         PoshPlan parsePlan = parsePlan("testplans/014Comparison.lap");
852         PoshEngine poshEngine = new PoshEngine(parsePlan);
853 
854         ValuePrimitive<Integer> value = new ValuePrimitive<Integer>("value", 0);
855 
856         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
857                     value, new PrintPrimitive("action", ActionResult.FAILED)
858                 });
859 
860         for (int i = 0; i < 14; i++) {
861             value.setValue(i);
862             assertTrue(poshEngine.evaluatePlan(executor).result != EvaluationResult.GOAL_SATISFIED);
863         }
864 
865         for (int i = 14; i < 100; i++) {
866             value.setValue(i);
867             assertTrue(" Loop " + i, poshEngine.evaluatePlan(executor).result == EvaluationResult.GOAL_SATISFIED);
868         }
869     }
870 
871     /**
872      * Test if AP in another AP is working as expected. In this case, every
873      * action is OK (=doesn't fail)
874      */
875     @Test
876     public void test015APDouble() throws IOException, ParseException {
877         System.out.println("\n === Test: " + getMethodName() + " ===");
878 
879         PoshPlan parsePlan = parsePlan("testplans/015APdouble.lap");
880         PoshEngine poshEngine = new PoshEngine(parsePlan);
881 
882 
883         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
884                     new PrintPrimitive("action0", ActionResult.FINISHED),
885                     new PrintPrimitive("action1", ActionResult.FINISHED),
886                     new PrintPrimitive("action2", ActionResult.FINISHED),
887                     new PrintPrimitive("action3", ActionResult.FINISHED),
888                     new PrintPrimitive("action4", ActionResult.FINISHED)
889                 });
890         // test order
891         String[][] primitivesOrder = {
892             // put testAP1 to stack
893             new String[]{},
894             // put action0 to top of stack
895             new String[]{},
896             // ok1 will be fired
897             new String[]{"action0"},
898             // put testAP2 to top of stack
899             new String[]{},
900             // action1 TOS
901             new String[]{},
902             // action1 fire
903             new String[]{"action1"},
904             // action2 TOS
905             new String[]{},
906             // action2 fire
907             new String[]{"action2"},
908             // action3 TOS
909             new String[]{},
910             // action3 fire
911             new String[]{"action3"},
912             // surface from testAP2
913             new String[]{},
914             // action4 TOS
915             new String[]{},
916             // action4 fire
917             new String[]{"action4"},
918             // surface from testAP1
919             new String[]{},};
920 
921         // because stack is reseted after last fail, you can repeat multiple times
922         for (int i = 0; i < 10; i++) {
923             testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder);
924         }
925     }
926 
927     /**
928      * Ap in AP, one action in deeper AP fails. Does engine behave correctly?
929      *
930      * @throws IOException
931      * @throws ParseException
932      */
933     @Test
934     public void test016APDoubleFail() throws IOException, ParseException {
935         System.out.println("\n === Test: " + getMethodName() + " ===");
936 
937         PoshPlan parsePlan = parsePlan("testplans/016APdoubleFail.lap");
938         PoshEngine poshEngine = new PoshEngine(parsePlan);
939 
940 
941         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
942                     new PrintPrimitive("action0", ActionResult.FINISHED),
943                     new PrintPrimitive("action1", ActionResult.FINISHED),
944                     new PrintPrimitive("action2", ActionResult.FAILED),
945                     new PrintPrimitive("action3", ActionResult.FINISHED),
946                     new PrintPrimitive("action4", ActionResult.FINISHED)
947                 });
948         // test order
949         String[][] primitivesOrder = {
950             // put testAP1 to stack
951             new String[]{},
952             // put action0 to top of stack
953             new String[]{},
954             // ok1 will be fired
955             new String[]{"action0"},
956             // put testAP2 to top of stack
957             new String[]{},
958             // action1 TOS
959             new String[]{},
960             // action1 fire
961             new String[]{"action1"},
962             // action2 TOS
963             new String[]{},
964             // action2 fire and fails! By failing, the whole stack is unrolled
965             new String[]{"action2"},};
966 
967         // because stack is reseted after last fail, you can repeat multiple times
968         for (int i = 0; i < 10; i++) {
969             testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder);
970         }
971     }
972 
973     /**
974      * Test if multiple CE in C are correctly evaluated. I should choose ce2 (=
975      * highest ce with valid trigger), go into testAP and back to testC. Repeat
976      * 20x
977      */
978     @Test
979     public void test017MultiCE() throws IOException, ParseException {
980         System.out.println("\n === Test: " + getMethodName() + " ===");
981 
982         PoshPlan parsePlan = parsePlan("testplans/017MultiCE.lap");
983         PoshEngine poshEngine = new PoshEngine(parsePlan);
984 
985         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
986                     new PrintPrimitive("tr1", false),
987                     new PrintPrimitive("tr2", true),
988                     new PrintPrimitive("tr3", false),
989                     new PrintPrimitive("action", ActionResult.FINISHED),
990                     new PrintPrimitive("action0", ActionResult.FINISHED),
991                     new PrintPrimitive("action1", ActionResult.FINISHED)
992                 });
993         
994         String[] traverseChoices = new String[]{
995             "/P:0/DC:0/DE:0",
996 
997             "/P:0/DC:0/DE:0",
998             "/P:0/DC:0/DE:0/A:0/C:0",
999             "/P:0/DC:0/DE:0/A:0/C:0/CE:0/S:0",
1000             "/P:0/DC:0/DE:0/A:0/C:0/CE:1/S:0",
1001 
1002             "/P:0/DC:0/DE:0",
1003             "/P:0/DC:0/DE:0/A:0/C:0/CE:1",
1004 
1005             "/P:0/DC:0/DE:0",
1006             "/P:0/DC:0/DE:0/A:0/C:0/CE:1/A:0/AP:0",
1007 
1008             "/P:0/DC:0/DE:0",
1009             "/P:0/DC:0/DE:0/A:0/C:0/CE:1/A:0/AP:0/A:0",
1010 
1011             "/P:0/DC:0/DE:0",
1012             "/P:0/DC:0/DE:0/A:0/C:0/CE:1/A:0/AP:0",
1013 
1014             "/P:0/DC:0/DE:0",
1015             "/P:0/DC:0/DE:0/A:0/C:0/CE:1/A:0/AP:0/A:1",
1016 
1017             "/P:0/DC:0/DE:0",
1018             "/P:0/DC:0/DE:0/A:0/C:0/CE:1/A:0/AP:0",
1019 
1020             "/P:0/DC:0/DE:0",
1021             "/P:0/DC:0/DE:0/A:0/C:0/CE:1",
1022 
1023             "/P:0/DC:0/DE:0",
1024             "/P:0/DC:0/DE:0/A:0/C:0",
1025         };
1026         for (int i=0; i<20; i++) {
1027             assertEngineProgress(poshEngine, executor, traverseChoices);
1028         }
1029     }
1030 
1031     /**
1032      * When everything is OK, I should get stuck in testC2 (no another DC to
1033      * change)
1034      */
1035     @Test
1036     public void test018MultiC() throws IOException, ParseException {
1037         System.out.println("\n === Test: " + getMethodName() + " ===");
1038 
1039         PoshPlan parsePlan = parsePlan("testplans/018MultiC.lap");
1040         PoshEngine poshEngine = new PoshEngine(parsePlan);
1041 
1042         ValuePrimitive<Boolean> tr1 = new ValuePrimitive<Boolean>("tr1", true);
1043         ValuePrimitive<Boolean> tr2 = new ValuePrimitive<Boolean>("tr2", true);
1044         ValuePrimitive<Boolean> action = new ValuePrimitive<Boolean>("action", true); // true is auto-evaluated to ActionResult.FINISHED
1045 
1046         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
1047                     tr1, tr2, action
1048                 });
1049 
1050         String[] traverseTwoCompetences = new String[]{
1051             "/P:0/DC:0/DE:0",
1052             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0",
1053             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0",
1054             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0/A:0/C:1",
1055             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0/A:0/C:1/CE:0",
1056             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0/A:0/C:1/CE:0/A:0",
1057             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0/A:0/C:1/CE:0",
1058             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0/A:0/C:1",
1059             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0/CE:0",
1060             "/P:0/DC:0/DE:0", "/P:0/DC:0/DE:0/A:0/C:0",
1061         };
1062         for (int i=0; i<10; i++) {
1063             assertEngineProgress(poshEngine, executor, traverseTwoCompetences);
1064         }
1065     }
1066 
1067     /**
1068      * Test that variable context is properly passed into sense
1069      */
1070     @Test
1071     public void test020SenseCtx() throws IOException, ParseException {
1072         System.out.println("\n === Test: " + getMethodName() + " ===");
1073 
1074         PoshPlan parsePlan = parsePlan("testplans/020SenseCtx.lap");
1075         PoshEngine poshEngine = new PoshEngine(parsePlan);
1076 
1077 
1078         StateWorkExecutor stateWorkExecutor = new StateWorkExecutor();
1079 
1080         stateWorkExecutor.addAction("doNothing", new IAction() {
1081 
1082             @Override
1083             public void init(VariableContext ctx) {
1084             }
1085 
1086             @Override
1087             public ActionResult run(VariableContext ctx) {
1088                 return ActionResult.FINISHED;
1089             }
1090 
1091             @Override
1092             public void done(VariableContext ctx) {
1093             }
1094         });
1095         stateWorkExecutor.addSense("playerClose", new ISense() {
1096 
1097             @Override
1098             public Object query(VariableContext ctx) {
1099                 if (ctx.size() != 3) {
1100                     fail("Size is not 3, but " + ctx.size());
1101                 }
1102 
1103                 assertEquals(ctx.getValue("0"), 12.4);
1104                 assertEquals(ctx.getValue("$second"), "brutal");
1105                 assertEquals(ctx.getValue("$third"), "lala");
1106 
1107                 return true;
1108             }
1109         });
1110 
1111         // put competence to the stack
1112         poshEngine.evaluatePlan(stateWorkExecutor);
1113         // evaluate
1114         poshEngine.evaluatePlan(stateWorkExecutor);
1115     }
1116 
1117     @Test
1118     public void test021TestEqualTrue() throws IOException, ParseException {
1119         System.out.println("\n === Test: " + getMethodName() + " ===");
1120 
1121         PoshPlan parsePlan = parsePlan("testplans/021TestEqualTrue.lap");
1122         PoshEngine poshEngine = new PoshEngine(parsePlan);
1123 
1124         PrintPrimitive something = new PrintPrimitive("something", ActionResult.FINISHED);
1125         PrintPrimitive nothing = new PrintPrimitive("doNothing", ActionResult.FINISHED);
1126 
1127         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
1128                     new PrintPrimitive("succeed", true),
1129                     new PrintPrimitive("fail", false),
1130                     something, nothing
1131                 });
1132         // test order
1133         String[][] primitivesOrder = {
1134             // put 'something' TOS
1135             new String[]{"fail", "succeed"},
1136             new String[]{"fail", "succeed", "something"},};
1137 
1138         // because stack is reseted after last fail, you can repeat multiple times
1139         for (int i = 0; i < 20; i++) {
1140             testPrimitiveExecutionOrder(poshEngine, executor, primitivesOrder);
1141         }
1142     }
1143 
1144     @Test
1145     public void test022TestAdopt() throws IOException, ParseException {
1146         System.out.println("\n === Test: " + getMethodName() + " ===");
1147 
1148         PoshPlan parsePlan = parsePlan("testplans/022TestAdopt.lap");
1149         PoshEngine poshEngine = new PoshEngine(parsePlan);
1150 
1151         PrintPrimitive action0 = new PrintPrimitive("action0", ActionResult.FINISHED);
1152         PrintPrimitive action1 = new PrintPrimitive("action1", ActionResult.FINISHED);
1153         PrintPrimitive action2 = new PrintPrimitive("action2", ActionResult.FINISHED);
1154 
1155         PrintPrimitive succeed0 = new PrintPrimitive("succeed0", true);
1156         PrintPrimitive succeed1 = new PrintPrimitive("succeed1", true);
1157         PrintPrimitive succeed2 = new PrintPrimitive("succeed2", true);
1158 
1159         PrintPrimitive fail = new PrintPrimitive("fail", false);
1160 
1161         PrintPrimitive sometime = new PrintPrimitive("sometime", false);
1162 
1163 
1164         TestWorkExecutor executor = new TestWorkExecutor(new ITestPrimitive[]{
1165                     succeed0, succeed1, succeed2, fail, sometime, action0, action1, action2
1166                 });
1167 
1168         System.out.println("--- CYCLE ---");
1169         System.out.println("put testC1 on stack");
1170         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1171         printDrives(poshEngine);
1172 
1173 
1174         System.out.println("--- CYCLE ---");
1175         System.out.println("put ce2 on stack");
1176         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1177         printDrives(poshEngine);
1178 
1179         System.out.println("--- CYCLE ---");
1180         System.out.println("put adoptTestC2 on stack");
1181         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1182         printDrives(poshEngine);
1183 
1184         System.out.println("--- CYCLE ---");
1185         System.out.println("put testC2 on stack");
1186         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1187         printDrives(poshEngine);
1188 
1189         System.out.println("--- CYCLE ---");
1190         System.out.println("put ce3 on stack");
1191         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1192         printDrives(poshEngine);
1193 
1194         System.out.println("--- CYCLE ---");
1195         System.out.println("put action2 on stack");
1196         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1197         printDrives(poshEngine);
1198 
1199         System.out.println("--- CYCLE ---");
1200         System.out.println("put execute action2, delete it from stack");
1201         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1202         printDrives(poshEngine);
1203         assertTrue(action2.triggered() == 1);
1204 
1205         System.out.println("--- CYCLE ---");
1206         System.out.println("let 'morePrior' drive to interrupt previous drive");
1207         sometime.setReturnValue(true);
1208         System.out.println("interrupt 'default' drive, put action0 on stack");
1209         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1210         printDrives(poshEngine);
1211         assertTrue(action2.triggered() == 1);
1212 
1213         System.out.println("--- CYCLE ---");
1214         System.out.println("execute action0, remove it from stack");
1215         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1216         printDrives(poshEngine);
1217         assertTrue(action0.triggered() == 1);
1218         assertTrue(action2.triggered() == 1);
1219 
1220         System.out.println("--- CYCLE ---");
1221         System.out.println("return to 'default' drive");
1222         sometime.setReturnValue(false);
1223         System.out.println("drive's stack should already be cut back to 'adoptTestC2', execute 'adoptTestC2' put testC2 on stack");
1224         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1225         printDrives(poshEngine);
1226         assertTrue(action0.triggered() == 1);
1227         assertTrue(action2.triggered() == 1);
1228 
1229         System.out.println("--- CYCLE ---");
1230         System.out.println("put ce3 on stack");
1231         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1232         printDrives(poshEngine);
1233         assertTrue(action0.triggered() == 1);
1234         assertTrue(action2.triggered() == 1);
1235 
1236         System.out.println("--- CYCLE ---");
1237         System.out.println("put action2 on stack");
1238         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1239         printDrives(poshEngine);
1240         assertTrue(action0.triggered() == 1);
1241         assertTrue(action2.triggered() == 1);
1242 
1243         System.out.println("--- CYCLE ---");
1244         System.out.println("execute action2, remove it from stack");
1245         assertEquals(EvaluationResult.ELEMENT_FIRED, poshEngine.evaluatePlan(executor).result);
1246         printDrives(poshEngine);
1247         assertTrue(action0.triggered() == 1);
1248         assertTrue(action2.triggered() == 2);
1249     }
1250 
1251     private void printDrives(PoshEngine poshEngine) {
1252         for (int i = 0; i < poshEngine.getDECount(); ++i) {
1253             System.out.println("Stack(" + poshEngine.getDEName(i) + "): " + poshEngine.getStackForDE(i));
1254         }
1255     }
1256 }