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