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.Collections;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.NoSuchElementException;
30  
31  import org.junit.jupiter.api.BeforeEach;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * A unit test to test the basic functions of {@link SkippingIterator}.
36   */
37  public class SkippingIteratorTest<E> extends AbstractIteratorTest<E> {
38  
39      /** Test array of size 7 */
40      private final String[] testArray = {
41          "a", "b", "c", "d", "e", "f", "g"
42      };
43  
44      private List<E> testList;
45  
46      public SkippingIteratorTest() {
47          super(SkippingIteratorTest.class.getSimpleName());
48      }
49  
50      @Override
51      public Iterator<E> makeEmptyIterator() {
52          return new SkippingIterator<>(Collections.<E>emptyList().iterator(), 0);
53      }
54  
55      @Override
56      public Iterator<E> makeObject() {
57          return new SkippingIterator<>(new ArrayList<>(testList).iterator(), 1);
58      }
59  
60      @SuppressWarnings("unchecked")
61      @BeforeEach
62      public void setUp()
63          throws Exception {
64          testList = Arrays.asList((E[]) testArray);
65      }
66  
67      /**
68       * Test the case if a negative {@code offset} is passed to the
69       * constructor. {@link IllegalArgumentException} is expected.
70       */
71      @Test
72      public void testNegativeOffset() {
73          assertThrows(IllegalArgumentException.class, () -> new SkippingIterator<>(testList.iterator(), -1),
74                  "Expected IllegalArgumentException.");
75      }
76  
77      /**
78       * Test the case if the {@code offset} passed to the constructor is
79       * greater than the decorated iterator's size. The SkippingIterator should
80       * behave as if there are no more elements to return.
81       */
82      @Test
83      public void testOffsetGreaterThanSize() {
84          final Iterator<E> iter = new SkippingIterator<>(testList.iterator(), 10);
85          assertFalse(iter.hasNext());
86  
87          assertThrows(NoSuchElementException.class, () -> iter.next(),
88                  "Expected NoSuchElementException.");
89      }
90  
91      /**
92       * Test the {@code remove()} method being called twice without calling
93       * {@code next()} in between.
94       */
95      @Test
96      public void testRemoveCalledTwice() {
97          final List<E> testListCopy = new ArrayList<>(testList);
98          final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 1);
99  
100         assertTrue(iter.hasNext());
101         assertEquals("b", iter.next());
102         iter.remove();
103 
104         assertThrows(IllegalStateException.class, () -> iter.remove(),
105                 "Expected IllegalStateException.");
106     }
107 
108     /**
109      * Test removing the first element. Verify that the element is removed from
110      * the underlying collection.
111      */
112     @Test
113     public void testRemoveFirst() {
114         final List<E> testListCopy = new ArrayList<>(testList);
115         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 4);
116 
117         assertTrue(iter.hasNext());
118         assertEquals("e", iter.next());
119 
120         iter.remove();
121         assertFalse(testListCopy.contains("e"));
122 
123         assertTrue(iter.hasNext());
124         assertEquals("f", iter.next());
125         assertTrue(iter.hasNext());
126         assertEquals("g", iter.next());
127 
128         assertFalse(iter.hasNext());
129 
130         assertThrows(NoSuchElementException.class, () -> iter.next(),
131                 "Expected NoSuchElementException.");
132     }
133 
134     /**
135      * Test removing the last element. Verify that the element is removed from
136      * the underlying collection.
137      */
138     @Test
139     public void testRemoveLast() {
140         final List<E> testListCopy = new ArrayList<>(testList);
141         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 5);
142 
143         assertTrue(iter.hasNext());
144         assertEquals("f", iter.next());
145         assertTrue(iter.hasNext());
146         assertEquals("g", iter.next());
147 
148         assertFalse(iter.hasNext());
149 
150         assertThrows(NoSuchElementException.class, () -> iter.next(),
151                 "Expected NoSuchElementException.");
152 
153         iter.remove();
154         assertFalse(testListCopy.contains("g"));
155 
156         assertFalse(iter.hasNext());
157 
158         assertThrows(NoSuchElementException.class, () -> iter.next(),
159                 "Expected NoSuchElementException.");
160     }
161 
162     /**
163      * Test removing an element in the middle of the iterator. Verify that the
164      * element is removed from the underlying collection.
165      */
166     @Test
167     public void testRemoveMiddle() {
168         final List<E> testListCopy = new ArrayList<>(testList);
169         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 3);
170 
171         assertTrue(iter.hasNext());
172         assertEquals("d", iter.next());
173 
174         iter.remove();
175         assertFalse(testListCopy.contains("d"));
176 
177         assertTrue(iter.hasNext());
178         assertEquals("e", iter.next());
179         assertTrue(iter.hasNext());
180         assertEquals("f", iter.next());
181         assertTrue(iter.hasNext());
182         assertEquals("g", iter.next());
183 
184         assertFalse(iter.hasNext());
185 
186         assertThrows(NoSuchElementException.class, () -> iter.next(),
187                 "Expected NoSuchElementException.");
188     }
189 
190     /**
191      * Test the case if the decorated iterator does not support the
192      * {@code remove()} method and throws an {@link UnsupportedOperationException}.
193      */
194     @Test
195     public void testRemoveUnsupported() {
196         final Iterator<E> mockIterator = new AbstractIteratorDecorator<E>(testList.iterator()) {
197             @Override
198             public void remove() {
199                 throw new UnsupportedOperationException();
200             }
201         };
202 
203         final Iterator<E> iter = new SkippingIterator<>(mockIterator, 1);
204         assertTrue(iter.hasNext());
205         assertEquals("b", iter.next());
206 
207         assertThrows(UnsupportedOperationException.class, () -> iter.remove(),
208                 "Expected UnsupportedOperationException.");
209     }
210 
211     /**
212      * Test the {@code remove()} method being called without
213      * {@code next()} being called first.
214      */
215     @Test
216     public void testRemoveWithoutCallingNext() {
217         final List<E> testListCopy = new ArrayList<>(testList);
218         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 1);
219 
220         assertThrows(IllegalStateException.class, () -> iter.remove(),
221                 "Expected IllegalStateException.");
222     }
223 
224     /**
225      * Test a decorated iterator bounded such that the {@code offset} is
226      * zero, in that the SkippingIterator should return all the same elements
227      * as its decorated iterator.
228      */
229     @Test
230     public void testSameAsDecorated() {
231         final Iterator<E> iter = new SkippingIterator<>(testList.iterator(), 0);
232 
233         assertTrue(iter.hasNext());
234         assertEquals("a", iter.next());
235         assertTrue(iter.hasNext());
236         assertEquals("b", iter.next());
237         assertTrue(iter.hasNext());
238         assertEquals("c", iter.next());
239         assertTrue(iter.hasNext());
240         assertEquals("d", iter.next());
241         assertTrue(iter.hasNext());
242         assertEquals("e", iter.next());
243         assertTrue(iter.hasNext());
244         assertEquals("f", iter.next());
245         assertTrue(iter.hasNext());
246         assertEquals("g", iter.next());
247 
248         assertFalse(iter.hasNext());
249 
250         assertThrows(NoSuchElementException.class, () -> iter.next(),
251                 "Expected NoSuchElementException.");
252     }
253 
254     /**
255      * Test a decorated iterator bounded such that the first element returned is
256      * at an index greater its first element, and the last element returned is
257      * at an index less than its last element.
258      */
259     @Test
260     public void testSkipping() {
261         final Iterator<E> iter = new SkippingIterator<>(testList.iterator(), 2);
262 
263         assertTrue(iter.hasNext());
264         assertEquals("c", iter.next());
265         assertTrue(iter.hasNext());
266         assertEquals("d", iter.next());
267         assertTrue(iter.hasNext());
268         assertEquals("e", iter.next());
269         assertTrue(iter.hasNext());
270         assertEquals("f", iter.next());
271         assertTrue(iter.hasNext());
272         assertEquals("g", iter.next());
273 
274         assertFalse(iter.hasNext());
275 
276         assertThrows(NoSuchElementException.class, () -> iter.next(),
277                 "Expected NoSuchElementException.");
278     }
279 
280 }