Java
289 строк · 12.1 Кб
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
17package com.google.common.collect.testing;
18
19import static com.google.common.collect.testing.DerivedCollectionGenerators.keySetGenerator;
20
21import com.google.common.annotations.GwtIncompatible;
22import com.google.common.collect.testing.DerivedCollectionGenerators.MapEntrySetGenerator;
23import com.google.common.collect.testing.DerivedCollectionGenerators.MapValueCollectionGenerator;
24import com.google.common.collect.testing.features.CollectionFeature;
25import com.google.common.collect.testing.features.CollectionSize;
26import com.google.common.collect.testing.features.Feature;
27import com.google.common.collect.testing.features.MapFeature;
28import com.google.common.collect.testing.testers.MapClearTester;
29import com.google.common.collect.testing.testers.MapComputeIfAbsentTester;
30import com.google.common.collect.testing.testers.MapComputeIfPresentTester;
31import com.google.common.collect.testing.testers.MapComputeTester;
32import com.google.common.collect.testing.testers.MapContainsKeyTester;
33import com.google.common.collect.testing.testers.MapContainsValueTester;
34import com.google.common.collect.testing.testers.MapCreationTester;
35import com.google.common.collect.testing.testers.MapEntrySetTester;
36import com.google.common.collect.testing.testers.MapEqualsTester;
37import com.google.common.collect.testing.testers.MapForEachTester;
38import com.google.common.collect.testing.testers.MapGetOrDefaultTester;
39import com.google.common.collect.testing.testers.MapGetTester;
40import com.google.common.collect.testing.testers.MapHashCodeTester;
41import com.google.common.collect.testing.testers.MapIsEmptyTester;
42import com.google.common.collect.testing.testers.MapMergeTester;
43import com.google.common.collect.testing.testers.MapPutAllTester;
44import com.google.common.collect.testing.testers.MapPutIfAbsentTester;
45import com.google.common.collect.testing.testers.MapPutTester;
46import com.google.common.collect.testing.testers.MapRemoveEntryTester;
47import com.google.common.collect.testing.testers.MapRemoveTester;
48import com.google.common.collect.testing.testers.MapReplaceAllTester;
49import com.google.common.collect.testing.testers.MapReplaceEntryTester;
50import com.google.common.collect.testing.testers.MapReplaceTester;
51import com.google.common.collect.testing.testers.MapSerializationTester;
52import com.google.common.collect.testing.testers.MapSizeTester;
53import com.google.common.collect.testing.testers.MapToStringTester;
54import com.google.common.testing.SerializableTester;
55import java.util.Arrays;
56import java.util.HashSet;
57import java.util.List;
58import java.util.Map;
59import java.util.Map.Entry;
60import java.util.Set;
61import junit.framework.TestSuite;
62
63/**
64* Creates, based on your criteria, a JUnit test suite that exhaustively tests a Map implementation.
65*
66* @author George van den Driessche
67*/
68@GwtIncompatible
69public class MapTestSuiteBuilder<K, V>
70extends PerCollectionSizeTestSuiteBuilder<
71MapTestSuiteBuilder<K, V>, TestMapGenerator<K, V>, Map<K, V>, Entry<K, V>> {
72public static <K, V> MapTestSuiteBuilder<K, V> using(TestMapGenerator<K, V> generator) {
73return new MapTestSuiteBuilder<K, V>().usingGenerator(generator);
74}
75
76@SuppressWarnings("rawtypes") // class literals
77@Override
78protected List<Class<? extends AbstractTester>> getTesters() {
79return Arrays.<Class<? extends AbstractTester>>asList(
80MapClearTester.class,
81MapComputeTester.class,
82MapComputeIfAbsentTester.class,
83MapComputeIfPresentTester.class,
84MapContainsKeyTester.class,
85MapContainsValueTester.class,
86MapCreationTester.class,
87MapEntrySetTester.class,
88MapEqualsTester.class,
89MapForEachTester.class,
90MapGetTester.class,
91MapGetOrDefaultTester.class,
92MapHashCodeTester.class,
93MapIsEmptyTester.class,
94MapMergeTester.class,
95MapPutTester.class,
96MapPutAllTester.class,
97MapPutIfAbsentTester.class,
98MapRemoveTester.class,
99MapRemoveEntryTester.class,
100MapReplaceTester.class,
101MapReplaceAllTester.class,
102MapReplaceEntryTester.class,
103MapSerializationTester.class,
104MapSizeTester.class,
105MapToStringTester.class);
106}
107
108@Override
109protected List<TestSuite> createDerivedSuites(
110FeatureSpecificTestSuiteBuilder<
111?, ? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>>
112parentBuilder) {
113// TODO: Once invariant support is added, supply invariants to each of the
114// derived suites, to check that mutations to the derived collections are
115// reflected in the underlying map.
116
117List<TestSuite> derivedSuites = super.createDerivedSuites(parentBuilder);
118
119if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
120derivedSuites.add(
121MapTestSuiteBuilder.using(
122new ReserializedMapGenerator<K, V>(parentBuilder.getSubjectGenerator()))
123.withFeatures(computeReserializedMapFeatures(parentBuilder.getFeatures()))
124.named(parentBuilder.getName() + " reserialized")
125.suppressing(parentBuilder.getSuppressedTests())
126.withSetUp(parentBuilder.getSetUp())
127.withTearDown(parentBuilder.getTearDown())
128.createTestSuite());
129}
130
131derivedSuites.add(
132createDerivedEntrySetSuite(
133new MapEntrySetGenerator<K, V>(parentBuilder.getSubjectGenerator()))
134.withFeatures(computeEntrySetFeatures(parentBuilder.getFeatures()))
135.named(parentBuilder.getName() + " entrySet")
136.suppressing(parentBuilder.getSuppressedTests())
137.withSetUp(parentBuilder.getSetUp())
138.withTearDown(parentBuilder.getTearDown())
139.createTestSuite());
140
141derivedSuites.add(
142createDerivedKeySetSuite(keySetGenerator(parentBuilder.getSubjectGenerator()))
143.withFeatures(computeKeySetFeatures(parentBuilder.getFeatures()))
144.named(parentBuilder.getName() + " keys")
145.suppressing(parentBuilder.getSuppressedTests())
146.withSetUp(parentBuilder.getSetUp())
147.withTearDown(parentBuilder.getTearDown())
148.createTestSuite());
149
150derivedSuites.add(
151createDerivedValueCollectionSuite(
152new MapValueCollectionGenerator<K, V>(parentBuilder.getSubjectGenerator()))
153.named(parentBuilder.getName() + " values")
154.withFeatures(computeValuesCollectionFeatures(parentBuilder.getFeatures()))
155.suppressing(parentBuilder.getSuppressedTests())
156.withSetUp(parentBuilder.getSetUp())
157.withTearDown(parentBuilder.getTearDown())
158.createTestSuite());
159
160return derivedSuites;
161}
162
163protected SetTestSuiteBuilder<Entry<K, V>> createDerivedEntrySetSuite(
164TestSetGenerator<Entry<K, V>> entrySetGenerator) {
165return SetTestSuiteBuilder.using(entrySetGenerator);
166}
167
168protected SetTestSuiteBuilder<K> createDerivedKeySetSuite(TestSetGenerator<K> keySetGenerator) {
169return SetTestSuiteBuilder.using(keySetGenerator);
170}
171
172protected CollectionTestSuiteBuilder<V> createDerivedValueCollectionSuite(
173TestCollectionGenerator<V> valueCollectionGenerator) {
174return CollectionTestSuiteBuilder.using(valueCollectionGenerator);
175}
176
177private static Set<Feature<?>> computeReserializedMapFeatures(Set<Feature<?>> mapFeatures) {
178Set<Feature<?>> derivedFeatures = Helpers.copyToSet(mapFeatures);
179derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
180derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
181return derivedFeatures;
182}
183
184private static Set<Feature<?>> computeEntrySetFeatures(Set<Feature<?>> mapFeatures) {
185Set<Feature<?>> entrySetFeatures = computeCommonDerivedCollectionFeatures(mapFeatures);
186if (mapFeatures.contains(MapFeature.ALLOWS_NULL_ENTRY_QUERIES)) {
187entrySetFeatures.add(CollectionFeature.ALLOWS_NULL_QUERIES);
188}
189return entrySetFeatures;
190}
191
192private static Set<Feature<?>> computeKeySetFeatures(Set<Feature<?>> mapFeatures) {
193Set<Feature<?>> keySetFeatures = computeCommonDerivedCollectionFeatures(mapFeatures);
194
195// TODO(lowasser): make this trigger only if the map is a submap
196// currently, the KeySetGenerator won't work properly for a subset of a keyset of a submap
197keySetFeatures.add(CollectionFeature.SUBSET_VIEW);
198if (mapFeatures.contains(MapFeature.ALLOWS_NULL_KEYS)) {
199keySetFeatures.add(CollectionFeature.ALLOWS_NULL_VALUES);
200} else if (mapFeatures.contains(MapFeature.ALLOWS_NULL_KEY_QUERIES)) {
201keySetFeatures.add(CollectionFeature.ALLOWS_NULL_QUERIES);
202}
203
204return keySetFeatures;
205}
206
207private static Set<Feature<?>> computeValuesCollectionFeatures(Set<Feature<?>> mapFeatures) {
208Set<Feature<?>> valuesCollectionFeatures = computeCommonDerivedCollectionFeatures(mapFeatures);
209if (mapFeatures.contains(MapFeature.ALLOWS_NULL_VALUE_QUERIES)) {
210valuesCollectionFeatures.add(CollectionFeature.ALLOWS_NULL_QUERIES);
211}
212if (mapFeatures.contains(MapFeature.ALLOWS_NULL_VALUES)) {
213valuesCollectionFeatures.add(CollectionFeature.ALLOWS_NULL_VALUES);
214}
215
216return valuesCollectionFeatures;
217}
218
219public static Set<Feature<?>> computeCommonDerivedCollectionFeatures(
220Set<Feature<?>> mapFeatures) {
221mapFeatures = new HashSet<>(mapFeatures);
222Set<Feature<?>> derivedFeatures = new HashSet<>();
223mapFeatures.remove(CollectionFeature.SERIALIZABLE);
224if (mapFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) {
225derivedFeatures.add(CollectionFeature.SERIALIZABLE);
226}
227if (mapFeatures.contains(MapFeature.SUPPORTS_REMOVE)) {
228derivedFeatures.add(CollectionFeature.SUPPORTS_REMOVE);
229}
230if (mapFeatures.contains(MapFeature.REJECTS_DUPLICATES_AT_CREATION)) {
231derivedFeatures.add(CollectionFeature.REJECTS_DUPLICATES_AT_CREATION);
232}
233if (mapFeatures.contains(MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION)) {
234derivedFeatures.add(CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION);
235}
236// add the intersection of CollectionFeature.values() and mapFeatures
237for (CollectionFeature feature : CollectionFeature.values()) {
238if (mapFeatures.contains(feature)) {
239derivedFeatures.add(feature);
240}
241}
242// add the intersection of CollectionSize.values() and mapFeatures
243for (CollectionSize size : CollectionSize.values()) {
244if (mapFeatures.contains(size)) {
245derivedFeatures.add(size);
246}
247}
248return derivedFeatures;
249}
250
251private static class ReserializedMapGenerator<K, V> implements TestMapGenerator<K, V> {
252private final OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>> mapGenerator;
253
254public ReserializedMapGenerator(
255OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>> mapGenerator) {
256this.mapGenerator = mapGenerator;
257}
258
259@Override
260public SampleElements<Entry<K, V>> samples() {
261return mapGenerator.samples();
262}
263
264@Override
265public Entry<K, V>[] createArray(int length) {
266return mapGenerator.createArray(length);
267}
268
269@Override
270public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) {
271return mapGenerator.order(insertionOrder);
272}
273
274@Override
275public Map<K, V> create(Object... elements) {
276return SerializableTester.reserialize(mapGenerator.create(elements));
277}
278
279@Override
280public K[] createKeyArray(int length) {
281return ((TestMapGenerator<K, V>) mapGenerator.getInnerGenerator()).createKeyArray(length);
282}
283
284@Override
285public V[] createValueArray(int length) {
286return ((TestMapGenerator<K, V>) mapGenerator.getInnerGenerator()).createValueArray(length);
287}
288}
289}
290