1/*
2 * Copyright (C) 2008 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 java.util.Arrays.asList;
20import static org.junit.contrib.truth.Truth.ASSERT;
21
22import com.google.common.annotations.GwtCompatible;
23import com.google.common.annotations.GwtIncompatible;
24import com.google.common.collect.testing.MinimalCollection;
25import com.google.common.collect.testing.SetTestSuiteBuilder;
26import com.google.common.collect.testing.TestStringSetGenerator;
27import com.google.common.collect.testing.features.CollectionFeature;
28import com.google.common.collect.testing.features.CollectionSize;
29import com.google.common.collect.testing.google.MultisetTestSuiteBuilder;
30import com.google.common.collect.testing.google.TestStringMultisetGenerator;
31import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
32import com.google.common.testing.NullPointerTester;
33import com.google.common.testing.SerializableTester;
34
35import junit.framework.Test;
36import junit.framework.TestCase;
37import junit.framework.TestSuite;
38
39import java.util.Collection;
40import java.util.Iterator;
41import java.util.List;
42import java.util.Set;
43
44/**
45 * Tests for {@link ImmutableMultiset}.
46 *
47 * @author Jared Levy
48 */
49@GwtCompatible(emulated = true)
50public class ImmutableMultisetTest extends TestCase {
51
52  @GwtIncompatible("suite") // TODO(cpovirk): add to collect/gwt/suites
53  public static Test suite() {
54    TestSuite suite = new TestSuite();
55    suite.addTestSuite(ImmutableMultisetTest.class);
56
57    suite.addTest(MultisetTestSuiteBuilder.using(
58        new TestStringMultisetGenerator() {
59          @Override protected Multiset<String> create(String[] elements) {
60            return ImmutableMultiset.copyOf(elements);
61          }
62        })
63        .named("ImmutableMultiset")
64        .withFeatures(CollectionSize.ANY,
65            CollectionFeature.ALLOWS_NULL_QUERIES)
66        .createTestSuite());
67
68    suite.addTest(MultisetTestSuiteBuilder.using(
69        new TestStringMultisetGenerator() {
70          @Override protected Multiset<String> create(String[] elements) {
71            return SerializableTester.reserialize(
72                ImmutableMultiset.copyOf(elements));
73          }
74        })
75        .named("ImmutableMultiset, reserialized")
76        .withFeatures(CollectionSize.ANY,
77            CollectionFeature.ALLOWS_NULL_QUERIES)
78        .createTestSuite());
79
80    suite.addTest(SetTestSuiteBuilder.using(new TestStringSetGenerator() {
81          @Override protected Set<String> create(String[] elements) {
82            return SerializableTester.reserialize(
83                ImmutableMultiset.copyOf(elements).elementSet());
84          }
85        })
86        .named("ImmutableMultiset, element set")
87        .withFeatures(CollectionSize.ANY,
88            CollectionFeature.ALLOWS_NULL_QUERIES)
89        .createTestSuite());
90
91    return suite;
92  }
93
94  public void testCreation_noArgs() {
95    Multiset<String> multiset = ImmutableMultiset.of();
96    assertTrue(multiset.isEmpty());
97  }
98
99  public void testCreation_oneElement() {
100    Multiset<String> multiset = ImmutableMultiset.of("a");
101    assertEquals(HashMultiset.create(asList("a")), multiset);
102  }
103
104  public void testCreation_twoElements() {
105    Multiset<String> multiset = ImmutableMultiset.of("a", "b");
106    assertEquals(HashMultiset.create(asList("a", "b")), multiset);
107  }
108
109  public void testCreation_threeElements() {
110    Multiset<String> multiset = ImmutableMultiset.of("a", "b", "c");
111    assertEquals(HashMultiset.create(asList("a", "b", "c")), multiset);
112  }
113
114  public void testCreation_fourElements() {
115    Multiset<String> multiset = ImmutableMultiset.of("a", "b", "c", "d");
116    assertEquals(HashMultiset.create(asList("a", "b", "c", "d")), multiset);
117  }
118
119  public void testCreation_fiveElements() {
120    Multiset<String> multiset = ImmutableMultiset.of("a", "b", "c", "d", "e");
121    assertEquals(HashMultiset.create(asList("a", "b", "c", "d", "e")),
122        multiset);
123  }
124
125  public void testCreation_sixElements() {
126    Multiset<String> multiset = ImmutableMultiset.of(
127        "a", "b", "c", "d", "e", "f");
128    assertEquals(HashMultiset.create(asList("a", "b", "c", "d", "e", "f")),
129        multiset);
130  }
131
132  public void testCreation_sevenElements() {
133    Multiset<String> multiset = ImmutableMultiset.of(
134        "a", "b", "c", "d", "e", "f", "g");
135    assertEquals(
136        HashMultiset.create(asList("a", "b", "c", "d", "e", "f", "g")),
137        multiset);
138  }
139
140  public void testCreation_emptyArray() {
141    String[] array = new String[0];
142    Multiset<String> multiset = ImmutableMultiset.copyOf(array);
143    assertTrue(multiset.isEmpty());
144  }
145
146  public void testCreation_arrayOfOneElement() {
147    String[] array = new String[] { "a" };
148    Multiset<String> multiset = ImmutableMultiset.copyOf(array);
149    assertEquals(HashMultiset.create(asList("a")), multiset);
150  }
151
152  public void testCreation_arrayOfArray() {
153    String[] array = new String[] { "a" };
154    Multiset<String[]> multiset = ImmutableMultiset.<String[]>of(array);
155    Multiset<String[]> expected = HashMultiset.create();
156    expected.add(array);
157    assertEquals(expected, multiset);
158  }
159
160  public void testCreation_arrayContainingOnlyNull() {
161    String[] array = new String[] { null };
162    try {
163      ImmutableMultiset.copyOf(array);
164      fail();
165    } catch (NullPointerException expected) {}
166  }
167
168  public void testCopyOf_collection_empty() {
169    // "<String>" is required to work around a javac 1.5 bug.
170    Collection<String> c = MinimalCollection.<String>of();
171    Multiset<String> multiset = ImmutableMultiset.copyOf(c);
172    assertTrue(multiset.isEmpty());
173  }
174
175  public void testCopyOf_collection_oneElement() {
176    Collection<String> c = MinimalCollection.of("a");
177    Multiset<String> multiset = ImmutableMultiset.copyOf(c);
178    assertEquals(HashMultiset.create(asList("a")), multiset);
179  }
180
181  public void testCopyOf_collection_general() {
182    Collection<String> c = MinimalCollection.of("a", "b", "a");
183    Multiset<String> multiset = ImmutableMultiset.copyOf(c);
184    assertEquals(HashMultiset.create(asList("a", "b", "a")), multiset);
185  }
186
187  public void testCopyOf_collectionContainingNull() {
188    Collection<String> c = MinimalCollection.of("a", null, "b");
189    try {
190      ImmutableMultiset.copyOf(c);
191      fail();
192    } catch (NullPointerException expected) {}
193  }
194
195  public void testCopyOf_multiset_empty() {
196    Multiset<String> c = HashMultiset.create();
197    Multiset<String> multiset = ImmutableMultiset.copyOf(c);
198    assertTrue(multiset.isEmpty());
199  }
200
201  public void testCopyOf_multiset_oneElement() {
202    Multiset<String> c = HashMultiset.create(asList("a"));
203    Multiset<String> multiset = ImmutableMultiset.copyOf(c);
204    assertEquals(HashMultiset.create(asList("a")), multiset);
205  }
206
207  public void testCopyOf_multiset_general() {
208    Multiset<String> c = HashMultiset.create(asList("a", "b", "a"));
209    Multiset<String> multiset = ImmutableMultiset.copyOf(c);
210    assertEquals(HashMultiset.create(asList("a", "b", "a")), multiset);
211  }
212
213  public void testCopyOf_multisetContainingNull() {
214    Multiset<String> c = HashMultiset.create(asList("a", null, "b"));
215    try {
216      ImmutableMultiset.copyOf(c);
217      fail();
218    } catch (NullPointerException expected) {}
219  }
220
221  public void testCopyOf_iterator_empty() {
222    Iterator<String> iterator = Iterators.emptyIterator();
223    Multiset<String> multiset = ImmutableMultiset.copyOf(iterator);
224    assertTrue(multiset.isEmpty());
225  }
226
227  public void testCopyOf_iterator_oneElement() {
228    Iterator<String> iterator = Iterators.singletonIterator("a");
229    Multiset<String> multiset = ImmutableMultiset.copyOf(iterator);
230    assertEquals(HashMultiset.create(asList("a")), multiset);
231  }
232
233  public void testCopyOf_iterator_general() {
234    Iterator<String> iterator = asList("a", "b", "a").iterator();
235    Multiset<String> multiset = ImmutableMultiset.copyOf(iterator);
236    assertEquals(HashMultiset.create(asList("a", "b", "a")), multiset);
237  }
238
239  public void testCopyOf_iteratorContainingNull() {
240    Iterator<String> iterator = asList("a", null, "b").iterator();
241    try {
242      ImmutableMultiset.copyOf(iterator);
243      fail();
244    } catch (NullPointerException expected) {}
245  }
246
247  private static class CountingIterable implements Iterable<String> {
248    int count = 0;
249    @Override
250    public Iterator<String> iterator() {
251      count++;
252      return asList("a", "b", "a").iterator();
253    }
254  }
255
256  public void testCopyOf_plainIterable() {
257    CountingIterable iterable = new CountingIterable();
258    Multiset<String> multiset = ImmutableMultiset.copyOf(iterable);
259    assertEquals(HashMultiset.create(asList("a", "b", "a")), multiset);
260    assertEquals(1, iterable.count);
261  }
262
263  public void testCopyOf_shortcut_empty() {
264    Collection<String> c = ImmutableMultiset.of();
265    assertSame(c, ImmutableMultiset.copyOf(c));
266  }
267
268  public void testCopyOf_shortcut_singleton() {
269    Collection<String> c = ImmutableMultiset.of("a");
270    assertSame(c, ImmutableMultiset.copyOf(c));
271  }
272
273  public void testCopyOf_shortcut_immutableMultiset() {
274    Collection<String> c = ImmutableMultiset.of("a", "b", "c");
275    assertSame(c, ImmutableMultiset.copyOf(c));
276  }
277
278  public void testBuilderAdd() {
279    ImmutableMultiset<String> multiset = new ImmutableMultiset.Builder<String>()
280        .add("a")
281        .add("b")
282        .add("a")
283        .add("c")
284        .build();
285    assertEquals(HashMultiset.create(asList("a", "b", "a", "c")), multiset);
286  }
287
288  public void testBuilderAddAll() {
289    List<String> a = asList("a", "b");
290    List<String> b = asList("c", "d");
291    ImmutableMultiset<String> multiset = new ImmutableMultiset.Builder<String>()
292        .addAll(a)
293        .addAll(b)
294        .build();
295    assertEquals(HashMultiset.create(asList("a", "b", "c", "d")), multiset);
296  }
297
298  public void testBuilderAddAllMultiset() {
299    Multiset<String> a = HashMultiset.create(asList("a", "b", "b"));
300    Multiset<String> b = HashMultiset.create(asList("c", "b"));
301    ImmutableMultiset<String> multiset = new ImmutableMultiset.Builder<String>()
302        .addAll(a)
303        .addAll(b)
304        .build();
305    assertEquals(
306        HashMultiset.create(asList("a", "b", "b", "b", "c")), multiset);
307  }
308
309  public void testBuilderAddAllIterator() {
310    Iterator<String> iterator = asList("a", "b", "a", "c").iterator();
311    ImmutableMultiset<String> multiset = new ImmutableMultiset.Builder<String>()
312        .addAll(iterator)
313        .build();
314    assertEquals(HashMultiset.create(asList("a", "b", "a", "c")), multiset);
315  }
316
317  public void testBuilderAddCopies() {
318    ImmutableMultiset<String> multiset = new ImmutableMultiset.Builder<String>()
319        .addCopies("a", 2)
320        .addCopies("b", 3)
321        .addCopies("c", 0)
322        .build();
323    assertEquals(
324        HashMultiset.create(asList("a", "a", "b", "b", "b")), multiset);
325  }
326
327  public void testBuilderSetCount() {
328    ImmutableMultiset<String> multiset = new ImmutableMultiset.Builder<String>()
329        .add("a")
330        .setCount("a", 2)
331        .setCount("b", 3)
332        .build();
333    assertEquals(
334        HashMultiset.create(asList("a", "a", "b", "b", "b")), multiset);
335  }
336
337  public void testBuilderAddHandlesNullsCorrectly() {
338    ImmutableMultiset.Builder<String> builder = ImmutableMultiset.builder();
339    try {
340      builder.add((String) null);
341      fail("expected NullPointerException");
342    } catch (NullPointerException expected) {}
343  }
344
345  public void testBuilderAddAllHandlesNullsCorrectly() {
346    ImmutableMultiset.Builder<String> builder = ImmutableMultiset.builder();
347    try {
348      builder.addAll((Collection<String>) null);
349      fail("expected NullPointerException");
350    } catch (NullPointerException expected) {}
351
352    builder = ImmutableMultiset.builder();
353    List<String> listWithNulls = asList("a", null, "b");
354    try {
355      builder.addAll(listWithNulls);
356      fail("expected NullPointerException");
357    } catch (NullPointerException expected) {}
358
359    builder = ImmutableMultiset.builder();
360    Multiset<String> multisetWithNull
361        = LinkedHashMultiset.create(asList("a", null, "b"));
362    try {
363      builder.addAll(multisetWithNull);
364      fail("expected NullPointerException");
365    } catch (NullPointerException expected) {}
366  }
367
368  public void testBuilderAddCopiesHandlesNullsCorrectly() {
369    ImmutableMultiset.Builder<String> builder = ImmutableMultiset.builder();
370    try {
371      builder.addCopies(null, 2);
372      fail("expected NullPointerException");
373    } catch (NullPointerException expected) {}
374  }
375
376  public void testBuilderAddCopiesIllegal() {
377    ImmutableMultiset.Builder<String> builder = ImmutableMultiset.builder();
378    try {
379      builder.addCopies("a", -2);
380      fail("expected IllegalArgumentException");
381    } catch (IllegalArgumentException expected) {}
382  }
383
384  public void testBuilderSetCountHandlesNullsCorrectly() {
385    ImmutableMultiset.Builder<String> builder = ImmutableMultiset.builder();
386    try {
387      builder.setCount(null, 2);
388      fail("expected NullPointerException");
389    } catch (NullPointerException expected) {}
390  }
391
392  public void testBuilderSetCountIllegal() {
393    ImmutableMultiset.Builder<String> builder = ImmutableMultiset.builder();
394    try {
395      builder.setCount("a", -2);
396      fail("expected IllegalArgumentException");
397    } catch (IllegalArgumentException expected) {}
398  }
399
400  @GwtIncompatible("NullPointerTester")
401  public void testNullPointers() throws Exception {
402    NullPointerTester tester = new NullPointerTester();
403    tester.testAllPublicStaticMethods(ImmutableMultiset.class);
404  }
405
406  @GwtIncompatible("SerializableTester")
407  public void testSerialization_empty() {
408    Collection<String> c = ImmutableMultiset.of();
409    assertSame(c, SerializableTester.reserialize(c));
410  }
411
412  @GwtIncompatible("SerializableTester")
413  public void testSerialization_multiple() {
414    Collection<String> c = ImmutableMultiset.of("a", "b", "a");
415    Collection<String> copy = SerializableTester.reserializeAndAssert(c);
416    ASSERT.that(copy).hasContentsInOrder("a", "a", "b");
417  }
418
419  @GwtIncompatible("SerializableTester")
420  public void testSerialization_elementSet() {
421    Multiset<String> c = ImmutableMultiset.of("a", "b", "a");
422    Collection<String> copy =
423        LenientSerializableTester.reserializeAndAssertLenient(c.elementSet());
424    ASSERT.that(copy).hasContentsInOrder("a", "b");
425  }
426
427  @GwtIncompatible("SerializableTester")
428  public void testSerialization_entrySet() {
429    Multiset<String> c = ImmutableMultiset.of("a", "b", "c");
430    SerializableTester.reserializeAndAssert(c.entrySet());
431  }
432
433  public void testEquals_immutableMultiset() {
434    Collection<String> c = ImmutableMultiset.of("a", "b", "a");
435    assertEquals(c, ImmutableMultiset.of("a", "b", "a"));
436    assertEquals(c, ImmutableMultiset.of("a", "a", "b"));
437    ASSERT.that(c).isNotEqualTo(ImmutableMultiset.of("a", "b"));
438    ASSERT.that(c).isNotEqualTo(ImmutableMultiset.of("a", "b", "c", "d"));
439  }
440
441  public void testIterationOrder() {
442    Collection<String> c = ImmutableMultiset.of("a", "b", "a");
443    ASSERT.that(c).hasContentsInOrder("a", "a", "b");
444  }
445
446  public void testMultisetWrites() {
447    Multiset<String> multiset = ImmutableMultiset.of("a", "b", "a");
448    UnmodifiableCollectionTests.assertMultisetIsUnmodifiable(multiset, "test");
449  }
450
451  public void testAsList() {
452    ImmutableMultiset<String> multiset
453        = ImmutableMultiset.of("a", "a", "b", "b", "b");
454    ImmutableList<String> list = multiset.asList();
455    assertEquals(ImmutableList.of("a", "a", "b", "b", "b"), list);
456    assertEquals(2, list.indexOf("b"));
457    assertEquals(4, list.lastIndexOf("b"));
458  }
459
460  @GwtIncompatible("SerializableTester")
461  public void testSerialization_asList() {
462    ImmutableMultiset<String> multiset
463        = ImmutableMultiset.of("a", "a", "b", "b", "b");
464    SerializableTester.reserializeAndAssert(multiset.asList());
465  }
466}
467