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 static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertNotNull;
21  import static org.junit.jupiter.api.Assertions.assertNotSame;
22  
23  import java.util.Map;
24  import java.util.Set;
25  import java.util.concurrent.atomic.AtomicInteger;
26  
27  import org.apache.commons.jexl3.internal.ArrayBuilder;
28  import org.apache.commons.jexl3.internal.MapBuilder;
29  import org.apache.commons.jexl3.internal.SetBuilder;
30  import org.junit.jupiter.api.Test;
31  
32  /**
33   * Counting the number of times map,sets,array literals are created.
34   * <p>
35   * Originally intended to prove one could cache results of constant map literals when used to create
36   * libraries (a map of lamba).
37   * However, those literals must be newly instantiated since their result may be modified; there is
38   * thus no point in trying to cache them. (Think harder and nod, don't try again.)
39   * These pointless tests as a reminder of 'why' those behave the way they do.
40   * </p>
41   */
42  class CollectionLiteralTest extends JexlTestCase {
43      public static class Arithmetic363 extends JexlArithmetic {
44          final AtomicInteger maps = new AtomicInteger();
45          final AtomicInteger sets = new AtomicInteger();
46          final AtomicInteger arrays = new AtomicInteger();
47  
48          public Arithmetic363(final boolean strict) {
49              super(strict);
50          }
51  
52          @Override public ArrayBuilder arrayBuilder(final int size, final boolean extended) {
53              return new CountingArrayBuilder(arrays, size, extended);
54          }
55          @Override public MapBuilder mapBuilder(final int size, final boolean extended) {
56              return new CountingMapBuilder(maps, size, extended);
57          }
58          @Override public SetBuilder setBuilder(final int size, final boolean extended) {
59              return new CountingSetBuilder(sets, size, extended);
60          }
61      }
62  
63      static class CountingArrayBuilder extends ArrayBuilder {
64          final AtomicInteger count;
65  
66          public CountingArrayBuilder(final AtomicInteger ai, final int size, final boolean extended) {
67              super(size, extended);
68              count = ai;
69          }
70  
71          @Override public Object create(final boolean extended) {
72              final Object array = super.create(extended);
73              count.incrementAndGet();
74              return array;
75          }
76      }
77  
78      static class CountingMapBuilder extends MapBuilder {
79          final AtomicInteger count;
80          public CountingMapBuilder(final AtomicInteger ai, final int size, final boolean extended) {
81              super(size, extended);
82              count = ai;
83          }
84          @Override public Map<Object, Object> create() {
85              final Map<Object, Object> map = super.create();
86              count.incrementAndGet();
87              return map;
88          }
89      }
90  
91      static class CountingSetBuilder extends SetBuilder {
92          final AtomicInteger count;
93          public CountingSetBuilder(final AtomicInteger ai, final int size, final boolean extended) {
94              super(size, extended);
95              count = ai;
96          }
97          @Override public Set<?> create() {
98              final Set<?> set = super.create();
99              count.incrementAndGet();
100             return set;
101         }
102     }
103 
104     public CollectionLiteralTest() {
105         super("CollectionLiteralTest");
106     }
107 
108     @Test
109     void testArrayBuilder() {
110         final Arithmetic363 jc = new Arithmetic363(true);
111         final JexlEngine jexl = new JexlBuilder().cache(4).arithmetic(jc).create();
112         JexlScript script;
113         Object result;
114 
115         script = jexl.createScript("[ (x)->{ 1 + x; }, (y)->{ y - 1; } ]");
116         Object previous = null;
117         for (int i = 0; i < 4; ++i) {
118             result = script.execute(null);
119             assertNotNull(result);
120             assertNotSame(previous, result);
121             previous = result;
122             assertEquals(1 + i, jc.arrays.get());
123         }
124     }
125 
126     @Test
127     void testMapLBuilder() {
128         final Arithmetic363 jc = new Arithmetic363(true);
129         final JexlEngine jexl = new JexlBuilder().cache(4).arithmetic(jc).create();
130         JexlScript script;
131         Object result;
132 
133         script = jexl.createScript("{ 'x':(x)->{ 1 + x; }, 'y' : (y)->{ y - 1; } }");
134         Object previous = null;
135         for(int i = 0; i < 4; ++i) {
136             result = script.execute(null);
137             assertNotNull(result);
138             assertNotSame(previous, result);
139             previous = result;
140             assertEquals(1 + i, jc.maps.get());
141         }
142     }
143 
144     @Test
145     void testSetBuilder() {
146         final Arithmetic363 jc = new Arithmetic363(true);
147         final JexlEngine jexl = new JexlBuilder().cache(4).arithmetic(jc).create();
148         JexlScript script;
149         Object result;
150 
151         script = jexl.createScript("{ (x)->{ 1 + x; }, (y)->{ y - 1; } }");
152         Object previous = null;
153         for(int i = 0; i < 4; ++i) {
154             result = script.execute(null);
155             assertNotNull(result);
156             assertNotSame(previous, result);
157             previous = result;
158             assertEquals(1 + i, jc.sets.get());
159         }
160     }
161 
162 }