• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11  * express or implied. See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 
15 package com.google.common.collect.testing.google;
16 
17 import static com.google.common.collect.BoundType.CLOSED;
18 import static com.google.common.collect.BoundType.OPEN;
19 import static com.google.common.collect.testing.Helpers.copyToList;
20 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_ADD;
21 import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE;
22 import static com.google.common.collect.testing.features.CollectionSize.ONE;
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.BoundType;
28 import com.google.common.collect.Iterators;
29 import com.google.common.collect.Multiset;
30 import com.google.common.collect.Multiset.Entry;
31 import com.google.common.collect.Multisets;
32 import com.google.common.collect.SortedMultiset;
33 import com.google.common.collect.testing.features.CollectionFeature;
34 import com.google.common.collect.testing.features.CollectionSize;
35 
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.NoSuchElementException;
41 
42 /**
43  * Tester for navigation of SortedMultisets.
44  *
45  * @author Louis Wasserman
46  */
47 @GwtCompatible
48 public class MultisetNavigationTester<E> extends AbstractMultisetTester<E> {
49   private SortedMultiset<E> sortedMultiset;
50   private List<E> entries;
51   private Entry<E> a;
52   private Entry<E> b;
53   private Entry<E> c;
54 
55   /**
56    * Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557
57    */
cast(Multiset<T> iterable)58   static <T> SortedMultiset<T> cast(Multiset<T> iterable) {
59     return (SortedMultiset<T>) iterable;
60   }
61 
62   @Override
setUp()63   public void setUp() throws Exception {
64     super.setUp();
65     sortedMultiset = cast(getMultiset());
66     entries =
67         copyToList(getSubjectGenerator().getSampleElements(
68             getSubjectGenerator().getCollectionSize().getNumElements()));
69     Collections.sort(entries, sortedMultiset.comparator());
70 
71     // some tests assume SEVERAL == 3
72     if (entries.size() >= 1) {
73       a = Multisets.immutableEntry(entries.get(0), sortedMultiset.count(entries.get(0)));
74       if (entries.size() >= 3) {
75         b = Multisets.immutableEntry(entries.get(1), sortedMultiset.count(entries.get(1)));
76         c = Multisets.immutableEntry(entries.get(2), sortedMultiset.count(entries.get(2)));
77       }
78     }
79   }
80 
81   /**
82    * Resets the contents of sortedMultiset to have entries a, c, for the navigation tests.
83    */
84   @SuppressWarnings("unchecked")
85   // Needed to stop Eclipse whining
resetWithHole()86   private void resetWithHole() {
87     List<E> container = new ArrayList<E>();
88     container.addAll(Collections.nCopies(a.getCount(), a.getElement()));
89     container.addAll(Collections.nCopies(c.getCount(), c.getElement()));
90     super.resetContainer(getSubjectGenerator().create(container.toArray()));
91     sortedMultiset = (SortedMultiset<E>) getMultiset();
92   }
93 
94   @CollectionSize.Require(ZERO)
testEmptyMultisetFirst()95   public void testEmptyMultisetFirst() {
96     assertNull(sortedMultiset.firstEntry());
97     try {
98       sortedMultiset.elementSet().first();
99       fail();
100     } catch (NoSuchElementException e) {}
101   }
102 
103   @CollectionFeature.Require(SUPPORTS_REMOVE)
104   @CollectionSize.Require(ZERO)
testEmptyMultisetPollFirst()105   public void testEmptyMultisetPollFirst() {
106     assertNull(sortedMultiset.pollFirstEntry());
107   }
108 
109   @CollectionSize.Require(ZERO)
testEmptyMultisetNearby()110   public void testEmptyMultisetNearby() {
111     for (BoundType type : BoundType.values()) {
112       assertNull(sortedMultiset.headMultiset(samples.e0, type).lastEntry());
113       assertNull(sortedMultiset.tailMultiset(samples.e0, type).firstEntry());
114     }
115   }
116 
117   @CollectionSize.Require(ZERO)
testEmptyMultisetLast()118   public void testEmptyMultisetLast() {
119     assertNull(sortedMultiset.lastEntry());
120     try {
121       assertNull(sortedMultiset.elementSet().last());
122       fail();
123     } catch (NoSuchElementException e) {}
124   }
125 
126   @CollectionFeature.Require(SUPPORTS_REMOVE)
127   @CollectionSize.Require(ZERO)
testEmptyMultisetPollLast()128   public void testEmptyMultisetPollLast() {
129     assertNull(sortedMultiset.pollLastEntry());
130   }
131 
132   @CollectionSize.Require(ONE)
testSingletonMultisetFirst()133   public void testSingletonMultisetFirst() {
134     assertEquals(a, sortedMultiset.firstEntry());
135   }
136 
137   @CollectionFeature.Require(SUPPORTS_REMOVE)
138   @CollectionSize.Require(ONE)
testSingletonMultisetPollFirst()139   public void testSingletonMultisetPollFirst() {
140     assertEquals(a, sortedMultiset.pollFirstEntry());
141     assertTrue(sortedMultiset.isEmpty());
142   }
143 
144   @CollectionSize.Require(ONE)
testSingletonMultisetNearby()145   public void testSingletonMultisetNearby() {
146     assertNull(sortedMultiset.headMultiset(samples.e0, OPEN).lastEntry());
147     assertNull(sortedMultiset.tailMultiset(samples.e0, OPEN).lastEntry());
148 
149     assertEquals(a, sortedMultiset.headMultiset(samples.e0, CLOSED).lastEntry());
150     assertEquals(a, sortedMultiset.tailMultiset(samples.e0, CLOSED).firstEntry());
151   }
152 
153   @CollectionSize.Require(ONE)
testSingletonMultisetLast()154   public void testSingletonMultisetLast() {
155     assertEquals(a, sortedMultiset.lastEntry());
156   }
157 
158   @CollectionFeature.Require(SUPPORTS_REMOVE)
159   @CollectionSize.Require(ONE)
testSingletonMultisetPollLast()160   public void testSingletonMultisetPollLast() {
161     assertEquals(a, sortedMultiset.pollLastEntry());
162     assertTrue(sortedMultiset.isEmpty());
163   }
164 
165   @CollectionSize.Require(SEVERAL)
testFirst()166   public void testFirst() {
167     assertEquals(a, sortedMultiset.firstEntry());
168   }
169 
170   @SuppressWarnings("unchecked")
171   @CollectionFeature.Require(SUPPORTS_REMOVE)
172   @CollectionSize.Require(SEVERAL)
testPollFirst()173   public void testPollFirst() {
174     assertEquals(a, sortedMultiset.pollFirstEntry());
175     assertEquals(Arrays.asList(b, c), copyToList(sortedMultiset.entrySet()));
176   }
177 
178   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
testPollFirstUnsupported()179   public void testPollFirstUnsupported() {
180     try {
181       sortedMultiset.pollFirstEntry();
182       fail();
183     } catch (UnsupportedOperationException e) {}
184   }
185 
186   @CollectionSize.Require(SEVERAL)
testLower()187   public void testLower() {
188     resetWithHole();
189     assertEquals(null, sortedMultiset.headMultiset(a.getElement(), OPEN).lastEntry());
190     assertEquals(a, sortedMultiset.headMultiset(b.getElement(), OPEN).lastEntry());
191     assertEquals(a, sortedMultiset.headMultiset(c.getElement(), OPEN).lastEntry());
192   }
193 
194   @CollectionSize.Require(SEVERAL)
testFloor()195   public void testFloor() {
196     resetWithHole();
197     assertEquals(a, sortedMultiset.headMultiset(a.getElement(), CLOSED).lastEntry());
198     assertEquals(a, sortedMultiset.headMultiset(b.getElement(), CLOSED).lastEntry());
199     assertEquals(c, sortedMultiset.headMultiset(c.getElement(), CLOSED).lastEntry());
200   }
201 
202   @CollectionSize.Require(SEVERAL)
testCeiling()203   public void testCeiling() {
204     resetWithHole();
205 
206     assertEquals(a, sortedMultiset.tailMultiset(a.getElement(), CLOSED).firstEntry());
207     assertEquals(c, sortedMultiset.tailMultiset(b.getElement(), CLOSED).firstEntry());
208     assertEquals(c, sortedMultiset.tailMultiset(c.getElement(), CLOSED).firstEntry());
209   }
210 
211   @CollectionSize.Require(SEVERAL)
testHigher()212   public void testHigher() {
213     resetWithHole();
214     assertEquals(c, sortedMultiset.tailMultiset(a.getElement(), OPEN).firstEntry());
215     assertEquals(c, sortedMultiset.tailMultiset(b.getElement(), OPEN).firstEntry());
216     assertEquals(null, sortedMultiset.tailMultiset(c.getElement(), OPEN).firstEntry());
217   }
218 
219   @CollectionSize.Require(SEVERAL)
testLast()220   public void testLast() {
221     assertEquals(c, sortedMultiset.lastEntry());
222   }
223 
224   @SuppressWarnings("unchecked")
225   @CollectionFeature.Require(SUPPORTS_REMOVE)
226   @CollectionSize.Require(SEVERAL)
testPollLast()227   public void testPollLast() {
228     assertEquals(c, sortedMultiset.pollLastEntry());
229     assertEquals(Arrays.asList(a, b), copyToList(sortedMultiset.entrySet()));
230   }
231 
232   @CollectionFeature.Require(absent = SUPPORTS_REMOVE)
233   @CollectionSize.Require(SEVERAL)
testPollLastUnsupported()234   public void testPollLastUnsupported() {
235     try {
236       sortedMultiset.pollLastEntry();
237       fail();
238     } catch (UnsupportedOperationException e) {}
239   }
240 
241   @CollectionSize.Require(SEVERAL)
testDescendingNavigation()242   public void testDescendingNavigation() {
243     List<Entry<E>> ascending = new ArrayList<Entry<E>>();
244     Iterators.addAll(ascending, sortedMultiset.entrySet().iterator());
245     List<Entry<E>> descending = new ArrayList<Entry<E>>();
246     Iterators.addAll(descending, sortedMultiset.descendingMultiset().entrySet().iterator());
247     Collections.reverse(descending);
248     assertEquals(ascending, descending);
249   }
250 
expectAddFailure(SortedMultiset<E> multiset, Entry<E> entry)251   void expectAddFailure(SortedMultiset<E> multiset, Entry<E> entry) {
252     try {
253       multiset.add(entry.getElement(), entry.getCount());
254       fail("Expected IllegalArgumentException");
255     } catch (IllegalArgumentException expected) {}
256 
257     try {
258       multiset.add(entry.getElement());
259       fail("Expected IllegalArgumentException");
260     } catch (IllegalArgumentException expected) {}
261 
262     try {
263       multiset.addAll(Collections.singletonList(entry.getElement()));
264       fail("Expected IllegalArgumentException");
265     } catch (IllegalArgumentException expected) {}
266   }
267 
expectRemoveZero(SortedMultiset<E> multiset, Entry<E> entry)268   void expectRemoveZero(SortedMultiset<E> multiset, Entry<E> entry) {
269     assertEquals(0, multiset.remove(entry.getElement(), entry.getCount()));
270     assertFalse(multiset.remove(entry.getElement()));
271     assertFalse(multiset.elementSet().remove(entry.getElement()));
272   }
273 
expectSetCountFailure(SortedMultiset<E> multiset, Entry<E> entry)274   void expectSetCountFailure(SortedMultiset<E> multiset, Entry<E> entry) {
275     try {
276       multiset.setCount(entry.getElement(), multiset.count(entry.getElement()));
277     } catch (IllegalArgumentException acceptable) {}
278     try {
279       multiset.setCount(entry.getElement(), multiset.count(entry.getElement()) + 1);
280       fail("Expected IllegalArgumentException");
281     } catch (IllegalArgumentException expected) {}
282   }
283 
284   @CollectionSize.Require(ONE)
285   @CollectionFeature.Require(SUPPORTS_ADD)
testAddOutOfTailBoundsOne()286   public void testAddOutOfTailBoundsOne() {
287     expectAddFailure(sortedMultiset.tailMultiset(a.getElement(), OPEN), a);
288   }
289 
290   @CollectionSize.Require(SEVERAL)
291   @CollectionFeature.Require(SUPPORTS_ADD)
testAddOutOfTailBoundsSeveral()292   public void testAddOutOfTailBoundsSeveral() {
293     expectAddFailure(sortedMultiset.tailMultiset(a.getElement(), OPEN), a);
294     expectAddFailure(sortedMultiset.tailMultiset(b.getElement(), CLOSED), a);
295     expectAddFailure(sortedMultiset.tailMultiset(b.getElement(), OPEN), a);
296     expectAddFailure(sortedMultiset.tailMultiset(b.getElement(), OPEN), b);
297     expectAddFailure(sortedMultiset.tailMultiset(c.getElement(), CLOSED), a);
298     expectAddFailure(sortedMultiset.tailMultiset(c.getElement(), CLOSED), b);
299     expectAddFailure(sortedMultiset.tailMultiset(c.getElement(), OPEN), a);
300     expectAddFailure(sortedMultiset.tailMultiset(c.getElement(), OPEN), b);
301     expectAddFailure(sortedMultiset.tailMultiset(c.getElement(), OPEN), c);
302   }
303 
304   @CollectionSize.Require(ONE)
305   @CollectionFeature.Require(SUPPORTS_ADD)
testAddOutOfHeadBoundsOne()306   public void testAddOutOfHeadBoundsOne() {
307     expectAddFailure(sortedMultiset.headMultiset(a.getElement(), OPEN), a);
308   }
309 
310   @CollectionSize.Require(SEVERAL)
311   @CollectionFeature.Require(SUPPORTS_ADD)
testAddOutOfHeadBoundsSeveral()312   public void testAddOutOfHeadBoundsSeveral() {
313     expectAddFailure(sortedMultiset.headMultiset(c.getElement(), OPEN), c);
314     expectAddFailure(sortedMultiset.headMultiset(b.getElement(), CLOSED), c);
315     expectAddFailure(sortedMultiset.headMultiset(b.getElement(), OPEN), c);
316     expectAddFailure(sortedMultiset.headMultiset(b.getElement(), OPEN), b);
317     expectAddFailure(sortedMultiset.headMultiset(a.getElement(), CLOSED), c);
318     expectAddFailure(sortedMultiset.headMultiset(a.getElement(), CLOSED), b);
319     expectAddFailure(sortedMultiset.headMultiset(a.getElement(), OPEN), c);
320     expectAddFailure(sortedMultiset.headMultiset(a.getElement(), OPEN), b);
321     expectAddFailure(sortedMultiset.headMultiset(a.getElement(), OPEN), a);
322   }
323 
324   @CollectionSize.Require(ONE)
325   @CollectionFeature.Require(SUPPORTS_REMOVE)
testRemoveOutOfTailBoundsOne()326   public void testRemoveOutOfTailBoundsOne() {
327     expectRemoveZero(sortedMultiset.tailMultiset(a.getElement(), OPEN), a);
328   }
329 
330   @CollectionSize.Require(SEVERAL)
331   @CollectionFeature.Require(SUPPORTS_REMOVE)
testRemoveOutOfTailBoundsSeveral()332   public void testRemoveOutOfTailBoundsSeveral() {
333     expectRemoveZero(sortedMultiset.tailMultiset(a.getElement(), OPEN), a);
334     expectRemoveZero(sortedMultiset.tailMultiset(b.getElement(), CLOSED), a);
335     expectRemoveZero(sortedMultiset.tailMultiset(b.getElement(), OPEN), a);
336     expectRemoveZero(sortedMultiset.tailMultiset(b.getElement(), OPEN), b);
337     expectRemoveZero(sortedMultiset.tailMultiset(c.getElement(), CLOSED), a);
338     expectRemoveZero(sortedMultiset.tailMultiset(c.getElement(), CLOSED), b);
339     expectRemoveZero(sortedMultiset.tailMultiset(c.getElement(), OPEN), a);
340     expectRemoveZero(sortedMultiset.tailMultiset(c.getElement(), OPEN), b);
341     expectRemoveZero(sortedMultiset.tailMultiset(c.getElement(), OPEN), c);
342   }
343 
344   @CollectionSize.Require(ONE)
345   @CollectionFeature.Require(SUPPORTS_REMOVE)
testRemoveOutOfHeadBoundsOne()346   public void testRemoveOutOfHeadBoundsOne() {
347     expectRemoveZero(sortedMultiset.headMultiset(a.getElement(), OPEN), a);
348   }
349 
350   @CollectionSize.Require(SEVERAL)
351   @CollectionFeature.Require(SUPPORTS_REMOVE)
testRemoveOutOfHeadBoundsSeveral()352   public void testRemoveOutOfHeadBoundsSeveral() {
353     expectRemoveZero(sortedMultiset.headMultiset(c.getElement(), OPEN), c);
354     expectRemoveZero(sortedMultiset.headMultiset(b.getElement(), CLOSED), c);
355     expectRemoveZero(sortedMultiset.headMultiset(b.getElement(), OPEN), c);
356     expectRemoveZero(sortedMultiset.headMultiset(b.getElement(), OPEN), b);
357     expectRemoveZero(sortedMultiset.headMultiset(a.getElement(), CLOSED), c);
358     expectRemoveZero(sortedMultiset.headMultiset(a.getElement(), CLOSED), b);
359     expectRemoveZero(sortedMultiset.headMultiset(a.getElement(), OPEN), c);
360     expectRemoveZero(sortedMultiset.headMultiset(a.getElement(), OPEN), b);
361     expectRemoveZero(sortedMultiset.headMultiset(a.getElement(), OPEN), a);
362   }
363 
364   @CollectionSize.Require(ONE)
365   @CollectionFeature.Require({SUPPORTS_ADD, SUPPORTS_REMOVE})
testSetCountOutOfTailBoundsOne()366   public void testSetCountOutOfTailBoundsOne() {
367     expectSetCountFailure(sortedMultiset.tailMultiset(a.getElement(), OPEN), a);
368   }
369 
370   @CollectionSize.Require(SEVERAL)
371   @CollectionFeature.Require({SUPPORTS_ADD, SUPPORTS_REMOVE})
testSetCountOutOfTailBoundsSeveral()372   public void testSetCountOutOfTailBoundsSeveral() {
373     expectSetCountFailure(sortedMultiset.tailMultiset(a.getElement(), OPEN), a);
374     expectSetCountFailure(sortedMultiset.tailMultiset(b.getElement(), CLOSED), a);
375     expectSetCountFailure(sortedMultiset.tailMultiset(b.getElement(), OPEN), a);
376     expectSetCountFailure(sortedMultiset.tailMultiset(b.getElement(), OPEN), b);
377     expectSetCountFailure(sortedMultiset.tailMultiset(c.getElement(), CLOSED), a);
378     expectSetCountFailure(sortedMultiset.tailMultiset(c.getElement(), CLOSED), b);
379     expectSetCountFailure(sortedMultiset.tailMultiset(c.getElement(), OPEN), a);
380     expectSetCountFailure(sortedMultiset.tailMultiset(c.getElement(), OPEN), b);
381     expectSetCountFailure(sortedMultiset.tailMultiset(c.getElement(), OPEN), c);
382   }
383 
384   @CollectionSize.Require(ONE)
385   @CollectionFeature.Require({SUPPORTS_ADD, SUPPORTS_REMOVE})
testSetCountOutOfHeadBoundsOne()386   public void testSetCountOutOfHeadBoundsOne() {
387     expectSetCountFailure(sortedMultiset.headMultiset(a.getElement(), OPEN), a);
388   }
389 
390   @CollectionSize.Require(SEVERAL)
391   @CollectionFeature.Require({SUPPORTS_ADD, SUPPORTS_REMOVE})
testSetCountOutOfHeadBoundsSeveral()392   public void testSetCountOutOfHeadBoundsSeveral() {
393     expectSetCountFailure(sortedMultiset.headMultiset(c.getElement(), OPEN), c);
394     expectSetCountFailure(sortedMultiset.headMultiset(b.getElement(), CLOSED), c);
395     expectSetCountFailure(sortedMultiset.headMultiset(b.getElement(), OPEN), c);
396     expectSetCountFailure(sortedMultiset.headMultiset(b.getElement(), OPEN), b);
397     expectSetCountFailure(sortedMultiset.headMultiset(a.getElement(), CLOSED), c);
398     expectSetCountFailure(sortedMultiset.headMultiset(a.getElement(), CLOSED), b);
399     expectSetCountFailure(sortedMultiset.headMultiset(a.getElement(), OPEN), c);
400     expectSetCountFailure(sortedMultiset.headMultiset(a.getElement(), OPEN), b);
401     expectSetCountFailure(sortedMultiset.headMultiset(a.getElement(), OPEN), a);
402   }
403 
404   @CollectionSize.Require(SEVERAL)
405   @CollectionFeature.Require(SUPPORTS_ADD)
testAddWithConflictingBounds()406   public void testAddWithConflictingBounds() {
407     testEmptyRangeSubMultisetSupportingAdd(sortedMultiset.subMultiset(a.getElement(), CLOSED,
408         a.getElement(), OPEN));
409     testEmptyRangeSubMultisetSupportingAdd(sortedMultiset.subMultiset(a.getElement(), OPEN,
410         a.getElement(), OPEN));
411     testEmptyRangeSubMultisetSupportingAdd(sortedMultiset.subMultiset(a.getElement(), OPEN,
412         a.getElement(), CLOSED));
413     testEmptyRangeSubMultisetSupportingAdd(sortedMultiset.subMultiset(b.getElement(), CLOSED,
414         a.getElement(), CLOSED));
415     testEmptyRangeSubMultisetSupportingAdd(sortedMultiset.subMultiset(b.getElement(), CLOSED,
416         a.getElement(), OPEN));
417     testEmptyRangeSubMultisetSupportingAdd(sortedMultiset.subMultiset(b.getElement(), OPEN,
418         a.getElement(), OPEN));
419   }
420 
421   @CollectionSize.Require(SEVERAL)
422   @CollectionFeature.Require(SUPPORTS_ADD)
testConflictingBounds()423   public void testConflictingBounds() {
424     testEmptyRangeSubMultiset(sortedMultiset.subMultiset(a.getElement(), CLOSED, a.getElement(),
425         OPEN));
426     testEmptyRangeSubMultiset(sortedMultiset.subMultiset(a.getElement(), OPEN, a.getElement(),
427         OPEN));
428     testEmptyRangeSubMultiset(sortedMultiset.subMultiset(a.getElement(), OPEN, a.getElement(),
429         CLOSED));
430     testEmptyRangeSubMultiset(sortedMultiset.subMultiset(b.getElement(), CLOSED, a.getElement(),
431         CLOSED));
432     testEmptyRangeSubMultiset(sortedMultiset.subMultiset(b.getElement(), CLOSED, a.getElement(),
433         OPEN));
434     testEmptyRangeSubMultiset(sortedMultiset.subMultiset(b.getElement(), OPEN, a.getElement(),
435         OPEN));
436   }
437 
testEmptyRangeSubMultiset(SortedMultiset<E> multiset)438   public void testEmptyRangeSubMultiset(SortedMultiset<E> multiset) {
439     assertTrue(multiset.isEmpty());
440     assertEquals(0, multiset.size());
441     assertEquals(0, multiset.toArray().length);
442     assertTrue(multiset.entrySet().isEmpty());
443     assertFalse(multiset.iterator().hasNext());
444     assertEquals(0, multiset.entrySet().size());
445     assertEquals(0, multiset.entrySet().toArray().length);
446     assertFalse(multiset.entrySet().iterator().hasNext());
447   }
448 
449   @SuppressWarnings("unchecked")
testEmptyRangeSubMultisetSupportingAdd(SortedMultiset<E> multiset)450   public void testEmptyRangeSubMultisetSupportingAdd(SortedMultiset<E> multiset) {
451     for (Entry<E> entry : Arrays.asList(a, b, c)) {
452       expectAddFailure(multiset, entry);
453     }
454   }
455 
totalSize(Iterable<? extends Entry<?>> entries)456   private int totalSize(Iterable<? extends Entry<?>> entries) {
457     int sum = 0;
458     for (Entry<?> entry : entries) {
459       sum += entry.getCount();
460     }
461     return sum;
462   }
463 
464   private enum SubMultisetSpec {
465     TAIL_CLOSED {
466       @Override
expectedEntries(int targetEntry, List<Entry<E>> entries)467       <E> List<Entry<E>> expectedEntries(int targetEntry, List<Entry<E>> entries) {
468         return entries.subList(targetEntry, entries.size());
469       }
470 
471       @Override
subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries, int targetEntry)472       <E> SortedMultiset<E> subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries,
473           int targetEntry) {
474         return multiset.tailMultiset(entries.get(targetEntry).getElement(), CLOSED);
475       }
476     },
477     TAIL_OPEN {
478       @Override
expectedEntries(int targetEntry, List<Entry<E>> entries)479       <E> List<Entry<E>> expectedEntries(int targetEntry, List<Entry<E>> entries) {
480         return entries.subList(targetEntry + 1, entries.size());
481       }
482 
483       @Override
subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries, int targetEntry)484       <E> SortedMultiset<E> subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries,
485           int targetEntry) {
486         return multiset.tailMultiset(entries.get(targetEntry).getElement(), OPEN);
487       }
488     },
489     HEAD_CLOSED {
490       @Override
expectedEntries(int targetEntry, List<Entry<E>> entries)491       <E> List<Entry<E>> expectedEntries(int targetEntry, List<Entry<E>> entries) {
492         return entries.subList(0, targetEntry + 1);
493       }
494 
495       @Override
subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries, int targetEntry)496       <E> SortedMultiset<E> subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries,
497           int targetEntry) {
498         return multiset.headMultiset(entries.get(targetEntry).getElement(), CLOSED);
499       }
500     },
501     HEAD_OPEN {
502       @Override
expectedEntries(int targetEntry, List<Entry<E>> entries)503       <E> List<Entry<E>> expectedEntries(int targetEntry, List<Entry<E>> entries) {
504         return entries.subList(0, targetEntry);
505       }
506 
507       @Override
subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries, int targetEntry)508       <E> SortedMultiset<E> subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries,
509           int targetEntry) {
510         return multiset.headMultiset(entries.get(targetEntry).getElement(), OPEN);
511       }
512     };
expectedEntries(int targetEntry, List<Entry<E>> entries)513     abstract <E> List<Entry<E>> expectedEntries(int targetEntry, List<Entry<E>> entries);
514 
subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries, int targetEntry)515     abstract <E> SortedMultiset<E> subMultiset(SortedMultiset<E> multiset, List<Entry<E>> entries,
516         int targetEntry);
517   }
518 
testSubMultisetEntrySet(SubMultisetSpec spec)519   private void testSubMultisetEntrySet(SubMultisetSpec spec) {
520     List<Entry<E>> entries = copyToList(sortedMultiset.entrySet());
521     for (int i = 0; i < entries.size(); i++) {
522       List<Entry<E>> expected = spec.expectedEntries(i, entries);
523       SortedMultiset<E> subMultiset = spec.subMultiset(sortedMultiset, entries, i);
524       assertEquals(expected, copyToList(subMultiset.entrySet()));
525     }
526   }
527 
testSubMultisetSize(SubMultisetSpec spec)528   private void testSubMultisetSize(SubMultisetSpec spec) {
529     List<Entry<E>> entries = copyToList(sortedMultiset.entrySet());
530     for (int i = 0; i < entries.size(); i++) {
531       List<Entry<E>> expected = spec.expectedEntries(i, entries);
532       SortedMultiset<E> subMultiset = spec.subMultiset(sortedMultiset, entries, i);
533       assertEquals(totalSize(expected), subMultiset.size());
534     }
535   }
536 
testSubMultisetDistinctElements(SubMultisetSpec spec)537   private void testSubMultisetDistinctElements(SubMultisetSpec spec) {
538     List<Entry<E>> entries = copyToList(sortedMultiset.entrySet());
539     for (int i = 0; i < entries.size(); i++) {
540       List<Entry<E>> expected = spec.expectedEntries(i, entries);
541       SortedMultiset<E> subMultiset = spec.subMultiset(sortedMultiset, entries, i);
542       assertEquals(expected.size(), subMultiset.entrySet().size());
543       assertEquals(expected.size(), subMultiset.elementSet().size());
544     }
545   }
546 
testTailClosedEntrySet()547   public void testTailClosedEntrySet() {
548     testSubMultisetEntrySet(SubMultisetSpec.TAIL_CLOSED);
549   }
550 
testTailClosedSize()551   public void testTailClosedSize() {
552     testSubMultisetSize(SubMultisetSpec.TAIL_CLOSED);
553   }
554 
testTailClosedDistinctElements()555   public void testTailClosedDistinctElements() {
556     testSubMultisetDistinctElements(SubMultisetSpec.TAIL_CLOSED);
557   }
558 
testTailOpenEntrySet()559   public void testTailOpenEntrySet() {
560     testSubMultisetEntrySet(SubMultisetSpec.TAIL_OPEN);
561   }
562 
testTailOpenSize()563   public void testTailOpenSize() {
564     testSubMultisetSize(SubMultisetSpec.TAIL_OPEN);
565   }
566 
testTailOpenDistinctElements()567   public void testTailOpenDistinctElements() {
568     testSubMultisetDistinctElements(SubMultisetSpec.TAIL_OPEN);
569   }
570 
testHeadClosedEntrySet()571   public void testHeadClosedEntrySet() {
572     testSubMultisetEntrySet(SubMultisetSpec.HEAD_CLOSED);
573   }
574 
testHeadClosedSize()575   public void testHeadClosedSize() {
576     testSubMultisetSize(SubMultisetSpec.HEAD_CLOSED);
577   }
578 
testHeadClosedDistinctElements()579   public void testHeadClosedDistinctElements() {
580     testSubMultisetDistinctElements(SubMultisetSpec.HEAD_CLOSED);
581   }
582 
testHeadOpenEntrySet()583   public void testHeadOpenEntrySet() {
584     testSubMultisetEntrySet(SubMultisetSpec.HEAD_OPEN);
585   }
586 
testHeadOpenSize()587   public void testHeadOpenSize() {
588     testSubMultisetSize(SubMultisetSpec.HEAD_OPEN);
589   }
590 
testHeadOpenDistinctElements()591   public void testHeadOpenDistinctElements() {
592     testSubMultisetDistinctElements(SubMultisetSpec.HEAD_OPEN);
593   }
594 
595   @CollectionSize.Require(SEVERAL)
596   @CollectionFeature.Require(SUPPORTS_REMOVE)
testClearTailOpen()597   public void testClearTailOpen() {
598     List<Entry<E>> expected =
599         copyToList(sortedMultiset.headMultiset(b.getElement(), CLOSED).entrySet());
600     sortedMultiset.tailMultiset(b.getElement(), OPEN).clear();
601     assertEquals(expected, copyToList(sortedMultiset.entrySet()));
602   }
603 
604   @CollectionSize.Require(SEVERAL)
605   @CollectionFeature.Require(SUPPORTS_REMOVE)
testClearTailOpenEntrySet()606   public void testClearTailOpenEntrySet() {
607     List<Entry<E>> expected =
608         copyToList(sortedMultiset.headMultiset(b.getElement(), CLOSED).entrySet());
609     sortedMultiset.tailMultiset(b.getElement(), OPEN).entrySet().clear();
610     assertEquals(expected, copyToList(sortedMultiset.entrySet()));
611   }
612 
613   @CollectionSize.Require(SEVERAL)
614   @CollectionFeature.Require(SUPPORTS_REMOVE)
testClearTailClosed()615   public void testClearTailClosed() {
616     List<Entry<E>> expected =
617         copyToList(sortedMultiset.headMultiset(b.getElement(), OPEN).entrySet());
618     sortedMultiset.tailMultiset(b.getElement(), CLOSED).clear();
619     assertEquals(expected, copyToList(sortedMultiset.entrySet()));
620   }
621 
622   @CollectionSize.Require(SEVERAL)
623   @CollectionFeature.Require(SUPPORTS_REMOVE)
testClearTailClosedEntrySet()624   public void testClearTailClosedEntrySet() {
625     List<Entry<E>> expected =
626         copyToList(sortedMultiset.headMultiset(b.getElement(), OPEN).entrySet());
627     sortedMultiset.tailMultiset(b.getElement(), CLOSED).entrySet().clear();
628     assertEquals(expected, copyToList(sortedMultiset.entrySet()));
629   }
630 
631   @CollectionSize.Require(SEVERAL)
632   @CollectionFeature.Require(SUPPORTS_REMOVE)
testClearHeadOpen()633   public void testClearHeadOpen() {
634     List<Entry<E>> expected =
635         copyToList(sortedMultiset.tailMultiset(b.getElement(), CLOSED).entrySet());
636     sortedMultiset.headMultiset(b.getElement(), OPEN).clear();
637     assertEquals(expected, copyToList(sortedMultiset.entrySet()));
638   }
639 
640   @CollectionSize.Require(SEVERAL)
641   @CollectionFeature.Require(SUPPORTS_REMOVE)
testClearHeadOpenEntrySet()642   public void testClearHeadOpenEntrySet() {
643     List<Entry<E>> expected =
644         copyToList(sortedMultiset.tailMultiset(b.getElement(), CLOSED).entrySet());
645     sortedMultiset.headMultiset(b.getElement(), OPEN).entrySet().clear();
646     assertEquals(expected, copyToList(sortedMultiset.entrySet()));
647   }
648 
649   @CollectionSize.Require(SEVERAL)
650   @CollectionFeature.Require(SUPPORTS_REMOVE)
testClearHeadClosed()651   public void testClearHeadClosed() {
652     List<Entry<E>> expected =
653         copyToList(sortedMultiset.tailMultiset(b.getElement(), OPEN).entrySet());
654     sortedMultiset.headMultiset(b.getElement(), CLOSED).clear();
655     assertEquals(expected, copyToList(sortedMultiset.entrySet()));
656   }
657 
658   @CollectionSize.Require(SEVERAL)
659   @CollectionFeature.Require(SUPPORTS_REMOVE)
testClearHeadClosedEntrySet()660   public void testClearHeadClosedEntrySet() {
661     List<Entry<E>> expected =
662         copyToList(sortedMultiset.tailMultiset(b.getElement(), OPEN).entrySet());
663     sortedMultiset.headMultiset(b.getElement(), CLOSED).entrySet().clear();
664     assertEquals(expected, copyToList(sortedMultiset.entrySet()));
665   }
666 }
667