1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.scxml2.env.javascript;
19
20 import java.io.StringReader;
21
22 import javax.xml.xpath.XPath;
23 import javax.xml.xpath.XPathConstants;
24 import javax.xml.xpath.XPathFactory;
25
26 import org.apache.commons.scxml2.Context;
27 import org.apache.commons.scxml2.Evaluator;
28 import org.apache.commons.scxml2.SCXMLExecutor;
29 import org.apache.commons.scxml2.SCXMLExpressionException;
30 import org.apache.commons.scxml2.SCXMLTestHelper;
31 import org.apache.commons.scxml2.io.SCXMLReader;
32 import org.junit.Assert;
33 import org.junit.Before;
34 import org.junit.Test;
35 import org.w3c.dom.Element;
36 import org.w3c.dom.Node;
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class JSEvaluatorTest {
51
52
53 private static final String BAD_EXPRESSION = ">";
54 private static final String SCRIPT = "<?xml version='1.0'?>" +
55 "<scxml xmlns = 'http://www.w3.org/2005/07/scxml' " +
56 "xmlns:scxml = 'http://commons.apache.org/scxml' " +
57 "datamodel = 'ecmascript' " +
58 "initial = 'start' " +
59 "version = '1.0'>" +
60 "<datamodel>" +
61 "<data id='forest'>" +
62 "<tree xmlns=''>" +
63 "<branch>" +
64 "<twig>leaf</twig>" +
65 "</branch>" +
66 "</tree>" +
67 "</data>" +
68 "</datamodel>" +
69 "<state id='start'>" +
70 "<transition target='end' />" +
71 "</state>" +
72 "<state id='end' final='true' />" +
73 "</scxml>";
74
75 private static final TestItem[] SIMPLE_EXPRESSIONS = {
76 new TestItem("'FIB: ' + (1 + 1 + 2 + 3 + 5)",new String("FIB: 12")),
77 new TestItem("1 + 1 + 2 + 3 + 5", new Integer(12)),
78 new TestItem("1.1 + 1.1 + 2.1 + 3.1 + 5.1", new Double(12.5)),
79 new TestItem("(1 + 1 + 2 + 3 + 5) == 12", new Boolean(true)),
80 new TestItem("(1 + 1 + 2 + 3 + 5) == 13", new Boolean(false)),
81 };
82
83 private static final TestItem[] VAR_EXPRESSIONS = {
84 new TestItem("'FIB: ' + fibonacci",new String("FIB: 12")),
85 new TestItem("fibonacci * 2", new Double(24)),
86 };
87
88 private static final String FUNCTION = "function factorial(N) {\r\n" +
89 "if (N == 1)\r\n" +
90 " return N;\r\n" +
91 "\r\n" +
92 "return N * factorial(N-1);\r\n" +
93 "};\r\n" +
94 "\r\n" +
95 "function fact5() {\r\n" +
96 " return factorial(FIVE);\r\n" +
97 "};\r\n" +
98 "\r\n" +
99 "fact5()";
100
101
102
103 private Context context;
104 private Evaluator evaluator;
105 private SCXMLExecutor fsm;
106
107
108
109
110
111
112
113 @Before
114 public void setUp() throws Exception {
115 fsm = SCXMLTestHelper.getExecutor(SCXMLReader.read(new StringReader(SCRIPT)));
116 evaluator = fsm.getEvaluator();
117 context = fsm.getGlobalContext();
118 context.set(Context.NAMESPACES_KEY,null);
119 }
120
121
122
123
124
125
126
127 public static void main(String args[]) {
128 String[] testCaseName = {JSEvaluatorTest.class.getName()};
129
130 junit.textui.TestRunner.main(testCaseName);
131 }
132
133
134
135
136
137
138
139
140 @Test
141 public void testBasic() throws SCXMLExpressionException {
142 Evaluator evaluator = new JSEvaluator();
143
144 Assert.assertNotNull(evaluator);
145 Assert.assertTrue (((Boolean) evaluator.eval(context, "1+1 == 2")).booleanValue());
146 }
147
148 @Test
149 public void testScript() throws SCXMLExpressionException {
150 Evaluator evaluator = new JSEvaluator();
151 context.set("x", 3);
152 context.set("y", 0);
153 String script =
154 "if ((x * 2.0) == 5.0) {" +
155 "y = 1.0;\n" +
156 "} else {\n" +
157 "y = 2.0;\n" +
158 "}";
159 Assert.assertEquals(2.0, evaluator.evalScript(context, script));
160 Assert.assertEquals(2.0, context.get("y"));
161 }
162
163
164
165
166
167 @Test
168 public void testIllegalExpresssion() {
169 Evaluator evaluator = new JSEvaluator();
170
171 Assert.assertNotNull(evaluator);
172
173 try {
174 evaluator.eval(context,BAD_EXPRESSION);
175 Assert.fail ("JSEvaluator should throw SCXMLExpressionException");
176
177 } catch (SCXMLExpressionException x) {
178 Assert.assertTrue("JSEvaluator: Incorrect error message",
179 x.getMessage().startsWith("Error evaluating ['" + BAD_EXPRESSION + "']"));
180 }
181 }
182
183
184
185
186
187 @Test
188 public void testStandardExpressions() throws Exception {
189 for (TestItem item: SIMPLE_EXPRESSIONS) {
190 Object eval = evaluator.eval(context,item.expression);
191 if (item.result instanceof Integer && eval instanceof Number) {
192 Assert.assertEquals("Invalid result: " + item.expression,
193 ((Integer) item.result).intValue(),
194 ((Number) eval).intValue());
195 } else {
196 Assert.assertEquals("Invalid result: " + item.expression,
197 item.result,
198 eval);
199 }
200 }
201 }
202
203
204
205
206
207 @Test
208 public void testVarExpressions() throws Exception {
209 context.set("fibonacci",Integer.valueOf(12));
210
211 for (TestItem item: VAR_EXPRESSIONS) {
212 Assert.assertNotNull(context.get("fibonacci"));
213 Assert.assertEquals (Integer.valueOf(12),context.get("fibonacci"));
214 Assert.assertEquals ("Invalid result: " + item.expression,
215 item.result,
216 evaluator.eval(context,item.expression));
217 }
218 }
219
220
221
222
223
224 @Test
225 public void testInvalidVarExpressions() {
226 for (TestItem item: VAR_EXPRESSIONS) {
227 try {
228 Assert.assertNull (context.get("fibonacci"));
229 evaluator.eval(context,item.expression);
230 Assert.fail ("Evaluated invalid <var... expression: " + item.expression);
231
232 } catch (SCXMLExpressionException x) {
233
234 }
235 }
236 }
237
238
239
240
241
242 @Test
243 public void testDataModelExpressions() throws Exception {
244 Assert.assertEquals("Invalid result: " + "Data('string($forest/tree/branch/twig)')",
245 "leaf",
246 evaluator.eval(context,"Data('string($forest/tree/branch/twig)')"));
247 }
248
249
250
251
252
253 @Test
254 public void testInvalidDataModelExpressions() {
255 Assert.assertNull(context.get("forestx"));
256
257 try {
258 evaluator.eval(context,"Data(forestx,'string($forestx/tree/branch/twig)')");
259 Assert.fail ("Evaluated invalid Data() expression: " + "Data('string($forestx/tree/branch/twig)')");
260
261 } catch (SCXMLExpressionException x) {
262
263 }
264 }
265
266
267
268
269
270 @Test
271 public void testDataModelLocations() throws Exception {
272 Assert.assertNotNull(context.get("forest"));
273 XPath xpath = XPathFactory.newInstance().newXPath();
274 Node node = (Node) context.get("forest");
275 Node twig = (Node) xpath.evaluate("tree/branch/twig", node, XPathConstants.NODE);
276
277 Assert.assertTrue ("Invalid result: " + "Data(forest,'$forest/tree/branch/twig')",
278 evaluator.eval(context,"Data('$forest/tree/branch/twig')") instanceof Element);
279
280 Assert.assertSame ("Incorrect node returned: " + "Data('$forest/tree/branch/twig')",
281 twig,
282 evaluator.eval(context,"Data('$forest/tree/branch/twig')"));
283 }
284
285
286
287
288
289 @Test
290 public void testInvalidDataModelLocations() throws Exception {
291 Assert.assertNotNull(context.get("forest"));
292 Assert.assertNull("Invalid result: " + "Data('$forest/tree/branch/twigx')",
293 evaluator.eval(context,"Data('$forest/tree/branch/twigx')"));
294 }
295
296
297
298
299
300 @Test
301 public void testScriptFunctions() throws Exception {
302 context.set("FIVE",Integer.valueOf(5));
303 Assert.assertEquals(Integer.valueOf(5),context.get("FIVE"));
304 Assert.assertEquals("Invalid function result",Double.valueOf(120.0),evaluator.eval(context,FUNCTION));
305 }
306
307
308
309
310 private static class TestItem {
311 private String expression;
312 private Object result;
313
314 private TestItem(String expression,Object result) {
315 this.expression = expression;
316 this.result = result;
317 }
318 }
319
320 }
321