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