View Javadoc
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.scxml2.io;
18  
19  import java.io.StringReader;
20  
21  import org.apache.commons.scxml2.SCXMLExecutor;
22  import org.apache.commons.scxml2.SCXMLTestHelper;
23  import org.apache.commons.scxml2.model.ModelException;
24  import org.apache.commons.scxml2.model.SCXML;
25  import org.junit.Test;
26  
27  import static org.junit.Assert.assertEquals;
28  import static org.junit.Assert.assertTrue;
29  import static org.junit.Assert.fail;
30  
31  /**
32   * Test enforcement of required SCXML element attributes, spec http://www.w3.org/TR/2013/WD-scxml-20130801
33   * <p>
34   * TODO required attributes for elements:
35   * <ul>
36   *   <li>&lt;raise&gt; required attribute: 'id'</li>
37   * </ul>
38   * </p>
39   */
40  public class SCXMLRequiredAttributesTest {
41  
42      private static final String VALID_SCXML =
43              "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" datamodel=\"jexl\" version=\"1.0\">\n" +
44                      "  <state id=\"s1\">\n" +
45                      "    <transition target=\"fine\">\n" +
46                      "      <if cond=\"true\"><log expr=\"'hello'\"/></if>\n" +
47                      "    </transition>\n" +
48                      "  </state>\n" +
49                      "  <final id=\"fine\"/>\n" +
50                      "</scxml>";
51  
52      private static final String SCXML_WITH_MISSING_VERSION =
53              "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\">\n" +
54                      "  <final id=\"fine\"/>\n" +
55                      "</scxml>";
56  
57      private static final String SCXML_WITH_INVALID_VERSION =
58              "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"2.0\">\n" +
59                      "  <final id=\"fine\"/>\n" +
60                      "</scxml>";
61  
62      private static final String SCXML_WITH_MISSING_IF_COND =
63              "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"1.0\">\n" +
64                      "  <state id=\"s1\">\n" +
65                      "    <transition target=\"fine\">\n" +
66                      "      <if><log expr=\"'hello'\"/></if>\n" +
67                      "    </transition>\n" +
68                      "  </state>\n" +
69                      "  <final id=\"fine\"/>\n" +
70                      "</scxml>";
71  
72      private static final String SCXML_WITH_MISSING_ELSEIF_COND =
73              "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"1.0\">\n" +
74                      "  <state id=\"s1\">\n" +
75                      "    <transition target=\"fine\">\n" +
76                      "      <if cond=\"false\"><elseif/><log expr=\"'hello'\"/></if>\n" +
77                      "    </transition>\n" +
78                      "  </state>\n" +
79                      "  <final id=\"fine\"/>\n" +
80                      "</scxml>";
81  
82      private static final String SCXML_WITH_MISSING_DATA_ID =
83              "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"1.0\">\n" +
84                      "  <datamodel><data></data></datamodel>\n" +
85                      "  <final id=\"fine\"/>\n" +
86                      "</scxml>";
87  
88      private static final String SCXML_WITH_MISSING_ASSIGN_LOCATION =
89              "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"1.0\">\n" +
90                      "  <state id=\"s1\">\n" +
91                      "    <transition target=\"fine\">\n" +
92                      "      <assign expr=\"1\"/>\n" +
93                      "    </transition>\n" +
94                      "  </state>\n" +
95                      "  <final id=\"fine\"/>\n" +
96                      "</scxml>";
97  
98      private static final String SCXML_WITH_MISSING_PARAM_NAME =
99              "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"1.0\">\n" +
100                     "  <state id=\"s1\">\n" +
101                     "    <invoke type=\"scxml\" src=\"foo\">\n" + // Note: invalid src, but not executed during test
102                     "      <param expr=\"1\"/>\n" +
103                     "    </invoke>\n" +
104                     "  </state>\n" +
105                     "  <final id=\"fine\"/>\n" +
106                     "</scxml>";
107 
108     private static final String SCXML_WITH_PARAM_AND_NAME =
109             "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"1.0\">\n" +
110                     "  <state id=\"s1\">\n" +
111                     "    <invoke type=\"scxml\" src=\"foo\">\n" + // Note: invalid src, but not executed during test
112                     "      <param name=\"bar\" expr=\"1\"/>\n" +
113                     "    </invoke>\n" +
114                     "  </state>\n" +
115                     "  <final id=\"fine\"/>\n" +
116                     "</scxml>";
117 
118     private static final String SCXML_WITH_MISSING_FOREACH_ARRAY =
119             "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"1.0\">\n" +
120                     "  <state id=\"s1\">\n" +
121                     "    <transition target=\"fine\">\n" +
122                     "      <foreach item=\"y\"></foreach>\n" +
123                     "    </transition>\n" +
124                     "  </state>\n" +
125                     "  <final id=\"fine\"/>\n" +
126                     "</scxml>";
127 
128     private static final String SCXML_WITH_MISSING_FOREACH_ITEM =
129             "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" version=\"1.0\">\n" +
130                     "  <state id=\"s1\">\n" +
131                     "    <transition target=\"fine\">\n" +
132                     "      <foreach array=\"[1,2]\"></foreach>\n" +
133                     "    </transition>\n" +
134                     "  </state>\n" +
135                     "  <final id=\"fine\"/>\n" +
136                     "</scxml>";
137 
138     private static final String SCXML_WITH_FOREACH =
139             "<scxml xmlns=\"http://www.w3.org/2005/07/scxml\" datamodel=\"jexl\" version=\"1.0\">\n" +
140                     "  <state id=\"s1\">\n" +
141                     "    <transition target=\"fine\">\n" +
142                     "      <foreach array=\"[1,2]\" item=\"x\"></foreach>\n" +
143                     "    </transition>\n" +
144                     "  </state>\n" +
145                     "  <final id=\"fine\"/>\n" +
146                     "</scxml>";
147 
148     @Test
149     public void testValidSCXML() throws Exception {
150         SCXML scxml = SCXMLTestHelper.parse(new StringReader(VALID_SCXML), null);
151         SCXMLExecutor exec = SCXMLTestHelper.getExecutor(scxml);
152         exec.go();
153         assertTrue(exec.getStatus().isFinal());
154     }
155 
156     @Test
157     public void testSCXMLMissingVersion() throws Exception {
158         try {
159             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_MISSING_VERSION), null);
160             fail("SCXML reading should have failed due to missing version in SCXML");
161         }
162         catch (ModelException e) {
163             assertTrue(e.getMessage().startsWith("<scxml> is missing required attribute \"version\" value"));
164         }
165     }
166 
167     @Test
168     public void testSCXMLInvalidVersion() throws Exception {
169         try {
170             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_INVALID_VERSION), null);
171             fail("SCXML reading should have failed due to missing version in SCXML");
172         }
173         catch (ModelException e) {
174             assertEquals("The <scxml> element defines an unsupported version \"2.0\", only version \"1.0\" is supported.", e.getMessage());
175         }
176     }
177 
178     @Test
179     public void testSCXMLMissingIfCond() throws Exception {
180         try {
181             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_MISSING_IF_COND), null);
182             fail("SCXML reading should have failed due to missing if condition in SCXML");
183         }
184         catch (ModelException e) {
185             assertTrue(e.getMessage().startsWith("<if> is missing required attribute \"cond\" value"));
186         }
187     }
188 
189     @Test
190     public void testSCXMLMissingElseIfCond() throws Exception {
191         try {
192             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_MISSING_ELSEIF_COND), null);
193             fail("SCXML reading should have failed due to missing elseif condition in SCXML");
194         }
195         catch (ModelException e) {
196             assertTrue(e.getMessage().startsWith("<elseif> is missing required attribute \"cond\" value"));
197         }
198     }
199 
200     @Test
201     public void testSCXMLMissingDataId() throws Exception {
202         try {
203             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_MISSING_DATA_ID), null);
204             fail("SCXML reading should have failed due to missing data id in SCXML");
205         }
206         catch (ModelException e) {
207             assertTrue(e.getMessage().startsWith("<data> is missing required attribute \"id\" value"));
208         }
209     }
210 
211     @Test
212     public void testSCXMLMissingAssignLocation() throws Exception {
213         try {
214             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_MISSING_ASSIGN_LOCATION), null);
215             fail("SCXML reading should have failed due to missing assign location in SCXML");
216         }
217         catch (ModelException e) {
218             assertTrue(e.getMessage().startsWith("<assign> is missing required attribute \"location\" value"));
219         }
220     }
221 
222     @Test
223     public void testSCXMLMissingParamName() throws Exception {
224         try {
225             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_MISSING_PARAM_NAME), null);
226             fail("SCXML reading should have failed due to missing param name in SCXML");
227         }
228         catch (ModelException e) {
229             assertTrue(e.getMessage().startsWith("<param> is missing required attribute \"name\" value"));
230         }
231     }
232 
233     @Test
234     public void testSCXMLParamWithName() throws Exception {
235         SCXMLTestHelper.parse(new StringReader(SCXML_WITH_PARAM_AND_NAME), null);
236         // Note: cannot execute this instance without providing proper <invoke> src attribute
237     }
238 
239     @Test
240     public void testSCXMLMissingForeachArray() throws Exception {
241         try {
242             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_MISSING_FOREACH_ARRAY), null);
243             fail("SCXML reading should have failed due to missing foreach array in SCXML");
244         }
245         catch (ModelException e) {
246             assertTrue(e.getMessage().startsWith("<foreach> is missing required attribute \"array\" value"));
247         }
248     }
249 
250     @Test
251     public void testSCXMLMissingForeachItem() throws Exception {
252         try {
253             SCXMLTestHelper.parse(new StringReader(SCXML_WITH_MISSING_FOREACH_ITEM), null);
254             fail("SCXML reading should have failed due to missing foreach item in SCXML");
255         }
256         catch (ModelException e) {
257             assertTrue(e.getMessage().startsWith("<foreach> is missing required attribute \"item\" value"));
258         }
259     }
260 
261     @Test
262     public void testSCXMLWithForEach() throws Exception {
263         SCXML scxml = SCXMLTestHelper.parse(new StringReader(SCXML_WITH_FOREACH), null);
264         SCXMLExecutor exec = SCXMLTestHelper.getExecutor(scxml);
265         exec.go();
266         assertTrue(exec.getStatus().isFinal());
267     }
268 }