| 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);
|
|
|
|
|