Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(439)

Unified Diff: webrtc/base/physicalsocketserver_unittest.cc

Issue 1452903006: Keep listening if "accept" returns an invalid socket. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Fixed presubmit Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/base/physicalsocketserver.cc ('k') | webrtc/base/socket_unittest.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « webrtc/base/physicalsocketserver.cc ('k') | webrtc/base/socket_unittest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698