• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 
17 package com.google.common.collect.testing.google;
18 
19 import static com.google.common.collect.testing.features.CollectionFeature.ALLOWS_NULL_VALUES;
20 import static com.google.common.collect.testing.features.CollectionFeature.RESTRICTS_ELEMENTS;
21 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ADD;
22 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
23 import static com.google.common.collect.testing.features.CollectionSize.SEVERAL;
24 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
25 
26 import com.google.common.annotations.GwtCompatible;
27 import com.google.common.collect.Multiset;
28 import com.google.common.collect.testing.features.CollectionFeature;
29 import com.google.common.collect.testing.features.CollectionSize;
30 
31 import java.lang.reflect.Method;
32 import java.util.Arrays;
33 import java.util.List;
34 
35 /**
36  * Common superclass for {@link MultisetSetCountUnconditionallyTester} and
37  * {@link MultisetSetCountConditionallyTester}. It is used by those testers to
38  * test calls to the unconditional {@code setCount()} method and calls to the
39  * conditional {@code setCount()} method when the expected present count is
40  * correct.
41  *
42  * @author Chris Povirk
43  */
44 @GwtCompatible
45 public abstract class AbstractMultisetSetCountTester<E>
46     extends AbstractMultisetTester<E> {
47   /*
48    * TODO: consider adding MultisetFeatures.SUPPORTS_SET_COUNT. Currently we
49    * assume that using setCount() to increase the count is permitted iff add()
50    * is permitted and similarly for decrease/remove(). We assume that a
51    * setCount() no-op is permitted if either add() or remove() is permitted,
52    * though we also allow it to "succeed" if neither is permitted.
53    */
54 
assertSetCount(E element, int count)55   private void assertSetCount(E element, int count) {
56     setCountCheckReturnValue(element, count);
57 
58     assertEquals(
59         "multiset.count() should return the value passed to setCount()",
60         count, getMultiset().count(element));
61 
62     int size = 0;
63     for (Multiset.Entry<E> entry : getMultiset().entrySet()) {
64       size += entry.getCount();
65     }
66     assertEquals(
67         "multiset.size() should be the sum of the counts of all entries",
68         size, getMultiset().size());
69   }
70 
71   /**
72    * Call the {@code setCount()} method under test, and check its return value.
73    */
setCountCheckReturnValue(E element, int count)74   abstract void setCountCheckReturnValue(E element, int count);
75 
76   /**
77    * Call the {@code setCount()} method under test, but do not check its return
78    * value. Callers should use this method over
79    * {@link #setCountCheckReturnValue(Object, int)} when they expect
80    * {@code setCount()} to throw an exception, as checking the return value
81    * could produce an incorrect error message like
82    * "setCount() should return the original count" instead of the message passed
83    * to a later invocation of {@code fail()}, like "setCount should throw
84    * UnsupportedOperationException."
85    */
setCountNoCheckReturnValue(E element, int count)86   abstract void setCountNoCheckReturnValue(E element, int count);
87 
assertSetCountIncreasingFailure(E element, int count)88   private void assertSetCountIncreasingFailure(E element, int count) {
89     try {
90       setCountNoCheckReturnValue(element, count);
91       fail("a call to multiset.setCount() to increase an element's count "
92           + "should throw");
93     } catch (UnsupportedOperationException expected) {
94     }
95   }
96 
assertSetCountDecreasingFailure(E element, int count)97   private void assertSetCountDecreasingFailure(E element, int count) {
98     try {
99       setCountNoCheckReturnValue(element, count);
100       fail("a call to multiset.setCount() to decrease an element's count "
101           + "should throw");
102     } catch (UnsupportedOperationException expected) {
103     }
104   }
105 
106   // Unconditional setCount no-ops.
107 
assertZeroToZero()108   private void assertZeroToZero() {
109     assertSetCount(samples.e3, 0);
110   }
111 
assertOneToOne()112   private void assertOneToOne() {
113     assertSetCount(samples.e0, 1);
114   }
115 
assertThreeToThree()116   private void assertThreeToThree() {
117     initThreeCopies();
118     assertSetCount(samples.e0, 3);
119   }
120 
121   @CollectionFeature.Require(SUPPORTS_ADD)
testSetCount_zeroToZero_addSupported()122   public void testSetCount_zeroToZero_addSupported() {
123     assertZeroToZero();
124   }
125 
126   @CollectionFeature.Require(SUPPORTS_REMOVE)
testSetCount_zeroToZero_removeSupported()127   public void testSetCount_zeroToZero_removeSupported() {
128     assertZeroToZero();
129   }
130 
131   @CollectionFeature.Require(absent = {SUPPORTS_ADD, SUPPORTS_REMOVE})
testSetCount_zeroToZero_unsupported()132   public void testSetCount_zeroToZero_unsupported() {
133     try {
134       assertZeroToZero();
135     } catch (UnsupportedOperationException tolerated) {
136     }
137   }
138 
139   @CollectionSize.Require(absent = ZERO)
140   @CollectionFeature.Require(SUPPORTS_ADD)
testSetCount_oneToOne_addSupported()141   public void testSetCount_oneToOne_addSupported() {
142     assertOneToOne();
143   }
144 
145   @CollectionSize.Require(absent = ZERO)
146   @CollectionFeature.Require(SUPPORTS_REMOVE)
testSetCount_oneToOne_removeSupported()147   public void testSetCount_oneToOne_removeSupported() {
148     assertOneToOne();
149   }
150 
151   @CollectionSize.Require(absent = ZERO)
152   @CollectionFeature.Require(absent = {SUPPORTS_ADD, SUPPORTS_REMOVE})
testSetCount_oneToOne_unsupported()153   public void testSetCount_oneToOne_unsupported() {
154     try {
155       assertOneToOne();
156     } catch (UnsupportedOperationException tolerated) {
157     }
158   }
159 
160   @CollectionSize.Require(SEVERAL)
161   @CollectionFeature.Require(SUPPORTS_ADD)
testSetCount_threeToThree_addSupported()162   public void testSetCount_threeToThree_addSupported() {
163     assertThreeToThree();
164   }
165 
166   @CollectionSize.Require(SEVERAL)
167   @CollectionFeature.Require(SUPPORTS_REMOVE)
testSetCount_threeToThree_removeSupported()168   public void testSetCount_threeToThree_removeSupported() {
169     assertThreeToThree();
170   }
171 
172   @CollectionSize.Require(SEVERAL)
173   @CollectionFeature.Require(absent = {SUPPORTS_ADD, SUPPORTS_REMOVE})
testSetCount_threeToThree_unsupported()174   public void testSetCount_threeToThree_unsupported() {
175     try {
176       assertThreeToThree();
177     } catch (UnsupportedOperationException tolerated) {
178     }
179   }
180 
181   // Unconditional setCount size increases:
182 
183   @CollectionFeature.Require(SUPPORTS_ADD)
testSetCount_zeroToOne_supported()184   public void testSetCount_zeroToOne_supported() {
185     assertSetCount(samples.e3, 1);
186   }
187 
188   @CollectionFeature.Require(SUPPORTS_ADD)
testSetCount_zeroToThree_supported()189   public void testSetCount_zeroToThree_supported() {
190     assertSetCount(samples.e3, 3);
191   }
192 
193   @CollectionSize.Require(absent = ZERO)
194   @CollectionFeature.Require(SUPPORTS_ADD)
testSetCount_oneToThree_supported()195   public void testSetCount_oneToThree_supported() {
196     assertSetCount(samples.e0, 3);
197   }
198 
199   @CollectionFeature.Require(absent = SUPPORTS_ADD)
testSetCount_zeroToOne_unsupported()200   public void testSetCount_zeroToOne_unsupported() {
201     assertSetCountIncreasingFailure(samples.e3, 1);
202   }
203 
204   @CollectionFeature.Require(absent = SUPPORTS_ADD)
testSetCount_zeroToThree_unsupported()205   public void testSetCount_zeroToThree_unsupported() {
206     assertSetCountIncreasingFailure(samples.e3, 3);
207   }
208 
209   @CollectionSize.Require(absent = ZERO)
210   @CollectionFeature.Require(absent = SUPPORTS_ADD)
testSetCount_oneToThree_unsupported()211   public void testSetCount_oneToThree_unsupported() {
212     assertSetCountIncreasingFailure(samples.e3, 3);
213   }
214 
215   // Unconditional setCount size decreases:
216 
217   @CollectionSize.Require(absent = ZERO)
218   @CollectionFeature.Require(SUPPORTS_REMOVE)
testSetCount_oneToZero_supported()219   public void testSetCount_oneToZero_supported() {
220     assertSetCount(samples.e0, 0);
221   }
222 
223   @CollectionSize.Require(SEVERAL)
224   @CollectionFeature.Require(SUPPORTS_REMOVE)
testSetCount_threeToZero_supported()225   public void testSetCount_threeToZero_supported() {
226     initThreeCopies();
227     assertSetCount(samples.e0, 0);
228   }
229 
230   @CollectionSize.Require(SEVERAL)
231   @CollectionFeature.Require(SUPPORTS_REMOVE)
testSetCount_threeToOne_supported()232   public void testSetCount_threeToOne_supported() {
233     initThreeCopies();
234     assertSetCount(samples.e0, 1);
235   }
236 
237   @CollectionSize.Require(absent = ZERO)
238   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
testSetCount_oneToZero_unsupported()239   public void testSetCount_oneToZero_unsupported() {
240     assertSetCountDecreasingFailure(samples.e0, 0);
241   }
242 
243   @CollectionSize.Require(SEVERAL)
244   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
testSetCount_threeToZero_unsupported()245   public void testSetCount_threeToZero_unsupported() {
246     initThreeCopies();
247     assertSetCountDecreasingFailure(samples.e0, 0);
248   }
249 
250   @CollectionSize.Require(SEVERAL)
251   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
testSetCount_threeToOne_unsupported()252   public void testSetCount_threeToOne_unsupported() {
253     initThreeCopies();
254     assertSetCountDecreasingFailure(samples.e0, 1);
255   }
256 
257   // setCount with nulls:
258 
259   @CollectionSize.Require(absent = ZERO)
260   @CollectionFeature.Require({SUPPORTS_REMOVE, ALLOWS_NULL_VALUES})
testSetCount_removeNull_nullSupported()261   public void testSetCount_removeNull_nullSupported() {
262     initCollectionWithNullElement();
263     assertSetCount(null, 0);
264   }
265 
266   @CollectionFeature.Require(value = {SUPPORTS_ADD, ALLOWS_NULL_VALUES},
267       absent = RESTRICTS_ELEMENTS)
testSetCount_addNull_nullSupported()268   public void testSetCount_addNull_nullSupported() {
269     assertSetCount(null, 1);
270   }
271 
272   @CollectionFeature.Require(value = SUPPORTS_ADD, absent = ALLOWS_NULL_VALUES)
testSetCount_addNull_nullUnsupported()273   public void testSetCount_addNull_nullUnsupported() {
274     try {
275       setCountNoCheckReturnValue(null, 1);
276       fail("adding null with setCount() should throw NullPointerException");
277     } catch (NullPointerException expected) {
278     }
279   }
280 
281   @CollectionFeature.Require(ALLOWS_NULL_VALUES)
testSetCount_noOpNull_nullSupported()282   public void testSetCount_noOpNull_nullSupported() {
283     try {
284       assertSetCount(null, 0);
285     } catch (UnsupportedOperationException tolerated) {
286     }
287   }
288 
289   @CollectionFeature.Require(absent = ALLOWS_NULL_VALUES)
testSetCount_noOpNull_nullUnsupported()290   public void testSetCount_noOpNull_nullUnsupported() {
291     try {
292       assertSetCount(null, 0);
293     } catch (NullPointerException tolerated) {
294     } catch (UnsupportedOperationException tolerated) {
295     }
296   }
297 
298   @CollectionSize.Require(absent = ZERO)
299   @CollectionFeature.Require(ALLOWS_NULL_VALUES)
testSetCount_existingNoNopNull_nullSupported()300   public void testSetCount_existingNoNopNull_nullSupported() {
301     initCollectionWithNullElement();
302     try {
303       assertSetCount(null, 1);
304     } catch (UnsupportedOperationException tolerated) {
305     }
306   }
307 
308   // Negative count.
309 
310   @CollectionFeature.Require(SUPPORTS_REMOVE)
testSetCount_negative_removeSupported()311   public void testSetCount_negative_removeSupported() {
312     try {
313       setCountNoCheckReturnValue(samples.e3, -1);
314       fail("calling setCount() with a negative count should throw "
315           + "IllegalArgumentException");
316     } catch (IllegalArgumentException expected) {
317     }
318   }
319 
320   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
testSetCount_negative_removeUnsupported()321   public void testSetCount_negative_removeUnsupported() {
322     try {
323       setCountNoCheckReturnValue(samples.e3, -1);
324       fail("calling setCount() with a negative count should throw "
325           + "IllegalArgumentException or UnsupportedOperationException");
326     } catch (IllegalArgumentException expected) {
327     } catch (UnsupportedOperationException expected) {
328     }
329   }
330 
331   // TODO: test adding element of wrong type
332 
333   /**
334    * Returns {@link Method} instances for the {@code setCount()} tests that
335    * assume multisets support duplicates so that the test of {@code
336    * Multisets.forSet()} can suppress them.
337    */
getSetCountDuplicateInitializingMethods()338   public static List<Method> getSetCountDuplicateInitializingMethods() {
339     return Arrays.asList(
340         getMethod("testSetCount_threeToThree_removeSupported"),
341         getMethod("testSetCount_threeToZero_supported"),
342         getMethod("testSetCount_threeToOne_supported"));
343   }
344 
getMethod(String methodName)345   private static Method getMethod(String methodName) {
346     return Platform.getMethod(AbstractMultisetSetCountTester.class, methodName);
347   }
348 }
349