001/* 002 * Copyright (C) 2008 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.getMethod; 020import static com.google.common.collect.testing.features.CollectionFeature.SERIALIZABLE_INCLUDING_VIEWS; 021import static com.google.common.collect.testing.features.CollectionSize.ONE; 022import static com.google.common.collect.testing.features.CollectionSize.ZERO; 023import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_ADD_WITH_INDEX; 024import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_REMOVE_WITH_INDEX; 025import static com.google.common.collect.testing.features.ListFeature.SUPPORTS_SET; 026import static java.util.Collections.emptyList; 027 028import com.google.common.annotations.GwtCompatible; 029import com.google.common.annotations.GwtIncompatible; 030import com.google.common.annotations.J2ktIncompatible; 031import com.google.common.collect.testing.Helpers; 032import com.google.common.collect.testing.features.CollectionFeature; 033import com.google.common.collect.testing.features.CollectionSize; 034import com.google.common.collect.testing.features.ListFeature; 035import com.google.common.testing.SerializableTester; 036import java.lang.reflect.Method; 037import java.util.Arrays; 038import java.util.Collections; 039import java.util.List; 040import java.util.concurrent.CopyOnWriteArrayList; 041import org.junit.Ignore; 042 043/** 044 * A generic JUnit test which tests {@code subList()} operations on a list. Can't be invoked 045 * directly; please see {@link com.google.common.collect.testing.ListTestSuiteBuilder}. 046 * 047 * @author Chris Povirk 048 */ 049@GwtCompatible(emulated = true) 050@Ignore // Affects only Android test runner, which respects JUnit 4 annotations on JUnit 3 tests. 051@SuppressWarnings("JUnit4ClassUsedInJUnit3") 052public class ListSubListTester<E> extends AbstractListTester<E> { 053 public void testSubList_startNegative() { 054 try { 055 getList().subList(-1, 0); 056 fail("subList(-1, 0) should throw"); 057 } catch (IndexOutOfBoundsException expected) { 058 } 059 } 060 061 public void testSubList_endTooLarge() { 062 try { 063 getList().subList(0, getNumElements() + 1); 064 fail("subList(0, size + 1) should throw"); 065 } catch (IndexOutOfBoundsException expected) { 066 } 067 } 068 069 public void testSubList_startGreaterThanEnd() { 070 try { 071 getList().subList(1, 0); 072 fail("subList(1, 0) should throw"); 073 } catch (IndexOutOfBoundsException expected) { 074 } catch (IllegalArgumentException expected) { 075 /* 076 * The subList() docs claim that this should be an 077 * IndexOutOfBoundsException, but many JDK implementations throw 078 * IllegalArgumentException: 079 * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4506427 080 */ 081 } 082 } 083 084 public void testSubList_empty() { 085 assertEquals("subList(0, 0) should be empty", emptyList(), getList().subList(0, 0)); 086 } 087 088 public void testSubList_entireList() { 089 assertEquals( 090 "subList(0, size) should be equal to the original list", 091 getList(), 092 getList().subList(0, getNumElements())); 093 } 094 095 @ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX) 096 @CollectionSize.Require(absent = ZERO) 097 public void testSubList_subListRemoveAffectsOriginal() { 098 List<E> subList = getList().subList(0, 1); 099 subList.remove(0); 100 List<E> expected = Arrays.asList(createSamplesArray()).subList(1, getNumElements()); 101 expectContents(expected); 102 } 103 104 @ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX) 105 @CollectionSize.Require(absent = ZERO) 106 public void testSubList_subListClearAffectsOriginal() { 107 List<E> subList = getList().subList(0, 1); 108 subList.clear(); 109 List<E> expected = Arrays.asList(createSamplesArray()).subList(1, getNumElements()); 110 expectContents(expected); 111 } 112 113 @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX) 114 public void testSubList_subListAddAffectsOriginal() { 115 List<E> subList = getList().subList(0, 0); 116 subList.add(e3()); 117 expectAdded(0, e3()); 118 } 119 120 @ListFeature.Require(SUPPORTS_SET) 121 @CollectionSize.Require(absent = ZERO) 122 public void testSubList_subListSetAffectsOriginal() { 123 List<E> subList = getList().subList(0, 1); 124 subList.set(0, e3()); 125 List<E> expected = Helpers.copyToList(createSamplesArray()); 126 expected.set(0, e3()); 127 expectContents(expected); 128 } 129 130 @ListFeature.Require(SUPPORTS_SET) 131 @CollectionSize.Require(absent = ZERO) 132 public void testSubList_originalListSetAffectsSubList() { 133 List<E> subList = getList().subList(0, 1); 134 getList().set(0, e3()); 135 assertEquals( 136 "A set() call to a list after a sublist has been created " 137 + "should be reflected in the sublist", 138 Collections.singletonList(e3()), 139 subList); 140 } 141 142 @ListFeature.Require(SUPPORTS_REMOVE_WITH_INDEX) 143 @CollectionSize.Require(absent = {ZERO, ONE}) 144 public void testSubList_subListRemoveAffectsOriginalLargeList() { 145 List<E> subList = getList().subList(1, 3); 146 subList.remove(e2()); 147 List<E> expected = Helpers.copyToList(createSamplesArray()); 148 expected.remove(2); 149 expectContents(expected); 150 } 151 152 @ListFeature.Require(SUPPORTS_ADD_WITH_INDEX) 153 @CollectionSize.Require(absent = {ZERO, ONE}) 154 public void testSubList_subListAddAtIndexAffectsOriginalLargeList() { 155 List<E> subList = getList().subList(2, 3); 156 subList.add(0, e3()); 157 expectAdded(2, e3()); 158 } 159 160 @ListFeature.Require(SUPPORTS_SET) 161 @CollectionSize.Require(absent = {ZERO, ONE}) 162 public void testSubList_subListSetAffectsOriginalLargeList() { 163 List<E> subList = getList().subList(1, 2); 164 subList.set(0, e3()); 165 List<E> expected = Helpers.copyToList(createSamplesArray()); 166 expected.set(1, e3()); 167 expectContents(expected); 168 } 169 170 @ListFeature.Require(SUPPORTS_SET) 171 @CollectionSize.Require(absent = {ZERO, ONE}) 172 public void testSubList_originalListSetAffectsSubListLargeList() { 173 List<E> subList = getList().subList(1, 3); 174 getList().set(1, e3()); 175 assertEquals( 176 "A set() call to a list after a sublist has been created " 177 + "should be reflected in the sublist", 178 Arrays.asList(e3(), e2()), 179 subList); 180 } 181 182 public void testSubList_ofSubListEmpty() { 183 List<E> subList = getList().subList(0, 0).subList(0, 0); 184 assertEquals("subList(0, 0).subList(0, 0) should be an empty list", emptyList(), subList); 185 } 186 187 @CollectionSize.Require(absent = {ZERO, ONE}) 188 public void testSubList_ofSubListNonEmpty() { 189 List<E> subList = getList().subList(0, 2).subList(1, 2); 190 assertEquals( 191 "subList(0, 2).subList(1, 2) " 192 + "should be a single-element list of the element at index 1", 193 Collections.singletonList(getOrderedElements().get(1)), 194 subList); 195 } 196 197 @CollectionSize.Require(absent = {ZERO}) 198 public void testSubList_size() { 199 List<E> list = getList(); 200 int size = getNumElements(); 201 assertEquals(size, list.subList(0, size).size()); 202 assertEquals(size - 1, list.subList(0, size - 1).size()); 203 assertEquals(size - 1, list.subList(1, size).size()); 204 assertEquals(0, list.subList(size, size).size()); 205 assertEquals(0, list.subList(0, 0).size()); 206 } 207 208 @CollectionSize.Require(absent = {ZERO}) 209 public void testSubList_isEmpty() { 210 List<E> list = getList(); 211 int size = getNumElements(); 212 for (List<E> subList : 213 Arrays.asList( 214 list.subList(0, size), 215 list.subList(0, size - 1), 216 list.subList(1, size), 217 list.subList(0, 0), 218 list.subList(size, size))) { 219 assertEquals(subList.size() == 0, subList.isEmpty()); 220 } 221 } 222 223 @CollectionSize.Require(absent = {ZERO, ONE}) 224 public void testSubList_get() { 225 List<E> list = getList(); 226 int size = getNumElements(); 227 List<E> copy = list.subList(0, size); 228 List<E> head = list.subList(0, size - 1); 229 List<E> tail = list.subList(1, size); 230 assertEquals(list.get(0), copy.get(0)); 231 assertEquals(list.get(size - 1), copy.get(size - 1)); 232 assertEquals(list.get(1), tail.get(0)); 233 assertEquals(list.get(size - 1), tail.get(size - 2)); 234 assertEquals(list.get(0), head.get(0)); 235 assertEquals(list.get(size - 2), head.get(size - 2)); 236 for (List<E> subList : Arrays.asList(copy, head, tail)) { 237 for (int index : Arrays.asList(-1, subList.size())) { 238 try { 239 subList.get(index); 240 fail("expected IndexOutOfBoundsException"); 241 } catch (IndexOutOfBoundsException expected) { 242 } 243 } 244 } 245 } 246 247 @CollectionSize.Require(absent = {ZERO, ONE}) 248 public void testSubList_contains() { 249 List<E> list = getList(); 250 int size = getNumElements(); 251 List<E> copy = list.subList(0, size); 252 List<E> head = list.subList(0, size - 1); 253 List<E> tail = list.subList(1, size); 254 assertTrue(copy.contains(list.get(0))); 255 assertTrue(head.contains(list.get(0))); 256 assertTrue(tail.contains(list.get(1))); 257 // The following assumes all elements are distinct. 258 assertTrue(copy.contains(list.get(size - 1))); 259 assertTrue(head.contains(list.get(size - 2))); 260 assertTrue(tail.contains(list.get(size - 1))); 261 assertFalse(head.contains(list.get(size - 1))); 262 assertFalse(tail.contains(list.get(0))); 263 } 264 265 @CollectionSize.Require(absent = {ZERO, ONE}) 266 public void testSubList_indexOf() { 267 List<E> list = getList(); 268 int size = getNumElements(); 269 List<E> copy = list.subList(0, size); 270 List<E> head = list.subList(0, size - 1); 271 List<E> tail = list.subList(1, size); 272 assertEquals(0, copy.indexOf(list.get(0))); 273 assertEquals(0, head.indexOf(list.get(0))); 274 assertEquals(0, tail.indexOf(list.get(1))); 275 // The following assumes all elements are distinct. 276 assertEquals(size - 1, copy.indexOf(list.get(size - 1))); 277 assertEquals(size - 2, head.indexOf(list.get(size - 2))); 278 assertEquals(size - 2, tail.indexOf(list.get(size - 1))); 279 assertEquals(-1, head.indexOf(list.get(size - 1))); 280 assertEquals(-1, tail.indexOf(list.get(0))); 281 } 282 283 @CollectionSize.Require(absent = {ZERO, ONE}) 284 public void testSubList_lastIndexOf() { 285 List<E> list = getList(); 286 int size = list.size(); 287 List<E> copy = list.subList(0, size); 288 List<E> head = list.subList(0, size - 1); 289 List<E> tail = list.subList(1, size); 290 assertEquals(size - 1, copy.lastIndexOf(list.get(size - 1))); 291 assertEquals(size - 2, head.lastIndexOf(list.get(size - 2))); 292 assertEquals(size - 2, tail.lastIndexOf(list.get(size - 1))); 293 // The following assumes all elements are distinct. 294 assertEquals(0, copy.lastIndexOf(list.get(0))); 295 assertEquals(0, head.lastIndexOf(list.get(0))); 296 assertEquals(0, tail.lastIndexOf(list.get(1))); 297 assertEquals(-1, head.lastIndexOf(list.get(size - 1))); 298 assertEquals(-1, tail.lastIndexOf(list.get(0))); 299 } 300 301 @CollectionFeature.Require(SERIALIZABLE_INCLUDING_VIEWS) 302 public void testReserializeWholeSubList() { 303 SerializableTester.reserializeAndAssert(getList().subList(0, getNumElements())); 304 } 305 306 @CollectionFeature.Require(SERIALIZABLE_INCLUDING_VIEWS) 307 public void testReserializeEmptySubList() { 308 SerializableTester.reserializeAndAssert(getList().subList(0, 0)); 309 } 310 311 @CollectionFeature.Require(SERIALIZABLE_INCLUDING_VIEWS) 312 @CollectionSize.Require(absent = {ZERO, ONE}) 313 public void testReserializeSubList() { 314 SerializableTester.reserializeAndAssert(getList().subList(0, 2)); 315 } 316 317 /** 318 * Returns the {@link Method} instance for {@link #testSubList_originalListSetAffectsSubList()} so 319 * that tests of {@link CopyOnWriteArrayList} can suppress them with {@code 320 * FeatureSpecificTestSuiteBuilder.suppressing()} until <a 321 * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570631">Sun bug 6570631</a> is fixed. 322 */ 323 @J2ktIncompatible 324 @GwtIncompatible // reflection 325 public static Method getSubListOriginalListSetAffectsSubListMethod() { 326 return getMethod(ListSubListTester.class, "testSubList_originalListSetAffectsSubList"); 327 } 328 329 /** 330 * Returns the {@link Method} instance for {@link 331 * #testSubList_originalListSetAffectsSubListLargeList()} so that tests of {@link 332 * CopyOnWriteArrayList} can suppress them with {@code 333 * FeatureSpecificTestSuiteBuilder.suppressing()} until <a 334 * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570631">Sun bug 6570631</a> is fixed. 335 */ 336 @J2ktIncompatible 337 @GwtIncompatible // reflection 338 public static Method getSubListOriginalListSetAffectsSubListLargeListMethod() { 339 return getMethod(ListSubListTester.class, "testSubList_originalListSetAffectsSubListLargeList"); 340 } 341 342 /** 343 * Returns the {@link Method} instance for {@link 344 * #testSubList_subListRemoveAffectsOriginalLargeList()} so that tests of {@link 345 * CopyOnWriteArrayList} can suppress it with {@code 346 * FeatureSpecificTestSuiteBuilder.suppressing()} until <a 347 * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570575">Sun bug 6570575</a> is fixed. 348 */ 349 @J2ktIncompatible 350 @GwtIncompatible // reflection 351 public static Method getSubListSubListRemoveAffectsOriginalLargeListMethod() { 352 return getMethod(ListSubListTester.class, "testSubList_subListRemoveAffectsOriginalLargeList"); 353 } 354 355 /* 356 * TODO: perform all List tests on subList(), but beware infinite recursion 357 */ 358}