1/*
2 * Copyright (C) 2008 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.CollectionSize.ONE;
22import static com.google.common.collect.testing.features.CollectionSize.ZERO;
23import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_ADD_WITH_INDEX;
24
25import com.google.common.annotations.GwtCompatible;
26import com.google.common.collect.testing.features.CollectionFeature;
27import com.google.common.collect.testing.features.CollectionSize;
28import com.google.common.collect.testing.features.ListFeature;
29
30import java.util.ConcurrentModificationException;
31import java.util.Iterator;
32
33/**
34 * A generic JUnit test which tests {@code add(int, Object)} operations on a
35 * list. Can't be invoked directly; please see
36 * {@link com.google.common.collect.testing.ListTestSuiteBuilder}.
37 *
38 * @author Chris Povirk
39 */
40@SuppressWarnings("unchecked") // too many "unchecked generic array creations"
41@GwtCompatible(emulated = true)
42public class ListAddAtIndexTester<E> extends AbstractListTester<E> {
43  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
44  @CollectionSize.Require(absent = ZERO)
45  public void testAddAtIndex_supportedPresent() {
46    getList().add(0, samples.e0);
47    expectAdded(0, samples.e0);
48  }
49
50  @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
51  @CollectionSize.Require(absent = ZERO)
52  /*
53   * absent = ZERO isn't required, since unmodList.add() must
54   * throw regardless, but it keeps the method name accurate.
55   */
56  public void testAddAtIndex_unsupportedPresent() {
57    try {
58      getList().add(0, samples.e0);
59      fail("add(n, present) should throw");
60    } catch (UnsupportedOperationException expected) {
61    }
62    expectUnchanged();
63  }
64
65  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
66  public void testAddAtIndex_supportedNotPresent() {
67    getList().add(0, samples.e3);
68    expectAdded(0, samples.e3);
69  }
70
71  @CollectionFeature.Require(FAILS_FAST_ON_CONCURRENT_MODIFICATION)
72  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
73  public void testAddAtIndexConcurrentWithIteration() {
74    try {
75      Iterator<E> iterator = collection.iterator();
76      getList().add(0, samples.e3);
77      iterator.next();
78      fail("Expected ConcurrentModificationException");
79    } catch (ConcurrentModificationException expected) {
80      // success
81    }
82  }
83
84  @ListFeature.Require(absent = SUPPORTS_ADD_WITH_INDEX)
85  public void testAddAtIndex_unsupportedNotPresent() {
86    try {
87      getList().add(0, samples.e3);
88      fail("add(n, notPresent) should throw");
89    } catch (UnsupportedOperationException expected) {
90    }
91    expectUnchanged();
92    expectMissing(samples.e3);
93  }
94
95  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
96  @CollectionSize.Require(absent = {ZERO, ONE})
97  public void testAddAtIndex_middle() {
98    getList().add(getNumElements() / 2, samples.e3);
99    expectAdded(getNumElements() / 2, samples.e3);
100  }
101
102  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
103  @CollectionSize.Require(absent = ZERO)
104  public void testAddAtIndex_end() {
105    getList().add(getNumElements(), samples.e3);
106    expectAdded(getNumElements(), samples.e3);
107  }
108
109  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
110  @CollectionFeature.Require(ALLOWS_NULL_VALUES)
111  public void testAddAtIndex_nullSupported() {
112    getList().add(0, null);
113    expectAdded(0, (E) null);
114  }
115
116  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
117  @CollectionFeature.Require(absent = ALLOWS_NULL_VALUES)
118  public void testAddAtIndex_nullUnsupported() {
119    try {
120      getList().add(0, null);
121      fail("add(n, null) should throw");
122    } catch (NullPointerException expected) {
123    }
124    expectUnchanged();
125    expectNullMissingWhenNullUnsupported(
126        "Should not contain null after unsupported add(n, null)");
127  }
128
129  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
130  public void testAddAtIndex_negative() {
131    try {
132      getList().add(-1, samples.e3);
133      fail("add(-1, e) should throw");
134    } catch (IndexOutOfBoundsException expected) {
135    }
136    expectUnchanged();
137    expectMissing(samples.e3);
138  }
139
140  @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
141  public void testAddAtIndex_tooLarge() {
142    try {
143      getList().add(getNumElements() + 1, samples.e3);
144      fail("add(size + 1, e) should throw");
145    } catch (IndexOutOfBoundsException expected) {
146    }
147    expectUnchanged();
148    expectMissing(samples.e3);
149  }
150}
151
152