Chromium Code Reviews| Index: webrtc/base/physicalsocketserver_unittest.cc |
| diff --git a/webrtc/base/physicalsocketserver_unittest.cc b/webrtc/base/physicalsocketserver_unittest.cc |
| index f2eabcd66cf15f6b0f2f23d6a2b3d1978aaaa876..073f6f20d708967c3fbe0429f0e47f86dc05ed25 100644 |
| --- a/webrtc/base/physicalsocketserver_unittest.cc |
| +++ b/webrtc/base/physicalsocketserver_unittest.cc |
| @@ -22,9 +22,72 @@ |
| namespace rtc { |
| +class PhysicalSocketTest; |
| + |
| +class MockSocketDispatcher : public SocketDispatcher { |
|
pthatcher1
2015/12/03 22:56:32
I think we would call these Fake, not Mock
|
| + public: |
| + explicit MockSocketDispatcher(PhysicalSocketServer* ss) |
| + : SocketDispatcher(ss) { |
| + } |
| + |
| + protected: |
| + SOCKET DoAccept(SOCKET socket, sockaddr* addr, socklen_t* addrlen) override; |
| +}; |
| + |
| +class MockPhysicalSocketServer : public PhysicalSocketServer { |
| + public: |
| + explicit MockPhysicalSocketServer(PhysicalSocketTest* test) |
| + : test_(test) { |
| + } |
| + |
| + AsyncSocket* CreateAsyncSocket(int family, int type) override { |
| + SocketDispatcher* dispatcher = new MockSocketDispatcher(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 MockPhysicalSocketServer(this)), |
| + scope_(server_.get()), |
| + fail_accept_(false) { |
| + } |
| + |
| + void ConnectInternalAcceptError(const IPAddress& loopback); |
| + |
| + rtc::scoped_ptr<MockPhysicalSocketServer> server_; |
| + SocketServerScope scope_; |
| + bool fail_accept_; |
| }; |
| +SOCKET MockSocketDispatcher::DoAccept(SOCKET socket, |
| + sockaddr* addr, |
| + socklen_t* addrlen) { |
| + MockPhysicalSocketServer* ss = |
| + static_cast<MockPhysicalSocketServer*>(socketserver()); |
| + if (ss->GetTest()->FailAccept()) { |
| + return INVALID_SOCKET; |
| + } |
| + |
| + return SocketDispatcher::DoAccept(socket, addr, addrlen); |
| +} |
| + |
| TEST_F(PhysicalSocketTest, TestConnectIPv4) { |
| SocketTest::TestConnectIPv4(); |
| } |
| @@ -51,6 +114,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 |