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

Unified Diff: webrtc/base/socket_unittest.cc

Issue 1616153007: Stay writable after partial socket writes. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: More feedback. Created 4 years, 11 months 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/socket_unittest.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/base/socket_unittest.cc
diff --git a/webrtc/base/socket_unittest.cc b/webrtc/base/socket_unittest.cc
index 8143823b862d792e98f83ae153ba54f941219113..d1369e2f78c1bef806e272ece186c9f60e327292 100644
--- a/webrtc/base/socket_unittest.cc
+++ b/webrtc/base/socket_unittest.cc
@@ -11,6 +11,7 @@
#include "webrtc/base/socket_unittest.h"
#include "webrtc/base/arraysize.h"
+#include "webrtc/base/buffer.h"
#include "webrtc/base/asyncudpsocket.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/nethelpers.h"
@@ -21,6 +22,9 @@
namespace rtc {
+// Data size to be used in TcpInternal tests.
+static const size_t kTcpInternalDataSize = 1024 * 1024; // bytes
+
#define MAYBE_SKIP_IPV6 \
if (!HasIPv6Enabled()) { \
LOG(LS_INFO) << "No IPv6... skipping"; \
@@ -129,12 +133,12 @@ void SocketTest::TestSocketServerWaitIPv6() {
}
void SocketTest::TestTcpIPv4() {
- TcpInternal(kIPv4Loopback);
+ TcpInternal(kIPv4Loopback, kTcpInternalDataSize, -1);
}
void SocketTest::TestTcpIPv6() {
MAYBE_SKIP_IPV6;
- TcpInternal(kIPv6Loopback);
+ TcpInternal(kIPv6Loopback, kTcpInternalDataSize, -1);
}
void SocketTest::TestSingleFlowControlCallbackIPv4() {
@@ -671,24 +675,15 @@ void SocketTest::SocketServerWaitInternal(const IPAddress& loopback) {
EXPECT_LT(0, accepted->Recv(buf, 1024));
}
-void SocketTest::TcpInternal(const IPAddress& loopback) {
+void SocketTest::TcpInternal(const IPAddress& loopback, size_t data_size,
+ ssize_t max_send_size) {
testing::StreamSink sink;
SocketAddress accept_addr;
- // Create test data.
- const size_t kDataSize = 1024 * 1024;
- scoped_ptr<char[]> send_buffer(new char[kDataSize]);
- scoped_ptr<char[]> recv_buffer(new char[kDataSize]);
- size_t send_pos = 0, recv_pos = 0;
- for (size_t i = 0; i < kDataSize; ++i) {
- send_buffer[i] = static_cast<char>(i % 256);
- recv_buffer[i] = 0;
- }
-
- // Create client.
- scoped_ptr<AsyncSocket> client(
+ // Create receiving client.
+ scoped_ptr<AsyncSocket> receiver(
ss_->CreateAsyncSocket(loopback.family(), SOCK_STREAM));
- sink.Monitor(client.get());
+ sink.Monitor(receiver.get());
// Create server and listen.
scoped_ptr<AsyncSocket> server(
@@ -698,97 +693,115 @@ void SocketTest::TcpInternal(const IPAddress& loopback) {
EXPECT_EQ(0, server->Listen(5));
// Attempt connection.
- EXPECT_EQ(0, client->Connect(server->GetLocalAddress()));
+ EXPECT_EQ(0, receiver->Connect(server->GetLocalAddress()));
- // Accept connection.
+ // Accept connection which will be used for sending.
EXPECT_TRUE_WAIT((sink.Check(server.get(), testing::SSE_READ)), kTimeout);
- scoped_ptr<AsyncSocket> accepted(server->Accept(&accept_addr));
- ASSERT_TRUE(accepted);
- sink.Monitor(accepted.get());
+ scoped_ptr<AsyncSocket> sender(server->Accept(&accept_addr));
+ ASSERT_TRUE(sender);
+ sink.Monitor(sender.get());
// Both sides are now connected.
- EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, client->GetState(), kTimeout);
- EXPECT_TRUE(sink.Check(client.get(), testing::SSE_OPEN));
- EXPECT_EQ(client->GetRemoteAddress(), accepted->GetLocalAddress());
- EXPECT_EQ(accepted->GetRemoteAddress(), client->GetLocalAddress());
+ EXPECT_EQ_WAIT(AsyncSocket::CS_CONNECTED, receiver->GetState(), kTimeout);
+ EXPECT_TRUE(sink.Check(receiver.get(), testing::SSE_OPEN));
+ EXPECT_EQ(receiver->GetRemoteAddress(), sender->GetLocalAddress());
+ EXPECT_EQ(sender->GetRemoteAddress(), receiver->GetLocalAddress());
+
+ // Create test data.
+ rtc::Buffer send_buffer(0, data_size);
+ rtc::Buffer recv_buffer(0, data_size);
+ for (size_t i = 0; i < data_size; ++i) {
+ char ch = static_cast<char>(i % 256);
+ send_buffer.AppendData(&ch, sizeof(ch));
+ }
// Send and receive a bunch of data.
- bool send_waiting_for_writability = false;
- bool send_expect_success = true;
- bool recv_waiting_for_readability = true;
- bool recv_expect_success = false;
- int data_in_flight = 0;
- while (recv_pos < kDataSize) {
- // Send as much as we can if we've been cleared to send.
- while (!send_waiting_for_writability && send_pos < kDataSize) {
- int tosend = static_cast<int>(kDataSize - send_pos);
- int sent = accepted->Send(send_buffer.get() + send_pos, tosend);
- if (send_expect_success) {
+ size_t sent_size = 0;
+ bool writable = true;
+ bool send_called = false;
+ bool readable = false;
+ bool recv_called = false;
+ while (recv_buffer.size() < send_buffer.size()) {
+ // Send as much as we can while we're cleared to send.
+ while (writable && sent_size < send_buffer.size()) {
+ int unsent_size = static_cast<int>(send_buffer.size() - sent_size);
+ int sent = sender->Send(send_buffer.data() + sent_size, unsent_size);
+ if (!send_called) {
// The first Send() after connecting or getting writability should
// succeed and send some data.
EXPECT_GT(sent, 0);
- send_expect_success = false;
+ send_called = true;
}
if (sent >= 0) {
- EXPECT_LE(sent, tosend);
- send_pos += sent;
- data_in_flight += sent;
+ EXPECT_LE(sent, unsent_size);
+ sent_size += sent;
+ if (max_send_size >= 0) {
+ EXPECT_LE(static_cast<ssize_t>(sent), max_send_size);
+ if (sent < unsent_size) {
+ // If max_send_size is limiting the amount to send per call such
+ // that the sent amount is less than the unsent amount, we simulate
+ // that the socket is no longer writable.
+ writable = false;
+ }
+ }
} else {
- ASSERT_TRUE(accepted->IsBlocking());
- send_waiting_for_writability = true;
+ ASSERT_TRUE(sender->IsBlocking());
+ writable = false;
}
}
// Read all the sent data.
- while (data_in_flight > 0) {
- if (recv_waiting_for_readability) {
+ while (recv_buffer.size() < sent_size) {
+ if (!readable) {
// Wait until data is available.
- EXPECT_TRUE_WAIT(sink.Check(client.get(), testing::SSE_READ), kTimeout);
- recv_waiting_for_readability = false;
- recv_expect_success = true;
+ EXPECT_TRUE_WAIT(sink.Check(receiver.get(), testing::SSE_READ),
+ kTimeout);
+ readable = true;
+ recv_called = false;
}
// Receive as much as we can get in a single recv call.
- int rcvd = client->Recv(recv_buffer.get() + recv_pos,
- kDataSize - recv_pos);
+ char recved_data[data_size];
+ int recved_size = receiver->Recv(recved_data, data_size);
- if (recv_expect_success) {
+ if (!recv_called) {
// The first Recv() after getting readability should succeed and receive
// some data.
// TODO: The following line is disabled due to flakey pulse
// builds. Re-enable if/when possible.
- // EXPECT_GT(rcvd, 0);
- recv_expect_success = false;
+ // EXPECT_GT(recved_size, 0);
+ recv_called = true;
}
- if (rcvd >= 0) {
- EXPECT_LE(rcvd, data_in_flight);
- recv_pos += rcvd;
- data_in_flight -= rcvd;
+ if (recved_size >= 0) {
+ EXPECT_LE(static_cast<size_t>(recved_size),
+ sent_size - recv_buffer.size());
+ recv_buffer.AppendData(recved_data, recved_size);
} else {
- ASSERT_TRUE(client->IsBlocking());
- recv_waiting_for_readability = true;
+ ASSERT_TRUE(receiver->IsBlocking());
+ readable = false;
}
}
- // Once all that we've sent has been rcvd, expect to be able to send again.
- if (send_waiting_for_writability) {
- EXPECT_TRUE_WAIT(sink.Check(accepted.get(), testing::SSE_WRITE),
+ // Once all that we've sent has been received, expect to be able to send
+ // again.
+ if (!writable) {
+ EXPECT_TRUE_WAIT(sink.Check(sender.get(), testing::SSE_WRITE),
kTimeout);
- send_waiting_for_writability = false;
- send_expect_success = true;
+ writable = true;
+ send_called = false;
}
}
// The received data matches the sent data.
- EXPECT_EQ(kDataSize, send_pos);
- EXPECT_EQ(kDataSize, recv_pos);
- EXPECT_EQ(0, memcmp(recv_buffer.get(), send_buffer.get(), kDataSize));
+ EXPECT_EQ(data_size, sent_size);
+ EXPECT_EQ(data_size, recv_buffer.size());
+ EXPECT_EQ(recv_buffer, send_buffer);
// Close down.
- accepted->Close();
- EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, client->GetState(), kTimeout);
- EXPECT_TRUE(sink.Check(client.get(), testing::SSE_CLOSE));
- client->Close();
+ sender->Close();
+ EXPECT_EQ_WAIT(AsyncSocket::CS_CLOSED, receiver->GetState(), kTimeout);
+ EXPECT_TRUE(sink.Check(receiver.get(), testing::SSE_CLOSE));
+ receiver->Close();
}
void SocketTest::SingleFlowControlCallbackInternal(const IPAddress& loopback) {
« no previous file with comments | « webrtc/base/socket_unittest.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698