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