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.assertThrows;
22  
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.ListIterator;
26  import java.util.NoSuchElementException;
27  
28  import org.apache.commons.collections4.ResettableListIterator;
29  import org.junit.jupiter.api.BeforeEach;
30  import org.junit.jupiter.api.Test;
31  
32  /**
33   * Tests the ListIteratorWrapper to ensure that it behaves as expected when wrapping a ListIterator.
34   */
35  public class ListIteratorWrapper2Test<E> extends AbstractIteratorTest<E> {
36  
37      protected String[] testArray = {
38          "One", "Two", "Three", "Four", "Five", "Six"
39      };
40  
41      protected List<E> list1;
42  
43      public ListIteratorWrapper2Test() {
44          super(ListIteratorWrapper2Test.class.getSimpleName());
45      }
46  
47      @Override
48      public ResettableListIterator<E> makeEmptyIterator() {
49          final ArrayList<E> list = new ArrayList<>();
50          return new ListIteratorWrapper<>(list.listIterator());
51      }
52  
53      @Override
54      public ResettableListIterator<E> makeObject() {
55          return new ListIteratorWrapper<>(list1.listIterator());
56      }
57  
58      @BeforeEach
59      @SuppressWarnings("unchecked")
60      public void setUp() {
61          list1 = new ArrayList<>();
62          list1.add((E) "One");
63          list1.add((E) "Two");
64          list1.add((E) "Three");
65          list1.add((E) "Four");
66          list1.add((E) "Five");
67          list1.add((E) "Six");
68      }
69  
70      @Test
71      public void testIterator() {
72          final ListIterator<E> iter = makeObject();
73          for (final String testValue : testArray) {
74              final Object iterValue = iter.next();
75  
76              assertEquals(testValue, iterValue, "Iteration value is correct");
77          }
78  
79          assertFalse(iter.hasNext(), "Iterator should now be empty");
80  
81          try {
82              iter.next();
83          } catch (final Exception e) {
84              assertEquals(e.getClass(), new NoSuchElementException().getClass(), "NoSuchElementException must be thrown");
85          }
86  
87          // now, read it backwards
88          for (int i = testArray.length - 1; i > -1; --i) {
89              final Object testValue = testArray[i];
90              final E iterValue = iter.previous();
91  
92              assertEquals(testValue, iterValue, "Iteration value is correct");
93          }
94  
95          try {
96              iter.previous();
97          } catch (final Exception e) {
98              assertEquals(e.getClass(), new NoSuchElementException().getClass(), "NoSuchElementException must be thrown");
99          }
100 
101         // now, read it forwards again
102         for (final String testValue : testArray) {
103             final Object iterValue = iter.next();
104 
105             assertEquals(testValue, iterValue, "Iteration value is correct");
106         }
107 
108     }
109 
110     @Test
111     @Override
112     public void testRemove() {
113         final ListIterator<E> iter = makeObject();
114 
115         //initial state:
116         assertEquals(-1, iter.previousIndex());
117         assertEquals(0, iter.nextIndex());
118 
119         assertThrows(IllegalStateException.class, () -> iter.remove(), "ListIteratorWrapper#remove() should fail; must be initially positioned first");
120 
121         //no change from invalid op:
122         assertEquals(-1, iter.previousIndex());
123         assertEquals(0, iter.nextIndex());
124 
125         //establish size:
126         int sz = list1.size();
127 
128         //verify initial next() call:
129         assertEquals(list1.get(0), iter.next());
130         assertEquals(0, iter.previousIndex());
131         assertEquals(1, iter.nextIndex());
132 
133         //verify remove():
134         iter.remove();
135         assertEquals(--sz, list1.size());
136         //like we never started iterating:
137         assertEquals(-1, iter.previousIndex());
138         assertEquals(0, iter.nextIndex());
139 
140         assertThrows(IllegalStateException.class, () -> iter.remove(), "ListIteratorWrapper#remove() should fail; must be repositioned first");
141 
142         //no change from invalid op:
143         assertEquals(-1, iter.previousIndex());
144         assertEquals(0, iter.nextIndex());
145 
146         //two consecutive next() calls:
147         assertEquals(list1.get(0), iter.next());
148         assertEquals(0, iter.previousIndex());
149         assertEquals(1, iter.nextIndex());
150 
151         assertEquals(list1.get(1), iter.next());
152         assertEquals(1, iter.previousIndex());
153         assertEquals(2, iter.nextIndex());
154 
155         //call previous():
156         assertEquals(list1.get(1), iter.previous());
157         assertEquals(0, iter.previousIndex());
158         assertEquals(1, iter.nextIndex());
159 
160         //should support remove() after calling previous() once from tip because we haven't changed the underlying iterator's position:
161         iter.remove();
162         assertEquals(--sz, list1.size());
163         assertEquals(0, iter.previousIndex());
164         assertEquals(1, iter.nextIndex());
165 
166         //this would dig into cache on a plain Iterator, but forwards directly to wrapped ListIterator:
167         assertEquals(list1.get(0), iter.previous());
168         assertEquals(-1, iter.previousIndex());
169         assertEquals(0, iter.nextIndex());
170 
171         //here's the proof; remove() still works:
172         iter.remove();
173         assertEquals(--sz, list1.size());
174         assertEquals(-1, iter.previousIndex());
175         assertEquals(0, iter.nextIndex());
176 
177         //further testing would be fairly meaningless:
178     }
179 
180     @Test
181     public void testReset() {
182         final ResettableListIterator<E> iter = makeObject();
183         final E first = iter.next();
184         final E second = iter.next();
185 
186         iter.reset();
187 
188         // after reset, there shouldn't be any previous elements
189         assertFalse(iter.hasPrevious(), "No previous elements after reset()");
190 
191         // after reset, the results should be the same as before
192         assertEquals(first, iter.next(), "First element should be the same");
193         assertEquals(second, iter.next(), "Second element should be the same");
194 
195         // after passing the point, where we reset, continuation should work as expected
196         for (int i = 2; i < testArray.length; i++) {
197             final Object testValue = testArray[i];
198             final E iterValue = iter.next();
199 
200             assertEquals(testValue, iterValue, "Iteration value is correct");
201         }
202     }
203 
204 }