• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect.testing.testers;
18 
19 import static com.google.common.collect.testing.Helpers.getMethod;
20 import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS;
21 import static com.google.common.collect.testing.features.CollectionSize.ONE;
22 import static com.google.common.collect.testing.features.CollectionSize.ZERO;
23 import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_ADD_WITH_INDEX;
24 import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_REMOVE_WITH_INDEX;
25 import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_SET;
26 import static java.util.Collections.emptyList;
27 
28 import com.google.common.annotations.GwtCompatible;
29 import com.google.common.annotations.GwtIncompatible;
30 import com.google.common.collect.testing.Helpers;
31 import com.google.common.collect.testing.features.CollectionFeature;
32 import com.google.common.collect.testing.features.CollectionSize;
33 import com.google.common.collect.testing.features.ListFeature;
34 import com.google.common.testing.SerializableTester;
35 
36 import java.lang.reflect.Method;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.concurrent.CopyOnWriteArrayList;
41 
42 /**
43  * A generic JUnit test which tests {@code subList()} operations on a list.
44  * Can't be invoked directly; please see
45  * {@link com.google.common.collect.testing.ListTestSuiteBuilder}.
46  *
47  * @author Chris Povirk
48  */
49 @SuppressWarnings("unchecked") // too many "unchecked generic array creations"
50 @GwtCompatible(emulated = true)
51 public class ListSubListTester<E> extends AbstractListTester<E> {
testSubList_startNegative()52   public void testSubList_startNegative() {
53     try {
54       getList().subList(-1, 0);
55       fail("subList(-1, 0) should throw");
56     } catch (IndexOutOfBoundsException expected) {
57     }
58   }
59 
testSubList_endTooLarge()60   public void testSubList_endTooLarge() {
61     try {
62       getList().subList(0, getNumElements() + 1);
63       fail("subList(0, size + 1) should throw");
64     } catch (IndexOutOfBoundsException expected) {
65     }
66   }
67 
testSubList_startGreaterThanEnd()68   public void testSubList_startGreaterThanEnd() {
69     try {
70       getList().subList(1, 0);
71       fail("subList(1, 0) should throw");
72     } catch (IndexOutOfBoundsException expected) {
73     } catch (IllegalArgumentException expected) {
74       /*
75        * The subList() docs claim that this should be an
76        * IndexOutOfBoundsException, but many JDK implementations throw
77        * IllegalArgumentException:
78        * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4506427
79        */
80     }
81   }
82 
testSubList_empty()83   public void testSubList_empty() {
84     assertEquals("subList(0, 0) should be empty",
85         emptyList(), getList().subList(0, 0));
86   }
87 
testSubList_entireList()88   public void testSubList_entireList() {
89     assertEquals("subList(0, size) should be equal to the original list",
90         getList(), getList().subList(0, getNumElements()));
91   }
92 
93   @ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX)
94   @CollectionSize.Require(absent = ZERO)
testSubList_subListRemoveAffectsOriginal()95   public void testSubList_subListRemoveAffectsOriginal() {
96     List<E> subList = getList().subList(0, 1);
97     subList.remove(0);
98     List<E> expected =
99         Arrays.asList(createSamplesArray()).subList(1, getNumElements());
100     expectContents(expected);
101   }
102 
103   @ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX)
104   @CollectionSize.Require(absent = ZERO)
testSubList_subListClearAffectsOriginal()105   public void testSubList_subListClearAffectsOriginal() {
106     List<E> subList = getList().subList(0, 1);
107     subList.clear();
108     List<E> expected =
109         Arrays.asList(createSamplesArray()).subList(1, getNumElements());
110     expectContents(expected);
111   }
112 
113   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
testSubList_subListAddAffectsOriginal()114   public void testSubList_subListAddAffectsOriginal() {
115     List<E> subList = getList().subList(0, 0);
116     subList.add(samples.e3);
117     expectAdded(0, samples.e3);
118   }
119 
120   @ListFeature.Require(SUPPORTS_SET)
121   @CollectionSize.Require(absent = ZERO)
testSubList_subListSetAffectsOriginal()122   public void testSubList_subListSetAffectsOriginal() {
123     List<E> subList = getList().subList(0, 1);
124     subList.set(0, samples.e3);
125     List<E> expected = Helpers.copyToList(createSamplesArray());
126     expected.set(0, samples.e3);
127     expectContents(expected);
128   }
129 
130   @ListFeature.Require(SUPPORTS_SET)
131   @CollectionSize.Require(absent = ZERO)
testSubList_originalListSetAffectsSubList()132   public void testSubList_originalListSetAffectsSubList() {
133     List<E> subList = getList().subList(0, 1);
134     getList().set(0, samples.e3);
135     assertEquals("A set() call to a list after a sublist has been created "
136         + "should be reflected in the sublist",
137         Collections.singletonList(samples.e3), subList);
138   }
139 
140   @ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX)
141   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_subListRemoveAffectsOriginalLargeList()142   public void testSubList_subListRemoveAffectsOriginalLargeList() {
143     List<E> subList = getList().subList(1, 3);
144     subList.remove(samples.e2);
145     List<E> expected = Helpers.copyToList(createSamplesArray());
146     expected.remove(2);
147     expectContents(expected);
148   }
149 
150   @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX)
151   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_subListAddAtIndexAffectsOriginalLargeList()152   public void testSubList_subListAddAtIndexAffectsOriginalLargeList() {
153     List<E> subList = getList().subList(2, 3);
154     subList.add(0, samples.e3);
155     expectAdded(2, samples.e3);
156   }
157 
158   @ListFeature.Require(SUPPORTS_SET)
159   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_subListSetAffectsOriginalLargeList()160   public void testSubList_subListSetAffectsOriginalLargeList() {
161     List<E> subList = getList().subList(1, 2);
162     subList.set(0, samples.e3);
163     List<E> expected = Helpers.copyToList(createSamplesArray());
164     expected.set(1, samples.e3);
165     expectContents(expected);
166   }
167 
168   @ListFeature.Require(SUPPORTS_SET)
169   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_originalListSetAffectsSubListLargeList()170   public void testSubList_originalListSetAffectsSubListLargeList() {
171     List<E> subList = getList().subList(1, 3);
172     getList().set(1, samples.e3);
173     assertEquals("A set() call to a list after a sublist has been created "
174         + "should be reflected in the sublist",
175         Arrays.asList(samples.e3, samples.e2), subList);
176   }
177 
testSubList_ofSubListEmpty()178   public void testSubList_ofSubListEmpty() {
179     List<E> subList = getList().subList(0, 0).subList(0, 0);
180     assertEquals("subList(0, 0).subList(0, 0) should be an empty list",
181         emptyList(), subList);
182   }
183 
184   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_ofSubListNonEmpty()185   public void testSubList_ofSubListNonEmpty() {
186     List<E> subList = getList().subList(0, 2).subList(1, 2);
187     assertEquals("subList(0, 2).subList(1, 2) "
188         + "should be a single-element list of the element at index 1",
189         Collections.singletonList(getOrderedElements().get(1)), subList);
190   }
191 
192   @CollectionSize.Require(absent = {ZERO})
testSubList_size()193   public void testSubList_size() {
194     List<E> list = getList();
195     int size = getNumElements();
196     assertEquals(list.subList(0, size).size(),
197                  size);
198     assertEquals(list.subList(0, size - 1).size(),
199                  size - 1);
200     assertEquals(list.subList(1, size).size(),
201                  size - 1);
202     assertEquals(list.subList(size, size).size(),
203                  0);
204     assertEquals(list.subList(0, 0).size(),
205                  0);
206   }
207 
208   @CollectionSize.Require(absent = {ZERO})
testSubList_isEmpty()209   public void testSubList_isEmpty() {
210     List<E> list = getList();
211     int size = getNumElements();
212     for (List<E> subList : Arrays.asList(
213         list.subList(0, size),
214         list.subList(0, size - 1),
215         list.subList(1, size),
216         list.subList(0, 0),
217         list.subList(size, size))) {
218       assertEquals(subList.isEmpty(), subList.size() == 0);
219     }
220   }
221 
222   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_get()223   public void testSubList_get() {
224     List<E> list = getList();
225     int size = getNumElements();
226     List<E> copy = list.subList(0, size);
227     List<E> head = list.subList(0, size - 1);
228     List<E> tail = list.subList(1, size);
229     assertEquals(list.get(0), copy.get(0));
230     assertEquals(list.get(size - 1), copy.get(size - 1));
231     assertEquals(list.get(1), tail.get(0));
232     assertEquals(list.get(size - 1), tail.get(size - 2));
233     assertEquals(list.get(0), head.get(0));
234     assertEquals(list.get(size - 2), head.get(size - 2));
235     for (List<E> subList : Arrays.asList(copy, head, tail)) {
236       for (int index : Arrays.asList(-1, subList.size())) {
237         try {
238           subList.get(index);
239           fail("expected IndexOutOfBoundsException");
240         } catch (IndexOutOfBoundsException expected) {
241         }
242       }
243     }
244   }
245 
246   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_contains()247   public void testSubList_contains() {
248     List<E> list = getList();
249     int size = getNumElements();
250     List<E> copy = list.subList(0, size);
251     List<E> head = list.subList(0, size - 1);
252     List<E> tail = list.subList(1, size);
253     assertTrue(copy.contains(list.get(0)));
254     assertTrue(head.contains(list.get(0)));
255     assertTrue(tail.contains(list.get(1)));
256     // The following assumes all elements are distinct.
257     assertTrue(copy.contains(list.get(size - 1)));
258     assertTrue(head.contains(list.get(size - 2)));
259     assertTrue(tail.contains(list.get(size - 1)));
260     assertFalse(head.contains(list.get(size - 1)));
261     assertFalse(tail.contains(list.get(0)));
262   }
263 
264   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_indexOf()265   public void testSubList_indexOf() {
266     List<E> list = getList();
267     int size = getNumElements();
268     List<E> copy = list.subList(0, size);
269     List<E> head = list.subList(0, size - 1);
270     List<E> tail = list.subList(1, size);
271     assertEquals(copy.indexOf(list.get(0)),
272                  0);
273     assertEquals(head.indexOf(list.get(0)),
274                  0);
275     assertEquals(tail.indexOf(list.get(1)),
276                  0);
277     // The following assumes all elements are distinct.
278     assertEquals(copy.indexOf(list.get(size - 1)),
279                  size - 1);
280     assertEquals(head.indexOf(list.get(size - 2)),
281                  size - 2);
282     assertEquals(tail.indexOf(list.get(size - 1)),
283                  size - 2);
284     assertEquals(head.indexOf(list.get(size - 1)),
285                  -1);
286     assertEquals(tail.indexOf(list.get(0)),
287                  -1);
288   }
289 
290   @CollectionSize.Require(absent = {ZERO, ONE})
testSubList_lastIndexOf()291   public void testSubList_lastIndexOf() {
292     List<E> list = getList();
293     int size = list.size();
294     List<E> copy = list.subList(0, size);
295     List<E> head = list.subList(0, size - 1);
296     List<E> tail = list.subList(1, size);
297     assertEquals(copy.lastIndexOf(list.get(size - 1)),
298                  size - 1);
299     assertEquals(head.lastIndexOf(list.get(size - 2)),
300                  size - 2);
301     assertEquals(tail.lastIndexOf(list.get(size - 1)),
302                  size - 2);
303     // The following assumes all elements are distinct.
304     assertEquals(copy.lastIndexOf(list.get(0)),
305                  0);
306     assertEquals(head.lastIndexOf(list.get(0)),
307                  0);
308     assertEquals(tail.lastIndexOf(list.get(1)),
309                  0);
310     assertEquals(head.lastIndexOf(list.get(size - 1)),
311                  -1);
312     assertEquals(tail.lastIndexOf(list.get(0)),
313                  -1);
314   }
315 
316   @CollectionFeature.Require(SERIALIZABLE_INCLUDING_VIEWS)
testReserializeWholeSubList()317   public void testReserializeWholeSubList() {
318     SerializableTester.reserializeAndAssert(getList().subList(0, getNumElements()));
319   }
320 
321   @CollectionFeature.Require(SERIALIZABLE_INCLUDING_VIEWS)
testReserializeEmptySubList()322   public void testReserializeEmptySubList() {
323     SerializableTester.reserializeAndAssert(getList().subList(0, 0));
324   }
325 
326   @CollectionFeature.Require(SERIALIZABLE_INCLUDING_VIEWS)
327   @CollectionSize.Require(absent = {ZERO, ONE})
testReserializeSubList()328   public void testReserializeSubList() {
329     SerializableTester.reserializeAndAssert(getList().subList(0, 2));
330   }
331 
332   /**
333    * Returns the {@link Method} instance for
334    * {@link #testSubList_originalListSetAffectsSubList()} so that tests
335    * of {@link CopyOnWriteArrayList} can suppress them with
336    * {@code FeatureSpecificTestSuiteBuilder.suppressing()} until <a
337    * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570631">Sun bug
338    * 6570631</a> is fixed.
339    */
340   @GwtIncompatible("reflection")
getSubListOriginalListSetAffectsSubListMethod()341   public static Method getSubListOriginalListSetAffectsSubListMethod() {
342     return getMethod(ListSubListTester.class, "testSubList_originalListSetAffectsSubList");
343   }
344 
345   /**
346    * Returns the {@link Method} instance for
347    * {@link #testSubList_originalListSetAffectsSubListLargeList()} ()} so that
348    * tests of {@link CopyOnWriteArrayList} can suppress them with
349    * {@code FeatureSpecificTestSuiteBuilder.suppressing()} until <a
350    * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570631">Sun bug
351    * 6570631</a> is fixed.
352    */
353   @GwtIncompatible("reflection")
getSubListOriginalListSetAffectsSubListLargeListMethod()354   public static Method getSubListOriginalListSetAffectsSubListLargeListMethod() {
355     return getMethod(ListSubListTester.class, "testSubList_originalListSetAffectsSubListLargeList");
356   }
357 
358   /**
359    * Returns the {@link Method} instance for
360    * {@link #testSubList_subListRemoveAffectsOriginalLargeList()} so that tests
361    * of {@link CopyOnWriteArrayList} can suppress it with
362    * {@code FeatureSpecificTestSuiteBuilder.suppressing()} until <a
363    * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570575">Sun bug
364    * 6570575</a> is fixed.
365    */
366   @GwtIncompatible("reflection")
getSubListSubListRemoveAffectsOriginalLargeListMethod()367   public static Method getSubListSubListRemoveAffectsOriginalLargeListMethod() {
368     return getMethod(ListSubListTester.class, "testSubList_subListRemoveAffectsOriginalLargeList");
369   }
370 
371   /*
372    * TODO: perform all List tests on subList(), but beware infinite recursion
373    */
374 }
375