• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 
15 package com.google.common.collect;
16 
17 import static com.google.common.collect.Streams.findLast;
18 import static com.google.common.collect.Streams.stream;
19 
20 import com.google.common.annotations.GwtCompatible;
21 import com.google.common.annotations.GwtIncompatible;
22 import com.google.common.collect.testing.SpliteratorTester;
23 import com.google.common.primitives.Doubles;
24 import com.google.common.truth.IterableSubject;
25 import com.google.common.truth.Truth;
26 import com.google.common.truth.Truth8;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.LinkedHashSet;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.OptionalDouble;
34 import java.util.OptionalInt;
35 import java.util.OptionalLong;
36 import java.util.concurrent.atomic.AtomicInteger;
37 import java.util.function.Function;
38 import java.util.stream.Collectors;
39 import java.util.stream.DoubleStream;
40 import java.util.stream.IntStream;
41 import java.util.stream.LongStream;
42 import java.util.stream.Stream;
43 import junit.framework.TestCase;
44 
45 /** Unit test for {@link Streams}. */
46 @GwtCompatible(emulated = true)
47 public class StreamsTest extends TestCase {
48   /*
49    * Full and proper black-box testing of a Stream-returning method is extremely involved, and is
50    * overkill when nearly all Streams are produced using well-tested JDK calls. So, we cheat and
51    * just test that the toArray() contents are as expected.
52    */
testStream_nonCollection()53   public void testStream_nonCollection() {
54     assertThat(stream(FluentIterable.of())).isEmpty();
55     assertThat(stream(FluentIterable.of("a"))).containsExactly("a");
56     assertThat(stream(FluentIterable.of(1, 2, 3)).filter(n -> n > 1)).containsExactly(2, 3);
57   }
58 
59   @SuppressWarnings("deprecation")
testStream_collection()60   public void testStream_collection() {
61     assertThat(stream(Arrays.asList())).isEmpty();
62     assertThat(stream(Arrays.asList("a"))).containsExactly("a");
63     assertThat(stream(Arrays.asList(1, 2, 3)).filter(n -> n > 1)).containsExactly(2, 3);
64   }
65 
testStream_iterator()66   public void testStream_iterator() {
67     assertThat(stream(Arrays.asList().iterator())).isEmpty();
68     assertThat(stream(Arrays.asList("a").iterator())).containsExactly("a");
69     assertThat(stream(Arrays.asList(1, 2, 3).iterator()).filter(n -> n > 1)).containsExactly(2, 3);
70   }
71 
testStream_googleOptional()72   public void testStream_googleOptional() {
73     assertThat(stream(com.google.common.base.Optional.absent())).isEmpty();
74     assertThat(stream(com.google.common.base.Optional.of("a"))).containsExactly("a");
75   }
76 
testStream_javaOptional()77   public void testStream_javaOptional() {
78     assertThat(stream(java.util.Optional.empty())).isEmpty();
79     assertThat(stream(java.util.Optional.of("a"))).containsExactly("a");
80   }
81 
testFindLast_refStream()82   public void testFindLast_refStream() {
83     Truth8.assertThat(findLast(Stream.of())).isEmpty();
84     Truth8.assertThat(findLast(Stream.of("a", "b", "c", "d"))).hasValue("d");
85 
86     // test with a large, not-subsized Spliterator
87     List<Integer> list =
88         IntStream.rangeClosed(0, 10000).boxed().collect(Collectors.toCollection(LinkedList::new));
89     Truth8.assertThat(findLast(list.stream())).hasValue(10000);
90 
91     // no way to find out the stream is empty without walking its spliterator
92     Truth8.assertThat(findLast(list.stream().filter(i -> i < 0))).isEmpty();
93   }
94 
testFindLast_intStream()95   public void testFindLast_intStream() {
96     Truth.assertThat(findLast(IntStream.of())).isEqualTo(OptionalInt.empty());
97     Truth.assertThat(findLast(IntStream.of(1, 2, 3, 4, 5))).isEqualTo(OptionalInt.of(5));
98 
99     // test with a large, not-subsized Spliterator
100     List<Integer> list =
101         IntStream.rangeClosed(0, 10000).boxed().collect(Collectors.toCollection(LinkedList::new));
102     Truth.assertThat(findLast(list.stream().mapToInt(i -> i))).isEqualTo(OptionalInt.of(10000));
103 
104     // no way to find out the stream is empty without walking its spliterator
105     Truth.assertThat(findLast(list.stream().mapToInt(i -> i).filter(i -> i < 0)))
106         .isEqualTo(OptionalInt.empty());
107   }
108 
testFindLast_longStream()109   public void testFindLast_longStream() {
110     Truth.assertThat(findLast(LongStream.of())).isEqualTo(OptionalLong.empty());
111     Truth.assertThat(findLast(LongStream.of(1, 2, 3, 4, 5))).isEqualTo(OptionalLong.of(5));
112 
113     // test with a large, not-subsized Spliterator
114     List<Long> list =
115         LongStream.rangeClosed(0, 10000).boxed().collect(Collectors.toCollection(LinkedList::new));
116     Truth.assertThat(findLast(list.stream().mapToLong(i -> i))).isEqualTo(OptionalLong.of(10000));
117 
118     // no way to find out the stream is empty without walking its spliterator
119     Truth.assertThat(findLast(list.stream().mapToLong(i -> i).filter(i -> i < 0)))
120         .isEqualTo(OptionalLong.empty());
121   }
122 
testFindLast_doubleStream()123   public void testFindLast_doubleStream() {
124     Truth.assertThat(findLast(DoubleStream.of())).isEqualTo(OptionalDouble.empty());
125     Truth.assertThat(findLast(DoubleStream.of(1, 2, 3, 4, 5))).isEqualTo(OptionalDouble.of(5));
126 
127     // test with a large, not-subsized Spliterator
128     List<Long> list =
129         LongStream.rangeClosed(0, 10000).boxed().collect(Collectors.toCollection(LinkedList::new));
130     Truth.assertThat(findLast(list.stream().mapToDouble(i -> i)))
131         .isEqualTo(OptionalDouble.of(10000));
132 
133     // no way to find out the stream is empty without walking its spliterator
134     Truth.assertThat(findLast(list.stream().mapToDouble(i -> i).filter(i -> i < 0)))
135         .isEqualTo(OptionalDouble.empty());
136   }
137 
testConcat_refStream()138   public void testConcat_refStream() {
139     assertThat(Streams.concat(Stream.of("a"), Stream.of("b"), Stream.empty(), Stream.of("c", "d")))
140         .containsExactly("a", "b", "c", "d")
141         .inOrder();
142     SpliteratorTester.of(
143             () ->
144                 Streams.concat(Stream.of("a"), Stream.of("b"), Stream.empty(), Stream.of("c", "d"))
145                     .spliterator())
146         .expect("a", "b", "c", "d");
147   }
148 
testConcat_refStream_closeIsPropagated()149   public void testConcat_refStream_closeIsPropagated() {
150     AtomicInteger closeCountB = new AtomicInteger(0);
151     Stream<String> streamB = Stream.of("b").onClose(closeCountB::incrementAndGet);
152     Stream<String> concatenated =
153         Streams.concat(Stream.of("a"), streamB, Stream.empty(), Stream.of("c", "d"));
154     assertThat(concatenated).containsExactly("a", "b", "c", "d").inOrder();
155     concatenated.close();
156     Truth.assertThat(closeCountB.get()).isEqualTo(1);
157   }
158 
testConcat_refStream_closeIsPropagated_Stream_concat()159   public void testConcat_refStream_closeIsPropagated_Stream_concat() {
160     // Just to demonstrate behavior of Stream::concat in the standard library
161     AtomicInteger closeCountB = new AtomicInteger(0);
162     Stream<String> streamB = Stream.of("b").onClose(closeCountB::incrementAndGet);
163     Stream<String> concatenated =
164         Stream.<Stream<String>>of(Stream.of("a"), streamB, Stream.empty(), Stream.of("c", "d"))
165             .reduce(Stream.empty(), Stream::concat);
166     assertThat(concatenated).containsExactly("a", "b", "c", "d").inOrder();
167     concatenated.close();
168     Truth.assertThat(closeCountB.get()).isEqualTo(1);
169   }
170 
testConcat_refStream_closeIsPropagated_Stream_flatMap()171   public void testConcat_refStream_closeIsPropagated_Stream_flatMap() {
172     // Just to demonstrate behavior of Stream::flatMap in the standard library
173     AtomicInteger closeCountB = new AtomicInteger(0);
174     Stream<String> streamB = Stream.of("b").onClose(closeCountB::incrementAndGet);
175     Stream<String> concatenated =
176         Stream.<Stream<String>>of(Stream.of("a"), streamB, Stream.empty(), Stream.of("c", "d"))
177             .flatMap(x -> x);
178     assertThat(concatenated).containsExactly("a", "b", "c", "d").inOrder();
179     concatenated.close();
180     // even without close, see doc for flatMap
181     Truth.assertThat(closeCountB.get()).isEqualTo(1);
182   }
183 
testConcat_refStream_closeIsPropagated_exceptionsChained()184   public void testConcat_refStream_closeIsPropagated_exceptionsChained() {
185     RuntimeException exception1 = new IllegalArgumentException("exception from stream 1");
186     RuntimeException exception2 = new IllegalStateException("exception from stream 2");
187     RuntimeException exception3 = new ArithmeticException("exception from stream 3");
188     Stream<String> stream1 = Stream.of("foo", "bar").onClose(doThrow(exception1));
189     Stream<String> stream2 = Stream.of("baz", "buh").onClose(doThrow(exception2));
190     Stream<String> stream3 = Stream.of("quux").onClose(doThrow(exception3));
191     RuntimeException exception = null;
192     try (Stream<String> concatenated = Streams.concat(stream1, stream2, stream3)) {
193     } catch (RuntimeException e) {
194       exception = e;
195     }
196     Truth.assertThat(exception).isEqualTo(exception1);
197     Truth.assertThat(exception.getSuppressed())
198         .asList()
199         .containsExactly(exception2, exception3)
200         .inOrder();
201   }
202 
doThrow(RuntimeException exception)203   private static Runnable doThrow(RuntimeException exception) {
204     return () -> {
205       throw exception;
206     };
207   }
208 
testConcat_refStream_parallel()209   public void testConcat_refStream_parallel() {
210     Truth.assertThat(
211             Streams.concat(Stream.of("a"), Stream.of("b"), Stream.empty(), Stream.of("c", "d"))
212                 .parallel()
213                 .toArray())
214         .asList()
215         .containsExactly("a", "b", "c", "d")
216         .inOrder();
217   }
218 
testConcat_intStream()219   public void testConcat_intStream() {
220     assertThat(
221             Streams.concat(IntStream.of(1), IntStream.of(2), IntStream.empty(), IntStream.of(3, 4)))
222         .containsExactly(1, 2, 3, 4)
223         .inOrder();
224   }
225 
testConcat_longStream()226   public void testConcat_longStream() {
227     assertThat(
228             Streams.concat(
229                 LongStream.of(1), LongStream.of(2), LongStream.empty(), LongStream.of(3, 4)))
230         .containsExactly(1L, 2L, 3L, 4L)
231         .inOrder();
232   }
233 
testConcat_doubleStream()234   public void testConcat_doubleStream() {
235     assertThat(
236             Streams.concat(
237                 DoubleStream.of(1),
238                 DoubleStream.of(2),
239                 DoubleStream.empty(),
240                 DoubleStream.of(3, 4)))
241         .containsExactly(1.0, 2.0, 3.0, 4.0)
242         .inOrder();
243   }
244 
testStream_optionalInt()245   public void testStream_optionalInt() {
246     assertThat(stream(OptionalInt.empty())).isEmpty();
247     assertThat(stream(OptionalInt.of(5))).containsExactly(5);
248   }
249 
testStream_optionalLong()250   public void testStream_optionalLong() {
251     assertThat(stream(OptionalLong.empty())).isEmpty();
252     assertThat(stream(OptionalLong.of(5L))).containsExactly(5L);
253   }
254 
testStream_optionalDouble()255   public void testStream_optionalDouble() {
256     assertThat(stream(OptionalDouble.empty())).isEmpty();
257     assertThat(stream(OptionalDouble.of(5.0))).containsExactly(5.0);
258   }
259 
testConcatInfiniteStream()260   public void testConcatInfiniteStream() {
261     assertThat(Streams.concat(Stream.of(1, 2, 3), Stream.generate(() -> 5)).limit(5))
262         .containsExactly(1, 2, 3, 5, 5)
263         .inOrder();
264   }
265 
testConcatInfiniteStream_int()266   public void testConcatInfiniteStream_int() {
267     assertThat(Streams.concat(IntStream.of(1, 2, 3), IntStream.generate(() -> 5)).limit(5))
268         .containsExactly(1, 2, 3, 5, 5)
269         .inOrder();
270   }
271 
testConcatInfiniteStream_long()272   public void testConcatInfiniteStream_long() {
273     assertThat(Streams.concat(LongStream.of(1, 2, 3), LongStream.generate(() -> 5)).limit(5))
274         .containsExactly(1L, 2L, 3L, 5L, 5L)
275         .inOrder();
276   }
277 
testConcatInfiniteStream_double()278   public void testConcatInfiniteStream_double() {
279     assertThat(Streams.concat(DoubleStream.of(1, 2, 3), DoubleStream.generate(() -> 5)).limit(5))
280         .containsExactly(1., 2., 3., 5., 5.)
281         .inOrder();
282   }
283 
testMapWithIndex(Function<Collection<String>, Stream<String>> collectionImpl)284   private void testMapWithIndex(Function<Collection<String>, Stream<String>> collectionImpl) {
285     SpliteratorTester.of(
286             () ->
287                 Streams.mapWithIndex(
288                         collectionImpl.apply(ImmutableList.of()), (str, i) -> str + ":" + i)
289                     .spliterator())
290         .expect(ImmutableList.of());
291     SpliteratorTester.of(
292             () ->
293                 Streams.mapWithIndex(
294                         collectionImpl.apply(ImmutableList.of("a", "b", "c", "d", "e")),
295                         (str, i) -> str + ":" + i)
296                     .spliterator())
297         .expect("a:0", "b:1", "c:2", "d:3", "e:4");
298   }
299 
testMapWithIndex_arrayListSource()300   public void testMapWithIndex_arrayListSource() {
301     testMapWithIndex(elems -> new ArrayList<>(elems).stream());
302   }
303 
testMapWithIndex_linkedHashSetSource()304   public void testMapWithIndex_linkedHashSetSource() {
305     testMapWithIndex(elems -> new LinkedHashSet<>(elems).stream());
306   }
307 
testMapWithIndex_unsizedSource()308   public void testMapWithIndex_unsizedSource() {
309     testMapWithIndex(
310         elems -> Stream.of((Object) null).flatMap(unused -> ImmutableList.copyOf(elems).stream()));
311   }
312 
testMapWithIndex_closeIsPropagated_sizedSource()313   public void testMapWithIndex_closeIsPropagated_sizedSource() {
314     testMapWithIndex_closeIsPropagated(Stream.of("a", "b", "c"));
315   }
316 
testMapWithIndex_closeIsPropagated_unsizedSource()317   public void testMapWithIndex_closeIsPropagated_unsizedSource() {
318     testMapWithIndex_closeIsPropagated(
319         Stream.of((Object) null).flatMap(unused -> Stream.of("a", "b", "c")));
320   }
321 
testMapWithIndex_closeIsPropagated(Stream<String> source)322   private void testMapWithIndex_closeIsPropagated(Stream<String> source) {
323     AtomicInteger stringsCloseCount = new AtomicInteger();
324     Stream<String> strings = source.onClose(stringsCloseCount::incrementAndGet);
325     Stream<String> withIndex = Streams.mapWithIndex(strings, (str, i) -> str + ":" + i);
326 
327     withIndex.close();
328 
329     Truth.assertThat(stringsCloseCount.get()).isEqualTo(1);
330   }
331 
testMapWithIndex_intStream()332   public void testMapWithIndex_intStream() {
333     SpliteratorTester.of(
334             () -> Streams.mapWithIndex(IntStream.of(0, 1, 2), (x, i) -> x + ":" + i).spliterator())
335         .expect("0:0", "1:1", "2:2");
336   }
337 
testMapWithIndex_intStream_closeIsPropagated_sized()338   public void testMapWithIndex_intStream_closeIsPropagated_sized() {
339     testMapWithIndex_intStream_closeIsPropagated(IntStream.of(1, 2, 3));
340   }
341 
testMapWithIndex_intStream_closeIsPropagated_unsized()342   public void testMapWithIndex_intStream_closeIsPropagated_unsized() {
343     testMapWithIndex_intStream_closeIsPropagated(
344         IntStream.of(0).flatMap(unused -> IntStream.of(1, 2, 3)));
345   }
346 
testMapWithIndex_intStream_closeIsPropagated(IntStream source)347   private void testMapWithIndex_intStream_closeIsPropagated(IntStream source) {
348     AtomicInteger intStreamCloseCount = new AtomicInteger();
349     IntStream intStream = source.onClose(intStreamCloseCount::incrementAndGet);
350     Stream<String> withIndex = Streams.mapWithIndex(intStream, (str, i) -> str + ":" + i);
351 
352     withIndex.close();
353 
354     Truth.assertThat(intStreamCloseCount.get()).isEqualTo(1);
355   }
356 
testMapWithIndex_longStream()357   public void testMapWithIndex_longStream() {
358     SpliteratorTester.of(
359             () -> Streams.mapWithIndex(LongStream.of(0, 1, 2), (x, i) -> x + ":" + i).spliterator())
360         .expect("0:0", "1:1", "2:2");
361   }
362 
testMapWithIndex_longStream_closeIsPropagated_sized()363   public void testMapWithIndex_longStream_closeIsPropagated_sized() {
364     testMapWithIndex_longStream_closeIsPropagated(LongStream.of(1, 2, 3));
365   }
366 
testMapWithIndex_longStream_closeIsPropagated_unsized()367   public void testMapWithIndex_longStream_closeIsPropagated_unsized() {
368     testMapWithIndex_longStream_closeIsPropagated(
369         LongStream.of(0).flatMap(unused -> LongStream.of(1, 2, 3)));
370   }
371 
testMapWithIndex_longStream_closeIsPropagated(LongStream source)372   private void testMapWithIndex_longStream_closeIsPropagated(LongStream source) {
373     AtomicInteger longStreamCloseCount = new AtomicInteger();
374     LongStream longStream = source.onClose(longStreamCloseCount::incrementAndGet);
375     Stream<String> withIndex = Streams.mapWithIndex(longStream, (str, i) -> str + ":" + i);
376 
377     withIndex.close();
378 
379     Truth.assertThat(longStreamCloseCount.get()).isEqualTo(1);
380   }
381 
382   @GwtIncompatible // TODO(b/38490623): reenable after GWT double-to-string conversion is fixed
testMapWithIndex_doubleStream()383   public void testMapWithIndex_doubleStream() {
384     SpliteratorTester.of(
385             () ->
386                 Streams.mapWithIndex(DoubleStream.of(0, 1, 2), (x, i) -> x + ":" + i).spliterator())
387         .expect("0.0:0", "1.0:1", "2.0:2");
388   }
389 
testMapWithIndex_doubleStream_closeIsPropagated_sized()390   public void testMapWithIndex_doubleStream_closeIsPropagated_sized() {
391     testMapWithIndex_doubleStream_closeIsPropagated(DoubleStream.of(1, 2, 3));
392   }
393 
testMapWithIndex_doubleStream_closeIsPropagated_unsized()394   public void testMapWithIndex_doubleStream_closeIsPropagated_unsized() {
395     testMapWithIndex_doubleStream_closeIsPropagated(
396         DoubleStream.of(0).flatMap(unused -> DoubleStream.of(1, 2, 3)));
397   }
398 
testMapWithIndex_doubleStream_closeIsPropagated(DoubleStream source)399   private void testMapWithIndex_doubleStream_closeIsPropagated(DoubleStream source) {
400     AtomicInteger doubleStreamCloseCount = new AtomicInteger();
401     DoubleStream doubleStream = source.onClose(doubleStreamCloseCount::incrementAndGet);
402     Stream<String> withIndex = Streams.mapWithIndex(doubleStream, (str, i) -> str + ":" + i);
403 
404     withIndex.close();
405 
406     Truth.assertThat(doubleStreamCloseCount.get()).isEqualTo(1);
407   }
408 
testZip()409   public void testZip() {
410     assertThat(Streams.zip(Stream.of("a", "b", "c"), Stream.of(1, 2, 3), (a, b) -> a + ":" + b))
411         .containsExactly("a:1", "b:2", "c:3")
412         .inOrder();
413   }
414 
testZip_closeIsPropagated()415   public void testZip_closeIsPropagated() {
416     AtomicInteger lettersCloseCount = new AtomicInteger();
417     Stream<String> letters = Stream.of("a", "b", "c").onClose(lettersCloseCount::incrementAndGet);
418     AtomicInteger numbersCloseCount = new AtomicInteger();
419     Stream<Integer> numbers = Stream.of(1, 2, 3).onClose(numbersCloseCount::incrementAndGet);
420 
421     Stream<String> zipped = Streams.zip(letters, numbers, (a, b) -> a + ":" + b);
422 
423     zipped.close();
424 
425     Truth.assertThat(lettersCloseCount.get()).isEqualTo(1);
426     Truth.assertThat(numbersCloseCount.get()).isEqualTo(1);
427   }
428 
testZipFiniteWithInfinite()429   public void testZipFiniteWithInfinite() {
430     assertThat(
431             Streams.zip(
432                 Stream.of("a", "b", "c"), Stream.iterate(1, i -> i + 1), (a, b) -> a + ":" + b))
433         .containsExactly("a:1", "b:2", "c:3")
434         .inOrder();
435   }
436 
testZipInfiniteWithInfinite()437   public void testZipInfiniteWithInfinite() {
438     // zip is doing an infinite zip, but we truncate the result so we can actually test it
439     // but we want the zip itself to work
440     assertThat(
441             Streams.zip(
442                     Stream.iterate(1, i -> i + 1).map(String::valueOf),
443                     Stream.iterate(1, i -> i + 1),
444                     (String str, Integer i) -> str.equals(Integer.toString(i)))
445                 .limit(100))
446         .doesNotContain(false);
447   }
448 
testZipDifferingLengths()449   public void testZipDifferingLengths() {
450     assertThat(
451             Streams.zip(Stream.of("a", "b", "c", "d"), Stream.of(1, 2, 3), (a, b) -> a + ":" + b))
452         .containsExactly("a:1", "b:2", "c:3")
453         .inOrder();
454     assertThat(Streams.zip(Stream.of("a", "b", "c"), Stream.of(1, 2, 3, 4), (a, b) -> a + ":" + b))
455         .containsExactly("a:1", "b:2", "c:3")
456         .inOrder();
457   }
458 
testForEachPair()459   public void testForEachPair() {
460     List<String> list = new ArrayList<>();
461     Streams.forEachPair(
462         Stream.of("a", "b", "c"), Stream.of(1, 2, 3), (a, b) -> list.add(a + ":" + b));
463     Truth.assertThat(list).containsExactly("a:1", "b:2", "c:3");
464   }
465 
testForEachPair_differingLengths1()466   public void testForEachPair_differingLengths1() {
467     List<String> list = new ArrayList<>();
468     Streams.forEachPair(
469         Stream.of("a", "b", "c", "d"), Stream.of(1, 2, 3), (a, b) -> list.add(a + ":" + b));
470     Truth.assertThat(list).containsExactly("a:1", "b:2", "c:3");
471   }
472 
testForEachPair_differingLengths2()473   public void testForEachPair_differingLengths2() {
474     List<String> list = new ArrayList<>();
475     Streams.forEachPair(
476         Stream.of("a", "b", "c"), Stream.of(1, 2, 3, 4), (a, b) -> list.add(a + ":" + b));
477     Truth.assertThat(list).containsExactly("a:1", "b:2", "c:3");
478   }
479 
testForEachPair_oneEmpty()480   public void testForEachPair_oneEmpty() {
481     Streams.forEachPair(Stream.of("a"), Stream.empty(), (a, b) -> fail());
482   }
483 
testForEachPair_finiteWithInfinite()484   public void testForEachPair_finiteWithInfinite() {
485     List<String> list = new ArrayList<>();
486     Streams.forEachPair(
487         Stream.of("a", "b", "c"), Stream.iterate(1, i -> i + 1), (a, b) -> list.add(a + ":" + b));
488     Truth.assertThat(list).containsExactly("a:1", "b:2", "c:3");
489   }
490 
testForEachPair_parallel()491   public void testForEachPair_parallel() {
492     Stream<String> streamA = IntStream.range(0, 100000).mapToObj(String::valueOf).parallel();
493     Stream<Integer> streamB = IntStream.range(0, 100000).mapToObj(i -> i).parallel();
494 
495     AtomicInteger count = new AtomicInteger(0);
496     Streams.forEachPair(
497         streamA,
498         streamB,
499         (a, b) -> {
500           count.incrementAndGet();
501           Truth.assertThat(a.equals(String.valueOf(b))).isTrue();
502         });
503     Truth.assertThat(count.get()).isEqualTo(100000);
504     // of course, this test doesn't prove that anything actually happened in parallel...
505   }
506 
507   // TODO(kevinb): switch to importing Truth's assertThat(Stream) if we get that added
assertThat(Stream<?> stream)508   private static IterableSubject assertThat(Stream<?> stream) {
509     return Truth.assertThat(stream.toArray()).asList();
510   }
511 
assertThat(IntStream stream)512   private static IterableSubject assertThat(IntStream stream) {
513     return Truth.assertThat(stream.toArray()).asList();
514   }
515 
assertThat(LongStream stream)516   private static IterableSubject assertThat(LongStream stream) {
517     return Truth.assertThat(stream.toArray()).asList();
518   }
519 
assertThat(DoubleStream stream)520   private static IterableSubject assertThat(DoubleStream stream) {
521     return Truth.assertThat(Doubles.asList(stream.toArray()));
522   }
523 }
524