• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.base;
18 
19 import com.google.common.annotations.GwtCompatible;
20 
21 import junit.framework.TestCase;
22 
23 import java.util.Iterator;
24 import java.util.NoSuchElementException;
25 
26 /**
27  * Unit test for {@code AbstractIterator}.
28  *
29  * @author Kevin Bourrillion
30  */
31 @SuppressWarnings("serial") // No serialization is used in this test
32 @GwtCompatible
33 // TODO(cpovirk): why is this slow (>1m/test) under GWT when fully optimized?
34 public class AbstractIteratorTest extends TestCase {
35 
testDefaultBehaviorOfNextAndHasNext()36   public void testDefaultBehaviorOfNextAndHasNext() {
37 
38     // This sample AbstractIterator returns 0 on the first call, 1 on the
39     // second, then signals that it's reached the end of the data
40     Iterator<Integer> iter = new AbstractIterator<Integer>() {
41       private int rep;
42       @Override public Integer computeNext() {
43         switch (rep++) {
44           case 0:
45             return 0;
46           case 1:
47             return 1;
48           case 2:
49             return endOfData();
50           default:
51             fail("Should not have been invoked again");
52             return null;
53         }
54       }
55     };
56 
57     assertTrue(iter.hasNext());
58     assertEquals(0, (int) iter.next());
59 
60     // verify idempotence of hasNext()
61     assertTrue(iter.hasNext());
62     assertTrue(iter.hasNext());
63     assertTrue(iter.hasNext());
64     assertEquals(1, (int) iter.next());
65 
66     assertFalse(iter.hasNext());
67 
68     // Make sure computeNext() doesn't get invoked again
69     assertFalse(iter.hasNext());
70 
71     try {
72       iter.next();
73       fail("no exception thrown");
74     } catch (NoSuchElementException expected) {
75     }
76   }
77 
testSneakyThrow()78   public void testSneakyThrow() throws Exception {
79     Iterator<Integer> iter = new AbstractIterator<Integer>() {
80       boolean haveBeenCalled;
81       @Override public Integer computeNext() {
82         if (haveBeenCalled) {
83           fail("Should not have been called again");
84         } else {
85           haveBeenCalled = true;
86           sneakyThrow(new SomeCheckedException());
87         }
88         return null; // never reached
89       }
90     };
91 
92     // The first time, the sneakily-thrown exception comes out
93     try {
94       iter.hasNext();
95       fail("No exception thrown");
96     } catch (Exception e) {
97       if (!(e instanceof SomeCheckedException)) {
98         throw e;
99       }
100     }
101 
102     // But the second time, AbstractIterator itself throws an ISE
103     try {
104       iter.hasNext();
105       fail("No exception thrown");
106     } catch (IllegalStateException expected) {
107     }
108   }
109 
testException()110   public void testException() {
111     final SomeUncheckedException exception = new SomeUncheckedException();
112     Iterator<Integer> iter = new AbstractIterator<Integer>() {
113       @Override public Integer computeNext() {
114         throw exception;
115       }
116     };
117 
118     // It should pass through untouched
119     try {
120       iter.hasNext();
121       fail("No exception thrown");
122     } catch (SomeUncheckedException e) {
123       assertSame(exception, e);
124     }
125   }
126 
testExceptionAfterEndOfData()127   public void testExceptionAfterEndOfData() {
128     Iterator<Integer> iter = new AbstractIterator<Integer>() {
129       @Override public Integer computeNext() {
130         endOfData();
131         throw new SomeUncheckedException();
132       }
133     };
134     try {
135       iter.hasNext();
136       fail("No exception thrown");
137     } catch (SomeUncheckedException expected) {
138     }
139   }
140 
testCantRemove()141   public void testCantRemove() {
142     Iterator<Integer> iter = new AbstractIterator<Integer>() {
143       boolean haveBeenCalled;
144       @Override public Integer computeNext() {
145         if (haveBeenCalled) {
146           endOfData();
147         }
148         haveBeenCalled = true;
149         return 0;
150       }
151     };
152 
153     assertEquals(0, (int) iter.next());
154 
155     try {
156       iter.remove();
157       fail("No exception thrown");
158     } catch (UnsupportedOperationException expected) {
159     }
160   }
161 
testReentrantHasNext()162   public void testReentrantHasNext() {
163     Iterator<Integer> iter = new AbstractIterator<Integer>() {
164       @Override protected Integer computeNext() {
165         hasNext();
166         return null;
167       }
168     };
169     try {
170       iter.hasNext();
171       fail();
172     } catch (IllegalStateException expected) {
173     }
174   }
175 
176   // Technically we should test other reentrant scenarios (4 combinations of
177   // hasNext/next), but we'll cop out for now, knowing that
178   // next() both start by invoking hasNext() anyway.
179 
180   /**
181    * Throws a undeclared checked exception.
182    */
sneakyThrow(Throwable t)183   private static void sneakyThrow(Throwable t) {
184     class SneakyThrower<T extends Throwable> {
185       @SuppressWarnings("unchecked") // not really safe, but that's the point
186       void throwIt(Throwable t) throws T {
187         throw (T) t;
188       }
189     }
190     new SneakyThrower<Error>().throwIt(t);
191   }
192 
193   private static class SomeCheckedException extends Exception {
194   }
195 
196   private static class SomeUncheckedException extends RuntimeException {
197   }
198 }
199