// Path: mug/src/main/java/com/google/mu/util/stream/MoreStreams.java
// public static <T, R> Stream<R> groupConsecutive(
//     Stream<T> stream,
//     BiPredicate<? super T, ? super T> sameGroup,
//     Collector<? super T, ?, R> groupCollector) {
//   return biStream(stream).groupConsecutiveIf(sameGroup, groupCollector);
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/MoreStreams.java
// public static Stream<Integer> indexesFrom(int firstIndex) {
//   return IntStream.iterate(firstIndex, i -> i + 1).boxed();
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/MoreStreams.java
// public static <T> Stream<T> whileNotNull(Supplier<? extends T> supplier) {
//   requireNonNull(supplier);
//   return StreamSupport.stream(
//       new Spliterator<T>() {
//         @Override public boolean tryAdvance(Consumer<? super T> action) {
//           T generated = supplier.get();
//           if (generated == null) {
//             return false;
//           }
//           action.accept(generated);
//           return true;
//         }
//         @Override public int characteristics() {
//           return Spliterator.NONNULL | Spliterator.ORDERED;
//         }
//         @Override public long estimateSize() {
//           return Long.MAX_VALUE;
//         }
//         @Override public Spliterator<T> trySplit() {
//           return null;
//         }
//       },
//       false);
// }


import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.mu.util.stream.MoreStreams.groupConsecutive;
import static com.google.mu.util.stream.MoreStreams.indexesFrom;
import static com.google.mu.util.stream.MoreStreams.whileNotNull;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.junit.Assume.assumeTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.Spliterator;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.testing.ClassSanityTester;
import com.google.common.testing.NullPointerTester;

    // now add to source
    source.add(1);

    // Change is reflected
    assertThat(stream).containsExactly(1);
    assertThat(list).containsExactly(1).inOrder();;
  }

  @Test public void withSideEffect_parallel() {
    ImmutableList<Integer> source = indexesFrom(1).limit(100).collect(toImmutableList());
    Set<Integer> set = ConcurrentHashMap.newKeySet();
    Stream<Integer> stream = MoreStreams.withSideEffect(source.stream(), set::add);
    assertThat(stream.isParallel()).isFalse();
    assertThat(set).isEmpty();
    assertThat(stream.parallel()).containsExactlyElementsIn(source);
    assertThat(set).containsExactlyElementsIn(source);
  }

  @Test public void testNulls() throws Exception {
    NullPointerTester tester = new NullPointerTester();
    asList(MoreStreams.class.getDeclaredMethods()).stream()
        .filter(m -> m.getName().equals("generate"))
        .forEach(tester::ignore);
    tester.testAllPublicStaticMethods(MoreStreams.class);
    new ClassSanityTester().forAllPublicStaticMethods(MoreStreams.class).testNulls();
  }

  @Test public void withSideEffectInOrder() {
    int num = 10000;
// Path: mug/src/main/java/com/google/mu/util/stream/MoreStreams.java
// public static <T, R> Stream<R> groupConsecutive(
//     Stream<T> stream,
//     BiPredicate<? super T, ? super T> sameGroup,
//     Collector<? super T, ?, R> groupCollector) {
//   return biStream(stream).groupConsecutiveIf(sameGroup, groupCollector);
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/MoreStreams.java
// public static Stream<Integer> indexesFrom(int firstIndex) {
//   return IntStream.iterate(firstIndex, i -> i + 1).boxed();
// }
// 
// Path: mug/src/main/java/com/google/mu/util/stream/MoreStreams.java
// public static <T> Stream<T> whileNotNull(Supplier<? extends T> supplier) {
//   requireNonNull(supplier);
//   return StreamSupport.stream(
//       new Spliterator<T>() {
//         @Override public boolean tryAdvance(Consumer<? super T> action) {
//           T generated = supplier.get();
//           if (generated == null) {
//             return false;
//           }
//           action.accept(generated);
//           return true;
//         }
//         @Override public int characteristics() {
//           return Spliterator.NONNULL | Spliterator.ORDERED;
//         }
//         @Override public long estimateSize() {
//           return Long.MAX_VALUE;
//         }
//         @Override public Spliterator<T> trySplit() {
//           return null;
//         }
//       },
//       false);
// }


// Path: mug/src/test/java/com/google/mu/util/stream/MoreStreamsTest.java
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.mu.util.stream.MoreStreams.groupConsecutive;
import static com.google.mu.util.stream.MoreStreams.indexesFrom;
import static com.google.mu.util.stream.MoreStreams.whileNotNull;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.junit.Assume.assumeTrue;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.Spliterator;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.testing.ClassSanityTester;
import com.google.common.testing.NullPointerTester;


    // now add to source
    source.add(1);

    // Change is reflected
    assertThat(stream).containsExactly(1);
    assertThat(list).containsExactly(1).inOrder();;
  }

  @Test public void withSideEffect_parallel() {
    ImmutableList<Integer> source = indexesFrom(1).limit(100).collect(toImmutableList());
    Set<Integer> set = ConcurrentHashMap.newKeySet();
    Stream<Integer> stream = MoreStreams.withSideEffect(source.stream(), set::add);
    assertThat(stream.isParallel()).isFalse();
    assertThat(set).isEmpty();
    assertThat(stream.parallel()).containsExactlyElementsIn(source);
    assertThat(set).containsExactlyElementsIn(source);
  }

  @Test public void testNulls() throws Exception {
    NullPointerTester tester = new NullPointerTester();
    asList(MoreStreams.class.getDeclaredMethods()).stream()
        .filter(m -> m.getName().equals("generate"))
        .forEach(tester::ignore);
    tester.testAllPublicStaticMethods(MoreStreams.class);
    new ClassSanityTester().forAllPublicStaticMethods(MoreStreams.class).testNulls();
  }

  @Test public void withSideEffectInOrder() {
    int num = 10000;
    ImmutableList<Integer> source =  indexesFrom(1).limit(num).collect(toImmutableList());