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