1 /* 2 * Copyright (C) 2010 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; 18 19 import static com.google.common.collect.testing.Helpers.castOrCopyToList; 20 import static java.util.Collections.reverse; 21 22 import com.google.common.collect.testing.DerivedCollectionGenerators.Bound; 23 import com.google.common.collect.testing.DerivedCollectionGenerators.SortedMapSubmapTestMapGenerator; 24 import com.google.common.collect.testing.features.Feature; 25 import com.google.common.collect.testing.testers.NavigableMapNavigationTester; 26 27 import junit.framework.TestSuite; 28 29 import java.util.ArrayList; 30 import java.util.List; 31 import java.util.Map; 32 import java.util.Map.Entry; 33 import java.util.NavigableMap; 34 import java.util.SortedMap; 35 36 /** 37 * Creates, based on your criteria, a JUnit test suite that exhaustively tests 38 * a NavigableMap implementation. 39 */ 40 public class NavigableMapTestSuiteBuilder<K, V> extends SortedMapTestSuiteBuilder<K, V> { 41 public static <K, V> NavigableMapTestSuiteBuilder<K, V> using( 42 TestSortedMapGenerator<K, V> generator) { 43 NavigableMapTestSuiteBuilder<K, V> result = new NavigableMapTestSuiteBuilder<K, V>(); 44 result.usingGenerator(generator); 45 return result; 46 } 47 48 @Override protected List<Class<? extends AbstractTester>> getTesters() { 49 List<Class<? extends AbstractTester>> testers = Helpers.copyToList(super.getTesters()); 50 testers.add(NavigableMapNavigationTester.class); 51 return testers; 52 } 53 54 @Override 55 protected List<TestSuite> createDerivedSuites(FeatureSpecificTestSuiteBuilder<?, 56 ? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>> parentBuilder) { 57 List<TestSuite> derivedSuites = super.createDerivedSuites(parentBuilder); 58 59 if (!parentBuilder.getFeatures().contains(NoRecurse.DESCENDING)) { 60 derivedSuites.add(createDescendingSuite(parentBuilder)); 61 } 62 63 if (!parentBuilder.getFeatures().contains(NoRecurse.SUBMAP)) { 64 // Other combinations are inherited from SortedMapTestSuiteBuilder. 65 derivedSuites.add(createSubmapSuite(parentBuilder, Bound.NO_BOUND, Bound.INCLUSIVE)); 66 derivedSuites.add(createSubmapSuite(parentBuilder, Bound.EXCLUSIVE, Bound.NO_BOUND)); 67 derivedSuites.add(createSubmapSuite(parentBuilder, Bound.EXCLUSIVE, Bound.EXCLUSIVE)); 68 derivedSuites.add(createSubmapSuite(parentBuilder, Bound.EXCLUSIVE, Bound.INCLUSIVE)); 69 derivedSuites.add(createSubmapSuite(parentBuilder, Bound.INCLUSIVE, Bound.INCLUSIVE)); 70 } 71 72 return derivedSuites; 73 } 74 75 @Override protected NavigableSetTestSuiteBuilder<K> createDerivedKeySetSuite( 76 TestSetGenerator<K> keySetGenerator) { 77 return NavigableSetTestSuiteBuilder.using((TestSortedSetGenerator<K>) keySetGenerator); 78 } 79 80 public static final class NavigableMapSubmapTestMapGenerator<K, V> 81 extends SortedMapSubmapTestMapGenerator<K, V> { 82 public NavigableMapSubmapTestMapGenerator( 83 TestSortedMapGenerator<K, V> delegate, Bound to, Bound from) { 84 super(delegate, to, from); 85 } 86 87 @Override NavigableMap<K, V> createSubMap(SortedMap<K, V> sortedMap, K firstExclusive, 88 K lastExclusive) { 89 NavigableMap<K, V> map = (NavigableMap<K, V>) sortedMap; 90 if (from == Bound.NO_BOUND && to == Bound.INCLUSIVE) { 91 return map.headMap(lastInclusive, true); 92 } else if (from == Bound.EXCLUSIVE && to == Bound.NO_BOUND) { 93 return map.tailMap(firstExclusive, false); 94 } else if (from == Bound.EXCLUSIVE && to == Bound.EXCLUSIVE) { 95 return map.subMap(firstExclusive, false, lastExclusive, false); 96 } else if (from == Bound.EXCLUSIVE && to == Bound.INCLUSIVE) { 97 return map.subMap(firstExclusive, false, lastInclusive, true); 98 } else if (from == Bound.INCLUSIVE && to == Bound.INCLUSIVE) { 99 return map.subMap(firstInclusive, true, lastInclusive, true); 100 } else { 101 return (NavigableMap<K, V>) super.createSubMap(map, firstExclusive, lastExclusive); 102 } 103 } 104 } 105 106 @Override 107 public NavigableMapTestSuiteBuilder<K, V> newBuilderUsing( 108 TestSortedMapGenerator<K, V> delegate, Bound to, Bound from) { 109 return using(new NavigableMapSubmapTestMapGenerator<K, V>(delegate, to, from)); 110 } 111 112 /** 113 * Create a suite whose maps are descending views of other maps. 114 */ 115 private TestSuite createDescendingSuite(final FeatureSpecificTestSuiteBuilder<?, 116 ? extends OneSizeTestContainerGenerator<Map<K, V>, Entry<K, V>>> parentBuilder) { 117 final TestMapGenerator<K, V> delegate 118 = (TestMapGenerator<K, V>) parentBuilder.getSubjectGenerator().getInnerGenerator(); 119 120 List<Feature<?>> features = new ArrayList<Feature<?>>(); 121 features.add(NoRecurse.DESCENDING); 122 features.addAll(parentBuilder.getFeatures()); 123 124 return NavigableMapTestSuiteBuilder 125 .using(new ForwardingTestMapGenerator<K, V>(delegate) { 126 @Override public Map<K, V> create(Object... entries) { 127 NavigableMap<K, V> map = (NavigableMap<K, V>) delegate.create(entries); 128 return map.descendingMap(); 129 } 130 131 @Override 132 public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) { 133 insertionOrder = castOrCopyToList(delegate.order(insertionOrder)); 134 reverse(insertionOrder); 135 return insertionOrder; 136 } 137 }) 138 .named(parentBuilder.getName() + " descending") 139 .withFeatures(features) 140 .suppressing(parentBuilder.getSuppressedTests()) 141 .createTestSuite(); 142 } 143 144 static class ForwardingTestMapGenerator<K, V> implements TestMapGenerator<K, V> { 145 private TestMapGenerator<K, V> delegate; 146 147 ForwardingTestMapGenerator(TestMapGenerator<K, V> delegate) { 148 this.delegate = delegate; 149 } 150 151 @Override 152 public Iterable<Entry<K, V>> order(List<Entry<K, V>> insertionOrder) { 153 return delegate.order(insertionOrder); 154 } 155 156 @Override 157 public K[] createKeyArray(int length) { 158 return delegate.createKeyArray(length); 159 } 160 161 @Override 162 public V[] createValueArray(int length) { 163 return delegate.createValueArray(length); 164 } 165 166 @Override 167 public SampleElements<Entry<K, V>> samples() { 168 return delegate.samples(); 169 } 170 171 @Override 172 public Map<K, V> create(Object... elements) { 173 return delegate.create(elements); 174 } 175 176 @Override 177 public Entry<K, V>[] createArray(int length) { 178 return delegate.createArray(length); 179 } 180 } 181 } 182