pekko/akka-stream-tests/src/test/scala/akka/stream/scaladsl/GraphBalanceSpec.scala

223 lines
6.1 KiB
Scala
Raw Normal View History

package akka.stream.scaladsl
2014-10-03 09:00:08 +03:00
import scala.concurrent.Await
import scala.concurrent.duration._
import FlowGraphImplicits._
import akka.stream.ActorFlowMaterializer
import akka.stream.ActorFlowMaterializerSettings
import akka.stream.testkit.{ AkkaSpec, StreamTestKit }
2014-10-03 09:00:08 +03:00
class GraphBalanceSpec extends AkkaSpec {
val settings = ActorFlowMaterializerSettings(system)
2014-10-03 09:00:08 +03:00
.withInputBuffer(initialSize = 2, maxSize = 16)
implicit val materializer = ActorFlowMaterializer(settings)
2014-10-03 09:00:08 +03:00
"A balance" must {
"balance between subscribers which signal demand" in {
val c1 = StreamTestKit.SubscriberProbe[Int]()
val c2 = StreamTestKit.SubscriberProbe[Int]()
FlowGraph { implicit b
val balance = Balance[Int]
2014-10-03 09:00:08 +03:00
Source(List(1, 2, 3)) ~> balance
balance ~> Sink(c1)
balance ~> Sink(c2)
2014-10-03 09:00:08 +03:00
}.run()
val sub1 = c1.expectSubscription()
val sub2 = c2.expectSubscription()
sub1.request(1)
c1.expectNext(1)
c1.expectNoMsg(100.millis)
sub2.request(2)
c2.expectNext(2)
c2.expectNext(3)
c1.expectComplete()
c2.expectComplete()
}
"support waiting for demand from all downstream subscriptions" in {
val s1 = StreamTestKit.SubscriberProbe[Int]()
val p2Sink = Sink.publisher[Int]
val m = FlowGraph { implicit b
val balance = Balance[Int](waitForAllDownstreams = true)
Source(List(1, 2, 3)) ~> balance
balance ~> Sink(s1)
balance ~> p2Sink
}.run()
val p2 = m.get(p2Sink)
val sub1 = s1.expectSubscription()
sub1.request(1)
s1.expectNoMsg(200.millis)
val s2 = StreamTestKit.SubscriberProbe[Int]()
p2.subscribe(s2)
val sub2 = s2.expectSubscription()
// still no demand from s2
s1.expectNoMsg(200.millis)
sub2.request(2)
s1.expectNext(1)
s2.expectNext(2)
s2.expectNext(3)
s1.expectComplete()
s2.expectComplete()
}
"support waiting for demand from all non-cancelled downstream subscriptions" in {
val s1 = StreamTestKit.SubscriberProbe[Int]()
val p2Sink = Sink.publisher[Int]
val p3Sink = Sink.publisher[Int]
val m = FlowGraph { implicit b
val balance = Balance[Int](waitForAllDownstreams = true)
Source(List(1, 2, 3)) ~> balance
balance ~> Sink(s1)
balance ~> p2Sink
balance ~> p3Sink
}.run()
val p2 = m.get(p2Sink)
val p3 = m.get(p3Sink)
val sub1 = s1.expectSubscription()
sub1.request(1)
val s2 = StreamTestKit.SubscriberProbe[Int]()
p2.subscribe(s2)
val sub2 = s2.expectSubscription()
val s3 = StreamTestKit.SubscriberProbe[Int]()
p3.subscribe(s3)
val sub3 = s3.expectSubscription()
sub2.request(2)
s1.expectNoMsg(200.millis)
sub3.cancel()
s1.expectNext(1)
s2.expectNext(2)
s2.expectNext(3)
s1.expectComplete()
s2.expectComplete()
}
2014-10-03 09:00:08 +03:00
"work with 5-way balance" in {
val f1 = Sink.head[Seq[Int]]
val f2 = Sink.head[Seq[Int]]
val f3 = Sink.head[Seq[Int]]
val f4 = Sink.head[Seq[Int]]
val f5 = Sink.head[Seq[Int]]
2014-10-03 09:00:08 +03:00
val g = FlowGraph { implicit b
val balance = Balance[Int](waitForAllDownstreams = true)
2014-10-03 09:00:08 +03:00
Source(0 to 14) ~> balance
balance ~> Flow[Int].grouped(15) ~> f1
balance ~> Flow[Int].grouped(15) ~> f2
balance ~> Flow[Int].grouped(15) ~> f3
balance ~> Flow[Int].grouped(15) ~> f4
balance ~> Flow[Int].grouped(15) ~> f5
}.run()
Set(f1, f2, f3, f4, f5) flatMap (sink Await.result(g.get(sink), 3.seconds)) should be((0 to 14).toSet)
2014-10-03 09:00:08 +03:00
}
"fairly balance between three outputs" in {
val numElementsForSink = 10000
val outputs = Seq.fill(3)(Sink.fold[Int, Int](0)(_ + _))
2014-10-03 09:00:08 +03:00
val g = FlowGraph { implicit b
val balance = Balance[Int](waitForAllDownstreams = true)
Source(Stream.fill(numElementsForSink * outputs.size)(1)) ~> balance
for { o outputs } balance ~> o
2014-10-03 09:00:08 +03:00
}.run()
for { o outputs } Await.result(g.get(o), 3.seconds) should be(numElementsForSink +- 1000)
2014-10-03 09:00:08 +03:00
}
"produce to second even though first cancels" in {
val c1 = StreamTestKit.SubscriberProbe[Int]()
val c2 = StreamTestKit.SubscriberProbe[Int]()
FlowGraph { implicit b
val balance = Balance[Int]
2014-10-03 09:00:08 +03:00
Source(List(1, 2, 3)) ~> balance
balance ~> Flow[Int] ~> Sink(c1)
balance ~> Flow[Int] ~> Sink(c2)
2014-10-03 09:00:08 +03:00
}.run()
val sub1 = c1.expectSubscription()
sub1.cancel()
val sub2 = c2.expectSubscription()
sub2.request(3)
c2.expectNext(1)
c2.expectNext(2)
c2.expectNext(3)
c2.expectComplete()
}
"produce to first even though second cancels" in {
val c1 = StreamTestKit.SubscriberProbe[Int]()
val c2 = StreamTestKit.SubscriberProbe[Int]()
FlowGraph { implicit b
val balance = Balance[Int]
2014-10-03 09:00:08 +03:00
Source(List(1, 2, 3)) ~> balance
balance ~> Flow[Int] ~> Sink(c1)
balance ~> Flow[Int] ~> Sink(c2)
2014-10-03 09:00:08 +03:00
}.run()
val sub1 = c1.expectSubscription()
val sub2 = c2.expectSubscription()
sub2.cancel()
sub1.request(3)
c1.expectNext(1)
c1.expectNext(2)
c1.expectNext(3)
c1.expectComplete()
}
"cancel upstream when downstreams cancel" in {
val p1 = StreamTestKit.PublisherProbe[Int]()
val c1 = StreamTestKit.SubscriberProbe[Int]()
val c2 = StreamTestKit.SubscriberProbe[Int]()
FlowGraph { implicit b
val balance = Balance[Int]
2014-10-03 09:00:08 +03:00
Source(p1.getPublisher) ~> balance
balance ~> Flow[Int] ~> Sink(c1)
balance ~> Flow[Int] ~> Sink(c2)
2014-10-03 09:00:08 +03:00
}.run()
val bsub = p1.expectSubscription()
val sub1 = c1.expectSubscription()
val sub2 = c2.expectSubscription()
sub1.request(1)
p1.expectRequest(bsub, 16)
bsub.sendNext(1)
c1.expectNext(1)
sub2.request(1)
bsub.sendNext(2)
c2.expectNext(2)
sub1.cancel()
sub2.cancel()
bsub.expectCancellation()
}
}
}