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 java.util.Arrays.asList; 20 21 import com.google.common.annotations.GwtIncompatible; 22 import com.google.common.base.Objects; 23 import com.google.common.base.Predicate; 24 import com.google.common.base.Predicates; 25 import com.google.common.collect.testing.features.CollectionFeature; 26 import com.google.common.collect.testing.features.CollectionSize; 27 import com.google.common.collect.testing.google.MultisetTestSuiteBuilder; 28 import com.google.common.collect.testing.google.SortedMultisetTestSuiteBuilder; 29 import com.google.common.collect.testing.google.TestStringMultisetGenerator; 30 31 import junit.framework.Test; 32 import junit.framework.TestCase; 33 import junit.framework.TestSuite; 34 35 import java.util.ArrayList; 36 import java.util.Collections; 37 import java.util.List; 38 39 /** 40 * Collection tests on wrappers from {@link Multisets}. 41 * 42 * @author Jared Levy 43 */ 44 @GwtIncompatible("suite") // TODO(cpovirk): set up collect/gwt/suites version 45 public class MultisetsCollectionTest extends TestCase { 46 public static Test suite() { 47 TestSuite suite = new TestSuite(); 48 49 suite.addTest(MultisetTestSuiteBuilder.using( 50 unmodifiableMultisetGenerator()) 51 .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, 52 CollectionFeature.SERIALIZABLE, 53 CollectionFeature.ALLOWS_NULL_QUERIES) 54 .named("Multisets.unmodifiableMultiset[LinkedHashMultiset]") 55 .createTestSuite()); 56 57 suite.addTest(SortedMultisetTestSuiteBuilder.using(unmodifiableSortedMultisetGenerator()) 58 .withFeatures(CollectionSize.ANY, CollectionFeature.KNOWN_ORDER, 59 CollectionFeature.ALLOWS_NULL_QUERIES) 60 .named("Multisets.unmodifiableMultiset[TreeMultiset]") 61 .createTestSuite()); 62 63 suite.addTest(MultisetTestSuiteBuilder.using(unionGenerator()) 64 .withFeatures(CollectionSize.ANY, 65 CollectionFeature.ALLOWS_NULL_VALUES) 66 .named("Multisets.union") 67 .createTestSuite()); 68 69 suite.addTest(MultisetTestSuiteBuilder.using(intersectionGenerator()) 70 .withFeatures(CollectionSize.ANY, 71 CollectionFeature.ALLOWS_NULL_VALUES, 72 CollectionFeature.KNOWN_ORDER) 73 .named("Multisets.intersection") 74 .createTestSuite()); 75 76 suite.addTest(MultisetTestSuiteBuilder.using(sumGenerator()) 77 .withFeatures(CollectionSize.ANY, 78 CollectionFeature.ALLOWS_NULL_VALUES) 79 .named("Multisets.sum") 80 .createTestSuite()); 81 82 suite.addTest(MultisetTestSuiteBuilder.using(differenceGenerator()) 83 .withFeatures(CollectionSize.ANY, 84 CollectionFeature.ALLOWS_NULL_VALUES, 85 CollectionFeature.KNOWN_ORDER) 86 .named("Multisets.difference") 87 .createTestSuite()); 88 89 suite.addTest(MultisetTestSuiteBuilder.using(filteredGenerator()) 90 .withFeatures(CollectionSize.ANY, 91 CollectionFeature.ALLOWS_NULL_VALUES, 92 CollectionFeature.KNOWN_ORDER, 93 CollectionFeature.SUPPORTS_ADD, 94 CollectionFeature.SUPPORTS_REMOVE) 95 .named("Multiset.filter[Multiset, Predicate]") 96 .createTestSuite()); 97 98 return suite; 99 } 100 101 private static TestStringMultisetGenerator unmodifiableMultisetGenerator() { 102 return new TestStringMultisetGenerator() { 103 @Override protected Multiset<String> create(String[] elements) { 104 return Multisets.unmodifiableMultiset( 105 LinkedHashMultiset.create(asList(elements))); 106 } 107 @Override public List<String> order(List<String> insertionOrder) { 108 List<String> order = new ArrayList<String>(); 109 for (String s : insertionOrder) { 110 int index = order.indexOf(s); 111 if (index == -1) { 112 order.add(s); 113 } else { 114 order.add(index, s); 115 } 116 } 117 return order; 118 } 119 }; 120 } 121 122 private static TestStringMultisetGenerator unmodifiableSortedMultisetGenerator() { 123 return new TestStringMultisetGenerator() { 124 @Override protected Multiset<String> create(String[] elements) { 125 return Multisets.unmodifiableSortedMultiset( 126 TreeMultiset.create(asList(elements))); 127 } 128 @Override public List<String> order(List<String> insertionOrder) { 129 Collections.sort(insertionOrder); 130 return insertionOrder; 131 } 132 }; 133 } 134 135 private static TestStringMultisetGenerator unionGenerator() { 136 return new TestStringMultisetGenerator() { 137 @Override 138 protected Multiset<String> create(String[] elements) { 139 Multiset<String> multiset1 = LinkedHashMultiset.create(); 140 Multiset<String> multiset2 = LinkedHashMultiset.create(); 141 for (int i = 0; i < elements.length; i++) { 142 String element = elements[i]; 143 if (multiset1.contains(element) || 144 multiset2.contains(element)) { 145 // add to both; the one already containing it will have more 146 multiset1.add(element); 147 multiset2.add(element); 148 } else if (i % 2 == 0) { 149 multiset1.add(elements[i]); 150 } else { 151 multiset2.add(elements[i]); 152 } 153 } 154 return Multisets.union(multiset1, multiset2); 155 } 156 }; 157 } 158 159 private static TestStringMultisetGenerator intersectionGenerator() { 160 return new TestStringMultisetGenerator() { 161 @Override protected Multiset<String> create(String[] elements) { 162 Multiset<String> multiset1 = LinkedHashMultiset.create(); 163 Multiset<String> multiset2 = LinkedHashMultiset.create(); 164 multiset1.add("only1"); 165 multiset2.add("only2"); 166 for (int i = 0; i < elements.length; i++) { 167 multiset1.add(elements[i]); 168 multiset2.add(elements[elements.length - 1 - i]); 169 } 170 if (elements.length > 0) { 171 multiset1.add(elements[0]); 172 } 173 if (elements.length > 1) { 174 /* 175 * When a test requests a multiset with duplicates, our plan of 176 * "add an extra item 0 to A and an extra item 1 to B" really means 177 * "add an extra item 0 to A and B," which isn't what we want. 178 */ 179 if (!Objects.equal(elements[0], elements[1])) { 180 multiset2.add(elements[1], 2); 181 } 182 } 183 return Multisets.intersection(multiset1, multiset2); 184 } 185 }; 186 } 187 188 private static TestStringMultisetGenerator sumGenerator() { 189 return new TestStringMultisetGenerator() { 190 @Override protected Multiset<String> create(String[] elements) { 191 Multiset<String> multiset1 = LinkedHashMultiset.create(); 192 Multiset<String> multiset2 = LinkedHashMultiset.create(); 193 for (int i = 0; i < elements.length; i++) { 194 // add to either; sum should contain all 195 if (i % 2 == 0) { 196 multiset1.add(elements[i]); 197 } else { 198 multiset2.add(elements[i]); 199 } 200 } 201 return Multisets.sum(multiset1, multiset2); 202 } 203 }; 204 } 205 206 private static TestStringMultisetGenerator differenceGenerator() { 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("equalIn1"); 212 multiset1.add("fewerIn1"); 213 multiset2.add("equalIn1"); 214 multiset2.add("fewerIn1", 3); 215 multiset2.add("onlyIn2", 2); 216 for (int i = 0; i < elements.length; i++) { 217 // add 1 more copy of each element to multiset1 than multiset2 218 multiset1.add(elements[i], i + 2); 219 multiset2.add(elements[i], i + 1); 220 } 221 return Multisets.difference(multiset1, multiset2); 222 } 223 }; 224 } 225 226 private static final Multiset<String> ELEMENTS_TO_FILTER_OUT = ImmutableMultiset.of( 227 "foobar", "bazfoo", "foobar", "foobar"); 228 229 private static final Predicate<String> PREDICATE = 230 Predicates.not(Predicates.in(ELEMENTS_TO_FILTER_OUT)); 231 232 private static TestStringMultisetGenerator filteredGenerator() { 233 return new TestStringMultisetGenerator() { 234 @Override 235 protected Multiset<String> create(String[] elements) { 236 Multiset<String> multiset = LinkedHashMultiset.create(); 237 Collections.addAll(multiset, elements); 238 multiset.addAll(ELEMENTS_TO_FILTER_OUT); 239 return Multisets.filter(multiset, PREDICATE); 240 } 241 242 @Override 243 public List<String> order(List<String> insertionOrder) { 244 return Lists.newArrayList(LinkedHashMultiset.create(insertionOrder)); 245 } 246 }; 247 } 248 } 249