1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.statemachine;
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertTrue;
24
25 import java.util.LinkedList;
26
27 import org.apache.mina.statemachine.annotation.Transition;
28 import org.apache.mina.statemachine.annotation.Transitions;
29 import org.apache.mina.statemachine.event.Event;
30 import org.apache.mina.statemachine.transition.MethodTransition;
31 import org.junit.Test;
32
33
34
35
36
37
38 public class StateMachineProxyBuilderTest {
39 @Test
40 public void testReentrantStateMachine() throws Exception {
41 ReentrantStateMachineHandler handler = new ReentrantStateMachineHandler();
42
43 State s1 = new State("s1");
44 State s2 = new State("s2");
45 State s3 = new State("s3");
46
47 s1.addTransition(new MethodTransition("call1", s2, handler));
48 s2.addTransition(new MethodTransition("call2", s3, handler));
49 s3.addTransition(new MethodTransition("call3", handler));
50
51 StateMachine sm = new StateMachine(new State[] { s1, s2, s3 }, "s1");
52 Reentrant reentrant = new StateMachineProxyBuilder().create(Reentrant.class, sm);
53 reentrant.call1(reentrant);
54 assertTrue(handler.finished);
55 }
56
57 @Test
58 public void testTapeDeckStateMachine() throws Exception {
59 TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler();
60
61 State parent = new State("parent");
62 State s1 = new State("s1", parent);
63 State s2 = new State("s2", parent);
64 State s3 = new State("s3", parent);
65 State s4 = new State("s4", parent);
66 State s5 = new State("s5", parent);
67
68 parent.addTransition(new MethodTransition("*", "error", handler));
69 s1.addTransition(new MethodTransition("insert", s2, "inserted", handler));
70 s2.addTransition(new MethodTransition("start", s3, "playing", handler));
71 s3.addTransition(new MethodTransition("stop", s4, "stopped", handler));
72 s3.addTransition(new MethodTransition("pause", s5, "paused", handler));
73 s4.addTransition(new MethodTransition("eject", s1, "ejected", handler));
74 s5.addTransition(new MethodTransition("pause", s3, "playing", handler));
75
76 StateMachine sm = new StateMachine(new State[] { s1, s2, s3, s4, s5 }, "s1");
77 TapeDeck player = new StateMachineProxyBuilder().create(TapeDeck.class, sm);
78 player.insert("Kings of convenience - Riot on an empty street");
79 player.start();
80 player.pause();
81 player.pause();
82 player.eject();
83 player.stop();
84 player.eject();
85
86 LinkedList<String> messages = handler.messages;
87 assertEquals("Tape 'Kings of convenience - Riot on an empty street' inserted", messages.removeFirst());
88 assertEquals("Playing", messages.removeFirst());
89 assertEquals("Paused", messages.removeFirst());
90 assertEquals("Playing", messages.removeFirst());
91 assertEquals("Error: Cannot eject at this time", messages.removeFirst());
92 assertEquals("Stopped", messages.removeFirst());
93 assertEquals("Tape ejected", messages.removeFirst());
94 assertTrue(messages.isEmpty());
95 }
96
97 @Test
98 public void testTapeDeckStateMachineAnnotations() throws Exception {
99 TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler();
100
101 StateMachine sm = StateMachineFactory.getInstance(Transition.class).create(TapeDeckStateMachineHandler.S1, handler);
102
103 TapeDeck player = new StateMachineProxyBuilder().create(TapeDeck.class, sm);
104 player.insert("Kings of convenience - Riot on an empty street");
105 player.start();
106 player.pause();
107 player.pause();
108 player.eject();
109 player.stop();
110 player.eject();
111
112 LinkedList<String> messages = handler.messages;
113 assertEquals("Tape 'Kings of convenience - Riot on an empty street' inserted", messages.removeFirst());
114 assertEquals("Playing", messages.removeFirst());
115 assertEquals("Paused", messages.removeFirst());
116 assertEquals("Playing", messages.removeFirst());
117 assertEquals("Error: Cannot eject at this time", messages.removeFirst());
118 assertEquals("Stopped", messages.removeFirst());
119 assertEquals("Tape ejected", messages.removeFirst());
120 assertTrue(messages.isEmpty());
121 }
122
123 public interface Reentrant {
124 void call1(Reentrant proxy);
125 void call2(Reentrant proxy);
126 void call3(Reentrant proxy);
127 }
128
129 public static class ReentrantStateMachineHandler {
130 private boolean finished = false;
131
132 public void call1(Reentrant proxy) {
133 proxy.call2(proxy);
134 }
135
136 public void call2(Reentrant proxy) {
137 proxy.call3(proxy);
138 }
139
140 public void call3(Reentrant proxy) {
141 finished = true;
142 }
143 }
144
145 public interface TapeDeck {
146 void insert(String name);
147 void eject();
148 void start();
149 void pause();
150 void stop();
151 }
152
153 public static class TapeDeckStateMachineHandler {
154 @org.apache.mina.statemachine.annotation.State public static final String PARENT = "parent";
155 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S1 = "s1";
156 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S2 = "s2";
157 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S3 = "s3";
158 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S4 = "s4";
159 @org.apache.mina.statemachine.annotation.State(PARENT) public static final String S5 = "s5";
160
161 private LinkedList<String> messages = new LinkedList<String>();
162
163 @Transition(on = "insert", in = "s1", next = "s2")
164 public void inserted(String name) {
165 messages.add("Tape '" + name + "' inserted");
166 }
167
168 @Transition(on = "eject", in = "s4", next = "s1")
169 public void ejected() {
170 messages.add("Tape ejected");
171 }
172
173 @Transitions({@Transition( on = "start", in = "s2", next = "s3" ),
174 @Transition( on = "pause", in = "s5", next = "s3" )})
175 public void playing() {
176 messages.add("Playing");
177 }
178
179 @Transition(on = "pause", in = "s3", next = "s5")
180 public void paused() {
181 messages.add("Paused");
182 }
183
184 @Transition(on = "stop", in = "s3", next = "s4")
185 public void stopped() {
186 messages.add("Stopped");
187 }
188
189 @Transition(on = "*", in = "parent")
190 public void error(Event event) {
191 messages.add("Error: Cannot " + event.getId() + " at this time");
192 }
193 }
194 }