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.jexl3;
18  
19  import org.junit.Assert;
20  import org.junit.Test;
21  
22  /**
23   * Test cases for the if statement.
24   *
25   * @since 1.1
26   */
27  @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
28  public class IfTest extends JexlTestCase {
29      public IfTest() {
30          super("IfTest");
31      }
32  
33      /**
34       * Make sure if true executes the true statement
35       *
36       * @throws Exception on any error
37       */
38      @Test
39      public void testSimpleIfTrue() throws Exception {
40          final JexlScript e = JEXL.createScript("if (true) 1");
41          final JexlContext jc = new MapContext();
42  
43          final Object o = e.execute(jc);
44          Assert.assertEquals("Result is not 1", new Integer(1), o);
45      }
46  
47      /**
48       * Make sure if false doesn't execute the true statement
49       *
50       * @throws Exception on any error
51       */
52      @Test
53      public void testSimpleIfFalse() throws Exception {
54          final JexlScript e = JEXL.createScript("if (false) 1");
55          final JexlContext jc = new MapContext();
56  
57          final Object o = e.execute(jc);
58          Assert.assertNull("Return value is not empty", o);
59      }
60  
61      /**
62       * Make sure if false executes the false statement
63       *
64       * @throws Exception on any error
65       */
66      @Test
67      public void testSimpleElse() throws Exception {
68          final JexlScript e = JEXL.createScript("if (false) 1 else 2;");
69          final JexlContext jc = new MapContext();
70  
71          final Object o = e.execute(jc);
72          Assert.assertEquals("Result is not 2", new Integer(2), o);
73      }
74  
75      /**
76       * Test the if statement handles blocks correctly
77       *
78       * @throws Exception on any error
79       */
80      @Test
81      public void testBlockIfTrue() throws Exception {
82          final JexlScript e = JEXL.createScript("if (true) { 'hello'; }");
83          final JexlContext jc = new MapContext();
84  
85          final Object o = e.execute(jc);
86          Assert.assertEquals("Result is wrong", "hello", o);
87      }
88  
89      /**
90       * Test the if statement handles blocks in the else statement correctly
91       *
92       * @throws Exception on any error
93       */
94      @Test
95      public void testBlockElse() throws Exception {
96          final JexlScript e = JEXL.createScript("if (false) {1} else {2 ; 3}");
97          final JexlContext jc = new MapContext();
98  
99          final Object o = e.execute(jc);
100         Assert.assertEquals("Result is wrong", new Integer(3), o);
101     }
102 
103     /**
104      * Test the if statement evaluates expressions correctly
105      *
106      * @throws Exception on any error
107      */
108     @Test
109     public void testIfWithSimpleExpression() throws Exception {
110         final JexlScript e = JEXL.createScript("if (x == 1) true;");
111         final JexlContext jc = new MapContext();
112         jc.set("x", new Integer(1));
113 
114         final Object o = e.execute(jc);
115         Assert.assertEquals("Result is not true", Boolean.TRUE, o);
116     }
117 
118     @Test
119     public void testIfElseIfExpression() throws Exception {
120         final JexlScript e = JEXL.createScript("if (x == 1) { 10; } else if (x == 2) 20  else 30", "x");
121         Object o = e.execute(null, 1);
122         Assert.assertEquals(10, o);
123         o = e.execute(null, 2);
124         Assert.assertEquals(20, o);
125         o = e.execute(null, 4);
126         Assert.assertEquals(30, o);
127     }
128 
129     @Test
130     public void testIfElseIfReturnExpression0() throws Exception {
131         final JexlScript e = JEXL.createScript(
132                 "if (x == 1) return 10; if (x == 2)  return 20; else if (x == 3) return 30  else { return 40 }",
133                 "x");
134         Object o = e.execute(null, 1);
135         Assert.assertEquals(10, o);
136         o = e.execute(null, 2);
137         Assert.assertEquals(20, o);
138         o = e.execute(null, 3);
139         Assert.assertEquals(30, o);
140         o = e.execute(null, 4);
141         Assert.assertEquals(40, o);
142     }
143 
144     @Test
145     public void testIfElseIfReturnExpression() throws Exception {
146         final JexlScript e = JEXL.createScript(
147                 "if (x == 1) return 10;  if (x == 2) return 20  else if (x == 3) return 30; else return 40;",
148                 "x");
149         Object o = e.execute(null, 1);
150         Assert.assertEquals(10, o);
151         o = e.execute(null, 2);
152         Assert.assertEquals(20, o);
153         o = e.execute(null, 3);
154         Assert.assertEquals(30, o);
155         o = e.execute(null, 4);
156         Assert.assertEquals(40, o);
157     }
158 
159     /**
160      * Test the if statement evaluates arithmetic expressions correctly
161      *
162      * @throws Exception on any error
163      */
164     @Test
165     public void testIfWithArithmeticExpression() throws Exception {
166         final JexlScript e = JEXL.createScript("if ((x * 2) + 1 == 5) true;");
167         final JexlContext jc = new MapContext();
168         jc.set("x", new Integer(2));
169 
170         final Object o = e.execute(jc);
171         Assert.assertEquals("Result is not true", Boolean.TRUE, o);
172     }
173 
174     /**
175      * Test the if statement evaluates decimal arithmetic expressions correctly
176      *
177      * @throws Exception on any error
178      */
179     @Test
180     public void testIfWithDecimalArithmeticExpression() throws Exception {
181         final JexlScript e = JEXL.createScript("if ((x * 2) == 5) true");
182         final JexlContext jc = new MapContext();
183         jc.set("x", new Float(2.5f));
184 
185         final Object o = e.execute(jc);
186         Assert.assertEquals("Result is not true", Boolean.TRUE, o);
187     }
188 
189     /**
190      * Test the if statement works with assignment
191      *
192      * @throws Exception on any error
193      */
194     @Test
195     public void testIfWithAssignment() throws Exception {
196         final JexlScript e = JEXL.createScript("if ((x * 2) == 5) {y = 1} else {y = 2;}");
197         final JexlContext jc = new MapContext();
198         jc.set("x", new Float(2.5f));
199 
200         e.execute(jc);
201         final Object result = jc.get("y");
202         Assert.assertEquals("y has the wrong value", new Integer(1), result);
203     }
204 
205     /**
206      * Ternary operator condition undefined or null evaluates to false
207      * independently of engine flags.
208      * @throws Exception
209      */
210     @Test
211     public void testTernary() throws Exception {
212         final JexlEngine jexl = JEXL;
213 
214         final JexlEvalContext jc = new JexlEvalContext();
215         final JexlOptions options = jc.getEngineOptions();
216         final JexlExpression e = jexl.createExpression("x.y.z = foo ?'bar':'quux'");
217         Object o;
218 
219         // undefined foo
220         for (int l = 0; l < 4; ++l) {
221             options.setStrict((l & 1) == 0);
222             options.setSilent((l & 2) != 0);
223             o = e.evaluate(jc);
224             Assert.assertEquals("Should be quux", "quux", o);
225             o = jc.get("x.y.z");
226             Assert.assertEquals("Should be quux", "quux", o);
227         }
228 
229         jc.set("foo", null);
230 
231         for (int l = 0; l < 4; ++l) {
232             options.setStrict((l & 1) == 0);
233             options.setSilent((l & 2) != 0);
234             o = e.evaluate(jc);
235             Assert.assertEquals("Should be quux", "quux", o);
236             o = jc.get("x.y.z");
237             Assert.assertEquals("Should be quux", "quux", o);
238         }
239 
240         jc.set("foo", Boolean.FALSE);
241 
242         for (int l = 0; l < 4; ++l) {
243             options.setStrict((l & 1) == 0);
244             options.setSilent((l & 2) != 0);
245             o = e.evaluate(jc);
246             Assert.assertEquals("Should be quux", "quux", o);
247             o = jc.get("x.y.z");
248             Assert.assertEquals("Should be quux", "quux", o);
249         }
250 
251         jc.set("foo", Boolean.TRUE);
252 
253         for (int l = 0; l < 4; ++l) {
254             options.setStrict((l & 1) == 0);
255             options.setSilent((l & 2) != 0);
256             o = e.evaluate(jc);
257             Assert.assertEquals("Should be bar", "bar", o);
258             o = jc.get("x.y.z");
259             Assert.assertEquals("Should be bar", "bar", o);
260         }
261 
262         debuggerCheck(jexl);
263     }
264 
265     /**
266      * Ternary operator condition undefined or null evaluates to false
267      * independently of engine flags; same for null coalescing operator.
268      * @throws Exception
269      */
270     @Test
271     public void testTernaryShorthand() throws Exception {
272         final JexlEvalContext jc = new JexlEvalContext();
273         final JexlOptions options = jc.getEngineOptions();
274         final JexlExpression e = JEXL.createExpression("x.y.z = foo?:'quux'");
275         final JexlExpression f = JEXL.createExpression("foo??'quux'");
276         Object o;
277 
278         // undefined foo
279         for (int l = 0; l < 4; ++l) {
280             options.setStrict((l & 1) == 0);
281             options.setSilent((l & 2) != 0);
282             o = e.evaluate(jc);
283             Assert.assertEquals("Should be quux", "quux", o);
284             o = jc.get("x.y.z");
285             Assert.assertEquals("Should be quux", "quux", o);
286             o = f.evaluate(jc);
287             Assert.assertEquals("Should be quux", "quux", o);
288         }
289 
290         jc.set("foo", null);
291 
292         for (int l = 0; l < 4; ++l) {
293             options.setStrict((l & 1) == 0);
294             options.setSilent((l & 2) != 0);
295             o = e.evaluate(jc);
296             Assert.assertEquals("Should be quux", "quux", o);
297             o = jc.get("x.y.z");
298             Assert.assertEquals("Should be quux", "quux", o);
299             o = f.evaluate(jc);
300             Assert.assertEquals("Should be quux", "quux", o);
301         }
302 
303         jc.set("foo", Boolean.FALSE);
304 
305         for (int l = 0; l < 4; ++l) {
306             options.setStrict((l & 1) == 0);
307             options.setSilent((l & 2) != 0);
308             o = e.evaluate(jc);
309             Assert.assertEquals("Should be quux", "quux", o);
310             o = jc.get("x.y.z");
311             Assert.assertEquals("Should be quux", "quux", o);
312             o = f.evaluate(jc);
313             Assert.assertEquals("Should be false", false, o);
314         }
315 
316         jc.set("foo", Double.NaN);
317 
318         for (int l = 0; l < 4; ++l) {
319             options.setStrict((l & 1) == 0);
320             options.setSilent((l & 2) != 0);
321             o = e.evaluate(jc);
322             Assert.assertEquals("Should be quux", "quux", o);
323             o = jc.get("x.y.z");
324             Assert.assertEquals("Should be quux", "quux", o);
325             o = f.evaluate(jc);
326             Assert.assertTrue("Should be NaN", Double.isNaN((Double) o));
327         }
328 
329         jc.set("foo", "");
330 
331         for (int l = 0; l < 4; ++l) {
332             options.setStrict((l & 1) == 0);
333             options.setSilent((l & 2) != 0);
334             o = e.evaluate(jc);
335             Assert.assertEquals("Should be quux", "quux", o);
336             o = jc.get("x.y.z");
337             Assert.assertEquals("Should be quux", "quux", o);
338             o = f.evaluate(jc);
339             Assert.assertEquals("Should be empty string", "", o);
340         }
341 
342         jc.set("foo", "false");
343 
344         for (int l = 0; l < 4; ++l) {
345             options.setStrict((l & 1) == 0);
346             options.setSilent((l & 2) != 0);
347             o = e.evaluate(jc);
348             Assert.assertEquals("Should be quux", "quux", o);
349             o = jc.get("x.y.z");
350             Assert.assertEquals("Should be quux", "quux", o);
351             o = f.evaluate(jc);
352             Assert.assertEquals("Should be 'false'", "false", o);
353         }
354 
355         jc.set("foo", 0d);
356 
357         for (int l = 0; l < 4; ++l) {
358             options.setStrict((l & 1) == 0);
359             options.setSilent((l & 2) != 0);
360             o = e.evaluate(jc);
361             Assert.assertEquals("Should be quux", "quux", o);
362             o = jc.get("x.y.z");
363             Assert.assertEquals("Should be quux", "quux", o);
364             o = f.evaluate(jc);
365             Assert.assertEquals("Should be 0", 0.d, o);
366         }
367 
368         jc.set("foo", 0);
369 
370         for (int l = 0; l < 4; ++l) {
371             options.setStrict((l & 1) == 0);
372             options.setSilent((l & 2) != 0);
373             o = e.evaluate(jc);
374             Assert.assertEquals("Should be quux", "quux", o);
375             o = jc.get("x.y.z");
376             Assert.assertEquals("Should be quux", "quux", o);
377             o = f.evaluate(jc);
378             Assert.assertEquals("Should be 0", 0, o);
379         }
380 
381         jc.set("foo", "bar");
382 
383         for (int l = 0; l < 4; ++l) {
384             options.setStrict((l & 1) == 0);
385             options.setSilent((l & 2) != 0);
386             o = e.evaluate(jc);
387             Assert.assertEquals("Should be bar", "bar", o);
388             o = jc.get("x.y.z");
389             Assert.assertEquals("Should be bar", "bar", o);
390         }
391 
392         debuggerCheck(JEXL);
393     }
394 
395     @Test
396     public void testNullCoaelescing() throws Exception {
397         Object o;
398         final JexlEvalContext jc = new JexlEvalContext();
399         final JexlExpression xtrue = JEXL.createExpression("x??true");
400         o = xtrue.evaluate(jc);
401         Assert.assertEquals("Should be true", true, o);
402         jc.set("x", false);
403         o = xtrue.evaluate(jc);
404         Assert.assertEquals("Should be false", false, o);
405         final JexlExpression yone = JEXL.createExpression("y??1");
406         o = yone.evaluate(jc);
407         Assert.assertEquals("Should be 1", 1, o);
408         jc.set("y", 0);
409         o = yone.evaluate(jc);
410         Assert.assertEquals("Should be 0", 0, o);
411         debuggerCheck(JEXL);
412     }
413 
414     @Test
415     public void testNullCoaelescingScript() throws Exception {
416         Object o;
417         final JexlEvalContext jc = new JexlEvalContext();
418         final JexlScript xtrue = JEXL.createScript("x??true");
419         o = xtrue.execute(jc);
420         Assert.assertEquals("Should be true", true, o);
421         jc.set("x", false);
422         o = xtrue.execute(jc);
423         Assert.assertEquals("Should be false", false, o);
424         final JexlScript yone = JEXL.createScript("y??1");
425         o = yone.execute(jc);
426         Assert.assertEquals("Should be 1", 1, o);
427         jc.set("y", 0);
428         o = yone.execute(jc);
429         Assert.assertEquals("Should be 0", 0, o);
430         debuggerCheck(JEXL);
431     }
432 
433 
434     @Test
435     public void testTernaryFail() throws Exception {
436         final JexlEvalContext jc = new JexlEvalContext();
437         final JexlOptions options = jc.getEngineOptions();
438         final JexlExpression e = JEXL.createExpression("false ? bar : quux");
439         Object o;
440         options.setStrict(true);
441         options.setSilent(false);
442         try {
443            o = e.evaluate(jc);
444            Assert.fail("Should have failed");
445         } catch (final JexlException xjexl) {
446            // OK
447            Assert.assertTrue(xjexl.toString().contains("quux"));
448         }
449     }
450 }