001/*
002 * Copyright (C) 2007 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.features.CollectionFeature.ALLOWS_NULL_VALUES;
020import static com.google.common.collect.testing.features.CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION;
021import static com.google.common.collect.testing.features.CollectionFeature.RESTRICTS_ELEMENTS;
022import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ADD;
023import static com.google.common.collect.testing.features.CollectionSize.ZERO;
024import static java.util.Collections.singletonList;
025
026import com.google.common.annotations.GwtCompatible;
027import com.google.common.annotations.GwtIncompatible;
028import com.google.common.collect.testing.AbstractCollectionTester;
029import com.google.common.collect.testing.Helpers;
030import com.google.common.collect.testing.MinimalCollection;
031import com.google.common.collect.testing.features.CollectionFeature;
032import com.google.common.collect.testing.features.CollectionSize;
033import java.lang.reflect.Method;
034import java.util.ConcurrentModificationException;
035import java.util.Iterator;
036import java.util.List;
037
038/**
039 * A generic JUnit test which tests addAll operations on a collection. Can't be invoked directly;
040 * please see {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}.
041 *
042 * @author Chris Povirk
043 * @author Kevin Bourrillion
044 */
045@SuppressWarnings("unchecked") // too many "unchecked generic array creations"
046@GwtCompatible(emulated = true)
047public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
048  @CollectionFeature.Require(SUPPORTS_ADD)
049  public void testAddAll_supportedNothing() {
050    assertFalse("addAll(nothing) should return false", collection.addAll(emptyCollection()));
051    expectUnchanged();
052  }
053
054  @CollectionFeature.Require(absent = SUPPORTS_ADD)
055  public void testAddAll_unsupportedNothing() {
056    try {
057      assertFalse(
058          "addAll(nothing) should return false or throw", collection.addAll(emptyCollection()));
059    } catch (UnsupportedOperationException tolerated) {
060    }
061    expectUnchanged();
062  }
063
064  @CollectionFeature.Require(SUPPORTS_ADD)
065  public void testAddAll_supportedNonePresent() {
066    assertTrue(
067        "addAll(nonePresent) should return true", collection.addAll(createDisjointCollection()));
068    expectAdded(e3(), e4());
069  }
070
071  @CollectionFeature.Require(absent = SUPPORTS_ADD)
072  public void testAddAll_unsupportedNonePresent() {
073    try {
074      collection.addAll(createDisjointCollection());
075      fail("addAll(nonePresent) should throw");
076    } catch (UnsupportedOperationException expected) {
077    }
078    expectUnchanged();
079    expectMissing(e3(), e4());
080  }
081
082  @CollectionFeature.Require(SUPPORTS_ADD)
083  @CollectionSize.Require(absent = ZERO)
084  public void testAddAll_supportedSomePresent() {
085    assertTrue(
086        "addAll(somePresent) should return true",
087        collection.addAll(MinimalCollection.of(e3(), e0())));
088    assertTrue("should contain " + e3(), collection.contains(e3()));
089    assertTrue("should contain " + e0(), collection.contains(e0()));
090  }
091
092  @CollectionFeature.Require(absent = SUPPORTS_ADD)
093  @CollectionSize.Require(absent = ZERO)
094  public void testAddAll_unsupportedSomePresent() {
095    try {
096      collection.addAll(MinimalCollection.of(e3(), e0()));
097      fail("addAll(somePresent) should throw");
098    } catch (UnsupportedOperationException expected) {
099    }
100    expectUnchanged();
101  }
102
103  @CollectionFeature.Require({SUPPORTS_ADD, FAILS_FAST_ON_CONCURRENT_MODIFICATION})
104  @CollectionSize.Require(absent = ZERO)
105  public void testAddAllConcurrentWithIteration() {
106    try {
107      Iterator<E> iterator = collection.iterator();
108      assertTrue(collection.addAll(MinimalCollection.of(e3(), e0())));
109      iterator.next();
110      fail("Expected ConcurrentModificationException");
111    } catch (ConcurrentModificationException expected) {
112      // success
113    }
114  }
115
116  @CollectionFeature.Require(absent = SUPPORTS_ADD)
117  @CollectionSize.Require(absent = ZERO)
118  public void testAddAll_unsupportedAllPresent() {
119    try {
120      assertFalse(
121          "addAll(allPresent) should return false or throw",
122          collection.addAll(MinimalCollection.of(e0())));
123    } catch (UnsupportedOperationException tolerated) {
124    }
125    expectUnchanged();
126  }
127
128  @CollectionFeature.Require(
129    value = {SUPPORTS_ADD, ALLOWS_NULL_VALUES},
130    absent = RESTRICTS_ELEMENTS
131  )
132  public void testAddAll_nullSupported() {
133    List<E> containsNull = singletonList(null);
134    assertTrue("addAll(containsNull) should return true", collection.addAll(containsNull));
135    /*
136     * We need (E) to force interpretation of null as the single element of a
137     * varargs array, not the array itself
138     */
139    expectAdded((E) null);
140  }
141
142  @CollectionFeature.Require(value = SUPPORTS_ADD, absent = ALLOWS_NULL_VALUES)
143  public void testAddAll_nullUnsupported() {
144    List<E> containsNull = singletonList(null);
145    try {
146      collection.addAll(containsNull);
147      fail("addAll(containsNull) should throw");
148    } catch (NullPointerException expected) {
149    }
150    expectUnchanged();
151    expectNullMissingWhenNullUnsupported(
152        "Should not contain null after unsupported addAll(containsNull)");
153  }
154
155  @CollectionFeature.Require(SUPPORTS_ADD)
156  public void testAddAll_nullCollectionReference() {
157    try {
158      collection.addAll(null);
159      fail("addAll(null) should throw NullPointerException");
160    } catch (NullPointerException expected) {
161    }
162  }
163
164  /**
165   * Returns the {@link Method} instance for {@link #testAddAll_nullUnsupported()} so that tests can
166   * suppress it with {@code FeatureSpecificTestSuiteBuilder.suppressing()} until <a
167   * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5045147">Sun bug 5045147</a> is fixed.
168   */
169  @GwtIncompatible // reflection
170  public static Method getAddAllNullUnsupportedMethod() {
171    return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_nullUnsupported");
172  }
173
174  /**
175   * Returns the {@link Method} instance for {@link #testAddAll_unsupportedNonePresent()} so that
176   * tests can suppress it with {@code FeatureSpecificTestSuiteBuilder.suppressing()} while we
177   * figure out what to do with <a href="http://goo.gl/qJBruX">{@code ConcurrentHashMap} support for
178   * {@code entrySet().add()}</a>.
179   */
180  @GwtIncompatible // reflection
181  public static Method getAddAllUnsupportedNonePresentMethod() {
182    return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_unsupportedNonePresent");
183  }
184
185  /**
186   * Returns the {@link Method} instance for {@link #testAddAll_unsupportedSomePresent()} so that
187   * tests can suppress it with {@code FeatureSpecificTestSuiteBuilder.suppressing()} while we
188   * figure out what to do with <a href="http://goo.gl/qJBruX">{@code ConcurrentHashMap} support for
189   * {@code entrySet().add()}</a>.
190   */
191  @GwtIncompatible // reflection
192  public static Method getAddAllUnsupportedSomePresentMethod() {
193    return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_unsupportedSomePresent");
194  }
195}