pekko/akka-actor-tests/src/test/scala/akka/io/TcpIntegrationSpec.scala

200 lines
7.9 KiB
Scala
Raw Normal View History

2013-01-18 13:20:17 +01:00
/**
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
2013-01-18 13:20:17 +01:00
*/
package akka.io
import akka.actor.{ ActorRef, PoisonPill }
import akka.io.Tcp._
import akka.testkit.{ TestProbe, AkkaSpec }
2013-06-14 14:45:43 +02:00
import akka.TestUtils._
import akka.util.ByteString
import java.io.IOException
import java.net.{ ServerSocket, InetSocketAddress }
import org.scalatest.concurrent.Timeouts
import scala.concurrent.duration._
import scala.language.postfixOps
2013-01-18 13:20:17 +01:00
class TcpIntegrationSpec extends AkkaSpec("""
akka.loglevel = INFO
akka.actor.serialize-creators = on
""") with TcpIntegrationSpecSupport with Timeouts {
2013-01-18 13:20:17 +01:00
"The TCP transport implementation" should {
"properly bind a test server" in new TestSetup
"allow connecting to and disconnecting from the test server" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
clientHandler.send(clientConnection, Close)
clientHandler.expectMsg(Closed)
serverHandler.expectMsg(PeerClosed)
verifyActorTermination(clientConnection)
verifyActorTermination(serverConnection)
}
"properly handle connection abort from client side" in new TestSetup {
2013-01-21 17:41:51 +01:00
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
clientHandler.send(clientConnection, Abort)
2013-01-21 17:41:51 +01:00
clientHandler.expectMsg(Aborted)
serverHandler.expectMsgType[ErrorClosed]
2013-01-21 17:41:51 +01:00
verifyActorTermination(clientConnection)
verifyActorTermination(serverConnection)
}
"properly handle connection abort from client side after chit-chat" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
chitchat(clientHandler, clientConnection, serverHandler, serverConnection)
clientHandler.send(clientConnection, Abort)
clientHandler.expectMsg(Aborted)
serverHandler.expectMsgType[ErrorClosed]
verifyActorTermination(clientConnection)
verifyActorTermination(serverConnection)
}
"properly handle connection abort from server side" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
serverHandler.send(serverConnection, Abort)
serverHandler.expectMsg(Aborted)
clientHandler.expectMsgType[ErrorClosed]
verifyActorTermination(clientConnection)
verifyActorTermination(serverConnection)
}
"properly handle connection abort from server side after chit-chat" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
chitchat(clientHandler, clientConnection, serverHandler, serverConnection)
serverHandler.send(serverConnection, Abort)
serverHandler.expectMsg(Aborted)
clientHandler.expectMsgType[ErrorClosed]
verifyActorTermination(clientConnection)
verifyActorTermination(serverConnection)
}
"properly handle connection abort via PosionPill from client side" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
clientHandler.send(clientConnection, PoisonPill)
verifyActorTermination(clientConnection)
serverHandler.expectMsgType[ErrorClosed]
verifyActorTermination(serverConnection)
}
"properly handle connection abort via PosionPill from client side after chit-chat" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
chitchat(clientHandler, clientConnection, serverHandler, serverConnection)
clientHandler.send(clientConnection, PoisonPill)
verifyActorTermination(clientConnection)
serverHandler.expectMsgType[ErrorClosed]
verifyActorTermination(serverConnection)
}
"properly handle connection abort via PosionPill from server side" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
serverHandler.send(serverConnection, PoisonPill)
verifyActorTermination(serverConnection)
clientHandler.expectMsgType[ErrorClosed]
verifyActorTermination(clientConnection)
}
"properly handle connection abort via PosionPill from server side after chit-chat" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
chitchat(clientHandler, clientConnection, serverHandler, serverConnection)
serverHandler.send(serverConnection, PoisonPill)
verifyActorTermination(serverConnection)
clientHandler.expectMsgType[ErrorClosed]
verifyActorTermination(clientConnection)
}
2013-01-18 13:20:17 +01:00
"properly complete one client/server request/response cycle" in new TestSetup {
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
object Aye extends Event
object Yes extends Event
clientHandler.send(clientConnection, Write(ByteString("Captain on the bridge!"), Aye))
clientHandler.expectMsg(Aye)
2015-01-16 11:09:59 +01:00
serverHandler.expectMsgType[Received].data.decodeString("ASCII") should ===("Captain on the bridge!")
2013-01-18 13:20:17 +01:00
serverHandler.send(serverConnection, Write(ByteString("For the king!"), Yes))
serverHandler.expectMsg(Yes)
2015-01-16 11:09:59 +01:00
clientHandler.expectMsgType[Received].data.decodeString("ASCII") should ===("For the king!")
2013-01-18 13:20:17 +01:00
serverHandler.send(serverConnection, Close)
serverHandler.expectMsg(Closed)
clientHandler.expectMsg(PeerClosed)
verifyActorTermination(clientConnection)
verifyActorTermination(serverConnection)
}
"support waiting for writes with backpressure" in new TestSetup {
2013-01-21 17:41:51 +01:00
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
object Ack extends Event
serverHandler.send(serverConnection, Write(ByteString(Array.fill[Byte](100000)(0)), Ack))
serverHandler.expectMsg(Ack)
2013-01-21 17:41:51 +01:00
expectReceivedData(clientHandler, 100000)
override def bindOptions = List(SO.SendBufferSize(1024))
override def connectOptions = List(SO.ReceiveBufferSize(1024))
2013-01-18 13:20:17 +01:00
}
"don't report Connected when endpoint isn't responding" in {
val connectCommander = TestProbe()
// a "random" endpoint hopefully unavailable since it's in the test-net IP range
val endpoint = new InetSocketAddress("192.0.2.1", 23825)
connectCommander.send(IO(Tcp), Connect(endpoint))
// expecting CommandFailed or no reply (within timeout)
val replies = connectCommander.receiveWhile(1.second) { case m: Connected m }
2015-01-16 11:09:59 +01:00
replies should ===(Nil)
}
2013-01-18 13:20:17 +01:00
"handle tcp connection actor death properly" in new TestSetup(shouldBindServer = false) {
val serverSocket = new ServerSocket(endpoint.getPort(), 100, endpoint.getAddress())
val connectCommander = TestProbe()
connectCommander.send(IO(Tcp), Connect(endpoint))
val accept = serverSocket.accept()
2015-01-16 11:09:59 +01:00
connectCommander.expectMsgType[Connected].remoteAddress should ===(endpoint)
val connectionActor = connectCommander.lastSender
connectCommander.send(connectionActor, PoisonPill)
failAfter(3 seconds) {
try {
2015-01-16 11:09:59 +01:00
accept.getInputStream.read() should ===(-1)
} catch {
case e: IOException // this is also fine
}
}
verifyActorTermination(connectionActor)
}
}
def chitchat(
clientHandler: TestProbe,
clientConnection: ActorRef,
serverHandler: TestProbe,
serverConnection: ActorRef,
rounds: Int = 100) = {
val testData = ByteString(0)
(1 to rounds) foreach { _
clientHandler.send(clientConnection, Write(testData))
serverHandler.expectMsg(Received(testData))
serverHandler.send(serverConnection, Write(testData))
clientHandler.expectMsg(Received(testData))
}
}
2013-01-21 17:41:51 +01:00
}