| Index: webrtc/base/physicalsocketserver_unittest.cc
|
| diff --git a/webrtc/base/physicalsocketserver_unittest.cc b/webrtc/base/physicalsocketserver_unittest.cc
|
| index ad0d4657e880c4728b8076d63edadb0347810b80..5ff4859e13ce45b12cfbf0d41f118de445171658 100644
|
| --- a/webrtc/base/physicalsocketserver_unittest.cc
|
| +++ b/webrtc/base/physicalsocketserver_unittest.cc
|
| @@ -22,9 +22,82 @@
|
|
|
| namespace rtc {
|
|
|
| +class PhysicalSocketTest;
|
| +
|
| +class FakeSocketDispatcher : public SocketDispatcher {
|
| + public:
|
| + explicit FakeSocketDispatcher(PhysicalSocketServer* ss)
|
| + : SocketDispatcher(ss) {
|
| + }
|
| +
|
| + protected:
|
| + SOCKET DoAccept(SOCKET socket, sockaddr* addr, socklen_t* addrlen) override;
|
| +};
|
| +
|
| +class FakePhysicalSocketServer : public PhysicalSocketServer {
|
| + public:
|
| + explicit FakePhysicalSocketServer(PhysicalSocketTest* test)
|
| + : test_(test) {
|
| + }
|
| +
|
| + AsyncSocket* CreateAsyncSocket(int type) override {
|
| + SocketDispatcher* dispatcher = new FakeSocketDispatcher(this);
|
| + if (dispatcher->Create(type)) {
|
| + return dispatcher;
|
| + } else {
|
| + delete dispatcher;
|
| + return nullptr;
|
| + }
|
| + }
|
| +
|
| + AsyncSocket* CreateAsyncSocket(int family, int type) override {
|
| + SocketDispatcher* dispatcher = new FakeSocketDispatcher(this);
|
| + if (dispatcher->Create(family, type)) {
|
| + return dispatcher;
|
| + } else {
|
| + delete dispatcher;
|
| + return nullptr;
|
| + }
|
| + }
|
| +
|
| + PhysicalSocketTest* GetTest() const { return test_; }
|
| +
|
| + private:
|
| + PhysicalSocketTest* test_;
|
| +};
|
| +
|
| class PhysicalSocketTest : public SocketTest {
|
| + public:
|
| + // Set flag to simluate failures when calling "::accept" on a AsyncSocket.
|
| + void SetFailAccept(bool fail) { fail_accept_ = fail; }
|
| + bool FailAccept() const { return fail_accept_; }
|
| +
|
| + protected:
|
| + PhysicalSocketTest()
|
| + : server_(new FakePhysicalSocketServer(this)),
|
| + scope_(server_.get()),
|
| + fail_accept_(false) {
|
| + }
|
| +
|
| + void ConnectInternalAcceptError(const IPAddress& loopback);
|
| +
|
| + rtc::scoped_ptr<FakePhysicalSocketServer> server_;
|
| + SocketServerScope scope_;
|
| + bool fail_accept_;
|
| };
|
|
|
| +SOCKET FakeSocketDispatcher::DoAccept(SOCKET socket,
|
| + sockaddr* addr,
|
| + socklen_t* addrlen) {
|
| + FakePhysicalSocketServer* ss =
|
| + static_cast<FakePhysicalSocketServer*>(socketserver());
|
| + if (ss->GetTest()->FailAccept()) {
|
| + return INVALID_SOCKET;
|
| + }
|
| +
|
| + return SocketDispatcher::DoAccept(socket, addr, addrlen);
|
| +}
|
| +
|
| TEST_F(PhysicalSocketTest, TestConnectIPv4) {
|
| SocketTest::TestConnectIPv4();
|
| }
|
| @@ -51,6 +124,92 @@ TEST_F(PhysicalSocketTest, TestConnectFailIPv4) {
|
| SocketTest::TestConnectFailIPv4();
|
| }
|
|
|
| +void PhysicalSocketTest::ConnectInternalAcceptError(const IPAddress& loopback) {
|
| + testing::StreamSink sink;
|
| + SocketAddress accept_addr;
|
| +
|
| + // Create two clients.
|
| + scoped_ptr<AsyncSocket> client1(server_->CreateAsyncSocket(loopback.family(),
|
| + SOCK_STREAM));
|
| + sink.Monitor(client1.get());
|
| + EXPECT_EQ(AsyncSocket::CS_CLOSED, client1->GetState());
|
| + EXPECT_PRED1(IsUnspecOrEmptyIP, client1->GetLocalAddress().ipaddr());
|
| +
|
| + scoped_ptr<AsyncSocket> client2(server_->CreateAsyncSocket(loopback.family(),
|
| + SOCK_STREAM));
|
| + sink.Monitor(client2.get());
|
| + EXPECT_EQ(AsyncSocket::CS_CLOSED, client2->GetState());
|
| + EXPECT_PRED1(IsUnspecOrEmptyIP, client2->GetLocalAddress().ipaddr());
|
| +
|
| + // Create server and listen.
|
| + scoped_ptr<AsyncSocket> server(
|
| + server_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
|
| + sink.Monitor(server.get());
|
| + EXPECT_EQ(0, server->Bind(SocketAddress(loopback, 0)));
|
| + EXPECT_EQ(0, server->Listen(5));
|
| + EXPECT_EQ(AsyncSocket::CS_CONNECTING, server->GetState());
|
| +
|
| + // Ensure no pending server connections, since we haven't done anything yet.
|
| + EXPECT_FALSE(sink.Check(server.get(), testing::SSE_READ));
|
| + EXPECT_TRUE(nullptr == server->Accept(&accept_addr));
|
| + EXPECT_TRUE(accept_addr.IsNil());
|
| +
|
| + // Attempt first connect to listening socket.
|
| + EXPECT_EQ(0, client1->Connect(server->GetLocalAddress()));
|
| + EXPECT_FALSE(client1->GetLocalAddress().IsNil());
|
| + EXPECT_NE(server->GetLocalAddress(), client1->GetLocalAddress());
|
| +
|
| + // Client is connecting, outcome not yet determined.
|
| + EXPECT_EQ(AsyncSocket::CS_CONNECTING, client1->GetState());
|
| + EXPECT_FALSE(sink.Check(client1.get(), testing::SSE_OPEN));
|
| + EXPECT_FALSE(sink.Check(client1.get(), testing::SSE_CLOSE));
|
| +
|
| + // Server has pending connection, try to accept it (will fail).
|
| + EXPECT_TRUE_WAIT((sink.Check(server.get(), testing::SSE_READ)), kTimeout);
|
| + // Simulate "::accept" returning an error.
|
| + SetFailAccept(true);
|
| + scoped_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
|
| + EXPECT_FALSE(accepted);
|
| + ASSERT_TRUE(accept_addr.IsNil());
|
| +
|
| + // Ensure no more pending server connections.
|
| + EXPECT_FALSE(sink.Check(server.get(), testing::SSE_READ));
|
| + EXPECT_TRUE(nullptr == server->Accept(&accept_addr));
|
| + EXPECT_TRUE(accept_addr.IsNil());
|
| +
|
| + // Attempt second connect to listening socket.
|
| + EXPECT_EQ(0, client2->Connect(server->GetLocalAddress()));
|
| + EXPECT_FALSE(client2->GetLocalAddress().IsNil());
|
| + EXPECT_NE(server->GetLocalAddress(), client2->GetLocalAddress());
|
| +
|
| + // Client is connecting, outcome not yet determined.
|
| + EXPECT_EQ(AsyncSocket::CS_CONNECTING, client2->GetState());
|
| + EXPECT_FALSE(sink.Check(client2.get(), testing::SSE_OPEN));
|
| + EXPECT_FALSE(sink.Check(client2.get(), testing::SSE_CLOSE));
|
| +
|
| + // Server has pending connection, try to accept it (will succeed).
|
| + EXPECT_TRUE_WAIT((sink.Check(server.get(), testing::SSE_READ)), kTimeout);
|
| + SetFailAccept(false);
|
| + scoped_ptr<AsyncSocket> accepted2(server->Accept(&accept_addr));
|
| + ASSERT_TRUE(accepted2);
|
| + EXPECT_FALSE(accept_addr.IsNil());
|
| + EXPECT_EQ(accepted2->GetRemoteAddress(), accept_addr);
|
| +}
|
| +
|
| +TEST_F(PhysicalSocketTest, TestConnectAcceptErrorIPv4) {
|
| + ConnectInternalAcceptError(kIPv4Loopback);
|
| +}
|
| +
|
| +// Crashes on Linux. See webrtc:4923.
|
| +#if defined(WEBRTC_LINUX)
|
| +#define MAYBE_TestConnectAcceptErrorIPv6 DISABLED_TestConnectAcceptErrorIPv6
|
| +#else
|
| +#define MAYBE_TestConnectAcceptErrorIPv6 TestConnectAcceptErrorIPv6
|
| +#endif
|
| +TEST_F(PhysicalSocketTest, MAYBE_TestConnectAcceptErrorIPv6) {
|
| + ConnectInternalAcceptError(kIPv6Loopback);
|
| +}
|
| +
|
| // Crashes on Linux. See webrtc:4923.
|
| #if defined(WEBRTC_LINUX)
|
| #define MAYBE_TestConnectFailIPv6 DISABLED_TestConnectFailIPv6
|
|
|