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