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 this
4    * work for additional information regarding copyright ownership. The ASF
5    * licenses this file to You under the Apache License, Version 2.0 (the
6    * "License"); you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
9    * or agreed to in writing, software distributed under the License is
10   * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11   * KIND, either express or implied. See the License for the specific language
12   * governing permissions and limitations under the License.
13   */
14  package org.apache.commons.collections4.iterators;
15  
16  import java.util.ArrayList;
17  import java.util.Arrays;
18  import java.util.Collections;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.NoSuchElementException;
22  
23  import org.junit.Test;
24  
25  /**
26   * A unit test to test the basic functions of {@link SkippingIterator}.
27   *
28   */
29  public class SkippingIteratorTest<E> extends AbstractIteratorTest<E> {
30  
31      /** Test array of size 7 */
32      private final String[] testArray = {
33          "a", "b", "c", "d", "e", "f", "g"
34      };
35  
36      private List<E> testList;
37  
38      public SkippingIteratorTest(final String testName) {
39          super(testName);
40      }
41  
42      @SuppressWarnings("unchecked")
43      @Override
44      public void setUp()
45          throws Exception {
46          super.setUp();
47          testList = Arrays.asList((E[]) testArray);
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      // ---------------- Tests ---------------------
61  
62      /**
63       * Test a decorated iterator bounded such that the first element returned is
64       * at an index greater its first element, and the last element returned is
65       * at an index less than its last element.
66       */
67      @Test
68      public void testSkipping() {
69          final Iterator<E> iter = new SkippingIterator<>(testList.iterator(), 2);
70  
71          assertTrue(iter.hasNext());
72          assertEquals("c", iter.next());
73          assertTrue(iter.hasNext());
74          assertEquals("d", iter.next());
75          assertTrue(iter.hasNext());
76          assertEquals("e", iter.next());
77          assertTrue(iter.hasNext());
78          assertEquals("f", iter.next());
79          assertTrue(iter.hasNext());
80          assertEquals("g", iter.next());
81  
82          assertFalse(iter.hasNext());
83          try {
84              iter.next();
85              fail("Expected NoSuchElementException.");
86          } catch (final NoSuchElementException nsee) { /* Success case */
87          }
88      }
89  
90      /**
91       * Test a decorated iterator bounded such that the <code>offset</code> is
92       * zero, in that the SkippingIterator should return all the same elements
93       * as its decorated iterator.
94       */
95      @Test
96      public void testSameAsDecorated() {
97          final Iterator<E> iter = new SkippingIterator<>(testList.iterator(), 0);
98  
99          assertTrue(iter.hasNext());
100         assertEquals("a", iter.next());
101         assertTrue(iter.hasNext());
102         assertEquals("b", iter.next());
103         assertTrue(iter.hasNext());
104         assertEquals("c", iter.next());
105         assertTrue(iter.hasNext());
106         assertEquals("d", iter.next());
107         assertTrue(iter.hasNext());
108         assertEquals("e", iter.next());
109         assertTrue(iter.hasNext());
110         assertEquals("f", iter.next());
111         assertTrue(iter.hasNext());
112         assertEquals("g", iter.next());
113 
114         assertFalse(iter.hasNext());
115         try {
116             iter.next();
117             fail("Expected NoSuchElementException.");
118         } catch (final NoSuchElementException nsee) { /* Success case */
119         }
120     }
121 
122     /**
123      * Test the case if the <code>offset</code> passed to the constructor is
124      * greater than the decorated iterator's size. The SkippingIterator should
125      * behave as if there are no more elements to return.
126      */
127     @Test
128     public void testOffsetGreaterThanSize() {
129         final Iterator<E> iter = new SkippingIterator<>(testList.iterator(), 10);
130         assertFalse(iter.hasNext());
131         try {
132             iter.next();
133             fail("Expected NoSuchElementException.");
134         } catch (final NoSuchElementException nsee) { /* Success case */
135         }
136     }
137 
138     /**
139      * Test the case if a negative <code>offset</code> is passed to the
140      * constructor. {@link IllegalArgumentException} is expected.
141      */
142     @Test
143     public void testNegativeOffset() {
144         try {
145             new SkippingIterator<>(testList.iterator(), -1);
146             fail("Expected IllegalArgumentException.");
147         } catch (final IllegalArgumentException iae) { /* Success case */
148         }
149     }
150 
151     /**
152      * Test the <code>remove()</code> method being called without
153      * <code>next()</code> being called first.
154      */
155     @Test
156     public void testRemoveWithoutCallingNext() {
157         final List<E> testListCopy = new ArrayList<>(testList);
158         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 1);
159 
160         try {
161             iter.remove();
162             fail("Expected IllegalStateException.");
163         } catch (final IllegalStateException ise) { /* Success case */
164         }
165     }
166 
167     /**
168      * Test the <code>remove()</code> method being called twice without calling
169      * <code>next()</code> in between.
170      */
171     @Test
172     public void testRemoveCalledTwice() {
173         final List<E> testListCopy = new ArrayList<>(testList);
174         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 1);
175 
176         assertTrue(iter.hasNext());
177         assertEquals("b", iter.next());
178         iter.remove();
179 
180         try {
181             iter.remove();
182             fail("Expected IllegalStateException.");
183         } catch (final IllegalStateException ise) { /* Success case */
184         }
185     }
186 
187     /**
188      * Test removing the first element. Verify that the element is removed from
189      * the underlying collection.
190      */
191     @Test
192     public void testRemoveFirst() {
193         final List<E> testListCopy = new ArrayList<>(testList);
194         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 4);
195 
196         assertTrue(iter.hasNext());
197         assertEquals("e", iter.next());
198 
199         iter.remove();
200         assertFalse(testListCopy.contains("e"));
201 
202         assertTrue(iter.hasNext());
203         assertEquals("f", iter.next());
204         assertTrue(iter.hasNext());
205         assertEquals("g", iter.next());
206 
207         assertFalse(iter.hasNext());
208         try {
209             iter.next();
210             fail("Expected NoSuchElementException.");
211         } catch (final NoSuchElementException nsee) { /* Success case */
212         }
213     }
214 
215     /**
216      * Test removing an element in the middle of the iterator. Verify that the
217      * element is removed from the underlying collection.
218      */
219     @Test
220     public void testRemoveMiddle() {
221         final List<E> testListCopy = new ArrayList<>(testList);
222         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 3);
223 
224         assertTrue(iter.hasNext());
225         assertEquals("d", iter.next());
226 
227         iter.remove();
228         assertFalse(testListCopy.contains("d"));
229 
230         assertTrue(iter.hasNext());
231         assertEquals("e", iter.next());
232         assertTrue(iter.hasNext());
233         assertEquals("f", iter.next());
234         assertTrue(iter.hasNext());
235         assertEquals("g", iter.next());
236 
237         assertFalse(iter.hasNext());
238         try {
239             iter.next();
240             fail("Expected NoSuchElementException.");
241         } catch (final NoSuchElementException nsee) { /* Success case */
242         }
243     }
244 
245     /**
246      * Test removing the last element. Verify that the element is removed from
247      * the underlying collection.
248      */
249     @Test
250     public void testRemoveLast() {
251         final List<E> testListCopy = new ArrayList<>(testList);
252         final Iterator<E> iter = new SkippingIterator<>(testListCopy.iterator(), 5);
253 
254         assertTrue(iter.hasNext());
255         assertEquals("f", iter.next());
256         assertTrue(iter.hasNext());
257         assertEquals("g", iter.next());
258 
259         assertFalse(iter.hasNext());
260         try {
261             iter.next();
262             fail("Expected NoSuchElementException.");
263         } catch (final NoSuchElementException nsee) { /* Success case */
264         }
265 
266         iter.remove();
267         assertFalse(testListCopy.contains("g"));
268 
269         assertFalse(iter.hasNext());
270         try {
271             iter.next();
272             fail("Expected NoSuchElementException.");
273         } catch (final NoSuchElementException nsee) { /* Success case */
274         }
275     }
276 
277     /**
278      * Test the case if the decorated iterator does not support the
279      * <code>remove()</code> method and throws an {@link UnsupportedOperationException}.
280      */
281     @Test
282     public void testRemoveUnsupported() {
283         final Iterator<E> mockIterator = new AbstractIteratorDecorator<E>(testList.iterator()) {
284             @Override
285             public void remove() {
286                 throw new UnsupportedOperationException();
287             }
288         };
289 
290         final Iterator<E> iter = new SkippingIterator<>(mockIterator, 1);
291         assertTrue(iter.hasNext());
292         assertEquals("b", iter.next());
293         try {
294             iter.remove();
295             fail("Expected UnsupportedOperationException.");
296         } catch (final UnsupportedOperationException usoe) { /* Success case */
297         }
298     }
299 }