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 17 package com.google.common.collect; 18 19 import static com.google.common.collect.testing.google.AbstractMultisetSetCountTester.getSetCountDuplicateInitializingMethods; 20 import static com.google.common.collect.testing.google.MultisetIteratorTester.getIteratorDuplicateInitializingMethods; 21 import static com.google.common.collect.testing.google.MultisetReadsTester.getReadsDuplicateInitializingMethods; 22 import static java.util.Arrays.asList; 23 24 import com.google.common.annotations.GwtIncompatible; 25 import com.google.common.collect.testing.AnEnum; 26 import com.google.common.collect.testing.features.CollectionFeature; 27 import com.google.common.collect.testing.features.CollectionSize; 28 import com.google.common.collect.testing.google.MultisetTestSuiteBuilder; 29 import com.google.common.collect.testing.google.SortedMultisetTestSuiteBuilder; 30 import com.google.common.collect.testing.google.TestEnumMultisetGenerator; 31 import com.google.common.collect.testing.google.TestStringMultisetGenerator; 32 33 import junit.framework.Test; 34 import junit.framework.TestCase; 35 import junit.framework.TestSuite; 36 37 import java.util.Arrays; 38 import java.util.Collections; 39 import java.util.List; 40 41 /** 42 * Collection tests for {@link Multiset} implementations. 43 * 44 * @author Jared Levy 45 */ 46 @GwtIncompatible("suite") // TODO(cpovirk): set up collect/gwt/suites version 47 public class MultisetCollectionTest extends TestCase { 48 49 public static Test suite() { 50 TestSuite suite = new TestSuite(); 51 52 suite.addTest(MultisetTestSuiteBuilder.using(hashMultisetGenerator()) 53 .withFeatures(CollectionSize.ANY, 54 CollectionFeature.ALLOWS_NULL_VALUES, 55 CollectionFeature.GENERAL_PURPOSE) 56 .named("HashMultiset") 57 .createTestSuite()); 58 59 suite.addTest(MultisetTestSuiteBuilder.using( 60 unmodifiableMultisetGenerator()) 61 .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, 62 CollectionFeature.ALLOWS_NULL_QUERIES) 63 .named("UnmodifiableTreeMultiset") 64 .createTestSuite()); 65 66 suite.addTest(SortedMultisetTestSuiteBuilder 67 .using(new TestStringMultisetGenerator() { 68 @Override 69 protected Multiset<String> create(String[] elements) { 70 return TreeMultiset.create(Arrays.asList(elements)); 71 } 72 73 @Override 74 public List<String> order(List<String> insertionOrder) { 75 return Ordering.natural().sortedCopy(insertionOrder); 76 } 77 }) 78 .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, 79 CollectionFeature.GENERAL_PURPOSE, 80 CollectionFeature.ALLOWS_NULL_QUERIES) 81 .named("TreeMultiset, Ordering.natural") 82 .createTestSuite()); 83 84 85 suite.addTest(SortedMultisetTestSuiteBuilder 86 .using(new TestStringMultisetGenerator() { 87 @Override 88 protected Multiset<String> create(String[] elements) { 89 Multiset<String> result = TreeMultiset.create(Ordering.natural().nullsFirst()); 90 result.addAll(Arrays.asList(elements)); 91 return result; 92 } 93 94 @Override 95 public List<String> order(List<String> insertionOrder) { 96 return Ordering.natural().nullsFirst().sortedCopy(insertionOrder); 97 } 98 }) 99 .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, 100 CollectionFeature.GENERAL_PURPOSE, 101 CollectionFeature.ALLOWS_NULL_VALUES) 102 .named("TreeMultiset, Ordering.natural.nullsFirst") 103 .createTestSuite()); 104 105 suite.addTest(MultisetTestSuiteBuilder.using(forSetGenerator()) 106 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES, 107 CollectionFeature.REMOVE_OPERATIONS) 108 .suppressing(getReadsDuplicateInitializingMethods()) 109 .suppressing(getSetCountDuplicateInitializingMethods()) 110 .suppressing(getIteratorDuplicateInitializingMethods()) 111 .named("ForSetMultiset") 112 .createTestSuite()); 113 114 suite.addTest(MultisetTestSuiteBuilder.using( 115 concurrentMultisetGenerator()) 116 .withFeatures(CollectionSize.ANY, 117 CollectionFeature.GENERAL_PURPOSE, 118 CollectionFeature.ALLOWS_NULL_QUERIES) 119 .named("ConcurrentHashMultiset") 120 .createTestSuite()); 121 122 suite.addTest(MultisetTestSuiteBuilder.using(enumMultisetGenerator()) 123 .withFeatures(CollectionSize.ANY, 124 CollectionFeature.KNOWN_ORDER, 125 CollectionFeature.GENERAL_PURPOSE, 126 CollectionFeature.ALLOWS_NULL_QUERIES) 127 .named("EnumMultiset") 128 .createTestSuite()); 129 130 suite.addTest(MultisetTestSuiteBuilder.using(intersectionGenerator()) 131 .withFeatures(CollectionSize.ANY, 132 CollectionFeature.ALLOWS_NULL_VALUES, 133 CollectionFeature.KNOWN_ORDER) 134 .named("IntersectionMultiset") 135 .createTestSuite()); 136 137 suite.addTest(SortedMultisetTestSuiteBuilder.using(unmodifiableSortedMultisetGenerator()) 138 .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, 139 CollectionFeature.ALLOWS_NULL_QUERIES) 140 .named("UnmodifiableSortedTreeMultiset") 141 .createTestSuite()); 142 143 return suite; 144 } 145 146 private static TestStringMultisetGenerator hashMultisetGenerator() { 147 return new TestStringMultisetGenerator() { 148 @Override protected Multiset<String> create(String[] elements) { 149 return HashMultiset.create(asList(elements)); 150 } 151 }; 152 } 153 154 private static TestStringMultisetGenerator unmodifiableMultisetGenerator() { 155 return new TestStringMultisetGenerator() { 156 @Override protected Multiset<String> create(String[] elements) { 157 return Multisets.unmodifiableMultiset( 158 TreeMultiset.create(asList(elements))); 159 } 160 @Override public List<String> order(List<String> insertionOrder) { 161 Collections.sort(insertionOrder); 162 return insertionOrder; 163 } 164 }; 165 } 166 167 private static TestStringMultisetGenerator unmodifiableSortedMultisetGenerator() { 168 return new TestStringMultisetGenerator() { 169 @Override protected Multiset<String> create(String[] elements) { 170 return Multisets.unmodifiableSortedMultiset( 171 TreeMultiset.create(asList(elements))); 172 } 173 @Override public List<String> order(List<String> insertionOrder) { 174 Collections.sort(insertionOrder); 175 return insertionOrder; 176 } 177 }; 178 } 179 180 private static TestStringMultisetGenerator forSetGenerator() { 181 return new TestStringMultisetGenerator() { 182 @Override protected Multiset<String> create(String[] elements) { 183 return Multisets.forSet(Sets.newHashSet(elements)); 184 } 185 }; 186 } 187 188 private static TestStringMultisetGenerator concurrentMultisetGenerator() { 189 return new TestStringMultisetGenerator() { 190 @Override protected Multiset<String> create(String[] elements) { 191 return ConcurrentHashMultiset.create(asList(elements)); 192 } 193 }; 194 } 195 196 private static TestEnumMultisetGenerator enumMultisetGenerator() { 197 return new TestEnumMultisetGenerator() { 198 @Override protected Multiset<AnEnum> create(AnEnum[] elements) { 199 return (elements.length == 0) 200 ? EnumMultiset.create(AnEnum.class) 201 : EnumMultiset.create(asList(elements)); 202 } 203 }; 204 } 205 206 private static TestStringMultisetGenerator intersectionGenerator() { 207 return new TestStringMultisetGenerator() { 208 @Override protected Multiset<String> create(String[] elements) { 209 Multiset<String> multiset1 = LinkedHashMultiset.create(); 210 Multiset<String> multiset2 = LinkedHashMultiset.create(); 211 multiset1.add("only1"); 212 multiset2.add("only2"); 213 for (int i = 0; i < elements.length; i++) { 214 multiset1.add(elements[i]); 215 multiset2.add(elements[elements.length - 1 - i]); 216 } 217 if (elements.length > 0) { 218 multiset1.add(elements[0]); 219 } 220 if (elements.length > 1) { 221 /* 222 * When a test requests a multiset with duplicates, our plan of 223 * "add an extra item 0 to A and an extra item 1 to B" really means 224 * "add an extra item 0 to A and B," which isn't what we want. 225 */ 226 if (!elements[0].equals(elements[1])) { 227 multiset2.add(elements[1], 2); 228 } 229 } 230 return Multisets.intersection(multiset1, multiset2); 231 } 232 }; 233 } 234 } 235