// Path: src/test/java/base/BaseTest.java
// public class BaseTest {
//     protected final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
//     protected final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
// 
//     @Before
//     public void setUpStreams() {
//         System.setOut(new PrintStream(outContent));
//         System.setErr(new PrintStream(errContent));
//     }
// 
//     @After
//     public void cleanUpStreams() {
//         System.setOut(null);
//         System.setErr(null);
//     }
// 
// 
//     protected <T> T runWithExpectedException(Callable<T> task) throws InterruptedException, ExecutionException, TimeoutException {
//         ExecutorService service = Executors.newSingleThreadExecutor();
// 
//         Future<T> result = service.submit(task);
// 
//         return result.get(1000, TimeUnit.MILLISECONDS);
//     }
// }
// 
// Path: src/main/java/streams/algebras/ExecStreamAlg.java
// public interface ExecStreamAlg<E, C> extends StreamAlg<C> {
//     <T> App<E, Long> count(App<C, T> app);
// 
//     <T> App<E, T> reduce(T identity, BinaryOperator<T> accumulator, App<C, T> app);
// }
// 
// Path: src/main/java/streams/higher/App.java
// public interface App<C, T> {
// }
// 
// Path: src/main/java/streams/higher/Future.java
// public class Future<T> extends FutureTask<T> implements App<Future.t, T> {
// 
//     public Future(Callable<T> callable) {
//         super(callable);
//     }
// 
//     public static <A> Future<A> prj(App<Future.t, A> app) {
//         return (Future<A>) app;
//     }
// 
//     public static class t {
//     }
// }
// 
// Path: src/main/java/streams/higher/Id.java
// public class Id<T> implements App<Id.t, T> {
// 
//     public final T value;
// 
//     public Id(T value) {
//         this.value = value;
//     }
// 
//     public static <A> Id<A> prj(App<Id.t, A> app) {
//         return (Id<A>) app;
//     }
// 
//     public static <A> App<Id.t, A> inj(Id<A> app) {
//         return (App<Id.t, A>) app;
//     }
// 
//     public static class t {
//     }
// }


import base.BaseTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import streams.algebras.ExecStreamAlg;
import streams.factories.*;
import streams.higher.App;
import streams.higher.Future;
import streams.higher.Id;
import java.util.concurrent.ExecutionException;
import java.util.stream.IntStream;
import static org.junit.Assert.assertEquals;
                        "flatMap : 1 -> 1\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 1\n" +
                        "map: 2 -> 2\n" +
                        "flatMap : 2 -> 2\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 2\n" +
                        "map: 2 -> 4\n" +
                        "flatMap : 3 -> 3\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 3\n" +
                        "map: 2 -> 6\n" +
                        "flatMap : 4 -> 4\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 4\n" +
                        "map: 2 -> 8\n",
                outContent.toString());
        assertEquals(expected, actual);
    }

    @Test
    public void testFlatMapCountPullLog() throws ExecutionException, InterruptedException {
        Long actual = Id.prj(cartCountStream(new LogFactory<>(new ExecPushFactory()))).value;

        Assert.assertEquals(
                "flatMap : 0 -> 0\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 0\n" +
                        "map: 2 -> 0\n" +
                        "flatMap : 1 -> 1\n" +
// Path: src/test/java/base/BaseTest.java
// public class BaseTest {
//     protected final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
//     protected final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
// 
//     @Before
//     public void setUpStreams() {
//         System.setOut(new PrintStream(outContent));
//         System.setErr(new PrintStream(errContent));
//     }
// 
//     @After
//     public void cleanUpStreams() {
//         System.setOut(null);
//         System.setErr(null);
//     }
// 
// 
//     protected <T> T runWithExpectedException(Callable<T> task) throws InterruptedException, ExecutionException, TimeoutException {
//         ExecutorService service = Executors.newSingleThreadExecutor();
// 
//         Future<T> result = service.submit(task);
// 
//         return result.get(1000, TimeUnit.MILLISECONDS);
//     }
// }
// 
// Path: src/main/java/streams/algebras/ExecStreamAlg.java
// public interface ExecStreamAlg<E, C> extends StreamAlg<C> {
//     <T> App<E, Long> count(App<C, T> app);
// 
//     <T> App<E, T> reduce(T identity, BinaryOperator<T> accumulator, App<C, T> app);
// }
// 
// Path: src/main/java/streams/higher/App.java
// public interface App<C, T> {
// }
// 
// Path: src/main/java/streams/higher/Future.java
// public class Future<T> extends FutureTask<T> implements App<Future.t, T> {
// 
//     public Future(Callable<T> callable) {
//         super(callable);
//     }
// 
//     public static <A> Future<A> prj(App<Future.t, A> app) {
//         return (Future<A>) app;
//     }
// 
//     public static class t {
//     }
// }
// 
// Path: src/main/java/streams/higher/Id.java
// public class Id<T> implements App<Id.t, T> {
// 
//     public final T value;
// 
//     public Id(T value) {
//         this.value = value;
//     }
// 
//     public static <A> Id<A> prj(App<Id.t, A> app) {
//         return (Id<A>) app;
//     }
// 
//     public static <A> App<Id.t, A> inj(Id<A> app) {
//         return (App<Id.t, A>) app;
//     }
// 
//     public static class t {
//     }
// }


// Path: src/test/java/algebras/TestAlgebrasOnOneQuery.java
import base.BaseTest;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import streams.algebras.ExecStreamAlg;
import streams.factories.*;
import streams.higher.App;
import streams.higher.Future;
import streams.higher.Id;
import java.util.concurrent.ExecutionException;
import java.util.stream.IntStream;
import static org.junit.Assert.assertEquals;

                        "flatMap : 1 -> 1\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 1\n" +
                        "map: 2 -> 2\n" +
                        "flatMap : 2 -> 2\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 2\n" +
                        "map: 2 -> 4\n" +
                        "flatMap : 3 -> 3\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 3\n" +
                        "map: 2 -> 6\n" +
                        "flatMap : 4 -> 4\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 4\n" +
                        "map: 2 -> 8\n",
                outContent.toString());
        assertEquals(expected, actual);
    }

    @Test
    public void testFlatMapCountPullLog() throws ExecutionException, InterruptedException {
        Long actual = Id.prj(cartCountStream(new LogFactory<>(new ExecPushFactory()))).value;

        Assert.assertEquals(
                "flatMap : 0 -> 0\n" +
                        "map: 0 -> 0\n" +
                        "map: 1 -> 0\n" +
                        "map: 2 -> 0\n" +
                        "flatMap : 1 -> 1\n" +
                        "map: 0 -> 0\n" +