001/* 002 * Copyright (C) 2010 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.google.common.collect.testing.testers; 018 019import static com.google.common.collect.testing.Helpers.copyToList; 020import static com.google.common.collect.testing.Helpers.getMethod; 021import static com.google.common.collect.testing.features.CollectionFeature.SUPPORTS_REMOVE; 022import static com.google.common.collect.testing.features.CollectionSize.ONE; 023import static com.google.common.collect.testing.features.CollectionSize.SEVERAL; 024import static com.google.common.collect.testing.features.CollectionSize.ZERO; 025import static java.util.Collections.sort; 026import static org.junit.Assert.assertThrows; 027 028import com.google.common.annotations.GwtIncompatible; 029import com.google.common.collect.testing.features.CollectionFeature; 030import com.google.common.collect.testing.features.CollectionSize; 031import java.lang.reflect.Method; 032import java.util.ArrayList; 033import java.util.Collections; 034import java.util.Iterator; 035import java.util.List; 036import java.util.NavigableSet; 037import java.util.TreeSet; 038import org.junit.Ignore; 039 040/** 041 * A generic JUnit test which tests operations on a NavigableSet. Can't be invoked directly; please 042 * see {@code NavigableSetTestSuiteBuilder}. 043 * 044 * @author Jesse Wilson 045 * @author Louis Wasserman 046 */ 047@GwtIncompatible 048@Ignore("test runners must not instantiate and run this directly, only via suites we build") 049// @Ignore affects the Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 050@SuppressWarnings("JUnit4ClassUsedInJUnit3") 051public class NavigableSetNavigationTester<E> extends AbstractSetTester<E> { 052 053 private NavigableSet<E> navigableSet; 054 private List<E> values; 055 private E a; 056 private E b; 057 private E c; 058 059 @Override 060 public void setUp() throws Exception { 061 super.setUp(); 062 navigableSet = (NavigableSet<E>) getSet(); 063 values = 064 copyToList( 065 getSubjectGenerator() 066 .getSampleElements(getSubjectGenerator().getCollectionSize().getNumElements())); 067 sort(values, navigableSet.comparator()); 068 069 // some tests assume SEVERAL == 3 070 if (values.size() >= 1) { 071 a = values.get(0); 072 if (values.size() >= 3) { 073 b = values.get(1); 074 c = values.get(2); 075 } 076 } 077 } 078 079 /** Resets the contents of navigableSet to have elements a, c, for the navigation tests. */ 080 protected void resetWithHole() { 081 super.resetContainer(getSubjectGenerator().create(a, c)); 082 navigableSet = (NavigableSet<E>) getSet(); 083 } 084 085 @CollectionFeature.Require(SUPPORTS_REMOVE) 086 @CollectionSize.Require(ZERO) 087 public void testEmptySetPollFirst() { 088 assertNull(navigableSet.pollFirst()); 089 } 090 091 @CollectionSize.Require(ZERO) 092 public void testEmptySetNearby() { 093 assertNull(navigableSet.lower(e0())); 094 assertNull(navigableSet.floor(e0())); 095 assertNull(navigableSet.ceiling(e0())); 096 assertNull(navigableSet.higher(e0())); 097 } 098 099 @CollectionFeature.Require(SUPPORTS_REMOVE) 100 @CollectionSize.Require(ZERO) 101 public void testEmptySetPollLast() { 102 assertNull(navigableSet.pollLast()); 103 } 104 105 @CollectionFeature.Require(SUPPORTS_REMOVE) 106 @CollectionSize.Require(ONE) 107 public void testSingletonSetPollFirst() { 108 assertEquals(a, navigableSet.pollFirst()); 109 assertTrue(navigableSet.isEmpty()); 110 } 111 112 @CollectionSize.Require(ONE) 113 public void testSingletonSetNearby() { 114 assertNull(navigableSet.lower(e0())); 115 assertEquals(a, navigableSet.floor(e0())); 116 assertEquals(a, navigableSet.ceiling(e0())); 117 assertNull(navigableSet.higher(e0())); 118 } 119 120 @CollectionFeature.Require(SUPPORTS_REMOVE) 121 @CollectionSize.Require(ONE) 122 public void testSingletonSetPollLast() { 123 assertEquals(a, navigableSet.pollLast()); 124 assertTrue(navigableSet.isEmpty()); 125 } 126 127 @CollectionFeature.Require(SUPPORTS_REMOVE) 128 @CollectionSize.Require(SEVERAL) 129 public void testPollFirst() { 130 assertEquals(a, navigableSet.pollFirst()); 131 assertEquals(values.subList(1, values.size()), copyToList(navigableSet)); 132 } 133 134 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 135 public void testPollFirstUnsupported() { 136 assertThrows(UnsupportedOperationException.class, () -> navigableSet.pollFirst()); 137 } 138 139 @CollectionSize.Require(SEVERAL) 140 public void testLowerHole() { 141 resetWithHole(); 142 assertEquals(null, navigableSet.lower(a)); 143 assertEquals(a, navigableSet.lower(b)); 144 assertEquals(a, navigableSet.lower(c)); 145 } 146 147 @CollectionSize.Require(SEVERAL) 148 public void testFloorHole() { 149 resetWithHole(); 150 assertEquals(a, navigableSet.floor(a)); 151 assertEquals(a, navigableSet.floor(b)); 152 assertEquals(c, navigableSet.floor(c)); 153 } 154 155 @CollectionSize.Require(SEVERAL) 156 public void testCeilingHole() { 157 resetWithHole(); 158 assertEquals(a, navigableSet.ceiling(a)); 159 assertEquals(c, navigableSet.ceiling(b)); 160 assertEquals(c, navigableSet.ceiling(c)); 161 } 162 163 @CollectionSize.Require(SEVERAL) 164 public void testHigherHole() { 165 resetWithHole(); 166 assertEquals(c, navigableSet.higher(a)); 167 assertEquals(c, navigableSet.higher(b)); 168 assertEquals(null, navigableSet.higher(c)); 169 } 170 171 /* 172 * TODO(cpovirk): make "too small" and "too large" elements available for better navigation 173 * testing. At that point, we may be able to eliminate the "hole" tests, which would mean that 174 * ContiguousSet's tests would no longer need to suppress them. 175 */ 176 @CollectionSize.Require(SEVERAL) 177 public void testLower() { 178 assertEquals(null, navigableSet.lower(a)); 179 assertEquals(a, navigableSet.lower(b)); 180 assertEquals(b, navigableSet.lower(c)); 181 } 182 183 @CollectionSize.Require(SEVERAL) 184 public void testFloor() { 185 assertEquals(a, navigableSet.floor(a)); 186 assertEquals(b, navigableSet.floor(b)); 187 assertEquals(c, navigableSet.floor(c)); 188 } 189 190 @CollectionSize.Require(SEVERAL) 191 public void testCeiling() { 192 assertEquals(a, navigableSet.ceiling(a)); 193 assertEquals(b, navigableSet.ceiling(b)); 194 assertEquals(c, navigableSet.ceiling(c)); 195 } 196 197 @CollectionSize.Require(SEVERAL) 198 public void testHigher() { 199 assertEquals(b, navigableSet.higher(a)); 200 assertEquals(c, navigableSet.higher(b)); 201 assertEquals(null, navigableSet.higher(c)); 202 } 203 204 @CollectionFeature.Require(SUPPORTS_REMOVE) 205 @CollectionSize.Require(SEVERAL) 206 public void testPollLast() { 207 assertEquals(c, navigableSet.pollLast()); 208 assertEquals(values.subList(0, values.size() - 1), copyToList(navigableSet)); 209 } 210 211 @CollectionFeature.Require(absent = SUPPORTS_REMOVE) 212 public void testPollLastUnsupported() { 213 assertThrows(UnsupportedOperationException.class, () -> navigableSet.pollLast()); 214 } 215 216 @CollectionSize.Require(SEVERAL) 217 public void testDescendingNavigation() { 218 List<E> descending = new ArrayList<>(); 219 for (Iterator<E> i = navigableSet.descendingIterator(); i.hasNext(); ) { 220 descending.add(i.next()); 221 } 222 Collections.reverse(descending); 223 assertEquals(values, descending); 224 } 225 226 public void testEmptySubSet() { 227 NavigableSet<E> empty = navigableSet.subSet(e0(), false, e0(), false); 228 assertEquals(new TreeSet<E>(), empty); 229 } 230 231 /* 232 * TODO(cpovirk): more testing of subSet/headSet/tailSet/descendingSet? and/or generate derived 233 * suites? 234 */ 235 236 /** 237 * Returns the {@link Method} instances for the test methods in this class that create a set with 238 * a "hole" in it so that set tests of {@code ContiguousSet} can suppress them with {@code 239 * FeatureSpecificTestSuiteBuilder.suppressing()}. 240 */ 241 /* 242 * TODO(cpovirk): or we could make HOLES_FORBIDDEN a feature. Or we could declare that 243 * implementations are permitted to throw IAE if a hole is requested, and we could update 244 * test*Hole to permit IAE. (But might this ignore genuine bugs?) But see the TODO above 245 * testLower, which could make this all unnecessary 246 */ 247 public static Method[] getHoleMethods() { 248 return new Method[] { 249 getMethod(NavigableSetNavigationTester.class, "testLowerHole"), 250 getMethod(NavigableSetNavigationTester.class, "testFloorHole"), 251 getMethod(NavigableSetNavigationTester.class, "testCeilingHole"), 252 getMethod(NavigableSetNavigationTester.class, "testHigherHole"), 253 }; 254 } 255}