11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 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.testing; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static junit.framework.Assert.assertEquals; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static junit.framework.Assert.fail; 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.AssertionFailedError; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.ArrayList; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.HashSet; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Iterator; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List; 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.ListIterator; 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.NoSuchElementException; 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set; 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Stack; 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Most of the logic for {@link IteratorTester} and {@link ListIteratorTester}. 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class is GWT compatible. 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <E> the type of element returned by the iterator 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <I> the type of the iterator ({@link Iterator} or 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ListIterator}) 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kevin Bourrillion 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Chris Povirk 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertabstract class AbstractIteratorTester<E, I extends Iterator<E>> { 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean whenNextThrowsExceptionStopTestingCallsToRemove; 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean whenAddThrowsExceptionStopTesting; 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Don't verify iterator behavior on remove() after a call to next() 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * throws an exception. 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>JDK 6 currently has a bug where some iterators get into a undefined 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * state when next() throws a NoSuchElementException. The correct 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * behavior is for remove() to remove the last element returned by 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * next, even if a subsequent next() call threw an exception; however 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * JDK 6's HashMap and related classes throw an IllegalStateException 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in this case. 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Calling this method causes the iterator tester to skip testing 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * any remove() in a stimulus sequence after the reference iterator 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * throws an exception in next(). 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>TODO: remove this once we're on 6u5, which has the fix. 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6529795"> 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Sun Java Bug 6529795</a> 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void ignoreSunJavaBug6529795() { 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert whenNextThrowsExceptionStopTestingCallsToRemove = true; 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Don't verify iterator behavior after a call to add() throws an exception. 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>AbstractList's ListIterator implementation gets into a undefined state 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * when add() throws an UnsupportedOperationException. Instead of leaving the 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * iterator's position unmodified, it increments it, skipping an element or 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * even moving past the end of the list. 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Calling this method causes the iterator tester to skip testing in a 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * stimulus sequence after the iterator under test throws an exception in 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * add(). 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>TODO: remove this once the behavior is fixed. 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @see <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6533203"> 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Sun Java Bug 6533203</a> 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void stopTestingWhenAddThrowsException() { 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert whenAddThrowsExceptionStopTesting = true; 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Stimulus<E, ? super I>[] stimuli; 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final Iterator<E> elementsToInsert; 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final Set<IteratorFeature> features; 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final List<E> expectedElements; 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final int startIndex; 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final KnownOrder knownOrder; 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Meta-exception thrown by 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link AbstractIteratorTester.MultiExceptionListIterator} instead of 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * throwing any particular exception type. 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // This class is accessible but not supported in GWT. 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final class PermittedMetaException extends RuntimeException { 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Set<? extends Class<? extends RuntimeException>> exceptionClasses; 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert PermittedMetaException( 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<? extends Class<? extends RuntimeException>> exceptionClasses) { 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super("one of " + exceptionClasses); 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.exceptionClasses = exceptionClasses; 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert PermittedMetaException(Class<? extends RuntimeException> exceptionClass) { 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this(Collections.singleton(exceptionClass)); 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // It's not supported In GWT, it always returns true. 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean isPermitted(RuntimeException exception) { 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Class<? extends RuntimeException> clazz : exceptionClasses) { 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (Platform.checkIsInstance(clazz, exception)) { 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // It's not supported in GWT, it always passes. 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void assertPermitted(RuntimeException exception) { 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!isPermitted(exception)) { 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO: use simple class names 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert String message = "Exception " + exception.getClass() 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert + " was thrown; expected " + this; 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.fail(exception, message); 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public String toString() { 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return getMessage(); 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final long serialVersionUID = 0; 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final class UnknownElementException extends RuntimeException { 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private UnknownElementException(Collection<?> expected, Object actual) { 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super("Returned value '" 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert + actual + "' not found. Remaining elements: " + expected); 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final long serialVersionUID = 0; 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Quasi-implementation of {@link ListIterator} that works from a list of 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * elements and a set of features to support (from the enclosing 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link AbstractIteratorTester} instance). Instead of throwing exceptions 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * like {@link NoSuchElementException} at the appropriate times, it throws 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link PermittedMetaException} instances, which wrap a set of all 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * exceptions that the iterator could throw during the invocation of that 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * method. This is necessary because, e.g., a call to 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code iterator().remove()} of an unmodifiable list could throw either 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link IllegalStateException} or {@link UnsupportedOperationException}. 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Note that iterator implementations should always throw one of the 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * exceptions in a {@code PermittedExceptions} instance, since 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code PermittedExceptions} is thrown only when a method call is invalid. 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class is accessible but not supported in GWT as it references 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link PermittedMetaException}. 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected final class MultiExceptionListIterator implements ListIterator<E> { 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO: track seen elements when order isn't guaranteed 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO: verify contents afterward 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO: something shiny and new instead of Stack 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO: test whether null is supported (create a Feature) 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The elements to be returned by future calls to {@code next()}, with the 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * first at the top of the stack. 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Stack<E> nextElements = new Stack<E>(); 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The elements to be returned by future calls to {@code previous()}, with 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the first at the top of the stack. 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Stack<E> previousElements = new Stack<E>(); 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #nextElements} if {@code next()} was called more recently then 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code previous}, {@link #previousElements} if the reverse is true, or -- 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * overriding both of these -- {@code null} if {@code remove()} or 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code add()} has been called more recently than either. We use this to 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * determine which stack to pop from on a call to {@code remove()} (or to 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * pop from and push to on a call to {@code set()}. 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stack<E> stackWithLastReturnedElementAtTop = null; 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MultiExceptionListIterator(List<E> expectedElements) { 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.addAll(nextElements, Helpers.reverse(expectedElements)); 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int i = 0; i < startIndex; i++) { 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert previousElements.push(nextElements.pop()); 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void add(E e) { 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!features.contains(IteratorFeature.SUPPORTS_ADD)) { 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new PermittedMetaException(UnsupportedOperationException.class); 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert previousElements.push(e); 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stackWithLastReturnedElementAtTop = null; 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean hasNext() { 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return !nextElements.isEmpty(); 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean hasPrevious() { 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return !previousElements.isEmpty(); 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public E next() { 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return transferElement(nextElements, previousElements); 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public int nextIndex() { 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return previousElements.size(); 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public E previous() { 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return transferElement(previousElements, nextElements); 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public int previousIndex() { 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return nextIndex() - 1; 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void remove() { 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throwIfInvalid(IteratorFeature.SUPPORTS_REMOVE); 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stackWithLastReturnedElementAtTop.pop(); 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stackWithLastReturnedElementAtTop = null; 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public void set(E e) { 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throwIfInvalid(IteratorFeature.SUPPORTS_SET); 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stackWithLastReturnedElementAtTop.pop(); 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stackWithLastReturnedElementAtTop.push(e); 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Moves the given element from its current position in 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #nextElements} to the top of the stack so that it is returned by 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the next call to {@link Iterator#next()}. If the element is not in 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #nextElements}, this method throws an 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link UnknownElementException}. 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This method is used when testing iterators without a known ordering. 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * We poll the target iterator's next element and pass it to the reference 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * iterator through this method so it can return the same element. This 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * enables the assertion to pass and the reference iterator to properly 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * update its state. 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void promoteToNext(E e) { 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (nextElements.remove(e)) { 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert nextElements.push(e); 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } else { 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new UnknownElementException(nextElements, e); 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private E transferElement(Stack<E> source, Stack<E> destination) { 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (source.isEmpty()) { 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new PermittedMetaException(NoSuchElementException.class); 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert destination.push(source.pop()); 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stackWithLastReturnedElementAtTop = destination; 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return destination.peek(); 2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void throwIfInvalid(IteratorFeature methodFeature) { 2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<Class<? extends RuntimeException>> exceptions 2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert = new HashSet<Class<? extends RuntimeException>>(); 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!features.contains(methodFeature)) { 3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert exceptions.add(UnsupportedOperationException.class); 3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (stackWithLastReturnedElementAtTop == null) { 3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert exceptions.add(IllegalStateException.class); 3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!exceptions.isEmpty()) { 3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new PermittedMetaException(exceptions); 3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private List<E> getElements() { 3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<E> elements = new ArrayList<E>(); 3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.addAll(elements, previousElements); 3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.addAll(elements, Helpers.reverse(nextElements)); 3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return elements; 3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public enum KnownOrder { KNOWN_ORDER, UNKNOWN_ORDER } 3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") // creating array of generic class Stimulus 3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AbstractIteratorTester(int steps, Iterable<E> elementsToInsertIterable, 3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Iterable<? extends IteratorFeature> features, 3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Iterable<E> expectedElements, KnownOrder knownOrder, int startIndex) { 3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // periodically we should manually try (steps * 3 / 2) here; all tests but 3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // one should still pass (testVerifyGetsCalled()). 3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stimuli = new Stimulus[steps]; 3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!elementsToInsertIterable.iterator().hasNext()) { 3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new IllegalArgumentException(); 3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert elementsToInsert = Helpers.cycle(elementsToInsertIterable); 3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.features = Helpers.copyToSet(features); 3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.expectedElements = Helpers.copyToList(expectedElements); 3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.knownOrder = knownOrder; 3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.startIndex = startIndex; 3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * I'd like to make this a parameter to the constructor, but I can't because 3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the stimulus instances refer to {@code this}. 3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected abstract Iterable<? extends Stimulus<E, ? super I>> 3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert getStimulusValues(); 3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a new target iterator each time it's called. This is the iterator 3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you are trying to test. This must return an Iterator that returns the 3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * expected elements passed to the constructor in the given order. Warning: it 3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * is not enough to simply pull multiple iterators from the same source 3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Iterable, unless that Iterator is unmodifiable. 3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected abstract I newTargetIterator(); 3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Override this to verify anything after running a list of Stimuli. 3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>For example, verify that calls to remove() actually removed 3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the correct elements. 3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param elements the expected elements passed to the constructor, as mutated 3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * by {@code remove()}, {@code set()}, and {@code add()} calls 3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void verify(List<E> elements) {} 3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Executes the test. 3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public final void test() { 3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert recurse(0); 3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (RuntimeException e) { 3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException(Arrays.toString(stimuli), e); 3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void recurse(int level) { 3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // We're going to reuse the stimuli array 3^steps times by overwriting it 3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // in a recursive loop. Sneaky. 3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (level == stimuli.length) { 3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // We've filled the array. 3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert compareResultsForThisListOfStimuli(); 3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } else { 3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Keep recursing to fill the array. 3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Stimulus<E, ? super I> stimulus : getStimulusValues()) { 3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert stimuli[level] = stimulus; 3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert recurse(level + 1); 3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void compareResultsForThisListOfStimuli() { 3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MultiExceptionListIterator reference = 3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new MultiExceptionListIterator(expectedElements); 3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert I target = newTargetIterator(); 3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean shouldStopTestingCallsToRemove = false; 3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int i = 0; i < stimuli.length; i++) { 3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, ? super I> stimulus = stimuli[i]; 3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (stimulus.equals(remove) && shouldStopTestingCallsToRemove) { 4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert break; 4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean threwException = stimulus.executeAndCompare(reference, target); 4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (threwException 4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert && stimulus.equals(next) 4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert && whenNextThrowsExceptionStopTestingCallsToRemove) { 4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert shouldStopTestingCallsToRemove = true; 4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (threwException 4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert && stimulus.equals(add) 4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert && whenAddThrowsExceptionStopTesting) { 4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert break; 4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<E> elements = reference.getElements(); 4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verify(elements); 4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (AssertionFailedError cause) { 4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.fail(cause, 4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "failed with stimuli " + subListCopy(stimuli, i + 1)); 4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static List<Object> subListCopy(Object[] source, int size) { 4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Object[] copy = new Object[size]; 4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Platform.unsafeArrayCopy(source, 0, copy, 0, size); 4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Arrays.asList(copy); 4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private interface IteratorOperation { 4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object execute(Iterator<?> iterator); 4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Apply this method to both iterators and return normally only if both 4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * produce the same response. 4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @return {@code true} if an exception was thrown by the iterators. 4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @see Stimulus#executeAndCompare(ListIterator, Iterator) 4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private <T extends Iterator<E>> boolean internalExecuteAndCompare( 4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert T reference, T target, IteratorOperation method) 4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throws AssertionFailedError { 4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object referenceReturnValue = null; 4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert PermittedMetaException referenceException = null; 4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object targetReturnValue = null; 4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert RuntimeException targetException = null; 4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert targetReturnValue = method.execute(target); 4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (RuntimeException e) { 4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert targetException = e; 4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (method == NEXT_METHOD && targetException == null 4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert && knownOrder == KnownOrder.UNKNOWN_ORDER) { 4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * We already know the iterator is an Iterator<E>, and now we know that 4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * we called next(), so the returned element must be of type E. 4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert E targetReturnValueFromNext = (E) targetReturnValue; 4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * We have an Iterator<E> and want to cast it to 4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * MultiExceptionListIterator. Because we're inside an 4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * AbstractIteratorTester<E>, that's implicitly a cast to 4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * AbstractIteratorTester<E>.MultiExceptionListIterator. The runtime 4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * won't be able to verify the AbstractIteratorTester<E> part, so it's 4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * an unchecked cast. We know, however, that the only possible value for 4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the type parameter is <E>, since otherwise the 4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * MultiExceptionListIterator wouldn't be an Iterator<E>. The cast is 4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * safe, even though javac can't tell. 4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Sun bug 6665356 is an additional complication. Until OpenJDK 7, javac 4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * doesn't recognize this kind of cast as unchecked cast. Neither does 4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Eclipse 3.4. Right now, this suppression is mostly unecessary. 4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MultiExceptionListIterator multiExceptionListIterator = 4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert (MultiExceptionListIterator) reference; 4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert multiExceptionListIterator.promoteToNext(targetReturnValueFromNext); 4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert referenceReturnValue = method.execute(reference); 4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (PermittedMetaException e) { 4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert referenceException = e; 4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (UnknownElementException e) { 4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.fail(e, e.getMessage()); 4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (referenceException == null) { 4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (targetException != null) { 4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.fail(targetException, 4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "Target threw exception when reference did not"); 4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Reference iterator returned a value, so we should expect the 5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * same value from the target 5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(referenceReturnValue, targetReturnValue); 5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (targetException == null) { 5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert fail("Target failed to throw " + referenceException); 5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Reference iterator threw an exception, so we should expect an acceptable 5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * exception from the target. 5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert referenceException.assertPermitted(targetException); 5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final IteratorOperation REMOVE_METHOD = 5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new IteratorOperation() { 5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Object execute(Iterator<?> iterator) { 5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert iterator.remove(); 5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final IteratorOperation NEXT_METHOD = 5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new IteratorOperation() { 5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Object execute(Iterator<?> iterator) { 5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return iterator.next(); 5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final IteratorOperation PREVIOUS_METHOD = 5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new IteratorOperation() { 5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Object execute(Iterator<?> iterator) { 5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return ((ListIterator<?>) iterator).previous(); 5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final IteratorOperation newAddMethod() { 5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Object toInsert = elementsToInsert.next(); 5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new IteratorOperation() { 5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Object execute(Iterator<?> iterator) { 5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListIterator<Object> rawIterator = (ListIterator<Object>) iterator; 5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert rawIterator.add(toInsert); 5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final IteratorOperation newSetMethod() { 5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final E toInsert = elementsToInsert.next(); 5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new IteratorOperation() { 5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Object execute(Iterator<?> iterator) { 5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListIterator<E> li = (ListIterator<E>) iterator; 5651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert li.set(toInsert); 5661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 5671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 5691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert abstract static class Stimulus<E, T extends Iterator<E>> { 5721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final String toString; 5731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Stimulus(String toString) { 5751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.toString = toString; 5761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 5791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Send this stimulus to both iterators and return normally only if both 5801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * produce the same response. 5811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @return {@code true} if an exception was thrown by the iterators. 5831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert abstract boolean executeAndCompare(ListIterator<E> reference, T target); 5851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public String toString() { 5871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return toString; 5881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, Iterator<E>> hasNext = new Stimulus<E, Iterator<E>>("hasNext") { 5921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean 5931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executeAndCompare(ListIterator<E> reference, Iterator<E> target) { 5941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // return only if both are true or both are false 5951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(reference.hasNext(), target.hasNext()); 5961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 5971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 5991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, Iterator<E>> next = new Stimulus<E, Iterator<E>>("next") { 6001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean 6011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executeAndCompare(ListIterator<E> reference, Iterator<E> target) { 6021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return internalExecuteAndCompare(reference, target, NEXT_METHOD); 6031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 6051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, Iterator<E>> remove = new Stimulus<E, Iterator<E>>("remove") { 6061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean 6071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert executeAndCompare(ListIterator<E> reference, Iterator<E> target) { 6081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return internalExecuteAndCompare(reference, target, REMOVE_METHOD); 6091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 6111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 6121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 6131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<Stimulus<E, Iterator<E>>> iteratorStimuli() { 6141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Arrays.asList(hasNext, next, remove); 6151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 6171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, ListIterator<E>> hasPrevious = 6181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new Stimulus<E, ListIterator<E>>("hasPrevious") { 6191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean executeAndCompare( 6201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListIterator<E> reference, ListIterator<E> target) { 6211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // return only if both are true or both are false 6221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(reference.hasPrevious(), target.hasPrevious()); 6231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 6241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 6261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, ListIterator<E>> nextIndex = 6271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new Stimulus<E, ListIterator<E>>("nextIndex") { 6281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean executeAndCompare( 6291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListIterator<E> reference, ListIterator<E> target) { 6301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(reference.nextIndex(), target.nextIndex()); 6311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 6321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 6341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, ListIterator<E>> previousIndex = 6351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new Stimulus<E, ListIterator<E>>("previousIndex") { 6361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean executeAndCompare( 6371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListIterator<E> reference, ListIterator<E> target) { 6381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assertEquals(reference.previousIndex(), target.previousIndex()); 6391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 6401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 6421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, ListIterator<E>> previous = 6431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new Stimulus<E, ListIterator<E>>("previous") { 6441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean executeAndCompare( 6451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListIterator<E> reference, ListIterator<E> target) { 6461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return internalExecuteAndCompare(reference, target, PREVIOUS_METHOD); 6471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 6491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, ListIterator<E>> add = new Stimulus<E, ListIterator<E>>("add") { 6501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean executeAndCompare( 6511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListIterator<E> reference, ListIterator<E> target) { 6521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return internalExecuteAndCompare(reference, target, newAddMethod()); 6531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 6551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Stimulus<E, ListIterator<E>> set = new Stimulus<E, ListIterator<E>>("set") { 6561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean executeAndCompare( 6571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ListIterator<E> reference, ListIterator<E> target) { 6581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return internalExecuteAndCompare(reference, target, newSetMethod()); 6591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 6611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 6621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 6631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<Stimulus<E, ListIterator<E>>> listIteratorStimuli() { 6641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Arrays.asList( 6651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert hasPrevious, nextIndex, previousIndex, previous, add, set); 6661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 668