11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Iterator;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.NoSuchElementException;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unit test for {@code AbstractIterator}.
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kevin Bourrillion
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@SuppressWarnings("serial") // No serialization is used in this test
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// TODO(cpovirk): why is this slow (>1m/test) under GWT when fully optimized?
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class AbstractIteratorTest extends TestCase {
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testDefaultBehaviorOfNextAndHasNext() {
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // This sample AbstractIterator returns 0 on the first call, 1 on the
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // second, then signals that it's reached the end of the data
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Iterator<Integer> iter = new AbstractIterator<Integer>() {
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      private int rep;
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Integer computeNext() {
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        switch (rep++) {
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          case 0:
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return 0;
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          case 1:
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return 1;
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          case 2:
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return endOfData();
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          default:
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            fail("Should not have been invoked again");
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return null;
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(iter.hasNext());
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, (int) iter.next());
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // verify idempotence of hasNext()
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(iter.hasNext());
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(iter.hasNext());
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(iter.hasNext());
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, (int) iter.next());
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(iter.hasNext());
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Make sure computeNext() doesn't get invoked again
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(iter.hasNext());
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.next();
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("no exception thrown");
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NoSuchElementException expected) {
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testDefaultBehaviorOfPeek() {
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * This sample AbstractIterator returns 0 on the first call, 1 on the
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * second, then signals that it's reached the end of the data
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AbstractIterator<Integer> iter = new AbstractIterator<Integer>() {
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      private int rep;
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Integer computeNext() {
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        switch (rep++) {
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          case 0:
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return 0;
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          case 1:
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return 1;
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          case 2:
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return endOfData();
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          default:
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            fail("Should not have been invoked again");
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return null;
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, (int) iter.peek());
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, (int) iter.peek());
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(iter.hasNext());
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, (int) iter.peek());
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, (int) iter.next());
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, (int) iter.peek());
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, (int) iter.next());
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.peek();
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("peek() should throw NoSuchElementException at end");
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NoSuchElementException expected) {
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.peek();
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("peek() should continue to throw NoSuchElementException at end");
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NoSuchElementException expected) {
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.next();
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("next() should throw NoSuchElementException as usual");
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NoSuchElementException expected) {
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.peek();
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("peek() should still throw NoSuchElementException after next()");
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NoSuchElementException expected) {
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testDefaultBehaviorOfPeekForEmptyIteration() {
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AbstractIterator<Integer> empty = new AbstractIterator<Integer>() {
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      private boolean alreadyCalledEndOfData;
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Integer computeNext() {
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (alreadyCalledEndOfData) {
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          fail("Should not have been invoked again");
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        alreadyCalledEndOfData = true;
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return endOfData();
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      empty.peek();
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("peek() should throw NoSuchElementException at end");
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NoSuchElementException expected) {
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      empty.peek();
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("peek() should continue to throw NoSuchElementException at end");
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NoSuchElementException expected) {
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testSneakyThrow() throws Exception {
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Iterator<Integer> iter = new AbstractIterator<Integer>() {
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean haveBeenCalled;
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Integer computeNext() {
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (haveBeenCalled) {
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          fail("Should not have been called again");
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          haveBeenCalled = true;
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          sneakyThrow(new SomeCheckedException());
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null; // never reached
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The first time, the sneakily-thrown exception comes out
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.hasNext();
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("No exception thrown");
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (Exception e) {
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!(e instanceof SomeCheckedException)) {
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw e;
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // But the second time, AbstractIterator itself throws an ISE
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.hasNext();
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("No exception thrown");
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testException() {
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final SomeUncheckedException exception = new SomeUncheckedException();
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Iterator<Integer> iter = new AbstractIterator<Integer>() {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Integer computeNext() {
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw exception;
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // It should pass through untouched
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.hasNext();
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("No exception thrown");
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (SomeUncheckedException e) {
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertSame(exception, e);
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testExceptionAfterEndOfData() {
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Iterator<Integer> iter = new AbstractIterator<Integer>() {
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Integer computeNext() {
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        endOfData();
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new SomeUncheckedException();
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.hasNext();
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("No exception thrown");
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (SomeUncheckedException expected) {
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testCantRemove() {
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Iterator<Integer> iter = new AbstractIterator<Integer>() {
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean haveBeenCalled;
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Integer computeNext() {
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (haveBeenCalled) {
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          endOfData();
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        haveBeenCalled = true;
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return 0;
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, (int) iter.next());
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.remove();
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("No exception thrown");
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (UnsupportedOperationException expected) {
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testReentrantHasNext() {
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Iterator<Integer> iter = new AbstractIterator<Integer>() {
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override protected Integer computeNext() {
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        hasNext();
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      iter.hasNext();
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Technically we should test other reentrant scenarios (9 combinations of
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // hasNext/next/peek), but we'll cop out for now, knowing that peek() and
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // next() both start by invoking hasNext() anyway.
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Throws a undeclared checked exception.
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static void sneakyThrow(Throwable t) {
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    class SneakyThrower<T extends Throwable> {
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @SuppressWarnings("unchecked") // not really safe, but that's the point
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      void throwIt(Throwable t) throws T {
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw (T) t;
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    new SneakyThrower<Error>().throwIt(t);
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class SomeCheckedException extends Exception {
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static class SomeUncheckedException extends RuntimeException {
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
281