/* * Copyright (C) 2007 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.collect; import static com.google.common.collect.BoundType.CLOSED; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE; import static java.util.Collections.sort; import static org.truth0.Truth.ASSERT; import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtIncompatible; import com.google.common.collect.testing.Helpers.NullsBeforeB; import com.google.common.collect.testing.IteratorTester; import com.google.common.collect.testing.NavigableSetTestSuiteBuilder; import com.google.common.collect.testing.TestStringSetGenerator; import com.google.common.collect.testing.features.CollectionFeature; import com.google.common.collect.testing.features.CollectionSize; import com.google.common.collect.testing.google.SortedMultisetTestSuiteBuilder; import com.google.common.collect.testing.google.TestStringMultisetGenerator; import junit.framework.Test; import junit.framework.TestSuite; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedSet; /** * Unit test for {@link TreeMultiset}. * * @author Neal Kanodia */ @GwtCompatible(emulated = true) public class TreeMultisetTest extends AbstractMultisetTest { @GwtIncompatible("suite") public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(SortedMultisetTestSuiteBuilder .using(new TestStringMultisetGenerator() { @Override protected Multiset<String> create(String[] elements) { return TreeMultiset.create(Arrays.asList(elements)); } @Override public List<String> order(List<String> insertionOrder) { return Ordering.natural().sortedCopy(insertionOrder); } }) .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, CollectionFeature.GENERAL_PURPOSE, CollectionFeature.SERIALIZABLE, CollectionFeature.ALLOWS_NULL_QUERIES) .named("TreeMultiset, Ordering.natural") .createTestSuite()); suite.addTest(SortedMultisetTestSuiteBuilder .using(new TestStringMultisetGenerator() { @Override protected Multiset<String> create(String[] elements) { Multiset<String> result = TreeMultiset.create(NullsBeforeB.INSTANCE); result.addAll(Arrays.asList(elements)); return result; } @Override public List<String> order(List<String> insertionOrder) { sort(insertionOrder, NullsBeforeB.INSTANCE); return insertionOrder; } }) .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, CollectionFeature.GENERAL_PURPOSE, CollectionFeature.SERIALIZABLE, CollectionFeature.ALLOWS_NULL_VALUES) .named("TreeMultiset, NullsBeforeB") .createTestSuite()); suite.addTest(NavigableSetTestSuiteBuilder.using(new TestStringSetGenerator() { @Override protected Set<String> create(String[] elements) { return TreeMultiset.create(Arrays.asList(elements)).elementSet(); } @Override public List<String> order(List<String> insertionOrder) { return Lists.newArrayList(Sets.newTreeSet(insertionOrder)); } }) .named("TreeMultiset[Ordering.natural].elementSet") .withFeatures( CollectionSize.ANY, CollectionFeature.SUPPORTS_REMOVE, CollectionFeature.ALLOWS_NULL_QUERIES) .createTestSuite()); suite.addTestSuite(TreeMultisetTest.class); return suite; } @SuppressWarnings("unchecked") @Override protected <E> Multiset<E> create() { return (Multiset) TreeMultiset.create(); } public void testCreate() { TreeMultiset<String> multiset = TreeMultiset.create(); multiset.add("foo", 2); multiset.add("bar"); assertEquals(3, multiset.size()); assertEquals(2, multiset.count("foo")); assertEquals(Ordering.natural(), multiset.comparator()); assertEquals("[bar, foo x 2]", multiset.toString()); } public void testCreateWithComparator() { Multiset<String> multiset = TreeMultiset.create(Collections.reverseOrder()); multiset.add("foo", 2); multiset.add("bar"); assertEquals(3, multiset.size()); assertEquals(2, multiset.count("foo")); assertEquals("[foo x 2, bar]", multiset.toString()); } public void testCreateFromIterable() { Multiset<String> multiset = TreeMultiset.create(Arrays.asList("foo", "bar", "foo")); assertEquals(3, multiset.size()); assertEquals(2, multiset.count("foo")); assertEquals("[bar, foo x 2]", multiset.toString()); } public void testToString() { ms.add("a", 3); ms.add("c", 1); ms.add("b", 2); assertEquals("[a x 3, b x 2, c]", ms.toString()); } @GwtIncompatible("unreasonable slow") public void testIteratorBashing() { IteratorTester<String> tester = new IteratorTester<String>(createSample().size() + 2, MODIFIABLE, newArrayList(createSample()), IteratorTester.KnownOrder.KNOWN_ORDER) { private Multiset<String> targetMultiset; @Override protected Iterator<String> newTargetIterator() { targetMultiset = createSample(); return targetMultiset.iterator(); } @Override protected void verify(List<String> elements) { assertEquals(elements, Lists.newArrayList(targetMultiset)); } }; /* This next line added as a stopgap until JDK6 bug is fixed. */ tester.ignoreSunJavaBug6529795(); tester.test(); } @GwtIncompatible("slow (~30s)") public void testElementSetIteratorBashing() { IteratorTester<String> tester = new IteratorTester<String>(5, MODIFIABLE, newArrayList("a", "b", "c"), IteratorTester.KnownOrder.KNOWN_ORDER) { private Set<String> targetSet; @Override protected Iterator<String> newTargetIterator() { Multiset<String> multiset = create(); multiset.add("a", 3); multiset.add("c", 1); multiset.add("b", 2); targetSet = multiset.elementSet(); return targetSet.iterator(); } @Override protected void verify(List<String> elements) { assertEquals(elements, Lists.newArrayList(targetSet)); } }; /* This next line added as a stopgap until JDK6 bug is fixed. */ tester.ignoreSunJavaBug6529795(); tester.test(); } public void testElementSetSortedSetMethods() { TreeMultiset<String> ms = TreeMultiset.create(); ms.add("c", 1); ms.add("a", 3); ms.add("b", 2); SortedSet<String> elementSet = ms.elementSet(); assertEquals("a", elementSet.first()); assertEquals("c", elementSet.last()); assertEquals(Ordering.natural(), elementSet.comparator()); ASSERT.that(elementSet.headSet("b")).has().allOf("a").inOrder(); ASSERT.that(elementSet.tailSet("b")).has().allOf("b", "c").inOrder(); ASSERT.that(elementSet.subSet("a", "c")).has().allOf("a", "b").inOrder(); } public void testElementSetSubsetRemove() { TreeMultiset<String> ms = TreeMultiset.create(); ms.add("a", 1); ms.add("b", 3); ms.add("c", 2); ms.add("d", 1); ms.add("e", 3); ms.add("f", 2); SortedSet<String> elementSet = ms.elementSet(); ASSERT.that(elementSet).has().allOf("a", "b", "c", "d", "e", "f").inOrder(); SortedSet<String> subset = elementSet.subSet("b", "f"); ASSERT.that(subset).has().allOf("b", "c", "d", "e").inOrder(); assertTrue(subset.remove("c")); ASSERT.that(elementSet).has().allOf("a", "b", "d", "e", "f").inOrder(); ASSERT.that(subset).has().allOf("b", "d", "e").inOrder(); assertEquals(10, ms.size()); assertFalse(subset.remove("a")); ASSERT.that(elementSet).has().allOf("a", "b", "d", "e", "f").inOrder(); ASSERT.that(subset).has().allOf("b", "d", "e").inOrder(); assertEquals(10, ms.size()); } public void testElementSetSubsetRemoveAll() { TreeMultiset<String> ms = TreeMultiset.create(); ms.add("a", 1); ms.add("b", 3); ms.add("c", 2); ms.add("d", 1); ms.add("e", 3); ms.add("f", 2); SortedSet<String> elementSet = ms.elementSet(); ASSERT.that(elementSet).has().allOf("a", "b", "c", "d", "e", "f").inOrder(); SortedSet<String> subset = elementSet.subSet("b", "f"); ASSERT.that(subset).has().allOf("b", "c", "d", "e").inOrder(); assertTrue(subset.removeAll(Arrays.asList("a", "c"))); ASSERT.that(elementSet).has().allOf("a", "b", "d", "e", "f").inOrder(); ASSERT.that(subset).has().allOf("b", "d", "e").inOrder(); assertEquals(10, ms.size()); } public void testElementSetSubsetRetainAll() { TreeMultiset<String> ms = TreeMultiset.create(); ms.add("a", 1); ms.add("b", 3); ms.add("c", 2); ms.add("d", 1); ms.add("e", 3); ms.add("f", 2); SortedSet<String> elementSet = ms.elementSet(); ASSERT.that(elementSet).has().allOf("a", "b", "c", "d", "e", "f").inOrder(); SortedSet<String> subset = elementSet.subSet("b", "f"); ASSERT.that(subset).has().allOf("b", "c", "d", "e").inOrder(); assertTrue(subset.retainAll(Arrays.asList("a", "c"))); ASSERT.that(elementSet).has().allOf("a", "c", "f").inOrder(); ASSERT.that(subset).has().allOf("c").inOrder(); assertEquals(5, ms.size()); } public void testElementSetSubsetClear() { TreeMultiset<String> ms = TreeMultiset.create(); ms.add("a", 1); ms.add("b", 3); ms.add("c", 2); ms.add("d", 1); ms.add("e", 3); ms.add("f", 2); SortedSet<String> elementSet = ms.elementSet(); ASSERT.that(elementSet).has().allOf("a", "b", "c", "d", "e", "f").inOrder(); SortedSet<String> subset = elementSet.subSet("b", "f"); ASSERT.that(subset).has().allOf("b", "c", "d", "e").inOrder(); subset.clear(); ASSERT.that(elementSet).has().allOf("a", "f").inOrder(); ASSERT.that(subset).isEmpty(); assertEquals(3, ms.size()); } public void testCustomComparator() throws Exception { Comparator<String> comparator = new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }; TreeMultiset<String> ms = TreeMultiset.create(comparator); ms.add("b"); ms.add("c"); ms.add("a"); ms.add("b"); ms.add("d"); ASSERT.that(ms).has().allOf("d", "c", "b", "b", "a").inOrder(); SortedSet<String> elementSet = ms.elementSet(); assertEquals("d", elementSet.first()); assertEquals("a", elementSet.last()); assertEquals(comparator, elementSet.comparator()); } public void testNullAcceptingComparator() throws Exception { Comparator<String> comparator = Ordering.<String>natural().nullsFirst(); TreeMultiset<String> ms = TreeMultiset.create(comparator); ms.add("b"); ms.add(null); ms.add("a"); ms.add("b"); ms.add(null, 2); ASSERT.that(ms).has().allOf(null, null, null, "a", "b", "b").inOrder(); assertEquals(3, ms.count(null)); SortedSet<String> elementSet = ms.elementSet(); assertEquals(null, elementSet.first()); assertEquals("b", elementSet.last()); assertEquals(comparator, elementSet.comparator()); } private static final Comparator<String> DEGENERATE_COMPARATOR = new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.length() - o2.length(); } }; /** * Test a TreeMultiset with a comparator that can return 0 when comparing * unequal values. */ public void testDegenerateComparator() throws Exception { TreeMultiset<String> ms = TreeMultiset.create(DEGENERATE_COMPARATOR); ms.add("foo"); ms.add("a"); ms.add("bar"); ms.add("b"); ms.add("c"); assertEquals(2, ms.count("bar")); assertEquals(3, ms.count("b")); Multiset<String> ms2 = TreeMultiset.create(DEGENERATE_COMPARATOR); ms2.add("cat", 2); ms2.add("x", 3); assertEquals(ms, ms2); assertEquals(ms2, ms); SortedSet<String> elementSet = ms.elementSet(); assertEquals("a", elementSet.first()); assertEquals("foo", elementSet.last()); assertEquals(DEGENERATE_COMPARATOR, elementSet.comparator()); } public void testSubMultisetSize() { TreeMultiset<String> ms = TreeMultiset.create(); ms.add("a", Integer.MAX_VALUE); ms.add("b", Integer.MAX_VALUE); ms.add("c", 3); assertEquals(Integer.MAX_VALUE, ms.count("a")); assertEquals(Integer.MAX_VALUE, ms.count("b")); assertEquals(3, ms.count("c")); assertEquals(Integer.MAX_VALUE, ms.headMultiset("c", CLOSED).size()); assertEquals(Integer.MAX_VALUE, ms.headMultiset("b", CLOSED).size()); assertEquals(Integer.MAX_VALUE, ms.headMultiset("a", CLOSED).size()); assertEquals(3, ms.tailMultiset("c", CLOSED).size()); assertEquals(Integer.MAX_VALUE, ms.tailMultiset("b", CLOSED).size()); assertEquals(Integer.MAX_VALUE, ms.tailMultiset("a", CLOSED).size()); } @Override public void testToStringNull() { c = ms = TreeMultiset.create(Ordering.natural().nullsFirst()); super.testToStringNull(); } @GwtIncompatible("reflection") public void testElementSetBridgeMethods() { for (Method m : TreeMultiset.class.getMethods()) { if (m.getName().equals("elementSet") && m.getReturnType().equals(SortedSet.class)) { return; } } fail("No bridge method found"); } }