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.assertAll;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertSame;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  
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).execute(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          assertAll(
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                 () -> {
101                     final Collection<Closure<Object>> finalColl = new ArrayList<>();
102                     finalColl.add(null);
103                     finalColl.add(null);
104                     assertThrows(NullPointerException.class, () -> ClosureUtils.chainedClosure(finalColl));
105                 }
106         );
107     }
108 
109     @Test
110     public void testDoWhileClosure() {
111         MockClosure<Object> cmd = new MockClosure<>();
112         ClosureUtils.doWhileClosure(cmd, FalsePredicate.falsePredicate()).execute(null);
113         assertEquals(1, cmd.count);
114 
115         cmd = new MockClosure<>();
116         ClosureUtils.doWhileClosure(cmd, PredicateUtils.uniquePredicate()).execute(null);
117         assertEquals(2, cmd.count);
118 
119         assertThrows(NullPointerException.class, () -> ClosureUtils.doWhileClosure(null, null));
120     }
121 
122     @Test
123     public void testExceptionClosure() {
124         assertNotNull(ClosureUtils.exceptionClosure());
125         assertSame(ClosureUtils.exceptionClosure(), ClosureUtils.exceptionClosure());
126         assertAll(
127                 () -> assertThrows(FunctorException.class, () -> ClosureUtils.exceptionClosure().execute(null)),
128                 () -> assertThrows(FunctorException.class, () -> ClosureUtils.exceptionClosure().execute(cString))
129         );
130     }
131 
132     @Test
133     public void testForClosure() {
134         final MockClosure<Object> cmd = new MockClosure<>();
135         ClosureUtils.forClosure(5, cmd).execute(null);
136         assertEquals(5, cmd.count);
137         assertSame(NOPClosure.INSTANCE, ClosureUtils.forClosure(0, new MockClosure<>()));
138         assertSame(NOPClosure.INSTANCE, ClosureUtils.forClosure(-1, new MockClosure<>()));
139         assertSame(NOPClosure.INSTANCE, ClosureUtils.forClosure(1, null));
140         assertSame(NOPClosure.INSTANCE, ClosureUtils.forClosure(3, null));
141         assertSame(cmd, ClosureUtils.forClosure(1, cmd));
142     }
143 
144     @Test
145     public void testIfClosure() {
146         MockClosure<Object> a = new MockClosure<>();
147         MockClosure<Object> b;
148         ClosureUtils.ifClosure(TruePredicate.truePredicate(), a).execute(null);
149         assertEquals(1, a.count);
150 
151         a = new MockClosure<>();
152         ClosureUtils.ifClosure(FalsePredicate.<Object>falsePredicate(), a).execute(null);
153         assertEquals(0, a.count);
154 
155         a = new MockClosure<>();
156         b = new MockClosure<>();
157         ClosureUtils.ifClosure(TruePredicate.<Object>truePredicate(), a, b).execute(null);
158         assertEquals(1, a.count);
159         assertEquals(0, b.count);
160 
161         a = new MockClosure<>();
162         b = new MockClosure<>();
163         ClosureUtils.ifClosure(FalsePredicate.<Object>falsePredicate(), a, b).execute(null);
164         assertEquals(0, a.count);
165         assertEquals(1, b.count);
166     }
167 
168     @Test
169     public void testInvokeClosure() {
170         StringBuilder buf = new StringBuilder("Hello"); // Only StringBuffer has setLength() method
171         ClosureUtils.invokerClosure("reverse").execute(buf);
172         assertEquals("olleH", buf.toString());
173         buf = new StringBuilder("Hello");
174         ClosureUtils.invokerClosure("setLength", new Class[] {Integer.TYPE}, new Object[] {Integer.valueOf(2)}).execute(buf);
175         assertEquals("He", buf.toString());
176     }
177 
178     @Test
179     public void testNopClosure() {
180         final StringBuilder buf = new StringBuilder("Hello");
181         ClosureUtils.nopClosure().execute(null);
182         assertEquals("Hello", buf.toString());
183         ClosureUtils.nopClosure().execute("Hello");
184         assertEquals("Hello", buf.toString());
185     }
186 
187     /**
188      * Test that all Closure singletons hold singleton pattern in
189      * serialization/deserialization process.
190      */
191     @Test
192     public void testSingletonPatternInSerialization() {
193         final Object[] singletons = {
194             ExceptionClosure.INSTANCE,
195             NOPClosure.INSTANCE,
196         };
197 
198         for (final Object original : singletons) {
199             TestUtils.assertSameAfterSerialization(
200                     "Singleton pattern broken for " + original.getClass(),
201                     original
202             );
203         }
204     }
205 
206     @Test
207     @SuppressWarnings("unchecked")
208     public void testSwitchClosure() {
209         final MockClosure<String> a = new MockClosure<>();
210         final MockClosure<String> b = new MockClosure<>();
211         ClosureUtils.<String>switchClosure(
212             new Predicate[] { EqualPredicate.equalPredicate("HELLO"), EqualPredicate.equalPredicate("THERE") },
213             new Closure[] { a, b }).execute("WELL");
214         assertEquals(0, a.count);
215         assertEquals(0, b.count);
216 
217         a.reset();
218         b.reset();
219         ClosureUtils.<String>switchClosure(
220             new Predicate[] { EqualPredicate.equalPredicate("HELLO"), EqualPredicate.equalPredicate("THERE") },
221             new Closure[] { a, b }).execute("HELLO");
222         assertEquals(1, a.count);
223         assertEquals(0, b.count);
224 
225         a.reset();
226         b.reset();
227         final MockClosure<String> c = new MockClosure<>();
228         ClosureUtils.<String>switchClosure(
229             new Predicate[] { EqualPredicate.equalPredicate("HELLO"), EqualPredicate.equalPredicate("THERE") },
230             new Closure[] { a, b }, c).execute("WELL");
231         assertEquals(0, a.count);
232         assertEquals(0, b.count);
233         assertEquals(1, c.count);
234 
235         a.reset();
236         b.reset();
237         final Map<Predicate<String>, Closure<String>> map = new HashMap<>();
238         map.put(EqualPredicate.equalPredicate("HELLO"), a);
239         map.put(EqualPredicate.equalPredicate("THERE"), b);
240         ClosureUtils.<String>switchClosure(map).execute(null);
241         assertEquals(0, a.count);
242         assertEquals(0, b.count);
243 
244         a.reset();
245         b.reset();
246         map.clear();
247         map.put(EqualPredicate.equalPredicate("HELLO"), a);
248         map.put(EqualPredicate.equalPredicate("THERE"), b);
249         ClosureUtils.switchClosure(map).execute("THERE");
250         assertEquals(0, a.count);
251         assertEquals(1, b.count);
252 
253         a.reset();
254         b.reset();
255         c.reset();
256         map.clear();
257         map.put(EqualPredicate.equalPredicate("HELLO"), a);
258         map.put(EqualPredicate.equalPredicate("THERE"), b);
259         map.put(null, c);
260         ClosureUtils.switchClosure(map).execute("WELL");
261         assertEquals(0, a.count);
262         assertEquals(0, b.count);
263         assertEquals(1, c.count);
264 
265         assertEquals(NOPClosure.INSTANCE, ClosureUtils.<String>switchClosure(new Predicate[0], new Closure[0]));
266         assertEquals(NOPClosure.INSTANCE, ClosureUtils.<String>switchClosure(new HashMap<>()));
267         map.clear();
268         map.put(null, null);
269         assertEquals(NOPClosure.INSTANCE, ClosureUtils.switchClosure(map));
270         assertAll(
271                 () -> assertThrows(NullPointerException.class, () -> ClosureUtils.switchClosure(null, null)),
272                 () -> assertThrows(NullPointerException.class, () -> ClosureUtils.<String>switchClosure((Predicate<String>[]) null, (Closure<String>[]) null)),
273                 () -> assertThrows(NullPointerException.class, () -> ClosureUtils.<String>switchClosure((Map<Predicate<String>, Closure<String>>) null)),
274                 () -> assertThrows(NullPointerException.class, () -> ClosureUtils.<String>switchClosure(new Predicate[2], new Closure[2])),
275                 () -> assertThrows(IllegalArgumentException.class, () -> ClosureUtils.<String>switchClosure(
276                         new Predicate[]{TruePredicate.<String>truePredicate()},
277                         new Closure[]{a, b}))
278         );
279     }
280 
281     @Test
282     public void testSwitchMapClosure() {
283         final MockClosure<String> a = new MockClosure<>();
284         final MockClosure<String> b = new MockClosure<>();
285         final Map<String, Closure<String>> map = new HashMap<>();
286         map.put("HELLO", a);
287         map.put("THERE", b);
288         ClosureUtils.switchMapClosure(map).execute(null);
289         assertEquals(0, a.count);
290         assertEquals(0, b.count);
291 
292         a.reset();
293         b.reset();
294         map.clear();
295         map.put("HELLO", a);
296         map.put("THERE", b);
297         ClosureUtils.switchMapClosure(map).execute("THERE");
298         assertEquals(0, a.count);
299         assertEquals(1, b.count);
300 
301         a.reset();
302         b.reset();
303         map.clear();
304         final MockClosure<String> c = new MockClosure<>();
305         map.put("HELLO", a);
306         map.put("THERE", b);
307         map.put(null, c);
308         ClosureUtils.switchMapClosure(map).execute("WELL");
309         assertEquals(0, a.count);
310         assertEquals(0, b.count);
311         assertEquals(1, c.count);
312 
313         assertEquals(NOPClosure.INSTANCE, ClosureUtils.switchMapClosure(new HashMap<>()));
314 
315         assertThrows(NullPointerException.class, () -> ClosureUtils.switchMapClosure(null));
316     }
317 
318     @Test
319     public void testTransformerClosure() {
320         final MockTransformer<Object> mock = new MockTransformer<>();
321         final Closure<Object> closure = ClosureUtils.asClosure(mock);
322         closure.execute(null);
323         assertEquals(1, mock.count);
324         closure.execute(null);
325         assertEquals(2, mock.count);
326 
327         assertEquals(ClosureUtils.nopClosure(), ClosureUtils.asClosure(null));
328     }
329 
330     @Test
331     public void testWhileClosure() {
332         MockClosure<Object> cmd = new MockClosure<>();
333         ClosureUtils.whileClosure(FalsePredicate.falsePredicate(), cmd).execute(null);
334         assertEquals(0, cmd.count);
335 
336         cmd = new MockClosure<>();
337         ClosureUtils.whileClosure(PredicateUtils.uniquePredicate(), cmd).execute(null);
338         assertEquals(1, cmd.count);
339         assertAll(
340                 () -> assertThrows(NullPointerException.class, () -> ClosureUtils.whileClosure(null, ClosureUtils.nopClosure())),
341                 () -> assertThrows(NullPointerException.class, () -> ClosureUtils.whileClosure(FalsePredicate.falsePredicate(), null)),
342                 () -> assertThrows(NullPointerException.class, () -> ClosureUtils.whileClosure(null, null))
343         );
344     }
345 
346 }