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}