View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.scxml2.model;
18  
19  import java.util.Iterator;
20  import java.util.Set;
21  
22  import org.apache.commons.scxml2.SCXMLExecutor;
23  import org.apache.commons.scxml2.SCXMLTestHelper;
24  import org.apache.commons.scxml2.TriggerEvent;
25  import org.junit.Assert;
26  import org.junit.Test;
27  /**
28   * Unit tests {@link org.apache.commons.scxml2.SCXMLExecutor}.
29   */
30  public class StatelessModelTest {
31  
32      /**
33       * Test the stateless model, simultaneous executions, JEXL expressions
34       */    
35      @Test
36      public void testStatelessModelSimultaneousJexl() throws Exception {
37      	// parse once, use many times
38          SCXML scxml = SCXMLTestHelper.parse("org/apache/commons/scxml2/env/jexl/stateless-01.xml");
39          SCXMLExecutor exec01 = SCXMLTestHelper.getExecutor(scxml);
40          exec01.go();
41          SCXMLExecutor exec02 = SCXMLTestHelper.getExecutor(scxml);
42          exec02.go();
43          Assert.assertFalse(exec01 == exec02);
44          runSimultaneousTest(exec01, exec02);
45      }
46  
47      /**
48       * Test the stateless model, sequential executions, JEXL expressions
49       */    
50      @Test
51      public void testStatelessModelSequentialJexl() throws Exception {
52          // rinse and repeat
53          SCXML scxml = SCXMLTestHelper.parse("org/apache/commons/scxml2/env/jexl/stateless-01.xml");
54          for (int i = 0; i < 3; i++) {
55              SCXMLExecutor exec01 = SCXMLTestHelper.getExecutor(scxml);
56              exec01.go();
57              runSequentialTest(exec01);
58          }
59      }
60  
61      /**
62       * Test sharing a single SCXML object between two executors
63       */    
64      @Test
65      public void testStatelessModelParallelSharedSCXML() throws Exception {
66          SCXML scxml01par = SCXMLTestHelper.parse("org/apache/commons/scxml2/model/stateless-parallel-01.xml");
67          SCXMLExecutor exec01 = SCXMLTestHelper.getExecutor(scxml01par);
68          exec01.go();
69          SCXMLExecutor exec02 = SCXMLTestHelper.getExecutor(scxml01par);
70          exec02.go();
71          Assert.assertFalse(exec01 == exec02);
72  
73          Set<EnterableState> currentStates = exec01.getStatus().getStates();
74          checkParallelStates(currentStates, "state1.init", "state2.init", "exec01");
75  
76          currentStates = exec02.getStatus().getStates();
77          checkParallelStates(currentStates, "state1.init", "state2.init", "exec02");
78  
79          currentStates = fireEvent("state1.event", exec01);
80          checkParallelStates(currentStates, "state1.final", "state2.init", "exec01");
81  
82          currentStates = fireEvent("state2.event", exec02);
83          checkParallelStates(currentStates, "state1.init", "state2.final", "exec02");
84  
85          currentStates = fireEvent("state2.event", exec01);
86          checkParallelStates(currentStates, "next", null, "exec01");
87  
88          currentStates = fireEvent("state1.event", exec02);
89          checkParallelStates(currentStates, "next", null, "exec02");
90      }
91  
92      /**
93       * TODO: Test sharing two SCXML objects between one executor (not recommended)
94       *
95      @Test
96      public void testStatelessModelParallelSwapSCXML() throws Exception {
97          SCXML scxml01par = SCXMLTestHelper.parse("org/apache/commons/scxml2/model/stateless-parallel-01.xml");
98          SCXML scxml02par = SCXMLTestHelper.parse("org/apache/commons/scxml2/model/stateless-parallel-01.xml");
99          SCXMLExecutor exec01 = SCXMLTestHelper.getExecutor(scxml01par);
100         exec01.go();
101         Assert.assertTrue(scxml01par != scxml02par);
102 
103         Set<EnterableState> currentStates = exec01.getStatus().getStates();
104         checkParallelStates(currentStates, "state1.init", "state2.init", "exec01");
105 
106         currentStates = fireEvent("state1.event", exec01);
107         checkParallelStates(currentStates, "state1.final", "state2.init", "exec01");
108         exec01.setStateMachine(scxml02par);
109         exec01.addListener(scxml02par, new SimpleSCXMLListener());
110         currentStates = fireEvent("state2.event", exec01);
111         checkParallelStates(currentStates, "next", null, "exec01");
112     }
113      */
114 
115     private void checkParallelStates(Set<EnterableState> currentStates,
116             String s1, String s2, String label) {
117         Iterator<EnterableState> i = currentStates.iterator();
118         Assert.assertTrue("Not enough states", i.hasNext());
119         String cs1 = i.next().getId();
120         String cs2;
121         if (s2 != null) {
122             Assert.assertTrue("Not enough states, found one state: " + cs1, i.hasNext());
123             cs2 = i.next().getId();
124             Assert.assertFalse("Too many states", i.hasNext());
125             if (s2.equals(cs2)) {
126                 cs2 = null;
127             } else if (s1.equals(cs2)) {
128                 cs2 = null;
129             } else {
130                 Assert.fail(label + " in unexpected state " + cs2);
131             }
132         } else {
133             Assert.assertFalse("Too many states", i.hasNext());
134         }
135         if (s1 != null && s1.equals(cs1)) {
136             return;
137         }
138         if (s2 != null && s2.equals(cs1)) {
139             return;
140         }
141         Assert.fail(label + " in unexpected state " + cs1);
142     }
143 
144     private void runSimultaneousTest(SCXMLExecutor exec01, SCXMLExecutor exec02) throws Exception {
145         //// Interleaved
146         // exec01
147         Set<EnterableState> currentStates = exec01.getStatus().getStates();
148         Assert.assertEquals(1, currentStates.size());
149         Assert.assertEquals("ten", currentStates.iterator().next().getId());
150         currentStates = fireEvent("done.state.ten", exec01);
151         Assert.assertEquals(1, currentStates.size());
152         Assert.assertEquals("twenty", currentStates.iterator().next().getId());
153         // exec02
154         currentStates = exec02.getStatus().getStates();
155         Assert.assertEquals(1, currentStates.size());
156         Assert.assertEquals("ten", currentStates.iterator().next().getId());
157         // exec01
158         currentStates = fireEvent("done.state.twenty", exec01);
159         Assert.assertEquals(1, currentStates.size());
160         Assert.assertEquals("thirty", currentStates.iterator().next().getId());
161         // exec02
162         currentStates = fireEvent("done.state.ten", exec02);
163         Assert.assertEquals(1, currentStates.size());
164         Assert.assertEquals("twenty", currentStates.iterator().next().getId());
165         currentStates = fireEvent("done.state.twenty", exec02);
166         Assert.assertEquals(1, currentStates.size());
167         Assert.assertEquals("thirty", currentStates.iterator().next().getId());
168     }
169 
170     private void runSequentialTest(SCXMLExecutor exec) throws Exception {
171         Set<EnterableState> currentStates = exec.getStatus().getStates();
172         Assert.assertEquals(1, currentStates.size());
173         Assert.assertEquals("ten", (currentStates.iterator().
174             next()).getId());
175         currentStates = fireEvent("done.state.ten", exec);
176         Assert.assertEquals(1, currentStates.size());
177         Assert.assertEquals("twenty", (currentStates.iterator().
178             next()).getId());
179         currentStates = fireEvent("done.state.twenty", exec);
180         Assert.assertEquals(1, currentStates.size());
181         Assert.assertEquals("thirty", (currentStates.iterator().
182             next()).getId());
183     }
184 
185     private Set<EnterableState> fireEvent(String name, SCXMLExecutor exec) throws Exception {
186         TriggerEvent[] evts = {new TriggerEvent(name, TriggerEvent.SIGNAL_EVENT, null)};
187         exec.triggerEvents(evts);
188         return exec.getStatus().getStates();
189     }
190 }
191