    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.scxml.model;
    18
    19  import java.net.URL;
    20  import java.util.Iterator;
    21  import java.util.Set;
    22
    23  import junit.framework.Test;
    24  import junit.framework.TestCase;
    25  import junit.framework.TestSuite;
    26  import junit.textui.TestRunner;
    27
    28  import org.apache.commons.scxml.SCXMLExecutor;
    29  import org.apache.commons.scxml.SCXMLTestHelper;
    30  import org.apache.commons.scxml.TriggerEvent;
    31  import org.apache.commons.scxml.env.jsp.ELContext;
    32  import org.apache.commons.scxml.env.jsp.ELEvaluator;
    33  /***
    34   * Unit tests {@link org.apache.commons.scxml.SCXMLExecutor}.
    35   */
    36  public class StatelessModelTest extends TestCase {
    37      /***
    38       * Construct a new instance of SCXMLExecutorTest with
    39       * the specified name
    40       */
    41      public StatelessModelTest(String name) {
    42          super(name);
    43      }
    44
    45      public static Test suite() {
    46          TestSuite suite = new TestSuite(StatelessModelTest.class);
    47          suite.setName("SCXML Executor Tests");
    48          return suite;
    49      }
    50
    51      // Test data
    52      private URL stateless01jexl, stateless01jsp, stateless01par;
    53      private SCXML scxml01jexl, scxml01jsp, scxml01par, scxml02par;
    54      private SCXMLExecutor exec01, exec02;
    55
    56      /***
    57       * Set up instance variables required by this test case.
    58       */
    59      public void setUp() {
    60          stateless01jexl = this.getClass().getClassLoader().
    61              getResource("org/apache/commons/scxml/env/jexl/stateless-01.xml");
    62          stateless01jsp = this.getClass().getClassLoader().
    63              getResource("org/apache/commons/scxml/env/jsp/stateless-01.xml");
    64          stateless01par = this.getClass().getClassLoader().
    65              getResource("org/apache/commons/scxml/model/stateless-parallel-01.xml");
    66          scxml01jexl = SCXMLTestHelper.digest(stateless01jexl);
    67          scxml01jsp = SCXMLTestHelper.digest(stateless01jsp);
    68          scxml01par = SCXMLTestHelper.digest(stateless01par);
    69          scxml02par = SCXMLTestHelper.digest(stateless01par);
    70      }
    71
    72      /***
    73       * Tear down instance variables required by this test case.
    74       */
    75      public void tearDown() {
    76          stateless01jexl = null;
    77      }
    78
    79      /***
    80       * Test the stateless model, simultaneous executions, JEXL expressions
    81       */
    82      public void testStatelessModelSimultaneousJexl() {
    83      	// parse once, use many times
    84          exec01 = SCXMLTestHelper.getExecutor(scxml01jexl);
    85          assertNotNull(exec01);
    86          exec02 = SCXMLTestHelper.getExecutor(scxml01jexl);
    87          assertNotNull(exec02);
    88          assertFalse(exec01 == exec02);
    89          runSimultaneousTest();
    90      }
    91
    92      /***
    93       * Test the stateless model, sequential executions, JEXL expressions
    94       */
    95      public void testStatelessModelSequentialJexl() {
    96          // rinse and repeat
    97          for (int i = 0; i < 3; i++) {
    98              exec01 = SCXMLTestHelper.getExecutor(scxml01jexl);
    99              assertNotNull(exec01);
    100             runSequentialTest();
    101         }
    102     }
    103
    104     /***
    105      * Test the stateless model, simultaneous executions, EL expressions
    106      */
    107     public void testStatelessModelSimultaneousEl() {
    108     	// parse once, use many times
    109         exec01 = SCXMLTestHelper.getExecutor(scxml01jsp,
    110             new ELContext(), new ELEvaluator());
    111         assertNotNull(exec01);
    112         exec02 = SCXMLTestHelper.getExecutor(scxml01jsp,
    113             new ELContext(), new ELEvaluator());
    114         assertNotNull(exec02);
    115         assertFalse(exec01 == exec02);
    116         runSimultaneousTest();
    117     }
    118
    119     /***
    120      * Test the stateless model, sequential executions, EL expressions
    121      */
    122     public void testStatelessModelSequentialEl() {
    123         // rinse and repeat
    124         for (int i = 0; i < 3; i++) {
    125             exec01 = SCXMLTestHelper.getExecutor(scxml01jsp,
    126                 new ELContext(), new ELEvaluator());
    127             assertNotNull(exec01);
    128             runSequentialTest();
    129         }
    130     }
    131
    132     /***
    133      * Test sharing a single SCXML object between two executors
    134      */
    135     public void testStatelessModelParallelSharedSCXML() {
    136         exec01 = SCXMLTestHelper.getExecutor(scxml01par);
    137         assertNotNull(exec01);
    138         exec02 = SCXMLTestHelper.getExecutor(scxml01par);
    139         assertNotNull(exec02);
    140         assertFalse(exec01 == exec02);
    141
    142         Set currentStates = exec01.getCurrentStatus().getStates();
    143         checkParallelStates(currentStates, "state1.init", "state2.init", "exec01");
    144
    145         currentStates = exec02.getCurrentStatus().getStates();
    146         checkParallelStates(currentStates, "state1.init", "state2.init", "exec02");
    147
    148         currentStates = fireEvent("state1.event", exec01);
    149         checkParallelStates(currentStates, "state1.final", "state2.init", "exec01");
    150
    151         currentStates = fireEvent("state2.event", exec02);
    152         checkParallelStates(currentStates, "state1.init", "state2.final", "exec02");
    153
    154         currentStates = fireEvent("state2.event", exec01);
    155         checkParallelStates(currentStates, "next", null, "exec01");
    156
    157         currentStates = fireEvent("state1.event", exec02);
    158         checkParallelStates(currentStates, "next", null, "exec02");
    159     }
    160
    161     /***
    162      * Test sharing two SCXML objects between one executor (not recommended)
    163      */
    164     public void testStatelessModelParallelSwapSCXML() {
    165         exec01 = SCXMLTestHelper.getExecutor(scxml01par);
    166         assertNotNull(exec01);
    167         assertTrue(scxml01par != scxml02par);
    168
    169         Set currentStates = exec01.getCurrentStatus().getStates();
    170         checkParallelStates(currentStates, "state1.init", "state2.init", "exec01");
    171
    172         currentStates = fireEvent("state1.event", exec01);
    173         checkParallelStates(currentStates, "state1.final", "state2.init", "exec01");
    174         exec01.setStateMachine(scxml02par);
    175
    176         currentStates = fireEvent("state2.event", exec01);
    177         checkParallelStates(currentStates, "next", null, "exec01");
    178     }
    179
    180     private void checkParallelStates(Set currentStates, String s1, String s2,
    181             String label) {
    182         Iterator i = currentStates.iterator();
    183         assertTrue("Not enough states", i.hasNext());
    184         String cs1 = ((State) i.next()).getId();
    185         String cs2 = null;
    186         if (s2 != null) {
    187             assertTrue("Not enough states, found one state: " + cs1, i.hasNext());
    188             cs2 = ((State) i.next()).getId();
    189             assertFalse("Too many states", i.hasNext());
    190             if (s2.equals(cs2)) {
    191                 cs2 = null;
    192             } else if (s1.equals(cs2)) {
    193                 cs2 = null;
    194             } else {
    195                 fail(label + " in unexpected state " + cs2);
    196             }
    197         } else {
    198             assertFalse("Too many states", i.hasNext());
    199         }
    200         if (s1 != null && s1.equals(cs1)) {
    201             return;
    202         }
    203         if (s2 != null && s2.equals(cs1)) {
    204             return;
    205         }
    206         fail(label + " in unexpected state " + cs1);
    207     }
    208
    209     private void runSimultaneousTest() {
    210         try {
    211             //// Interleaved
    212             // exec01
    213             Set currentStates = exec01.getCurrentStatus().getStates();
    214             assertEquals(1, currentStates.size());
    215             assertEquals("ten", ((State)currentStates.iterator().
    216                 next()).getId());
    217             currentStates = fireEvent("ten.done", exec01);
    218             assertEquals(1, currentStates.size());
    219             assertEquals("twenty", ((State)currentStates.iterator().
    220                 next()).getId());
    221             // exec02
    222             currentStates = exec02.getCurrentStatus().getStates();
    223             assertEquals(1, currentStates.size());
    224             assertEquals("ten", ((State)currentStates.iterator().
    225                 next()).getId());
    226             // exec01
    227             currentStates = fireEvent("twenty.done", exec01);
    228             assertEquals(1, currentStates.size());
    229             assertEquals("thirty", ((State)currentStates.iterator().
    230                 next()).getId());
    231             // exec02
    232             currentStates = fireEvent("ten.done", exec02);
    233             assertEquals(1, currentStates.size());
    234             assertEquals("twenty", ((State)currentStates.iterator().
    235                 next()).getId());
    236             currentStates = fireEvent("twenty.done", exec02);
    237             assertEquals(1, currentStates.size());
    238             assertEquals("thirty", ((State)currentStates.iterator().
    239                 next()).getId());
    240         } catch (Exception e) {
    241             fail(e.getMessage());
    242         }
    243     }
    244
    245     private void runSequentialTest() {
    246         try {
    247             Set currentStates = exec01.getCurrentStatus().getStates();
    248             assertEquals(1, currentStates.size());
    249             assertEquals("ten", ((State)currentStates.iterator().
    250                 next()).getId());
    251             currentStates = fireEvent("ten.done", exec01);
    252             assertEquals(1, currentStates.size());
    253             assertEquals("twenty", ((State)currentStates.iterator().
    254                 next()).getId());
    255             currentStates = fireEvent("twenty.done", exec01);
    256             assertEquals(1, currentStates.size());
    257             assertEquals("thirty", ((State)currentStates.iterator().
    258                 next()).getId());
    259         } catch (Exception e) {
    260             fail(e.getMessage());
    261         }
    262     }
    263
    264     private Set fireEvent(String name, SCXMLExecutor exec) {
    265         TriggerEvent[] evts = {new TriggerEvent(name,
    266                 TriggerEvent.SIGNAL_EVENT, null)};
    267         try {
    268             exec.triggerEvents(evts);
    269         } catch (Exception e) {
    270             fail(e.getMessage());
    271         }
    272         return exec.getCurrentStatus().getStates();
    273     }
    274
    275     public static void main(String args[]) {
    276         TestRunner.run(suite());
    277     }
    278 }
    279