ImmutableSortedMultisetTest.java revision 7dd252788645e940eada959bdde927426e2531c9
1/*
2 * Copyright (C) 2011 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14
15package com.google.common.collect;
16
17import static com.google.common.base.Preconditions.checkArgument;
18import static java.util.Arrays.asList;
19import static org.truth0.Truth.ASSERT;
20
21import com.google.common.base.Function;
22import com.google.common.collect.Multiset.Entry;
23import com.google.common.collect.testing.ListTestSuiteBuilder;
24import com.google.common.collect.testing.MinimalCollection;
25import com.google.common.collect.testing.TestStringListGenerator;
26import com.google.common.collect.testing.features.CollectionFeature;
27import com.google.common.collect.testing.features.CollectionSize;
28import com.google.common.collect.testing.google.SortedMultisetTestSuiteBuilder;
29import com.google.common.collect.testing.google.TestStringMultisetGenerator;
30import com.google.common.collect.testing.google.UnmodifiableCollectionTests;
31import com.google.common.testing.NullPointerTester;
32import com.google.common.testing.SerializableTester;
33
34import java.util.Arrays;
35import java.util.Collection;
36import java.util.Comparator;
37import java.util.Iterator;
38import java.util.List;
39import java.util.Set;
40
41import junit.framework.Test;
42import junit.framework.TestCase;
43import junit.framework.TestSuite;
44
45import org.easymock.EasyMock;
46import org.truth0.subjects.CollectionSubject;
47
48/**
49 * Tests for {@link ImmutableSortedMultiset}.
50 *
51 * @author Louis Wasserman
52 */
53public class ImmutableSortedMultisetTest extends TestCase {
54  public static Test suite() {
55    TestSuite suite = new TestSuite();
56    suite.addTestSuite(ImmutableSortedMultisetTest.class);
57
58    suite.addTest(SortedMultisetTestSuiteBuilder.using(new TestStringMultisetGenerator() {
59        @Override
60        protected Multiset<String> create(String[] elements) {
61          return ImmutableSortedMultiset.copyOf(elements);
62        }
63
64        @Override
65        public List<String> order(List<String> insertionOrder) {
66          return Ordering.natural().sortedCopy(insertionOrder);
67        }
68      })
69      .named("ImmutableSortedMultiset")
70      .withFeatures(CollectionSize.ANY,
71          CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS,
72          CollectionFeature.ALLOWS_NULL_QUERIES)
73        .createTestSuite());
74
75    suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
76        @Override
77        protected List<String> create(String[] elements) {
78          return ImmutableSortedMultiset.copyOf(elements).asList();
79        }
80
81        @Override
82        public List<String> order(List<String> insertionOrder) {
83          return Ordering.natural().sortedCopy(insertionOrder);
84        }
85      })
86      .named("ImmutableSortedMultiset.asList")
87      .withFeatures(CollectionSize.ANY,
88          CollectionFeature.SERIALIZABLE,
89          CollectionFeature.ALLOWS_NULL_QUERIES)
90        .createTestSuite());
91
92    suite.addTest(ListTestSuiteBuilder.using(new TestStringListGenerator() {
93        @Override
94        protected List<String> create(String[] elements) {
95          Set<String> set = Sets.newHashSet();
96          ImmutableSortedMultiset.Builder<String> builder = ImmutableSortedMultiset.naturalOrder();
97          for (String s : elements) {
98            checkArgument(set.add(s));
99            builder.addCopies(s, 2);
100          }
101          return builder.build().elementSet().asList();
102        }
103
104        @Override
105        public List<String> order(List<String> insertionOrder) {
106          return Ordering.natural().sortedCopy(insertionOrder);
107        }
108      })
109      .named("ImmutableSortedMultiset.elementSet.asList")
110      .withFeatures(CollectionSize.ANY,
111          CollectionFeature.REJECTS_DUPLICATES_AT_CREATION,
112          CollectionFeature.SERIALIZABLE,
113          CollectionFeature.ALLOWS_NULL_QUERIES)
114        .createTestSuite());
115
116    return suite;
117  }
118
119  public void testCreation_noArgs() {
120    Multiset<String> multiset = ImmutableSortedMultiset.of();
121    assertTrue(multiset.isEmpty());
122  }
123
124  public void testCreation_oneElement() {
125    Multiset<String> multiset = ImmutableSortedMultiset.of("a");
126    assertEquals(HashMultiset.create(asList("a")), multiset);
127  }
128
129  public void testCreation_twoElements() {
130    Multiset<String> multiset = ImmutableSortedMultiset.of("a", "b");
131    assertEquals(HashMultiset.create(asList("a", "b")), multiset);
132  }
133
134  public void testCreation_threeElements() {
135    Multiset<String> multiset = ImmutableSortedMultiset.of("a", "b", "c");
136    assertEquals(HashMultiset.create(asList("a", "b", "c")), multiset);
137  }
138
139  public void testCreation_fourElements() {
140    Multiset<String> multiset = ImmutableSortedMultiset.of("a", "b", "c", "d");
141    assertEquals(HashMultiset.create(asList("a", "b", "c", "d")), multiset);
142  }
143
144  public void testCreation_fiveElements() {
145    Multiset<String> multiset = ImmutableSortedMultiset.of("a", "b", "c", "d", "e");
146    assertEquals(HashMultiset.create(asList("a", "b", "c", "d", "e")), multiset);
147  }
148
149  public void testCreation_sixElements() {
150    Multiset<String> multiset = ImmutableSortedMultiset.of("a", "b", "c", "d", "e", "f");
151    assertEquals(HashMultiset.create(asList("a", "b", "c", "d", "e", "f")), multiset);
152  }
153
154  public void testCreation_sevenElements() {
155    Multiset<String> multiset = ImmutableSortedMultiset.of("a", "b", "c", "d", "e", "f", "g");
156    assertEquals(HashMultiset.create(asList("a", "b", "c", "d", "e", "f", "g")), multiset);
157  }
158
159  public void testCreation_emptyArray() {
160    String[] array = new String[0];
161    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(array);
162    assertTrue(multiset.isEmpty());
163  }
164
165  public void testCreation_arrayOfOneElement() {
166    String[] array = new String[] {"a"};
167    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(array);
168    assertEquals(HashMultiset.create(asList("a")), multiset);
169  }
170
171  public void testCreation_arrayOfArray() {
172    Comparator<String[]> comparator =
173        Ordering.natural().lexicographical()
174            .onResultOf(new Function<String[], Iterable<Comparable>>() {
175              @Override
176              public Iterable<Comparable> apply(String[] input) {
177                return Arrays.<Comparable>asList(input);
178              }
179            });
180    String[] array = new String[] {"a"};
181    Multiset<String[]> multiset = ImmutableSortedMultiset.orderedBy(comparator).add(array).build();
182    Multiset<String[]> expected = HashMultiset.create();
183    expected.add(array);
184    assertEquals(expected, multiset);
185  }
186
187  public void testCreation_arrayContainingOnlyNull() {
188    String[] array = new String[] {null};
189    try {
190      ImmutableSortedMultiset.copyOf(array);
191      fail();
192    } catch (NullPointerException expected) {}
193  }
194
195  public void testCopyOf_collection_empty() {
196    // "<String>" is required to work around a javac 1.5 bug.
197    Collection<String> c = MinimalCollection.<String>of();
198    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(c);
199    assertTrue(multiset.isEmpty());
200  }
201
202  public void testCopyOf_collection_oneElement() {
203    Collection<String> c = MinimalCollection.of("a");
204    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(c);
205    assertEquals(HashMultiset.create(asList("a")), multiset);
206  }
207
208  public void testCopyOf_collection_general() {
209    Collection<String> c = MinimalCollection.of("a", "b", "a");
210    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(c);
211    assertEquals(HashMultiset.create(asList("a", "b", "a")), multiset);
212  }
213
214  public void testCopyOf_collectionContainingNull() {
215    Collection<String> c = MinimalCollection.of("a", null, "b");
216    try {
217      ImmutableSortedMultiset.copyOf(c);
218      fail();
219    } catch (NullPointerException expected) {}
220  }
221
222  public void testCopyOf_multiset_empty() {
223    Multiset<String> c = HashMultiset.create();
224    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(c);
225    assertTrue(multiset.isEmpty());
226  }
227
228  public void testCopyOf_multiset_oneElement() {
229    Multiset<String> c = HashMultiset.create(asList("a"));
230    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(c);
231    assertEquals(HashMultiset.create(asList("a")), multiset);
232  }
233
234  public void testCopyOf_multiset_general() {
235    Multiset<String> c = HashMultiset.create(asList("a", "b", "a"));
236    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(c);
237    assertEquals(HashMultiset.create(asList("a", "b", "a")), multiset);
238  }
239
240  public void testCopyOf_multisetContainingNull() {
241    Multiset<String> c = HashMultiset.create(asList("a", null, "b"));
242    try {
243      ImmutableSortedMultiset.copyOf(c);
244      fail();
245    } catch (NullPointerException expected) {}
246  }
247
248  public void testCopyOf_iterator_empty() {
249    Iterator<String> iterator = Iterators.emptyIterator();
250    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(iterator);
251    assertTrue(multiset.isEmpty());
252  }
253
254  public void testCopyOf_iterator_oneElement() {
255    Iterator<String> iterator = Iterators.singletonIterator("a");
256    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(iterator);
257    assertEquals(HashMultiset.create(asList("a")), multiset);
258  }
259
260  public void testCopyOf_iterator_general() {
261    Iterator<String> iterator = asList("a", "b", "a").iterator();
262    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(iterator);
263    assertEquals(HashMultiset.create(asList("a", "b", "a")), multiset);
264  }
265
266  public void testCopyOf_iteratorContainingNull() {
267    Iterator<String> iterator = asList("a", null, "b").iterator();
268    try {
269      ImmutableSortedMultiset.copyOf(iterator);
270      fail();
271    } catch (NullPointerException expected) {}
272  }
273
274  private static class CountingIterable implements Iterable<String> {
275    int count = 0;
276
277    @Override
278    public Iterator<String> iterator() {
279      count++;
280      return asList("a", "b", "a").iterator();
281    }
282  }
283
284  public void testCopyOf_plainIterable() {
285    CountingIterable iterable = new CountingIterable();
286    Multiset<String> multiset = ImmutableSortedMultiset.copyOf(iterable);
287    assertEquals(HashMultiset.create(asList("a", "b", "a")), multiset);
288    assertEquals(1, iterable.count);
289  }
290
291  public void testCopyOf_shortcut_empty() {
292    Collection<String> c = ImmutableSortedMultiset.of();
293    assertSame(c, ImmutableSortedMultiset.copyOf(c));
294  }
295
296  public void testCopyOf_shortcut_singleton() {
297    Collection<String> c = ImmutableSortedMultiset.of("a");
298    assertSame(c, ImmutableSortedMultiset.copyOf(c));
299  }
300
301  public void testCopyOf_shortcut_immutableMultiset() {
302    Collection<String> c = ImmutableSortedMultiset.of("a", "b", "c");
303    assertSame(c, ImmutableSortedMultiset.copyOf(c));
304  }
305
306  public void testBuilderAdd() {
307    ImmutableSortedMultiset<String> multiset =
308        ImmutableSortedMultiset.<String>naturalOrder().add("a").add("b").add("a").add("c").build();
309    assertEquals(HashMultiset.create(asList("a", "b", "a", "c")), multiset);
310  }
311
312  public void testBuilderAddAll() {
313    List<String> a = asList("a", "b");
314    List<String> b = asList("c", "d");
315    ImmutableSortedMultiset<String> multiset =
316        ImmutableSortedMultiset.<String>naturalOrder().addAll(a).addAll(b).build();
317    assertEquals(HashMultiset.create(asList("a", "b", "c", "d")), multiset);
318  }
319
320  public void testBuilderAddAllMultiset() {
321    Multiset<String> a = HashMultiset.create(asList("a", "b", "b"));
322    Multiset<String> b = HashMultiset.create(asList("c", "b"));
323    ImmutableSortedMultiset<String> multiset =
324        ImmutableSortedMultiset.<String>naturalOrder().addAll(a).addAll(b).build();
325    assertEquals(HashMultiset.create(asList("a", "b", "b", "b", "c")), multiset);
326  }
327
328  public void testBuilderAddAllIterator() {
329    Iterator<String> iterator = asList("a", "b", "a", "c").iterator();
330    ImmutableSortedMultiset<String> multiset =
331        ImmutableSortedMultiset.<String>naturalOrder().addAll(iterator).build();
332    assertEquals(HashMultiset.create(asList("a", "b", "a", "c")), multiset);
333  }
334
335  public void testBuilderAddCopies() {
336    ImmutableSortedMultiset<String> multiset =
337        ImmutableSortedMultiset.<String>naturalOrder().addCopies("a", 2).addCopies("b", 3)
338            .addCopies("c", 0).build();
339    assertEquals(HashMultiset.create(asList("a", "a", "b", "b", "b")), multiset);
340  }
341
342  public void testBuilderSetCount() {
343    ImmutableSortedMultiset<String> multiset =
344        ImmutableSortedMultiset.<String>naturalOrder().add("a").setCount("a", 2).setCount("b", 3)
345            .build();
346    assertEquals(HashMultiset.create(asList("a", "a", "b", "b", "b")), multiset);
347  }
348
349  public void testBuilderAddHandlesNullsCorrectly() {
350    ImmutableSortedMultiset.Builder<String> builder = ImmutableSortedMultiset.naturalOrder();
351    try {
352      builder.add((String) null);
353      fail("expected NullPointerException");
354    } catch (NullPointerException expected) {}
355  }
356
357  public void testBuilderAddAllHandlesNullsCorrectly() {
358    ImmutableSortedMultiset.Builder<String> builder = ImmutableSortedMultiset.naturalOrder();
359    try {
360      builder.addAll((Collection<String>) null);
361      fail("expected NullPointerException");
362    } catch (NullPointerException expected) {}
363
364    builder = ImmutableSortedMultiset.naturalOrder();
365    List<String> listWithNulls = asList("a", null, "b");
366    try {
367      builder.addAll(listWithNulls);
368      fail("expected NullPointerException");
369    } catch (NullPointerException expected) {}
370
371    builder = ImmutableSortedMultiset.naturalOrder();
372    Multiset<String> multisetWithNull = LinkedHashMultiset.create(asList("a", null, "b"));
373    try {
374      builder.addAll(multisetWithNull);
375      fail("expected NullPointerException");
376    } catch (NullPointerException expected) {}
377  }
378
379  public void testBuilderAddCopiesHandlesNullsCorrectly() {
380    ImmutableSortedMultiset.Builder<String> builder = ImmutableSortedMultiset.naturalOrder();
381    try {
382      builder.addCopies(null, 2);
383      fail("expected NullPointerException");
384    } catch (NullPointerException expected) {}
385  }
386
387  public void testBuilderAddCopiesIllegal() {
388    ImmutableSortedMultiset.Builder<String> builder = ImmutableSortedMultiset.naturalOrder();
389    try {
390      builder.addCopies("a", -2);
391      fail("expected IllegalArgumentException");
392    } catch (IllegalArgumentException expected) {}
393  }
394
395  public void testBuilderSetCountHandlesNullsCorrectly() {
396    ImmutableSortedMultiset.Builder<String> builder =
397        new ImmutableSortedMultiset.Builder<String>(Ordering.natural().nullsFirst());
398    try {
399      builder.setCount(null, 2);
400      fail("expected NullPointerException");
401    } catch (NullPointerException expected) {}
402  }
403
404  public void testBuilderSetCountIllegal() {
405    ImmutableSortedMultiset.Builder<String> builder = ImmutableSortedMultiset.naturalOrder();
406    try {
407      builder.setCount("a", -2);
408      fail("expected IllegalArgumentException");
409    } catch (IllegalArgumentException expected) {}
410  }
411
412  public void testNullPointers() {
413    new NullPointerTester().testAllPublicStaticMethods(ImmutableSortedMultiset.class);
414  }
415
416  public void testSerialization_empty() {
417    Collection<String> c = ImmutableSortedMultiset.of();
418    assertSame(c, SerializableTester.reserialize(c));
419  }
420
421  public void testSerialization_multiple() {
422    Collection<String> c = ImmutableSortedMultiset.of("a", "b", "a");
423    Collection<String> copy = SerializableTester.reserializeAndAssert(c);
424    assertThat(copy).has().allOf("a", "a", "b").inOrder();
425  }
426
427  public void testSerialization_elementSet() {
428    Multiset<String> c = ImmutableSortedMultiset.of("a", "b", "a");
429    Collection<String> copy = SerializableTester.reserializeAndAssert(c.elementSet());
430    assertThat(copy).has().allOf("a", "b").inOrder();
431  }
432
433  public void testSerialization_entrySet() {
434    Multiset<String> c = ImmutableSortedMultiset.of("a", "b", "c");
435    SerializableTester.reserializeAndAssert(c.entrySet());
436  }
437
438  public void testEquals_immutableMultiset() {
439    Collection<String> c = ImmutableSortedMultiset.of("a", "b", "a");
440    assertEquals(c, ImmutableSortedMultiset.of("a", "b", "a"));
441    assertEquals(c, ImmutableSortedMultiset.of("a", "a", "b"));
442    assertThat(c).isNotEqualTo(ImmutableSortedMultiset.of("a", "b"));
443    assertThat(c).isNotEqualTo(ImmutableSortedMultiset.of("a", "b", "c", "d"));
444  }
445
446  public void testIterationOrder() {
447    Collection<String> c = ImmutableSortedMultiset.of("a", "b", "a");
448    assertThat(c).has().allOf("a", "a", "b").inOrder();
449  }
450
451  public void testMultisetWrites() {
452    Multiset<String> multiset = ImmutableSortedMultiset.of("a", "b", "a");
453    UnmodifiableCollectionTests.assertMultisetIsUnmodifiable(multiset, "test");
454  }
455
456  public void testAsList() {
457    ImmutableSortedMultiset<String> multiset = ImmutableSortedMultiset.of("a", "a", "b", "b", "b");
458    ImmutableList<String> list = multiset.asList();
459    assertEquals(ImmutableList.of("a", "a", "b", "b", "b"), list);
460    assertTrue(list instanceof ImmutableAsList);
461    ImmutableList<String> copy = SerializableTester.reserializeAndAssert(list);
462    assertTrue(copy instanceof ImmutableAsList);
463    assertEquals(2, list.indexOf("b"));
464    assertEquals(4, list.lastIndexOf("b"));
465  }
466
467  public void testCopyOfDefensiveCopy() {
468    // Test that toArray() is used to make a defensive copy in copyOf(), so concurrently modified
469    // synchronized collections can be safely copied.
470    @SuppressWarnings("unchecked")
471    Collection<String> toCopy = EasyMock.createMock(Collection.class);
472    EasyMock.expect(toCopy.toArray()).andReturn(new Object[0]);
473    EasyMock.replay(toCopy);
474    ImmutableSortedMultiset<String> multiset =
475        ImmutableSortedMultiset.copyOf(Ordering.natural(), toCopy);
476    EasyMock.verify(toCopy);
477  }
478
479  @SuppressWarnings("unchecked")
480  public void testCopyOfSortedDefensiveCopy() {
481    // Test that toArray() is used to make a defensive copy in copyOf(), so concurrently modified
482    // synchronized collections can be safely copied.
483    SortedMultiset<String> toCopy = EasyMock.createMock(SortedMultiset.class);
484    Set<Entry<String>> entrySet = EasyMock.createMock(Set.class);
485    EasyMock.expect((Comparator<Comparable>) toCopy.comparator())
486      .andReturn(Ordering.natural());
487    EasyMock.expect(toCopy.entrySet()).andReturn(entrySet);
488    EasyMock.expect(entrySet.toArray()).andReturn(new Object[0]);
489    EasyMock.replay(toCopy, entrySet);
490    ImmutableSortedMultiset<String> multiset =
491        ImmutableSortedMultiset.copyOfSorted(toCopy);
492    EasyMock.verify(toCopy, entrySet);
493  }
494
495  private static class IntegerDiv10 implements Comparable<IntegerDiv10> {
496    final int value;
497
498    IntegerDiv10(int value) {
499      this.value = value;
500    }
501
502    @Override
503    public int compareTo(IntegerDiv10 o) {
504      return value / 10 - o.value / 10;
505    }
506
507    @Override public String toString() {
508      return Integer.toString(value);
509    }
510  }
511
512  public void testCopyOfDuplicateInconsistentWithEquals() {
513    IntegerDiv10 three = new IntegerDiv10(3);
514    IntegerDiv10 eleven = new IntegerDiv10(11);
515    IntegerDiv10 twelve = new IntegerDiv10(12);
516    IntegerDiv10 twenty = new IntegerDiv10(20);
517
518    List<IntegerDiv10> original = ImmutableList.of(three, eleven, twelve, twenty);
519
520    Multiset<IntegerDiv10> copy = ImmutableSortedMultiset.copyOf(original);
521    assertTrue(copy.contains(eleven));
522    assertTrue(copy.contains(twelve));
523  }
524
525  // Hack for JDK5 type inference.
526  private static <T> CollectionSubject<? extends CollectionSubject<?, T, Collection<T>>, T, Collection<T>> assertThat(
527      Collection<T> collection) {
528    return ASSERT.<T, Collection<T>>that(collection);
529  }
530}
531