1/*
2 * Copyright (C) 2007 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.collect.testing.testers;
18
19import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
20import static com.google.common.collect.testing.features.CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION;
21import static com.google.common.collect.testing.features.CollectionFeature.RESTRICTS_ELEMENTS;
22import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ADD;
23import static com.google.common.collect.testing.features.CollectionSize.ZERO;
24import static java.util.Collections.singletonList;
25
26import com.google.common.annotations.GwtCompatible;
27import com.google.common.annotations.GwtIncompatible;
28import com.google.common.collect.testing.AbstractCollectionTester;
29import com.google.common.collect.testing.Helpers;
30import com.google.common.collect.testing.MinimalCollection;
31import com.google.common.collect.testing.features.CollectionFeature;
32import com.google.common.collect.testing.features.CollectionSize;
33
34import java.lang.reflect.Method;
35import java.util.ConcurrentModificationException;
36import java.util.Iterator;
37import java.util.List;
38
39/**
40 * A generic JUnit test which tests addAll operations on a collection. Can't be
41 * invoked directly; please see
42 * {@link com.google.common.collect.testing.CollectionTestSuiteBuilder}.
43 *
44 * @author Chris Povirk
45 * @author Kevin Bourrillion
46 */
47@SuppressWarnings("unchecked") // too many "unchecked generic array creations"
48@GwtCompatible(emulated = true)
49public class CollectionAddAllTester<E> extends AbstractCollectionTester<E> {
50  @CollectionFeature.Require(SUPPORTS_ADD)
51  public void testAddAll_supportedNothing() {
52    assertFalse("addAll(nothing) should return false",
53        collection.addAll(emptyCollection()));
54    expectUnchanged();
55  }
56
57  @CollectionFeature.Require(absent = SUPPORTS_ADD)
58  public void testAddAll_unsupportedNothing() {
59    try {
60      assertFalse("addAll(nothing) should return false or throw",
61          collection.addAll(emptyCollection()));
62    } catch (UnsupportedOperationException tolerated) {
63    }
64    expectUnchanged();
65  }
66
67  @CollectionFeature.Require(SUPPORTS_ADD)
68  public void testAddAll_supportedNonePresent() {
69    assertTrue("addAll(nonePresent) should return true",
70        collection.addAll(createDisjointCollection()));
71    expectAdded(samples.e3, samples.e4);
72  }
73
74  @CollectionFeature.Require(absent = SUPPORTS_ADD)
75  public void testAddAll_unsupportedNonePresent() {
76    try {
77      collection.addAll(createDisjointCollection());
78      fail("addAll(nonePresent) should throw");
79    } catch (UnsupportedOperationException expected) {
80    }
81    expectUnchanged();
82    expectMissing(samples.e3, samples.e4);
83  }
84
85  @CollectionFeature.Require(SUPPORTS_ADD)
86  @CollectionSize.Require(absent = ZERO)
87  public void testAddAll_supportedSomePresent() {
88    assertTrue("addAll(somePresent) should return true",
89        collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
90    assertTrue("should contain " + samples.e3, collection.contains(samples.e3));
91    assertTrue("should contain " + samples.e0, collection.contains(samples.e0));
92  }
93
94  @CollectionFeature.Require(absent = SUPPORTS_ADD)
95  @CollectionSize.Require(absent = ZERO)
96  public void testAddAll_unsupportedSomePresent() {
97    try {
98      collection.addAll(MinimalCollection.of(samples.e3, samples.e0));
99      fail("addAll(somePresent) should throw");
100    } catch (UnsupportedOperationException expected) {
101    }
102    expectUnchanged();
103  }
104
105  @CollectionFeature.Require({SUPPORTS_ADD,
106      FAILS_FAST_ON_CONCURRENT_MODIFICATION})
107  @CollectionSize.Require(absent = ZERO)
108  public void testAddAllConcurrentWithIteration() {
109    try {
110      Iterator<E> iterator = collection.iterator();
111      assertTrue(collection.addAll(MinimalCollection.of(samples.e3, samples.e0)));
112      iterator.next();
113      fail("Expected ConcurrentModificationException");
114    } catch (ConcurrentModificationException expected) {
115      // success
116    }
117  }
118
119  @CollectionFeature.Require(absent = SUPPORTS_ADD)
120  @CollectionSize.Require(absent = ZERO)
121  public void testAddAll_unsupportedAllPresent() {
122    try {
123      assertFalse("addAll(allPresent) should return false or throw",
124          collection.addAll(MinimalCollection.of(samples.e0)));
125    } catch (UnsupportedOperationException tolerated) {
126    }
127    expectUnchanged();
128  }
129
130  @CollectionFeature.Require(value = {SUPPORTS_ADD,
131      ALLOWS_NULL_VALUES}, absent = RESTRICTS_ELEMENTS)
132  public void testAddAll_nullSupported() {
133    List<E> containsNull = singletonList(null);
134    assertTrue("addAll(containsNull) should return true", collection
135        .addAll(containsNull));
136    /*
137     * We need (E) to force interpretation of null as the single element of a
138     * varargs array, not the array itself
139     */
140    expectAdded((E) null);
141  }
142
143  @CollectionFeature.Require(value = SUPPORTS_ADD,
144      absent = ALLOWS_NULL_VALUES)
145  public void testAddAll_nullUnsupported() {
146    List<E> containsNull = singletonList(null);
147    try {
148      collection.addAll(containsNull);
149      fail("addAll(containsNull) should throw");
150    } catch (NullPointerException expected) {
151    }
152    expectUnchanged();
153    expectNullMissingWhenNullUnsupported(
154        "Should not contain null after unsupported addAll(containsNull)");
155  }
156
157  @CollectionFeature.Require(SUPPORTS_ADD)
158  public void testAddAll_nullCollectionReference() {
159    try {
160      collection.addAll(null);
161      fail("addAll(null) should throw NullPointerException");
162    } catch (NullPointerException expected) {
163    }
164  }
165
166  /**
167   * Returns the {@link Method} instance for {@link
168   * #testAddAll_nullUnsupported()} so that tests can suppress it with {@code
169   * FeatureSpecificTestSuiteBuilder.suppressing()} until <a
170   * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5045147">Sun
171   * bug 5045147</a> is fixed.
172   */
173  @GwtIncompatible("reflection")
174  public static Method getAddAllNullUnsupportedMethod() {
175    return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_nullUnsupported");
176  }
177
178  /**
179   * Returns the {@link Method} instance for {@link
180   * #testAddAll_unsupportedNonePresent()} so that tests can suppress it with
181   * {@code FeatureSpecificTestSuiteBuilder.suppressing()} while we figure out
182   * what to do with <a href="http://goo.gl/qJBruX">{@code ConcurrentHashMap}
183   * support for {@code entrySet().add()}</a>.
184   */
185  @GwtIncompatible("reflection")
186  public static Method getAddAllUnsupportedNonePresentMethod() {
187    return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_unsupportedNonePresent");
188  }
189
190  /**
191   * Returns the {@link Method} instance for {@link
192   * #testAddAll_unsupportedSomePresent()} so that tests can suppress it with
193   * {@code FeatureSpecificTestSuiteBuilder.suppressing()} while we figure out
194   * what to do with <a href="http://goo.gl/qJBruX">{@code ConcurrentHashMap}
195   * support for {@code entrySet().add()}</a>.
196   */
197  @GwtIncompatible("reflection")
198  public static Method getAddAllUnsupportedSomePresentMethod() {
199    return Helpers.getMethod(CollectionAddAllTester.class, "testAddAll_unsupportedSomePresent");
200  }
201}
202