Coverage Summary for Class: SortedMultisetTestSuiteBuilder (com.google.common.collect.testing.google)

Class Method, % Line, %
SortedMultisetTestSuiteBuilder 0% (0/10) 0% (0/83)
SortedMultisetTestSuiteBuilder$1 0% (0/2) 0% (0/26)
SortedMultisetTestSuiteBuilder$2 0% (0/3) 0% (0/3)
SortedMultisetTestSuiteBuilder$3 0% (0/2) 0% (0/2)
SortedMultisetTestSuiteBuilder$Bound 0% (0/1) 0% (0/4)
SortedMultisetTestSuiteBuilder$ForwardingTestMultisetGenerator 0% (0/5) 0% (0/6)
SortedMultisetTestSuiteBuilder$NoRecurse 0% (0/2) 0% (0/4)
Total 0% (0/25) 0% (0/128)


1 /* 2  * Copyright (C) 2011 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5  * use this file except in compliance with the License. You may obtain a copy of 6  * 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, WITHOUT 12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13  * License for the specific language governing permissions and limitations under 14  * the License. 15  */ 16  17 package com.google.common.collect.testing.google; 18  19 import static com.google.common.collect.testing.features.CollectionFeature.KNOWN_ORDER; 20 import static com.google.common.collect.testing.features.CollectionFeature.RESTRICTS_ELEMENTS; 21 import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE; 22 import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS; 23  24 import com.google.common.annotations.GwtIncompatible; 25 import com.google.common.collect.BoundType; 26 import com.google.common.collect.ImmutableList; 27 import com.google.common.collect.Lists; 28 import com.google.common.collect.Multiset; 29 import com.google.common.collect.SortedMultiset; 30 import com.google.common.collect.testing.AbstractTester; 31 import com.google.common.collect.testing.FeatureSpecificTestSuiteBuilder; 32 import com.google.common.collect.testing.Helpers; 33 import com.google.common.collect.testing.OneSizeTestContainerGenerator; 34 import com.google.common.collect.testing.SampleElements; 35 import com.google.common.collect.testing.SetTestSuiteBuilder; 36 import com.google.common.collect.testing.features.Feature; 37 import com.google.common.testing.SerializableTester; 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.Collection; 41 import java.util.Collections; 42 import java.util.Comparator; 43 import java.util.HashSet; 44 import java.util.List; 45 import java.util.Set; 46 import junit.framework.TestSuite; 47  48 /** 49  * Creates, based on your criteria, a JUnit test suite that exhaustively tests a {@code 50  * SortedMultiset} implementation. 51  * 52  * <p><b>Warning:</b> expects that {@code E} is a String. 53  * 54  * @author Louis Wasserman 55  */ 56 @GwtIncompatible 57 public class SortedMultisetTestSuiteBuilder<E> extends MultisetTestSuiteBuilder<E> { 58  public static <E> SortedMultisetTestSuiteBuilder<E> using(TestMultisetGenerator<E> generator) { 59  SortedMultisetTestSuiteBuilder<E> result = new SortedMultisetTestSuiteBuilder<E>(); 60  result.usingGenerator(generator); 61  return result; 62  } 63  64  @Override 65  public TestSuite createTestSuite() { 66  withFeatures(KNOWN_ORDER); 67  TestSuite suite = super.createTestSuite(); 68  for (TestSuite subSuite : createDerivedSuites(this)) { 69  suite.addTest(subSuite); 70  } 71  return suite; 72  } 73  74  @Override 75  protected List<Class<? extends AbstractTester>> getTesters() { 76  List<Class<? extends AbstractTester>> testers = Helpers.copyToList(super.getTesters()); 77  testers.add(MultisetNavigationTester.class); 78  return testers; 79  } 80  81  @Override 82  TestSuite createElementSetTestSuite( 83  FeatureSpecificTestSuiteBuilder<?, ? extends OneSizeTestContainerGenerator<Collection<E>, E>> 84  parentBuilder) { 85  // TODO(lowasser): make a SortedElementSetGenerator 86  return SetTestSuiteBuilder.using( 87  new ElementSetGenerator<E>(parentBuilder.getSubjectGenerator())) 88  .named(getName() + ".elementSet") 89  .withFeatures(computeElementSetFeatures(parentBuilder.getFeatures())) 90  .suppressing(parentBuilder.getSuppressedTests()) 91  .createTestSuite(); 92  } 93  94  /** 95  * To avoid infinite recursion, test suites with these marker features won't have derived suites 96  * created for them. 97  */ 98  enum NoRecurse implements Feature<Void> { 99  SUBMULTISET, 100  DESCENDING; 101  102  @Override 103  public Set<Feature<? super Void>> getImpliedFeatures() { 104  return Collections.emptySet(); 105  } 106  } 107  108  /** Two bounds (from and to) define how to build a subMultiset. */ 109  enum Bound { 110  INCLUSIVE, 111  EXCLUSIVE, 112  NO_BOUND; 113  } 114  115  List<TestSuite> createDerivedSuites(SortedMultisetTestSuiteBuilder<E> parentBuilder) { 116  List<TestSuite> derivedSuites = Lists.newArrayList(); 117  118  if (!parentBuilder.getFeatures().contains(NoRecurse.DESCENDING)) { 119  derivedSuites.add(createDescendingSuite(parentBuilder)); 120  } 121  122  if (parentBuilder.getFeatures().contains(SERIALIZABLE)) { 123  derivedSuites.add(createReserializedSuite(parentBuilder)); 124  } 125  126  if (!parentBuilder.getFeatures().contains(NoRecurse.SUBMULTISET)) { 127  derivedSuites.add(createSubMultisetSuite(parentBuilder, Bound.NO_BOUND, Bound.EXCLUSIVE)); 128  derivedSuites.add(createSubMultisetSuite(parentBuilder, Bound.NO_BOUND, Bound.INCLUSIVE)); 129  derivedSuites.add(createSubMultisetSuite(parentBuilder, Bound.EXCLUSIVE, Bound.NO_BOUND)); 130  derivedSuites.add(createSubMultisetSuite(parentBuilder, Bound.EXCLUSIVE, Bound.EXCLUSIVE)); 131  derivedSuites.add(createSubMultisetSuite(parentBuilder, Bound.EXCLUSIVE, Bound.INCLUSIVE)); 132  derivedSuites.add(createSubMultisetSuite(parentBuilder, Bound.INCLUSIVE, Bound.NO_BOUND)); 133  derivedSuites.add(createSubMultisetSuite(parentBuilder, Bound.INCLUSIVE, Bound.EXCLUSIVE)); 134  derivedSuites.add(createSubMultisetSuite(parentBuilder, Bound.INCLUSIVE, Bound.INCLUSIVE)); 135  } 136  137  return derivedSuites; 138  } 139  140  private TestSuite createSubMultisetSuite( 141  SortedMultisetTestSuiteBuilder<E> parentBuilder, final Bound from, final Bound to) { 142  final TestMultisetGenerator<E> delegate = 143  (TestMultisetGenerator<E>) parentBuilder.getSubjectGenerator(); 144  145  Set<Feature<?>> features = new HashSet<>(); 146  features.add(NoRecurse.SUBMULTISET); 147  features.add(RESTRICTS_ELEMENTS); 148  features.addAll(parentBuilder.getFeatures()); 149  150  if (!features.remove(SERIALIZABLE_INCLUDING_VIEWS)) { 151  features.remove(SERIALIZABLE); 152  } 153  154  SortedMultiset<E> emptyMultiset = (SortedMultiset<E>) delegate.create(); 155  final Comparator<? super E> comparator = emptyMultiset.comparator(); 156  SampleElements<E> samples = delegate.samples(); 157  @SuppressWarnings("unchecked") 158  List<E> samplesList = 159  Arrays.asList(samples.e0(), samples.e1(), samples.e2(), samples.e3(), samples.e4()); 160  161  Collections.sort(samplesList, comparator); 162  final E firstInclusive = samplesList.get(0); 163  final E lastInclusive = samplesList.get(samplesList.size() - 1); 164  165  return SortedMultisetTestSuiteBuilder.using( 166  new ForwardingTestMultisetGenerator<E>(delegate) { 167  @Override 168  public SortedMultiset<E> create(Object... entries) { 169  @SuppressWarnings("unchecked") 170  // we dangerously assume E is a string 171  List<E> extremeValues = (List<E>) getExtremeValues(); 172  @SuppressWarnings("unchecked") 173  // map generators must past entry objects 174  List<E> normalValues = (List<E>) Arrays.asList(entries); 175  176  // prepare extreme values to be filtered out of view 177  Collections.sort(extremeValues, comparator); 178  E firstExclusive = extremeValues.get(1); 179  E lastExclusive = extremeValues.get(2); 180  if (from == Bound.NO_BOUND) { 181  extremeValues.remove(0); 182  extremeValues.remove(0); 183  } 184  if (to == Bound.NO_BOUND) { 185  extremeValues.remove(extremeValues.size() - 1); 186  extremeValues.remove(extremeValues.size() - 1); 187  } 188  189  // the regular values should be visible after filtering 190  List<E> allEntries = new ArrayList<E>(); 191  allEntries.addAll(extremeValues); 192  allEntries.addAll(normalValues); 193  SortedMultiset<E> multiset = 194  (SortedMultiset<E>) delegate.create(allEntries.toArray()); 195  196  // call the smallest subMap overload that filters out the extreme 197  // values 198  if (from == Bound.INCLUSIVE) { 199  multiset = multiset.tailMultiset(firstInclusive, BoundType.CLOSED); 200  } else if (from == Bound.EXCLUSIVE) { 201  multiset = multiset.tailMultiset(firstExclusive, BoundType.OPEN); 202  } 203  204  if (to == Bound.INCLUSIVE) { 205  multiset = multiset.headMultiset(lastInclusive, BoundType.CLOSED); 206  } else if (to == Bound.EXCLUSIVE) { 207  multiset = multiset.headMultiset(lastExclusive, BoundType.OPEN); 208  } 209  210  return multiset; 211  } 212  }) 213  .named(parentBuilder.getName() + " subMultiset " + from + "-" + to) 214  .withFeatures(features) 215  .suppressing(parentBuilder.getSuppressedTests()) 216  .createTestSuite(); 217  } 218  219  /** 220  * Returns an array of four bogus elements that will always be too high or too low for the 221  * display. This includes two values for each extreme. 222  * 223  * <p>This method (dangerously) assume that the strings {@code "!! a"} and {@code "~~ z"} will 224  * work for this purpose, which may cause problems for navigable maps with non-string or unicode 225  * generators. 226  */ 227  private List<String> getExtremeValues() { 228  List<String> result = new ArrayList<>(); 229  result.add("!! a"); 230  result.add("!! b"); 231  result.add("~~ y"); 232  result.add("~~ z"); 233  return result; 234  } 235  236  private TestSuite createDescendingSuite(SortedMultisetTestSuiteBuilder<E> parentBuilder) { 237  final TestMultisetGenerator<E> delegate = 238  (TestMultisetGenerator<E>) parentBuilder.getSubjectGenerator(); 239  240  Set<Feature<?>> features = new HashSet<>(); 241  features.add(NoRecurse.DESCENDING); 242  features.addAll(parentBuilder.getFeatures()); 243  if (!features.remove(SERIALIZABLE_INCLUDING_VIEWS)) { 244  features.remove(SERIALIZABLE); 245  } 246  247  return SortedMultisetTestSuiteBuilder.using( 248  new ForwardingTestMultisetGenerator<E>(delegate) { 249  @Override 250  public SortedMultiset<E> create(Object... entries) { 251  return ((SortedMultiset<E>) super.create(entries)).descendingMultiset(); 252  } 253  254  @Override 255  public Iterable<E> order(List<E> insertionOrder) { 256  return ImmutableList.copyOf(super.order(insertionOrder)).reverse(); 257  } 258  }) 259  .named(parentBuilder.getName() + " descending") 260  .withFeatures(features) 261  .suppressing(parentBuilder.getSuppressedTests()) 262  .createTestSuite(); 263  } 264  265  private TestSuite createReserializedSuite(SortedMultisetTestSuiteBuilder<E> parentBuilder) { 266  final TestMultisetGenerator<E> delegate = 267  (TestMultisetGenerator<E>) parentBuilder.getSubjectGenerator(); 268  269  Set<Feature<?>> features = new HashSet<>(parentBuilder.getFeatures()); 270  features.remove(SERIALIZABLE); 271  features.remove(SERIALIZABLE_INCLUDING_VIEWS); 272  273  return SortedMultisetTestSuiteBuilder.using( 274  new ForwardingTestMultisetGenerator<E>(delegate) { 275  @Override 276  public SortedMultiset<E> create(Object... entries) { 277  return SerializableTester.reserialize(((SortedMultiset<E>) super.create(entries))); 278  } 279  }) 280  .named(parentBuilder.getName() + " reserialized") 281  .withFeatures(features) 282  .suppressing(parentBuilder.getSuppressedTests()) 283  .createTestSuite(); 284  } 285  286  private static class ForwardingTestMultisetGenerator<E> implements TestMultisetGenerator<E> { 287  private final TestMultisetGenerator<E> delegate; 288  289  ForwardingTestMultisetGenerator(TestMultisetGenerator<E> delegate) { 290  this.delegate = delegate; 291  } 292  293  @Override 294  public SampleElements<E> samples() { 295  return delegate.samples(); 296  } 297  298  @Override 299  public E[] createArray(int length) { 300  return delegate.createArray(length); 301  } 302  303  @Override 304  public Iterable<E> order(List<E> insertionOrder) { 305  return delegate.order(insertionOrder); 306  } 307  308  @Override 309  public Multiset<E> create(Object... elements) { 310  return delegate.create(elements); 311  } 312  } 313 }