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