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

Unified Diff: net/socket/socket_test_util.cc

Issue 6341004: More net/ reordering. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Window gyp dependency Created 9 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 | « net/socket/socket_test_util.h ('k') | net/socket/socks_client_socket_pool.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/socket_test_util.cc
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index a7bebed41d8d257588265780a909d937a30e79e7..d5ee9ae6470d9623d84e42dd472f88457a409b8d 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -116,977 +116,981 @@ void DumpMockRead(const MockRead& r) {
} // namespace
-MockClientSocket::MockClientSocket(net::NetLog* net_log)
- : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
- connected_(false),
- net_log_(NetLog::Source(), net_log) {
-}
-
-void MockClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
- NOTREACHED();
+StaticSocketDataProvider::StaticSocketDataProvider()
+ : reads_(NULL),
+ read_index_(0),
+ read_count_(0),
+ writes_(NULL),
+ write_index_(0),
+ write_count_(0) {
}
-void MockClientSocket::GetSSLCertRequestInfo(
- net::SSLCertRequestInfo* cert_request_info) {
+StaticSocketDataProvider::StaticSocketDataProvider(MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count)
+ : reads_(reads),
+ read_index_(0),
+ read_count_(reads_count),
+ writes_(writes),
+ write_index_(0),
+ write_count_(writes_count) {
}
-SSLClientSocket::NextProtoStatus
-MockClientSocket::GetNextProto(std::string* proto) {
- proto->clear();
- return SSLClientSocket::kNextProtoUnsupported;
-}
+StaticSocketDataProvider::~StaticSocketDataProvider() {}
-void MockClientSocket::Disconnect() {
- connected_ = false;
+const MockRead& StaticSocketDataProvider::PeekRead() const {
+ DCHECK(!at_read_eof());
+ return reads_[read_index_];
}
-bool MockClientSocket::IsConnected() const {
- return connected_;
+const MockWrite& StaticSocketDataProvider::PeekWrite() const {
+ DCHECK(!at_write_eof());
+ return writes_[write_index_];
}
-bool MockClientSocket::IsConnectedAndIdle() const {
- return connected_;
+const MockRead& StaticSocketDataProvider::PeekRead(size_t index) const {
+ DCHECK_LT(index, read_count_);
+ return reads_[index];
}
-int MockClientSocket::GetPeerAddress(AddressList* address) const {
- return net::SystemHostResolverProc("localhost", ADDRESS_FAMILY_UNSPECIFIED,
- 0, address, NULL);
+const MockWrite& StaticSocketDataProvider::PeekWrite(size_t index) const {
+ DCHECK_LT(index, write_count_);
+ return writes_[index];
}
-void MockClientSocket::RunCallbackAsync(net::CompletionCallback* callback,
- int result) {
- MessageLoop::current()->PostTask(FROM_HERE,
- method_factory_.NewRunnableMethod(
- &MockClientSocket::RunCallback, callback, result));
+MockRead StaticSocketDataProvider::GetNextRead() {
+ DCHECK(!at_read_eof());
+ reads_[read_index_].time_stamp = base::Time::Now();
+ return reads_[read_index_++];
}
-void MockClientSocket::RunCallback(net::CompletionCallback* callback,
- int result) {
- if (callback)
- callback->Run(result);
-}
+MockWriteResult StaticSocketDataProvider::OnWrite(const std::string& data) {
+ if (!writes_) {
+ // Not using mock writes; succeed synchronously.
+ return MockWriteResult(false, data.length());
+ }
-MockTCPClientSocket::MockTCPClientSocket(const net::AddressList& addresses,
- net::NetLog* net_log,
- net::SocketDataProvider* data)
- : MockClientSocket(net_log),
- addresses_(addresses),
- data_(data),
- read_offset_(0),
- read_data_(false, net::ERR_UNEXPECTED),
- need_read_data_(true),
- peer_closed_connection_(false),
- pending_buf_(NULL),
- pending_buf_len_(0),
- pending_callback_(NULL),
- was_used_to_convey_data_(false) {
- DCHECK(data_);
- data_->Reset();
-}
+ DCHECK(!at_write_eof());
-int MockTCPClientSocket::Connect(net::CompletionCallback* callback) {
- if (connected_)
- return net::OK;
- connected_ = true;
- peer_closed_connection_ = false;
- if (data_->connect_data().async) {
- RunCallbackAsync(callback, data_->connect_data().result);
- return net::ERR_IO_PENDING;
+ // Check that what we are writing matches the expectation.
+ // Then give the mocked return value.
+ net::MockWrite* w = &writes_[write_index_++];
+ w->time_stamp = base::Time::Now();
+ int result = w->result;
+ if (w->data) {
+ // Note - we can simulate a partial write here. If the expected data
+ // is a match, but shorter than the write actually written, that is legal.
+ // Example:
+ // Application writes "foobarbaz" (9 bytes)
+ // Expected write was "foo" (3 bytes)
+ // This is a success, and we return 3 to the application.
+ std::string expected_data(w->data, w->data_len);
+ EXPECT_GE(data.length(), expected_data.length());
+ std::string actual_data(data.substr(0, w->data_len));
+ EXPECT_EQ(expected_data, actual_data);
+ if (expected_data != actual_data)
+ return MockWriteResult(false, net::ERR_UNEXPECTED);
+ if (result == net::OK)
+ result = w->data_len;
}
- return data_->connect_data().result;
+ return MockWriteResult(w->async, result);
}
-void MockTCPClientSocket::Disconnect() {
- MockClientSocket::Disconnect();
- pending_callback_ = NULL;
+void StaticSocketDataProvider::Reset() {
+ read_index_ = 0;
+ write_index_ = 0;
}
-bool MockTCPClientSocket::IsConnected() const {
- return connected_ && !peer_closed_connection_;
+DynamicSocketDataProvider::DynamicSocketDataProvider()
+ : short_read_limit_(0),
+ allow_unconsumed_reads_(false) {
}
-int MockTCPClientSocket::Read(net::IOBuffer* buf, int buf_len,
- net::CompletionCallback* callback) {
- if (!connected_)
- 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;
+DynamicSocketDataProvider::~DynamicSocketDataProvider() {}
- if (need_read_data_) {
- read_data_ = data_->GetNextRead();
- if (read_data_.result == ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ) {
- // This MockRead is just a marker to instruct us to set
- // peer_closed_connection_. Skip it and get the next one.
- read_data_ = data_->GetNextRead();
- peer_closed_connection_ = true;
- }
- // 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;
+MockRead DynamicSocketDataProvider::GetNextRead() {
+ if (reads_.empty())
+ return MockRead(false, ERR_UNEXPECTED);
+ MockRead result = reads_.front();
+ if (short_read_limit_ == 0 || result.data_len <= short_read_limit_) {
+ reads_.pop_front();
+ } else {
+ result.data_len = short_read_limit_;
+ reads_.front().data += result.data_len;
+ reads_.front().data_len -= result.data_len;
}
-
- return CompleteRead();
+ return result;
}
-int MockTCPClientSocket::Write(net::IOBuffer* buf, int buf_len,
- net::CompletionCallback* callback) {
- DCHECK(buf);
- DCHECK_GT(buf_len, 0);
-
- if (!connected_)
- return net::ERR_UNEXPECTED;
-
- std::string data(buf->data(), buf_len);
- net::MockWriteResult write_result = data_->OnWrite(data);
-
- was_used_to_convey_data_ = true;
+void DynamicSocketDataProvider::Reset() {
+ reads_.clear();
+}
- if (write_result.async) {
- RunCallbackAsync(callback, write_result.result);
- return net::ERR_IO_PENDING;
+void DynamicSocketDataProvider::SimulateRead(const char* data,
+ const size_t length) {
+ if (!allow_unconsumed_reads_) {
+ EXPECT_TRUE(reads_.empty()) << "Unconsumed read: " << reads_.front().data;
}
+ reads_.push_back(MockRead(true, data, length));
+}
- return write_result.result;
+DelayedSocketData::DelayedSocketData(
+ int write_delay, MockRead* reads, size_t reads_count,
+ MockWrite* writes, size_t writes_count)
+ : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
+ write_delay_(write_delay),
+ ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
+ DCHECK_GE(write_delay_, 0);
}
-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_);
+DelayedSocketData::DelayedSocketData(
+ const MockConnect& connect, int write_delay, MockRead* reads,
+ size_t reads_count, MockWrite* writes, size_t writes_count)
+ : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
+ write_delay_(write_delay),
+ ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
+ DCHECK_GE(write_delay_, 0);
+ set_connect_data(connect);
+}
- read_data_ = data;
- need_read_data_ = false;
+DelayedSocketData::~DelayedSocketData() {
+}
- // The caller is simulating that this IO completes right now. Don't
- // let CompleteRead() schedule a callback.
- read_data_.async = false;
+void DelayedSocketData::ForceNextRead() {
+ write_delay_ = 0;
+ CompleteRead();
+}
- net::CompletionCallback* callback = pending_callback_;
- int rv = CompleteRead();
- RunCallback(callback, rv);
+MockRead DelayedSocketData::GetNextRead() {
+ if (write_delay_ > 0)
+ return MockRead(true, ERR_IO_PENDING);
+ return StaticSocketDataProvider::GetNextRead();
}
-int MockTCPClientSocket::CompleteRead() {
- DCHECK(pending_buf_);
- DCHECK(pending_buf_len_ > 0);
+MockWriteResult DelayedSocketData::OnWrite(const std::string& data) {
+ MockWriteResult rv = StaticSocketDataProvider::OnWrite(data);
+ // Now that our write has completed, we can allow reads to continue.
+ if (!--write_delay_)
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ factory_.NewRunnableMethod(&DelayedSocketData::CompleteRead), 100);
+ return rv;
+}
- was_used_to_convey_data_ = true;
+void DelayedSocketData::Reset() {
+ set_socket(NULL);
+ factory_.RevokeAll();
+ StaticSocketDataProvider::Reset();
+}
- // 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;
+void DelayedSocketData::CompleteRead() {
+ if (socket())
+ socket()->OnReadComplete(GetNextRead());
+}
- int result = read_data_.result;
- DCHECK(result != ERR_IO_PENDING);
+OrderedSocketData::OrderedSocketData(
+ MockRead* reads, size_t reads_count, MockWrite* writes, size_t writes_count)
+ : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
+ sequence_number_(0), loop_stop_stage_(0), callback_(NULL),
+ blocked_(false), ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
+}
- if (read_data_.data) {
- if (read_data_.data_len - read_offset_ > 0) {
- result = std::min(buf_len, read_data_.data_len - read_offset_);
- memcpy(buf->data(), read_data_.data + read_offset_, result);
- read_offset_ += result;
- if (read_offset_ == read_data_.data_len) {
- need_read_data_ = true;
- read_offset_ = 0;
- }
+OrderedSocketData::OrderedSocketData(
+ const MockConnect& connect,
+ MockRead* reads, size_t reads_count,
+ MockWrite* writes, size_t writes_count)
+ : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
+ sequence_number_(0), loop_stop_stage_(0), callback_(NULL),
+ blocked_(false), ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
+ set_connect_data(connect);
+}
+
+void OrderedSocketData::EndLoop() {
+ // If we've already stopped the loop, don't do it again until we've advanced
+ // to the next sequence_number.
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ << ": EndLoop()";
+ if (loop_stop_stage_ > 0) {
+ const MockRead& next_read = StaticSocketDataProvider::PeekRead();
+ if ((next_read.sequence_number & ~MockRead::STOPLOOP) >
+ loop_stop_stage_) {
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
+ << ": Clearing stop index";
+ loop_stop_stage_ = 0;
} else {
- result = 0; // EOF
+ return;
}
}
+ // Record the sequence_number at which we stopped the loop.
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
+ << ": Posting Quit at read " << read_index();
+ loop_stop_stage_ = sequence_number_;
+ if (callback_)
+ callback_->RunWithParams(Tuple1<int>(ERR_IO_PENDING));
+}
- if (read_data_.async) {
- DCHECK(callback);
- RunCallbackAsync(callback, result);
- return net::ERR_IO_PENDING;
+MockRead OrderedSocketData::GetNextRead() {
+ factory_.RevokeAll();
+ blocked_ = false;
+ const MockRead& next_read = StaticSocketDataProvider::PeekRead();
+ if (next_read.sequence_number & MockRead::STOPLOOP)
+ EndLoop();
+ if ((next_read.sequence_number & ~MockRead::STOPLOOP) <=
+ sequence_number_++) {
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ - 1
+ << ": Read " << read_index();
+ DumpMockRead(next_read);
+ return StaticSocketDataProvider::GetNextRead();
}
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ - 1
+ << ": I/O Pending";
+ MockRead result = MockRead(true, ERR_IO_PENDING);
+ DumpMockRead(result);
+ blocked_ = true;
return result;
}
-DeterministicMockTCPClientSocket::DeterministicMockTCPClientSocket(
- net::NetLog* net_log, net::DeterministicSocketData* data)
- : MockClientSocket(net_log),
- write_pending_(false),
- write_callback_(NULL),
- write_result_(0),
- read_data_(),
- read_buf_(NULL),
- read_buf_len_(0),
- read_pending_(false),
- read_callback_(NULL),
- data_(data),
- was_used_to_convey_data_(false) {}
-
-void DeterministicMockTCPClientSocket::OnReadComplete(const MockRead& data) {}
-
-// TODO(erikchen): Support connect sequencing.
-int DeterministicMockTCPClientSocket::Connect(
- net::CompletionCallback* callback) {
- if (connected_)
- return net::OK;
- connected_ = true;
- if (data_->connect_data().async) {
- RunCallbackAsync(callback, data_->connect_data().result);
- return net::ERR_IO_PENDING;
+MockWriteResult OrderedSocketData::OnWrite(const std::string& data) {
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
+ << ": Write " << write_index();
+ DumpMockRead(PeekWrite());
+ ++sequence_number_;
+ if (blocked_) {
+ // TODO(willchan): This 100ms delay seems to work around some weirdness. We
+ // should probably fix the weirdness. One example is in SpdyStream,
+ // DoSendRequest() will return ERR_IO_PENDING, and there's a race. If the
+ // SYN_REPLY causes OnResponseReceived() to get called before
+ // SpdyStream::ReadResponseHeaders() is called, we hit a NOTREACHED().
+ MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ factory_.NewRunnableMethod(&OrderedSocketData::CompleteRead), 100);
}
- return data_->connect_data().result;
+ return StaticSocketDataProvider::OnWrite(data);
}
-void DeterministicMockTCPClientSocket::Disconnect() {
- MockClientSocket::Disconnect();
+void OrderedSocketData::Reset() {
+ NET_TRACE(INFO, " *** ") << "Stage "
+ << sequence_number_ << ": Reset()";
+ sequence_number_ = 0;
+ loop_stop_stage_ = 0;
+ set_socket(NULL);
+ factory_.RevokeAll();
+ StaticSocketDataProvider::Reset();
}
-bool DeterministicMockTCPClientSocket::IsConnected() const {
- return connected_;
+void OrderedSocketData::CompleteRead() {
+ if (socket()) {
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_;
+ socket()->OnReadComplete(GetNextRead());
+ }
}
-int DeterministicMockTCPClientSocket::Write(
- net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) {
- DCHECK(buf);
- DCHECK_GT(buf_len, 0);
+OrderedSocketData::~OrderedSocketData() {}
- if (!connected_)
- return net::ERR_UNEXPECTED;
+DeterministicSocketData::DeterministicSocketData(MockRead* reads,
+ size_t reads_count, MockWrite* writes, size_t writes_count)
+ : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
+ sequence_number_(0),
+ current_read_(),
+ current_write_(),
+ stopping_sequence_number_(0),
+ stopped_(false),
+ print_debug_(false) {}
- std::string data(buf->data(), buf_len);
- net::MockWriteResult write_result = data_->OnWrite(data);
+DeterministicSocketData::~DeterministicSocketData() {}
- if (write_result.async) {
- write_callback_ = callback;
- write_result_ = write_result.result;
- DCHECK(write_callback_ != NULL);
- write_pending_ = true;
- return net::ERR_IO_PENDING;
+void DeterministicSocketData::Run() {
+ SetStopped(false);
+ int counter = 0;
+ // Continue to consume data until all data has run out, or the stopped_ flag
+ // has been set. Consuming data requires two separate operations -- running
+ // the tasks in the message loop, and explicitly invoking the read/write
+ // callbacks (simulating network I/O). We check our conditions between each,
+ // since they can change in either.
+ while ((!at_write_eof() || !at_read_eof()) && !stopped()) {
+ if (counter % 2 == 0)
+ MessageLoop::current()->RunAllPending();
+ if (counter % 2 == 1) {
+ InvokeCallbacks();
+ }
+ counter++;
}
+ // We're done consuming new data, but it is possible there are still some
+ // pending callbacks which we expect to complete before returning.
+ while (socket_ && (socket_->write_pending() || socket_->read_pending()) &&
+ !stopped()) {
+ InvokeCallbacks();
+ MessageLoop::current()->RunAllPending();
+ }
+ SetStopped(false);
+}
- was_used_to_convey_data_ = true;
- write_pending_ = false;
- return write_result.result;
+void DeterministicSocketData::RunFor(int steps) {
+ StopAfter(steps);
+ Run();
}
-int DeterministicMockTCPClientSocket::Read(
- net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) {
- if (!connected_)
- return net::ERR_UNEXPECTED;
+void DeterministicSocketData::SetStop(int seq) {
+ DCHECK_LT(sequence_number_, seq);
+ stopping_sequence_number_ = seq;
+ stopped_ = false;
+}
- read_data_ = data_->GetNextRead();
- // The buffer should always be big enough to contain all the MockRead data. To
- // use small buffers, split the data into multiple MockReads.
- DCHECK_LE(read_data_.data_len, buf_len);
+void DeterministicSocketData::StopAfter(int seq) {
+ SetStop(sequence_number_ + seq);
+}
- read_buf_ = buf;
- read_buf_len_ = buf_len;
- read_callback_ = callback;
+MockRead DeterministicSocketData::GetNextRead() {
+ current_read_ = StaticSocketDataProvider::PeekRead();
+ EXPECT_LE(sequence_number_, current_read_.sequence_number);
- if (read_data_.async || (read_data_.result == ERR_IO_PENDING)) {
- read_pending_ = true;
- DCHECK(read_callback_);
- return ERR_IO_PENDING;
+ // Synchronous read while stopped is an error
+ if (stopped() && !current_read_.async) {
+ LOG(ERROR) << "Unable to perform synchronous IO while stopped";
+ return MockRead(false, ERR_UNEXPECTED);
}
- was_used_to_convey_data_ = true;
- return CompleteRead();
-}
+ // Async read which will be called back in a future step.
+ if (sequence_number_ < current_read_.sequence_number) {
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
+ << ": I/O Pending";
+ MockRead result = MockRead(false, ERR_IO_PENDING);
+ if (!current_read_.async) {
+ LOG(ERROR) << "Unable to perform synchronous read: "
+ << current_read_.sequence_number
+ << " at stage: " << sequence_number_;
+ result = MockRead(false, ERR_UNEXPECTED);
+ }
+ if (print_debug_)
+ DumpMockRead(result);
+ return result;
+ }
-void DeterministicMockTCPClientSocket::CompleteWrite() {
- was_used_to_convey_data_ = true;
- write_pending_ = false;
- write_callback_->Run(write_result_);
-}
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
+ << ": Read " << read_index();
+ if (print_debug_)
+ DumpMockRead(current_read_);
-int DeterministicMockTCPClientSocket::CompleteRead() {
- DCHECK_GT(read_buf_len_, 0);
- DCHECK_LE(read_data_.data_len, read_buf_len_);
- DCHECK(read_buf_);
+ // Increment the sequence number if IO is complete
+ if (!current_read_.async)
+ NextStep();
- was_used_to_convey_data_ = true;
+ DCHECK_NE(ERR_IO_PENDING, current_read_.result);
+ StaticSocketDataProvider::GetNextRead();
- if (read_data_.result == ERR_IO_PENDING)
- read_data_ = data_->GetNextRead();
- DCHECK_NE(ERR_IO_PENDING, read_data_.result);
- // If read_data_.async is true, we do not need to wait, since this is already
- // the callback. Therefore we don't even bother to check it.
- int result = read_data_.result;
+ return current_read_;
+}
- if (read_data_.data_len > 0) {
- DCHECK(read_data_.data);
- result = std::min(read_buf_len_, read_data_.data_len);
- memcpy(read_buf_->data(), read_data_.data, result);
+MockWriteResult DeterministicSocketData::OnWrite(const std::string& data) {
+ const MockWrite& next_write = StaticSocketDataProvider::PeekWrite();
+ current_write_ = next_write;
+
+ // Synchronous write while stopped is an error
+ if (stopped() && !next_write.async) {
+ LOG(ERROR) << "Unable to perform synchronous IO while stopped";
+ return MockWriteResult(false, ERR_UNEXPECTED);
}
- if (read_pending_) {
- read_pending_ = false;
- read_callback_->Run(result);
+ // Async write which will be called back in a future step.
+ if (sequence_number_ < next_write.sequence_number) {
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
+ << ": I/O Pending";
+ if (!next_write.async) {
+ LOG(ERROR) << "Unable to perform synchronous write: "
+ << next_write.sequence_number << " at stage: " << sequence_number_;
+ return MockWriteResult(false, ERR_UNEXPECTED);
+ }
+ } else {
+ NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
+ << ": Write " << write_index();
}
- return result;
+ if (print_debug_)
+ DumpMockRead(next_write);
+
+ // Move to the next step if I/O is synchronous, since the operation will
+ // complete when this method returns.
+ if (!next_write.async)
+ NextStep();
+
+ // This is either a sync write for this step, or an async write.
+ return StaticSocketDataProvider::OnWrite(data);
}
-class MockSSLClientSocket::ConnectCallback
- : public net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback> {
- public:
- ConnectCallback(MockSSLClientSocket *ssl_client_socket,
- net::CompletionCallback* user_callback,
- int rv)
- : ALLOW_THIS_IN_INITIALIZER_LIST(
- net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback>(
- this, &ConnectCallback::Wrapper)),
- ssl_client_socket_(ssl_client_socket),
- user_callback_(user_callback),
- rv_(rv) {
- }
+void DeterministicSocketData::Reset() {
+ NET_TRACE(INFO, " *** ") << "Stage "
+ << sequence_number_ << ": Reset()";
+ sequence_number_ = 0;
+ StaticSocketDataProvider::Reset();
+ NOTREACHED();
+}
- private:
- void Wrapper(int rv) {
- if (rv_ == net::OK)
- ssl_client_socket_->connected_ = true;
- user_callback_->Run(rv_);
- delete this;
+void DeterministicSocketData::InvokeCallbacks() {
+ if (socket_ && socket_->write_pending() &&
+ (current_write().sequence_number == sequence_number())) {
+ socket_->CompleteWrite();
+ NextStep();
+ return;
+ }
+ if (socket_ && socket_->read_pending() &&
+ (current_read().sequence_number == sequence_number())) {
+ socket_->CompleteRead();
+ NextStep();
+ return;
}
+}
- MockSSLClientSocket* ssl_client_socket_;
- net::CompletionCallback* user_callback_;
- int rv_;
-};
+void DeterministicSocketData::NextStep() {
+ // Invariant: Can never move *past* the stopping step.
+ DCHECK_LT(sequence_number_, stopping_sequence_number_);
+ sequence_number_++;
+ if (sequence_number_ == stopping_sequence_number_)
+ SetStopped(true);
+}
-MockSSLClientSocket::MockSSLClientSocket(
- net::ClientSocketHandle* transport_socket,
- const HostPortPair& host_port_pair,
- const net::SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info,
- net::SSLSocketDataProvider* data)
- : MockClientSocket(transport_socket->socket()->NetLog().net_log()),
- transport_(transport_socket),
- data_(data),
- is_npn_state_set_(false),
- new_npn_value_(false) {
- DCHECK(data_);
- delete ssl_host_info; // we take ownership but don't use it.
+MockClientSocketFactory::MockClientSocketFactory() {}
+
+MockClientSocketFactory::~MockClientSocketFactory() {}
+
+void MockClientSocketFactory::AddSocketDataProvider(
+ SocketDataProvider* data) {
+ mock_data_.Add(data);
}
-MockSSLClientSocket::~MockSSLClientSocket() {
- Disconnect();
+void MockClientSocketFactory::AddSSLSocketDataProvider(
+ SSLSocketDataProvider* data) {
+ mock_ssl_data_.Add(data);
}
-int MockSSLClientSocket::Connect(net::CompletionCallback* callback) {
- ConnectCallback* connect_callback = new ConnectCallback(
- this, callback, data_->connect.result);
- int rv = transport_->socket()->Connect(connect_callback);
- if (rv == net::OK) {
- delete connect_callback;
- if (data_->connect.result == net::OK)
- connected_ = true;
- if (data_->connect.async) {
- RunCallbackAsync(callback, data_->connect.result);
- return net::ERR_IO_PENDING;
- }
- return data_->connect.result;
- }
- return rv;
+void MockClientSocketFactory::ResetNextMockIndexes() {
+ mock_data_.ResetNextIndex();
+ mock_ssl_data_.ResetNextIndex();
}
-void MockSSLClientSocket::Disconnect() {
- MockClientSocket::Disconnect();
- if (transport_->socket() != NULL)
- transport_->socket()->Disconnect();
+MockTCPClientSocket* MockClientSocketFactory::GetMockTCPClientSocket(
+ size_t index) const {
+ DCHECK_LT(index, tcp_client_sockets_.size());
+ return tcp_client_sockets_[index];
}
-bool MockSSLClientSocket::IsConnected() const {
- return transport_->socket()->IsConnected();
+MockSSLClientSocket* MockClientSocketFactory::GetMockSSLClientSocket(
+ size_t index) const {
+ DCHECK_LT(index, ssl_client_sockets_.size());
+ return ssl_client_sockets_[index];
}
-bool MockSSLClientSocket::WasEverUsed() const {
- return transport_->socket()->WasEverUsed();
+ClientSocket* MockClientSocketFactory::CreateTCPClientSocket(
+ const AddressList& addresses,
+ net::NetLog* net_log,
+ const NetLog::Source& source) {
+ SocketDataProvider* data_provider = mock_data_.GetNext();
+ MockTCPClientSocket* socket =
+ new MockTCPClientSocket(addresses, net_log, data_provider);
+ data_provider->set_socket(socket);
+ tcp_client_sockets_.push_back(socket);
+ return socket;
}
-bool MockSSLClientSocket::UsingTCPFastOpen() const {
- return transport_->socket()->UsingTCPFastOpen();
+SSLClientSocket* MockClientSocketFactory::CreateSSLClientSocket(
+ ClientSocketHandle* transport_socket,
+ const HostPortPair& host_and_port,
+ const SSLConfig& ssl_config,
+ SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
+ DnsCertProvenanceChecker* dns_cert_checker) {
+ MockSSLClientSocket* socket =
+ new MockSSLClientSocket(transport_socket, host_and_port, ssl_config,
+ ssl_host_info, mock_ssl_data_.GetNext());
+ ssl_client_sockets_.push_back(socket);
+ return socket;
}
-int MockSSLClientSocket::Read(net::IOBuffer* buf, int buf_len,
- net::CompletionCallback* callback) {
- return transport_->socket()->Read(buf, buf_len, callback);
+MockClientSocket::MockClientSocket(net::NetLog* net_log)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
+ connected_(false),
+ net_log_(NetLog::Source(), net_log) {
}
-int MockSSLClientSocket::Write(net::IOBuffer* buf, int buf_len,
- net::CompletionCallback* callback) {
- return transport_->socket()->Write(buf, buf_len, callback);
+bool MockClientSocket::SetReceiveBufferSize(int32 size) {
+ return true;
}
-void MockSSLClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
- ssl_info->Reset();
+bool MockClientSocket::SetSendBufferSize(int32 size) {
+ return true;
}
-void MockSSLClientSocket::GetSSLCertRequestInfo(
- net::SSLCertRequestInfo* cert_request_info) {
- DCHECK(cert_request_info);
- if (data_->cert_request_info) {
- cert_request_info->host_and_port =
- data_->cert_request_info->host_and_port;
- cert_request_info->client_certs = data_->cert_request_info->client_certs;
- } else {
- cert_request_info->Reset();
- }
+void MockClientSocket::Disconnect() {
+ connected_ = false;
}
-SSLClientSocket::NextProtoStatus MockSSLClientSocket::GetNextProto(
- std::string* proto) {
- *proto = data_->next_proto;
- return data_->next_proto_status;
+bool MockClientSocket::IsConnected() const {
+ return connected_;
}
-bool MockSSLClientSocket::was_npn_negotiated() const {
- if (is_npn_state_set_)
- return new_npn_value_;
- return data_->was_npn_negotiated;
+bool MockClientSocket::IsConnectedAndIdle() const {
+ return connected_;
}
-bool MockSSLClientSocket::set_was_npn_negotiated(bool negotiated) {
- is_npn_state_set_ = true;
- return new_npn_value_ = negotiated;
+int MockClientSocket::GetPeerAddress(AddressList* address) const {
+ return net::SystemHostResolverProc("localhost", ADDRESS_FAMILY_UNSPECIFIED,
+ 0, address, NULL);
}
-StaticSocketDataProvider::StaticSocketDataProvider()
- : reads_(NULL),
- read_index_(0),
- read_count_(0),
- writes_(NULL),
- write_index_(0),
- write_count_(0) {
+const BoundNetLog& MockClientSocket::NetLog() const {
+ return net_log_;
}
-StaticSocketDataProvider::StaticSocketDataProvider(MockRead* reads,
- size_t reads_count,
- MockWrite* writes,
- size_t writes_count)
- : reads_(reads),
- read_index_(0),
- read_count_(reads_count),
- writes_(writes),
- write_index_(0),
- write_count_(writes_count) {
+void MockClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
+ NOTREACHED();
}
-StaticSocketDataProvider::~StaticSocketDataProvider() {}
+void MockClientSocket::GetSSLCertRequestInfo(
+ net::SSLCertRequestInfo* cert_request_info) {
+}
-MockRead StaticSocketDataProvider::GetNextRead() {
- DCHECK(!at_read_eof());
- reads_[read_index_].time_stamp = base::Time::Now();
- return reads_[read_index_++];
+SSLClientSocket::NextProtoStatus
+MockClientSocket::GetNextProto(std::string* proto) {
+ proto->clear();
+ return SSLClientSocket::kNextProtoUnsupported;
}
-MockWriteResult StaticSocketDataProvider::OnWrite(const std::string& data) {
- if (!writes_) {
- // Not using mock writes; succeed synchronously.
- return MockWriteResult(false, data.length());
- }
+MockClientSocket::~MockClientSocket() {}
- DCHECK(!at_write_eof());
-
- // Check that what we are writing matches the expectation.
- // Then give the mocked return value.
- net::MockWrite* w = &writes_[write_index_++];
- w->time_stamp = base::Time::Now();
- int result = w->result;
- if (w->data) {
- // Note - we can simulate a partial write here. If the expected data
- // is a match, but shorter than the write actually written, that is legal.
- // Example:
- // Application writes "foobarbaz" (9 bytes)
- // Expected write was "foo" (3 bytes)
- // This is a success, and we return 3 to the application.
- std::string expected_data(w->data, w->data_len);
- EXPECT_GE(data.length(), expected_data.length());
- std::string actual_data(data.substr(0, w->data_len));
- EXPECT_EQ(expected_data, actual_data);
- if (expected_data != actual_data)
- return MockWriteResult(false, net::ERR_UNEXPECTED);
- if (result == net::OK)
- result = w->data_len;
- }
- return MockWriteResult(w->async, result);
+void MockClientSocket::RunCallbackAsync(net::CompletionCallback* callback,
+ int result) {
+ MessageLoop::current()->PostTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &MockClientSocket::RunCallback, callback, result));
}
-const MockRead& StaticSocketDataProvider::PeekRead() const {
- DCHECK(!at_read_eof());
- return reads_[read_index_];
+void MockClientSocket::RunCallback(net::CompletionCallback* callback,
+ int result) {
+ if (callback)
+ callback->Run(result);
}
-const MockWrite& StaticSocketDataProvider::PeekWrite() const {
- DCHECK(!at_write_eof());
- return writes_[write_index_];
+MockTCPClientSocket::MockTCPClientSocket(const net::AddressList& addresses,
+ net::NetLog* net_log,
+ net::SocketDataProvider* data)
+ : MockClientSocket(net_log),
+ addresses_(addresses),
+ data_(data),
+ read_offset_(0),
+ read_data_(false, net::ERR_UNEXPECTED),
+ need_read_data_(true),
+ peer_closed_connection_(false),
+ pending_buf_(NULL),
+ pending_buf_len_(0),
+ pending_callback_(NULL),
+ was_used_to_convey_data_(false) {
+ DCHECK(data_);
+ data_->Reset();
}
-const MockRead& StaticSocketDataProvider::PeekRead(size_t index) const {
- DCHECK_LT(index, read_count_);
- return reads_[index];
-}
+int MockTCPClientSocket::Read(net::IOBuffer* buf, int buf_len,
+ net::CompletionCallback* callback) {
+ if (!connected_)
+ return net::ERR_UNEXPECTED;
-const MockWrite& StaticSocketDataProvider::PeekWrite(size_t index) const {
- DCHECK_LT(index, write_count_);
- return writes_[index];
-}
+ // If the buffer is already in use, a read is already in progress!
+ DCHECK(pending_buf_ == NULL);
-void StaticSocketDataProvider::Reset() {
- read_index_ = 0;
- write_index_ = 0;
-}
+ // Store our async IO data.
+ pending_buf_ = buf;
+ pending_buf_len_ = buf_len;
+ pending_callback_ = callback;
-DynamicSocketDataProvider::DynamicSocketDataProvider()
- : short_read_limit_(0),
- allow_unconsumed_reads_(false) {
+ if (need_read_data_) {
+ read_data_ = data_->GetNextRead();
+ if (read_data_.result == ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ) {
+ // This MockRead is just a marker to instruct us to set
+ // peer_closed_connection_. Skip it and get the next one.
+ read_data_ = data_->GetNextRead();
+ peer_closed_connection_ = true;
+ }
+ // 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();
}
-DynamicSocketDataProvider::~DynamicSocketDataProvider() {}
+int MockTCPClientSocket::Write(net::IOBuffer* buf, int buf_len,
+ net::CompletionCallback* callback) {
+ DCHECK(buf);
+ DCHECK_GT(buf_len, 0);
-MockRead DynamicSocketDataProvider::GetNextRead() {
- if (reads_.empty())
- return MockRead(false, ERR_UNEXPECTED);
- MockRead result = reads_.front();
- if (short_read_limit_ == 0 || result.data_len <= short_read_limit_) {
- reads_.pop_front();
- } else {
- result.data_len = short_read_limit_;
- reads_.front().data += result.data_len;
- reads_.front().data_len -= result.data_len;
+ if (!connected_)
+ return net::ERR_UNEXPECTED;
+
+ std::string data(buf->data(), buf_len);
+ net::MockWriteResult write_result = data_->OnWrite(data);
+
+ was_used_to_convey_data_ = true;
+
+ if (write_result.async) {
+ RunCallbackAsync(callback, write_result.result);
+ return net::ERR_IO_PENDING;
}
- return result;
-}
-void DynamicSocketDataProvider::Reset() {
- reads_.clear();
+ return write_result.result;
}
-void DynamicSocketDataProvider::SimulateRead(const char* data,
- const size_t length) {
- if (!allow_unconsumed_reads_) {
- EXPECT_TRUE(reads_.empty()) << "Unconsumed read: " << reads_.front().data;
+int MockTCPClientSocket::Connect(net::CompletionCallback* callback) {
+ if (connected_)
+ return net::OK;
+ connected_ = true;
+ peer_closed_connection_ = false;
+ if (data_->connect_data().async) {
+ RunCallbackAsync(callback, data_->connect_data().result);
+ return net::ERR_IO_PENDING;
}
- reads_.push_back(MockRead(true, data, length));
+ return data_->connect_data().result;
}
-DelayedSocketData::DelayedSocketData(
- int write_delay, MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count)
- : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
- write_delay_(write_delay),
- ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
- DCHECK_GE(write_delay_, 0);
+void MockTCPClientSocket::Disconnect() {
+ MockClientSocket::Disconnect();
+ pending_callback_ = NULL;
}
-DelayedSocketData::DelayedSocketData(
- const MockConnect& connect, int write_delay, MockRead* reads,
- size_t reads_count, MockWrite* writes, size_t writes_count)
- : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
- write_delay_(write_delay),
- ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
- DCHECK_GE(write_delay_, 0);
- set_connect_data(connect);
+bool MockTCPClientSocket::IsConnected() const {
+ return connected_ && !peer_closed_connection_;
}
-DelayedSocketData::~DelayedSocketData() {
+bool MockTCPClientSocket::IsConnectedAndIdle() const {
+ return IsConnected();
}
-MockRead DelayedSocketData::GetNextRead() {
- if (write_delay_ > 0)
- return MockRead(true, ERR_IO_PENDING);
- return StaticSocketDataProvider::GetNextRead();
+bool MockTCPClientSocket::WasEverUsed() const {
+ return was_used_to_convey_data_;
}
-MockWriteResult DelayedSocketData::OnWrite(const std::string& data) {
- MockWriteResult rv = StaticSocketDataProvider::OnWrite(data);
- // Now that our write has completed, we can allow reads to continue.
- if (!--write_delay_)
- MessageLoop::current()->PostDelayedTask(FROM_HERE,
- factory_.NewRunnableMethod(&DelayedSocketData::CompleteRead), 100);
- return rv;
+bool MockTCPClientSocket::UsingTCPFastOpen() const {
+ return false;
}
-void DelayedSocketData::Reset() {
- set_socket(NULL);
- factory_.RevokeAll();
- StaticSocketDataProvider::Reset();
-}
+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_);
-void DelayedSocketData::CompleteRead() {
- if (socket())
- socket()->OnReadComplete(GetNextRead());
-}
+ read_data_ = data;
+ need_read_data_ = false;
-void DelayedSocketData::ForceNextRead() {
- write_delay_ = 0;
- CompleteRead();
-}
+ // The caller is simulating that this IO completes right now. Don't
+ // let CompleteRead() schedule a callback.
+ read_data_.async = false;
-OrderedSocketData::OrderedSocketData(
- MockRead* reads, size_t reads_count, MockWrite* writes, size_t writes_count)
- : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
- sequence_number_(0), loop_stop_stage_(0), callback_(NULL),
- blocked_(false), ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
+ net::CompletionCallback* callback = pending_callback_;
+ int rv = CompleteRead();
+ RunCallback(callback, rv);
}
-OrderedSocketData::OrderedSocketData(
- const MockConnect& connect,
- MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count)
- : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
- sequence_number_(0), loop_stop_stage_(0), callback_(NULL),
- blocked_(false), ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
- set_connect_data(connect);
-}
+int MockTCPClientSocket::CompleteRead() {
+ DCHECK(pending_buf_);
+ DCHECK(pending_buf_len_ > 0);
-MockRead OrderedSocketData::GetNextRead() {
- factory_.RevokeAll();
- blocked_ = false;
- const MockRead& next_read = StaticSocketDataProvider::PeekRead();
- if (next_read.sequence_number & MockRead::STOPLOOP)
- EndLoop();
- if ((next_read.sequence_number & ~MockRead::STOPLOOP) <=
- sequence_number_++) {
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ - 1
- << ": Read " << read_index();
- DumpMockRead(next_read);
- return StaticSocketDataProvider::GetNextRead();
- }
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ - 1
- << ": I/O Pending";
- MockRead result = MockRead(true, ERR_IO_PENDING);
- DumpMockRead(result);
- blocked_ = true;
- return result;
-}
+ was_used_to_convey_data_ = true;
-MockWriteResult OrderedSocketData::OnWrite(const std::string& data) {
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
- << ": Write " << write_index();
- DumpMockRead(PeekWrite());
- ++sequence_number_;
- if (blocked_) {
- // TODO(willchan): This 100ms delay seems to work around some weirdness. We
- // should probably fix the weirdness. One example is in SpdyStream,
- // DoSendRequest() will return ERR_IO_PENDING, and there's a race. If the
- // SYN_REPLY causes OnResponseReceived() to get called before
- // SpdyStream::ReadResponseHeaders() is called, we hit a NOTREACHED().
- MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- factory_.NewRunnableMethod(&OrderedSocketData::CompleteRead), 100);
- }
- return StaticSocketDataProvider::OnWrite(data);
-}
+ // 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;
-void OrderedSocketData::Reset() {
- NET_TRACE(INFO, " *** ") << "Stage "
- << sequence_number_ << ": Reset()";
- sequence_number_ = 0;
- loop_stop_stage_ = 0;
- set_socket(NULL);
- factory_.RevokeAll();
- StaticSocketDataProvider::Reset();
-}
+ int result = read_data_.result;
+ DCHECK(result != ERR_IO_PENDING);
-void OrderedSocketData::EndLoop() {
- // If we've already stopped the loop, don't do it again until we've advanced
- // to the next sequence_number.
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ << ": EndLoop()";
- if (loop_stop_stage_ > 0) {
- const MockRead& next_read = StaticSocketDataProvider::PeekRead();
- if ((next_read.sequence_number & ~MockRead::STOPLOOP) >
- loop_stop_stage_) {
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
- << ": Clearing stop index";
- loop_stop_stage_ = 0;
+ if (read_data_.data) {
+ if (read_data_.data_len - read_offset_ > 0) {
+ result = std::min(buf_len, read_data_.data_len - read_offset_);
+ memcpy(buf->data(), read_data_.data + read_offset_, result);
+ read_offset_ += result;
+ if (read_offset_ == read_data_.data_len) {
+ need_read_data_ = true;
+ read_offset_ = 0;
+ }
} else {
- return;
+ result = 0; // EOF
}
}
- // Record the sequence_number at which we stopped the loop.
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
- << ": Posting Quit at read " << read_index();
- loop_stop_stage_ = sequence_number_;
- if (callback_)
- callback_->RunWithParams(Tuple1<int>(ERR_IO_PENDING));
-}
-void OrderedSocketData::CompleteRead() {
- if (socket()) {
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_;
- socket()->OnReadComplete(GetNextRead());
+ if (read_data_.async) {
+ DCHECK(callback);
+ RunCallbackAsync(callback, result);
+ return net::ERR_IO_PENDING;
}
+ return result;
}
-OrderedSocketData::~OrderedSocketData() {}
+DeterministicMockTCPClientSocket::DeterministicMockTCPClientSocket(
+ net::NetLog* net_log, net::DeterministicSocketData* data)
+ : MockClientSocket(net_log),
+ write_pending_(false),
+ write_callback_(NULL),
+ write_result_(0),
+ read_data_(),
+ read_buf_(NULL),
+ read_buf_len_(0),
+ read_pending_(false),
+ read_callback_(NULL),
+ data_(data),
+ was_used_to_convey_data_(false) {}
-DeterministicSocketData::DeterministicSocketData(MockRead* reads,
- size_t reads_count, MockWrite* writes, size_t writes_count)
- : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
- sequence_number_(0),
- current_read_(),
- current_write_(),
- stopping_sequence_number_(0),
- stopped_(false),
- print_debug_(false) {}
+DeterministicMockTCPClientSocket::~DeterministicMockTCPClientSocket() {}
-MockRead DeterministicSocketData::GetNextRead() {
- current_read_ = StaticSocketDataProvider::PeekRead();
- EXPECT_LE(sequence_number_, current_read_.sequence_number);
+void DeterministicMockTCPClientSocket::CompleteWrite() {
+ was_used_to_convey_data_ = true;
+ write_pending_ = false;
+ write_callback_->Run(write_result_);
+}
- // Synchronous read while stopped is an error
- if (stopped() && !current_read_.async) {
- LOG(ERROR) << "Unable to perform synchronous IO while stopped";
- return MockRead(false, ERR_UNEXPECTED);
- }
+int DeterministicMockTCPClientSocket::CompleteRead() {
+ DCHECK_GT(read_buf_len_, 0);
+ DCHECK_LE(read_data_.data_len, read_buf_len_);
+ DCHECK(read_buf_);
- // Async read which will be called back in a future step.
- if (sequence_number_ < current_read_.sequence_number) {
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
- << ": I/O Pending";
- MockRead result = MockRead(false, ERR_IO_PENDING);
- if (!current_read_.async) {
- LOG(ERROR) << "Unable to perform synchronous read: "
- << current_read_.sequence_number
- << " at stage: " << sequence_number_;
- result = MockRead(false, ERR_UNEXPECTED);
- }
- if (print_debug_)
- DumpMockRead(result);
- return result;
- }
+ was_used_to_convey_data_ = true;
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
- << ": Read " << read_index();
- if (print_debug_)
- DumpMockRead(current_read_);
+ if (read_data_.result == ERR_IO_PENDING)
+ read_data_ = data_->GetNextRead();
+ DCHECK_NE(ERR_IO_PENDING, read_data_.result);
+ // If read_data_.async is true, we do not need to wait, since this is already
+ // the callback. Therefore we don't even bother to check it.
+ int result = read_data_.result;
- // Increment the sequence number if IO is complete
- if (!current_read_.async)
- NextStep();
+ if (read_data_.data_len > 0) {
+ DCHECK(read_data_.data);
+ result = std::min(read_buf_len_, read_data_.data_len);
+ memcpy(read_buf_->data(), read_data_.data, result);
+ }
- DCHECK_NE(ERR_IO_PENDING, current_read_.result);
- StaticSocketDataProvider::GetNextRead();
+ if (read_pending_) {
+ read_pending_ = false;
+ read_callback_->Run(result);
+ }
- return current_read_;
+ return result;
}
-MockWriteResult DeterministicSocketData::OnWrite(const std::string& data) {
- const MockWrite& next_write = StaticSocketDataProvider::PeekWrite();
- current_write_ = next_write;
+int DeterministicMockTCPClientSocket::Write(
+ net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) {
+ DCHECK(buf);
+ DCHECK_GT(buf_len, 0);
- // Synchronous write while stopped is an error
- if (stopped() && !next_write.async) {
- LOG(ERROR) << "Unable to perform synchronous IO while stopped";
- return MockWriteResult(false, ERR_UNEXPECTED);
- }
+ if (!connected_)
+ return net::ERR_UNEXPECTED;
- // Async write which will be called back in a future step.
- if (sequence_number_ < next_write.sequence_number) {
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
- << ": I/O Pending";
- if (!next_write.async) {
- LOG(ERROR) << "Unable to perform synchronous write: "
- << next_write.sequence_number << " at stage: " << sequence_number_;
- return MockWriteResult(false, ERR_UNEXPECTED);
- }
- } else {
- NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_
- << ": Write " << write_index();
+ std::string data(buf->data(), buf_len);
+ net::MockWriteResult write_result = data_->OnWrite(data);
+
+ if (write_result.async) {
+ write_callback_ = callback;
+ write_result_ = write_result.result;
+ DCHECK(write_callback_ != NULL);
+ write_pending_ = true;
+ return net::ERR_IO_PENDING;
}
- if (print_debug_)
- DumpMockRead(next_write);
+ was_used_to_convey_data_ = true;
+ write_pending_ = false;
+ return write_result.result;
+}
- // Move to the next step if I/O is synchronous, since the operation will
- // complete when this method returns.
- if (!next_write.async)
- NextStep();
+int DeterministicMockTCPClientSocket::Read(
+ net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) {
+ if (!connected_)
+ return net::ERR_UNEXPECTED;
- // This is either a sync write for this step, or an async write.
- return StaticSocketDataProvider::OnWrite(data);
+ read_data_ = data_->GetNextRead();
+ // The buffer should always be big enough to contain all the MockRead data. To
+ // use small buffers, split the data into multiple MockReads.
+ DCHECK_LE(read_data_.data_len, buf_len);
+
+ read_buf_ = buf;
+ read_buf_len_ = buf_len;
+ read_callback_ = callback;
+
+ if (read_data_.async || (read_data_.result == ERR_IO_PENDING)) {
+ read_pending_ = true;
+ DCHECK(read_callback_);
+ return ERR_IO_PENDING;
+ }
+
+ was_used_to_convey_data_ = true;
+ return CompleteRead();
}
-void DeterministicSocketData::Reset() {
- NET_TRACE(INFO, " *** ") << "Stage "
- << sequence_number_ << ": Reset()";
- sequence_number_ = 0;
- StaticSocketDataProvider::Reset();
- NOTREACHED();
+// TODO(erikchen): Support connect sequencing.
+int DeterministicMockTCPClientSocket::Connect(
+ net::CompletionCallback* callback) {
+ if (connected_)
+ return net::OK;
+ connected_ = true;
+ if (data_->connect_data().async) {
+ RunCallbackAsync(callback, data_->connect_data().result);
+ return net::ERR_IO_PENDING;
+ }
+ return data_->connect_data().result;
}
-void DeterministicSocketData::RunFor(int steps) {
- StopAfter(steps);
- Run();
+void DeterministicMockTCPClientSocket::Disconnect() {
+ MockClientSocket::Disconnect();
}
-void DeterministicSocketData::Run() {
- SetStopped(false);
- int counter = 0;
- // Continue to consume data until all data has run out, or the stopped_ flag
- // has been set. Consuming data requires two separate operations -- running
- // the tasks in the message loop, and explicitly invoking the read/write
- // callbacks (simulating network I/O). We check our conditions between each,
- // since they can change in either.
- while ((!at_write_eof() || !at_read_eof()) && !stopped()) {
- if (counter % 2 == 0)
- MessageLoop::current()->RunAllPending();
- if (counter % 2 == 1) {
- InvokeCallbacks();
- }
- counter++;
- }
- // We're done consuming new data, but it is possible there are still some
- // pending callbacks which we expect to complete before returning.
- while (socket_ && (socket_->write_pending() || socket_->read_pending()) &&
- !stopped()) {
- InvokeCallbacks();
- MessageLoop::current()->RunAllPending();
- }
- SetStopped(false);
+bool DeterministicMockTCPClientSocket::IsConnected() const {
+ return connected_;
}
-void DeterministicSocketData::InvokeCallbacks() {
- if (socket_ && socket_->write_pending() &&
- (current_write().sequence_number == sequence_number())) {
- socket_->CompleteWrite();
- NextStep();
- return;
- }
- if (socket_ && socket_->read_pending() &&
- (current_read().sequence_number == sequence_number())) {
- socket_->CompleteRead();
- NextStep();
- return;
- }
+bool DeterministicMockTCPClientSocket::IsConnectedAndIdle() const {
+ return IsConnected();
}
-void DeterministicSocketData::NextStep() {
- // Invariant: Can never move *past* the stopping step.
- DCHECK_LT(sequence_number_, stopping_sequence_number_);
- sequence_number_++;
- if (sequence_number_ == stopping_sequence_number_)
- SetStopped(true);
+bool DeterministicMockTCPClientSocket::WasEverUsed() const {
+ return was_used_to_convey_data_;
}
+bool DeterministicMockTCPClientSocket::UsingTCPFastOpen() const {
+ return false;
+}
-MockClientSocketFactory::MockClientSocketFactory() {}
+void DeterministicMockTCPClientSocket::OnReadComplete(const MockRead& data) {}
-MockClientSocketFactory::~MockClientSocketFactory() {}
+class MockSSLClientSocket::ConnectCallback
+ : public net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback> {
+ public:
+ ConnectCallback(MockSSLClientSocket *ssl_client_socket,
+ net::CompletionCallback* user_callback,
+ int rv)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(
+ net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback>(
+ this, &ConnectCallback::Wrapper)),
+ ssl_client_socket_(ssl_client_socket),
+ user_callback_(user_callback),
+ rv_(rv) {
+ }
-void MockClientSocketFactory::AddSocketDataProvider(
- SocketDataProvider* data) {
- mock_data_.Add(data);
+ private:
+ void Wrapper(int rv) {
+ if (rv_ == net::OK)
+ ssl_client_socket_->connected_ = true;
+ user_callback_->Run(rv_);
+ delete this;
+ }
+
+ MockSSLClientSocket* ssl_client_socket_;
+ net::CompletionCallback* user_callback_;
+ int rv_;
+};
+
+MockSSLClientSocket::MockSSLClientSocket(
+ net::ClientSocketHandle* transport_socket,
+ const HostPortPair& host_port_pair,
+ const net::SSLConfig& ssl_config,
+ SSLHostInfo* ssl_host_info,
+ net::SSLSocketDataProvider* data)
+ : MockClientSocket(transport_socket->socket()->NetLog().net_log()),
+ transport_(transport_socket),
+ data_(data),
+ is_npn_state_set_(false),
+ new_npn_value_(false) {
+ DCHECK(data_);
+ delete ssl_host_info; // we take ownership but don't use it.
}
-void MockClientSocketFactory::AddSSLSocketDataProvider(
- SSLSocketDataProvider* data) {
- mock_ssl_data_.Add(data);
+MockSSLClientSocket::~MockSSLClientSocket() {
+ Disconnect();
}
-void MockClientSocketFactory::ResetNextMockIndexes() {
- mock_data_.ResetNextIndex();
- mock_ssl_data_.ResetNextIndex();
+int MockSSLClientSocket::Read(net::IOBuffer* buf, int buf_len,
+ net::CompletionCallback* callback) {
+ return transport_->socket()->Read(buf, buf_len, callback);
}
-MockTCPClientSocket* MockClientSocketFactory::GetMockTCPClientSocket(
- size_t index) const {
- DCHECK_LT(index, tcp_client_sockets_.size());
- return tcp_client_sockets_[index];
+int MockSSLClientSocket::Write(net::IOBuffer* buf, int buf_len,
+ net::CompletionCallback* callback) {
+ return transport_->socket()->Write(buf, buf_len, callback);
}
-MockSSLClientSocket* MockClientSocketFactory::GetMockSSLClientSocket(
- size_t index) const {
- DCHECK_LT(index, ssl_client_sockets_.size());
- return ssl_client_sockets_[index];
+int MockSSLClientSocket::Connect(net::CompletionCallback* callback) {
+ ConnectCallback* connect_callback = new ConnectCallback(
+ this, callback, data_->connect.result);
+ int rv = transport_->socket()->Connect(connect_callback);
+ if (rv == net::OK) {
+ delete connect_callback;
+ if (data_->connect.result == net::OK)
+ connected_ = true;
+ if (data_->connect.async) {
+ RunCallbackAsync(callback, data_->connect.result);
+ return net::ERR_IO_PENDING;
+ }
+ return data_->connect.result;
+ }
+ return rv;
}
-ClientSocket* MockClientSocketFactory::CreateTCPClientSocket(
- const AddressList& addresses,
- net::NetLog* net_log,
- const NetLog::Source& source) {
- SocketDataProvider* data_provider = mock_data_.GetNext();
- MockTCPClientSocket* socket =
- new MockTCPClientSocket(addresses, net_log, data_provider);
- data_provider->set_socket(socket);
- tcp_client_sockets_.push_back(socket);
- return socket;
+void MockSSLClientSocket::Disconnect() {
+ MockClientSocket::Disconnect();
+ if (transport_->socket() != NULL)
+ transport_->socket()->Disconnect();
}
-SSLClientSocket* MockClientSocketFactory::CreateSSLClientSocket(
- ClientSocketHandle* transport_socket,
- const HostPortPair& host_and_port,
- const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info,
- CertVerifier* cert_verifier,
- DnsCertProvenanceChecker* dns_cert_checker) {
- MockSSLClientSocket* socket =
- new MockSSLClientSocket(transport_socket, host_and_port, ssl_config,
- ssl_host_info, mock_ssl_data_.GetNext());
- ssl_client_sockets_.push_back(socket);
- return socket;
+bool MockSSLClientSocket::IsConnected() const {
+ return transport_->socket()->IsConnected();
}
-DeterministicMockClientSocketFactory::DeterministicMockClientSocketFactory() {}
+bool MockSSLClientSocket::WasEverUsed() const {
+ return transport_->socket()->WasEverUsed();
+}
-DeterministicMockClientSocketFactory::~DeterministicMockClientSocketFactory() {}
+bool MockSSLClientSocket::UsingTCPFastOpen() const {
+ return transport_->socket()->UsingTCPFastOpen();
+}
-void DeterministicMockClientSocketFactory::AddSocketDataProvider(
- DeterministicSocketData* data) {
- mock_data_.Add(data);
+void MockSSLClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
+ ssl_info->Reset();
}
-void DeterministicMockClientSocketFactory::AddSSLSocketDataProvider(
- SSLSocketDataProvider* data) {
- mock_ssl_data_.Add(data);
+void MockSSLClientSocket::GetSSLCertRequestInfo(
+ net::SSLCertRequestInfo* cert_request_info) {
+ DCHECK(cert_request_info);
+ if (data_->cert_request_info) {
+ cert_request_info->host_and_port =
+ data_->cert_request_info->host_and_port;
+ cert_request_info->client_certs = data_->cert_request_info->client_certs;
+ } else {
+ cert_request_info->Reset();
+ }
}
-void DeterministicMockClientSocketFactory::ResetNextMockIndexes() {
- mock_data_.ResetNextIndex();
- mock_ssl_data_.ResetNextIndex();
+SSLClientSocket::NextProtoStatus MockSSLClientSocket::GetNextProto(
+ std::string* proto) {
+ *proto = data_->next_proto;
+ return data_->next_proto_status;
}
-MockSSLClientSocket* DeterministicMockClientSocketFactory::
- GetMockSSLClientSocket(size_t index) const {
- DCHECK_LT(index, ssl_client_sockets_.size());
- return ssl_client_sockets_[index];
+bool MockSSLClientSocket::was_npn_negotiated() const {
+ if (is_npn_state_set_)
+ return new_npn_value_;
+ return data_->was_npn_negotiated;
}
-ClientSocket* DeterministicMockClientSocketFactory::CreateTCPClientSocket(
- const AddressList& addresses,
- net::NetLog* net_log,
- const net::NetLog::Source& source) {
- DeterministicSocketData* data_provider = mock_data().GetNext();
- DeterministicMockTCPClientSocket* socket =
- new DeterministicMockTCPClientSocket(net_log, data_provider);
- data_provider->set_socket(socket->AsWeakPtr());
- tcp_client_sockets().push_back(socket);
- return socket;
+bool MockSSLClientSocket::set_was_npn_negotiated(bool negotiated) {
+ is_npn_state_set_ = true;
+ return new_npn_value_ = negotiated;
}
-SSLClientSocket* DeterministicMockClientSocketFactory::CreateSSLClientSocket(
- ClientSocketHandle* transport_socket,
- const HostPortPair& host_and_port,
- const SSLConfig& ssl_config,
- SSLHostInfo* ssl_host_info,
- CertVerifier* cert_verifier,
- DnsCertProvenanceChecker* dns_cert_checker) {
- MockSSLClientSocket* socket =
- new MockSSLClientSocket(transport_socket, host_and_port, ssl_config,
- ssl_host_info, mock_ssl_data_.GetNext());
- ssl_client_sockets_.push_back(socket);
- return socket;
+void MockSSLClientSocket::OnReadComplete(const MockRead& data) {
+ NOTIMPLEMENTED();
}
TestSocketRequest::TestSocketRequest(
@@ -1215,6 +1219,8 @@ MockTCPClientSocketPool::MockTCPClientSocketPool(
cancel_count_(0) {
}
+MockTCPClientSocketPool::~MockTCPClientSocketPool() {}
+
int MockTCPClientSocketPool::RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
@@ -1247,7 +1253,56 @@ void MockTCPClientSocketPool::ReleaseSocket(const std::string& group_name,
delete socket;
}
-MockTCPClientSocketPool::~MockTCPClientSocketPool() {}
+DeterministicMockClientSocketFactory::DeterministicMockClientSocketFactory() {}
+
+DeterministicMockClientSocketFactory::~DeterministicMockClientSocketFactory() {}
+
+void DeterministicMockClientSocketFactory::AddSocketDataProvider(
+ DeterministicSocketData* data) {
+ mock_data_.Add(data);
+}
+
+void DeterministicMockClientSocketFactory::AddSSLSocketDataProvider(
+ SSLSocketDataProvider* data) {
+ mock_ssl_data_.Add(data);
+}
+
+void DeterministicMockClientSocketFactory::ResetNextMockIndexes() {
+ mock_data_.ResetNextIndex();
+ mock_ssl_data_.ResetNextIndex();
+}
+
+MockSSLClientSocket* DeterministicMockClientSocketFactory::
+ GetMockSSLClientSocket(size_t index) const {
+ DCHECK_LT(index, ssl_client_sockets_.size());
+ return ssl_client_sockets_[index];
+}
+
+ClientSocket* DeterministicMockClientSocketFactory::CreateTCPClientSocket(
+ const AddressList& addresses,
+ net::NetLog* net_log,
+ const net::NetLog::Source& source) {
+ DeterministicSocketData* data_provider = mock_data().GetNext();
+ DeterministicMockTCPClientSocket* socket =
+ new DeterministicMockTCPClientSocket(net_log, data_provider);
+ data_provider->set_socket(socket->AsWeakPtr());
+ tcp_client_sockets().push_back(socket);
+ return socket;
+}
+
+SSLClientSocket* DeterministicMockClientSocketFactory::CreateSSLClientSocket(
+ ClientSocketHandle* transport_socket,
+ const HostPortPair& host_and_port,
+ const SSLConfig& ssl_config,
+ SSLHostInfo* ssl_host_info,
+ CertVerifier* cert_verifier,
+ DnsCertProvenanceChecker* dns_cert_checker) {
+ MockSSLClientSocket* socket =
+ new MockSSLClientSocket(transport_socket, host_and_port, ssl_config,
+ ssl_host_info, mock_ssl_data_.GetNext());
+ ssl_client_sockets_.push_back(socket);
+ return socket;
+}
MockSOCKSClientSocketPool::MockSOCKSClientSocketPool(
int max_sockets,
@@ -1259,6 +1314,8 @@ MockSOCKSClientSocketPool::MockSOCKSClientSocketPool(
tcp_pool_(tcp_pool) {
}
+MockSOCKSClientSocketPool::~MockSOCKSClientSocketPool() {}
+
int MockSOCKSClientSocketPool::RequestSocket(const std::string& group_name,
const void* socket_params,
RequestPriority priority,
@@ -1280,8 +1337,6 @@ void MockSOCKSClientSocketPool::ReleaseSocket(const std::string& group_name,
return tcp_pool_->ReleaseSocket(group_name, socket, id);
}
-MockSOCKSClientSocketPool::~MockSOCKSClientSocketPool() {}
-
const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
const int kSOCKS5GreetRequestLength = arraysize(kSOCKS5GreetRequest);
« no previous file with comments | « net/socket/socket_test_util.h ('k') | net/socket/socks_client_socket_pool.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698