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    *      https://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 java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.commons.jexl3.junit.Asserter;
25  import org.junit.jupiter.api.BeforeEach;
26  import org.junit.jupiter.api.Test;
27  
28  /**
29   * Tests for array access operator []
30   */
31  @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
32  class ArrayAccessTest extends JexlTestCase {
33  
34      public static class Sample {
35          private int[] array;
36          public int[] getFoo() {
37              return array;
38          }
39          public void setFoo(final int[] a) {
40              array = a;
41          }
42      }
43  
44      private static final String GET_METHOD_STRING = "GetMethod string";
45  
46      // Needs to be accessible by Foo.class
47      static final String[] GET_METHOD_ARRAY =
48          { "One", "Two", "Three" };
49  
50      // Needs to be accessible by Foo.class
51      static final String[][] GET_METHOD_ARRAY2 =
52          { {"One", "Two", "Three"},{"Four", "Five", "Six"} };
53  
54      private Asserter asserter;
55  
56      public ArrayAccessTest() {
57          super("ArrayAccessTest");
58      }
59  
60      @Override
61      @BeforeEach
62      public void setUp() {
63          asserter = new Asserter(JEXL);
64      }
65  
66      /**
67       * test simple array access
68       */
69      @Test
70      void testArrayAccess() throws Exception {
71  
72          /*
73           * test List access
74           */
75  
76          final List<Integer> l = new ArrayList<>();
77          l.add(Integer.valueOf(1));
78          l.add(Integer.valueOf(2));
79          l.add(Integer.valueOf(3));
80  
81          asserter.setVariable("list", l);
82  
83          asserter.assertExpression("list[1]", Integer.valueOf(2));
84          asserter.assertExpression("list[1+1]", Integer.valueOf(3));
85          asserter.setVariable("loc", Integer.valueOf(1));
86          asserter.assertExpression("list[loc+1]", Integer.valueOf(3));
87  
88          /*
89           * test array access
90           */
91  
92          final String[] args = { "hello", "there" };
93          asserter.setVariable("array", args);
94          asserter.assertExpression("array[0]", "hello");
95  
96          /*
97           * to think that this was an intentional syntax...
98           */
99          asserter.assertExpression("array.0", "hello");
100 
101         /*
102          * test map access
103          */
104         final Map<String, String> m = new HashMap<>();
105         m.put("foo", "bar");
106 
107         asserter.setVariable("map", m);
108         asserter.setVariable("key", "foo");
109 
110         asserter.assertExpression("map[\"foo\"]", "bar");
111         asserter.assertExpression("map[key]", "bar");
112 
113         /*
114          * test bean access
115          */
116         asserter.setVariable("foo", new Foo());
117         asserter.assertExpression("foo[\"bar\"]", GET_METHOD_STRING);
118         asserter.assertExpression("foo[\"bar\"] == foo.bar", Boolean.TRUE);
119     }
120 
121     // This is JEXL-26
122     @Test
123     void testArrayAndDottedConflict() throws Exception {
124         final Object[] objects = {"an", "array", Long.valueOf(0)};
125         asserter.setStrict(false);
126         asserter.setSilent(true);
127         asserter.setVariable("objects", objects);
128         asserter.setVariable("status", "Enabled");
129         asserter.assertExpression("objects[1].status", null);
130         asserter.assertExpression("objects.1.status", null);
131 
132         asserter.setVariable("base.status", "Ok");
133         asserter.assertExpression("base.objects[1].status", null);
134         asserter.assertExpression("base.objects.1.status", null);
135     }
136 
137     @Test
138     void testArrayArray() throws Exception {
139         final Integer i42 = Integer.valueOf(42);
140         final Integer i43 = Integer.valueOf(43);
141         final String s42 = "fourty-two";
142         final String s43 = "fourty-three";
143         final Object[] foo = new Object[3];
144         foo[0] = foo;
145         foo[1] = i42;
146         foo[2] = s42;
147         asserter.setVariable("foo", foo);
148         asserter.setVariable("zero", Integer.valueOf(0));
149         asserter.setVariable("one", Integer.valueOf(1));
150         asserter.setVariable("two", Integer.valueOf(2));
151         for(int l = 0; l < 2; ++l) {
152             asserter.assertExpression("foo[0]", foo);
153             asserter.assertExpression("foo[0][0]", foo);
154             asserter.assertExpression("foo[1]", foo[1]);
155             asserter.assertExpression("foo[0][1]", foo[1]);
156             asserter.assertExpression("foo[0][1] = 43", i43);
157             asserter.assertExpression("foo[0][1]", i43);
158             asserter.assertExpression("foo[0][1] = 42", i42);
159             asserter.assertExpression("foo[0][1]", i42);
160             asserter.assertExpression("foo[0][0][1]", foo[1]);
161             asserter.assertExpression("foo[0][0][1] = 43", i43);
162             asserter.assertExpression("foo[0][0][1]", i43);
163             asserter.assertExpression("foo[0][0][1] = 42", i42);
164             asserter.assertExpression("foo[0][0][1]", i42);
165             asserter.assertExpression("foo[2]", foo[2]);
166             asserter.assertExpression("foo[0][2]", foo[2]);
167             asserter.assertExpression("foo[0][2] = 'fourty-three'", s43);
168             asserter.assertExpression("foo[0][2]", s43);
169             asserter.assertExpression("foo[0][2] = 'fourty-two'", s42);
170             asserter.assertExpression("foo[0][2]", s42);
171             asserter.assertExpression("foo[0][0][2]", foo[2]);
172             asserter.assertExpression("foo[0][0][2] = 'fourty-three'", s43);
173             asserter.assertExpression("foo[0][0][2]", s43);
174             asserter.assertExpression("foo[0][0][2] = 'fourty-two'", s42);
175             asserter.assertExpression("foo[0][0][2]", s42);
176 
177             asserter.assertExpression("foo[zero]", foo);
178             asserter.assertExpression("foo[zero][zero]", foo);
179             asserter.assertExpression("foo[one]", foo[1]);
180             asserter.assertExpression("foo[zero][one]", foo[1]);
181             asserter.assertExpression("foo[zero][one] = 43", i43);
182             asserter.assertExpression("foo[zero][one]", i43);
183             asserter.assertExpression("foo[zero][one] = 42", i42);
184             asserter.assertExpression("foo[zero][one]", i42);
185             asserter.assertExpression("foo[zero][zero][one]", foo[1]);
186             asserter.assertExpression("foo[zero][zero][one] = 43", i43);
187             asserter.assertExpression("foo[zero][zero][one]", i43);
188             asserter.assertExpression("foo[zero][zero][one] = 42", i42);
189             asserter.assertExpression("foo[zero][zero][one]", i42);
190             asserter.assertExpression("foo[two]", foo[2]);
191             asserter.assertExpression("foo[zero][two]", foo[2]);
192             asserter.assertExpression("foo[zero][two] = 'fourty-three'", s43);
193             asserter.assertExpression("foo[zero][two]", s43);
194             asserter.assertExpression("foo[zero][two] = 'fourty-two'", s42);
195             asserter.assertExpression("foo[zero][two]", s42);
196             asserter.assertExpression("foo[zero][zero][two]", foo[2]);
197             asserter.assertExpression("foo[zero][zero][two] = 'fourty-three'", s43);
198             asserter.assertExpression("foo[zero][zero][two]", s43);
199             asserter.assertExpression("foo[zero][zero][two] = 'fourty-two'", s42);
200             asserter.assertExpression("foo[zero][zero][two]", s42);
201         }
202     }
203 
204     @Test
205     void testArrayGetSet() throws Exception {
206         final Sample bar  = new Sample();
207         bar.setFoo(new int[]{24});
208         asserter.setVariable("bar", bar);
209         asserter.assertExpression("bar.foo[0]", 24);
210         asserter.assertExpression("bar.foo = []", new int[0]);
211         //asserter.assertExpression("bar.foo[0]", 42);
212     }
213 
214     @Test
215     void testArrayIdentifierParsing() throws Exception {
216         final Map<Object, Number> map = new HashMap<>();
217         map.put("00200", -42.42d);
218         map.put(200, 42.42d);
219         asserter.setVariable("objects", map);
220         asserter.assertExpression("objects.get('00200')", -42.42d);
221         asserter.assertExpression("objects.'00200'", -42.42d);
222         asserter.assertExpression("objects.get(200)", 42.42d);
223         asserter.assertExpression("objects.'200'", 42.42d);
224         asserter.assertExpression("objects.200", 42.42d);
225     }
226 
227     @Test
228     void testArrayMethods() throws Exception {
229         final Object[] objects = {"an", "array", Long.valueOf(0)};
230 
231         asserter.setVariable("objects", objects);
232         asserter.assertExpression("objects.get(1)", "array");
233         asserter.assertExpression("objects.size()", Integer.valueOf(3));
234         // setting an index returns the old value
235         asserter.assertExpression("objects.set(1, 'dion')", "array");
236         asserter.assertExpression("objects[1]", "dion");
237     }
238 
239     @Test
240     void testArrayProperty() throws Exception {
241         final Foo foo = new Foo();
242 
243         asserter.setVariable("foo", foo);
244 
245         asserter.assertExpression("foo.array[1]", GET_METHOD_ARRAY[1]);
246         asserter.assertExpression("foo.array.1", GET_METHOD_ARRAY[1]);
247         asserter.assertExpression("foo.array2[1][1]", GET_METHOD_ARRAY2[1][1]);
248         asserter.assertExpression("foo.array2[1].1", GET_METHOD_ARRAY2[1][1]);
249     }
250 
251     /**
252      * test some simple double array lookups
253      */
254     @Test
255     void testDoubleArrays() throws Exception {
256         final Object[][] foo = new Object[2][2];
257 
258         foo[0][0] = "one";
259         foo[0][1] = "two";
260         asserter.setVariable("foo", foo);
261         asserter.assertExpression("foo[0][1]", "two");
262         asserter.assertExpression("foo[0][1] = 'three'", "three");
263         asserter.assertExpression("foo[0][1]", "three");
264 
265         foo[0][0] = "one";
266         foo[0][1] = "two";
267         asserter.assertExpression("foo.0[1]", "two");
268         asserter.assertExpression("foo.0[1] = 'three'", "three");
269         asserter.assertExpression("foo.0[1]", "three");
270 
271         foo[0][0] = "one";
272         foo[0][1] = "two";
273         asserter.assertExpression("foo.0.'1'", "two");
274         asserter.assertExpression("foo.0.'1' = 'three'", "three");
275         asserter.assertExpression("foo.0.'1'", "three");
276 
277         foo[0][0] = "one";
278         foo[0][1] = "two";
279         asserter.assertExpression("foo.'0'.'1'", "two");
280         asserter.assertExpression("foo.'0'.'1' = 'three'", "three");
281         asserter.assertExpression("foo.'0'.'1'", "three");
282 
283         foo[0][0] = "one";
284         foo[0][1] = "two";
285         asserter.assertExpression("foo.0.1", "two");
286         asserter.assertExpression("foo.0.1 = 'three'", "three");
287         asserter.assertExpression("foo.0.1", "three");
288     }
289     @Test
290     void testDoubleMaps() throws Exception {
291         final Map<Object, Map<Object, Object>> foo = new HashMap<>();
292         final Map<Object, Object> foo0 = new HashMap<>();
293         foo.put(0, foo0);
294         foo0.put(0, "one");
295         foo0.put(1, "two");
296         foo0.put("3.0", "three");
297         asserter.setVariable("foo", foo);
298         asserter.assertExpression("foo[0][1]", "two");
299         asserter.assertExpression("foo[0][1] = 'three'", "three");
300         asserter.assertExpression("foo[0][1]", "three");
301         asserter.assertExpression("foo[0]['3.0']", "three");
302 
303         foo0.put(0, "one");
304         foo0.put(1, "two");
305         asserter.assertExpression("foo.0[1]", "two");
306         asserter.assertExpression("foo.0[1] = 'three'", "three");
307         asserter.assertExpression("foo.0[1]", "three");
308         asserter.assertExpression("foo.0['3.0']", "three");
309 
310         foo0.put(0, "one");
311         foo0.put(1, "two");
312         asserter.assertExpression("foo.0.'1'", "two");
313         asserter.assertExpression("foo.0.'1' = 'three'", "three");
314         asserter.assertExpression("foo.0.'1'", "three");
315 
316         foo0.put(0, "one");
317         foo0.put(1, "two");
318         asserter.assertExpression("foo.'0'.'1'", "two");
319         asserter.assertExpression("foo.'0'.'1' = 'three'", "three");
320         asserter.assertExpression("foo.'0'.'1'", "three");
321 
322         foo0.put(0, "one");
323         foo0.put(1, "two");
324         asserter.assertExpression("foo.0.1", "two");
325         asserter.assertExpression("foo.0.1 = 'three'", "three");
326         asserter.assertExpression("foo.0.1", "three");
327     }
328 }