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