1 /* 2 * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package test.java.util.SequencedCollection; 25 26 import java.io.*; 27 import java.util.*; 28 import java.util.concurrent.CopyOnWriteArrayList; 29 import org.testng.annotations.DataProvider; 30 import org.testng.annotations.Test; 31 32 import static org.testng.Assert.assertEquals; 33 import static org.testng.Assert.assertSame; 34 import static org.testng.Assert.assertThrows; 35 import static org.testng.Assert.assertTrue; 36 37 /* 38 * @test 39 * @bug 8266571 40 * @summary Basic tests for SequencedCollection 41 * @modules java.base/java.util:open 42 * @build SimpleDeque SimpleList SimpleSortedSet 43 * @run testng Basic 44 */ 45 46 // TODO test that remove(obj) with duplicates removes the right element 47 48 public class Basic { 49 50 // ========== Data Providers ========== 51 52 static final List<String> ORIGINAL = List.of("a", "b", "c", "d", "e", "f", "g"); 53 cklist(List<String> contents)54 static List<String> cklist(List<String> contents) { 55 return Collections.checkedList(contents, String.class); 56 } 57 cknav(NavigableSet<String> set)58 static NavigableSet<String> cknav(NavigableSet<String> set) { 59 return Collections.checkedNavigableSet(set, String.class); 60 } 61 cksorted(SortedSet<String> set)62 static SortedSet<String> cksorted(SortedSet<String> set) { 63 return Collections.checkedSortedSet(set, String.class); 64 } 65 setFromMap(List<String> contents)66 static SequencedSet<String> setFromMap(List<String> contents) { 67 var lhm = new LinkedHashMap<String, Boolean>(); 68 var ss = Collections.newSequencedSetFromMap(lhm); 69 ss.addAll(contents); 70 return ss; 71 } 72 ucoll(SequencedCollection<String> coll)73 static SequencedCollection<String> ucoll(SequencedCollection<String> coll) { 74 return Collections.unmodifiableSequencedCollection(coll); 75 } 76 ulist(List<String> list)77 static SequencedCollection<String> ulist(List<String> list) { 78 return Collections.unmodifiableList(list); 79 } 80 unav(NavigableSet<String> set)81 static NavigableSet<String> unav(NavigableSet<String> set) { 82 return Collections.unmodifiableNavigableSet(set); 83 } 84 uset(SequencedSet<String> set)85 static SequencedSet<String> uset(SequencedSet<String> set) { 86 return Collections.unmodifiableSequencedSet(set); 87 } 88 usorted(SortedSet<String> set)89 static SortedSet<String> usorted(SortedSet<String> set) { 90 return Collections.unmodifiableSortedSet(set); 91 } 92 copyReversed(List<T> list)93 static <T> List<T> copyReversed(List<T> list) { 94 var r = new ArrayList<T>(list); 95 Collections.reverse(r); 96 return r; 97 } 98 99 @DataProvider(name="all") all()100 public Iterator<Object[]> all() { 101 var result = new ArrayList<Object[]>(); 102 populated().forEachRemaining(result::add); 103 empties().forEachRemaining(result::add); 104 return result.iterator(); 105 } 106 107 @DataProvider(name="populated") populated()108 public Iterator<Object[]> populated() { 109 return Arrays.asList( 110 new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL), ORIGINAL }, 111 new Object[] { "ArrayList", new ArrayList<>(ORIGINAL), ORIGINAL }, 112 new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()), ORIGINAL }, 113 new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL }, 114 new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL }, 115 new Object[] { "LinkedList", new LinkedList<>(ORIGINAL), ORIGINAL }, 116 new Object[] { "ListOf", ORIGINAL, ORIGINAL }, 117 new Object[] { "SetFromMap", setFromMap(ORIGINAL), ORIGINAL }, 118 new Object[] { "SimpleDeque", new SimpleDeque<>(ORIGINAL), ORIGINAL }, 119 new Object[] { "SimpleList", new SimpleList<>(ORIGINAL), ORIGINAL }, 120 new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(ORIGINAL), ORIGINAL }, 121 new Object[] { "TreeSet", new TreeSet<>(ORIGINAL), ORIGINAL }, 122 new Object[] { "UnmodColl", ucoll(new ArrayList<>(ORIGINAL)), ORIGINAL }, 123 new Object[] { "UnmodSet", uset(new LinkedHashSet<>(ORIGINAL)), ORIGINAL } 124 ).iterator(); 125 } 126 127 @DataProvider(name="empties") empties()128 public Iterator<Object[]> empties() { 129 return Arrays.asList( 130 new Object[] { "ArrayDeque", new ArrayDeque<>(), List.of() }, 131 new Object[] { "ArrayList", new ArrayList<>(), List.of() }, 132 new Object[] { "AsList", Arrays.asList(new String[0]), List.of() }, 133 new Object[] { "COWAL", new CopyOnWriteArrayList<>(), List.of() }, 134 new Object[] { "EmptyList", Collections.emptyList(), List.of() }, 135 new Object[] { "EmptyNavigableSet", Collections.emptyNavigableSet(), List.of() }, 136 new Object[] { "EmptySortedSet", Collections.emptySortedSet(), List.of() }, 137 new Object[] { "LinkedHashSet", new LinkedHashSet<>(), List.of() }, 138 new Object[] { "LinkedList", new LinkedList<>(), List.of() }, 139 new Object[] { "ListOf", List.of(), List.of() }, 140 new Object[] { "SetFromMap", setFromMap(List.of()), List.of() }, 141 new Object[] { "SimpleDeque", new SimpleDeque<>(), List.of() }, 142 new Object[] { "SimpleList", new SimpleList<>(), List.of() }, 143 new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(), List.of() }, 144 new Object[] { "TreeSet", new TreeSet<>(), List.of() }, 145 new Object[] { "UnmodColl", ucoll(new ArrayList<>()), List.of() }, 146 new Object[] { "UnmodSet", uset(new LinkedHashSet<>()), List.of() } 147 ).iterator(); 148 } 149 150 @DataProvider(name="adds") adds()151 public Iterator<Object[]> adds() { 152 return Arrays.asList( 153 new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL), ORIGINAL }, 154 new Object[] { "ArrayList", new ArrayList<>(ORIGINAL), ORIGINAL }, 155 new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL }, 156 new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL }, 157 new Object[] { "LinkedList", new LinkedList<>(ORIGINAL), ORIGINAL }, 158 new Object[] { "SetFromMap", setFromMap(ORIGINAL), ORIGINAL }, 159 new Object[] { "SimpleDeque", new SimpleDeque<>(ORIGINAL), ORIGINAL }, 160 new Object[] { "SimpleList", new SimpleList<>(ORIGINAL), ORIGINAL } 161 ).iterator(); 162 } 163 164 @DataProvider(name="unpositionedAdd") unpositionedAdd()165 public Iterator<Object[]> unpositionedAdd() { 166 return Arrays.<Object[]>asList( 167 new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL } 168 ).iterator(); 169 } 170 171 @DataProvider(name="removes") removes()172 public Iterator<Object[]> removes() { 173 return Arrays.asList( 174 new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL), ORIGINAL }, 175 new Object[] { "ArrayList", new ArrayList<>(ORIGINAL), ORIGINAL }, 176 new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL }, 177 new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL }, 178 new Object[] { "LinkedList", new LinkedList<>(ORIGINAL), ORIGINAL }, 179 new Object[] { "SetFromMap", setFromMap(ORIGINAL), ORIGINAL }, 180 new Object[] { "SimpleDeque", new SimpleDeque<>(ORIGINAL), ORIGINAL }, 181 new Object[] { "SimpleList", new SimpleList<>(ORIGINAL), ORIGINAL }, 182 new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(ORIGINAL), ORIGINAL }, 183 new Object[] { "TreeSet", new TreeSet<>(ORIGINAL), ORIGINAL } 184 ).iterator(); 185 } 186 187 @DataProvider(name="emptyRemoves") emptyRemoves()188 public Iterator<Object[]> emptyRemoves() { 189 return Arrays.asList( 190 new Object[] { "ArrayDeque", new ArrayDeque<>(), List.of() }, 191 new Object[] { "ArrayList", new ArrayList<>(), List.of() }, 192 new Object[] { "COWAL", new CopyOnWriteArrayList<>(), List.of() }, 193 new Object[] { "LinkedHashSet", new LinkedHashSet<>(), List.of() }, 194 new Object[] { "LinkedList", new LinkedList<>(), List.of() }, 195 new Object[] { "SetFromMap", setFromMap(List.of()), List.of() }, 196 new Object[] { "SimpleDeque", new SimpleDeque<>(), List.of() }, 197 new Object[] { "SimpleList", new SimpleList<>(), List.of() }, 198 new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(), List.of() }, 199 new Object[] { "TreeSet", new TreeSet<>(), List.of() } 200 ).iterator(); 201 } 202 203 @DataProvider(name="serializable") serializable()204 public Iterator<Object[]> serializable() { 205 return Arrays.asList( 206 new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL), ORIGINAL }, 207 new Object[] { "ArrayList", new ArrayList<>(ORIGINAL), ORIGINAL }, 208 new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()), ORIGINAL }, 209 new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL }, 210 new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL), ORIGINAL }, 211 new Object[] { "LinkedList", new LinkedList<>(ORIGINAL), ORIGINAL }, 212 new Object[] { "ListOf", ORIGINAL, ORIGINAL }, 213 new Object[] { "SetFromMap", setFromMap(ORIGINAL), ORIGINAL }, 214 new Object[] { "TreeSet", new TreeSet<>(ORIGINAL), ORIGINAL }, 215 new Object[] { "UnmodColl", ucoll(new ArrayList<>(ORIGINAL)), ORIGINAL }, 216 new Object[] { "UnmodSet", uset(new LinkedHashSet<>(ORIGINAL)), ORIGINAL } 217 ).iterator(); 218 } 219 220 @DataProvider(name="notSerializable") notSerializable()221 public Iterator<Object[]> notSerializable() { 222 return Arrays.asList( 223 new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL).reversed() }, 224 new Object[] { "ArrayList", new ArrayList<>(ORIGINAL).reversed() }, 225 new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()).reversed() }, 226 new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL).reversed() }, 227 new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL).reversed() }, 228 new Object[] { "LinkedList", new LinkedList<>(ORIGINAL).reversed() }, 229 new Object[] { "ListOf", ORIGINAL.reversed() }, 230 new Object[] { "SetFromMap", setFromMap(ORIGINAL).reversed() }, 231 new Object[] { "UnmodColl", ucoll(new ArrayList<>(ORIGINAL)).reversed() }, 232 new Object[] { "UnmodSet", uset(new LinkedHashSet<>(ORIGINAL)).reversed() } 233 ).iterator(); 234 } 235 236 @DataProvider(name="doubleReverse") doubleReverse()237 public Iterator<Object[]> doubleReverse() { 238 return Arrays.asList( 239 new Object[] { "ArrayDeque", new ArrayDeque<>(ORIGINAL) }, 240 new Object[] { "ArrayList", new ArrayList<>(ORIGINAL) }, 241 new Object[] { "AsList", Arrays.asList(ORIGINAL.toArray()) }, 242 new Object[] { "COWAL", new CopyOnWriteArrayList<>(ORIGINAL) }, 243 new Object[] { "LinkedHashSet", new LinkedHashSet<>(ORIGINAL) }, 244 new Object[] { "LinkedList", new LinkedList<>(ORIGINAL) }, 245 new Object[] { "ListOf", ORIGINAL }, 246 new Object[] { "SimpleDeque", new SimpleDeque<>(ORIGINAL) }, 247 new Object[] { "SimpleList", new SimpleList<>(ORIGINAL) }, 248 new Object[] { "SimpleSortedSet", new SimpleSortedSet<>(ORIGINAL) } 249 ).iterator(); 250 } 251 252 @DataProvider(name="unmodifiable") unmodifiable()253 public Iterator<Object[]> unmodifiable() { 254 return Arrays.asList( 255 new Object[] { "ListOf", ORIGINAL, ORIGINAL }, 256 new Object[] { "ListOfSub", ORIGINAL.subList(1, 3), ORIGINAL.subList(1, 3) }, 257 new Object[] { "SingleList", Collections.singletonList("a"), List.of("a") }, 258 new Object[] { "UnmodColl", ucoll(new ArrayList<>(ORIGINAL)), ORIGINAL }, 259 new Object[] { "UnmodList", ulist(new ArrayList<>(ORIGINAL)), ORIGINAL }, 260 new Object[] { "UnmodNav", unav(new TreeSet<>(ORIGINAL)), ORIGINAL }, 261 new Object[] { "UnmodSet", uset(new LinkedHashSet<>(ORIGINAL)), ORIGINAL }, 262 new Object[] { "UnmodSorted", usorted(new TreeSet<>(ORIGINAL)), ORIGINAL } 263 ).iterator(); 264 } 265 266 @DataProvider(name="checkedList") checkedList()267 public Iterator<Object[]> checkedList() { 268 return Arrays.<Object[]>asList( 269 new Object[] { "ChkList", cklist(new ArrayList<>(ORIGINAL)), ORIGINAL } 270 ).iterator(); 271 } 272 273 @DataProvider(name="checkedNavSet") checkedNavSet()274 public Iterator<Object[]> checkedNavSet() { 275 return Arrays.<Object[]>asList( 276 new Object[] { "ChkNav", cknav(new TreeSet<>(ORIGINAL)), ORIGINAL } 277 ).iterator(); 278 } 279 280 @DataProvider(name="checkedSortedSet") checkedSortedSet()281 public Iterator<Object[]> checkedSortedSet() { 282 return Arrays.<Object[]>asList( 283 new Object[] { "ChkSorted", cksorted(new TreeSet<>(ORIGINAL)), ORIGINAL } 284 ).iterator(); 285 } 286 287 // mode bit tests for subList testing 288 reverseList(int mode)289 boolean reverseList(int mode) { return (mode & 1) != 0; } reverseSub(int mode)290 boolean reverseSub(int mode) { return (mode & 2) != 0; } isReversed(int mode)291 boolean isReversed(int mode) { return reverseList(mode) ^ reverseSub(mode); } 292 applyMode(int mode, List<String> base)293 List<String> applyMode(int mode, List<String> base) { 294 var list = reverseList(mode) ? base.reversed() : base; 295 var sub = list.subList(2, 5); 296 return reverseSub(mode) ? sub.reversed() : sub; 297 } 298 299 /** 300 * Generate cases for testing subLists. For each different List implementation, generate 4 301 * cases from the two bits of the testing mode int value: 302 * 303 * (bit 1) if true, the List is reversed 304 * (bit 2) if true, the subList is reversed 305 * 306 * @return the generated cases 307 */ 308 @DataProvider(name="subListMods") subListMods()309 public Iterator<Object[]> subListMods() { 310 var cases = new ArrayList<Object[]>(); 311 for (int mode = 0; mode < 4; mode++) { 312 cases.addAll(Arrays.asList( 313 new Object[] { "ArrayList", mode, new ArrayList<>(ORIGINAL), ORIGINAL }, 314 new Object[] { "COWAL", mode, new CopyOnWriteArrayList<>(ORIGINAL), ORIGINAL }, 315 new Object[] { "LinkedList", mode, new LinkedList<>(ORIGINAL), ORIGINAL }, 316 new Object[] { "SimpleList", mode, new SimpleList<>(ORIGINAL), ORIGINAL } 317 )); 318 } 319 return cases.iterator(); 320 } 321 322 @DataProvider(name="iteratorMods") iteratorMods()323 public Iterator<Object[]> iteratorMods() { 324 var cases = new ArrayList<Object[]>(); 325 for (boolean rev : List.of(false, true)) { 326 cases.addAll(Arrays.asList( 327 new Object[] { "ArrayList", rev, new ArrayList<>(ORIGINAL), ORIGINAL }, 328 new Object[] { "LinkedList", rev, new LinkedList<>(ORIGINAL), ORIGINAL }, 329 new Object[] { "SimpleList", rev, new SimpleList<>(ORIGINAL), ORIGINAL } 330 )); 331 } 332 return cases.iterator(); 333 } 334 335 @DataProvider(name="subListIteratorMods") subListIteratorMods()336 public Iterator<Object[]> subListIteratorMods() { 337 var cases = new ArrayList<Object[]>(); 338 for (int mode = 0; mode < 4; mode++) { 339 cases.addAll(Arrays.asList( 340 new Object[] { "ArrayList", mode, new ArrayList<>(ORIGINAL), ORIGINAL }, 341 new Object[] { "LinkedList", mode, new LinkedList<>(ORIGINAL), ORIGINAL }, 342 new Object[] { "SimpleList", mode, new SimpleList<>(ORIGINAL), ORIGINAL } 343 )); 344 } 345 return cases.iterator(); 346 } 347 348 // ========== Assertions ========== 349 350 /** 351 * Basic checks over the contents of a SequencedCollection, 352 * compared to a reference List, in one direction. 353 * 354 * @param seq the SequencedCollection under test 355 * @param ref the reference List 356 */ checkContents1(SequencedCollection<String> seq, List<String> ref)357 public void checkContents1(SequencedCollection<String> seq, List<String> ref) { 358 var list1 = new ArrayList<String>(); 359 for (var s : seq) 360 list1.add(s); 361 assertEquals(list1, ref); 362 363 var list2 = new ArrayList<String>(); 364 seq.forEach(list2::add); 365 assertEquals(list2, ref); 366 367 var list3 = Arrays.asList(seq.toArray()); 368 assertEquals(list3, ref); 369 370 var list4 = Arrays.asList(seq.toArray(new String[0])); 371 assertEquals(list4, ref); 372 373 var list5 = Arrays.asList(seq.toArray(String[]::new)); 374 assertEquals(list5, ref); 375 376 var list6 = seq.stream().toList(); 377 assertEquals(list6, ref); 378 379 var list7 = seq.parallelStream().toList(); 380 assertEquals(list7, ref); 381 382 assertEquals(seq.size(), ref.size()); 383 assertEquals(seq.isEmpty(), ref.isEmpty()); 384 385 for (var s : ref) { 386 assertTrue(seq.contains(s)); 387 } 388 } 389 390 /** 391 * Check the contents of a SequencedCollection against a reference List, 392 * in both directions. 393 * 394 * @param seq the SequencedCollection under test 395 * @param ref the reference List 396 */ checkContents(SequencedCollection<String> seq, List<String> ref)397 public void checkContents(SequencedCollection<String> seq, List<String> ref) { 398 checkContents1(seq, ref); 399 400 var rref = copyReversed(ref); 401 var rseq = seq.reversed(); 402 checkContents1(rseq, rref); 403 404 var rrseq = rseq.reversed(); 405 checkContents1(rrseq, ref); 406 } 407 408 /** 409 * Check that modification operations will throw UnsupportedOperationException, 410 * in one direction. 411 * 412 * @param seq the SequencedCollection under test 413 */ checkUnmodifiable1(SequencedCollection<String> seq)414 public void checkUnmodifiable1(SequencedCollection<String> seq) { 415 final var UOE = UnsupportedOperationException.class; 416 417 assertThrows(UOE, () -> seq.add("x")); 418 assertThrows(UOE, () -> seq.clear()); 419 assertThrows(UOE, () -> { var it = seq.iterator(); it.next(); it.remove(); }); 420 assertThrows(UOE, () -> seq.removeIf(x -> true)); 421 422 assertThrows(UOE, () -> seq.addFirst("x")); 423 assertThrows(UOE, () -> seq.addLast("x")); 424 assertThrows(UOE, () -> seq.removeFirst()); 425 assertThrows(UOE, () -> seq.removeLast()); 426 427 // TODO these ops should throw unconditionally, but they don't in some implementations 428 // assertThrows(UOE, () -> seq.addAll(List.of())); 429 // assertThrows(UOE, () -> seq.remove("x")); 430 // assertThrows(UOE, () -> seq.removeAll(List.of())); 431 // assertThrows(UOE, () -> seq.removeIf(x -> false)); 432 // assertThrows(UOE, () -> seq.retainAll(seq)); 433 assertThrows(UOE, () -> seq.addAll(seq)); 434 assertThrows(UOE, () -> seq.remove(seq.iterator().next())); 435 assertThrows(UOE, () -> seq.removeAll(seq)); 436 assertThrows(UOE, () -> seq.retainAll(List.of())); 437 } 438 439 /** 440 * Check that modification operations will throw UnsupportedOperationException, 441 * in both directions. 442 * 443 * @param seq the SequencedCollection under test 444 */ checkUnmodifiable(SequencedCollection<String> seq)445 public void checkUnmodifiable(SequencedCollection<String> seq) { 446 checkUnmodifiable1(seq); 447 checkUnmodifiable1(seq.reversed()); 448 } 449 450 static final Class<? extends Throwable> CCE = ClassCastException.class; 451 checkCheckedList(List<String> list)452 public void checkCheckedList(List<String> list) { 453 List<Object> objList = (List<Object>)(List)list; 454 assertThrows(CCE, () -> { objList.addFirst(new Object()); }); 455 assertThrows(CCE, () -> { objList.addLast(new Object()); }); 456 assertThrows(CCE, () -> { objList.reversed().addFirst(new Object()); }); 457 assertThrows(CCE, () -> { objList.reversed().addLast(new Object()); }); 458 } 459 checkCheckedNavSet(NavigableSet<String> set)460 public void checkCheckedNavSet(NavigableSet<String> set) { 461 NavigableSet<Object> objSet = (NavigableSet<Object>)(NavigableSet)set; 462 assertThrows(CCE, () -> { objSet.add(new Object()); }); 463 assertThrows(CCE, () -> { objSet.reversed().add(new Object()); }); 464 } 465 checkCheckedSortedSet(SortedSet<String> set)466 public void checkCheckedSortedSet(SortedSet<String> set) { 467 SortedSet<Object> objSet = (SortedSet<Object>)(SortedSet)set; 468 assertThrows(CCE, () -> { objSet.add(new Object()); }); 469 assertThrows(CCE, () -> { objSet.reversed().add(new Object()); }); 470 } 471 472 // ========== Tests ========== 473 474 @Test(dataProvider="all") testFundamentals(String label, SequencedCollection<String> seq, List<String> ref)475 public void testFundamentals(String label, SequencedCollection<String> seq, List<String> ref) { 476 checkContents(seq, ref); 477 } 478 479 @Test(dataProvider="populated") testGetFirst(String label, SequencedCollection<String> seq, List<String> ref)480 public void testGetFirst(String label, SequencedCollection<String> seq, List<String> ref) { 481 assertEquals(seq.getFirst(), ref.get(0)); 482 assertEquals(seq.reversed().getFirst(), ref.get(ref.size() - 1)); 483 checkContents(seq, ref); 484 } 485 486 @Test(dataProvider="populated") testGetLast(String label, SequencedCollection<String> seq, List<String> ref)487 public void testGetLast(String label, SequencedCollection<String> seq, List<String> ref) { 488 assertEquals(seq.getLast(), ref.get(ref.size() - 1)); 489 assertEquals(seq.reversed().getLast(), ref.get(0)); 490 checkContents(seq, ref); 491 } 492 493 @Test(dataProvider="empties") testEmptyGetFirst(String label, SequencedCollection<String> seq, List<String> ref)494 public void testEmptyGetFirst(String label, SequencedCollection<String> seq, List<String> ref) { 495 assertThrows(NoSuchElementException.class, () -> seq.getFirst()); 496 assertThrows(NoSuchElementException.class, () -> seq.reversed().getFirst()); 497 checkContents(seq, ref); 498 } 499 500 @Test(dataProvider="empties") testEmptyGetLast(String label, SequencedCollection<String> seq, List<String> ref)501 public void testEmptyGetLast(String label, SequencedCollection<String> seq, List<String> ref) { 502 assertThrows(NoSuchElementException.class, () -> seq.getLast()); 503 assertThrows(NoSuchElementException.class, () -> seq.reversed().getLast()); 504 checkContents(seq, ref); 505 } 506 507 @Test(dataProvider="adds") testAddFirst(String label, SequencedCollection<String> seq, List<String> baseref)508 public void testAddFirst(String label, SequencedCollection<String> seq, List<String> baseref) { 509 var ref = new ArrayList<>(baseref); 510 ref.add(0, "x"); 511 seq.addFirst("x"); 512 checkContents(seq, ref); 513 } 514 515 @Test(dataProvider="adds") testAddFirstRev(String label, SequencedCollection<String> seq, List<String> baseref)516 public void testAddFirstRev(String label, SequencedCollection<String> seq, List<String> baseref) { 517 var ref = new ArrayList<>(baseref); 518 ref.add("x"); 519 seq.reversed().addFirst("x"); 520 checkContents(seq, ref); 521 } 522 523 @Test(dataProvider="adds") testAddLast(String label, SequencedCollection<String> seq, List<String> baseref)524 public void testAddLast(String label, SequencedCollection<String> seq, List<String> baseref) { 525 var ref = new ArrayList<>(baseref); 526 ref.add("x"); 527 seq.addLast("x"); 528 checkContents(seq, ref); 529 } 530 531 @Test(dataProvider="adds") testAddLastRev(String label, SequencedCollection<String> seq, List<String> baseref)532 public void testAddLastRev(String label, SequencedCollection<String> seq, List<String> baseref) { 533 var ref = new ArrayList<>(baseref); 534 ref.add(0, "x"); 535 seq.reversed().addLast("x"); 536 checkContents(seq, ref); 537 } 538 539 @Test(dataProvider="unpositionedAdd") testUnpositionedAdd(String label, SequencedCollection<String> seq, List<String> baseref)540 public void testUnpositionedAdd(String label, SequencedCollection<String> seq, List<String> baseref) { 541 var ref = new ArrayList<>(baseref); 542 ref.add("x"); 543 seq.add("x"); 544 checkContents(seq, ref); 545 } 546 547 @Test(dataProvider="unpositionedAdd") testUnpositionedAddRev(String label, SequencedCollection<String> seq, List<String> baseref)548 public void testUnpositionedAddRev(String label, SequencedCollection<String> seq, List<String> baseref) { 549 var ref = new ArrayList<>(baseref); 550 ref.add("x"); 551 seq.reversed().add("x"); 552 checkContents(seq, ref); 553 } 554 555 @Test(dataProvider="removes") testRemoveFirst(String label, SequencedCollection<String> seq, List<String> baseref)556 public void testRemoveFirst(String label, SequencedCollection<String> seq, List<String> baseref) { 557 var ref = new ArrayList<>(baseref); 558 var exp = ref.remove(0); 559 var act = seq.removeFirst(); 560 assertEquals(act, exp); 561 checkContents(seq, ref); 562 } 563 564 @Test(dataProvider="removes") testRemoveFirstRev(String label, SequencedCollection<String> seq, List<String> baseref)565 public void testRemoveFirstRev(String label, SequencedCollection<String> seq, List<String> baseref) { 566 var ref = new ArrayList<>(baseref); 567 var exp = ref.remove(ref.size() - 1); 568 var act = seq.reversed().removeFirst(); 569 assertEquals(act, exp); 570 checkContents(seq, ref); 571 } 572 573 @Test(dataProvider="removes") testRemoveLast(String label, SequencedCollection<String> seq, List<String> baseref)574 public void testRemoveLast(String label, SequencedCollection<String> seq, List<String> baseref) { 575 var ref = new ArrayList<>(baseref); 576 var exp = ref.remove(ref.size() - 1); 577 var act = seq.removeLast(); 578 assertEquals(act, exp); 579 checkContents(seq, ref); 580 } 581 582 @Test(dataProvider="removes") testRemoveLastRev(String label, SequencedCollection<String> seq, List<String> baseref)583 public void testRemoveLastRev(String label, SequencedCollection<String> seq, List<String> baseref) { 584 var ref = new ArrayList<>(baseref); 585 var exp = ref.remove(0); 586 var act = seq.reversed().removeLast(); 587 assertEquals(act, exp); 588 checkContents(seq, ref); 589 } 590 591 @Test(dataProvider="emptyRemoves") testEmptyRemoveFirst(String label, SequencedCollection<String> seq, List<String> baseref)592 public void testEmptyRemoveFirst(String label, SequencedCollection<String> seq, List<String> baseref) { 593 assertThrows(NoSuchElementException.class, () -> seq.removeFirst()); 594 assertThrows(NoSuchElementException.class, () -> seq.reversed().removeFirst()); 595 checkContents(seq, baseref); 596 } 597 598 @Test(dataProvider="emptyRemoves") testEmptyRemoveLast(String label, SequencedCollection<String> seq, List<String> baseref)599 public void testEmptyRemoveLast(String label, SequencedCollection<String> seq, List<String> baseref) { 600 assertThrows(NoSuchElementException.class, () -> seq.removeLast()); 601 assertThrows(NoSuchElementException.class, () -> seq.reversed().removeLast()); 602 checkContents(seq, baseref); 603 } 604 605 @Test(dataProvider="serializable") testSerializable(String label, SequencedCollection<String> seq, List<String> ref)606 public void testSerializable(String label, SequencedCollection<String> seq, List<String> ref) 607 throws ClassNotFoundException, IOException 608 { 609 var baos = new ByteArrayOutputStream(); 610 try (var oos = new ObjectOutputStream(baos)) { 611 oos.writeObject(seq); 612 } 613 614 try (var bais = new ByteArrayInputStream(baos.toByteArray()); 615 var ois = new ObjectInputStream(bais)) { 616 var seq2 = (SequencedCollection<String>) ois.readObject(); 617 checkContents(seq2, ref); 618 } 619 } 620 621 @Test(dataProvider="notSerializable") testNotSerializable(String label, SequencedCollection<String> seq)622 public void testNotSerializable(String label, SequencedCollection<String> seq) 623 throws ClassNotFoundException, IOException 624 { 625 var baos = new ByteArrayOutputStream(); 626 try (var oos = new ObjectOutputStream(baos)) { 627 assertThrows(ObjectStreamException.class, () -> oos.writeObject(seq)); 628 } 629 } 630 631 @Test(dataProvider="doubleReverse") testDoubleReverse(String label, SequencedCollection<String> seq)632 public void testDoubleReverse(String label, SequencedCollection<String> seq) { 633 var rrseq = seq.reversed().reversed(); 634 assertSame(rrseq, seq); 635 } 636 637 @Test(dataProvider="unmodifiable") testUnmodifiable(String label, SequencedCollection<String> seq, List<String> ref)638 public void testUnmodifiable(String label, SequencedCollection<String> seq, List<String> ref) { 639 checkUnmodifiable(seq); 640 checkContents(seq, ref); 641 } 642 643 @Test(dataProvider="checkedList") testCheckedList(String label, List<String> list, List<String> ref)644 public void testCheckedList(String label, List<String> list, List<String> ref) { 645 checkCheckedList(list); 646 checkContents(list, ref); 647 } 648 649 @Test(dataProvider="checkedNavSet") testCheckedNavSet(String label, NavigableSet<String> set, List<String> ref)650 public void testCheckedNavSet(String label, NavigableSet<String> set, List<String> ref) { 651 checkCheckedNavSet(set); 652 checkContents(set, ref); 653 } 654 655 @Test(dataProvider="checkedSortedSet") testCheckedSortedSet(String label, SortedSet<String> set, List<String> ref)656 public void testCheckedSortedSet(String label, SortedSet<String> set, List<String> ref) { 657 checkCheckedSortedSet(set); 658 checkContents(set, ref); 659 } 660 661 // Indexes for subList modification tests: 662 // 0 1 2 3 4 5 6 663 // a, b, c, d, e, f, g 664 // c, d, e 665 666 @Test(dataProvider="subListMods") testSubListGet(String label, int mode, List<String> list, List<String> base)667 public void testSubListGet(String label, int mode, List<String> list, List<String> base) { 668 var sub = applyMode(mode, list); 669 assertEquals(sub.getFirst(), isReversed(mode) ? "e" : "c"); 670 assertEquals(sub.getLast(), isReversed(mode) ? "c" : "e"); 671 } 672 673 @Test(dataProvider="subListMods") testSubListAddFirst(String label, int mode, List<String> list, List<String> base)674 public void testSubListAddFirst(String label, int mode, List<String> list, List<String> base) { 675 var refList = new ArrayList<>(base); 676 var sub = applyMode(mode, list); 677 var refSub = new ArrayList<>(sub); 678 679 refList.add(isReversed(mode) ? 5 : 2, "x"); 680 sub.addFirst("x"); 681 refSub.add(0, "x"); 682 683 checkContents(sub, refSub); 684 checkContents(list, refList); 685 } 686 687 @Test(dataProvider="subListMods") testSubListAddLast(String label, int mode, List<String> list, List<String> base)688 public void testSubListAddLast(String label, int mode, List<String> list, List<String> base) { 689 var refList = new ArrayList<>(base); 690 var sub = applyMode(mode, list); 691 var refSub = new ArrayList<>(sub); 692 693 refList.add(isReversed(mode) ? 2 : 5, "x"); 694 sub.addLast("x"); 695 refSub.add("x"); 696 697 checkContents(sub, refSub); 698 checkContents(list, refList); 699 } 700 701 @Test(dataProvider="subListMods") testSubListRemoveFirst(String label, int mode, List<String> list, List<String> base)702 public void testSubListRemoveFirst(String label, int mode, List<String> list, List<String> base) { 703 var refList = new ArrayList<>(base); 704 var sub = applyMode(mode, list); 705 var refSub = new ArrayList<>(sub); 706 707 refList.remove(isReversed(mode) ? 4 : 2); 708 var act = sub.removeFirst(); 709 var exp = refSub.remove(0); 710 711 assertEquals(act, exp); 712 checkContents(sub, refSub); 713 checkContents(list, refList); 714 } 715 716 @Test(dataProvider="subListMods") testSubListRemoveLast(String label, int mode, List<String> list, List<String> base)717 public void testSubListRemoveLast(String label, int mode, List<String> list, List<String> base) { 718 var refList = new ArrayList<>(base); 719 var sub = applyMode(mode, list); 720 var refSub = new ArrayList<>(sub); 721 722 refList.remove(isReversed(mode) ? 2 : 4); 723 var act = sub.removeLast(); 724 var exp = refSub.remove(refSub.size() - 1); 725 726 assertEquals(act, exp); 727 checkContents(sub, refSub); 728 checkContents(list, refList); 729 } 730 731 @Test(dataProvider="subListMods") testSubListAddAllFirst(String label, int mode, List<String> list, List<String> base)732 public void testSubListAddAllFirst(String label, int mode, List<String> list, List<String> base) { 733 var refList = new ArrayList<>(base); 734 var sub = applyMode(mode, list); 735 var refSub = new ArrayList<>(sub); 736 737 if (isReversed(mode)) 738 refList.addAll(5, List.of("y", "x")); 739 else 740 refList.addAll(2, List.of("x", "y")); 741 sub.addAll(0, List.of("x", "y")); 742 refSub.addAll(0, List.of("x", "y")); 743 744 checkContents(sub, refSub); 745 checkContents(list, refList); 746 } 747 748 @Test(dataProvider="subListMods") testSubListAddAllLast(String label, int mode, List<String> list, List<String> base)749 public void testSubListAddAllLast(String label, int mode, List<String> list, List<String> base) { 750 var refList = new ArrayList<>(base); 751 var sub = applyMode(mode, list); 752 var refSub = new ArrayList<>(sub); 753 754 if (isReversed(mode)) 755 refList.addAll(2, List.of("y", "x")); 756 else 757 refList.addAll(5, List.of("x", "y")); 758 sub.addAll(List.of("x", "y")); 759 refSub.addAll(List.of("x", "y")); 760 761 checkContents(sub, refSub); 762 checkContents(list, refList); 763 } 764 765 @Test(dataProvider="iteratorMods") testListIteratorAdd(String label, boolean rev, List<String> list, List<String> base)766 public void testListIteratorAdd(String label, boolean rev, List<String> list, List<String> base) { 767 var ref = new ArrayList<>(base); 768 var it = (rev ? list.reversed() : list).listIterator(); 769 770 ref.add(rev ? 5 : 2, "x"); 771 it.next(); 772 it.next(); 773 it.add("x"); 774 775 assertEquals(it.next(), rev ? "e" : "c"); 776 checkContents(list, ref); 777 } 778 779 @Test(dataProvider="iteratorMods") testListIteratorSet(String label, boolean rev, List<String> list, List<String> base)780 public void testListIteratorSet(String label, boolean rev, List<String> list, List<String> base) { 781 var ref = new ArrayList<>(base); 782 var it = (rev ? list.reversed() : list).listIterator(); 783 784 ref.set(rev ? 5 : 1, "x"); 785 it.next(); 786 it.next(); 787 it.set("x"); 788 789 assertEquals(it.next(), rev ? "e" : "c"); 790 checkContents(list, ref); 791 } 792 793 @Test(dataProvider="iteratorMods") testListIteratorRemove(String label, boolean rev, List<String> list, List<String> base)794 public void testListIteratorRemove(String label, boolean rev, List<String> list, List<String> base) { 795 var ref = new ArrayList<>(base); 796 var it = (rev ? list.reversed() : list).listIterator(); 797 798 ref.remove(rev ? 5 : 1); 799 it.next(); 800 it.next(); 801 it.remove(); 802 803 assertEquals(it.next(), rev ? "e" : "c"); 804 checkContents(list, ref); 805 } 806 807 // SubList ListIterator modification tests. 808 809 @Test(dataProvider="subListIteratorMods") testSubListIteratorAdd(String label, int mode, List<String> list, List<String> base)810 public void testSubListIteratorAdd(String label, int mode, List<String> list, List<String> base) { 811 var refList = new ArrayList<>(base); 812 var sub = applyMode(mode, list); 813 var refSub = new ArrayList<>(sub); 814 815 var it = sub.listIterator(); 816 it.next(); 817 it.add("x"); 818 refList.add(isReversed(mode) ? 4 : 3, "x"); 819 refSub.add(1, "x"); 820 821 assertEquals(it.next(), "d"); 822 checkContents(sub, refSub); 823 checkContents(list, refList); 824 } 825 826 @Test(dataProvider="subListIteratorMods") testSubListIteratorSet(String label, int mode, List<String> list, List<String> base)827 public void testSubListIteratorSet(String label, int mode, List<String> list, List<String> base) { 828 var refList = new ArrayList<>(base); 829 var sub = applyMode(mode, list); 830 var refSub = new ArrayList<>(sub); 831 832 var it = sub.listIterator(); 833 it.next(); 834 it.set("x"); 835 refList.set(isReversed(mode) ? 4 : 2, "x"); 836 refSub.set(0, "x"); 837 838 assertEquals(it.next(), "d"); 839 checkContents(sub, refSub); 840 checkContents(list, refList); 841 } 842 843 @Test(dataProvider="subListIteratorMods") testSubListIteratorRemove(String label, int mode, List<String> list, List<String> base)844 public void testSubListIteratorRemove(String label, int mode, List<String> list, List<String> base) { 845 var refList = new ArrayList<>(base); 846 var sub = applyMode(mode, list); 847 var refSub = new ArrayList<>(sub); 848 849 var it = sub.listIterator(); 850 it.next(); 851 it.remove(); 852 refList.remove(isReversed(mode) ? 4 : 2); 853 refSub.remove(0); 854 855 assertEquals(it.next(), "d"); 856 checkContents(sub, refSub); 857 checkContents(list, refList); 858 } 859 } 860