001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020: package org.apache.mina.statemachine;
021:
022: import java.util.LinkedList;
023:
024: import junit.framework.TestCase;
025:
026: import org.apache.mina.statemachine.annotation.Transition;
027: import org.apache.mina.statemachine.annotation.Transitions;
028: import org.apache.mina.statemachine.event.Event;
029: import org.apache.mina.statemachine.transition.MethodTransition;
030:
031: /**
032: * Tests {@link StateMachineProxyFactory}.
033: *
034: * @author The Apache MINA Project (dev@mina.apache.org)
035: * @version $Rev: 600096 $, $Date: 2007-12-01 05:00:27 -0700 (Sat, 01 Dec 2007) $
036: */
037: public class StateMachineProxyFactoryTest extends TestCase {
038:
039: public void testReentrantStateMachine() throws Exception {
040: ReentrantStateMachineHandler handler = new ReentrantStateMachineHandler();
041:
042: State s1 = new State("s1");
043: State s2 = new State("s2");
044: State s3 = new State("s3");
045:
046: s1.addTransition(new MethodTransition("call1", s2, handler));
047: s2.addTransition(new MethodTransition("call2", s3, handler));
048: s3.addTransition(new MethodTransition("call3", handler));
049:
050: StateMachine sm = new StateMachine(new State[] { s1, s2, s3 },
051: "s1");
052: Reentrant reentrant = StateMachineProxyFactory.create(
053: Reentrant.class, sm);
054: reentrant.call1(reentrant);
055: assertTrue(handler.finished);
056: }
057:
058: public void testTapeDeckStateMachine() throws Exception {
059: TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler();
060:
061: State parent = new State("parent");
062: State s1 = new State("s1", parent);
063: State s2 = new State("s2", parent);
064: State s3 = new State("s3", parent);
065: State s4 = new State("s4", parent);
066: State s5 = new State("s5", parent);
067:
068: parent
069: .addTransition(new MethodTransition("*", "error",
070: handler));
071: s1.addTransition(new MethodTransition("insert", s2, "inserted",
072: handler));
073: s2.addTransition(new MethodTransition("start", s3, "playing",
074: handler));
075: s3.addTransition(new MethodTransition("stop", s4, "stopped",
076: handler));
077: s3.addTransition(new MethodTransition("pause", s5, "paused",
078: handler));
079: s4.addTransition(new MethodTransition("eject", s1, "ejected",
080: handler));
081: s5.addTransition(new MethodTransition("pause", s3, "playing",
082: handler));
083:
084: StateMachine sm = new StateMachine(new State[] { s1, s2, s3,
085: s4, s5 }, "s1");
086: TapeDeck player = StateMachineProxyFactory.create(
087: TapeDeck.class, sm);
088: player.insert("Kings of convenience - Riot on an empty street");
089: player.start();
090: player.pause();
091: player.pause();
092: player.eject();
093: player.stop();
094: player.eject();
095:
096: LinkedList<String> messages = handler.messages;
097: assertEquals(
098: "Tape 'Kings of convenience - Riot on an empty street' inserted",
099: messages.removeFirst());
100: assertEquals("Playing", messages.removeFirst());
101: assertEquals("Paused", messages.removeFirst());
102: assertEquals("Playing", messages.removeFirst());
103: assertEquals("Error: Cannot eject at this time", messages
104: .removeFirst());
105: assertEquals("Stopped", messages.removeFirst());
106: assertEquals("Tape ejected", messages.removeFirst());
107: assertTrue(messages.isEmpty());
108: }
109:
110: public void testTapeDeckStateMachineAnnotations() throws Exception {
111: TapeDeckStateMachineHandler handler = new TapeDeckStateMachineHandler();
112:
113: StateMachine sm = StateMachineFactory.getInstance(
114: Transition.class).create(
115: TapeDeckStateMachineHandler.S1, handler);
116:
117: TapeDeck player = StateMachineProxyFactory.create(
118: TapeDeck.class, sm);
119: player.insert("Kings of convenience - Riot on an empty street");
120: player.start();
121: player.pause();
122: player.pause();
123: player.eject();
124: player.stop();
125: player.eject();
126:
127: LinkedList<String> messages = handler.messages;
128: assertEquals(
129: "Tape 'Kings of convenience - Riot on an empty street' inserted",
130: messages.removeFirst());
131: assertEquals("Playing", messages.removeFirst());
132: assertEquals("Paused", messages.removeFirst());
133: assertEquals("Playing", messages.removeFirst());
134: assertEquals("Error: Cannot eject at this time", messages
135: .removeFirst());
136: assertEquals("Stopped", messages.removeFirst());
137: assertEquals("Tape ejected", messages.removeFirst());
138: assertTrue(messages.isEmpty());
139: }
140:
141: public interface Reentrant {
142: void call1(Reentrant proxy);
143:
144: void call2(Reentrant proxy);
145:
146: void call3(Reentrant proxy);
147: }
148:
149: public static class ReentrantStateMachineHandler {
150: private boolean finished = false;
151:
152: public void call1(Reentrant proxy) {
153: proxy.call2(proxy);
154: }
155:
156: public void call2(Reentrant proxy) {
157: proxy.call3(proxy);
158: }
159:
160: public void call3(@SuppressWarnings("unused")
161: Reentrant proxy) {
162: finished = true;
163: }
164: }
165:
166: public interface TapeDeck {
167: void insert(String name);
168:
169: void eject();
170:
171: void start();
172:
173: void pause();
174:
175: void stop();
176: }
177:
178: public static class TapeDeckStateMachineHandler {
179: @org.apache.mina.statemachine.annotation.State
180: public static final String PARENT = "parent";
181: @org.apache.mina.statemachine.annotation.State(PARENT)
182: public static final String S1 = "s1";
183: @org.apache.mina.statemachine.annotation.State(PARENT)
184: public static final String S2 = "s2";
185: @org.apache.mina.statemachine.annotation.State(PARENT)
186: public static final String S3 = "s3";
187: @org.apache.mina.statemachine.annotation.State(PARENT)
188: public static final String S4 = "s4";
189: @org.apache.mina.statemachine.annotation.State(PARENT)
190: public static final String S5 = "s5";
191:
192: private LinkedList<String> messages = new LinkedList<String>();
193:
194: @Transition(on="insert",in="s1",next="s2")
195: public void inserted(String name) {
196: messages.add("Tape '" + name + "' inserted");
197: }
198:
199: @Transition(on="eject",in="s4",next="s1")
200: public void ejected() {
201: messages.add("Tape ejected");
202: }
203:
204: @Transitions({@Transition(on="start",in="s2",next="s3"),@Transition(on="pause",in="s5",next="s3")})
205: public void playing() {
206: messages.add("Playing");
207: }
208:
209: @Transition(on="pause",in="s3",next="s5")
210: public void paused() {
211: messages.add("Paused");
212: }
213:
214: @Transition(on="stop",in="s3",next="s4")
215: public void stopped() {
216: messages.add("Stopped");
217: }
218:
219: @Transition(on="*",in="parent")
220: public void error(Event event) {
221: messages.add("Error: Cannot " + event.getId()
222: + " at this time");
223: }
224: };
225: }
|