1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.statemachine;
21  
22  import java.lang.reflect.Method;
23  import java.util.List;
24  
25  import junit.framework.TestCase;
26  
27  import org.apache.mina.statemachine.State;
28  import org.apache.mina.statemachine.StateMachine;
29  import org.apache.mina.statemachine.StateMachineCreationException;
30  import org.apache.mina.statemachine.StateMachineFactory;
31  import org.apache.mina.statemachine.annotation.Transition;
32  import org.apache.mina.statemachine.annotation.Transitions;
33  import org.apache.mina.statemachine.transition.MethodTransition;
34  
35  /**
36   * Tests {@link StateMachineFactory}.
37   *
38   * @author The Apache MINA Project (dev@mina.apache.org)
39   */
40  public class StateMachineFactoryTest extends TestCase {
41      Method barInA;
42      Method error;
43      Method fooInA;
44      Method fooInB;
45      Method barInC;
46      Method fooOrBarInCOrFooInD;
47  
48      protected void setUp() throws Exception {
49          barInA = States.class.getDeclaredMethod("barInA", new Class[0]);
50          error = States.class.getDeclaredMethod("error", new Class[0]);
51          fooInA = States.class.getDeclaredMethod("fooInA", new Class[0]);
52          fooInB = States.class.getDeclaredMethod("fooInB", new Class[0]);
53          barInC = States.class.getDeclaredMethod("barInC", new Class[0]);
54          fooOrBarInCOrFooInD = States.class.getDeclaredMethod("fooOrBarInCOrFooInD", new Class[0]);
55      }
56  
57      public void testCreate() throws Exception {
58          States states = new States();
59          StateMachine sm = StateMachineFactory.getInstance(Transition.class).create(States.A, states);
60  
61          State a = sm.getState(States.A);
62          State b = sm.getState(States.B);
63          State c = sm.getState(States.C);
64          State d = sm.getState(States.D);
65  
66          assertEquals(States.A, a.getId());
67          assertNull(a.getParent());
68          assertEquals(States.B, b.getId());
69          assertSame(a, b.getParent());
70          assertEquals(States.C, c.getId());
71          assertSame(b, c.getParent());
72          assertEquals(States.D, d.getId());
73          assertSame(a, d.getParent());
74  
75          List<org.apache.mina.statemachine.transition.Transition> trans = null;
76  
77          trans = a.getTransitions();
78          assertEquals(3, trans.size());
79          assertEquals(new MethodTransition("bar", barInA, states), trans.get(0));
80          assertEquals(new MethodTransition("*", error, states), trans.get(1));
81          assertEquals(new MethodTransition("foo", b, fooInA, states), trans.get(2));
82          
83          trans = b.getTransitions();
84          assertEquals(1, trans.size());
85          assertEquals(new MethodTransition("foo", c, fooInB, states), trans.get(0));
86  
87          trans = c.getTransitions();
88          assertEquals(3, trans.size());
89          assertEquals(new MethodTransition("bar", a, barInC, states), trans.get(0));
90          assertEquals(new MethodTransition("foo", d, fooOrBarInCOrFooInD, states), trans.get(1));
91          assertEquals(new MethodTransition("bar", d, fooOrBarInCOrFooInD, states), trans.get(2));
92  
93          trans = d.getTransitions();
94          assertEquals(1, trans.size());
95          assertEquals(new MethodTransition("foo", fooOrBarInCOrFooInD, states), trans.get(0));
96      }
97      
98      public void testCreateStates() throws Exception {
99          State[] states = StateMachineFactory.createStates(StateMachineFactory.getFields(States.class));
100         assertEquals(States.A, states[0].getId());
101         assertNull(states[0].getParent());
102         assertEquals(States.B, states[1].getId());
103         assertEquals(states[0], states[1].getParent());
104         assertEquals(States.C, states[2].getId());
105         assertEquals(states[1], states[2].getParent());
106         assertEquals(States.D, states[3].getId());
107         assertEquals(states[0], states[3].getParent());
108     }
109     
110     public void testCreateStatesMissingParents() throws Exception {
111         try {
112             StateMachineFactory.createStates(StateMachineFactory.getFields(StatesWithMissingParents.class));
113             fail("Missing parents. FsmCreationException expected.");
114         } catch (StateMachineCreationException fce) {
115         }
116     }
117     
118     public static class States {
119         @org.apache.mina.statemachine.annotation.State
120         protected static final String A = "a";
121         @org.apache.mina.statemachine.annotation.State(A)
122         protected static final String B = "b";
123         @org.apache.mina.statemachine.annotation.State(B)
124         protected static final String C = "c";
125         @org.apache.mina.statemachine.annotation.State(A)
126         protected static final String D = "d";
127         
128         @Transition(on = "bar", in = A)
129         protected void barInA() {
130         }
131 
132         @Transition(on = "bar", in = C, next = A)
133         protected void barInC() {
134         }
135 
136         @Transition(in = A)
137         protected void error() {
138         }
139 
140         @Transition(on = "foo", in = A, next = B)
141         protected void fooInA() {
142         }
143 
144         @Transition(on = "foo", in = B, next = C)
145         protected void fooInB() {
146         }
147 
148         @Transitions( { @Transition(on = { "foo", "bar" }, in = C, next = D), @Transition(on = "foo", in = D) })
149         protected void fooOrBarInCOrFooInD() {
150         }
151       
152     }
153     
154     public static class StatesWithMissingParents {
155         @org.apache.mina.statemachine.annotation.State("b")
156         public static final String A = "a";
157         @org.apache.mina.statemachine.annotation.State("c")
158         public static final String B = "b";
159         @org.apache.mina.statemachine.annotation.State("d")
160         public static final String C = "c";
161         @org.apache.mina.statemachine.annotation.State("e")
162         public static final String D = "d";
163     }
164 }