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