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.ArrayList;
020import java.util.List;
021
022import org.apache.commons.scxml2.SCXMLExecutor;
023import org.apache.commons.scxml2.SCXMLTestHelper;
024import org.junit.Assert;
025import org.junit.Before;
026import org.junit.Test;
027
028public class CustomActionTest {
029
030    /**
031     * Set up instance variables required by this test case.
032     */
033    @Before
034    public void setUp() {
035        Hello.callbacks = 0;
036    }
037
038    @Test
039    public void testAddGoodCustomAction01() throws Exception {
040        new CustomAction("http://my.actions.domain/CUSTOM", "hello",
041            Hello.class);
042    }
043
044    @Test
045    public void testAddBadCustomAction01() {
046        try {
047            new CustomAction(null, "hello", Hello.class);
048            Assert.fail("Added custom action with illegal namespace");
049        } catch (IllegalArgumentException iae) {
050            // Expected
051        }
052    }
053
054    @Test
055    public void testAddBadCustomAction02() {
056        try {
057            new CustomAction("  ", "hello", Hello.class);
058            Assert.fail("Added custom action with illegal namespace");
059        } catch (IllegalArgumentException iae) {
060            // Expected
061        }
062    }
063
064    @Test
065    public void testAddBadCustomAction03() {
066        try {
067            new CustomAction("http://my.actions.domain/CUSTOM", "",
068                Hello.class);
069            Assert.fail("Added custom action with illegal local name");
070        } catch (IllegalArgumentException iae) {
071            // Expected
072        }
073    }
074
075    @Test
076    public void testAddBadCustomAction04() {
077        try {
078            new CustomAction("http://my.actions.domain/CUSTOM", "  ",
079                Hello.class);
080            Assert.fail("Added custom action with illegal local name");
081        } catch (IllegalArgumentException iae) {
082            // Expected
083        }
084    }
085
086    @Test
087    public void testAddBadCustomAction05() {
088        try {            
089            new CustomAction("http://www.w3.org/2005/07/scxml", "foo",
090                Hello.class);
091            Assert.fail("Added custom action in the SCXML namespace");
092        } catch (IllegalArgumentException iae) {
093            // Expected
094        }
095    }
096
097    // Hello World example using the SCXML <log> action
098    @Test
099    public void testHelloWorld() throws Exception {
100        // (1) Get a SCXMLExecutor
101        SCXMLExecutor exec = SCXMLTestHelper.getExecutor("org/apache/commons/scxml2/hello-world.xml");
102        exec.go();
103        // (2) Single, final state
104        Assert.assertEquals("hello", (exec.getStatus().getStates().
105                iterator().next()).getId());
106        Assert.assertTrue(exec.getStatus().isFinal());
107    }
108
109    // Hello World example using a custom <hello> action
110    @Test
111    public void testCustomActionHelloWorld() throws Exception {
112        // (1) Form a list of custom actions defined in the SCXML
113        //     document (and any included documents via "src" attributes)
114        CustomAction ca1 =
115            new CustomAction("http://my.custom-actions.domain/CUSTOM1",
116                             "hello", Hello.class);
117        // Register the same action under a different name, just to test
118        // multiple custom actions
119        CustomAction ca2 =
120            new CustomAction("http://my.custom-actions.domain/CUSTOM2",
121                             "bar", Hello.class);
122        List<CustomAction> customActions = new ArrayList<CustomAction>();
123        customActions.add(ca1);
124        customActions.add(ca2);
125        // (2) Parse the document
126        SCXML scxml = SCXMLTestHelper.parse("org/apache/commons/scxml2/custom-hello-world-01.xml", customActions);
127        // (3) Get a SCXMLExecutor
128        SCXMLExecutor exec = SCXMLTestHelper.getExecutor(scxml);
129        exec.go();
130        // (4) Single, final state
131        Assert.assertEquals("custom", (exec.getStatus().getStates().
132                iterator().next()).getId());
133        Assert.assertTrue(exec.getStatus().isFinal());
134
135        // The custom action defined by Hello.class should be called
136        // to execute() exactly twice at this point (one by <my:hello/> and the other by <foo:bar/>).
137        Assert.assertEquals(2, Hello.callbacks);
138    }
139
140    // Hello World example using custom <my:hello> action
141    // as part of an external state source (src attribute)
142    @Test
143    public void testCustomActionExternalSrcHelloWorld() throws Exception {
144        // (1) Form a list of custom actions defined in the SCXML
145        //     document (and any included documents via "src" attributes)
146        CustomAction ca =
147            new CustomAction("http://my.custom-actions.domain/CUSTOM",
148                             "hello", Hello.class);
149        List<CustomAction> customActions = new ArrayList<CustomAction>();
150        customActions.add(ca);
151        // (2) Parse the document
152        SCXML scxml = SCXMLTestHelper.parse("org/apache/commons/scxml2/external-hello-world.xml", customActions);
153        // (3) Get a SCXMLExecutor
154        SCXMLExecutor exec = SCXMLTestHelper.getExecutor(scxml);
155        exec.go();
156        // (4) Single, final state
157        Assert.assertEquals("custom", (exec.getStatus().getStates().
158            iterator().next()).getId());
159
160        // The custom action defined by Hello.class should be called
161        // to execute() exactly twice at this point (one by <my:hello/> and the other by <my:hello/> in external).
162        Assert.assertEquals(2, Hello.callbacks);
163    }
164
165    // Hello World example using custom <my:send> action
166    // (overriding SCXML local name "send")
167    @Test
168    public void testCustomActionOverrideLocalName() throws Exception {
169        // (1) List of custom actions, use same local name as SCXML action
170        CustomAction ca =
171            new CustomAction("http://my.custom-actions.domain/CUSTOM",
172                             "send", Hello.class);
173        List<CustomAction> customActions = new ArrayList<CustomAction>();
174        customActions.add(ca);
175        // (2) Parse the document
176        SCXML scxml = SCXMLTestHelper.parse("org/apache/commons/scxml2/custom-hello-world-03.xml", customActions);
177        // (3) Get a SCXMLExecutor
178        SCXMLExecutor exec = SCXMLTestHelper.getExecutor(scxml);
179        exec.go();
180        // (4) Single, final state
181        Assert.assertEquals("custom", (exec.getStatus().getStates().
182            iterator().next()).getId());
183
184        // The custom action defined by Hello.class should be called
185        // to execute() exactly once at this point (by <my:send/>).
186        Assert.assertEquals(1, Hello.callbacks);
187    }
188
189    // Hello World example using custom <my:hello> action that generates an
190    // event which has the payload examined with JEXL expressions
191    @Test
192    public void testCustomActionEventPayloadHelloWorldJexl() throws Exception {
193        // (1) Form a list of custom actions defined in the SCXML
194        //     document (and any included documents via "src" attributes)
195        CustomAction ca =
196            new CustomAction("http://my.custom-actions.domain/CUSTOM",
197                             "hello", Hello.class);
198        List<CustomAction> customActions = new ArrayList<CustomAction>();
199        customActions.add(ca);
200        // (2) Parse the document
201        SCXML scxml = SCXMLTestHelper.parse("org/apache/commons/scxml2/custom-hello-world-04-jexl.xml", customActions);
202        // (3) Get a SCXMLExecutor
203        SCXMLExecutor exec = SCXMLTestHelper.getExecutor(scxml);
204        exec.go();
205        // (4) Single, final state
206        Assert.assertEquals("Invalid intermediate state",
207                     "custom1", (exec.getStatus().getStates().
208                                iterator().next()).getId());
209        // (5) Verify datamodel variable is correct
210        Assert.assertEquals("Missing helloName1 in root context", "custom04a",
211                     exec.getGlobalContext().get("helloName1"));
212
213        // The custom action defined by Hello.class should be called
214        // to execute() exactly once at this point (by onentry in init state).
215        Assert.assertEquals(1, Hello.callbacks);
216
217        // (6) Check use of payload in non-initial state
218        SCXMLTestHelper.fireEvent(exec, "custom.next");
219        // (7) Verify correct end state
220        Assert.assertEquals("Missing helloName1 in root context", "custom04b",
221                exec.getGlobalContext().get("helloName1"));
222        Assert.assertEquals("Invalid final state",
223                "end", (exec.getStatus().getStates().
224                iterator().next()).getId());
225        Assert.assertTrue(exec.getStatus().isFinal());
226
227        // The custom action defined by Hello.class should be called
228        // to execute() exactly two times at this point (by onentry in custom2 state).
229        Assert.assertEquals(2, Hello.callbacks);
230    }
231}
232