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.collections4;
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.assertSame;
22  import static org.junit.jupiter.api.Assertions.assertThrows;
23  
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.HashMap;
29  import java.util.Map;
30  
31  import org.apache.commons.collections4.functors.EqualPredicate;
32  import org.apache.commons.collections4.functors.ExceptionClosure;
33  import org.apache.commons.collections4.functors.FalsePredicate;
34  import org.apache.commons.collections4.functors.NOPClosure;
35  import org.apache.commons.collections4.functors.TruePredicate;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * Tests the ClosureUtils class.
40   */
41  public class ClosureUtilsTest {
42  
43      static class MockClosure<T> implements Closure<T> {
44          int count;
45  
46          @Override
47          public void execute(final T object) {
48              count++;
49          }
50  
51          public void reset() {
52              count = 0;
53          }
54      }
55  
56      static class MockTransformer<T> implements Transformer<T, T> {
57          int count;
58  
59          @Override
60          public T transform(final T object) {
61              count++;
62              return object;
63          }
64      }
65  
66      private static final Object cString = "Hello";
67  
68      @Test
69      @SuppressWarnings("unchecked")
70      public void testChainedClosure() {
71          MockClosure<Object> a = new MockClosure<>();
72          MockClosure<Object> b = new MockClosure<>();
73          ClosureUtils.chainedClosure(a, b).accept(null);
74          assertEquals(1, a.count);
75          assertEquals(1, b.count);
76  
77          a = new MockClosure<>();
78          b = new MockClosure<>();
79          ClosureUtils.<Object>chainedClosure(a, b, a).execute(null);
80          assertEquals(2, a.count);
81          assertEquals(1, b.count);
82  
83          a = new MockClosure<>();
84          b = new MockClosure<>();
85          final Collection<Closure<Object>> coll = new ArrayList<>();
86          coll.add(b);
87          coll.add(a);
88          coll.add(b);
89          ClosureUtils.<Object>chainedClosure(coll).execute(null);
90          assertEquals(1, a.count);
91          assertEquals(2, b.count);
92  
93          assertSame(NOPClosure.INSTANCE, ClosureUtils.<Object>chainedClosure());
94          assertSame(NOPClosure.INSTANCE, ClosureUtils.<Object>chainedClosure(Collections.<Closure<Object>>emptyList()));
95  
96          assertThrows(NullPointerException.class, () -> ClosureUtils.chainedClosure(null, null));
97          assertThrows(NullPointerException.class, () -> ClosureUtils.<Object>chainedClosure((Closure[]) null));
98          assertThrows(NullPointerException.class, () -> ClosureUtils.<Object>chainedClosure((Collection<Closure<Object>>) null));
99          assertThrows(NullPointerException.class, () -> ClosureUtils.<Object>chainedClosure(null, null));
100         final Collection<Closure<Object>> finalColl = new ArrayList<>();
101         finalColl.add(null);
102         finalColl.add(null);
103         assertThrows(NullPointerException.class, () -> ClosureUtils.chainedClosure(finalColl));
104     }
105 
106     @Test
107     public void testDoWhileClosure() {
108         MockClosure<Object> cmd = new MockClosure<>();
109         ClosureUtils.doWhileClosure(cmd, FalsePredicate.falsePredicate()).execute(null);
110         assertEquals(1, cmd.count);
111 
112         cmd = new MockClosure<>();
113         ClosureUtils.doWhileClosure(cmd, PredicateUtils.uniquePredicate()).execute(null);
114         assertEquals(2, cmd.count);
115 
116         assertThrows(NullPointerException.class, () -> ClosureUtils.doWhileClosure(null, null));
117     }
118 
119     @Test
120     public void testExceptionClosure() {
121         assertNotNull(ClosureUtils.exceptionClosure());
122         assertSame(ClosureUtils.exceptionClosure(), ClosureUtils.exceptionClosure());
123 
124         assertThrows(FunctorException.class, () -> ClosureUtils.exceptionClosure().execute(null));
125         assertThrows(FunctorException.class, () -> ClosureUtils.exceptionClosure().execute(cString));
126     }
127 
128     @Test
129     public void testForClosure() {
130         final MockClosure<Object> cmd = new MockClosure<>();
131         ClosureUtils.forClosure(5, cmd).execute(null);
132         assertEquals(5, cmd.count);
133         assertSame(NOPClosure.INSTANCE, ClosureUtils.forClosure(0, new MockClosure<>()));
134         assertSame(NOPClosure.INSTANCE, ClosureUtils.forClosure(-1, new MockClosure<>()));
135         assertSame(NOPClosure.INSTANCE, ClosureUtils.forClosure(1, null));
136         assertSame(NOPClosure.INSTANCE, ClosureUtils.forClosure(3, null));
137         assertSame(cmd, ClosureUtils.forClosure(1, cmd));
138     }
139 
140     @Test
141     public void testIfClosure() {
142         MockClosure<Object> a = new MockClosure<>();
143         MockClosure<Object> b;
144         ClosureUtils.ifClosure(TruePredicate.truePredicate(), a).execute(null);
145         assertEquals(1, a.count);
146 
147         a = new MockClosure<>();
148         ClosureUtils.ifClosure(FalsePredicate.<Object>falsePredicate(), a).execute(null);
149         assertEquals(0, a.count);
150 
151         a = new MockClosure<>();
152         b = new MockClosure<>();
153         ClosureUtils.ifClosure(TruePredicate.<Object>truePredicate(), a, b).execute(null);
154         assertEquals(1, a.count);
155         assertEquals(0, b.count);
156 
157         a = new MockClosure<>();
158         b = new MockClosure<>();
159         ClosureUtils.ifClosure(FalsePredicate.<Object>falsePredicate(), a, b).execute(null);
160         assertEquals(0, a.count);
161         assertEquals(1, b.count);
162     }
163 
164     @Test
165     public void testInvokeClosure() {
166         StringBuilder buf = new StringBuilder("Hello"); // Only StringBuffer has setLength() method
167         ClosureUtils.invokerClosure("reverse").execute(buf);
168         assertEquals("olleH", buf.toString());
169         buf = new StringBuilder("Hello");
170         ClosureUtils.invokerClosure("setLength", new Class[] {Integer.TYPE}, new Object[] {Integer.valueOf(2)}).execute(buf);
171         assertEquals("He", buf.toString());
172     }
173 
174     @Test
175     public void testNopClosure() {
176         final StringBuilder buf = new StringBuilder("Hello");
177         ClosureUtils.nopClosure().execute(null);
178         assertEquals("Hello", buf.toString());
179         ClosureUtils.nopClosure().execute("Hello");
180         assertEquals("Hello", buf.toString());
181     }
182 
183     /**
184      * Test that all Closure singletons hold singleton pattern in
185      * serialization/deserialization process.
186      */
187     @Test
188     public void testSingletonPatternInSerialization() throws ClassNotFoundException, IOException {
189         final Object[] singletons = {
190             ExceptionClosure.INSTANCE,
191             NOPClosure.INSTANCE,
192         };
193 
194         for (final Object original : singletons) {
195             TestUtils.assertSameAfterSerialization(
196                     "Singleton pattern broken for " + original.getClass(),
197                     original
198             );
199         }
200     }
201 
202     @Test
203     @SuppressWarnings("unchecked")
204     public void testSwitchClosure() {
205         final MockClosure<String> a = new MockClosure<>();
206         final MockClosure<String> b = new MockClosure<>();
207         ClosureUtils.<String>switchClosure(
208             new Predicate[] { EqualPredicate.equalPredicate("HELLO"), EqualPredicate.equalPredicate("THERE") },
209             new Closure[] { a, b }).execute("WELL");
210         assertEquals(0, a.count);
211         assertEquals(0, b.count);
212 
213         a.reset();
214         b.reset();
215         ClosureUtils.<String>switchClosure(
216             new Predicate[] { EqualPredicate.equalPredicate("HELLO"), EqualPredicate.equalPredicate("THERE") },
217             new Closure[] { a, b }).execute("HELLO");
218         assertEquals(1, a.count);
219         assertEquals(0, b.count);
220 
221         a.reset();
222         b.reset();
223         final MockClosure<String> c = new MockClosure<>();
224         ClosureUtils.<String>switchClosure(
225             new Predicate[] { EqualPredicate.equalPredicate("HELLO"), EqualPredicate.equalPredicate("THERE") },
226             new Closure[] { a, b }, c).execute("WELL");
227         assertEquals(0, a.count);
228         assertEquals(0, b.count);
229         assertEquals(1, c.count);
230 
231         a.reset();
232         b.reset();
233         final Map<Predicate<String>, Closure<String>> map = new HashMap<>();
234         map.put(EqualPredicate.equalPredicate("HELLO"), a);
235         map.put(EqualPredicate.equalPredicate("THERE"), b);
236         ClosureUtils.<String>switchClosure(map).execute(null);
237         assertEquals(0, a.count);
238         assertEquals(0, b.count);
239 
240         a.reset();
241         b.reset();
242         map.clear();
243         map.put(EqualPredicate.equalPredicate("HELLO"), a);
244         map.put(EqualPredicate.equalPredicate("THERE"), b);
245         ClosureUtils.switchClosure(map).execute("THERE");
246         assertEquals(0, a.count);
247         assertEquals(1, b.count);
248 
249         a.reset();
250         b.reset();
251         c.reset();
252         map.clear();
253         map.put(EqualPredicate.equalPredicate("HELLO"), a);
254         map.put(EqualPredicate.equalPredicate("THERE"), b);
255         map.put(null, c);
256         ClosureUtils.switchClosure(map).execute("WELL");
257         assertEquals(0, a.count);
258         assertEquals(0, b.count);
259         assertEquals(1, c.count);
260 
261         assertEquals(NOPClosure.INSTANCE, ClosureUtils.<String>switchClosure(new Predicate[0], new Closure[0]));
262         assertEquals(NOPClosure.INSTANCE, ClosureUtils.<String>switchClosure(new HashMap<>()));
263         map.clear();
264         map.put(null, null);
265         assertEquals(NOPClosure.INSTANCE, ClosureUtils.switchClosure(map));
266 
267         assertThrows(NullPointerException.class, () -> ClosureUtils.switchClosure(null, null));
268         assertThrows(NullPointerException.class, () -> ClosureUtils.<String>switchClosure((Predicate<String>[]) null, (Closure<String>[]) null));
269         assertThrows(NullPointerException.class, () -> ClosureUtils.<String>switchClosure((Map<Predicate<String>, Closure<String>>) null));
270         assertThrows(NullPointerException.class, () -> ClosureUtils.<String>switchClosure(new Predicate[2], new Closure[2]));
271         assertThrows(IllegalArgumentException.class,
272                 () -> ClosureUtils.<String>switchClosure(new Predicate[] { TruePredicate.<String>truePredicate() }, new Closure[] { a, b }));
273     }
274 
275     @Test
276     public void testSwitchMapClosure() {
277         final MockClosure<String> a = new MockClosure<>();
278         final MockClosure<String> b = new MockClosure<>();
279         final Map<String, Closure<String>> map = new HashMap<>();
280         map.put("HELLO", a);
281         map.put("THERE", b);
282         ClosureUtils.switchMapClosure(map).execute(null);
283         assertEquals(0, a.count);
284         assertEquals(0, b.count);
285 
286         a.reset();
287         b.reset();
288         map.clear();
289         map.put("HELLO", a);
290         map.put("THERE", b);
291         ClosureUtils.switchMapClosure(map).execute("THERE");
292         assertEquals(0, a.count);
293         assertEquals(1, b.count);
294 
295         a.reset();
296         b.reset();
297         map.clear();
298         final MockClosure<String> c = new MockClosure<>();
299         map.put("HELLO", a);
300         map.put("THERE", b);
301         map.put(null, c);
302         ClosureUtils.switchMapClosure(map).execute("WELL");
303         assertEquals(0, a.count);
304         assertEquals(0, b.count);
305         assertEquals(1, c.count);
306 
307         assertEquals(NOPClosure.INSTANCE, ClosureUtils.switchMapClosure(new HashMap<>()));
308 
309         assertThrows(NullPointerException.class, () -> ClosureUtils.switchMapClosure(null));
310     }
311 
312     @Test
313     public void testTransformerClosure() {
314         final MockTransformer<Object> mock = new MockTransformer<>();
315         final Closure<Object> closure = ClosureUtils.asClosure(mock);
316         closure.execute(null);
317         assertEquals(1, mock.count);
318         closure.execute(null);
319         assertEquals(2, mock.count);
320 
321         assertEquals(ClosureUtils.nopClosure(), ClosureUtils.asClosure(null));
322     }
323 
324     @Test
325     public void testWhileClosure() {
326         MockClosure<Object> cmd = new MockClosure<>();
327         ClosureUtils.whileClosure(FalsePredicate.falsePredicate(), cmd).execute(null);
328         assertEquals(0, cmd.count);
329 
330         cmd = new MockClosure<>();
331         ClosureUtils.whileClosure(PredicateUtils.uniquePredicate(), cmd).execute(null);
332         assertEquals(1, cmd.count);
333 
334         assertThrows(NullPointerException.class, () -> ClosureUtils.whileClosure(null, ClosureUtils.nopClosure()));
335         assertThrows(NullPointerException.class, () -> ClosureUtils.whileClosure(FalsePredicate.falsePredicate(), null));
336         assertThrows(NullPointerException.class, () -> ClosureUtils.whileClosure(null, null));
337     }
338 
339 }