com.google.common.collect.testing
Class IteratorTester<E>

java.lang.Object
  extended by com.google.common.collect.testing.IteratorTester<E>

public abstract class IteratorTester<E>
extends Object

A utility for testing an Iterator implementation by comparing its behavior to that of a "known good" reference implementation. In order to accomplish this, it's important to test a great variety of sequences of the Iterator.next(), Iterator.hasNext() and Iterator.remove() operations. This utility takes the brute-force approach of trying all possible sequences of these operations, up to a given number of steps. So, if the caller specifies to use n steps, a total of 3^n tests are actually performed.

For instance, if steps is 5, one example sequence that will be tested is:

  1. remove();
  2. hasNext()
  3. hasNext();
  4. remove();
  5. next();
This particular order of operations may be unrealistic, and testing all 3^5 of them may be thought of as overkill; however, it's difficult to determine which proper subset of this massive set would be sufficient to expose any possible bug. Brute force is simpler.

To use this class the concrete subclass must implement the AbstractIteratorTester.newTargetIterator() method. This is because it's impossible to test an Iterator without changing its state, so the tester needs a steady supply of fresh Iterators.

If your iterator supports modification through remove(), you may wish to override the verify() method, which is called after each sequence and is guaranteed to be called using the latest values obtained from AbstractIteratorTester.newTargetIterator().

This class is GWT compatible.

Author:
Kevin Bourrillion, Chris Povirk

Nested Class Summary
static class AbstractIteratorTester.KnownOrder
           
 
Constructor Summary
protected IteratorTester(int steps, Iterable<? extends IteratorFeature> features, Iterable<E> expectedElements, AbstractIteratorTester.KnownOrder knownOrder)
          Creates an IteratorTester.
 
Method Summary
protected  Iterable<com.google.common.collect.testing.AbstractIteratorTester.Stimulus<E,Iterator<E>>> getStimulusValues()
          I'd like to make this a parameter to the constructor, but I can't because the stimulus instances refer to this.
 void ignoreSunJavaBug6529795()
          Don't verify iterator behavior on remove() after a call to next() throws an exception.
protected abstract  I newTargetIterator()
          Returns a new target iterator each time it's called.
 void stopTestingWhenAddThrowsException()
          Don't verify iterator behavior after a call to add() throws an exception.
 void test()
          Executes the test.
protected  void verify(List<E> elements)
          Override this to verify anything after running a list of Stimuli.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

IteratorTester

protected IteratorTester(int steps,
                         Iterable<? extends IteratorFeature> features,
                         Iterable<E> expectedElements,
                         AbstractIteratorTester.KnownOrder knownOrder)
Creates an IteratorTester.

Parameters:
steps - how many operations to test for each tested pair of iterators
features - the features supported by the iterator
Method Detail

getStimulusValues

protected final Iterable<com.google.common.collect.testing.AbstractIteratorTester.Stimulus<E,Iterator<E>>> getStimulusValues()
I'd like to make this a parameter to the constructor, but I can't because the stimulus instances refer to this.


ignoreSunJavaBug6529795

public void ignoreSunJavaBug6529795()
Don't verify iterator behavior on remove() after a call to next() throws an exception.

JDK 6 currently has a bug where some iterators get into a undefined state when next() throws a NoSuchElementException. The correct behavior is for remove() to remove the last element returned by next, even if a subsequent next() call threw an exception; however JDK 6's HashMap and related classes throw an IllegalStateException in this case.

Calling this method causes the iterator tester to skip testing any remove() in a stimulus sequence after the reference iterator throws an exception in next().

TODO: remove this once we're on 6u5, which has the fix.

See Also:
Sun Java Bug 6529795

stopTestingWhenAddThrowsException

public void stopTestingWhenAddThrowsException()
Don't verify iterator behavior after a call to add() throws an exception.

AbstractList's ListIterator implementation gets into a undefined state when add() throws an UnsupportedOperationException. Instead of leaving the iterator's position unmodified, it increments it, skipping an element or even moving past the end of the list.

Calling this method causes the iterator tester to skip testing in a stimulus sequence after the iterator under test throws an exception in add().

TODO: remove this once the behavior is fixed.

See Also:
Sun Java Bug 6533203

newTargetIterator

protected abstract I newTargetIterator()
Returns a new target iterator each time it's called. This is the iterator you are trying to test. This must return an Iterator that returns the expected elements passed to the constructor in the given order. Warning: it is not enough to simply pull multiple iterators from the same source Iterable, unless that Iterator is unmodifiable.


verify

protected void verify(List<E> elements)
Override this to verify anything after running a list of Stimuli.

For example, verify that calls to remove() actually removed the correct elements.

Parameters:
elements - the expected elements passed to the constructor, as mutated by remove(), set(), and add() calls

test

public final void test()
Executes the test.



Copyright © 2010-2011. All Rights Reserved.