summaryrefslogtreecommitdiffstats
path: root/net/socket/socket_test_util.cc
diff options
context:
space:
mode:
authormbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-11 22:04:22 +0000
committermbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-11 22:04:22 +0000
commit584460dac4ee02b146000be533fb4cc8cb2ab108 (patch)
tree1d13471bf7add3ff4d0bd1f6be678b31bdfa746a /net/socket/socket_test_util.cc
parent0e5a729239c4be751a5c582249b943243c5b3e60 (diff)
downloadchromium_src-584460dac4ee02b146000be533fb4cc8cb2ab108.zip
chromium_src-584460dac4ee02b146000be533fb4cc8cb2ab108.tar.gz
chromium_src-584460dac4ee02b146000be533fb4cc8cb2ab108.tar.bz2
Enable async IO completions on MockSockets through the
SocketDataProvider. This makes a few changes: - The SocketDataProvider::GetNextRead() is now allowed to return a result of ERR_IO_PENDING. Previously, this was just an error. Now, this informs the MockClientSocket using the SocketDataProvider that the Mock IO will be completely asynchronously. - MockClientSocket implements a new method called OnReadComplete(). This method is used to asynchronously complete a Read from the SocketDataProvider. The MockClientSocket, after receiving ERR_IO_PENDING from SocketDataProvider::GetNextRead will be blocked until this call is made. The rest of the patch is just refactoring the MockTCPClientSocket to implement a true async-io simulation. It needs to record the user buffer from the initial read, and then fill it when the data is provided. BUG=none TEST=<this is for better testing> Review URL: http://codereview.chromium.org/392003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31723 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/socket_test_util.cc')
-rw-r--r--net/socket/socket_test_util.cc100
1 files changed, 79 insertions, 21 deletions
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 8b7fcbf..239a81d 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -67,7 +67,10 @@ MockTCPClientSocket::MockTCPClientSocket(const net::AddressList& addresses,
data_(data),
read_offset_(0),
read_data_(true, net::ERR_UNEXPECTED),
- need_read_data_(true) {
+ need_read_data_(true),
+ pending_buf_(NULL),
+ pending_buf_len_(0),
+ pending_callback_(NULL) {
DCHECK(data_);
data_->Reset();
}
@@ -89,11 +92,77 @@ int MockTCPClientSocket::Read(net::IOBuffer* buf, int buf_len,
if (!IsConnected())
return net::ERR_UNEXPECTED;
+ // If the buffer is already in use, a read is already in progress!
+ DCHECK(pending_buf_ == NULL);
+
+ // Store our async IO data.
+ pending_buf_ = buf;
+ pending_buf_len_ = buf_len;
+ pending_callback_ = callback;
+
if (need_read_data_) {
read_data_ = data_->GetNextRead();
+ // ERR_IO_PENDING means that the SocketDataProvider is taking responsibility
+ // to complete the async IO manually later (via OnReadComplete).
+ if (read_data_.result == ERR_IO_PENDING) {
+ DCHECK(callback); // We need to be using async IO in this case.
+ return ERR_IO_PENDING;
+ }
need_read_data_ = false;
}
+
+ return CompleteRead();
+}
+
+int MockTCPClientSocket::Write(net::IOBuffer* buf, int buf_len,
+ net::CompletionCallback* callback) {
+ DCHECK(buf);
+ DCHECK_GT(buf_len, 0);
+
+ if (!IsConnected())
+ return net::ERR_UNEXPECTED;
+
+ std::string data(buf->data(), buf_len);
+ net::MockWriteResult write_result = data_->OnWrite(data);
+
+ if (write_result.async) {
+ RunCallbackAsync(callback, write_result.result);
+ return net::ERR_IO_PENDING;
+ }
+ return write_result.result;
+}
+
+void MockTCPClientSocket::OnReadComplete(const MockRead& data) {
+ // There must be a read pending.
+ DCHECK(pending_buf_);
+ // You can't complete a read with another ERR_IO_PENDING status code.
+ DCHECK_NE(ERR_IO_PENDING, data.result);
+ // Since we've been waiting for data, need_read_data_ should be true.
+ DCHECK(need_read_data_);
+ // In order to fire the callback, this IO needs to be marked as async.
+ DCHECK(data.async);
+
+ read_data_ = data;
+ need_read_data_ = false;
+
+ CompleteRead();
+}
+
+int MockTCPClientSocket::CompleteRead() {
+ DCHECK(pending_buf_);
+ DCHECK(pending_buf_len_ > 0);
+
+ // Save the pending async IO data and reset our |pending_| state.
+ net::IOBuffer* buf = pending_buf_;
+ int buf_len = pending_buf_len_;
+ net::CompletionCallback* callback = pending_callback_;
+ pending_buf_ = NULL;
+ pending_buf_len_ = 0;
+ pending_callback_ = NULL;
+
int result = read_data_.result;
+ DCHECK(result != ERR_IO_PENDING);
+
if (read_data_.data) {
if (read_data_.data_len - read_offset_ > 0) {
result = std::min(buf_len, read_data_.data_len - read_offset_);
@@ -107,31 +176,15 @@ int MockTCPClientSocket::Read(net::IOBuffer* buf, int buf_len,
result = 0; // EOF
}
}
+
if (read_data_.async) {
+ DCHECK(callback);
RunCallbackAsync(callback, result);
return net::ERR_IO_PENDING;
}
return result;
}
-int MockTCPClientSocket::Write(net::IOBuffer* buf, int buf_len,
- net::CompletionCallback* callback) {
- DCHECK(buf);
- DCHECK_GT(buf_len, 0);
-
- if (!IsConnected())
- return net::ERR_UNEXPECTED;
-
- std::string data(buf->data(), buf_len);
- net::MockWriteResult write_result = data_->OnWrite(data);
-
- if (write_result.async) {
- RunCallbackAsync(callback, write_result.result);
- return net::ERR_IO_PENDING;
- }
- return write_result.result;
-}
-
class MockSSLClientSocket::ConnectCallback :
public net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback> {
public:
@@ -212,7 +265,10 @@ int MockSSLClientSocket::Write(net::IOBuffer* buf, int buf_len,
}
MockRead StaticSocketDataProvider::GetNextRead() {
- return reads_[read_index_++];
+ MockRead rv = reads_[read_index_];
+ if (reads_[read_index_].data_len != 0)
+ read_index_++; // Don't advance past an EOF.
+ return rv;
}
MockWriteResult StaticSocketDataProvider::OnWrite(const std::string& data) {
@@ -298,8 +354,10 @@ MockSSLClientSocket* MockClientSocketFactory::GetMockSSLClientSocket(
ClientSocket* MockClientSocketFactory::CreateTCPClientSocket(
const AddressList& addresses) {
+ SocketDataProvider* data_provider = mock_data_.GetNext();
MockTCPClientSocket* socket =
- new MockTCPClientSocket(addresses, mock_data_.GetNext());
+ new MockTCPClientSocket(addresses, data_provider);
+ data_provider->set_socket(socket);
tcp_client_sockets_.push_back(socket);
return socket;
}