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 org.junit.contrib.truth.Truth.ASSERT;
20import static com.google.common.testing.SerializableTester.reserializeAndAssert;
21
22import java.util.Arrays;
23import java.util.Collections;
24import java.util.HashSet;
25import java.util.Set;
26
27import junit.framework.TestCase;
28
29import com.google.common.annotations.GwtCompatible;
30import com.google.common.annotations.GwtIncompatible;
31import com.google.common.collect.testing.DerivedComparable;
32import com.google.common.testing.NullPointerTester;
33
34/**
35 * Tests for {@link Multisets}.
36 *
37 * @author Mike Bostock
38 * @author Jared Levy
39 * @author Louis Wasserman
40 */
41@GwtCompatible(emulated = true)
42public class MultisetsTest extends TestCase {
43
44  /* See MultisetsImmutableEntryTest for immutableEntry() tests. */
45
46  public void testForSet() {
47    Set<String> set = new HashSet<String>();
48    set.add("foo");
49    set.add("bar");
50    set.add(null);
51    Multiset<String> multiset = HashMultiset.create();
52    multiset.addAll(set);
53    Multiset<String> multisetView = Multisets.forSet(set);
54    assertTrue(multiset.equals(multisetView));
55    assertTrue(multisetView.equals(multiset));
56    assertEquals(multiset.toString(), multisetView.toString());
57    assertEquals(multiset.hashCode(), multisetView.hashCode());
58    assertEquals(multiset.size(), multisetView.size());
59    assertTrue(multisetView.contains("foo"));
60    assertEquals(set, multisetView.elementSet());
61    assertEquals(multisetView.elementSet(), set);
62    assertEquals(multiset.elementSet(), multisetView.elementSet());
63    assertEquals(multisetView.elementSet(), multiset.elementSet());
64    try {
65      multisetView.add("baz");
66      fail("UnsupportedOperationException expected");
67    } catch (UnsupportedOperationException expected) {}
68    try {
69      multisetView.addAll(Collections.singleton("baz"));
70      fail("UnsupportedOperationException expected");
71    } catch (UnsupportedOperationException expected) {}
72    try {
73      multisetView.elementSet().add("baz");
74      fail("UnsupportedOperationException expected");
75    } catch (UnsupportedOperationException expected) {}
76    try {
77      multisetView.elementSet().addAll(Collections.singleton("baz"));
78      fail("UnsupportedOperationException expected");
79    } catch (UnsupportedOperationException expected) {}
80    multisetView.remove("bar");
81    assertFalse(multisetView.contains("bar"));
82    assertFalse(set.contains("bar"));
83    assertEquals(set, multisetView.elementSet());
84    ASSERT.that(multisetView.elementSet()).hasContentsAnyOrder("foo", null);
85    ASSERT.that(multisetView.entrySet()).hasContentsAnyOrder(
86        Multisets.immutableEntry("foo", 1), Multisets.immutableEntry((String) null, 1));
87    multisetView.clear();
88    assertFalse(multisetView.contains("foo"));
89    assertFalse(set.contains("foo"));
90    assertTrue(set.isEmpty());
91    assertTrue(multisetView.isEmpty());
92    multiset.clear();
93    assertEquals(multiset.toString(), multisetView.toString());
94    assertEquals(multiset.hashCode(), multisetView.hashCode());
95    assertEquals(multiset.size(), multisetView.size());
96  }
97
98  @GwtIncompatible("SerializableTester")
99  public void testForSetSerialization() {
100    Set<String> set = new HashSet<String>();
101    set.add("foo");
102    set.add("bar");
103    set.add(null);
104    Multiset<String> multiset = HashMultiset.create();
105    multiset.addAll(set);
106    Multiset<String> multisetView = Multisets.forSet(set);
107    assertTrue(multiset.equals(multisetView));
108    reserializeAndAssert(multisetView);
109  }
110
111  public void testNewTreeMultisetDerived() {
112    TreeMultiset<DerivedComparable> set = TreeMultiset.create();
113    assertTrue(set.isEmpty());
114    set.add(new DerivedComparable("foo"), 2);
115    set.add(new DerivedComparable("bar"), 3);
116    ASSERT.that(set).hasContentsInOrder(
117        new DerivedComparable("bar"), new DerivedComparable("bar"), new DerivedComparable("bar"),
118        new DerivedComparable("foo"), new DerivedComparable("foo"));
119  }
120
121  public void testNewTreeMultisetNonGeneric() {
122    TreeMultiset<LegacyComparable> set = TreeMultiset.create();
123    assertTrue(set.isEmpty());
124    set.add(new LegacyComparable("foo"), 2);
125    set.add(new LegacyComparable("bar"), 3);
126    ASSERT.that(set).hasContentsInOrder(new LegacyComparable("bar"),
127        new LegacyComparable("bar"), new LegacyComparable("bar"),
128        new LegacyComparable("foo"), new LegacyComparable("foo"));
129  }
130
131  public void testNewTreeMultisetComparator() {
132    TreeMultiset<String> multiset
133        = TreeMultiset.create(Collections.reverseOrder());
134    multiset.add("bar", 3);
135    multiset.add("foo", 2);
136    ASSERT.that(multiset).hasContentsInOrder("foo", "foo", "bar", "bar", "bar");
137  }
138
139  public void testRetainOccurrencesEmpty() {
140    Multiset<String> multiset = HashMultiset.create();
141    Multiset<String> toRetain =
142        HashMultiset.create(Arrays.asList("a", "b", "a"));
143    assertFalse(Multisets.retainOccurrences(multiset, toRetain));
144    ASSERT.that(multiset).hasContentsInOrder();
145  }
146
147  public void testRemoveOccurrencesEmpty() {
148    Multiset<String> multiset = HashMultiset.create();
149    Multiset<String> toRemove =
150        HashMultiset.create(Arrays.asList("a", "b", "a"));
151    assertFalse(Multisets.retainOccurrences(multiset, toRemove));
152    assertTrue(multiset.isEmpty());
153  }
154
155  public void testIntersectEmptyNonempty() {
156    Multiset<String> ms1 = HashMultiset.create();
157    Multiset<String> ms2 = HashMultiset.create(Arrays.asList("a", "b", "a"));
158    ASSERT.that(Multisets.intersection(ms1, ms2)).hasContentsInOrder();
159  }
160
161  public void testIntersectNonemptyEmpty() {
162    Multiset<String> ms1 = HashMultiset.create(Arrays.asList("a", "b", "a"));
163    Multiset<String> ms2 = HashMultiset.create();
164    ASSERT.that(Multisets.intersection(ms1, ms2)).hasContentsInOrder();
165  }
166
167  public void testContainsOccurrencesEmpty() {
168    Multiset<String> superMultiset = HashMultiset.create(Arrays.asList("a", "b", "a"));
169    Multiset<String> subMultiset = HashMultiset.create();
170    assertTrue(Multisets.containsOccurrences(superMultiset, subMultiset));
171    assertFalse(Multisets.containsOccurrences(subMultiset, superMultiset));
172  }
173
174  public void testContainsOccurrences() {
175    Multiset<String> superMultiset = HashMultiset.create(Arrays.asList("a", "b", "a"));
176    Multiset<String> subMultiset = HashMultiset.create(Arrays.asList("a", "b"));
177    assertTrue(Multisets.containsOccurrences(superMultiset, subMultiset));
178    assertFalse(Multisets.containsOccurrences(subMultiset, superMultiset));
179    Multiset<String> diffMultiset = HashMultiset.create(Arrays.asList("a", "b", "c"));
180    assertFalse(Multisets.containsOccurrences(superMultiset, diffMultiset));
181    assertTrue(Multisets.containsOccurrences(diffMultiset, subMultiset));
182  }
183
184  public void testRetainEmptyOccurrences() {
185    Multiset<String> multiset =
186        HashMultiset.create(Arrays.asList("a", "b", "a"));
187    Multiset<String> toRetain = HashMultiset.create();
188    assertTrue(Multisets.retainOccurrences(multiset, toRetain));
189    assertTrue(multiset.isEmpty());
190  }
191
192  public void testRetainOccurrences() {
193    Multiset<String> multiset =
194        TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
195    Multiset<String> toRetain =
196        HashMultiset.create(Arrays.asList("a", "b", "b"));
197    assertTrue(Multisets.retainOccurrences(multiset, toRetain));
198    ASSERT.that(multiset).hasContentsInOrder("a", "b");
199  }
200
201  public void testRemoveEmptyOccurrences() {
202    Multiset<String> multiset =
203        TreeMultiset.create(Arrays.asList("a", "b", "a"));
204    Multiset<String> toRemove = HashMultiset.create();
205    assertFalse(Multisets.removeOccurrences(multiset, toRemove));
206    ASSERT.that(multiset).hasContentsInOrder("a", "a", "b");
207  }
208
209  public void testRemoveOccurrences() {
210    Multiset<String> multiset =
211        TreeMultiset.create(Arrays.asList("a", "b", "a", "c"));
212    Multiset<String> toRemove =
213        HashMultiset.create(Arrays.asList("a", "b", "b"));
214    assertTrue(Multisets.removeOccurrences(multiset, toRemove));
215    ASSERT.that(multiset).hasContentsInOrder("a", "c");
216  }
217
218  @SuppressWarnings("deprecation")
219  public void testUnmodifiableMultisetShortCircuit(){
220    Multiset<String> mod = HashMultiset.create();
221    Multiset<String> unmod = Multisets.unmodifiableMultiset(mod);
222    assertNotSame(mod, unmod);
223    assertSame(unmod, Multisets.unmodifiableMultiset(unmod));
224    ImmutableMultiset<String> immutable = ImmutableMultiset.of("a", "a", "b", "a");
225    assertSame(immutable, Multisets.unmodifiableMultiset(immutable));
226    assertSame(immutable, Multisets.unmodifiableMultiset((Multiset<String>) immutable));
227  }
228
229  public void testHighestCountFirst() {
230    Multiset<String> multiset = HashMultiset.create(
231        Arrays.asList("a", "a", "a", "b", "c", "c"));
232    ImmutableMultiset<String> sortedMultiset =
233        Multisets.copyHighestCountFirst(multiset);
234
235    ASSERT.that(sortedMultiset.entrySet()).hasContentsInOrder(
236        Multisets.immutableEntry("a", 3), Multisets.immutableEntry("c", 2),
237        Multisets.immutableEntry("b", 1));
238
239    ASSERT.that(sortedMultiset).hasContentsInOrder(
240        "a",
241        "a",
242        "a",
243        "c",
244        "c",
245        "b");
246
247    ASSERT.that(Multisets.copyHighestCountFirst(ImmutableMultiset.of())).isEmpty();
248  }
249
250  @GwtIncompatible("NullPointerTester")
251  public void testNullPointers() throws Exception {
252    NullPointerTester tester = new NullPointerTester();
253    tester.setDefault(Multiset.class, ImmutableMultiset.of());
254    tester.testAllPublicStaticMethods(Multisets.class);
255  }
256}
257