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