1   /*
2    * Created on 25-Oct-2006
3    *
4    */
5   package com.tomgibara.pronto.state;
6   
7   import com.tomgibara.pronto.core.ProntoException;
8   
9   import junit.framework.TestCase;
10  
11  public class StateEngineTest extends TestCase {
12  
13      static StateActivator<String, Integer, Object> trivialActivator = new StateActivator<String, Integer, Object>() {
14          public void changeState(String state) throws ProntoStateException, RuntimeException {
15              /* do nothing */
16          }
17  
18          public void transitionState(StateTransition<String, Integer> transition, Object parameter)
19                  throws ProntoStateException, RuntimeException {
20              /* do nothing */
21          }
22      };
23  
24      static StateActivator<String, Integer, Object> failingActivator = new StateActivator<String, Integer, Object>() {
25          public void changeState(String state) throws ProntoStateException, RuntimeException {
26              /* do nothing */
27          }
28  
29          public void transitionState(StateTransition<String, Integer> transition, Object parameter)
30                  throws ProntoStateException, RuntimeException {
31              throw new RuntimeException("failed");
32          }
33      };
34  
35      public void testCreate() {
36          StateFactory factory = StateFactory.getInstance();
37          StateEngine<String, Integer, Object> engine = factory.<String, Integer, Object> newEngine(factory
38                  .<String, Integer> emptyStateGraph(), trivialActivator);
39      }
40  
41      public void testInitialPossibleStates() {
42          StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B"),
43                  new TestingActivator());
44          assertEquals(TestUtil.stateSet("A;B"), engine.getPossibleStates());
45      }
46  
47      public void testSetFirstState1() {
48          TestingActivator activator = new TestingActivator();
49          StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B"), activator);
50          engine.setState("A");
51          assertEquals("A", engine.getState());
52          assertEquals("A", activator.states.getLast());
53      }
54  
55      public void testSetFirstState2() {
56          TestingActivator activator = new TestingActivator();
57          StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B"), activator);
58          engine.setState("B");
59          assertEquals("B", engine.getState());
60          assertEquals("B", activator.states.getLast());
61      }
62  
63      public void testSetBadFirstState() {
64          TestingActivator activator = new TestingActivator();
65          StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B"), activator);
66          try {
67              engine.setState("C");
68              fail();
69          } catch (ProntoException e) {
70              /* expected */
71              assert (activator.states.isEmpty());
72          }
73      }
74  
75      public void testAnonymousTransition() {
76          TestingActivator activator = new TestingActivator();
77          StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B"), activator);
78          engine.setState("A");
79          engine.transition(null, null, null);
80          assertEquals(TestUtil.transitionList("A->B"), activator.transitions);
81      }
82  
83      public void testBadAnonymousTransition() {
84          TestingActivator activator = new TestingActivator();
85          StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B;A->C"), activator);
86          engine.setState("A");
87          try {
88              engine.transition(null, null, null);
89              fail();
90          } catch (ProntoException e) {
91              /* expected */
92              assertTrue(activator.transitions.isEmpty());
93          }
94      }
95  
96      public void testLabelledTransition() {
97          TestingActivator activator = new TestingActivator();
98          StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A-1->B;A-2->C"), activator);
99          engine.setState("A");
100         engine.transition(null, 1, null);
101         assertEquals(TestUtil.transitionList("A-1->B"), activator.transitions);
102     }
103 
104     public void testBadLabelledTransition() {
105         TestingActivator activator = new TestingActivator();
106         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A-1->B;A-2->C"), activator);
107         engine.setState("A");
108         try {
109             engine.transition(null, 3, null);
110             fail();
111         } catch (ProntoException e) {
112             /* expected */
113             assert (activator.transitions.isEmpty());
114         }
115     }
116     
117     public void testStateTransition() {
118         TestingActivator activator = new TestingActivator();
119         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B;A->C"), activator);
120         engine.setState("A");
121         engine.transition("B", null, null);
122         assertEquals(TestUtil.transitionList("A->B"), activator.transitions);
123     }
124 
125     public void testCircularTransition() {
126         TestingActivator activator = new TestingActivator();
127         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B;A->A"), activator);
128         engine.setState("A");
129         engine.transition("A", null, null);
130         assertEquals(TestUtil.transitionList("A->A"), activator.transitions);
131     }
132 
133     public void testBadStateTransition() {
134         TestingActivator activator = new TestingActivator();
135         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A-1->B;A-2->C"), activator);
136         engine.setState("A");
137         try {
138             engine.transition("D", null, null);
139             fail();
140         } catch (ProntoException e) {
141             /* expected */
142             assert (activator.transitions.isEmpty());
143         }
144     }
145 
146     public void testSpecificTransition() {
147         TestingActivator activator = new TestingActivator();
148         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A-1->B;A-2->B;A-1->C;A-2->C"), activator);
149         engine.setState("A");
150         engine.transition("B", 1, null);
151         assertEquals(TestUtil.transitionList("A-1->B"), activator.transitions);
152     }
153 
154 
155     public void testLinearTransitionPath() {
156         TestingActivator activator = new TestingActivator();
157         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B;B->C;C->D"),
158                 activator);
159         engine.setState("A");
160         engine.pathTransition("D", null, PathType.uniqueTransitions, null);
161         assertEquals(TestUtil.transitionList("A->B;B->C;C->D"), activator.transitions);
162     }
163 
164     public void testCircularTransitionPath() {
165         TestingActivator activator = new TestingActivator();
166         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B;B->C;C->A"),
167                 activator);
168         engine.setState("A");
169         engine.pathTransition("A", null, PathType.uniqueTransitions, null);
170         assertEquals(TestUtil.transitionList("A->B;B->C;C->A"), activator.transitions);
171     }
172 
173     public void testLabelledTransitionPath() {
174         TestingActivator activator = new TestingActivator();
175         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A-1->B;A-2->C;A-3->D"),
176                 activator);
177         engine.setState("A");
178         engine.pathTransition("C", 2, PathType.uniqueTransitions, null);
179         assertEquals(TestUtil.transitionList("A-2->C"), activator.transitions);
180     }
181 
182     public void testLabelledTransitionPaths() {
183         TestingActivator activator = new TestingActivator();
184         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil
185                 .makeGraph("A-1->B;B-1->C;B-2->D;C-1->E;D-2->E"), activator);
186         engine.setState("A");
187         engine.pathTransition("E", 1, PathType.uniqueTransitions, null);
188         assertEquals(TestUtil.transitionList("A-1->B;B-1->C;C-1->E"), activator.transitions);
189     }
190 
191     public void testFailingTransitionPath() {
192         StateEngine<String, Integer, Object> engine = TestUtil.makeEngine(TestUtil.makeGraph("A->B;B->C"),
193                 failingActivator);
194         engine.setState("A");
195         try {
196             engine.pathTransition("C", null, PathType.uniqueTransitions, null);
197             fail("operation succeeded unexpectedly");
198         } catch (ProntoStateException e) {
199             assertEquals(TestUtil.stateSet("A;B"), engine.getPossibleStates());
200         }
201         try {
202             engine.setState("C");
203             fail("operation succeeded unexpectedly");
204         } catch (ProntoStateException e) {
205             // expected
206         }
207         engine.setState("B");
208     }
209 
210 }