1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.commons.collections;
18
19 import static org.apache.juneau.commons.utils.CollectionUtils.*;
20 import static org.apache.juneau.junit.bct.BctAssertions.*;
21 import static org.junit.jupiter.api.Assertions.*;
22
23 import java.util.*;
24
25 import org.apache.juneau.*;
26 import org.junit.jupiter.api.*;
27
28 class MultiList_Test extends TestBase {
29
30 @Test
31 void a01_basicIteration() {
32 List<String> l1, l2;
33 MultiList<String> ml;
34
35 l1 = l(a("1", "2"));
36 l2 = l(a("3", "4"));
37 ml = new MultiList<>(l1, l2);
38 var i1 = ml.iterator();
39 assertTrue(i1.hasNext());
40 assertEquals("1", i1.next());
41 assertTrue(i1.hasNext());
42 assertEquals("2", i1.next());
43 assertTrue(i1.hasNext());
44 assertEquals("3", i1.next());
45 assertTrue(i1.hasNext());
46 assertEquals("4", i1.next());
47 assertFalse(i1.hasNext());
48 assertThrows(NoSuchElementException.class, i1::next);
49 }
50
51 @Test
52 void a02_emptySecondList() {
53 List<String> l1 = l(a("1", "2"));
54 List<String> l2 = l(a());
55 MultiList<String> ml = new MultiList<>(l1, l2);
56 var i2 = ml.iterator();
57 assertTrue(i2.hasNext());
58 assertEquals("1", i2.next());
59 assertTrue(i2.hasNext());
60 assertEquals("2", i2.next());
61 assertFalse(i2.hasNext());
62 assertThrows(NoSuchElementException.class, i2::next);
63 }
64
65 @Test
66 void a03_emptyFirstList() {
67 List<String> l1 = l(a());
68 List<String> l2 = l(a("3", "4"));
69 MultiList<String> ml = new MultiList<>(l1, l2);
70 var i3 = ml.iterator();
71 assertTrue(i3.hasNext());
72 assertEquals("3", i3.next());
73 assertTrue(i3.hasNext());
74 assertEquals("4", i3.next());
75 assertFalse(i3.hasNext());
76 assertThrows(NoSuchElementException.class, i3::next);
77 }
78
79 @Test
80 void a04_bothEmptyLists() {
81 List<String> l1 = l(a());
82 List<String> l2 = l(a());
83 MultiList<String> ml = new MultiList<>(l1, l2);
84 var i4 = ml.iterator();
85 assertFalse(i4.hasNext());
86 assertThrows(NoSuchElementException.class, i4::next);
87 }
88
89 @Test
90 void a05_singleList() {
91 List<String> l1 = l(a("1", "2"));
92 MultiList<String> ml = new MultiList<>(l1);
93 var i5 = ml.iterator();
94 assertTrue(i5.hasNext());
95 assertEquals("1", i5.next());
96 assertTrue(i5.hasNext());
97 assertEquals("2", i5.next());
98 assertFalse(i5.hasNext());
99 assertThrows(NoSuchElementException.class, i5::next);
100 }
101
102 @Test
103 void a06_assertListAndEnumerator() {
104 List<String> l1 = new LinkedList<>(l(a("1", "2")));
105 List<String> l2 = new LinkedList<>(l(a("3", "4")));
106 MultiList<String> ml = new MultiList<>(l1, l2);
107 assertList(ml, "1", "2", "3", "4");
108 assertList(ml.enumerator(), "1", "2", "3", "4");
109 assertSize(4, ml);
110 }
111
112 @Test
113 void a07_iteratorRemove() {
114 List<String> l1 = new LinkedList<>(l(a("1", "2")));
115 List<String> l2 = new LinkedList<>(l(a("3", "4")));
116 MultiList<String> ml = new MultiList<>(l1, l2);
117
118 var t = ml.iterator();
119 t.next();
120 t.remove();
121 assertList(ml.enumerator(), "2", "3", "4");
122
123 t = ml.iterator();
124 t.next();
125 t.remove();
126 assertList(ml.enumerator(), "3", "4");
127
128 t = ml.iterator();
129 t.next();
130 t.remove();
131 assertList(ml.enumerator(), "4");
132
133 t = ml.iterator();
134 t.next();
135 t.remove();
136 assertEmpty(ml.enumerator());
137 assertEmpty(ml);
138 }
139
140 @Test
141 void a08_emptyMultiList() {
142 MultiList<String> ml = new MultiList<>();
143 assertEmpty(ml);
144 assertThrows(NoSuchElementException.class, () -> new MultiList<String>().iterator().next());
145 assertThrows(IllegalStateException.class, () -> new MultiList<String>().iterator().remove());
146 }
147
148 @Test
149 void a09_nullListThrowsException() {
150 assertThrows(IllegalArgumentException.class, () -> new MultiList<>((List<String>)null));
151 }
152
153 @Test
154 void a10_hasNext_whenCurrentIteratorExhausted_butMoreListsHaveElements() {
155
156 var l1 = l(a("1", "2"));
157 var l2 = l(a("3", "4"));
158 var l3 = l(a("5", "6"));
159 var ml = new MultiList<>(l1, l2, l3);
160 var it = ml.iterator();
161
162
163 assertTrue(it.hasNext());
164 assertEquals("1", it.next());
165 assertTrue(it.hasNext());
166 assertEquals("2", it.next());
167
168
169
170 assertTrue(it.hasNext());
171 assertEquals("3", it.next());
172
173
174 assertTrue(it.hasNext());
175 assertEquals("4", it.next());
176
177
178 assertTrue(it.hasNext());
179 assertEquals("5", it.next());
180 assertTrue(it.hasNext());
181 assertEquals("6", it.next());
182 assertFalse(it.hasNext());
183 }
184
185 @Test
186 void a11_hasNext_withEmptyListsInBetween() {
187
188 var l1 = l(a("1"));
189 var l2 = l(new String[0]);
190 var l3 = l(a("2"));
191 var l4 = l(new String[0]);
192 var l5 = l(a("3"));
193 var ml = new MultiList<>(l1, l2, l3, l4, l5);
194 var it = ml.iterator();
195
196
197 assertTrue(it.hasNext());
198 assertEquals("1", it.next());
199
200
201 assertTrue(it.hasNext());
202 assertEquals("2", it.next());
203
204
205 assertTrue(it.hasNext());
206 assertEquals("3", it.next());
207 assertFalse(it.hasNext());
208 }
209
210
211
212
213
214 @Test
215 void b01_getByIndex() {
216 var l1 = l(a("1", "2"));
217 var l2 = l(a("3", "4", "5"));
218 var ml = new MultiList<>(l1, l2);
219
220 assertEquals("1", ml.get(0));
221 assertEquals("2", ml.get(1));
222 assertEquals("3", ml.get(2));
223 assertEquals("4", ml.get(3));
224 assertEquals("5", ml.get(4));
225 }
226
227 @Test
228 void b02_getByIndex_withEmptyLists() {
229 var l1 = l(a("1"));
230 var l2 = l(new String[0]);
231 var l3 = l(a("2", "3"));
232 var ml = new MultiList<>(l1, l2, l3);
233
234 assertEquals("1", ml.get(0));
235 assertEquals("2", ml.get(1));
236 assertEquals("3", ml.get(2));
237 }
238
239 @Test
240 void b03_getByIndex_outOfBounds() {
241 var l1 = l(a("1", "2"));
242 var ml = new MultiList<>(l1);
243
244 assertThrows(IndexOutOfBoundsException.class, () -> ml.get(-1));
245 assertThrows(IndexOutOfBoundsException.class, () -> ml.get(2));
246 }
247
248 @Test
249 void b04_getByIndex_singleElementLists() {
250 var l1 = l(a("1"));
251 var l2 = l(a("2"));
252 var l3 = l(a("3"));
253 var ml = new MultiList<>(l1, l2, l3);
254
255 assertEquals("1", ml.get(0));
256 assertEquals("2", ml.get(1));
257 assertEquals("3", ml.get(2));
258 }
259
260
261
262
263
264 @Test
265 void c01_listIterator_forward() {
266 var l1 = l(a("1", "2"));
267 var l2 = l(a("3", "4"));
268 var ml = new MultiList<>(l1, l2);
269 var li = ml.listIterator();
270
271 assertTrue(li.hasNext());
272 assertEquals(0, li.nextIndex());
273 assertEquals("1", li.next());
274 assertEquals(1, li.nextIndex());
275 assertEquals("2", li.next());
276 assertEquals(2, li.nextIndex());
277 assertEquals("3", li.next());
278 assertEquals(3, li.nextIndex());
279 assertEquals("4", li.next());
280 assertEquals(4, li.nextIndex());
281 assertFalse(li.hasNext());
282 }
283
284 @Test
285 void c02_listIterator_backward() {
286 var l1 = l(a("1", "2"));
287 var l2 = l(a("3", "4"));
288 var ml = new MultiList<>(l1, l2);
289 var li = ml.listIterator(ml.size());
290
291 assertTrue(li.hasPrevious());
292 assertEquals(3, li.previousIndex());
293 assertEquals("4", li.previous());
294 assertEquals(2, li.previousIndex());
295 assertEquals("3", li.previous());
296 assertEquals(1, li.previousIndex());
297 assertEquals("2", li.previous());
298 assertEquals(0, li.previousIndex());
299 assertEquals("1", li.previous());
300 assertEquals(-1, li.previousIndex());
301 assertFalse(li.hasPrevious());
302 }
303
304 @Test
305 void c03_listIterator_bidirectional() {
306 var l1 = l(a("1", "2"));
307 var l2 = l(a("3", "4"));
308 var ml = new MultiList<>(l1, l2);
309 var li = ml.listIterator();
310
311
312 assertEquals("1", li.next());
313 assertEquals("2", li.next());
314
315
316 assertEquals("2", li.previous());
317 assertEquals("1", li.previous());
318
319
320 assertEquals("1", li.next());
321 assertEquals("2", li.next());
322 assertEquals("3", li.next());
323 }
324
325 @Test
326 void c04_listIterator_remove() {
327 var l1 = new LinkedList<>(l(a("1", "2")));
328 var l2 = new LinkedList<>(l(a("3", "4")));
329 var ml = new MultiList<>(l1, l2);
330 var li = ml.listIterator();
331
332 li.next();
333 li.next();
334 li.remove();
335 assertList(ml, "1", "3", "4");
336
337 li.next();
338 li.remove();
339 assertList(ml, "1", "4");
340 }
341
342 @Test
343 void c05_listIterator_set() {
344 var l1 = new ArrayList<>(l(a("1", "2")));
345 var l2 = new ArrayList<>(l(a("3", "4")));
346 var ml = new MultiList<>(l1, l2);
347 var li = ml.listIterator();
348
349 li.next();
350 li.set("10");
351 assertEquals("10", ml.get(0));
352
353 li.next();
354 li.next();
355 li.set("30");
356 assertEquals("30", ml.get(2));
357 }
358
359 @Test
360 void c06_listIterator_addThrowsException() {
361 var l1 = l(a("1", "2"));
362 var ml = new MultiList<>(l1);
363 var li = ml.listIterator();
364
365 li.next();
366 assertThrows(UnsupportedOperationException.class, () -> li.add("x"));
367 }
368
369 @Test
370 void c07_listIterator_startAtIndex() {
371 var l1 = l(a("1", "2"));
372 var l2 = l(a("3", "4"));
373 var ml = new MultiList<>(l1, l2);
374 var li = ml.listIterator(2);
375
376 assertTrue(li.hasNext());
377 assertEquals(2, li.nextIndex());
378 assertEquals("3", li.next());
379 assertEquals("4", li.next());
380 assertFalse(li.hasNext());
381 }
382
383 @Test
384 void c08_listIterator_startAtEnd() {
385 var l1 = l(a("1", "2"));
386 var l2 = l(a("3", "4"));
387 var ml = new MultiList<>(l1, l2);
388 var li = ml.listIterator(ml.size());
389
390 assertFalse(li.hasNext());
391 assertTrue(li.hasPrevious());
392 assertEquals("4", li.previous());
393 }
394
395 @Test
396 void c09_listIterator_outOfBounds() {
397 var l1 = l(a("1", "2"));
398 var ml = new MultiList<>(l1);
399
400 assertThrows(IndexOutOfBoundsException.class, () -> ml.listIterator(-1));
401 assertThrows(IndexOutOfBoundsException.class, () -> ml.listIterator(3));
402 }
403
404
405
406
407
408 @Test
409 void d01_size() {
410 var l1 = l(a("1", "2"));
411 var l2 = l(a("3", "4", "5"));
412 var ml = new MultiList<>(l1, l2);
413
414 assertEquals(5, ml.size());
415 }
416
417 @Test
418 void d02_size_withEmptyLists() {
419 var l1 = l(new String[0]);
420 var l2 = l(a("1"));
421 var l3 = l(new String[0]);
422 var ml = new MultiList<>(l1, l2, l3);
423
424 assertEquals(1, ml.size());
425 }
426
427 @Test
428 void d03_size_emptyMultiList() {
429 var ml = new MultiList<String>();
430 assertEquals(0, ml.size());
431 }
432
433
434
435
436
437 @Test
438 void e01_forEach() {
439 var l1 = l(a("1", "2"));
440 var l2 = l(a("3", "4"));
441 var ml = new MultiList<>(l1, l2);
442 var result = new ArrayList<String>();
443
444 ml.forEach(result::add);
445 assertList(result, "1", "2", "3", "4");
446 }
447
448 @Test
449 void e02_stream() {
450 var l1 = l(a("1", "2"));
451 var l2 = l(a("3", "4"));
452 var ml = new MultiList<>(l1, l2);
453
454 var result = ml.stream().toList();
455 assertList(result, "1", "2", "3", "4");
456 }
457
458 @Test
459 void e03_indexOf() {
460 var l1 = l(a("1", "2"));
461 var l2 = l(a("3", "2", "4"));
462 var ml = new MultiList<>(l1, l2);
463
464 assertEquals(1, ml.indexOf("2"));
465 assertEquals(3, ml.lastIndexOf("2"));
466 }
467
468 @Test
469 void e04_contains() {
470 var l1 = l(a("1", "2"));
471 var l2 = l(a("3", "4"));
472 var ml = new MultiList<>(l1, l2);
473
474 assertTrue(ml.contains("2"));
475 assertTrue(ml.contains("3"));
476 assertFalse(ml.contains("5"));
477 }
478
479 @Test
480 void e05_toArray() {
481 var l1 = l(a("1", "2"));
482 var l2 = l(a("3", "4"));
483 var ml = new MultiList<>(l1, l2);
484
485 var array = ml.toArray();
486 assertEquals(4, array.length);
487 assertEquals("1", array[0]);
488 assertEquals("2", array[1]);
489 assertEquals("3", array[2]);
490 assertEquals("4", array[3]);
491 }
492
493
494
495
496
497 @Test
498 void f01_toString_singleList() {
499 var l1 = l(a("1", "2"));
500 var ml = new MultiList<>(l1);
501
502 var expected = "[" + l1.toString() + "]";
503 assertEquals(expected, ml.toString());
504 }
505
506 @Test
507 void f02_toString_multipleLists() {
508 var l1 = l(a("1", "2"));
509 var l2 = l(a("3", "4"));
510 var l3 = l(a("5", "6"));
511 var ml = new MultiList<>(l1, l2, l3);
512
513 var expected = "[" + l1.toString() + ", " + l2.toString() + ", " + l3.toString() + "]";
514 assertEquals(expected, ml.toString());
515 }
516
517 @Test
518 void f03_toString_emptyLists() {
519 var l1 = l(a());
520 var l2 = l(a());
521 var ml = new MultiList<>(l1, l2);
522
523 var expected = "[" + l1.toString() + ", " + l2.toString() + "]";
524 assertEquals(expected, ml.toString());
525 }
526
527 @Test
528 void f04_toString_mixedEmptyAndNonEmpty() {
529 List<String> l1 = l(a());
530 var l2 = l(a("1", "2"));
531 List<String> l3 = l(a());
532 var ml = new MultiList<>(l1, l2, l3);
533
534 var expected = "[" + l1.toString() + ", " + l2.toString() + ", " + l3.toString() + "]";
535 assertEquals(expected, ml.toString());
536 }
537
538
539
540
541
542 @Test
543 void g01_equals_sameContents() {
544 var l1 = l(a("1", "2"));
545 var l2 = l(a("3", "4"));
546 var multiList1 = new MultiList<>(l1, l2);
547
548 var l3 = l(a("1", "2"));
549 var l4 = l(a("3", "4"));
550 var multiList2 = new MultiList<>(l3, l4);
551
552 assertTrue(multiList1.equals(multiList2));
553 assertTrue(multiList2.equals(multiList1));
554 }
555
556 @Test
557 void g02_equals_differentContents() {
558 var l1 = l(a("1", "2"));
559 var multiList1 = new MultiList<>(l1);
560
561 var l2 = l(a("1", "3"));
562 var multiList2 = new MultiList<>(l2);
563
564 assertFalse(multiList1.equals(multiList2));
565 assertFalse(multiList2.equals(multiList1));
566 }
567
568 @Test
569 void g03_equals_differentOrder() {
570 var l1 = l(a("1", "2"));
571 var l2 = l(a("3", "4"));
572 var multiList1 = new MultiList<>(l1, l2);
573
574 var l3 = l(a("3", "4"));
575 var l4 = l(a("1", "2"));
576 var multiList2 = new MultiList<>(l3, l4);
577
578 assertFalse(multiList1.equals(multiList2));
579 }
580
581 @Test
582 void g04_equals_regularList() {
583 var l1 = l(a("1", "2", "3"));
584 var multiList = new MultiList<>(l1);
585
586 var regularList = new ArrayList<>(l(a("1", "2", "3")));
587
588 assertTrue(multiList.equals(regularList));
589 assertTrue(regularList.equals(multiList));
590 }
591
592 @Test
593 void g05_equals_notAList() {
594 var l1 = l(a("1", "2"));
595 var multiList = new MultiList<>(l1);
596 assertFalse(multiList.equals(null));
597 }
598
599 @Test
600 void g06_hashCode_sameContents() {
601 var l1 = l(a("1", "2", "3"));
602 var multiList1 = new MultiList<>(l1);
603
604 var l2 = l(a("1", "2", "3"));
605 var multiList2 = new MultiList<>(l2);
606
607 assertEquals(multiList1.hashCode(), multiList2.hashCode());
608 }
609
610 @Test
611 void g07_hashCode_regularList() {
612 var l1 = l(a("1", "2", "3"));
613 var multiList = new MultiList<>(l1);
614
615 var regularList = new ArrayList<>(l(a("1", "2", "3")));
616
617 assertEquals(multiList.hashCode(), regularList.hashCode());
618 }
619
620
621
622
623
624 @Test
625 void h01_iterator_hasNext_whenI2IsNull() {
626
627
628 var ml = new MultiList<String>();
629 var it = ml.iterator();
630 assertFalse(it.hasNext());
631 }
632
633 @Test
634 void h02_listIterator_hasNext_whenCurrentIteratorIsNull() {
635
636
637 List<String> l1 = l(a());
638 List<String> l2 = l(a());
639 var ml = new MultiList<>(l1, l2);
640 var li = ml.listIterator(0);
641
642 assertFalse(li.hasNext());
643 }
644
645 @Test
646 void h03_listIterator_hasNext_findsNextNonEmptyList() {
647
648 var l1 = l(a("1", "2"));
649 List<String> l2 = l(a());
650 var l3 = l(a("3", "4"));
651 var ml = new MultiList<>(l1, l2, l3);
652 var li = ml.listIterator();
653
654
655 assertEquals("1", li.next());
656 assertEquals("2", li.next());
657
658 assertTrue(li.hasNext());
659 assertEquals("3", li.next());
660 }
661
662 @Test
663 void h04_listIterator_next_throwsWhenCurrentIteratorIsNull() {
664
665
666 List<String> l1 = l(a());
667 var ml = new MultiList<>(l1);
668 var li = ml.listIterator(0);
669
670 assertThrows(NoSuchElementException.class, li::next);
671 }
672
673 @Test
674 void h05_listIterator_next_throwsWhenExhausted() {
675
676 var l1 = l(a("1", "2"));
677 var l2 = l(a("3"));
678 var ml = new MultiList<>(l1, l2);
679 var li = ml.listIterator();
680
681
682 assertEquals("1", li.next());
683 assertEquals("2", li.next());
684 assertEquals("3", li.next());
685
686 assertThrows(NoSuchElementException.class, li::next);
687 }
688
689 @Test
690 void h06_listIterator_hasPrevious_whenCurrentIteratorIsNull() {
691
692 var l1 = l(a());
693 var ml = new MultiList<>(l1);
694 var li = ml.listIterator(0);
695 assertFalse(li.hasPrevious());
696 }
697
698 @Test
699 void h07_listIterator_hasPrevious_findsPreviousList() {
700
701 var l1 = l(a("1", "2"));
702 List<String> l2 = l(a());
703 var l3 = l(a("3", "4"));
704 var ml = new MultiList<>(l1, l2, l3);
705 var li = ml.listIterator(ml.size());
706
707
708 assertEquals("4", li.previous());
709 assertEquals("3", li.previous());
710
711 assertTrue(li.hasPrevious());
712 assertEquals("2", li.previous());
713 }
714
715 @Test
716 void h08_listIterator_remove_throwsWhenCurrentIteratorIsNull() {
717
718 var l1 = l(a("1"));
719 var ml = new MultiList<>(l1);
720 var li = ml.listIterator();
721
722 assertThrows(IllegalStateException.class, li::remove);
723 }
724
725 @Test
726 void h09_listIterator_set_throwsWhenCurrentIteratorIsNull() {
727
728 var l1 = l(a("1"));
729 var ml = new MultiList<>(l1);
730 var li = ml.listIterator();
731
732 assertThrows(IllegalStateException.class, () -> li.set("x"));
733 }
734
735 @Test
736 void h10_listIterator_constructor_atEndWithNonEmptyLists() {
737
738
739 var l1 = l(a("1", "2"));
740 var l2 = l(a("3", "4"));
741 var ml = new MultiList<>(l1, l2);
742 var li = ml.listIterator(ml.size());
743
744
745 assertTrue(li.hasPrevious());
746 assertEquals("4", li.previous());
747 }
748
749 @Test
750 void h11_equals_differentLengths() {
751
752
753
754 var l1 = l(a("1", "2"));
755 var ml1 = new MultiList<>(l1);
756
757 var l2 = l(a("1", "2", "3"));
758 var ml2 = new MultiList<>(l2);
759
760 assertFalse(ml1.equals(ml2));
761 assertFalse(ml2.equals(ml1));
762 }
763
764 @Test
765 void h12_equals_oneExhausted() {
766
767 var l1 = l(a("1", "2"));
768 var ml1 = new MultiList<>(l1);
769
770 var l2 = l(a("1", "2", "3"));
771 var ml2 = new MultiList<>(l2);
772
773
774
775 assertFalse(ml1.equals(ml2));
776 }
777
778 @Test
779 void h13_hashCode_iteratesThroughAllElements() {
780
781
782 var l1 = l(a("1", "2"));
783 var l2 = l(a("3", "4"));
784 var ml = new MultiList<>(l1, l2);
785
786
787 int expectedHashCode = 1;
788 for (String e : ml) {
789 expectedHashCode = 31 * expectedHashCode + (e == null ? 0 : e.hashCode());
790 }
791
792 assertEquals(expectedHashCode, ml.hashCode());
793 }
794
795 @Test
796 void h14_hashCode_withNullElements() {
797
798 var l1 = l(a("1", null));
799 var l2 = l(a("2"));
800 var ml = new MultiList<>(l1, l2);
801
802
803 int expectedHashCode = 1;
804 expectedHashCode = 31 * expectedHashCode + "1".hashCode();
805 expectedHashCode = 31 * expectedHashCode + 0;
806 expectedHashCode = 31 * expectedHashCode + "2".hashCode();
807
808 assertEquals(expectedHashCode, ml.hashCode());
809 }
810 }
811