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 17 package com.google.common.collect; 18 19 import static com.google.common.collect.BoundType.CLOSED; 20 import static com.google.common.truth.Truth.assertThat; 21 import static java.util.Collections.sort; 22 23 import com.google.common.annotations.GwtCompatible; 24 import com.google.common.annotations.GwtIncompatible; 25 import com.google.common.annotations.J2ktIncompatible; 26 import com.google.common.collect.testing.Helpers.NullsBeforeB; 27 import com.google.common.collect.testing.NavigableSetTestSuiteBuilder; 28 import com.google.common.collect.testing.TestStringSetGenerator; 29 import com.google.common.collect.testing.features.CollectionFeature; 30 import com.google.common.collect.testing.features.CollectionSize; 31 import com.google.common.collect.testing.google.MultisetFeature; 32 import com.google.common.collect.testing.google.SortedMultisetTestSuiteBuilder; 33 import com.google.common.collect.testing.google.TestStringMultisetGenerator; 34 import java.lang.reflect.Method; 35 import java.util.Arrays; 36 import java.util.Collections; 37 import java.util.Comparator; 38 import java.util.List; 39 import java.util.Set; 40 import java.util.SortedSet; 41 import junit.framework.Test; 42 import junit.framework.TestCase; 43 import junit.framework.TestSuite; 44 import org.checkerframework.checker.nullness.qual.Nullable; 45 46 /** 47 * Unit test for {@link TreeMultiset}. 48 * 49 * @author Neal Kanodia 50 */ 51 @GwtCompatible(emulated = true) 52 @ElementTypesAreNonnullByDefault 53 public class TreeMultisetTest extends TestCase { 54 55 @J2ktIncompatible 56 @GwtIncompatible // suite suite()57 public static Test suite() { 58 TestSuite suite = new TestSuite(); 59 suite.addTest( 60 SortedMultisetTestSuiteBuilder.using( 61 new TestStringMultisetGenerator() { 62 @Override 63 protected Multiset<String> create(String[] elements) { 64 return TreeMultiset.create(Arrays.asList(elements)); 65 } 66 67 @Override 68 public List<String> order(List<String> insertionOrder) { 69 return Ordering.natural().sortedCopy(insertionOrder); 70 } 71 }) 72 .withFeatures( 73 CollectionSize.ANY, 74 CollectionFeature.KNOWN_ORDER, 75 CollectionFeature.GENERAL_PURPOSE, 76 CollectionFeature.SERIALIZABLE, 77 CollectionFeature.ALLOWS_NULL_QUERIES, 78 MultisetFeature.ENTRIES_ARE_VIEWS) 79 .named("TreeMultiset, Ordering.natural") 80 .createTestSuite()); 81 suite.addTest( 82 SortedMultisetTestSuiteBuilder.using( 83 new TestStringMultisetGenerator() { 84 @Override 85 protected Multiset<String> create(String[] elements) { 86 Multiset<String> result = TreeMultiset.create(NullsBeforeB.INSTANCE); 87 Collections.addAll(result, elements); 88 return result; 89 } 90 91 @Override 92 public List<String> order(List<String> insertionOrder) { 93 sort(insertionOrder, NullsBeforeB.INSTANCE); 94 return insertionOrder; 95 } 96 }) 97 .withFeatures( 98 CollectionSize.ANY, 99 CollectionFeature.KNOWN_ORDER, 100 CollectionFeature.GENERAL_PURPOSE, 101 CollectionFeature.SERIALIZABLE, 102 CollectionFeature.ALLOWS_NULL_VALUES, 103 MultisetFeature.ENTRIES_ARE_VIEWS) 104 .named("TreeMultiset, NullsBeforeB") 105 .createTestSuite()); 106 suite.addTest( 107 NavigableSetTestSuiteBuilder.using( 108 new TestStringSetGenerator() { 109 @Override 110 protected Set<String> create(String[] elements) { 111 return TreeMultiset.create(Arrays.asList(elements)).elementSet(); 112 } 113 114 @Override 115 public List<String> order(List<String> insertionOrder) { 116 return Lists.newArrayList(Sets.newTreeSet(insertionOrder)); 117 } 118 }) 119 .named("TreeMultiset[Ordering.natural].elementSet") 120 .withFeatures( 121 CollectionSize.ANY, 122 CollectionFeature.REMOVE_OPERATIONS, 123 CollectionFeature.ALLOWS_NULL_QUERIES) 124 .createTestSuite()); 125 suite.addTestSuite(TreeMultisetTest.class); 126 return suite; 127 } 128 testCreate()129 public void testCreate() { 130 TreeMultiset<String> multiset = TreeMultiset.create(); 131 multiset.add("foo", 2); 132 multiset.add("bar"); 133 assertEquals(3, multiset.size()); 134 assertEquals(2, multiset.count("foo")); 135 assertEquals(Ordering.natural(), multiset.comparator()); 136 assertEquals("[bar, foo x 2]", multiset.toString()); 137 } 138 testCreateWithComparator()139 public void testCreateWithComparator() { 140 Multiset<String> multiset = TreeMultiset.create(Collections.reverseOrder()); 141 multiset.add("foo", 2); 142 multiset.add("bar"); 143 assertEquals(3, multiset.size()); 144 assertEquals(2, multiset.count("foo")); 145 assertEquals("[foo x 2, bar]", multiset.toString()); 146 } 147 testCreateFromIterable()148 public void testCreateFromIterable() { 149 Multiset<String> multiset = TreeMultiset.create(Arrays.asList("foo", "bar", "foo")); 150 assertEquals(3, multiset.size()); 151 assertEquals(2, multiset.count("foo")); 152 assertEquals("[bar, foo x 2]", multiset.toString()); 153 } 154 testToString()155 public void testToString() { 156 Multiset<String> ms = TreeMultiset.create(); 157 ms.add("a", 3); 158 ms.add("c", 1); 159 ms.add("b", 2); 160 161 assertEquals("[a x 3, b x 2, c]", ms.toString()); 162 } 163 testElementSetSortedSetMethods()164 public void testElementSetSortedSetMethods() { 165 TreeMultiset<String> ms = TreeMultiset.create(); 166 ms.add("c", 1); 167 ms.add("a", 3); 168 ms.add("b", 2); 169 SortedSet<String> elementSet = ms.elementSet(); 170 171 assertEquals("a", elementSet.first()); 172 assertEquals("c", elementSet.last()); 173 assertEquals(Ordering.natural(), elementSet.comparator()); 174 175 assertThat(elementSet.headSet("b")).containsExactly("a"); 176 assertThat(elementSet.tailSet("b")).containsExactly("b", "c").inOrder(); 177 assertThat(elementSet.subSet("a", "c")).containsExactly("a", "b").inOrder(); 178 } 179 testElementSetSubsetRemove()180 public void testElementSetSubsetRemove() { 181 TreeMultiset<String> ms = TreeMultiset.create(); 182 ms.add("a", 1); 183 ms.add("b", 3); 184 ms.add("c", 2); 185 ms.add("d", 1); 186 ms.add("e", 3); 187 ms.add("f", 2); 188 189 SortedSet<String> elementSet = ms.elementSet(); 190 assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder(); 191 SortedSet<String> subset = elementSet.subSet("b", "f"); 192 assertThat(subset).containsExactly("b", "c", "d", "e").inOrder(); 193 194 assertTrue(subset.remove("c")); 195 assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder(); 196 assertThat(subset).containsExactly("b", "d", "e").inOrder(); 197 assertEquals(10, ms.size()); 198 199 assertFalse(subset.remove("a")); 200 assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder(); 201 assertThat(subset).containsExactly("b", "d", "e").inOrder(); 202 assertEquals(10, ms.size()); 203 } 204 testElementSetSubsetRemoveAll()205 public void testElementSetSubsetRemoveAll() { 206 TreeMultiset<String> ms = TreeMultiset.create(); 207 ms.add("a", 1); 208 ms.add("b", 3); 209 ms.add("c", 2); 210 ms.add("d", 1); 211 ms.add("e", 3); 212 ms.add("f", 2); 213 214 SortedSet<String> elementSet = ms.elementSet(); 215 assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder(); 216 SortedSet<String> subset = elementSet.subSet("b", "f"); 217 assertThat(subset).containsExactly("b", "c", "d", "e").inOrder(); 218 219 assertTrue(subset.removeAll(Arrays.asList("a", "c"))); 220 assertThat(elementSet).containsExactly("a", "b", "d", "e", "f").inOrder(); 221 assertThat(subset).containsExactly("b", "d", "e").inOrder(); 222 assertEquals(10, ms.size()); 223 } 224 testElementSetSubsetRetainAll()225 public void testElementSetSubsetRetainAll() { 226 TreeMultiset<String> ms = TreeMultiset.create(); 227 ms.add("a", 1); 228 ms.add("b", 3); 229 ms.add("c", 2); 230 ms.add("d", 1); 231 ms.add("e", 3); 232 ms.add("f", 2); 233 234 SortedSet<String> elementSet = ms.elementSet(); 235 assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder(); 236 SortedSet<String> subset = elementSet.subSet("b", "f"); 237 assertThat(subset).containsExactly("b", "c", "d", "e").inOrder(); 238 239 assertTrue(subset.retainAll(Arrays.asList("a", "c"))); 240 assertThat(elementSet).containsExactly("a", "c", "f").inOrder(); 241 assertThat(subset).containsExactly("c"); 242 assertEquals(5, ms.size()); 243 } 244 testElementSetSubsetClear()245 public void testElementSetSubsetClear() { 246 TreeMultiset<String> ms = TreeMultiset.create(); 247 ms.add("a", 1); 248 ms.add("b", 3); 249 ms.add("c", 2); 250 ms.add("d", 1); 251 ms.add("e", 3); 252 ms.add("f", 2); 253 254 SortedSet<String> elementSet = ms.elementSet(); 255 assertThat(elementSet).containsExactly("a", "b", "c", "d", "e", "f").inOrder(); 256 SortedSet<String> subset = elementSet.subSet("b", "f"); 257 assertThat(subset).containsExactly("b", "c", "d", "e").inOrder(); 258 259 subset.clear(); 260 assertThat(elementSet).containsExactly("a", "f").inOrder(); 261 assertThat(subset).isEmpty(); 262 assertEquals(3, ms.size()); 263 } 264 testCustomComparator()265 public void testCustomComparator() throws Exception { 266 Comparator<String> comparator = 267 new Comparator<String>() { 268 @Override 269 public int compare(String o1, String o2) { 270 return o2.compareTo(o1); 271 } 272 }; 273 TreeMultiset<String> ms = TreeMultiset.create(comparator); 274 275 ms.add("b"); 276 ms.add("c"); 277 ms.add("a"); 278 ms.add("b"); 279 ms.add("d"); 280 281 assertThat(ms).containsExactly("d", "c", "b", "b", "a").inOrder(); 282 283 SortedSet<String> elementSet = ms.elementSet(); 284 assertEquals("d", elementSet.first()); 285 assertEquals("a", elementSet.last()); 286 assertEquals(comparator, elementSet.comparator()); 287 } 288 testNullAcceptingComparator()289 public void testNullAcceptingComparator() throws Exception { 290 Comparator<@Nullable String> comparator = Ordering.<String>natural().<String>nullsFirst(); 291 TreeMultiset<@Nullable String> ms = TreeMultiset.create(comparator); 292 293 ms.add("b"); 294 ms.add(null); 295 ms.add("a"); 296 ms.add("b"); 297 ms.add(null, 2); 298 299 assertThat(ms).containsExactly(null, null, null, "a", "b", "b").inOrder(); 300 assertEquals(3, ms.count(null)); 301 302 SortedSet<@Nullable String> elementSet = ms.elementSet(); 303 assertEquals(null, elementSet.first()); 304 assertEquals("b", elementSet.last()); 305 assertEquals(comparator, elementSet.comparator()); 306 } 307 308 private static final Comparator<String> DEGENERATE_COMPARATOR = 309 new Comparator<String>() { 310 @Override 311 public int compare(String o1, String o2) { 312 return o1.length() - o2.length(); 313 } 314 }; 315 316 /** Test a TreeMultiset with a comparator that can return 0 when comparing unequal values. */ testDegenerateComparator()317 public void testDegenerateComparator() throws Exception { 318 TreeMultiset<String> ms = TreeMultiset.create(DEGENERATE_COMPARATOR); 319 320 ms.add("foo"); 321 ms.add("a"); 322 ms.add("bar"); 323 ms.add("b"); 324 ms.add("c"); 325 326 assertEquals(2, ms.count("bar")); 327 assertEquals(3, ms.count("b")); 328 329 Multiset<String> ms2 = TreeMultiset.create(DEGENERATE_COMPARATOR); 330 331 ms2.add("cat", 2); 332 ms2.add("x", 3); 333 334 assertEquals(ms, ms2); 335 assertEquals(ms2, ms); 336 337 SortedSet<String> elementSet = ms.elementSet(); 338 assertEquals("a", elementSet.first()); 339 assertEquals("foo", elementSet.last()); 340 assertEquals(DEGENERATE_COMPARATOR, elementSet.comparator()); 341 } 342 testSubMultisetSize()343 public void testSubMultisetSize() { 344 TreeMultiset<String> ms = TreeMultiset.create(); 345 ms.add("a", Integer.MAX_VALUE); 346 ms.add("b", Integer.MAX_VALUE); 347 ms.add("c", 3); 348 349 assertEquals(Integer.MAX_VALUE, ms.count("a")); 350 assertEquals(Integer.MAX_VALUE, ms.count("b")); 351 assertEquals(3, ms.count("c")); 352 353 assertEquals(Integer.MAX_VALUE, ms.headMultiset("c", CLOSED).size()); 354 assertEquals(Integer.MAX_VALUE, ms.headMultiset("b", CLOSED).size()); 355 assertEquals(Integer.MAX_VALUE, ms.headMultiset("a", CLOSED).size()); 356 357 assertEquals(3, ms.tailMultiset("c", CLOSED).size()); 358 assertEquals(Integer.MAX_VALUE, ms.tailMultiset("b", CLOSED).size()); 359 assertEquals(Integer.MAX_VALUE, ms.tailMultiset("a", CLOSED).size()); 360 } 361 362 @J2ktIncompatible 363 @GwtIncompatible // reflection 364 @AndroidIncompatible // Reflection bug, or actual binary compatibility problem? testElementSetBridgeMethods()365 public void testElementSetBridgeMethods() { 366 for (Method m : TreeMultiset.class.getMethods()) { 367 if (m.getName().equals("elementSet") && m.getReturnType().equals(SortedSet.class)) { 368 return; 369 } 370 } 371 fail("No bridge method found"); 372 } 373 } 374