/* * Copyright (C) 2015-2020 Lightbend Inc. */ package jdocs.stream; import java.time.Duration; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import akka.NotUsed; import jdocs.AbstractJavaTest; import akka.testkit.javadsl.TestKit; import org.junit.*; import static org.junit.Assert.assertEquals; import akka.actor.*; import akka.japi.Pair; import akka.stream.*; import akka.stream.javadsl.*; import akka.stream.testkit.*; import akka.stream.testkit.javadsl.*; public class StreamTestKitDocTest extends AbstractJavaTest { static ActorSystem system; @BeforeClass public static void setup() { system = ActorSystem.create("StreamTestKitDocTest"); } @AfterClass public static void tearDown() { TestKit.shutdownActorSystem(system); system = null; } @Test public void strictCollection() throws Exception { // #strict-collection final Sink> sinkUnderTest = Flow.of(Integer.class) .map(i -> i * 2) .toMat(Sink.fold(0, (agg, next) -> agg + next), Keep.right()); final CompletionStage future = Source.from(Arrays.asList(1, 2, 3, 4)).runWith(sinkUnderTest, system); final Integer result = future.toCompletableFuture().get(3, TimeUnit.SECONDS); assert (result == 20); // #strict-collection } @Test public void groupedPartOfInfiniteStream() throws Exception { // #grouped-infinite final Source sourceUnderTest = Source.repeat(1).map(i -> i * 2); final CompletionStage> future = sourceUnderTest.take(10).runWith(Sink.seq(), system); final List result = future.toCompletableFuture().get(3, TimeUnit.SECONDS); assertEquals(result, Collections.nCopies(10, 2)); // #grouped-infinite } @Test public void foldedStream() throws Exception { // #folded-stream final Flow flowUnderTest = Flow.of(Integer.class).takeWhile(i -> i < 5); final CompletionStage future = Source.from(Arrays.asList(1, 2, 3, 4, 5, 6)) .via(flowUnderTest) .runWith(Sink.fold(0, (agg, next) -> agg + next), system); final Integer result = future.toCompletableFuture().get(3, TimeUnit.SECONDS); assert (result == 10); // #folded-stream } @Test public void pipeToTestProbe() throws Exception { // #pipeto-testprobe final Source, NotUsed> sourceUnderTest = Source.from(Arrays.asList(1, 2, 3, 4)).grouped(2); final TestKit probe = new TestKit(system); final CompletionStage>> future = sourceUnderTest.grouped(2).runWith(Sink.head(), system); akka.pattern.Patterns.pipe(future, system.dispatcher()).to(probe.getRef()); probe.expectMsg(Duration.ofSeconds(3), Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4))); // #pipeto-testprobe } public enum Tick { TOCK, COMPLETED }; @Test public void sinkActorRef() throws Exception { // #sink-actorref final Source sourceUnderTest = Source.tick(Duration.ZERO, Duration.ofMillis(200), Tick.TOCK); final TestKit probe = new TestKit(system); final Cancellable cancellable = sourceUnderTest.to(Sink.actorRef(probe.getRef(), Tick.COMPLETED)).run(system); probe.expectMsg(Duration.ofSeconds(3), Tick.TOCK); probe.expectNoMessage(Duration.ofMillis(100)); probe.expectMsg(Duration.ofSeconds(3), Tick.TOCK); cancellable.cancel(); probe.expectMsg(Duration.ofSeconds(3), Tick.COMPLETED); // #sink-actorref } @Test public void sourceActorRef() throws Exception { // #source-actorref final Sink> sinkUnderTest = Flow.of(Integer.class) .map(i -> i.toString()) .toMat(Sink.fold("", (agg, next) -> agg + next), Keep.right()); final Pair> refAndCompletionStage = Source.actorRef(8, OverflowStrategy.fail()) .toMat(sinkUnderTest, Keep.both()) .run(system); final ActorRef ref = refAndCompletionStage.first(); final CompletionStage future = refAndCompletionStage.second(); ref.tell(1, ActorRef.noSender()); ref.tell(2, ActorRef.noSender()); ref.tell(3, ActorRef.noSender()); ref.tell(new akka.actor.Status.Success("done"), ActorRef.noSender()); final String result = future.toCompletableFuture().get(1, TimeUnit.SECONDS); assertEquals(result, "123"); // #source-actorref } @Test public void testSinkProbe() { // #test-sink-probe final Source sourceUnderTest = Source.from(Arrays.asList(1, 2, 3, 4)).filter(elem -> elem % 2 == 0).map(elem -> elem * 2); sourceUnderTest .runWith(TestSink.probe(system), system) .request(2) .expectNext(4, 8) .expectComplete(); // #test-sink-probe } @Test public void testSourceProbe() { // #test-source-probe final Sink sinkUnderTest = Sink.cancelled(); TestSource.probe(system) .toMat(sinkUnderTest, Keep.left()) .run(system) .expectCancellation(); // #test-source-probe } @Test public void injectingFailure() throws Exception { // #injecting-failure final Sink> sinkUnderTest = Sink.head(); final Pair, CompletionStage> probeAndCompletionStage = TestSource.probe(system).toMat(sinkUnderTest, Keep.both()).run(system); final TestPublisher.Probe probe = probeAndCompletionStage.first(); final CompletionStage future = probeAndCompletionStage.second(); probe.sendError(new Exception("boom")); try { future.toCompletableFuture().get(3, TimeUnit.SECONDS); assert false; } catch (ExecutionException ee) { final Throwable exception = ee.getCause(); assertEquals(exception.getMessage(), "boom"); } // #injecting-failure } @Test public void testSourceAndTestSink() throws Exception { // #test-source-and-sink final Flow flowUnderTest = Flow.of(Integer.class) .mapAsyncUnordered( 2, sleep -> akka.pattern.Patterns.after( Duration.ofMillis(10), system.scheduler(), system.dispatcher(), () -> CompletableFuture.completedFuture(sleep))); final Pair, TestSubscriber.Probe> pubAndSub = TestSource.probe(system) .via(flowUnderTest) .toMat(TestSink.probe(system), Keep.both()) .run(system); final TestPublisher.Probe pub = pubAndSub.first(); final TestSubscriber.Probe sub = pubAndSub.second(); sub.request(3); pub.sendNext(3); pub.sendNext(2); pub.sendNext(1); sub.expectNextUnordered(1, 2, 3); pub.sendError(new Exception("Power surge in the linear subroutine C-47!")); final Throwable ex = sub.expectError(); assert (ex.getMessage().contains("C-47")); // #test-source-and-sink } }