• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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;
18 
19 import static com.google.common.collect.BoundType.CLOSED;
20 import static com.google.common.truth.Truth.assertThat;
21 import static java.util.Collections.sort;
22 
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.annotations.GwtIncompatible;
25 import com.google.common.annotations.J2ktIncompatible;
26 import com.google.common.collect.testing.Helpers.NullsBeforeB;
27 import com.google.common.collect.testing.NavigableSetTestSuiteBuilder;
28 import com.google.common.collect.testing.TestStringSetGenerator;
29 import com.google.common.collect.testing.features.CollectionFeature;
30 import com.google.common.collect.testing.features.CollectionSize;
31 import com.google.common.collect.testing.google.MultisetFeature;
32 import com.google.common.collect.testing.google.SortedMultisetTestSuiteBuilder;
33 import com.google.common.collect.testing.google.TestStringMultisetGenerator;
34 import java.lang.reflect.Method;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.Comparator;
38 import java.util.List;
39 import java.util.Set;
40 import java.util.SortedSet;
41 import junit.framework.Test;
42 import junit.framework.TestCase;
43 import junit.framework.TestSuite;
44 import org.checkerframework.checker.nullness.qual.Nullable;
45 
46 /**
47  * Unit test for {@link TreeMultiset}.
48  *
49  * @author Neal Kanodia
50  */
51 @GwtCompatible(emulated = true)
52 @ElementTypesAreNonnullByDefault
53 public class TreeMultisetTest extends TestCase {
54 
55   @J2ktIncompatible
56   @GwtIncompatible // suite
suite()57   public static Test suite() {
58     TestSuite suite = new TestSuite();
59     suite.addTest(
60         SortedMultisetTestSuiteBuilder.using(
61                 new TestStringMultisetGenerator() {
62                   @Override
63                   protected Multiset<String> create(String[] elements) {
64                     return TreeMultiset.create(Arrays.asList(elements));
65                   }
66 
67                   @Override
68                   public List<String> order(List<String> insertionOrder) {
69                     return Ordering.natural().sortedCopy(insertionOrder);
70                   }
71                 })
72             .withFeatures(
73                 CollectionSize.ANY,
74                 CollectionFeature.KNOWN_ORDER,
75                 CollectionFeature.GENERAL_PURPOSE,
76                 CollectionFeature.SERIALIZABLE,
77                 CollectionFeature.ALLOWS_NULL_QUERIES,
78                 MultisetFeature.ENTRIES_ARE_VIEWS)
79             .named("TreeMultiset, Ordering.natural")
80             .createTestSuite());
81     suite.addTest(
82         SortedMultisetTestSuiteBuilder.using(
83                 new TestStringMultisetGenerator() {
84                   @Override
85                   protected Multiset<String> create(String[] elements) {
86                     Multiset<String> result = TreeMultiset.create(NullsBeforeB.INSTANCE);
87                     Collections.addAll(result, elements);
88                     return result;
89                   }
90 
91                   @Override
92                   public List<String> order(List<String> insertionOrder) {
93                     sort(insertionOrder, NullsBeforeB.INSTANCE);
94                     return insertionOrder;
95                   }
96                 })
97             .withFeatures(
98                 CollectionSize.ANY,
99                 CollectionFeature.KNOWN_ORDER,
100                 CollectionFeature.GENERAL_PURPOSE,
101                 CollectionFeature.SERIALIZABLE,
102                 CollectionFeature.ALLOWS_NULL_VALUES,
103                 MultisetFeature.ENTRIES_ARE_VIEWS)
104             .named("TreeMultiset, NullsBeforeB")
105             .createTestSuite());
106     suite.addTest(
107         NavigableSetTestSuiteBuilder.using(
108                 new TestStringSetGenerator() {
109                   @Override
110                   protected Set<String> create(String[] elements) {
111                     return TreeMultiset.create(Arrays.asList(elements)).elementSet();
112                   }
113 
114                   @Override
115                   public List<String> order(List<String> insertionOrder) {
116                     return Lists.newArrayList(Sets.newTreeSet(insertionOrder));
117                   }
118                 })
119             .named("TreeMultiset[Ordering.natural].elementSet")
120             .withFeatures(
121                 CollectionSize.ANY,
122                 CollectionFeature.REMOVE_OPERATIONS,
123                 CollectionFeature.ALLOWS_NULL_QUERIES)
124             .createTestSuite());
125     suite.addTestSuite(TreeMultisetTest.class);
126     return suite;
127   }
128 
testCreate()129   public void testCreate() {
130     TreeMultiset<String> multiset = TreeMultiset.create();
131     multiset.add("foo", 2);
132     multiset.add("bar");
133     assertEquals(3, multiset.size());
134     assertEquals(2, multiset.count("foo"));
135     assertEquals(Ordering.natural(), multiset.comparator());
136     assertEquals("[bar, foo x 2]", multiset.toString());
137   }
138 
testCreateWithComparator()139   public void testCreateWithComparator() {
140     Multiset<String> multiset = TreeMultiset.create(Collections.reverseOrder());
141     multiset.add("foo", 2);
142     multiset.add("bar");
143     assertEquals(3, multiset.size());
144     assertEquals(2, multiset.count("foo"));
145     assertEquals("[foo x 2, bar]", multiset.toString());
146   }
147 
testCreateFromIterable()148   public void testCreateFromIterable() {
149     Multiset<String> multiset = TreeMultiset.create(Arrays.asList("foo", "bar", "foo"));
150     assertEquals(3, multiset.size());
151     assertEquals(2, multiset.count("foo"));
152     assertEquals("[bar, foo x 2]", multiset.toString());
153   }
154 
testToString()155   public void testToString() {
156     Multiset<String> ms = TreeMultiset.create();
157     ms.add("a", 3);
158     ms.add("c", 1);
159     ms.add("b", 2);
160 
161     assertEquals("[a x 3, b x 2, c]", ms.toString());
162   }
163 
testElementSetSortedSetMethods()164   public void testElementSetSortedSetMethods() {
165     TreeMultiset<String> ms = TreeMultiset.create();
166     ms.add("c", 1);
167     ms.add("a", 3);
168     ms.add("b", 2);
169     SortedSet<String> elementSet = ms.elementSet();
170 
171     assertEquals("a", elementSet.first());
172     assertEquals("c", elementSet.last());
173     assertEquals(Ordering.natural(), elementSet.comparator());
174 
175     assertThat(elementSet.headSet("b")).containsExactly("a");
176     assertThat(elementSet.tailSet("b")).containsExactly("b", "c").inOrder();
177     assertThat(elementSet.subSet("a", "c")).containsExactly("a", "b").inOrder();
178   }
179 
testElementSetSubsetRemove()180   public void testElementSetSubsetRemove() {
181     TreeMultiset<String> ms = TreeMultiset.create();
182     ms.add("a", 1);
183     ms.add("b", 3);
184     ms.add("c", 2);
185     ms.add("d", 1);
186     ms.add("e", 3);
187     ms.add("f", 2);
188 
189     SortedSet<String> elementSet = ms.elementSet();
190     assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
191     SortedSet<String> subset = elementSet.subSet("b", "f");
192     assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
193 
194     assertTrue(subset.remove("c"));
195     assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
196     assertThat(subset).containsExactly("b", "d", "e").inOrder();
197     assertEquals(10, ms.size());
198 
199     assertFalse(subset.remove("a"));
200     assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
201     assertThat(subset).containsExactly("b", "d", "e").inOrder();
202     assertEquals(10, ms.size());
203   }
204 
testElementSetSubsetRemoveAll()205   public void testElementSetSubsetRemoveAll() {
206     TreeMultiset<String> ms = TreeMultiset.create();
207     ms.add("a", 1);
208     ms.add("b", 3);
209     ms.add("c", 2);
210     ms.add("d", 1);
211     ms.add("e", 3);
212     ms.add("f", 2);
213 
214     SortedSet<String> elementSet = ms.elementSet();
215     assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
216     SortedSet<String> subset = elementSet.subSet("b", "f");
217     assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
218 
219     assertTrue(subset.removeAll(Arrays.asList("a", "c")));
220     assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder();
221     assertThat(subset).containsExactly("b", "d", "e").inOrder();
222     assertEquals(10, ms.size());
223   }
224 
testElementSetSubsetRetainAll()225   public void testElementSetSubsetRetainAll() {
226     TreeMultiset<String> ms = TreeMultiset.create();
227     ms.add("a", 1);
228     ms.add("b", 3);
229     ms.add("c", 2);
230     ms.add("d", 1);
231     ms.add("e", 3);
232     ms.add("f", 2);
233 
234     SortedSet<String> elementSet = ms.elementSet();
235     assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
236     SortedSet<String> subset = elementSet.subSet("b", "f");
237     assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
238 
239     assertTrue(subset.retainAll(Arrays.asList("a", "c")));
240     assertThat(elementSet).containsExactly("a", "c", "f").inOrder();
241     assertThat(subset).containsExactly("c");
242     assertEquals(5, ms.size());
243   }
244 
testElementSetSubsetClear()245   public void testElementSetSubsetClear() {
246     TreeMultiset<String> ms = TreeMultiset.create();
247     ms.add("a", 1);
248     ms.add("b", 3);
249     ms.add("c", 2);
250     ms.add("d", 1);
251     ms.add("e", 3);
252     ms.add("f", 2);
253 
254     SortedSet<String> elementSet = ms.elementSet();
255     assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder();
256     SortedSet<String> subset = elementSet.subSet("b", "f");
257     assertThat(subset).containsExactly("b", "c", "d", "e").inOrder();
258 
259     subset.clear();
260     assertThat(elementSet).containsExactly("a", "f").inOrder();
261     assertThat(subset).isEmpty();
262     assertEquals(3, ms.size());
263   }
264 
testCustomComparator()265   public void testCustomComparator() throws Exception {
266     Comparator<String> comparator =
267         new Comparator<String>() {
268           @Override
269           public int compare(String o1, String o2) {
270             return o2.compareTo(o1);
271           }
272         };
273     TreeMultiset<String> ms = TreeMultiset.create(comparator);
274 
275     ms.add("b");
276     ms.add("c");
277     ms.add("a");
278     ms.add("b");
279     ms.add("d");
280 
281     assertThat(ms).containsExactly("d", "c", "b", "b", "a").inOrder();
282 
283     SortedSet<String> elementSet = ms.elementSet();
284     assertEquals("d", elementSet.first());
285     assertEquals("a", elementSet.last());
286     assertEquals(comparator, elementSet.comparator());
287   }
288 
testNullAcceptingComparator()289   public void testNullAcceptingComparator() throws Exception {
290     Comparator<@Nullable String> comparator = Ordering.<String>natural().<String>nullsFirst();
291     TreeMultiset<@Nullable String> ms = TreeMultiset.create(comparator);
292 
293     ms.add("b");
294     ms.add(null);
295     ms.add("a");
296     ms.add("b");
297     ms.add(null, 2);
298 
299     assertThat(ms).containsExactly(null, null, null, "a", "b", "b").inOrder();
300     assertEquals(3, ms.count(null));
301 
302     SortedSet<@Nullable String> elementSet = ms.elementSet();
303     assertEquals(null, elementSet.first());
304     assertEquals("b", elementSet.last());
305     assertEquals(comparator, elementSet.comparator());
306   }
307 
308   private static final Comparator<String> DEGENERATE_COMPARATOR =
309       new Comparator<String>() {
310         @Override
311         public int compare(String o1, String o2) {
312           return o1.length() - o2.length();
313         }
314       };
315 
316   /** Test a TreeMultiset with a comparator that can return 0 when comparing unequal values. */
testDegenerateComparator()317   public void testDegenerateComparator() throws Exception {
318     TreeMultiset<String> ms = TreeMultiset.create(DEGENERATE_COMPARATOR);
319 
320     ms.add("foo");
321     ms.add("a");
322     ms.add("bar");
323     ms.add("b");
324     ms.add("c");
325 
326     assertEquals(2, ms.count("bar"));
327     assertEquals(3, ms.count("b"));
328 
329     Multiset<String> ms2 = TreeMultiset.create(DEGENERATE_COMPARATOR);
330 
331     ms2.add("cat", 2);
332     ms2.add("x", 3);
333 
334     assertEquals(ms, ms2);
335     assertEquals(ms2, ms);
336 
337     SortedSet<String> elementSet = ms.elementSet();
338     assertEquals("a", elementSet.first());
339     assertEquals("foo", elementSet.last());
340     assertEquals(DEGENERATE_COMPARATOR, elementSet.comparator());
341   }
342 
testSubMultisetSize()343   public void testSubMultisetSize() {
344     TreeMultiset<String> ms = TreeMultiset.create();
345     ms.add("a", Integer.MAX_VALUE);
346     ms.add("b", Integer.MAX_VALUE);
347     ms.add("c", 3);
348 
349     assertEquals(Integer.MAX_VALUE, ms.count("a"));
350     assertEquals(Integer.MAX_VALUE, ms.count("b"));
351     assertEquals(3, ms.count("c"));
352 
353     assertEquals(Integer.MAX_VALUE, ms.headMultiset("c", CLOSED).size());
354     assertEquals(Integer.MAX_VALUE, ms.headMultiset("b", CLOSED).size());
355     assertEquals(Integer.MAX_VALUE, ms.headMultiset("a", CLOSED).size());
356 
357     assertEquals(3, ms.tailMultiset("c", CLOSED).size());
358     assertEquals(Integer.MAX_VALUE, ms.tailMultiset("b", CLOSED).size());
359     assertEquals(Integer.MAX_VALUE, ms.tailMultiset("a", CLOSED).size());
360   }
361 
362   @J2ktIncompatible
363   @GwtIncompatible // reflection
364   @AndroidIncompatible // Reflection bug, or actual binary compatibility problem?
testElementSetBridgeMethods()365   public void testElementSetBridgeMethods() {
366     for (Method m : TreeMultiset.class.getMethods()) {
367       if (m.getName().equals("elementSet") && m.getReturnType().equals(SortedSet.class)) {
368         return;
369       }
370     }
371     fail("No bridge method found");
372   }
373 }
374