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.parser;
18  
19  import org.apache.commons.jexl3.JexlBuilder;
20  import org.apache.commons.jexl3.JexlEngine;
21  import org.apache.commons.jexl3.JexlFeatures;
22  import org.apache.commons.jexl3.JexlTestCase;
23  import org.apache.commons.jexl3.junit.Asserter;
24  import org.junit.jupiter.api.Test;
25  
26  public class FeatureControllerTest extends JexlTestCase {
27  
28      public FeatureControllerTest() {
29          super("FeatureControllerTest");
30  
31      }
32  
33      private JexlEngine createEngine(final JexlFeatures features) {
34          return new JexlBuilder().features(features).imports("java.lang").create();
35      }
36  
37      @Test
38      public void testAnnotationFeatureSwitch() throws Exception {
39          final Asserter onAsserter = new Asserter(createEngine(new JexlFeatures().methodCall(true).annotation(true)));
40          final Asserter offAsserter = new Asserter(createEngine(new JexlFeatures().methodCall(true).annotation(false)));
41          final String expr = "@silent ''.toString()";
42          onAsserter.assertExpression(expr, "");
43          offAsserter.failExpression(expr, "@1:1 annotation error in '@silent'");
44      }
45  
46      @Test
47      public void testLoopFeatureSwitch() throws Exception {
48          final Asserter onAsserter = new Asserter(createEngine(new JexlFeatures().loops(true)));
49          onAsserter.setVariable("cond", true);
50          onAsserter.setVariable("i", 0);
51  
52          final Asserter offAsserter = new Asserter(createEngine(new JexlFeatures().loops(false)));
53          offAsserter.setVariable("cond", true);
54          offAsserter.setVariable("i", 0);
55          String matchException = "@1:1 loop error in 'while (...) ...'";
56          final String whileExpr = "while(cond) { i++;  cond = false; }; i;";
57          onAsserter.assertExpression(whileExpr, 1);
58          offAsserter.failExpression(whileExpr, matchException, String::equals);
59  
60          matchException = "@1:1 loop error in 'do ... while (...)'";
61          onAsserter.setVariable("i", 0);
62          offAsserter.setVariable("i", 0);
63          final String doWhileExpr = "do { i++; } while(false); i;";
64          onAsserter.assertExpression(doWhileExpr, 1);
65          offAsserter.failExpression(doWhileExpr, matchException, String::equals);
66  
67          matchException = "@1:1 loop error in 'for(... : ...) ...'";
68          onAsserter.setVariable("i", 0);
69          offAsserter.setVariable("i", 0);
70          String forExpr = "for (let j : [1, 2]) { i = i + j; }; i;";
71          onAsserter.assertExpression(forExpr, 3);
72          offAsserter.failExpression(forExpr, matchException, String::equals);
73  
74          final int[] a = {1, 2};
75          onAsserter.setVariable("a", a);
76          offAsserter.setVariable("a", a);
77          onAsserter.setVariable("i", 0);
78          offAsserter.setVariable("i", 0);
79          forExpr = "for(let j = 0; j < 2; ++j) { i = i + a[j]; } i;";
80          onAsserter.assertExpression(forExpr, 3);
81          offAsserter.failExpression(forExpr, matchException, String::equals);
82      }
83  
84      @Test
85      public void testMethodCallFeatureSwitch() throws Exception {
86          final Asserter onAsserter = new Asserter(createEngine(new JexlFeatures().methodCall(true)));
87          final Asserter offAsserter = new Asserter(createEngine(new JexlFeatures().methodCall(false)));
88          final String expr = "'jexl'.toUpperCase()";
89          onAsserter.assertExpression(expr, "JEXL");
90          offAsserter.failExpression(expr, "@1:7 method call error in '.toUpperCase(...)'", String::equals);
91      }
92  
93      @Test
94      public void testNewInstanceFeatureSwitch() throws Exception {
95          final Asserter onAsserter = new Asserter(createEngine(new JexlFeatures().newInstance(true)));
96          final Asserter offAsserter = new Asserter(createEngine(new JexlFeatures().newInstance(false)));
97          String expr = "new('java.lang.String', 'JEXL')";
98          onAsserter.assertExpression(expr, "JEXL");
99          offAsserter.failExpression(expr, "@1:1 create instance error in 'new(..., ...)'", String::equals);
100         expr = "new String('JEXL')";
101         onAsserter.assertExpression(expr, "JEXL");
102         offAsserter.failExpression(expr, "@1:1 create instance error in 'new ...(...)'", String::equals);
103     }
104 
105     @Test
106     public void testSideEffectDisabled() throws Exception {
107         final Asserter asserter = new Asserter(createEngine(new JexlFeatures().sideEffect(false)));
108         asserter.setVariable("i", 1);
109         String matchException = "@1:1 assign/modify error in 'i'";
110         asserter.failExpression("i = 1", matchException);
111         asserter.failExpression("i = i + 1", matchException);
112         asserter.failExpression("i = i - 1", matchException);
113         asserter.failExpression("i = i * 2", matchException);
114         asserter.failExpression("i = i / 2", matchException);
115         asserter.failExpression("i = i % 2", matchException);
116         asserter.failExpression("i = i ^ 0", matchException);
117         asserter.failExpression("i = i << 1", matchException);
118         asserter.failExpression("i = i >> 1", matchException);
119         asserter.failExpression("i = i >>> 1", matchException);
120 
121         asserter.failExpression("i += 1", matchException);
122         asserter.failExpression("i -= 1", matchException);
123         asserter.failExpression("i *= 2", matchException);
124         asserter.failExpression("i /= 2", matchException);
125         asserter.failExpression("i %= 2", matchException);
126         asserter.failExpression("i ^= 0", matchException);
127         asserter.failExpression("i <<= 1", matchException);
128         asserter.failExpression("i >>= 1", matchException);
129         asserter.failExpression("i >>>= 1", matchException);
130 
131         asserter.failExpression("i++", matchException);
132         asserter.failExpression("i--", matchException);
133         matchException = "@1:3 assign/modify error in 'i'";
134         asserter.failExpression("++i", matchException);
135         asserter.failExpression("--i", matchException);
136     }
137 
138     @Test
139     public void testSideEffectEnabled() throws Exception {
140         final Asserter asserter = new Asserter(createEngine(new JexlFeatures().sideEffect(true)));
141         asserter.assertExpression("i = 1", 1); // 1
142         asserter.assertExpression("i = i + 1", 2); // 1 + 1 = 2
143         asserter.assertExpression("i = i - 1", 1); // 2 - 1 = 1
144         asserter.assertExpression("i = i * 2", 2); // 1 * 2 = 2
145         asserter.assertExpression("i = i / 2", 1); // 2 / 2 = 1
146         asserter.assertExpression("i = i % 2", 1); // 1 % 1 = 1
147         asserter.assertExpression("i = i ^ 0", 1L); // 1 ^ 0 = 1
148         asserter.assertExpression("i = i << 1", 2L); // 1 << 1 = 2
149         asserter.assertExpression("i = i >> 1", 1L); // 1 >> 1 = 1
150         asserter.assertExpression("i = i >>> 1", 0L); // 1 >>> 1 = 0
151 
152         // reset
153         asserter.assertExpression("i = 1", 1);
154         asserter.assertExpression("i += 1", 2);
155         asserter.assertExpression("i -= 1", 1);
156         asserter.assertExpression("i *= 2", 2);
157         asserter.assertExpression("i /= 2", 1);
158         asserter.assertExpression("i %= 2", 1);
159         asserter.assertExpression("i ^= 0", 1L);
160         asserter.assertExpression("i <<= 1", 2L);
161         asserter.assertExpression("i >>= 1", 1L);
162         asserter.assertExpression("i >>>= 1", 0L);
163 
164         // reset
165         asserter.assertExpression("i = 1", 1);
166         asserter.assertExpression("++i", 2);
167         asserter.assertExpression("--i", 1);
168         asserter.assertExpression("i++", 1);
169         asserter.assertExpression("i--", 2);
170     }
171 
172     @Test
173     public void testStructuredLiteralFeatureSwitch() throws Exception {
174         final Asserter onAsserter = new Asserter(createEngine(new JexlFeatures().structuredLiteral(true)));
175         final Asserter offAsserter = new Asserter(createEngine(new JexlFeatures().structuredLiteral(false)));
176         final String arrayLitExpr = "[1, 2, 3, 4][3]";
177         onAsserter.assertExpression(arrayLitExpr, 4);
178         offAsserter.failExpression(arrayLitExpr, "@1:1 set/map/array literal error in '[ ... ]'", String::equals);
179 
180         final String mapLitExpr = "{'A' : 1, 'B' : 2}['B']";
181         onAsserter.assertExpression(mapLitExpr, 2);
182         offAsserter.failExpression(mapLitExpr, "@1:1 set/map/array literal error in '{ ... }'", String::equals);
183 
184         final String setLitExpr = "{'A', 'B'}.size()";
185         onAsserter.assertExpression(setLitExpr, 2);
186         offAsserter.failExpression(setLitExpr, "@1:1 set/map/array literal error in '{ ... }'", String::equals);
187 
188         final String rangeLitExpr = "(0..3).size()";
189         onAsserter.assertExpression(rangeLitExpr, 4);
190         offAsserter.failExpression(rangeLitExpr, "@1:5 set/map/array literal error in '( .. )'", String::equals);
191     }
192 
193 }