Java
356 строк · 10.3 Кб
1/*
2* Copyright (C) 2008 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
17package com.google.common.collect.testing;
18
19import static com.google.common.collect.Lists.newArrayList;
20import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
21import static java.util.Collections.emptyList;
22
23import com.google.common.annotations.GwtCompatible;
24import com.google.common.collect.ImmutableList;
25import com.google.common.collect.Lists;
26import java.util.Iterator;
27import java.util.List;
28import java.util.NoSuchElementException;
29import junit.framework.TestCase;
30
31/**
32* Unit test for IteratorTester.
33*
34* @author Mick Killianey
35*/
36@GwtCompatible
37@SuppressWarnings("serial") // No serialization is used in this test
38public class IteratorTesterTest extends TestCase {
39
40public void testCanCatchDifferentLengthOfIteration() {
41IteratorTester<Integer> tester =
42new IteratorTester<Integer>(
434, MODIFIABLE, newArrayList(1, 2, 3), IteratorTester.KnownOrder.KNOWN_ORDER) {
44@Override
45protected Iterator<Integer> newTargetIterator() {
46return Lists.newArrayList(1, 2, 3, 4).iterator();
47}
48};
49assertFailure(tester);
50}
51
52public void testCanCatchDifferentContents() {
53IteratorTester<Integer> tester =
54new IteratorTester<Integer>(
553, MODIFIABLE, newArrayList(1, 2, 3), IteratorTester.KnownOrder.KNOWN_ORDER) {
56@Override
57protected Iterator<Integer> newTargetIterator() {
58return Lists.newArrayList(1, 3, 2).iterator();
59}
60};
61assertFailure(tester);
62}
63
64public void testCanCatchDifferentRemoveBehaviour() {
65IteratorTester<Integer> tester =
66new IteratorTester<Integer>(
673, MODIFIABLE, newArrayList(1, 2), IteratorTester.KnownOrder.KNOWN_ORDER) {
68@Override
69protected Iterator<Integer> newTargetIterator() {
70return ImmutableList.of(1, 2).iterator();
71}
72};
73assertFailure(tester);
74}
75
76public void testUnknownOrder() {
77new IteratorTester<Integer>(
783, MODIFIABLE, newArrayList(1, 2), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
79@Override
80protected Iterator<Integer> newTargetIterator() {
81return newArrayList(2, 1).iterator();
82}
83}.test();
84}
85
86public void testUnknownOrderUnrecognizedElement() {
87IteratorTester<Integer> tester =
88new IteratorTester<Integer>(
893, MODIFIABLE, newArrayList(1, 2, 50), IteratorTester.KnownOrder.UNKNOWN_ORDER) {
90@Override
91protected Iterator<Integer> newTargetIterator() {
92return newArrayList(2, 1, 3).iterator();
93}
94};
95assertFailure(tester);
96}
97
98/**
99* This Iterator wraps another iterator and gives it a bug found in JDK6.
100*
101* <p>This bug is this: if you create an iterator from a TreeSet and call next() on that iterator
102* when hasNext() is false, so that next() throws a NoSuchElementException, then subsequent calls
103* to remove() will incorrectly throw an IllegalStateException, instead of removing the last
104* element returned.
105*
106* <p>See <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6529795">Sun bug 6529795</a>
107*/
108static class IteratorWithSunJavaBug6529795<T> implements Iterator<T> {
109Iterator<T> iterator;
110boolean nextThrewException;
111
112IteratorWithSunJavaBug6529795(Iterator<T> iterator) {
113this.iterator = iterator;
114}
115
116@Override
117public boolean hasNext() {
118return iterator.hasNext();
119}
120
121@Override
122public T next() {
123try {
124return iterator.next();
125} catch (NoSuchElementException e) {
126nextThrewException = true;
127throw e;
128}
129}
130
131@Override
132public void remove() {
133if (nextThrewException) {
134throw new IllegalStateException();
135}
136iterator.remove();
137}
138}
139
140public void testCanCatchSunJavaBug6529795InTargetIterator() {
141try {
142/* Choose 4 steps to get sequence [next, next, next, remove] */
143new IteratorTester<Integer>(
1444, MODIFIABLE, newArrayList(1, 2), IteratorTester.KnownOrder.KNOWN_ORDER) {
145@Override
146protected Iterator<Integer> newTargetIterator() {
147Iterator<Integer> iterator = Lists.newArrayList(1, 2).iterator();
148return new IteratorWithSunJavaBug6529795<>(iterator);
149}
150}.test();
151} catch (AssertionError e) {
152return;
153}
154fail("Should have caught jdk6 bug in target iterator");
155}
156
157private static final int STEPS = 3;
158
159static class TesterThatCountsCalls extends IteratorTester<Integer> {
160TesterThatCountsCalls() {
161super(STEPS, MODIFIABLE, newArrayList(1), IteratorTester.KnownOrder.KNOWN_ORDER);
162}
163
164int numCallsToNewTargetIterator;
165int numCallsToVerify;
166
167@Override
168protected Iterator<Integer> newTargetIterator() {
169numCallsToNewTargetIterator++;
170return Lists.newArrayList(1).iterator();
171}
172
173@Override
174protected void verify(List<Integer> elements) {
175numCallsToVerify++;
176super.verify(elements);
177}
178}
179
180public void testVerifyGetsCalled() {
181TesterThatCountsCalls tester = new TesterThatCountsCalls();
182
183tester.test();
184
185assertEquals(
186"Should have verified once per stimulus executed",
187tester.numCallsToVerify,
188tester.numCallsToNewTargetIterator * STEPS);
189}
190
191public void testVerifyCanThrowAssertionThatFailsTest() {
192final String message = "Important info about why verify failed";
193IteratorTester<Integer> tester =
194new IteratorTester<Integer>(
1951, MODIFIABLE, newArrayList(1, 2, 3), IteratorTester.KnownOrder.KNOWN_ORDER) {
196@Override
197protected Iterator<Integer> newTargetIterator() {
198return Lists.newArrayList(1, 2, 3).iterator();
199}
200
201@Override
202protected void verify(List<Integer> elements) {
203throw new AssertionError(message);
204}
205};
206AssertionError actual = null;
207try {
208tester.test();
209} catch (AssertionError e) {
210actual = e;
211}
212assertNotNull("verify() should be able to cause test failure", actual);
213assertTrue(
214"AssertionError should have info about why test failed",
215actual.getCause().getMessage().contains(message));
216}
217
218public void testMissingException() {
219List<Integer> emptyList = newArrayList();
220
221IteratorTester<Integer> tester =
222new IteratorTester<Integer>(
2231, MODIFIABLE, emptyList, IteratorTester.KnownOrder.KNOWN_ORDER) {
224@Override
225protected Iterator<Integer> newTargetIterator() {
226return new Iterator<Integer>() {
227@Override
228public void remove() {
229// We should throw here, but we won't!
230}
231
232@Override
233public Integer next() {
234// We should throw here, but we won't!
235return 0;
236}
237
238@Override
239public boolean hasNext() {
240return false;
241}
242};
243}
244};
245assertFailure(tester);
246}
247
248public void testUnexpectedException() {
249IteratorTester<Integer> tester =
250new IteratorTester<Integer>(
2511, MODIFIABLE, newArrayList(1), IteratorTester.KnownOrder.KNOWN_ORDER) {
252@Override
253protected Iterator<Integer> newTargetIterator() {
254return new ThrowingIterator<>(new IllegalStateException());
255}
256};
257assertFailure(tester);
258}
259
260public void testSimilarException() {
261List<Integer> emptyList = emptyList();
262IteratorTester<Integer> tester =
263new IteratorTester<Integer>(
2641, MODIFIABLE, emptyList, IteratorTester.KnownOrder.KNOWN_ORDER) {
265@Override
266protected Iterator<Integer> newTargetIterator() {
267return new Iterator<Integer>() {
268@Override
269public void remove() {
270throw new IllegalStateException() {
271/* subclass */
272};
273}
274
275@Override
276public Integer next() {
277throw new NoSuchElementException() {
278/* subclass */
279};
280}
281
282@Override
283public boolean hasNext() {
284return false;
285}
286};
287}
288};
289tester.test();
290}
291
292public void testMismatchedException() {
293List<Integer> emptyList = emptyList();
294IteratorTester<Integer> tester =
295new IteratorTester<Integer>(
2961, MODIFIABLE, emptyList, IteratorTester.KnownOrder.KNOWN_ORDER) {
297@Override
298protected Iterator<Integer> newTargetIterator() {
299return new Iterator<Integer>() {
300@Override
301public void remove() {
302// Wrong exception type.
303throw new IllegalArgumentException();
304}
305
306@Override
307public Integer next() {
308// Wrong exception type.
309throw new UnsupportedOperationException();
310}
311
312@Override
313public boolean hasNext() {
314return false;
315}
316};
317}
318};
319assertFailure(tester);
320}
321
322private static void assertFailure(IteratorTester<?> tester) {
323try {
324tester.test();
325} catch (AssertionError expected) {
326return;
327}
328fail();
329}
330
331private static final class ThrowingIterator<E> implements Iterator<E> {
332private final RuntimeException ex;
333
334private ThrowingIterator(RuntimeException ex) {
335this.ex = ex;
336}
337
338@Override
339public boolean hasNext() {
340// IteratorTester doesn't expect exceptions for hasNext().
341return true;
342}
343
344@Override
345public E next() {
346ex.fillInStackTrace();
347throw ex;
348}
349
350@Override
351public void remove() {
352ex.fillInStackTrace();
353throw ex;
354}
355}
356}
357