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.ArrayList;
21  import java.util.List;
22  
23  import junit.framework.Test;
24  import junit.framework.TestCase;
25  import junit.framework.TestSuite;
26  
27  import org.apache.commons.scxml.SCXMLExecutor;
28  import org.apache.commons.scxml.SCXMLTestHelper;
29  import org.apache.commons.scxml.env.jsp.ELEvaluator;
30  
31  public class CustomActionTest extends TestCase {
32  
33      public CustomActionTest(String testName) {
34          super(testName);
35      }
36  
37      public static Test suite() {
38          return new TestSuite(CustomActionTest.class);
39      }
40  
41      public static void main(String args[]) {
42          String[] testCaseName = { CustomActionTest.class.getName()};
43          junit.textui.TestRunner.main(testCaseName);
44      }
45  
46      private URL hello01, custom01, external01, override01, payload01, payload02;
47      private SCXMLExecutor exec;
48  
49      /***
50       * Set up instance variables required by this test case.
51       */
52      public void setUp() {
53          hello01 = this.getClass().getClassLoader().
54              getResource("org/apache/commons/scxml/hello-world.xml");
55          custom01 = this.getClass().getClassLoader().
56              getResource("org/apache/commons/scxml/custom-hello-world-01.xml");
57          external01 = this.getClass().getClassLoader().
58              getResource("org/apache/commons/scxml/external-hello-world.xml");
59          override01 = this.getClass().getClassLoader().
60              getResource("org/apache/commons/scxml/custom-hello-world-03.xml");
61          payload01 = this.getClass().getClassLoader().
62              getResource("org/apache/commons/scxml/custom-hello-world-04-jexl.xml");
63          payload02 = this.getClass().getClassLoader().
64              getResource("org/apache/commons/scxml/custom-hello-world-04-el.xml");
65      }
66  
67      /***
68       * Tear down instance variables required by this test case.
69       */
70      public void tearDown() {
71          hello01 = custom01 = external01 = payload01 = payload02 = null;
72          exec = null;
73      }
74  
75      public void testAddGoodCustomAction01() {
76          try {
77              new CustomAction("http://my.actions.domain/CUSTOM", "hello",
78                  Hello.class);
79          } catch (IllegalArgumentException iae) {
80              fail("Failed to add custom action "Hello"");
81          }
82      }
83  
84      public void testAddBadCustomAction01() {
85          try {
86              new CustomAction(null, "hello", Hello.class);
87              fail("Added custom action with illegal namespace");
88          } catch (IllegalArgumentException iae) {
89              // Expected
90          }
91      }
92  
93      public void testAddBadCustomAction02() {
94          try {
95              new CustomAction("  ", "hello", Hello.class);
96              fail("Added custom action with illegal namespace");
97          } catch (IllegalArgumentException iae) {
98              // Expected
99          }
100     }
101 
102     public void testAddBadCustomAction03() {
103         try {
104             new CustomAction("http://my.actions.domain/CUSTOM", "",
105                 Hello.class);
106             fail("Added custom action with illegal local name");
107         } catch (IllegalArgumentException iae) {
108             // Expected
109         }
110     }
111 
112     public void testAddBadCustomAction04() {
113         try {
114             new CustomAction("http://my.actions.domain/CUSTOM", "  ",
115                 Hello.class);
116             fail("Added custom action with illegal local name");
117         } catch (IllegalArgumentException iae) {
118             // Expected
119         }
120     }
121 
122     public void testAddBadCustomAction05() {
123         try {
124             new CustomAction("http://my.actions.domain/CUSTOM", "foo",
125                 this.getClass());
126             fail("Added custom action which is not an Action class subtype");
127         } catch (IllegalArgumentException iae) {
128             // Expected
129         }
130     }
131 
132     public void testAddBadCustomAction06() {
133         try {
134             new CustomAction("http://www.w3.org/2005/07/scxml", "foo",
135                 this.getClass());
136             fail("Added custom action in the SCXML namespace");
137         } catch (IllegalArgumentException iae) {
138             // Expected
139         }
140     }
141 
142     // Hello World example using the SCXML <log> action
143     public void testHelloWorld() {
144         // (1) Get a SCXMLExecutor
145         exec = SCXMLTestHelper.getExecutor(hello01);
146         // (2) Single, final state
147         assertEquals("hello", ((State) exec.getCurrentStatus().getStates().
148                 iterator().next()).getId());
149         assertTrue(exec.getCurrentStatus().isFinal());
150     }
151 
152     // Hello World example using a custom <hello> action
153     public void testCustomActionHelloWorld() {
154         // (1) Form a list of custom actions defined in the SCXML
155         //     document (and any included documents via "src" attributes)
156         CustomAction ca1 =
157             new CustomAction("http://my.custom-actions.domain/CUSTOM1",
158                              "hello", Hello.class);
159         // Register the same action under a different name, just to test
160         // multiple custom actions
161         CustomAction ca2 =
162             new CustomAction("http://my.custom-actions.domain/CUSTOM2",
163                              "bar", Hello.class);
164         List customActions = new ArrayList();
165         customActions.add(ca1);
166         customActions.add(ca2);
167         // (2) Parse the document with a custom digester.
168         SCXML scxml = SCXMLTestHelper.digest(custom01, customActions);
169         // (3) Get a SCXMLExecutor
170         exec = SCXMLTestHelper.getExecutor(scxml);
171         // (4) Single, final state
172         assertEquals("custom", ((State) exec.getCurrentStatus().getStates().
173                 iterator().next()).getId());
174         assertTrue(exec.getCurrentStatus().isFinal());
175     }
176 
177     // Hello World example using custom <my:hello> action
178     // as part of an external state source (src attribute)
179     public void testCustomActionExternalSrcHelloWorld() {
180         // (1) Form a list of custom actions defined in the SCXML
181         //     document (and any included documents via "src" attributes)
182         CustomAction ca =
183             new CustomAction("http://my.custom-actions.domain/CUSTOM",
184                              "hello", Hello.class);
185         List customActions = new ArrayList();
186         customActions.add(ca);
187         // (2) Parse the document with a custom digester.
188         SCXML scxml = SCXMLTestHelper.digest(external01, customActions);
189         // (3) Get a SCXMLExecutor
190         exec = SCXMLTestHelper.getExecutor(scxml);
191         // (4) Single, final state
192         assertEquals("custom", ((State) exec.getCurrentStatus().getStates().
193             iterator().next()).getId());
194     }
195 
196     // Hello World example using custom <my:send> action
197     // (overriding SCXML local name "send")
198     public void testCustomActionOverrideLocalName() {
199         // (1) List of custom actions, use same local name as SCXML action
200         CustomAction ca =
201             new CustomAction("http://my.custom-actions.domain/CUSTOM",
202                              "send", Hello.class);
203         List customActions = new ArrayList();
204         customActions.add(ca);
205         // (2) Parse the document with a custom digester.
206         SCXML scxml = SCXMLTestHelper.digest(override01, customActions);
207         // (3) Get a SCXMLExecutor
208         exec = SCXMLTestHelper.getExecutor(scxml);
209         // (4) Single, final state
210         assertEquals("custom", ((State) exec.getCurrentStatus().getStates().
211             iterator().next()).getId());
212     }
213 
214     // The custom action defined by Hello.class should be called
215     // to execute() exactly 5 times upto this point
216     public void testCustomActionCallbacks() {
217         assertEquals(5, Hello.callbacks);
218     }
219 
220     // Hello World example using custom <my:hello> action that generates an
221     // event which has the payload examined with JEXL expressions
222     public void testCustomActionEventPayloadHelloWorldJexl() {
223         // (1) Form a list of custom actions defined in the SCXML
224         //     document (and any included documents via "src" attributes)
225         CustomAction ca =
226             new CustomAction("http://my.custom-actions.domain/CUSTOM",
227                              "hello", Hello.class);
228         List customActions = new ArrayList();
229         customActions.add(ca);
230         // (2) Parse the document with a custom digester.
231         SCXML scxml = SCXMLTestHelper.digest(payload01, customActions);
232         // (3) Get a SCXMLExecutor
233         exec = SCXMLTestHelper.getExecutor(scxml);
234         // (4) Single, final state
235         assertEquals("Invalid intermediate state",
236                      "custom1", ((State) exec.getCurrentStatus().getStates().
237                                 iterator().next()).getId());
238         // (5) Verify datamodel variable is correct
239         assertEquals("Missing helloName1 in root context", "custom04a",
240                      (String) exec.getRootContext().get("helloName1"));
241         // (6) Check use of payload in non-initial state
242         SCXMLTestHelper.fireEvent(exec, "custom.next");
243         // (7) Verify correct end state
244         assertEquals("Missing helloName1 in root context", "custom04b",
245                 (String) exec.getRootContext().get("helloName1"));
246         assertEquals("Invalid final state",
247                 "end", ((State) exec.getCurrentStatus().getStates().
248                 iterator().next()).getId());
249         assertTrue(exec.getCurrentStatus().isFinal());
250     }
251 
252     // Hello World example using custom <my:hello> action that generates an
253     // event which has the payload examined with EL expressions
254     public void testCustomActionEventPayloadHelloWorldEL() {
255         // (1) Form a list of custom actions defined in the SCXML
256         //     document (and any included documents via "src" attributes)
257         CustomAction ca =
258             new CustomAction("http://my.custom-actions.domain/CUSTOM",
259                              "hello", Hello.class);
260         List customActions = new ArrayList();
261         customActions.add(ca);
262         // (2) Parse the document with a custom digester.
263         SCXML scxml = SCXMLTestHelper.digest(payload02, customActions);
264         // (3) Get a SCXMLExecutor
265         exec = SCXMLTestHelper.getExecutor(new ELEvaluator(), scxml);
266         // (4) Single, final state
267         assertEquals("Invalid final state",
268                      "custom", ((State) exec.getCurrentStatus().getStates().
269                                 iterator().next()).getId());
270         // (5) Verify datamodel variable is correct
271         assertEquals("Missing helloName1 in root context", "custom04",
272                      (String) exec.getRootContext().get("helloName1"));
273     }
274 
275 }
276