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
17package com.google.common.collect;
18
19import static com.google.common.truth.Truth.assertThat;
20
21import com.google.common.annotations.GwtCompatible;
22import com.google.common.annotations.GwtIncompatible;
23import com.google.common.collect.testing.DerivedComparable;
24import com.google.common.testing.NullPointerTester;
25
26import junit.framework.TestCase;
27
28import java.util.Arrays;
29import java.util.Collections;
30import java.util.List;
31
32/**
33 * Tests for {@link Multisets}.
34 *
35 * @author Mike Bostock
36 * @author Jared Levy
37 * @author Louis Wasserman
38 */
39@GwtCompatible(emulated = true)
40public class MultisetsTest extends TestCase {
41
42  /* See MultisetsImmutableEntryTest for immutableEntry() tests. */
43
44  public void testNewTreeMultisetDerived() {
45    TreeMultiset<DerivedComparable> set = TreeMultiset.create();
46    assertTrue(set.isEmpty());
47    set.add(new DerivedComparable("foo"), 2);
48    set.add(new DerivedComparable("bar"), 3);
49    assertThat(set).has().exactly(
50        new DerivedComparable("bar"), new DerivedComparable("bar"), new DerivedComparable("bar"),
51        new DerivedComparable("foo"), new DerivedComparable("foo")).inOrder();
52  }
53
54  public void testNewTreeMultisetNonGeneric() {
55    TreeMultiset<LegacyComparable> set = TreeMultiset.create();
56    assertTrue(set.isEmpty());
57    set.add(new LegacyComparable("foo"), 2);
58    set.add(new LegacyComparable("bar"), 3);
59    assertThat(set).has().exactly(new LegacyComparable("bar"),
60        new LegacyComparable("bar"), new LegacyComparable("bar"),
61        new LegacyComparable("foo"), new LegacyComparable("foo")).inOrder();
62  }
63
64  public void testNewTreeMultisetComparator() {
65    TreeMultiset<String> multiset
66        = TreeMultiset.create(Collections.reverseOrder());
67    multiset.add("bar", 3);
68    multiset.add("foo", 2);
69    assertThat(multiset).has().exactly("foo", "foo", "bar", "bar", "bar").inOrder();
70  }
71
72  public void testRetainOccurrencesEmpty() {
73    Multiset<String> multiset = HashMultiset.create();
74    Multiset<String> toRetain =
75        HashMultiset.create(Arrays.asList("a", "b", "a"));
76    assertFalse(Multisets.retainOccurrences(multiset, toRetain));
77    assertThat(multiset).isEmpty();
78  }
79
80  public void testRemoveOccurrencesIterableEmpty() {
81    Multiset<String> multiset = HashMultiset.create();
82    Iterable<String> toRemove = Arrays.asList("a", "b", "a");
83    assertFalse(Multisets.removeOccurrences(multiset, toRemove));
84    assertTrue(multiset.isEmpty());
85  }
86
87  public void testRemoveOccurrencesMultisetEmpty() {
88    Multiset<String> multiset = HashMultiset.create();
89    Multiset<String> toRemove =
90        HashMultiset.create(Arrays.asList("a", "b", "a"));
91    assertFalse(Multisets.retainOccurrences(multiset, toRemove));
92    assertTrue(multiset.isEmpty());
93  }
94
95  public void testUnion() {
96    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
97    Multiset<String> ms2 = HashMultiset.create(
98        Arrays.asList("a", "b", "b", "c"));
99    assertThat(Multisets.union(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
100  }
101
102  public void testUnionEqualMultisets() {
103    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
104    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
105    assertEquals(ms1, Multisets.union(ms1, ms2));
106  }
107
108  public void testUnionEmptyNonempty() {
109    Multiset<String> ms1 = HashMultiset.create();
110    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
111    assertEquals(ms2, Multisets.union(ms1, ms2));
112  }
113
114  public void testUnionNonemptyEmpty() {
115    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
116    Multiset<String> ms2 = HashMultiset.create();
117    assertEquals(ms1, Multisets.union(ms1, ms2));
118  }
119
120  public void testIntersectEmptyNonempty() {
121    Multiset<String> ms1 = HashMultiset.create();
122    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
123    assertThat(Multisets.intersection(ms1, ms2)).isEmpty();
124  }
125
126  public void testIntersectNonemptyEmpty() {
127    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
128    Multiset<String> ms2 = HashMultiset.create();
129    assertThat(Multisets.intersection(ms1, ms2)).isEmpty();
130  }
131
132  public void testSum() {
133    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
134    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b", "c"));
135    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "a", "b", "b", "c");
136  }
137
138  public void testSumEmptyNonempty() {
139    Multiset<String> ms1 = HashMultiset.create();
140    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
141    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
142  }
143
144  public void testSumNonemptyEmpty() {
145    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
146    Multiset<String> ms2 = HashMultiset.create();
147    assertThat(Multisets.sum(ms1, ms2)).has().exactly("a", "b", "a");
148  }
149
150  public void testDifferenceWithNoRemovedElements() {
151    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
152    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a"));
153    assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "b");
154  }
155
156  public void testDifferenceWithRemovedElement() {
157    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
158    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("b"));
159    assertThat(Multisets.difference(ms1, ms2)).has().exactly("a", "a");
160  }
161
162  public void testDifferenceWithMoreElementsInSecondMultiset() {
163    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
164    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "b", "b"));
165    Multiset<String> diff = Multisets.difference(ms1, ms2);
166    assertThat(diff).has().item("a");
167    assertEquals(0, diff.count("b"));
168    assertEquals(1, diff.count("a"));
169    assertFalse(diff.contains("b"));
170    assertTrue(diff.contains("a"));
171  }
172
173  public void testDifferenceEmptyNonempty() {
174    Multiset<String> ms1 = HashMultiset.create();
175    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
176    assertEquals(ms1, Multisets.difference(ms1, ms2));
177  }
178
179  public void testDifferenceNonemptyEmpty() {
180    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
181    Multiset<String> ms2 = HashMultiset.create();
182    assertEquals(ms1, Multisets.difference(ms1, ms2));
183  }
184
185  public void testContainsOccurrencesEmpty() {
186    Multiset<String> superMultiset = HashMultiset.create(Arrays.asList("a", "b", "a"));
187    Multiset<String> subMultiset = HashMultiset.create();
188    assertTrue(Multisets.containsOccurrences(superMultiset, subMultiset));
189    assertFalse(Multisets.containsOccurrences(subMultiset, superMultiset));
190  }
191
192  public void testContainsOccurrences() {
193    Multiset<String> superMultiset = HashMultiset.create(Arrays.asList("a", "b", "a"));
194    Multiset<String> subMultiset = HashMultiset.create(Arrays.asList("a", "b"));
195    assertTrue(Multisets.containsOccurrences(superMultiset, subMultiset));
196    assertFalse(Multisets.containsOccurrences(subMultiset, superMultiset));
197    Multiset<String> diffMultiset = HashMultiset.create(Arrays.asList("a", "b", "c"));
198    assertFalse(Multisets.containsOccurrences(superMultiset, diffMultiset));
199    assertTrue(Multisets.containsOccurrences(diffMultiset, subMultiset));
200  }
201
202  public void testRetainEmptyOccurrences() {
203    Multiset<String> multiset =
204        HashMultiset.create(Arrays.asList("a", "b", "a"));
205    Multiset<String> toRetain = HashMultiset.create();
206    assertTrue(Multisets.retainOccurrences(multiset, toRetain));
207    assertTrue(multiset.isEmpty());
208  }
209
210  public void testRetainOccurrences() {
211    Multiset<String> multiset =
212        TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
213    Multiset<String> toRetain =
214        HashMultiset.create(Arrays.asList("a", "b", "b"));
215    assertTrue(Multisets.retainOccurrences(multiset, toRetain));
216    assertThat(multiset).has().exactly("a", "b").inOrder();
217  }
218
219  public void testRemoveEmptyOccurrencesMultiset() {
220    Multiset<String> multiset =
221        TreeMultiset.create(Arrays.asList("a", "b", "a"));
222    Multiset<String> toRemove = HashMultiset.create();
223    assertFalse(Multisets.removeOccurrences(multiset, toRemove));
224    assertThat(multiset).has().exactly("a", "a", "b").inOrder();
225  }
226
227  public void testRemoveOccurrencesMultiset() {
228    Multiset<String> multiset =
229        TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
230    Multiset<String> toRemove =
231        HashMultiset.create(Arrays.asList("a", "b", "b"));
232    assertTrue(Multisets.removeOccurrences(multiset, toRemove));
233    assertThat(multiset).has().exactly("a", "c").inOrder();
234  }
235
236  public void testRemoveEmptyOccurrencesIterable() {
237    Multiset<String> multiset =
238        TreeMultiset.create(Arrays.asList("a", "b", "a"));
239    Iterable<String> toRemove = ImmutableList.of();
240    assertFalse(Multisets.removeOccurrences(multiset, toRemove));
241    assertThat(multiset).has().exactly("a", "a", "b").inOrder();
242  }
243
244  public void testRemoveOccurrencesMultisetIterable() {
245    Multiset<String> multiset =
246        TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
247    List<String> toRemove = Arrays.asList("a", "b", "b");
248    assertTrue(Multisets.removeOccurrences(multiset, toRemove));
249    assertThat(multiset).has().exactly("a", "c").inOrder();
250  }
251
252  @SuppressWarnings("deprecation")
253  public void testUnmodifiableMultisetShortCircuit() {
254    Multiset<String> mod = HashMultiset.create();
255    Multiset<String> unmod = Multisets.unmodifiableMultiset(mod);
256    assertNotSame(mod, unmod);
257    assertSame(unmod, Multisets.unmodifiableMultiset(unmod));
258    ImmutableMultiset<String> immutable = ImmutableMultiset.of("a", "a", "b", "a");
259    assertSame(immutable, Multisets.unmodifiableMultiset(immutable));
260    assertSame(immutable, Multisets.unmodifiableMultiset((Multiset<String>) immutable));
261  }
262
263  public void testHighestCountFirst() {
264    Multiset<String> multiset = HashMultiset.create(
265        Arrays.asList("a", "a", "a", "b", "c", "c"));
266    ImmutableMultiset<String> sortedMultiset =
267        Multisets.copyHighestCountFirst(multiset);
268
269    assertThat(sortedMultiset.entrySet()).has().exactly(
270        Multisets.immutableEntry("a", 3), Multisets.immutableEntry("c", 2),
271        Multisets.immutableEntry("b", 1)).inOrder();
272
273    assertThat(sortedMultiset).has().exactly(
274        "a",
275        "a",
276        "a",
277        "c",
278        "c",
279        "b").inOrder();
280
281    assertThat(Multisets.copyHighestCountFirst(ImmutableMultiset.of())).isEmpty();
282  }
283
284  @GwtIncompatible("NullPointerTester")
285  public void testNullPointers() {
286    new NullPointerTester().testAllPublicStaticMethods(Multisets.class);
287  }
288}
289