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