aboutsummaryrefslogtreecommitdiff
path: root/webrtc/base/physicalsocketserver_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/base/physicalsocketserver_unittest.cc')
-rw-r--r--webrtc/base/physicalsocketserver_unittest.cc165
1 files changed, 163 insertions, 2 deletions
diff --git a/webrtc/base/physicalsocketserver_unittest.cc b/webrtc/base/physicalsocketserver_unittest.cc
index 6c7be9f63c..a2fde80b42 100644
--- a/webrtc/base/physicalsocketserver_unittest.cc
+++ b/webrtc/base/physicalsocketserver_unittest.cc
@@ -18,13 +18,85 @@
#include "webrtc/base/socket_unittest.h"
#include "webrtc/base/testutils.h"
#include "webrtc/base/thread.h"
-#include "webrtc/test/testsupport/gtest_disable.h"
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 +123,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
@@ -215,8 +373,11 @@ TEST_F(PhysicalSocketTest, MAYBE_TestUdpIPv6) {
// https://code.google.com/p/webrtc/issues/detail?id=4958
// TODO(deadbeef): Enable again once test is reimplemented to be unflaky.
// Also disable for ASan.
+// Disabled on Android: https://code.google.com/p/webrtc/issues/detail?id=4364
+// Disabled on Linux: https://bugs.chromium.org/p/webrtc/issues/detail?id=5233
#if defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(ADDRESS_SANITIZER)
+ defined(ADDRESS_SANITIZER) || defined(WEBRTC_ANDROID) || \
+ defined(WEBRTC_LINUX)
#define MAYBE_TestUdpReadyToSendIPv4 DISABLED_TestUdpReadyToSendIPv4
#else
#define MAYBE_TestUdpReadyToSendIPv4 TestUdpReadyToSendIPv4