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.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.CollectionSize.ONE;
022import static com.google.common.collect.testing.features.CollectionSize.ZERO;
023import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_ADD_WITH_INDEX;
024
025import com.google.common.annotations.GwtCompatible;
026import com.google.common.annotations.GwtIncompatible;
027import com.google.common.collect.testing.Helpers;
028import com.google.common.collect.testing.features.CollectionFeature;
029import com.google.common.collect.testing.features.CollectionSize;
030import com.google.common.collect.testing.features.ListFeature;
031import java.lang.reflect.Method;
032import java.util.ConcurrentModificationException;
033import java.util.Iterator;
034import org.junit.Ignore;
035
036/**
037 * A generic JUnit test which tests {@code add(int, Object)} operations on a list. Can't be invoked
038 * directly; please see {@link com.google.common.collect.testing.ListTestSuiteBuilder}.
039 *
040 * @author Chris Povirk
041 */
042@SuppressWarnings("unchecked") // too many "unchecked generic array creations"
043@GwtCompatible(emulated = true)
044@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
045public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
046  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
047  @CollectionSize.Require(absent = ZERO)
048  public void testAddAtIndex_supportedPresent() {
049    getList().add(0, e0());
050    expectAdded(0, e0());
051  }
052
053  @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
054  @CollectionSize.Require(absent = ZERO)
055  /*
056   * absent = ZERO isn't required, since unmodList.add() must
057   * throw regardless, but it keeps the method name accurate.
058   */
059  public void testAddAtIndex_unsupportedPresent() {
060    try {
061      getList().add(0, e0());
062      fail("add(n, present) should throw");
063    } catch (UnsupportedOperationException expected) {
064    }
065    expectUnchanged();
066  }
067
068  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
069  public void testAddAtIndex_supportedNotPresent() {
070    getList().add(0, e3());
071    expectAdded(0, e3());
072  }
073
074  @CollectionFeature.Require(FAILS_FAST_ON_CONCURRENT_MODIFICATION)
075  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
076  public void testAddAtIndexConcurrentWithIteration() {
077    try {
078      Iterator<E> iterator = collection.iterator();
079      getList().add(0, e3());
080      iterator.next();
081      fail("Expected ConcurrentModificationException");
082    } catch (ConcurrentModificationException expected) {
083      // success
084    }
085  }
086
087  @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
088  public void testAddAtIndex_unsupportedNotPresent() {
089    try {
090      getList().add(0, e3());
091      fail("add(n, notPresent) should throw");
092    } catch (UnsupportedOperationException expected) {
093    }
094    expectUnchanged();
095    expectMissing(e3());
096  }
097
098  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
099  @CollectionSize.Require(absent = {ZERO, ONE})
100  public void testAddAtIndex_middle() {
101    getList().add(getNumElements() / 2, e3());
102    expectAdded(getNumElements() / 2, e3());
103  }
104
105  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
106  @CollectionSize.Require(absent = ZERO)
107  public void testAddAtIndex_end() {
108    getList().add(getNumElements(), e3());
109    expectAdded(getNumElements(), e3());
110  }
111
112  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
113  @CollectionFeature.Require(ALLOWS_NULL_VALUES)
114  public void testAddAtIndex_nullSupported() {
115    getList().add(0, null);
116    expectAdded(0, (E) null);
117  }
118
119  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
120  @CollectionFeature.Require(absent = ALLOWS_NULL_VALUES)
121  public void testAddAtIndex_nullUnsupported() {
122    try {
123      getList().add(0, null);
124      fail("add(n, null) should throw");
125    } catch (NullPointerException expected) {
126    }
127    expectUnchanged();
128    expectNullMissingWhenNullUnsupported("Should not contain null after unsupported add(n, null)");
129  }
130
131  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
132  public void testAddAtIndex_negative() {
133    try {
134      getList().add(-1, e3());
135      fail("add(-1, e) should throw");
136    } catch (IndexOutOfBoundsException expected) {
137    }
138    expectUnchanged();
139    expectMissing(e3());
140  }
141
142  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
143  public void testAddAtIndex_tooLarge() {
144    try {
145      getList().add(getNumElements() + 1, e3());
146      fail("add(size + 1, e) should throw");
147    } catch (IndexOutOfBoundsException expected) {
148    }
149    expectUnchanged();
150    expectMissing(e3());
151  }
152
153  /**
154   * Returns the {@link Method} instance for {@link #testAddAtIndex_nullSupported()} so that tests
155   * can suppress it. See {@link CollectionAddTester#getAddNullSupportedMethod()} for details.
156   */
157  @GwtIncompatible // reflection
158  public static Method getAddNullSupportedMethod() {
159    return Helpers.getMethod(ListAddAtIndexTester.class, "testAddAtIndex_nullSupported");
160  }
161}