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