/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.scxml.model;
import java.net.URL;
import java.util.Iterator;
import java.util.Set;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.textui.TestRunner;
import org.apache.commons.scxml.SCXMLExecutor;
import org.apache.commons.scxml.SCXMLTestHelper;
import org.apache.commons.scxml.TriggerEvent;
import org.apache.commons.scxml.env.jsp.ELContext;
import org.apache.commons.scxml.env.jsp.ELEvaluator;
/**
* Unit tests {@link org.apache.commons.scxml.SCXMLExecutor}.
*/
public class StatelessModelTest extends TestCase {
/**
* Construct a new instance of SCXMLExecutorTest with
* the specified name
*/
public StatelessModelTest(String name) {
super(name);
}
public static Test suite() {
TestSuite suite = new TestSuite(StatelessModelTest.class);
suite.setName("SCXML Executor Tests");
return suite;
}
// Test data
private URL stateless01jexl, stateless01jsp, stateless01par;
private SCXML scxml01jexl, scxml01jsp, scxml01par, scxml02par;
private SCXMLExecutor exec01, exec02;
/**
* Set up instance variables required by this test case.
*/
public void setUp() {
stateless01jexl = this.getClass().getClassLoader().
getResource("org/apache/commons/scxml/env/jexl/stateless-01.xml");
stateless01jsp = this.getClass().getClassLoader().
getResource("org/apache/commons/scxml/env/jsp/stateless-01.xml");
stateless01par = this.getClass().getClassLoader().
getResource("org/apache/commons/scxml/model/stateless-parallel-01.xml");
scxml01jexl = SCXMLTestHelper.digest(stateless01jexl);
scxml01jsp = SCXMLTestHelper.digest(stateless01jsp);
scxml01par = SCXMLTestHelper.digest(stateless01par);
scxml02par = SCXMLTestHelper.digest(stateless01par);
}
/**
* Tear down instance variables required by this test case.
*/
public void tearDown() {
stateless01jexl = null;
}
/**
* Test the stateless model, simultaneous executions, JEXL expressions
*/
public void testStatelessModelSimultaneousJexl() {
// parse once, use many times
exec01 = SCXMLTestHelper.getExecutor(scxml01jexl);
assertNotNull(exec01);
exec02 = SCXMLTestHelper.getExecutor(scxml01jexl);
assertNotNull(exec02);
assertFalse(exec01 == exec02);
runSimultaneousTest();
}
/**
* Test the stateless model, sequential executions, JEXL expressions
*/
public void testStatelessModelSequentialJexl() {
// rinse and repeat
for (int i = 0; i < 3; i++) {
exec01 = SCXMLTestHelper.getExecutor(scxml01jexl);
assertNotNull(exec01);
runSequentialTest();
}
}
/**
* Test the stateless model, simultaneous executions, EL expressions
*/
public void testStatelessModelSimultaneousEl() {
// parse once, use many times
exec01 = SCXMLTestHelper.getExecutor(scxml01jsp,
new ELContext(), new ELEvaluator());
assertNotNull(exec01);
exec02 = SCXMLTestHelper.getExecutor(scxml01jsp,
new ELContext(), new ELEvaluator());
assertNotNull(exec02);
assertFalse(exec01 == exec02);
runSimultaneousTest();
}
/**
* Test the stateless model, sequential executions, EL expressions
*/
public void testStatelessModelSequentialEl() {
// rinse and repeat
for (int i = 0; i < 3; i++) {
exec01 = SCXMLTestHelper.getExecutor(scxml01jsp,
new ELContext(), new ELEvaluator());
assertNotNull(exec01);
runSequentialTest();
}
}
/**
* Test sharing a single SCXML object between two executors
*/
public void testStatelessModelParallelSharedSCXML() {
exec01 = SCXMLTestHelper.getExecutor(scxml01par);
assertNotNull(exec01);
exec02 = SCXMLTestHelper.getExecutor(scxml01par);
assertNotNull(exec02);
assertFalse(exec01 == exec02);
Set currentStates = exec01.getCurrentStatus().getStates();
checkParallelStates(currentStates, "state1.init", "state2.init", "exec01");
currentStates = exec02.getCurrentStatus().getStates();
checkParallelStates(currentStates, "state1.init", "state2.init", "exec02");
currentStates = fireEvent("state1.event", exec01);
checkParallelStates(currentStates, "state1.final", "state2.init", "exec01");
currentStates = fireEvent("state2.event", exec02);
checkParallelStates(currentStates, "state1.init", "state2.final", "exec02");
currentStates = fireEvent("state2.event", exec01);
checkParallelStates(currentStates, "next", null, "exec01");
currentStates = fireEvent("state1.event", exec02);
checkParallelStates(currentStates, "next", null, "exec02");
}
/**
* Test sharing two SCXML objects between one executor (not recommended)
*/
public void testStatelessModelParallelSwapSCXML() {
exec01 = SCXMLTestHelper.getExecutor(scxml01par);
assertNotNull(exec01);
assertTrue(scxml01par != scxml02par);
Set currentStates = exec01.getCurrentStatus().getStates();
checkParallelStates(currentStates, "state1.init", "state2.init", "exec01");
currentStates = fireEvent("state1.event", exec01);
checkParallelStates(currentStates, "state1.final", "state2.init", "exec01");
exec01.setStateMachine(scxml02par);
currentStates = fireEvent("state2.event", exec01);
checkParallelStates(currentStates, "next", null, "exec01");
}
private void checkParallelStates(Set currentStates, String s1, String s2,
String label) {
Iterator i = currentStates.iterator();
assertTrue("Not enough states", i.hasNext());
String cs1 = ((State) i.next()).getId();
String cs2 = null;
if (s2 != null) {
assertTrue("Not enough states, found one state: " + cs1, i.hasNext());
cs2 = ((State) i.next()).getId();
assertFalse("Too many states", i.hasNext());
if (s2.equals(cs2)) {
cs2 = null;
} else if (s1.equals(cs2)) {
cs2 = null;
} else {
fail(label + " in unexpected state " + cs2);
}
} else {
assertFalse("Too many states", i.hasNext());
}
if (s1 != null && s1.equals(cs1)) {
return;
}
if (s2 != null && s2.equals(cs1)) {
return;
}
fail(label + " in unexpected state " + cs1);
}
private void runSimultaneousTest() {
try {
//// Interleaved
// exec01
Set currentStates = exec01.getCurrentStatus().getStates();
assertEquals(1, currentStates.size());
assertEquals("ten", ((State)currentStates.iterator().
next()).getId());
currentStates = fireEvent("ten.done", exec01);
assertEquals(1, currentStates.size());
assertEquals("twenty", ((State)currentStates.iterator().
next()).getId());
// exec02
currentStates = exec02.getCurrentStatus().getStates();
assertEquals(1, currentStates.size());
assertEquals("ten", ((State)currentStates.iterator().
next()).getId());
// exec01
currentStates = fireEvent("twenty.done", exec01);
assertEquals(1, currentStates.size());
assertEquals("thirty", ((State)currentStates.iterator().
next()).getId());
// exec02
currentStates = fireEvent("ten.done", exec02);
assertEquals(1, currentStates.size());
assertEquals("twenty", ((State)currentStates.iterator().
next()).getId());
currentStates = fireEvent("twenty.done", exec02);
assertEquals(1, currentStates.size());
assertEquals("thirty", ((State)currentStates.iterator().
next()).getId());
} catch (Exception e) {
fail(e.getMessage());
}
}
private void runSequentialTest() {
try {
Set currentStates = exec01.getCurrentStatus().getStates();
assertEquals(1, currentStates.size());
assertEquals("ten", ((State)currentStates.iterator().
next()).getId());
currentStates = fireEvent("ten.done", exec01);
assertEquals(1, currentStates.size());
assertEquals("twenty", ((State)currentStates.iterator().
next()).getId());
currentStates = fireEvent("twenty.done", exec01);
assertEquals(1, currentStates.size());
assertEquals("thirty", ((State)currentStates.iterator().
next()).getId());
} catch (Exception e) {
fail(e.getMessage());
}
}
private Set fireEvent(String name, SCXMLExecutor exec) {
TriggerEvent[] evts = {new TriggerEvent(name,
TriggerEvent.SIGNAL_EVENT, null)};
try {
exec.triggerEvents(evts);
} catch (Exception e) {
fail(e.getMessage());
}
return exec.getCurrentStatus().getStates();
}
public static void main(String args[]) {
TestRunner.run(suite());
}
}