Home | History | Annotate | Download | only in google
      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.testing.google;
     18 
     19 import static com.google.common.base.Preconditions.checkArgument;
     20 
     21 import com.google.common.collect.Multiset;
     22 import com.google.common.collect.Multiset.Entry;
     23 import com.google.common.collect.Multisets;
     24 import com.google.common.collect.testing.AbstractCollectionTestSuiteBuilder;
     25 import com.google.common.collect.testing.AbstractTester;
     26 import com.google.common.collect.testing.FeatureSpecificTestSuiteBuilder;
     27 import com.google.common.collect.testing.Helpers;
     28 import com.google.common.collect.testing.OneSizeTestContainerGenerator;
     29 import com.google.common.collect.testing.SampleElements;
     30 import com.google.common.collect.testing.SetTestSuiteBuilder;
     31 import com.google.common.collect.testing.TestSetGenerator;
     32 import com.google.common.collect.testing.features.CollectionFeature;
     33 import com.google.common.collect.testing.features.Feature;
     34 import com.google.common.collect.testing.testers.CollectionSerializationEqualTester;
     35 import com.google.common.testing.SerializableTester;
     36 
     37 import junit.framework.TestSuite;
     38 
     39 import java.util.ArrayList;
     40 import java.util.Collection;
     41 import java.util.Collections;
     42 import java.util.HashSet;
     43 import java.util.LinkedHashMap;
     44 import java.util.LinkedHashSet;
     45 import java.util.List;
     46 import java.util.Map;
     47 import java.util.Set;
     48 
     49 /**
     50  * Creates, based on your criteria, a JUnit test suite that exhaustively tests
     51  * a {@code Multiset} implementation.
     52  *
     53  * @author Jared Levy
     54  * @author Louis Wasserman
     55  */
     56 public class MultisetTestSuiteBuilder<E> extends
     57     AbstractCollectionTestSuiteBuilder<MultisetTestSuiteBuilder<E>, E> {
     58   public static <E> MultisetTestSuiteBuilder<E> using(
     59       TestMultisetGenerator<E> generator) {
     60     return new MultisetTestSuiteBuilder<E>().usingGenerator(generator);
     61   }
     62 
     63   public enum NoRecurse implements Feature<Void> {
     64     NO_ENTRY_SET;
     65 
     66     @Override
     67     public Set<Feature<? super Void>> getImpliedFeatures() {
     68       return Collections.emptySet();
     69     }
     70   }
     71 
     72   @Override protected List<Class<? extends AbstractTester>> getTesters() {
     73     List<Class<? extends AbstractTester>> testers
     74         = Helpers.copyToList(super.getTesters());
     75     testers.add(CollectionSerializationEqualTester.class);
     76     testers.add(MultisetAddTester.class);
     77     testers.add(MultisetContainsTester.class);
     78     testers.add(MultisetCountTester.class);
     79     testers.add(MultisetElementSetTester.class);
     80     testers.add(MultisetEqualsTester.class);
     81     testers.add(MultisetReadsTester.class);
     82     testers.add(MultisetSetCountConditionallyTester.class);
     83     testers.add(MultisetSetCountUnconditionallyTester.class);
     84     testers.add(MultisetRemoveTester.class);
     85     testers.add(MultisetEntrySetTester.class);
     86     testers.add(MultisetIteratorTester.class);
     87     testers.add(MultisetSerializationTester.class);
     88     return testers;
     89   }
     90 
     91   private static Set<Feature<?>> computeEntrySetFeatures(
     92       Set<Feature<?>> features) {
     93     Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
     94     derivedFeatures.addAll(features);
     95     derivedFeatures.remove(CollectionFeature.GENERAL_PURPOSE);
     96     derivedFeatures.remove(CollectionFeature.SUPPORTS_ADD);
     97     derivedFeatures.remove(CollectionFeature.ALLOWS_NULL_VALUES);
     98     derivedFeatures.add(CollectionFeature.REJECTS_DUPLICATES_AT_CREATION);
     99     if (!derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) {
    100       derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
    101     }
    102     return derivedFeatures;
    103   }
    104 
    105   static Set<Feature<?>> computeElementSetFeatures(
    106       Set<Feature<?>> features) {
    107     Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
    108     derivedFeatures.addAll(features);
    109     derivedFeatures.remove(CollectionFeature.GENERAL_PURPOSE);
    110     derivedFeatures.remove(CollectionFeature.SUPPORTS_ADD);
    111     if (!derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS)) {
    112       derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
    113     }
    114     return derivedFeatures;
    115   }
    116 
    117   private static Set<Feature<?>> computeReserializedMultisetFeatures(
    118       Set<Feature<?>> features) {
    119     Set<Feature<?>> derivedFeatures = new HashSet<Feature<?>>();
    120     derivedFeatures.addAll(features);
    121     derivedFeatures.remove(CollectionFeature.SERIALIZABLE);
    122     derivedFeatures.remove(CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS);
    123     return derivedFeatures;
    124   }
    125 
    126   @Override
    127   protected List<TestSuite> createDerivedSuites(FeatureSpecificTestSuiteBuilder<
    128       ?, ? extends OneSizeTestContainerGenerator<Collection<E>, E>> parentBuilder) {
    129     List<TestSuite> derivedSuites = new ArrayList<TestSuite>(
    130         super.createDerivedSuites(parentBuilder));
    131 
    132     derivedSuites.add(createElementSetTestSuite(parentBuilder));
    133 
    134     if (!parentBuilder.getFeatures().contains(NoRecurse.NO_ENTRY_SET)) {
    135       derivedSuites.add(
    136           SetTestSuiteBuilder.using(new EntrySetGenerator<E>(parentBuilder.getSubjectGenerator()))
    137               .named(getName() + ".entrySet")
    138               .withFeatures(computeEntrySetFeatures(parentBuilder.getFeatures()))
    139               .suppressing(parentBuilder.getSuppressedTests())
    140               .createTestSuite());
    141     }
    142 
    143     if (parentBuilder.getFeatures().contains(CollectionFeature.SERIALIZABLE)) {
    144       derivedSuites.add(MultisetTestSuiteBuilder
    145           .using(new ReserializedMultisetGenerator<E>(parentBuilder.getSubjectGenerator()))
    146           .named(getName() + " reserialized")
    147           .withFeatures(computeReserializedMultisetFeatures(parentBuilder.getFeatures()))
    148           .suppressing(parentBuilder.getSuppressedTests())
    149           .createTestSuite());
    150     }
    151     return derivedSuites;
    152   }
    153 
    154   TestSuite createElementSetTestSuite(FeatureSpecificTestSuiteBuilder<
    155       ?, ? extends OneSizeTestContainerGenerator<Collection<E>, E>> parentBuilder) {
    156     return SetTestSuiteBuilder
    157         .using(new ElementSetGenerator<E>(parentBuilder.getSubjectGenerator()))
    158         .named(getName() + ".elementSet")
    159         .withFeatures(computeElementSetFeatures(parentBuilder.getFeatures()))
    160         .suppressing(parentBuilder.getSuppressedTests())
    161         .createTestSuite();
    162   }
    163 
    164   static class ElementSetGenerator<E> implements TestSetGenerator<E> {
    165     final OneSizeTestContainerGenerator<Collection<E>, E> gen;
    166 
    167     ElementSetGenerator(OneSizeTestContainerGenerator<Collection<E>, E> gen) {
    168       this.gen = gen;
    169     }
    170 
    171     @Override
    172     public SampleElements<E> samples() {
    173       return gen.samples();
    174     }
    175 
    176     @Override
    177     public Set<E> create(Object... elements) {
    178       Object[] duplicated = new Object[elements.length * 2];
    179       for (int i = 0; i < elements.length; i++) {
    180         duplicated[i] = elements[i];
    181         duplicated[i + elements.length] = elements[i];
    182       }
    183       return ((Multiset<E>) gen.create(duplicated)).elementSet();
    184     }
    185 
    186     @Override
    187     public E[] createArray(int length) {
    188       return gen.createArray(length);
    189     }
    190 
    191     @Override
    192     public Iterable<E> order(List<E> insertionOrder) {
    193       return gen.order(new ArrayList<E>(new LinkedHashSet<E>(insertionOrder)));
    194     }
    195   }
    196 
    197   static class EntrySetGenerator<E> implements TestSetGenerator<Multiset.Entry<E>> {
    198     final OneSizeTestContainerGenerator<Collection<E>, E> gen;
    199 
    200     private EntrySetGenerator(OneSizeTestContainerGenerator<Collection<E>, E> gen) {
    201       this.gen = gen;
    202     }
    203 
    204     @Override
    205     public SampleElements<Multiset.Entry<E>> samples() {
    206       SampleElements<E> samples = gen.samples();
    207       return new SampleElements<Multiset.Entry<E>>(
    208           Multisets.immutableEntry(samples.e0, 3),
    209           Multisets.immutableEntry(samples.e1, 4),
    210           Multisets.immutableEntry(samples.e2, 1),
    211           Multisets.immutableEntry(samples.e3, 5),
    212           Multisets.immutableEntry(samples.e4, 2));
    213     }
    214 
    215     @Override
    216     public Set<Multiset.Entry<E>> create(Object... entries) {
    217       List<Object> contents = new ArrayList<Object>();
    218       Set<E> elements = new HashSet<E>();
    219       for (Object o : entries) {
    220         @SuppressWarnings("unchecked")
    221         Multiset.Entry<E> entry = (Entry<E>) o;
    222         checkArgument(elements.add(entry.getElement()),
    223             "Duplicate keys not allowed in EntrySetGenerator");
    224         for (int i = 0; i < entry.getCount(); i++) {
    225           contents.add(entry.getElement());
    226         }
    227       }
    228       return ((Multiset<E>) gen.create(contents.toArray())).entrySet();
    229     }
    230 
    231     @SuppressWarnings("unchecked")
    232     @Override
    233     public Multiset.Entry<E>[] createArray(int length) {
    234       return new Multiset.Entry[length];
    235     }
    236 
    237     @Override
    238     public Iterable<Entry<E>> order(List<Entry<E>> insertionOrder) {
    239       // We mimic the order from gen.
    240       Map<E, Entry<E>> map = new LinkedHashMap<E, Entry<E>>();
    241       for (Entry<E> entry : insertionOrder) {
    242         map.put(entry.getElement(), entry);
    243       }
    244 
    245       Set<E> seen = new HashSet<E>();
    246       List<Entry<E>> order = new ArrayList<Entry<E>>();
    247       for (E e : gen.order(new ArrayList<E>(map.keySet()))) {
    248         if (seen.add(e)) {
    249           order.add(map.get(e));
    250         }
    251       }
    252       return order;
    253     }
    254   }
    255 
    256   static class ReserializedMultisetGenerator<E> implements TestMultisetGenerator<E>{
    257     final OneSizeTestContainerGenerator<Collection<E>, E> gen;
    258 
    259     private ReserializedMultisetGenerator(OneSizeTestContainerGenerator<Collection<E>, E> gen) {
    260       this.gen = gen;
    261     }
    262 
    263     @Override
    264     public SampleElements<E> samples() {
    265       return gen.samples();
    266     }
    267 
    268     @Override
    269     public Multiset<E> create(Object... elements) {
    270       return (Multiset<E>) SerializableTester.reserialize(gen.create(elements));
    271     }
    272 
    273     @Override
    274     public E[] createArray(int length) {
    275       return gen.createArray(length);
    276     }
    277 
    278     @Override
    279     public Iterable<E> order(List<E> insertionOrder) {
    280       return gen.order(insertionOrder);
    281     }
    282   }
    283 }
    284 
    285