10888a09821a98ac0680fad765217302858e70fa4Paul Duffin/*
20888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Copyright (C) 2007 The Guava Authors
30888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
50888a09821a98ac0680fad765217302858e70fa4Paul Duffin * you may not use this file except in compliance with the License.
60888a09821a98ac0680fad765217302858e70fa4Paul Duffin * You may obtain a copy of the License at
70888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
80888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
90888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
100888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unless required by applicable law or agreed to in writing, software
110888a09821a98ac0680fad765217302858e70fa4Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
120888a09821a98ac0680fad765217302858e70fa4Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130888a09821a98ac0680fad765217302858e70fa4Paul Duffin * See the License for the specific language governing permissions and
140888a09821a98ac0680fad765217302858e70fa4Paul Duffin * limitations under the License.
150888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
160888a09821a98ac0680fad765217302858e70fa4Paul Duffin
170888a09821a98ac0680fad765217302858e70fa4Paul Duffinpackage com.google.common.collect;
180888a09821a98ac0680fad765217302858e70fa4Paul Duffin
190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.annotations.GwtCompatible;
200888a09821a98ac0680fad765217302858e70fa4Paul Duffin
210888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport junit.framework.TestCase;
220888a09821a98ac0680fad765217302858e70fa4Paul Duffin
230888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.Iterator;
240888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.util.NoSuchElementException;
250888a09821a98ac0680fad765217302858e70fa4Paul Duffin
260888a09821a98ac0680fad765217302858e70fa4Paul Duffin/**
270888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unit test for {@code AbstractIterator}.
280888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
290888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @author Kevin Bourrillion
300888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
310888a09821a98ac0680fad765217302858e70fa4Paul Duffin@SuppressWarnings("serial") // No serialization is used in this test
320888a09821a98ac0680fad765217302858e70fa4Paul Duffin@GwtCompatible(emulated = true)
330888a09821a98ac0680fad765217302858e70fa4Paul Duffin// TODO(cpovirk): why is this slow (>1m/test) under GWT when fully optimized?
340888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic class AbstractIteratorTest extends TestCase {
350888a09821a98ac0680fad765217302858e70fa4Paul Duffin
360888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testDefaultBehaviorOfNextAndHasNext() {
370888a09821a98ac0680fad765217302858e70fa4Paul Duffin
380888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // This sample AbstractIterator returns 0 on the first call, 1 on the
390888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // second, then signals that it's reached the end of the data
400888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Iterator<Integer> iter = new AbstractIterator<Integer>() {
410888a09821a98ac0680fad765217302858e70fa4Paul Duffin      private int rep;
420888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Integer computeNext() {
430888a09821a98ac0680fad765217302858e70fa4Paul Duffin        switch (rep++) {
440888a09821a98ac0680fad765217302858e70fa4Paul Duffin          case 0:
450888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return 0;
460888a09821a98ac0680fad765217302858e70fa4Paul Duffin          case 1:
470888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return 1;
480888a09821a98ac0680fad765217302858e70fa4Paul Duffin          case 2:
490888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return endOfData();
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin          default:
510888a09821a98ac0680fad765217302858e70fa4Paul Duffin            fail("Should not have been invoked again");
520888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return null;
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin
570888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertTrue(iter.hasNext());
580888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(0, (int) iter.next());
590888a09821a98ac0680fad765217302858e70fa4Paul Duffin
600888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // verify idempotence of hasNext()
610888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertTrue(iter.hasNext());
620888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertTrue(iter.hasNext());
630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertTrue(iter.hasNext());
640888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(1, (int) iter.next());
650888a09821a98ac0680fad765217302858e70fa4Paul Duffin
660888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFalse(iter.hasNext());
670888a09821a98ac0680fad765217302858e70fa4Paul Duffin
680888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // Make sure computeNext() doesn't get invoked again
690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFalse(iter.hasNext());
700888a09821a98ac0680fad765217302858e70fa4Paul Duffin
710888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
720888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.next();
730888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("no exception thrown");
740888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (NoSuchElementException expected) {
750888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
760888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
770888a09821a98ac0680fad765217302858e70fa4Paul Duffin
780888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testDefaultBehaviorOfPeek() {
790888a09821a98ac0680fad765217302858e70fa4Paul Duffin    /*
800888a09821a98ac0680fad765217302858e70fa4Paul Duffin     * This sample AbstractIterator returns 0 on the first call, 1 on the
810888a09821a98ac0680fad765217302858e70fa4Paul Duffin     * second, then signals that it's reached the end of the data
820888a09821a98ac0680fad765217302858e70fa4Paul Duffin     */
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin    AbstractIterator<Integer> iter = new AbstractIterator<Integer>() {
840888a09821a98ac0680fad765217302858e70fa4Paul Duffin      private int rep;
850888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Integer computeNext() {
860888a09821a98ac0680fad765217302858e70fa4Paul Duffin        switch (rep++) {
870888a09821a98ac0680fad765217302858e70fa4Paul Duffin          case 0:
880888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return 0;
890888a09821a98ac0680fad765217302858e70fa4Paul Duffin          case 1:
900888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return 1;
910888a09821a98ac0680fad765217302858e70fa4Paul Duffin          case 2:
920888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return endOfData();
930888a09821a98ac0680fad765217302858e70fa4Paul Duffin          default:
940888a09821a98ac0680fad765217302858e70fa4Paul Duffin            fail("Should not have been invoked again");
950888a09821a98ac0680fad765217302858e70fa4Paul Duffin            return null;
960888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
970888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
990888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(0, (int) iter.peek());
1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(0, (int) iter.peek());
1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertTrue(iter.hasNext());
1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(0, (int) iter.peek());
1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(0, (int) iter.next());
1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(1, (int) iter.peek());
1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(1, (int) iter.next());
1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.peek();
1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("peek() should throw NoSuchElementException at end");
1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (NoSuchElementException expected) {
1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.peek();
1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("peek() should continue to throw NoSuchElementException at end");
1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (NoSuchElementException expected) {
1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.next();
1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("next() should throw NoSuchElementException as usual");
1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (NoSuchElementException expected) {
1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.peek();
1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("peek() should still throw NoSuchElementException after next()");
1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (NoSuchElementException expected) {
1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testDefaultBehaviorOfPeekForEmptyIteration() {
1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin    AbstractIterator<Integer> empty = new AbstractIterator<Integer>() {
1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin      private boolean alreadyCalledEndOfData;
1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Integer computeNext() {
1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (alreadyCalledEndOfData) {
1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin          fail("Should not have been invoked again");
1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin        alreadyCalledEndOfData = true;
1430888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return endOfData();
1440888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin      empty.peek();
1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("peek() should throw NoSuchElementException at end");
1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (NoSuchElementException expected) {
1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin      empty.peek();
1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("peek() should continue to throw NoSuchElementException at end");
1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (NoSuchElementException expected) {
1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testSneakyThrow() throws Exception {
1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Iterator<Integer> iter = new AbstractIterator<Integer>() {
1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin      boolean haveBeenCalled;
1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Integer computeNext() {
1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (haveBeenCalled) {
1650888a09821a98ac0680fad765217302858e70fa4Paul Duffin          fail("Should not have been called again");
1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin        } else {
1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin          haveBeenCalled = true;
1680888a09821a98ac0680fad765217302858e70fa4Paul Duffin          sneakyThrow(new SomeCheckedException());
1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
1700888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return null; // never reached
1710888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1720888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
1730888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // The first time, the sneakily-thrown exception comes out
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1760888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.hasNext();
1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("No exception thrown");
1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (Exception e) {
1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin      if (!(e instanceof SomeCheckedException)) {
1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throw e;
1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // But the second time, AbstractIterator itself throws an ISE
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.hasNext();
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("No exception thrown");
1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalStateException expected) {
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testException() {
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin    final SomeUncheckedException exception = new SomeUncheckedException();
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Iterator<Integer> iter = new AbstractIterator<Integer>() {
1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Integer computeNext() {
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throw exception;
1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2000888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // It should pass through untouched
2010888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
2020888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.hasNext();
2030888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("No exception thrown");
2040888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (SomeUncheckedException e) {
2050888a09821a98ac0680fad765217302858e70fa4Paul Duffin      assertSame(exception, e);
2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2070888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2080888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2090888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testExceptionAfterEndOfData() {
2100888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Iterator<Integer> iter = new AbstractIterator<Integer>() {
2110888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Integer computeNext() {
2120888a09821a98ac0680fad765217302858e70fa4Paul Duffin        endOfData();
2130888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throw new SomeUncheckedException();
2140888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2150888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
2160888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
2170888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.hasNext();
2180888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("No exception thrown");
2190888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (SomeUncheckedException expected) {
2200888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2210888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2220888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2230888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testCantRemove() {
2240888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Iterator<Integer> iter = new AbstractIterator<Integer>() {
2250888a09821a98ac0680fad765217302858e70fa4Paul Duffin      boolean haveBeenCalled;
2260888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override public Integer computeNext() {
2270888a09821a98ac0680fad765217302858e70fa4Paul Duffin        if (haveBeenCalled) {
2280888a09821a98ac0680fad765217302858e70fa4Paul Duffin          endOfData();
2290888a09821a98ac0680fad765217302858e70fa4Paul Duffin        }
2300888a09821a98ac0680fad765217302858e70fa4Paul Duffin        haveBeenCalled = true;
2310888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return 0;
2320888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2330888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
2340888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2350888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(0, (int) iter.next());
2360888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2370888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
2380888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.remove();
2390888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("No exception thrown");
2400888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (UnsupportedOperationException expected) {
2410888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2420888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2430888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2440888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testReentrantHasNext() {
2450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    Iterator<Integer> iter = new AbstractIterator<Integer>() {
2460888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @Override protected Integer computeNext() {
2470888a09821a98ac0680fad765217302858e70fa4Paul Duffin        hasNext();
2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return null;
2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    };
2510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
2520888a09821a98ac0680fad765217302858e70fa4Paul Duffin      iter.hasNext();
2530888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail();
2540888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalStateException expected) {
2550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2560888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2570888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2580888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // Technically we should test other reentrant scenarios (9 combinations of
2590888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // hasNext/next/peek), but we'll cop out for now, knowing that peek() and
2600888a09821a98ac0680fad765217302858e70fa4Paul Duffin  // next() both start by invoking hasNext() anyway.
2610888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2620888a09821a98ac0680fad765217302858e70fa4Paul Duffin  /**
2630888a09821a98ac0680fad765217302858e70fa4Paul Duffin   * Throws a undeclared checked exception.
2640888a09821a98ac0680fad765217302858e70fa4Paul Duffin   */
2650888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void sneakyThrow(Throwable t) {
2660888a09821a98ac0680fad765217302858e70fa4Paul Duffin    class SneakyThrower<T extends Throwable> {
2670888a09821a98ac0680fad765217302858e70fa4Paul Duffin      @SuppressWarnings("unchecked") // not really safe, but that's the point
2680888a09821a98ac0680fad765217302858e70fa4Paul Duffin      void throwIt(Throwable t) throws T {
2690888a09821a98ac0680fad765217302858e70fa4Paul Duffin        throw (T) t;
2700888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2710888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2720888a09821a98ac0680fad765217302858e70fa4Paul Duffin    new SneakyThrower<Error>().throwIt(t);
2730888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2740888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2750888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static class SomeCheckedException extends Exception {
2760888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2770888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2780888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static class SomeUncheckedException extends RuntimeException {
2790888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2800888a09821a98ac0680fad765217302858e70fa4Paul Duffin}
2810888a09821a98ac0680fad765217302858e70fa4Paul Duffin
282