2013-01-18 13:20:17 +01:00
|
|
|
/**
|
2015-03-07 22:58:48 -08:00
|
|
|
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
|
2013-01-18 13:20:17 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package akka.io
|
|
|
|
|
|
2014-09-15 11:19:07 +02:00
|
|
|
import akka.actor.{ ActorRef, PoisonPill }
|
2014-08-29 11:17:49 +02:00
|
|
|
import akka.io.Tcp._
|
2013-09-12 11:28:45 +02:00
|
|
|
import akka.testkit.{ TestProbe, AkkaSpec }
|
2013-06-14 14:45:43 +02:00
|
|
|
import akka.TestUtils._
|
2014-08-29 11:17:49 +02:00
|
|
|
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
|
|
|
|
2013-05-29 16:13:10 +02:00
|
|
|
class TcpIntegrationSpec extends AkkaSpec("""
|
|
|
|
|
akka.loglevel = INFO
|
|
|
|
|
akka.actor.serialize-creators = on
|
2014-08-29 11:17:49 +02:00
|
|
|
""") 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)
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-15 11:19:07 +02:00
|
|
|
"properly handle connection abort from client side" in new TestSetup {
|
2013-01-21 17:41:51 +01:00
|
|
|
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
|
2013-05-31 09:52:51 +02:00
|
|
|
clientHandler.send(clientConnection, Abort)
|
2013-01-21 17:41:51 +01:00
|
|
|
clientHandler.expectMsg(Aborted)
|
2013-01-23 11:47:12 +01:00
|
|
|
serverHandler.expectMsgType[ErrorClosed]
|
2013-01-21 17:41:51 +01:00
|
|
|
verifyActorTermination(clientConnection)
|
|
|
|
|
verifyActorTermination(serverConnection)
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-15 11:19:07 +02:00
|
|
|
"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()
|
|
|
|
|
|
2013-05-26 10:58:55 +02:00
|
|
|
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
|
|
|
|
2013-05-26 10:58:55 +02: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)
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-22 13:48:36 +01:00
|
|
|
"support waiting for writes with backpressure" in new TestSetup {
|
2013-01-21 17:41:51 +01:00
|
|
|
val (clientHandler, clientConnection, serverHandler, serverConnection) = establishNewClientConnection()
|
|
|
|
|
|
2013-05-26 10:58:55 +02:00
|
|
|
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)
|
|
|
|
|
|
2013-02-06 11:38:42 +01:00
|
|
|
override def bindOptions = List(SO.SendBufferSize(1024))
|
|
|
|
|
override def connectOptions = List(SO.ReceiveBufferSize(1024))
|
2013-01-18 13:20:17 +01:00
|
|
|
}
|
2014-08-29 11:17:49 +02:00
|
|
|
|
2013-09-12 11:28:45 +02:00
|
|
|
"don't report Connected when endpoint isn't responding" in {
|
|
|
|
|
val connectCommander = TestProbe()
|
2014-08-29 11:17:49 +02:00
|
|
|
// a "random" endpoint hopefully unavailable since it's in the test-net IP range
|
|
|
|
|
val endpoint = new InetSocketAddress("192.0.2.1", 23825)
|
2013-09-12 11:28:45 +02:00
|
|
|
connectCommander.send(IO(Tcp), Connect(endpoint))
|
2014-01-08 17:51:18 +01:00
|
|
|
// 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-09-12 11:28:45 +02:00
|
|
|
}
|
2013-01-18 13:20:17 +01:00
|
|
|
|
2014-08-29 11:17:49 +02: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)
|
2014-08-29 11:17:49 +02:00
|
|
|
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)
|
2014-08-29 11:17:49 +02:00
|
|
|
} catch {
|
|
|
|
|
case e: IOException ⇒ // this is also fine
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
verifyActorTermination(connectionActor)
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-09-15 11:19:07 +02:00
|
|
|
|
|
|
|
|
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
|
|
|
}
|