001/*
002 * Copyright (C) 2008 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package com.google.common.collect.testing.testers;
018
019import static com.google.common.collect.testing.Helpers.mapEntry;
020import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
021import static com.google.common.collect.testing.IteratorFeature.UNMODIFIABLE;
022import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER;
023import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ITERATOR_REMOVE;
024import static com.google.common.collect.testing.features.CollectionSize.ZERO;
025
026import com.google.common.annotations.GwtCompatible;
027import com.google.common.collect.testing.AbstractCollectionTester;
028import com.google.common.collect.testing.Helpers;
029import com.google.common.collect.testing.IteratorFeature;
030import com.google.common.collect.testing.IteratorTester;
031import com.google.common.collect.testing.features.CollectionFeature;
032import com.google.common.collect.testing.features.CollectionSize;
033import java.util.ArrayList;
034import java.util.Arrays;
035import java.util.Iterator;
036import java.util.List;
037import java.util.Map.Entry;
038import java.util.NoSuchElementException;
039import java.util.Set;
040import org.junit.Ignore;
041
042/**
043 * A generic JUnit test which tests {@code iterator} operations on a collection. Can't be invoked
044 * directly; please see {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}.
045 *
046 * @author Chris Povirk
047 */
048@GwtCompatible(emulated = true)
049@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
050public class CollectionIteratorTester<E> extends AbstractCollectionTester<E> {
051  public void testIterator() {
052    List<E> iteratorElements = new ArrayList<E>();
053    for (E element : collection) { // uses iterator()
054      iteratorElements.add(element);
055    }
056    Helpers.assertEqualIgnoringOrder(Arrays.asList(createSamplesArray()), iteratorElements);
057  }
058
059  @CollectionFeature.Require(KNOWN_ORDER)
060  public void testIterationOrdering() {
061    List<E> iteratorElements = new ArrayList<E>();
062    for (E element : collection) { // uses iterator()
063      iteratorElements.add(element);
064    }
065    List<E> expected = Helpers.copyToList(getOrderedElements());
066    assertEquals("Different ordered iteration", expected, iteratorElements);
067  }
068
069  @CollectionFeature.Require(SUPPORTS_ITERATOR_REMOVE)
070  @CollectionSize.Require(absent = ZERO)
071  public void testIterator_removeAffectsBackingCollection() {
072    int originalSize = collection.size();
073    Iterator<E> iterator = collection.iterator();
074    Object element = iterator.next();
075    // If it's an Entry, it may become invalid once it's removed from the Map. Copy it.
076    if (element instanceof Entry) {
077      Entry<?, ?> entry = (Entry<?, ?>) element;
078      element = mapEntry(entry.getKey(), entry.getValue());
079    }
080    assertTrue(collection.contains(element)); // sanity check
081    iterator.remove();
082    assertFalse(collection.contains(element));
083    assertEquals(originalSize - 1, collection.size());
084  }
085
086  @CollectionFeature.Require({KNOWN_ORDER, SUPPORTS_ITERATOR_REMOVE})
087  public void testIterator_knownOrderRemoveSupported() {
088    runIteratorTest(MODIFIABLE, IteratorTester.KnownOrder.KNOWN_ORDER, getOrderedElements());
089  }
090
091  @CollectionFeature.Require(value = KNOWN_ORDER, absent = SUPPORTS_ITERATOR_REMOVE)
092  public void testIterator_knownOrderRemoveUnsupported() {
093    runIteratorTest(UNMODIFIABLE, IteratorTester.KnownOrder.KNOWN_ORDER, getOrderedElements());
094  }
095
096  @CollectionFeature.Require(absent = KNOWN_ORDER, value = SUPPORTS_ITERATOR_REMOVE)
097  public void testIterator_unknownOrderRemoveSupported() {
098    runIteratorTest(MODIFIABLE, IteratorTester.KnownOrder.UNKNOWN_ORDER, getSampleElements());
099  }
100
101  @CollectionFeature.Require(absent = {KNOWN_ORDER, SUPPORTS_ITERATOR_REMOVE})
102  public void testIterator_unknownOrderRemoveUnsupported() {
103    runIteratorTest(UNMODIFIABLE, IteratorTester.KnownOrder.UNKNOWN_ORDER, getSampleElements());
104  }
105
106  private void runIteratorTest(
107      Set<IteratorFeature> features, IteratorTester.KnownOrder knownOrder, Iterable<E> elements) {
108    new IteratorTester<E>(
109        Platform.collectionIteratorTesterNumIterations(), features, elements, knownOrder) {
110      @Override
111      protected Iterator<E> newTargetIterator() {
112        resetCollection();
113        return collection.iterator();
114      }
115
116      @Override
117      protected void verify(List<E> elements) {
118        expectContents(elements);
119      }
120    }.test();
121  }
122
123  public void testIteratorNoSuchElementException() {
124    Iterator<E> iterator = collection.iterator();
125    while (iterator.hasNext()) {
126      iterator.next();
127    }
128
129    try {
130      iterator.next();
131      fail("iterator.next() should throw NoSuchElementException");
132    } catch (NoSuchElementException expected) {
133    }
134  }
135}