1 package dev.aherscu.qa.testing.utils;
2
3 import java.util.Iterator;
4 import java.util.LinkedList;
5 import java.util.List;
6 import java.util.Objects;
7 import java.util.PrimitiveIterator;
8 import java.util.stream.BaseStream;
9 import java.util.stream.DoubleStream;
10 import java.util.stream.IntStream;
11 import java.util.stream.LongStream;
12 import java.util.stream.Stream;
13
14 import org.hamcrest.Description;
15 import org.hamcrest.Matcher;
16 import org.hamcrest.TypeSafeMatcher;
17
18 public class StreamMatchers {
19
20
21
22
23
24
25
26
27
28 public static <T, S extends BaseStream<T, ? extends S>> Matcher<S> yieldsNothing() {
29 return new TypeSafeMatcher<S>() {
30
31 private Iterator<T> actualIterator;
32
33 @Override
34 protected boolean matchesSafely(S actual) {
35 actualIterator = actual.iterator();
36 return !actualIterator.hasNext();
37 }
38
39 @Override
40 public void describeTo(Description description) {
41 description.appendText("A Stream yielding no elements");
42 }
43
44 @Override
45 protected void describeMismatchSafely(S item,
46 Description description) {
47 description.appendText("the Stream started with ")
48 .appendValue(actualIterator.next());
49 if (actualIterator.hasNext()) {
50 description
51 .appendText(" and will yield even more elements");
52 } else {
53 description.appendText(" and is then exhausted");
54 }
55 }
56 };
57 }
58
59
60
61
62
63
64
65
66
67
68
69
70 @Deprecated
71 public static <T, S extends BaseStream<T, ? extends S>> Matcher<S> empty() {
72 return yieldsNothing();
73 }
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 public static <T, S extends BaseStream<T, ? extends S>> Matcher<S> yieldsSameAs(
93 S expected) {
94 return new BaseStreamMatcher<T, S>() {
95 @Override
96 protected boolean matchesSafely(S actual) {
97 return remainingItemsEqual(expected.iterator(),
98 actual.iterator());
99 }
100 };
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 @Deprecated
119 public static <T, S extends BaseStream<T, ? extends S>> Matcher<S> equalTo(
120 S expected) {
121 return yieldsSameAs(expected);
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 public static <T> Matcher<Stream<T>> startsWith(Stream<T> expected,
140 long limit) {
141 return new BaseStreamMatcher<T, Stream<T>>() {
142 @Override
143 protected boolean matchesSafely(Stream<T> actual) {
144 return remainingItemsEqual(expected.limit(limit).iterator(),
145 actual.limit(limit).iterator());
146 }
147 };
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public static Matcher<DoubleStream> startsWith(DoubleStream expected,
164 long limit) {
165 return new BaseStreamMatcher<Double, DoubleStream>() {
166 @Override
167 protected boolean matchesSafely(DoubleStream actual) {
168 return remainingItemsEqual(expected.limit(limit).iterator(),
169 actual.limit(limit).iterator());
170 }
171 };
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187 public static Matcher<IntStream> startsWith(IntStream expected,
188 long limit) {
189 return new BaseStreamMatcher<Integer, IntStream>() {
190 @Override
191 protected boolean matchesSafely(IntStream actual) {
192 return remainingItemsEqual(expected.limit(limit).iterator(),
193 actual.limit(limit).iterator());
194 }
195 };
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 public static Matcher<LongStream> startsWith(LongStream expected,
212 long limit) {
213 return new BaseStreamMatcher<Long, LongStream>() {
214 @Override
215 protected boolean matchesSafely(LongStream actual) {
216 return remainingItemsEqual(expected.limit(limit).iterator(),
217 actual.limit(limit).iterator());
218 }
219 };
220 }
221
222 private static void describeToStartsAllWith(Description description,
223 long limit, Matcher<?> matcher) {
224 description
225 .appendText("First ")
226 .appendText(Long.toString(limit))
227 .appendText(" to match ")
228 .appendValue(matcher);
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244 public static <T> Matcher<Stream<T>> startsWithAll(Matcher<T> matcher,
245 long limit) {
246 return new StreamAllMatches<T>(matcher) {
247 @Override
248 protected boolean matchesSafely(Stream<T> actual) {
249 return super.matchesSafely(actual.limit(limit));
250 }
251
252 @Override
253 public void describeTo(Description description) {
254 describeToStartsAllWith(description, limit, matcher);
255 }
256 };
257
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273 public static Matcher<LongStream> startsWithAllLong(Matcher<Long> matcher,
274 long limit) {
275 return new LongStreamAllMatches(matcher) {
276 @Override
277 protected boolean matchesSafely(LongStream actual) {
278 return super.matchesSafely(actual.limit(limit));
279 }
280
281 @Override
282 public void describeTo(Description description) {
283 describeToStartsAllWith(description, limit, matcher);
284 }
285 };
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 public static Matcher<IntStream> startsWithAllInt(Matcher<Integer> matcher,
302 long limit) {
303 return new IntStreamAllMatches(matcher) {
304 @Override
305 protected boolean matchesSafely(IntStream actual) {
306 return super.matchesSafely(actual.limit(limit));
307 }
308
309 @Override
310 public void describeTo(Description description) {
311 describeToStartsAllWith(description, limit, matcher);
312 }
313 };
314 }
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 public static Matcher<DoubleStream> startsWithAllDouble(
330 Matcher<Double> matcher, long limit) {
331 return new DoubleStreamAllMatches(matcher) {
332 @Override
333 protected boolean matchesSafely(DoubleStream actual) {
334 return super.matchesSafely(actual.limit(limit));
335 }
336
337 @Override
338 public void describeTo(Description description) {
339 describeToStartsAllWith(description, limit, matcher);
340 }
341 };
342 }
343
344 private static void describeToStartsAnyWith(Description description,
345 long limit, Matcher<?> matcher) {
346 description
347 .appendText("Any of first ")
348 .appendText(Long.toString(limit))
349 .appendText(" to match ")
350 .appendValue(matcher);
351 }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366 public static <T> Matcher<Stream<T>> startsWithAny(Matcher<T> matcher,
367 long limit) {
368 return new StreamAnyMatches<T>(matcher) {
369 @Override
370 protected boolean matchesSafely(Stream<T> actual) {
371 return super.matchesSafely(actual.limit(limit));
372 }
373
374 @Override
375 public void describeTo(Description description) {
376 describeToStartsAnyWith(description, limit, matcher);
377 }
378 };
379 }
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394 public static Matcher<LongStream> startsWithAnyLong(Matcher<Long> matcher,
395 long limit) {
396 return new LongStreamAnyMatches(matcher) {
397 @Override
398 protected boolean matchesSafely(LongStream actual) {
399 return super.matchesSafely(actual.limit(limit));
400 }
401
402 @Override
403 public void describeTo(Description description) {
404 describeToStartsAnyWith(description, limit, matcher);
405 }
406 };
407 }
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422 public static Matcher<DoubleStream> startsWithAnyDouble(
423 Matcher<Double> matcher, long limit) {
424 return new DoubleStreamAnyMatches(matcher) {
425 @Override
426 protected boolean matchesSafely(DoubleStream actual) {
427 return super.matchesSafely(actual.limit(limit));
428 }
429
430 @Override
431 public void describeTo(Description description) {
432 describeToStartsAnyWith(description, limit, matcher);
433 }
434 };
435 }
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450 public static Matcher<IntStream> startsWithAnyInt(Matcher<Integer> matcher,
451 long limit) {
452 return new IntStreamAnyMatches(matcher) {
453 @Override
454 protected boolean matchesSafely(IntStream actual) {
455 return super.matchesSafely(actual.limit(limit));
456 }
457
458 @Override
459 public void describeTo(Description description) {
460 describeToStartsAnyWith(description, limit, matcher);
461 }
462 };
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484 @SafeVarargs
485 public static <T, S extends BaseStream<T, ? extends S>> Matcher<S> yieldsExactly(
486 Matcher<T>... expectedMatchers) {
487 return new BaseMatcherStreamMatcher<T, S>() {
488 @Override
489 protected boolean matchesSafely(S actual) {
490 return remainingItemsMatch(
491 new ArrayIterator<>(expectedMatchers), actual.iterator());
492 }
493 };
494 }
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512 @SafeVarargs
513 @Deprecated
514 public static <T, S extends BaseStream<T, ? extends S>> Matcher<S> contains(
515 Matcher<T>... expectedMatchers) {
516 return yieldsExactly(expectedMatchers);
517 }
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537 @SafeVarargs
538 public static <T, S extends BaseStream<T, ? extends S>> Matcher<S> yieldsExactly(
539 T... expected) {
540 return new BaseStreamMatcher<T, S>() {
541 @Override
542 protected boolean matchesSafely(S actual) {
543 return remainingItemsEqual(new ArrayIterator<>(expected),
544 actual.iterator());
545 }
546 };
547 }
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564 @SafeVarargs
565 @Deprecated
566 public static <T, S extends BaseStream<T, ? extends S>> Matcher<S> contains(
567 T... expected) {
568 return yieldsExactly(expected);
569 }
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586 public static <T> Matcher<Stream<T>> allMatch(Matcher<T> matcher) {
587 return new StreamAllMatches<T>(matcher) {
588 @Override
589 public void describeTo(Description description) {
590 description.appendText("All to match ").appendValue(matcher);
591 }
592 };
593 }
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608 public static Matcher<IntStream> allMatchInt(Matcher<Integer> matcher) {
609 return new IntStreamAllMatches(matcher) {
610 @Override
611 public void describeTo(Description description) {
612 description.appendText("All to match ").appendValue(matcher);
613 }
614 };
615 }
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630 public static Matcher<LongStream> allMatchLong(Matcher<Long> matcher) {
631 return new LongStreamAllMatches(matcher) {
632 @Override
633 public void describeTo(Description description) {
634 description.appendText("All to match ").appendValue(matcher);
635 }
636 };
637 }
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652 public static Matcher<DoubleStream> allMatchDouble(
653 Matcher<Double> matcher) {
654 return new DoubleStreamAllMatches(matcher) {
655 @Override
656 public void describeTo(Description description) {
657 description.appendText("All to match ").appendValue(matcher);
658 }
659 };
660 }
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677 public static <T> Matcher<Stream<T>> anyMatch(Matcher<T> matcher) {
678 return new StreamAnyMatches<T>(matcher) {
679 @Override
680 public void describeTo(Description description) {
681 description.appendText("Any to match ").appendValue(matcher);
682 }
683 };
684 }
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699 public static Matcher<LongStream> anyMatchLong(Matcher<Long> matcher) {
700 return new LongStreamAnyMatches(matcher) {
701 @Override
702 public void describeTo(Description description) {
703 description.appendText("Any to match ").appendValue(matcher);
704 }
705 };
706 }
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721 public static Matcher<DoubleStream> anyMatchDouble(
722 Matcher<Double> matcher) {
723 return new DoubleStreamAnyMatches(matcher) {
724 @Override
725 public void describeTo(Description description) {
726 description.appendText("Any to match ").appendValue(matcher);
727 }
728 };
729 }
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745 public static Matcher<IntStream> anyMatchInt(Matcher<Integer> matcher) {
746 return new IntStreamAnyMatches(matcher) {
747 @Override
748 public void describeTo(Description description) {
749 description.appendText("Any to match ").appendValue(matcher);
750 }
751 };
752 }
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770 @SafeVarargs
771 public static <T> Matcher<Stream<T>> startsWith(T... expected) {
772 return new BaseStreamMatcher<T, Stream<T>>() {
773 @Override
774 protected boolean matchesSafely(Stream<T> actual) {
775 return remainingItemsEqual(new ArrayIterator<>(expected),
776 actual.limit(expected.length).iterator());
777 }
778 };
779 }
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794 public static Matcher<DoubleStream> startsWithDouble(double... expected) {
795 return new BaseStreamMatcher<Double, DoubleStream>() {
796 @Override
797 protected boolean matchesSafely(DoubleStream actual) {
798 return remainingItemsEqual(new DoubleArrayIterator(expected),
799 actual.limit(expected.length).iterator());
800 }
801 };
802 }
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817 public static Matcher<LongStream> startsWithLong(long... expected) {
818 return new BaseStreamMatcher<Long, LongStream>() {
819 @Override
820 protected boolean matchesSafely(LongStream actual) {
821 return remainingItemsEqual(new LongArrayIterator(expected),
822 actual.limit(expected.length).iterator());
823 }
824 };
825 }
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840 public static Matcher<IntStream> startsWithInt(int... expected) {
841 return new BaseStreamMatcher<Integer, IntStream>() {
842 @Override
843 protected boolean matchesSafely(IntStream actual) {
844 return remainingItemsEqual(new IntArrayIterator(expected),
845 actual.limit(expected.length).iterator());
846 }
847 };
848 }
849
850 private static abstract class BaseStreamMatcher<T, S extends BaseStream<T, ?>>
851 extends TypeSafeMatcher<S> {
852 final List<T> expectedAccumulator = new LinkedList<>();
853 final List<T> actualAccumulator = new LinkedList<>();
854
855 @Override
856 public void describeTo(Description description) {
857 describe(description, expectedAccumulator);
858 }
859
860 @Override
861 protected void describeMismatchSafely(S item, Description description) {
862 describe(description, actualAccumulator);
863 }
864
865 private void describe(Description description, List<T> values) {
866 description.appendText("Stream of ").appendValueList("[", ",", "]",
867 values);
868 }
869
870 boolean remainingItemsEqual(Iterator<T> expectedIterator,
871 Iterator<T> actualIterator) {
872 if (!expectedIterator.hasNext() && !actualIterator.hasNext()) {
873 return true;
874 }
875 if (expectedIterator.hasNext() && actualIterator.hasNext()) {
876 T nextExpected = expectedIterator.next();
877 expectedAccumulator.add(nextExpected);
878 T nextActual = actualIterator.next();
879 actualAccumulator.add(nextActual);
880 if (Objects.equals(nextExpected, nextActual)) {
881 return remainingItemsEqual(expectedIterator,
882 actualIterator);
883 }
884 }
885 expectedIterator.forEachRemaining(expectedAccumulator::add);
886 actualIterator.forEachRemaining(actualAccumulator::add);
887 return false;
888 }
889 }
890
891 private static abstract class BaseMatcherStreamMatcher<T, S extends BaseStream<T, ?>>
892 extends TypeSafeMatcher<S> {
893 final List<Matcher<T>> expectedAccumulator = new LinkedList<>();
894 final List<T> actualAccumulator = new LinkedList<>();
895
896 @Override
897 protected void describeMismatchSafely(S item, Description description) {
898 description.appendText("Stream of ").appendValueList("[", ",", "]",
899 actualAccumulator);
900 }
901
902 @Override
903 public void describeTo(Description description) {
904 description.appendText("Stream of ").appendValueList("[", ",", "]",
905 expectedAccumulator);
906 }
907
908 boolean remainingItemsMatch(Iterator<Matcher<T>> expectedIterator,
909 Iterator<T> actualIterator) {
910 if (!expectedIterator.hasNext() && !actualIterator.hasNext()) {
911 return true;
912 }
913 if (expectedIterator.hasNext() && actualIterator.hasNext()) {
914 Matcher<T> nextExpected = expectedIterator.next();
915 expectedAccumulator.add(nextExpected);
916 T nextActual = actualIterator.next();
917 actualAccumulator.add(nextActual);
918 if (nextExpected.matches(nextActual)) {
919 return remainingItemsMatch(expectedIterator,
920 actualIterator);
921 }
922 }
923 expectedIterator.forEachRemaining(expectedAccumulator::add);
924 actualIterator.forEachRemaining(actualAccumulator::add);
925 return false;
926 }
927 }
928
929 private static void allMatchMismatch(Description mismatchDescription,
930 long position, Object nonMatch) {
931 mismatchDescription.appendText("Item ")
932 .appendText(Long.toString(position))
933 .appendText(" failed to match: ").appendValue(nonMatch);
934 }
935
936 private static abstract class StreamAllMatches<T>
937 extends TypeSafeMatcher<Stream<T>> {
938 private T nonMatching;
939 private long positionNonMatching = -1L;
940 private final Matcher<T> matcher;
941
942 StreamAllMatches(Matcher<T> matcher) {
943 this.matcher = matcher;
944 }
945
946 @Override
947 protected boolean matchesSafely(Stream<T> actual) {
948 return actual
949 .peek(i -> {
950 nonMatching = i;
951 positionNonMatching++;
952 })
953 .allMatch(matcher::matches);
954 }
955
956 @Override
957 protected void describeMismatchSafely(Stream<T> actual,
958 Description mismatchDescription) {
959 allMatchMismatch(mismatchDescription, positionNonMatching,
960 nonMatching);
961 }
962 }
963
964 private static abstract class IntStreamAllMatches
965 extends TypeSafeMatcher<IntStream> {
966 private int nonMatching;
967 private long positionNonMatching = -1L;
968 private final Matcher<Integer> matcher;
969
970 IntStreamAllMatches(Matcher<Integer> matcher) {
971 this.matcher = matcher;
972 }
973
974 @Override
975 protected boolean matchesSafely(IntStream actual) {
976 return actual
977 .peek(i -> {
978 nonMatching = i;
979 positionNonMatching++;
980 })
981 .allMatch(matcher::matches);
982 }
983
984 @Override
985 protected void describeMismatchSafely(IntStream actual,
986 Description mismatchDescription) {
987 allMatchMismatch(mismatchDescription, positionNonMatching,
988 nonMatching);
989 }
990 }
991
992 private static abstract class LongStreamAllMatches
993 extends TypeSafeMatcher<LongStream> {
994 private long nonMatching;
995 private long positionNonMatching = -1L;
996 private final Matcher<Long> matcher;
997
998 LongStreamAllMatches(Matcher<Long> matcher) {
999 this.matcher = matcher;
1000 }
1001
1002 @Override
1003 protected boolean matchesSafely(LongStream actual) {
1004 return actual
1005 .peek(i -> {
1006 nonMatching = i;
1007 positionNonMatching++;
1008 })
1009 .allMatch(matcher::matches);
1010 }
1011
1012 @Override
1013 protected void describeMismatchSafely(LongStream actual,
1014 Description mismatchDescription) {
1015 allMatchMismatch(mismatchDescription, positionNonMatching,
1016 nonMatching);
1017 }
1018 }
1019
1020 private static abstract class DoubleStreamAllMatches
1021 extends TypeSafeMatcher<DoubleStream> {
1022 private double nonMatching;
1023 private long positionNonMatching = -1L;
1024 private final Matcher<Double> matcher;
1025
1026 DoubleStreamAllMatches(Matcher<Double> matcher) {
1027 this.matcher = matcher;
1028 }
1029
1030 @Override
1031 protected boolean matchesSafely(DoubleStream actual) {
1032 return actual
1033 .peek(i -> {
1034 nonMatching = i;
1035 positionNonMatching++;
1036 })
1037 .allMatch(matcher::matches);
1038 }
1039
1040 @Override
1041 protected void describeMismatchSafely(DoubleStream actual,
1042 Description mismatchDescription) {
1043 allMatchMismatch(mismatchDescription, positionNonMatching,
1044 nonMatching);
1045 }
1046 }
1047
1048 private static void anyMatchMismatch(Description mismatchDescription,
1049 List<?> accumulator) {
1050 mismatchDescription
1051 .appendText("None of these items matched: ")
1052 .appendValueList("[", ",", "]", accumulator);
1053 }
1054
1055 private static abstract class StreamAnyMatches<T>
1056 extends TypeSafeMatcher<Stream<T>> {
1057 final List<T> accumulator = new LinkedList<>();
1058 final Matcher<T> matcher;
1059
1060 StreamAnyMatches(Matcher<T> matcher) {
1061 this.matcher = matcher;
1062 }
1063
1064 @Override
1065 protected boolean matchesSafely(Stream<T> actual) {
1066 return actual.peek(accumulator::add).anyMatch(matcher::matches);
1067 }
1068
1069 @Override
1070 protected void describeMismatchSafely(Stream<T> actual,
1071 Description mismatchDescription) {
1072 anyMatchMismatch(mismatchDescription, accumulator);
1073 }
1074 }
1075
1076 private static abstract class LongStreamAnyMatches
1077 extends TypeSafeMatcher<LongStream> {
1078 final List<Long> accumulator = new LinkedList<>();
1079 final Matcher<Long> matcher;
1080
1081 LongStreamAnyMatches(Matcher<Long> matcher) {
1082 this.matcher = matcher;
1083 }
1084
1085 @Override
1086 protected boolean matchesSafely(LongStream actual) {
1087 return actual.peek(accumulator::add).anyMatch(matcher::matches);
1088 }
1089
1090 @Override
1091 protected void describeMismatchSafely(LongStream actual,
1092 Description mismatchDescription) {
1093 anyMatchMismatch(mismatchDescription, accumulator);
1094 }
1095 }
1096
1097 private static abstract class IntStreamAnyMatches
1098 extends TypeSafeMatcher<IntStream> {
1099 final List<Integer> accumulator = new LinkedList<>();
1100 final Matcher<Integer> matcher;
1101
1102 IntStreamAnyMatches(Matcher<Integer> matcher) {
1103 this.matcher = matcher;
1104 }
1105
1106 @Override
1107 protected boolean matchesSafely(IntStream actual) {
1108 return actual.peek(accumulator::add).anyMatch(matcher::matches);
1109 }
1110
1111 @Override
1112 protected void describeMismatchSafely(IntStream actual,
1113 Description mismatchDescription) {
1114 anyMatchMismatch(mismatchDescription, accumulator);
1115 }
1116 }
1117
1118 private static abstract class DoubleStreamAnyMatches
1119 extends TypeSafeMatcher<DoubleStream> {
1120 final List<Double> accumulator = new LinkedList<>();
1121 final Matcher<Double> matcher;
1122
1123 DoubleStreamAnyMatches(Matcher<Double> matcher) {
1124 this.matcher = matcher;
1125 }
1126
1127 @Override
1128 protected boolean matchesSafely(DoubleStream actual) {
1129 return actual.peek(accumulator::add).anyMatch(matcher::matches);
1130 }
1131
1132 @Override
1133 protected void describeMismatchSafely(DoubleStream actual,
1134 Description mismatchDescription) {
1135 anyMatchMismatch(mismatchDescription, accumulator);
1136 }
1137 }
1138
1139 private static class ArrayIterator<T> implements Iterator<T> {
1140 private final T[] expected;
1141 private int currentPos = 0;
1142
1143 @SafeVarargs
1144 public ArrayIterator(T... expected) {
1145 this.expected = expected;
1146 }
1147
1148 @Override
1149 public boolean hasNext() {
1150 return currentPos < expected.length;
1151 }
1152
1153 @Override
1154 public T next() {
1155 return expected[currentPos++];
1156 }
1157 }
1158
1159 private static class IntArrayIterator implements PrimitiveIterator.OfInt {
1160 private final int[] expected;
1161 private int currentPos = 0;
1162
1163 public IntArrayIterator(int... expected) {
1164 this.expected = expected;
1165 }
1166
1167 @Override
1168 public boolean hasNext() {
1169 return currentPos < expected.length;
1170 }
1171
1172 @Override
1173 public int nextInt() {
1174 return expected[currentPos++];
1175 }
1176 }
1177
1178 private static class LongArrayIterator implements PrimitiveIterator.OfLong {
1179 private final long[] expected;
1180 private int currentPos = 0;
1181
1182 public LongArrayIterator(long... expected) {
1183 this.expected = expected;
1184 }
1185
1186 @Override
1187 public boolean hasNext() {
1188 return currentPos < expected.length;
1189 }
1190
1191 @Override
1192 public long nextLong() {
1193 return expected[currentPos++];
1194 }
1195 }
1196
1197 private static class DoubleArrayIterator
1198 implements PrimitiveIterator.OfDouble {
1199 private final double[] expected;
1200 private int currentPos = 0;
1201
1202 public DoubleArrayIterator(double... expected) {
1203 this.expected = expected;
1204 }
1205
1206 @Override
1207 public boolean hasNext() {
1208 return currentPos < expected.length;
1209 }
1210
1211 @Override
1212 public double nextDouble() {
1213 return expected[currentPos++];
1214 }
1215 }
1216 }