001/*
002 * Copyright (C) 2013 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.google;
018
019import static com.google.common.collect.testing.Helpers.assertEmpty;
020import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_QUERIES;
021import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
022import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
023import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
024import static com.google.common.collect.testing.features.CollectionSize.ZERO;
025
026import com.google.common.annotations.GwtCompatible;
027import com.google.common.annotations.GwtIncompatible;
028import com.google.common.annotations.J2ktIncompatible;
029import com.google.common.collect.testing.Helpers;
030import com.google.common.collect.testing.WrongType;
031import com.google.common.collect.testing.features.CollectionFeature;
032import com.google.common.collect.testing.features.CollectionSize;
033import java.lang.reflect.Method;
034import java.util.Arrays;
035import java.util.Collections;
036import java.util.List;
037import org.junit.Ignore;
038
039/**
040 * Tests for {@code Multiset#remove}, {@code Multiset.removeAll}, and {@code Multiset.retainAll} not
041 * already covered by the corresponding Collection testers.
042 *
043 * @author Jared Levy
044 */
045@GwtCompatible(emulated = true)
046@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests.
047@SuppressWarnings("JUnit4ClassUsedInJUnit3")
048public class MultisetRemoveTester<E> extends AbstractMultisetTester<E> {
049  @CollectionFeature.Require(SUPPORTS_REMOVE)
050  public void testRemoveNegative() {
051    try {
052      getMultiset().remove(e0(), -1);
053      fail("Expected IllegalArgumentException");
054    } catch (IllegalArgumentException expected) {
055    }
056    expectUnchanged();
057  }
058
059  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
060  public void testRemoveUnsupported() {
061    try {
062      getMultiset().remove(e0(), 2);
063      fail("Expected UnsupportedOperationException");
064    } catch (UnsupportedOperationException expected) {
065    }
066  }
067
068  @CollectionFeature.Require(SUPPORTS_REMOVE)
069  public void testRemoveZeroNoOp() {
070    int originalCount = getMultiset().count(e0());
071    assertEquals("old count", originalCount, getMultiset().remove(e0(), 0));
072    expectUnchanged();
073  }
074
075  @CollectionSize.Require(absent = ZERO)
076  @CollectionFeature.Require(SUPPORTS_REMOVE)
077  public void testRemove_occurrences_present() {
078    assertEquals(
079        "multiset.remove(present, 2) didn't return the old count",
080        1,
081        getMultiset().remove(e0(), 2));
082    assertFalse(
083        "multiset contains present after multiset.remove(present, 2)",
084        getMultiset().contains(e0()));
085    assertEquals(0, getMultiset().count(e0()));
086  }
087
088  @CollectionSize.Require(SEVERAL)
089  @CollectionFeature.Require(SUPPORTS_REMOVE)
090  public void testRemove_some_occurrences_present() {
091    initThreeCopies();
092    assertEquals(
093        "multiset.remove(present, 2) didn't return the old count",
094        3,
095        getMultiset().remove(e0(), 2));
096    assertTrue(
097        "multiset contains present after multiset.remove(present, 2)",
098        getMultiset().contains(e0()));
099    assertEquals(1, getMultiset().count(e0()));
100  }
101
102  @CollectionFeature.Require(SUPPORTS_REMOVE)
103  public void testRemove_occurrences_absent() {
104    int distinct = getMultiset().elementSet().size();
105    assertEquals("multiset.remove(absent, 0) didn't return 0", 0, getMultiset().remove(e3(), 2));
106    assertEquals(distinct, getMultiset().elementSet().size());
107  }
108
109  @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
110  public void testRemove_occurrences_unsupported_absent() {
111    // notice: we don't care whether it succeeds, or fails with UOE
112    try {
113      assertEquals(
114          "multiset.remove(absent, 2) didn't return 0 or throw an exception",
115          0,
116          getMultiset().remove(e3(), 2));
117    } catch (UnsupportedOperationException ok) {
118    }
119  }
120
121  @CollectionFeature.Require(SUPPORTS_REMOVE)
122  public void testRemove_occurrences_0() {
123    int oldCount = getMultiset().count(e0());
124    assertEquals(
125        "multiset.remove(E, 0) didn't return the old count",
126        oldCount,
127        getMultiset().remove(e0(), 0));
128  }
129
130  @CollectionFeature.Require(SUPPORTS_REMOVE)
131  public void testRemove_occurrences_negative() {
132    try {
133      getMultiset().remove(e0(), -1);
134      fail("multiset.remove(E, -1) didn't throw an exception");
135    } catch (IllegalArgumentException required) {
136    }
137  }
138
139  @CollectionFeature.Require(SUPPORTS_REMOVE)
140  public void testRemove_occurrences_wrongType() {
141    assertEquals(
142        "multiset.remove(wrongType, 1) didn't return 0",
143        0,
144        getMultiset().remove(WrongType.VALUE, 1));
145  }
146
147  @CollectionSize.Require(absent = ZERO)
148  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
149  public void testRemove_nullPresent() {
150    initCollectionWithNullElement();
151    assertEquals(1, getMultiset().remove(null, 2));
152    assertFalse(
153        "multiset contains present after multiset.remove(present, 2)",
154        getMultiset().contains(null));
155    assertEquals(0, getMultiset().count(null));
156  }
157
158  @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_QUERIES})
159  public void testRemove_nullAbsent() {
160    assertEquals(0, getMultiset().remove(null, 2));
161  }
162
163  @CollectionFeature.Require(value = SUPPORTS_REMOVE, absent = ALLOWS_NULL_QUERIES)
164  public void testRemove_nullForbidden() {
165    try {
166      getMultiset().remove(null, 2);
167      fail("Expected NullPointerException");
168    } catch (NullPointerException expected) {
169    }
170  }
171
172  @CollectionSize.Require(SEVERAL)
173  @CollectionFeature.Require(SUPPORTS_REMOVE)
174  public void testRemoveAllIgnoresCount() {
175    initThreeCopies();
176    assertTrue(getMultiset().removeAll(Collections.singleton(e0())));
177    assertEmpty(getMultiset());
178  }
179
180  @CollectionSize.Require(SEVERAL)
181  @CollectionFeature.Require(SUPPORTS_REMOVE)
182  public void testRetainAllIgnoresCount() {
183    initThreeCopies();
184    List<E> contents = Helpers.copyToList(getMultiset());
185    assertFalse(getMultiset().retainAll(Collections.singleton(e0())));
186    expectContents(contents);
187  }
188
189  /**
190   * Returns {@link Method} instances for the remove tests that assume multisets support duplicates
191   * so that the test of {@code Multisets.forSet()} can suppress them.
192   */
193  @J2ktIncompatible
194  @GwtIncompatible // reflection
195  public static List<Method> getRemoveDuplicateInitializingMethods() {
196    return Arrays.asList(
197        Helpers.getMethod(MultisetRemoveTester.class, "testRemove_some_occurrences_present"));
198  }
199}