001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.scxml2.model; 018 019import java.util.Iterator; 020import java.util.Set; 021 022import org.apache.commons.scxml2.SCXMLExecutor; 023import org.apache.commons.scxml2.SCXMLTestHelper; 024import org.apache.commons.scxml2.TriggerEvent; 025import org.junit.Assert; 026import org.junit.Test; 027/** 028 * Unit tests {@link org.apache.commons.scxml2.SCXMLExecutor}. 029 */ 030public class StatelessModelTest { 031 032 /** 033 * Test the stateless model, simultaneous executions, JEXL expressions 034 */ 035 @Test 036 public void testStatelessModelSimultaneousJexl() throws Exception { 037 // parse once, use many times 038 SCXML scxml = SCXMLTestHelper.parse("org/apache/commons/scxml2/env/jexl/stateless-01.xml"); 039 SCXMLExecutor exec01 = SCXMLTestHelper.getExecutor(scxml); 040 exec01.go(); 041 SCXMLExecutor exec02 = SCXMLTestHelper.getExecutor(scxml); 042 exec02.go(); 043 Assert.assertFalse(exec01 == exec02); 044 runSimultaneousTest(exec01, exec02); 045 } 046 047 /** 048 * Test the stateless model, sequential executions, JEXL expressions 049 */ 050 @Test 051 public void testStatelessModelSequentialJexl() throws Exception { 052 // rinse and repeat 053 SCXML scxml = SCXMLTestHelper.parse("org/apache/commons/scxml2/env/jexl/stateless-01.xml"); 054 for (int i = 0; i < 3; i++) { 055 SCXMLExecutor exec01 = SCXMLTestHelper.getExecutor(scxml); 056 exec01.go(); 057 runSequentialTest(exec01); 058 } 059 } 060 061 /** 062 * Test sharing a single SCXML object between two executors 063 */ 064 @Test 065 public void testStatelessModelParallelSharedSCXML() throws Exception { 066 SCXML scxml01par = SCXMLTestHelper.parse("org/apache/commons/scxml2/model/stateless-parallel-01.xml"); 067 SCXMLExecutor exec01 = SCXMLTestHelper.getExecutor(scxml01par); 068 exec01.go(); 069 SCXMLExecutor exec02 = SCXMLTestHelper.getExecutor(scxml01par); 070 exec02.go(); 071 Assert.assertFalse(exec01 == exec02); 072 073 Set<EnterableState> currentStates = exec01.getStatus().getStates(); 074 checkParallelStates(currentStates, "state1.init", "state2.init", "exec01"); 075 076 currentStates = exec02.getStatus().getStates(); 077 checkParallelStates(currentStates, "state1.init", "state2.init", "exec02"); 078 079 currentStates = fireEvent("state1.event", exec01); 080 checkParallelStates(currentStates, "state1.final", "state2.init", "exec01"); 081 082 currentStates = fireEvent("state2.event", exec02); 083 checkParallelStates(currentStates, "state1.init", "state2.final", "exec02"); 084 085 currentStates = fireEvent("state2.event", exec01); 086 checkParallelStates(currentStates, "next", null, "exec01"); 087 088 currentStates = fireEvent("state1.event", exec02); 089 checkParallelStates(currentStates, "next", null, "exec02"); 090 } 091 092 /** 093 * TODO: Test sharing two SCXML objects between one executor (not recommended) 094 * 095 @Test 096 public void testStatelessModelParallelSwapSCXML() throws Exception { 097 SCXML scxml01par = SCXMLTestHelper.parse("org/apache/commons/scxml2/model/stateless-parallel-01.xml"); 098 SCXML scxml02par = SCXMLTestHelper.parse("org/apache/commons/scxml2/model/stateless-parallel-01.xml"); 099 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