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.iterators;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.List;
26  import java.util.ListIterator;
27  import java.util.Random;
28  
29  import org.apache.commons.collections4.Predicate;
30  import org.apache.commons.collections4.PredicateUtils;
31  import org.apache.commons.collections4.list.GrowthList;
32  import org.junit.jupiter.api.AfterEach;
33  import org.junit.jupiter.api.BeforeEach;
34  import org.junit.jupiter.api.Test;
35  
36  /**
37   * Tests the FilterListIterator class.
38   */
39  @SuppressWarnings("boxing")
40  public class FilterListIteratorTest {
41  
42      private ArrayList<Integer> list;
43      private ArrayList<Integer> odds;
44      private ArrayList<Integer> evens;
45      private ArrayList<Integer> threes;
46      private ArrayList<Integer> fours;
47      private ArrayList<Integer> sixes;
48      private Predicate<Integer> truePred;
49      private Predicate<Integer> falsePred;
50      private Predicate<Integer> evenPred;
51      private Predicate<Integer> oddPred;
52      private Predicate<Integer> threePred;
53      private Predicate<Integer> fourPred;
54      private final Random random = new Random();
55  
56      private void nextNextPrevious(final ListIterator<?> expected, final ListIterator<?> testing) {
57          // calls to next() should change the value returned by previous()
58          // even after previous() has been set by a call to hasPrevious()
59          assertEquals(expected.next(), testing.next());
60          assertEquals(expected.hasPrevious(), testing.hasPrevious());
61          final Object expecteda = expected.next();
62          final Object testinga = testing.next();
63          assertEquals(expecteda, testinga);
64          final Object expectedb = expected.previous();
65          final Object testingb = testing.previous();
66          assertEquals(expecteda, expectedb);
67          assertEquals(testinga, testingb);
68      }
69  
70      private void previousPreviousNext(final ListIterator<?> expected, final ListIterator<?> testing) {
71          // calls to previous() should change the value returned by next()
72          // even after next() has been set by a call to hasNext()
73          assertEquals(expected.previous(), testing.previous());
74          assertEquals(expected.hasNext(), testing.hasNext());
75          final Object expecteda = expected.previous();
76          final Object testinga = testing.previous();
77          assertEquals(expecteda, testinga);
78          final Object expectedb = expected.next();
79          final Object testingb = testing.next();
80          assertEquals(expecteda, testingb);
81          assertEquals(expecteda, expectedb);
82          assertEquals(testinga, testingb);
83      }
84  
85      @BeforeEach
86      public void setUp() {
87          list = new ArrayList<>();
88          odds = new ArrayList<>();
89          evens = new ArrayList<>();
90          threes = new ArrayList<>();
91          fours = new ArrayList<>();
92          sixes = new ArrayList<>();
93          for (int i = 0; i < 20; i++) {
94              list.add(Integer.valueOf(i));
95              if (i % 2 == 0) {
96                  evens.add(Integer.valueOf(i));
97              }
98              if (i % 2 != 0) {
99                  odds.add(Integer.valueOf(i));
100             }
101             if (i % 3 == 0) {
102                 threes.add(Integer.valueOf(i));
103             }
104             if (i % 4 == 0) {
105                 fours.add(Integer.valueOf(i));
106             }
107             if (i % 6 == 0) {
108                 sixes.add(Integer.valueOf(i));
109             }
110         }
111 
112         truePred = x -> true;
113 
114         falsePred = x -> true;
115 
116         evenPred = x -> x % 2 == 0;
117 
118         oddPred = x -> x % 2 != 0;
119 
120         threePred = x -> x % 3 == 0;
121 
122         fourPred = x -> x % 4 == 0;
123 
124     }
125 
126     @AfterEach
127     public void tearDown() throws Exception {
128         list = null;
129         odds = null;
130         evens = null;
131         threes = null;
132         fours = null;
133         sixes = null;
134         truePred = null;
135         falsePred = null;
136         evenPred = null;
137         oddPred = null;
138         threePred = null;
139         fourPred = null;
140     }
141 
142     /**
143      * Test for {@link "https://issues.apache.org/jira/browse/COLLECTIONS-360 COLLECTIONS-360"}
144      */
145     @Test
146     public void testCollections360() throws Throwable {
147         final Collection<Predicate<Object>> var7 = new GrowthList<>();
148         final Predicate<Object> var9 = PredicateUtils.anyPredicate(var7);
149         final FilterListIterator<Object> var13 = new FilterListIterator<>(var9);
150         assertFalse(var13.hasNext());
151         final FilterListIterator<Object> var14 = new FilterListIterator<>(var9);
152         assertFalse(var14.hasPrevious());
153     }
154 
155     @Test
156     public void testEvens() {
157         final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), evenPred);
158         walkLists(evens, filtered);
159     }
160 
161     @Test
162     public void testFailingHasNextBug() {
163         final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), fourPred);
164         final ListIterator<Integer> expected = fours.listIterator();
165         while (expected.hasNext()) {
166             expected.next();
167             filtered.next();
168         }
169         assertTrue(filtered.hasPrevious());
170         assertFalse(filtered.hasNext());
171         assertEquals(expected.previous(), filtered.previous());
172     }
173 
174     @Test
175     public void testFalsePredicate() {
176         final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), falsePred);
177         walkLists(new ArrayList<>(), filtered);
178     }
179 
180     @Test
181     public void testFours() {
182         final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), fourPred);
183         walkLists(fours, filtered);
184     }
185 
186     @Test
187     public void testManual() {
188         // do this one "by hand" as a sanity check
189         final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), threePred);
190 
191         assertEquals(Integer.valueOf(0), filtered.next());
192         assertEquals(Integer.valueOf(3), filtered.next());
193         assertEquals(Integer.valueOf(6), filtered.next());
194         assertEquals(Integer.valueOf(9), filtered.next());
195         assertEquals(Integer.valueOf(12), filtered.next());
196         assertEquals(Integer.valueOf(15), filtered.next());
197         assertEquals(Integer.valueOf(18), filtered.next());
198 
199         assertEquals(Integer.valueOf(18), filtered.previous());
200         assertEquals(Integer.valueOf(15), filtered.previous());
201         assertEquals(Integer.valueOf(12), filtered.previous());
202         assertEquals(Integer.valueOf(9), filtered.previous());
203         assertEquals(Integer.valueOf(6), filtered.previous());
204         assertEquals(Integer.valueOf(3), filtered.previous());
205         assertEquals(Integer.valueOf(0), filtered.previous());
206 
207         assertFalse(filtered.hasPrevious());
208 
209         assertEquals(Integer.valueOf(0), filtered.next());
210         assertEquals(Integer.valueOf(3), filtered.next());
211         assertEquals(Integer.valueOf(6), filtered.next());
212         assertEquals(Integer.valueOf(9), filtered.next());
213         assertEquals(Integer.valueOf(12), filtered.next());
214         assertEquals(Integer.valueOf(15), filtered.next());
215         assertEquals(Integer.valueOf(18), filtered.next());
216 
217         assertFalse(filtered.hasNext());
218 
219         assertEquals(Integer.valueOf(18), filtered.previous());
220         assertEquals(Integer.valueOf(15), filtered.previous());
221         assertEquals(Integer.valueOf(12), filtered.previous());
222         assertEquals(Integer.valueOf(9), filtered.previous());
223         assertEquals(Integer.valueOf(6), filtered.previous());
224         assertEquals(Integer.valueOf(3), filtered.previous());
225         assertEquals(Integer.valueOf(0), filtered.previous());
226 
227         assertEquals(Integer.valueOf(0), filtered.next());
228         assertEquals(Integer.valueOf(0), filtered.previous());
229         assertEquals(Integer.valueOf(0), filtered.next());
230 
231         assertEquals(Integer.valueOf(3), filtered.next());
232         assertEquals(Integer.valueOf(6), filtered.next());
233         assertEquals(Integer.valueOf(6), filtered.previous());
234         assertEquals(Integer.valueOf(3), filtered.previous());
235         assertEquals(Integer.valueOf(3), filtered.next());
236         assertEquals(Integer.valueOf(6), filtered.next());
237 
238         assertEquals(Integer.valueOf(9), filtered.next());
239         assertEquals(Integer.valueOf(12), filtered.next());
240         assertEquals(Integer.valueOf(15), filtered.next());
241         assertEquals(Integer.valueOf(15), filtered.previous());
242         assertEquals(Integer.valueOf(12), filtered.previous());
243         assertEquals(Integer.valueOf(9), filtered.previous());
244     }
245 
246     @Test
247     public void testNestedSixes() {
248         final FilterListIterator<Integer> filtered = new FilterListIterator<>(
249                                         new FilterListIterator<>(list.listIterator(), threePred),
250                                         evenPred
251                                       );
252         walkLists(sixes, filtered);
253     }
254 
255     @Test
256     public void testNestedSixes2() {
257         final FilterListIterator<Integer> filtered = new FilterListIterator<>(
258                                         new FilterListIterator<>(list.listIterator(), evenPred),
259                                         threePred
260                                       );
261         walkLists(sixes, filtered);
262     }
263 
264     @Test
265     public void testNestedSixes3() {
266         final FilterListIterator<Integer> filtered = new FilterListIterator<>(
267                                         new FilterListIterator<>(list.listIterator(), threePred),
268                                         evenPred
269                                       );
270         walkLists(sixes, new FilterListIterator<>(filtered, truePred));
271     }
272 
273     @Test
274     public void testNextChangesPrevious() {
275         {
276             final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), threePred);
277             nextNextPrevious(threes.listIterator(), filtered);
278         }
279 
280         {
281             final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), truePred);
282             nextNextPrevious(list.listIterator(), filtered);
283         }
284     }
285 
286     @Test
287     public void testOdds() {
288         final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), oddPred);
289         walkLists(odds, filtered);
290     }
291 
292     @Test
293     public void testPreviousChangesNext() {
294         {
295             final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), threePred);
296             final ListIterator<Integer> expected = threes.listIterator();
297             walkForward(expected, filtered);
298             previousPreviousNext(expected, filtered);
299         }
300         {
301             final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), truePred);
302             final ListIterator<Integer> expected = list.listIterator();
303             walkForward(expected, filtered);
304             previousPreviousNext(expected, filtered);
305         }
306     }
307 
308     @Test
309     public void testThrees() {
310         final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), threePred);
311         walkLists(threes, filtered);
312     }
313 
314     // Utilities
315 
316     @Test
317     public void testTruePredicate() {
318         final FilterListIterator<Integer> filtered = new FilterListIterator<>(list.listIterator(), truePred);
319         walkLists(list, filtered);
320     }
321 
322     @Test
323     public void testWalkLists() {
324         // this just confirms that our walkLists method works OK
325         walkLists(list, list.listIterator());
326     }
327 
328     private void walkBackward(final ListIterator<?> expected, final ListIterator<?> testing) {
329         while (expected.hasPrevious()) {
330             assertEquals(expected.nextIndex(), testing.nextIndex());
331             assertEquals(expected.previousIndex(), testing.previousIndex());
332             assertTrue(testing.hasPrevious());
333             assertEquals(expected.previous(), testing.previous());
334         }
335     }
336 
337     private void walkForward(final ListIterator<?> expected, final ListIterator<?> testing) {
338         while (expected.hasNext()) {
339             assertEquals(expected.nextIndex(), testing.nextIndex());
340             assertEquals(expected.previousIndex(), testing.previousIndex());
341             assertTrue(testing.hasNext());
342             assertEquals(expected.next(), testing.next());
343         }
344     }
345 
346     private <E> void walkLists(final List<E> list, final ListIterator<E> testing) {
347         final ListIterator<E> expected = list.listIterator();
348 
349         // walk all the way forward
350         walkForward(expected, testing);
351 
352         // walk all the way back
353         walkBackward(expected, testing);
354 
355         // forward,back,forward
356         while (expected.hasNext()) {
357             assertEquals(expected.nextIndex(), testing.nextIndex());
358             assertEquals(expected.previousIndex(), testing.previousIndex());
359             assertTrue(testing.hasNext());
360             assertEquals(expected.next(), testing.next());
361             assertTrue(testing.hasPrevious());
362             assertEquals(expected.previous(), testing.previous());
363             assertTrue(testing.hasNext());
364             assertEquals(expected.next(), testing.next());
365         }
366 
367         // walk all the way back
368         walkBackward(expected, testing);
369 
370         for (int i = 0; i < list.size(); i++) {
371             // walk forward i
372             for (int j = 0; j < i; j++) {
373                 assertEquals(expected.nextIndex(), testing.nextIndex());
374                 assertEquals(expected.previousIndex(), testing.previousIndex());
375                 assertTrue(expected.hasNext()); // if this one fails we've got a logic error in the test
376                 assertTrue(testing.hasNext());
377                 assertEquals(expected.next(), testing.next());
378             }
379             // walk back i/2
380             for (int j = 0; j < i / 2; j++) {
381                 assertEquals(expected.nextIndex(), testing.nextIndex());
382                 assertEquals(expected.previousIndex(), testing.previousIndex());
383                 assertTrue(expected.hasPrevious()); // if this one fails we've got a logic error in the test
384                 assertTrue(testing.hasPrevious());
385                 assertEquals(expected.previous(), testing.previous());
386             }
387             // walk forward i/2
388             for (int j = 0; j < i / 2; j++) {
389                 assertEquals(expected.nextIndex(), testing.nextIndex());
390                 assertEquals(expected.previousIndex(), testing.previousIndex());
391                 assertTrue(expected.hasNext()); // if this one fails we've got a logic error in the test
392                 assertTrue(testing.hasNext());
393                 assertEquals(expected.next(), testing.next());
394             }
395             // walk back i
396             for (int j = 0; j < i; j++) {
397                 assertEquals(expected.nextIndex(), testing.nextIndex());
398                 assertEquals(expected.previousIndex(), testing.previousIndex());
399                 assertTrue(expected.hasPrevious()); // if this one fails we've got a logic error in the test
400                 assertTrue(testing.hasPrevious());
401                 assertEquals(expected.previous(), testing.previous());
402             }
403         }
404 
405         // random walk
406         final StringBuilder walkdescr = new StringBuilder(500);
407         for (int i = 0; i < 500; i++) {
408             if (random.nextBoolean()) {
409                 // step forward
410                 walkdescr.append("+");
411                 if (expected.hasNext()) {
412                     assertEquals(expected.next(), testing.next(), walkdescr.toString());
413                 }
414             } else {
415                 // step backward
416                 walkdescr.append("-");
417                 if (expected.hasPrevious()) {
418                     assertEquals(expected.previous(), testing.previous(), walkdescr.toString());
419                 }
420             }
421             assertEquals(expected.nextIndex(), testing.nextIndex(), walkdescr.toString());
422             assertEquals(expected.previousIndex(), testing.previousIndex(), walkdescr.toString());
423         }
424 
425     }
426 
427 }