11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2010 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect.testing;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.testing.features.Feature;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.testing.testers.MapNavigationTester;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestSuite;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.ArrayList;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Comparator;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map.Entry;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.NavigableMap;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Creates, based on your criteria, a JUnit test suite that exhaustively tests
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * a NavigableMap implementation.
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class NavigableMapTestSuiteBuilder<K, V> extends MapTestSuiteBuilder<K, V> {
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public static <K, V> NavigableMapTestSuiteBuilder<K, V> using(
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      TestMapGenerator<K, V> generator) {
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    NavigableMapTestSuiteBuilder<K, V> result = new NavigableMapTestSuiteBuilder<K, V>();
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    result.usingGenerator(generator);
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return result;
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override protected List<Class<? extends AbstractTester>> getTesters() {
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<Class<? extends AbstractTester>> testers = Helpers.copyToList(super.getTesters());
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    testers.add(MapNavigationTester.class);
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return testers;
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override List<TestSuite> createDerivedSuites(FeatureSpecificTestSuiteBuilder<?,
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>> parentBuilder) {
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<TestSuite> derivedSuites = super.createDerivedSuites(parentBuilder);
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!parentBuilder.getFeatures().contains(NoRecurse.DESCENDING)) {
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createDescendingSuite(parentBuilder));
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!parentBuilder.getFeatures().contains(NoRecurse.SUBMAP)) {
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createSubmapSuite(parentBuilder, Bound.NO_BOUND, Bound.EXCLUSIVE));
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createSubmapSuite(parentBuilder, Bound.NO_BOUND, Bound.INCLUSIVE));
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createSubmapSuite(parentBuilder, Bound.EXCLUSIVE, Bound.NO_BOUND));
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createSubmapSuite(parentBuilder, Bound.EXCLUSIVE, Bound.EXCLUSIVE));
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createSubmapSuite(parentBuilder, Bound.EXCLUSIVE, Bound.INCLUSIVE));
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createSubmapSuite(parentBuilder, Bound.INCLUSIVE, Bound.NO_BOUND));
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createSubmapSuite(parentBuilder, Bound.INCLUSIVE, Bound.EXCLUSIVE));
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      derivedSuites.add(createSubmapSuite(parentBuilder, Bound.INCLUSIVE, Bound.INCLUSIVE));
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return derivedSuites;
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override protected SetTestSuiteBuilder<K> createDerivedKeySetSuite(
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      TestSetGenerator<K> keySetGenerator) {
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return NavigableSetTestSuiteBuilder.using(keySetGenerator);
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * To avoid infinite recursion, test suites with these marker features won't
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * have derived suites created for them.
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  enum NoRecurse implements Feature<Void> {
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SUBMAP,
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    DESCENDING;
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Set<Feature<? super Void>> getImpliedFeatures() {
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Collections.emptySet();
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Two bounds (from and to) define how to build a subMap.
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  enum Bound {
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    INCLUSIVE,
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    EXCLUSIVE,
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    NO_BOUND;
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a suite whose map has some elements filtered out of view.
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Because the map may be ascending or descending, this test must derive
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the relative order of these extreme values rather than relying on their
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * regular sort ordering.
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private TestSuite createSubmapSuite(final FeatureSpecificTestSuiteBuilder<?,
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>>
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          parentBuilder, final Bound from, final Bound to) {
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final TestMapGenerator<K, V> delegate
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        = (TestMapGenerator<K, V>) parentBuilder.getSubjectGenerator().getInnerGenerator();
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<Feature<?>> features = new ArrayList<Feature<?>>();
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    features.add(NoRecurse.SUBMAP);
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    features.addAll(parentBuilder.getFeatures());
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    NavigableMap<K, V> emptyMap = (NavigableMap<K, V>) delegate.create();
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Comparator<Entry<K, V>> entryComparator = Helpers.entryComparator(emptyMap.comparator());
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // derive values for inclusive filtering from the input samples
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SampleElements<Entry<K, V>> samples = delegate.samples();
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @SuppressWarnings("unchecked") // no elements are inserted into the array
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<Entry<K, V>> samplesList = Arrays.asList(
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        samples.e0, samples.e1, samples.e2, samples.e3, samples.e4);
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Collections.sort(samplesList, entryComparator);
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final K firstInclusive = samplesList.get(0).getKey();
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final K lastInclusive = samplesList.get(samplesList.size() - 1).getKey();
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return NavigableMapTestSuiteBuilder
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .using(new ForwardingTestMapGenerator<K, V>(delegate) {
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override public Map<K, V> create(Object... entries) {
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            @SuppressWarnings("unchecked") // we dangerously assume K and V are both strings
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            List<Entry<K, V>> extremeValues = (List) getExtremeValues();
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            @SuppressWarnings("unchecked") // map generators must past entry objects
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            List<Entry<K, V>> normalValues = (List) Arrays.asList(entries);
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // prepare extreme values to be filtered out of view
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            Collections.sort(extremeValues, entryComparator);
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            K firstExclusive = extremeValues.get(1).getKey();
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            K lastExclusive = extremeValues.get(2).getKey();
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (from == Bound.NO_BOUND) {
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              extremeValues.remove(0);
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              extremeValues.remove(0);
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (to == Bound.NO_BOUND) {
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              extremeValues.remove(extremeValues.size() - 1);
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              extremeValues.remove(extremeValues.size() - 1);
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // the regular values should be visible after filtering
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            List<Entry<K, V>> allEntries = new ArrayList<Entry<K, V>>();
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            allEntries.addAll(extremeValues);
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            allEntries.addAll(normalValues);
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            NavigableMap<K, V> map = (NavigableMap<K, V>)
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                delegate.create((Object[])
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    allEntries.toArray(new Entry[allEntries.size()]));
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // call the smallest subMap overload that filters out the extreme values
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (from == Bound.NO_BOUND && to == Bound.EXCLUSIVE) {
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return map.headMap(lastExclusive);
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (from == Bound.NO_BOUND && to == Bound.INCLUSIVE) {
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return map.headMap(lastInclusive, true);
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (from == Bound.EXCLUSIVE && to == Bound.NO_BOUND) {
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return map.tailMap(firstExclusive, false);
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (from == Bound.EXCLUSIVE && to == Bound.EXCLUSIVE) {
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return map.subMap(firstExclusive, false, lastExclusive, false);
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (from == Bound.EXCLUSIVE && to == Bound.INCLUSIVE) {
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return map.subMap(firstExclusive, false, lastInclusive, true);
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (from == Bound.INCLUSIVE && to == Bound.NO_BOUND) {
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return map.tailMap(firstInclusive);
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (from == Bound.INCLUSIVE && to == Bound.EXCLUSIVE) {
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return map.subMap(firstInclusive, lastExclusive);
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (from == Bound.INCLUSIVE && to == Bound.INCLUSIVE) {
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return map.subMap(firstInclusive, true, lastInclusive, true);
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else {
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              throw new IllegalArgumentException();
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        })
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .named(parentBuilder.getName() + " subMap " + from + "-" + to)
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .withFeatures(features)
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .suppressing(parentBuilder.getSuppressedTests())
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .createTestSuite();
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns an array of four bogus elements that will always be too high or
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * too low for the display. This includes two values for each extreme.
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This method (dangerously) assume that the strings {@code "!! a"} and
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code "~~ z"} will work for this purpose, which may cause problems for
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * navigable maps with non-string or unicode generators.
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private List<Entry<String, String>> getExtremeValues() {
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<Entry<String, String>> result = new ArrayList<Entry<String, String>>();
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    result.add(Helpers.mapEntry("!! a", "below view"));
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    result.add(Helpers.mapEntry("!! b", "below view"));
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    result.add(Helpers.mapEntry("~~ y", "above view"));
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    result.add(Helpers.mapEntry("~~ z", "above view"));
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return result;
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Create a suite whose maps are descending views of other maps.
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private TestSuite createDescendingSuite(final FeatureSpecificTestSuiteBuilder<?,
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>> parentBuilder) {
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final TestMapGenerator<K, V> delegate
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        = (TestMapGenerator<K, V>) parentBuilder.getSubjectGenerator().getInnerGenerator();
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<Feature<?>> features = new ArrayList<Feature<?>>();
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    features.add(NoRecurse.DESCENDING);
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    features.addAll(parentBuilder.getFeatures());
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return NavigableMapTestSuiteBuilder
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .using(new ForwardingTestMapGenerator<K, V>(delegate) {
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override public Map<K, V> create(Object... entries) {
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            NavigableMap<K, V> map = (NavigableMap<K, V>) delegate.create(entries);
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return map.descendingMap();
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        })
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .named(parentBuilder.getName() + " descending")
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .withFeatures(features)
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .suppressing(parentBuilder.getSuppressedTests())
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .createTestSuite();
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class ForwardingTestMapGenerator<K, V> implements TestMapGenerator<K, V> {
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private TestMapGenerator<K, V> delegate;
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ForwardingTestMapGenerator(TestMapGenerator<K, V> delegate) {
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.delegate = delegate;
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) {
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.order(insertionOrder);
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public K[] createKeyArray(int length) {
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.createKeyArray(length);
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V[] createValueArray(int length) {
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.createValueArray(length);
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public SampleElements<Entry<K, V>> samples() {
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.samples();
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Map<K, V> create(Object... elements) {
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.create(elements);
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Entry<K, V>[] createArray(int length) {
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate.createArray(length);
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
268