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.getMethod;
020import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
021import static com.google.common.collect.testing.features.CollectionSize.ZERO;
022import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_SET;
023import static com.google.common.collect.testing.testers.ReflectionFreeAssertThrows.assertThrows;
024
025import com.google.common.annotations.GwtCompatible;
026import com.google.common.annotations.GwtIncompatible;
027import com.google.common.annotations.J2ktIncompatible;
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 org.junit.Ignore;
033
034/**
035 * A generic JUnit test which tests {@code set()} operations on a list. Can't be invoked directly;
036 * please see {@link com.google.common.collect.testing.ListTestSuiteBuilder}.
037 *
038 * @author George van den Driessche
039 */
040@GwtCompatible(emulated = true)
041@Ignore("test runners must not instantiate and run this directly, only via suites we build")
042// @Ignore affects the Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
043@SuppressWarnings("JUnit4ClassUsedInJUnit3")
044public class ListSetTester<E> extends AbstractListTester<E> {
045  @ListFeature.Require(SUPPORTS_SET)
046  @CollectionSize.Require(absent = ZERO)
047  public void testSet() {
048    doTestSet(e3());
049  }
050
051  @CollectionSize.Require(absent = ZERO)
052  @CollectionFeature.Require(ALLOWS_NULL_VALUES)
053  @ListFeature.Require(SUPPORTS_SET)
054  public void testSet_null() {
055    doTestSet(null);
056  }
057
058  @CollectionSize.Require(absent = ZERO)
059  @CollectionFeature.Require(ALLOWS_NULL_VALUES)
060  @ListFeature.Require(SUPPORTS_SET)
061  public void testSet_replacingNull() {
062    E[] elements = createSamplesArray();
063    int i = aValidIndex();
064    elements[i] = null;
065    collection = getSubjectGenerator().create(elements);
066
067    doTestSet(e3());
068  }
069
070  private void doTestSet(E newValue) {
071    int index = aValidIndex();
072    E initialValue = getList().get(index);
073    assertEquals(
074        "set(i, x) should return the old element at position i.",
075        initialValue,
076        getList().set(index, newValue));
077    assertEquals("After set(i, x), get(i) should return x", newValue, getList().get(index));
078    assertEquals("set() should not change the size of a list.", getNumElements(), getList().size());
079  }
080
081  @ListFeature.Require(SUPPORTS_SET)
082  public void testSet_indexTooLow() {
083    assertThrows(IndexOutOfBoundsException.class, () -> getList().set(-1, e3()));
084    expectUnchanged();
085  }
086
087  @ListFeature.Require(SUPPORTS_SET)
088  public void testSet_indexTooHigh() {
089    int index = getNumElements();
090    assertThrows(IndexOutOfBoundsException.class, () -> getList().set(index, e3()));
091    expectUnchanged();
092  }
093
094  @CollectionSize.Require(absent = ZERO)
095  @ListFeature.Require(absent = SUPPORTS_SET)
096  public void testSet_unsupported() {
097    assertThrows(UnsupportedOperationException.class, () -> getList().set(aValidIndex(), e3()));
098    expectUnchanged();
099  }
100
101  @CollectionSize.Require(ZERO)
102  @ListFeature.Require(absent = SUPPORTS_SET)
103  public void testSet_unsupportedByEmptyList() {
104    try {
105      getList().set(0, e3());
106      fail("set() should throw UnsupportedOperationException or IndexOutOfBoundsException");
107    } catch (UnsupportedOperationException | IndexOutOfBoundsException expected) {
108    }
109    expectUnchanged();
110  }
111
112  @CollectionSize.Require(absent = ZERO)
113  @ListFeature.Require(SUPPORTS_SET)
114  @CollectionFeature.Require(absent = ALLOWS_NULL_VALUES)
115  public void testSet_nullUnsupported() {
116    assertThrows(NullPointerException.class, () -> getList().set(aValidIndex(), null));
117    expectUnchanged();
118  }
119
120  private int aValidIndex() {
121    return getList().size() / 2;
122  }
123
124  /**
125   * Returns the {@link java.lang.reflect.Method} instance for {@link #testSet_null()} so that tests
126   * of {@link java.util.Collections#checkedCollection(java.util.Collection, Class)} can suppress it
127   * with {@code FeatureSpecificTestSuiteBuilder.suppressing()} until <a
128   * href="https://bugs.openjdk.org/browse/JDK-6409434">JDK-6409434</a> is fixed. It's unclear
129   * whether nulls were to be permitted or forbidden, but presumably the eventual fix will be to
130   * permit them, as it seems more likely that code would depend on that behavior than on the other.
131   * Thus, we say the bug is in set(), which fails to support null.
132   */
133  @J2ktIncompatible
134  @GwtIncompatible // reflection
135  public static Method getSetNullSupportedMethod() {
136    return getMethod(ListSetTester.class, "testSet_null");
137  }
138}