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  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.List;
27  import java.util.NoSuchElementException;
28  
29  import org.junit.jupiter.api.Test;
30  
31  /**
32   * Tests the LoopingListIterator class.
33   */
34  public class LoopingListIteratorTest {
35  
36      /**
37       * Tests the add method.
38       */
39      @Test
40      public void testAdd() {
41          List<String> list = new ArrayList<>(Arrays.asList("b", "e", "f"));
42          LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <b> e f
43  
44          loop.add("a");                      // <a> b e f
45          assertEquals("b", loop.next());     // a <b> e f
46          loop.reset();                       // <a> b e f
47          assertEquals("a", loop.next());     // a <b> e f
48          assertEquals("b", loop.next());     // a b <e> f
49  
50          loop.add("c");                      // a b c <e> f
51          assertEquals("e", loop.next());     // a b c e <f>
52          assertEquals("e", loop.previous()); // a b c <e> f
53          assertEquals("c", loop.previous()); // a b <c> e f
54          assertEquals("c", loop.next());     // a b c <e> f
55  
56          loop.add("d");                      // a b c d <e> f
57          loop.reset();                       // <a> b c d e f
58          assertEquals("a", loop.next());     // a <b> c d e f
59          assertEquals("b", loop.next());     // a b <c> d e f
60          assertEquals("c", loop.next());     // a b c <d> e f
61          assertEquals("d", loop.next());     // a b c d <e> f
62          assertEquals("e", loop.next());     // a b c d e <f>
63          assertEquals("f", loop.next());     // <a> b c d e f
64          assertEquals("a", loop.next());     // a <b> c d e f
65  
66          list = new ArrayList<>(Arrays.asList("b", "e", "f"));
67          loop = new LoopingListIterator<>(list); // <b> e f
68  
69          loop.add("a");                      // a <b> e f
70          assertEquals("a", loop.previous()); // a b e <f>
71          loop.reset();                       // <a> b e f
72          assertEquals("f", loop.previous()); // a b e <f>
73          assertEquals("e", loop.previous()); // a b <e> f
74  
75          loop.add("d");                      // a b d <e> f
76          assertEquals("d", loop.previous()); // a b <d> e f
77  
78          loop.add("c");                      // a b c <d> e f
79          assertEquals("c", loop.previous()); // a b <c> d e f
80  
81          loop.reset();
82          assertEquals("a", loop.next());     // a <b> c d e f
83          assertEquals("b", loop.next());     // a b <c> d e f
84          assertEquals("c", loop.next());     // a b c <d> e f
85          assertEquals("d", loop.next());     // a b c d <e> f
86          assertEquals("e", loop.next());     // a b c d e <f>
87          assertEquals("f", loop.next());     // <a> b c d e f
88          assertEquals("a", loop.next());     // a <b> c d e f
89      }
90  
91      /**
92       * Tests constructor exception.
93       */
94      @Test
95      public void testConstructorEx() {
96          assertThrows(NullPointerException.class, () -> new LoopingListIterator<>(null));
97      }
98  
99      /**
100      * Tests jogging back and forth between two elements, but not over
101      * the begin/end boundary of the list.
102      */
103     @Test
104     public void testJoggingNotOverBoundary() {
105         final List<String> list = Arrays.asList("a", "b");
106         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <a> b
107 
108         // Try jogging back and forth between the elements, but not
109         // over the begin/end boundary.
110         loop.reset();
111         assertEquals("a", loop.next());     // a <b>
112         assertEquals("a", loop.previous()); // <a> b
113         assertEquals("a", loop.next());     // a <b>
114 
115         assertEquals("b", loop.next());     // <a> b
116         assertEquals("b", loop.previous()); // a <b>
117         assertEquals("b", loop.next());     // <a> b
118     }
119 
120     /**
121      * Tests jogging back and forth between two elements over the
122      * begin/end boundary of the list.
123      */
124     @Test
125     public void testJoggingOverBoundary() {
126         final List<String> list = Arrays.asList("a", "b");
127         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <a> b
128 
129         // Try jogging back and forth between the elements, but not
130         // over the begin/end boundary.
131         assertEquals("b", loop.previous()); // a <b>
132         assertEquals("b", loop.next());     // <a> b
133         assertEquals("b", loop.previous()); // a <b>
134 
135         assertEquals("a", loop.previous()); // <a> b
136         assertEquals("a", loop.next());     // a <b>
137         assertEquals("a", loop.previous()); // <a> b
138     }
139 
140     /**
141      * Tests whether an empty looping list iterator works.
142      */
143     @Test
144     public void testLooping0() {
145         final List<Object> list = new ArrayList<>();
146         final LoopingListIterator<Object> loop = new LoopingListIterator<>(list);
147         assertFalse(loop.hasNext());
148         assertFalse(loop.hasPrevious());
149         assertThrows(NoSuchElementException.class, () -> loop.next());
150         assertThrows(NoSuchElementException.class, () -> loop.previous());
151     }
152 
153     /**
154      * Tests whether a looping list iterator works on a list with only
155      * one element.
156      */
157     @Test
158     public void testLooping1() {
159         final List<String> list = Arrays.asList("a");
160         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <a>
161 
162         assertTrue(loop.hasNext());
163         assertEquals("a", loop.next());     // <a>
164 
165         assertTrue(loop.hasNext());
166         assertEquals("a", loop.next());     // <a>
167 
168         assertTrue(loop.hasNext());
169         assertEquals("a", loop.next());     // <a>
170 
171         assertTrue(loop.hasPrevious());
172         assertEquals("a", loop.previous()); // <a>
173 
174         assertTrue(loop.hasPrevious());
175         assertEquals("a", loop.previous()); // <a>
176 
177         assertTrue(loop.hasPrevious());
178         assertEquals("a", loop.previous()); // <a>
179     }
180 
181     /**
182      * Tests whether a looping list iterator works on a list with two
183      * elements.
184      */
185     @Test
186     public void testLooping2() {
187         final List<String> list = Arrays.asList("a", "b");
188         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <a> b
189 
190         assertTrue(loop.hasNext());
191         assertEquals("a", loop.next());     // a <b>
192 
193         assertTrue(loop.hasNext());
194         assertEquals("b", loop.next());     // <a> b
195 
196         assertTrue(loop.hasNext());
197         assertEquals("a", loop.next());     // a <b>
198 
199         // Reset the iterator and try using previous.
200         loop.reset();                       // <a> b
201 
202         assertTrue(loop.hasPrevious());
203         assertEquals("b", loop.previous()); // a <b>
204 
205         assertTrue(loop.hasPrevious());
206         assertEquals("a", loop.previous()); // <a> b
207 
208         assertTrue(loop.hasPrevious());
209         assertEquals("b", loop.previous()); // a <b>
210     }
211 
212     /**
213      * Tests nextIndex and previousIndex.
214      */
215     @Test
216     public void testNextAndPreviousIndex() {
217         final List<String> list = Arrays.asList("a", "b", "c");
218         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <a> b c
219 
220         assertEquals(0, loop.nextIndex());
221         assertEquals(2, loop.previousIndex());
222 
223         assertEquals("a", loop.next());        // a <b> c
224         assertEquals(1, loop.nextIndex());
225         assertEquals(0, loop.previousIndex());
226 
227         assertEquals("a", loop.previous());    // <a> b c
228         assertEquals(0, loop.nextIndex());
229         assertEquals(2, loop.previousIndex());
230 
231         assertEquals("c", loop.previous());    // a b <c>
232         assertEquals(2, loop.nextIndex());
233         assertEquals(1, loop.previousIndex());
234 
235         assertEquals("b", loop.previous());    // a <b> c
236         assertEquals(1, loop.nextIndex());
237         assertEquals(0, loop.previousIndex());
238 
239         assertEquals("a", loop.previous());    // <a> b c
240         assertEquals(0, loop.nextIndex());
241         assertEquals(2, loop.previousIndex());
242     }
243 
244     /**
245      * Tests removing an element from a wrapped ArrayList.
246      */
247     @Test
248     public void testRemovingElementsAndIteratingBackwards() {
249         final List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
250         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <a> b c
251 
252         assertTrue(loop.hasPrevious());
253         assertEquals("c", loop.previous()); // a b <c>
254         loop.remove();                      // <a> b
255         assertEquals(2, list.size());
256 
257         assertTrue(loop.hasPrevious());
258         assertEquals("b", loop.previous()); // a <b>
259         loop.remove();                      // <a>
260         assertEquals(1, list.size());
261 
262         assertTrue(loop.hasPrevious());
263         assertEquals("a", loop.previous()); // <a>
264         loop.remove();                      // ---
265         assertEquals(0, list.size());
266 
267         assertFalse(loop.hasPrevious());
268 
269         assertThrows(NoSuchElementException.class, () -> loop.previous());
270     }
271 
272     /**
273      * Tests removing an element from a wrapped ArrayList.
274      */
275     @Test
276     public void testRemovingElementsAndIteratingForward() {
277         final List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
278         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <a> b c
279 
280         assertTrue(loop.hasNext());
281         assertEquals("a", loop.next()); // a <b> c
282         loop.remove();                  // <b> c
283         assertEquals(2, list.size());
284 
285         assertTrue(loop.hasNext());
286         assertEquals("b", loop.next()); // b <c>
287         loop.remove();                  // <c>
288         assertEquals(1, list.size());
289 
290         assertTrue(loop.hasNext());
291         assertEquals("c", loop.next()); // <c>
292         loop.remove();                  // ---
293         assertEquals(0, list.size());
294 
295         assertFalse(loop.hasNext());
296 
297         assertThrows(NoSuchElementException.class, () -> loop.next());
298     }
299 
300     /**
301      * Tests the reset method.
302      */
303     @Test
304     public void testReset() {
305         final List<String> list = Arrays.asList("a", "b", "c");
306         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <a> b c
307 
308         assertEquals("a", loop.next()); // a <b> c
309         assertEquals("b", loop.next()); // a b <c>
310         loop.reset();                   // <a> b c
311         assertEquals("a", loop.next()); // a <b> c
312         loop.reset();                   // <a> b c
313         assertEquals("a", loop.next()); // a <b> c
314         assertEquals("b", loop.next()); // a b <c>
315         assertEquals("c", loop.next()); // <a> b c
316         loop.reset();                   // <a> b c
317 
318         assertEquals("c", loop.previous()); // a b <c>
319         assertEquals("b", loop.previous()); // a <b> c
320         loop.reset();                       // <a> b c
321         assertEquals("c", loop.previous()); // a b <c>
322         loop.reset();                       // <a> b c
323         assertEquals("c", loop.previous()); // a b <c>
324         assertEquals("b", loop.previous()); // a <b> c
325         assertEquals("a", loop.previous()); // <a> b c
326     }
327 
328     /**
329      * Tests using the set method to change elements.
330      */
331     @Test
332     public void testSet() {
333         final List<String> list = Arrays.asList("q", "r", "z");
334         final LoopingListIterator<String> loop = new LoopingListIterator<>(list); // <q> r z
335 
336         assertEquals("z", loop.previous()); // q r <z>
337         loop.set("c");                      // q r <c>
338 
339         loop.reset();                       // <q> r c
340         assertEquals("q", loop.next());     // q <r> c
341         loop.set("a");                      // a <r> c
342 
343         assertEquals("r", loop.next());     // a r <c>
344         loop.set("b");                      // a b <c>
345 
346         loop.reset();                       // <a> b c
347         assertEquals("a", loop.next());     // a <b> c
348         assertEquals("b", loop.next());     // a b <c>
349         assertEquals("c", loop.next());     // <a> b c
350     }
351 
352 }