diff options
author | erikchen@google.com <erikchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-18 18:33:27 +0000 |
---|---|---|
committer | erikchen@google.com <erikchen@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-18 18:33:27 +0000 |
commit | 3b78284325c04007a09ba8b47ac2980997e39e1d (patch) | |
tree | 10c1d14f07aa4c43f133820d7cf561071838e66e | |
parent | cce6f1b3b3d54334bf116084fadfe5b828c87227 (diff) | |
download | chromium_src-3b78284325c04007a09ba8b47ac2980997e39e1d.zip chromium_src-3b78284325c04007a09ba8b47ac2980997e39e1d.tar.gz chromium_src-3b78284325c04007a09ba8b47ac2980997e39e1d.tar.bz2 |
Added a new MockSocket that enforces ordering of reads/writes.
Re-enabled two broken SPDY tests, using new MockSocket. All SPDY tests should eventually convert to using this new object.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/3179016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56560 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/socket/socket_test_util.cc | 263 | ||||
-rw-r--r-- | net/socket/socket_test_util.h | 163 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream_unittest.cc | 2 | ||||
-rw-r--r-- | net/spdy/spdy_network_transaction_unittest.cc | 95 | ||||
-rw-r--r-- | net/spdy/spdy_session_unittest.cc | 4 | ||||
-rw-r--r-- | net/spdy/spdy_stream_unittest.cc | 2 | ||||
-rw-r--r-- | net/spdy/spdy_test_util.cc | 14 | ||||
-rw-r--r-- | net/spdy/spdy_test_util.h | 27 |
8 files changed, 530 insertions, 40 deletions
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 1cce947..069c293 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc @@ -312,6 +312,120 @@ int MockTCPClientSocket::CompleteRead() { 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) {} + +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; + } + return data_->connect_data().result; +} + +void DeterministicMockTCPClientSocket::Disconnect() { + MockClientSocket::Disconnect(); +} + +bool DeterministicMockTCPClientSocket::IsConnected() const { + return connected_; +} + +int DeterministicMockTCPClientSocket::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); + + if (write_result.async) { + write_callback_ = callback; + write_result_ = write_result.result; + DCHECK(write_callback_ != NULL); + write_pending_ = true; + return net::ERR_IO_PENDING; + } + write_pending_ = false; + return write_result.result; +} + +int DeterministicMockTCPClientSocket::Read( + net::IOBuffer* buf, int buf_len, net::CompletionCallback* callback) { + if (!connected_) + return net::ERR_UNEXPECTED; + + 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; + } + + return CompleteRead(); +} + +void DeterministicMockTCPClientSocket::CompleteWrite(){ + write_pending_ = false; + write_callback_->Run(write_result_); +} + +int DeterministicMockTCPClientSocket::CompleteRead() { + DCHECK_GT(read_buf_len_, 0); + DCHECK_LE(read_data_.data_len, read_buf_len_); + DCHECK(read_buf_); + + 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; + + 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); + } else { + result = 0; + } + + if (read_pending_) { + read_pending_ = false; + read_callback_->Run(result); + } + + return result; +} + class MockSSLClientSocket::ConnectCallback : public net::CompletionCallbackImpl<MockSSLClientSocket::ConnectCallback> { public: @@ -650,6 +764,113 @@ void OrderedSocketData::CompleteRead() { } } +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_(), + next_read_seq_(0), + stopping_sequence_number_(1<<31), + stopped_(false), + print_debug_(false) {} + +MockRead DeterministicSocketData::GetNextRead() { + const MockRead& next_read = StaticSocketDataProvider::PeekRead(); + EXPECT_LE(sequence_number_, next_read.sequence_number); + current_read_ = next_read; + next_read_seq_ = current_read_.sequence_number; + if (sequence_number_ >= stopping_sequence_number_) { + SetStopped(true); + NET_TRACE(INFO, " *** ") << "Force Stop. I/O Pending on read. Stage " + << sequence_number_; + MockRead result = MockRead(false, ERR_IO_PENDING); + if (print_debug_) + DumpMockRead(result); + return result; + } + if (sequence_number_ < next_read.sequence_number) { + NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ + << ": I/O Pending"; + MockRead result = MockRead(false, ERR_IO_PENDING); + if (print_debug_) + DumpMockRead(result); + return result; + } + + NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ + << ": Read " << read_index(); + if (print_debug_) + DumpMockRead(next_read); + sequence_number_++; + StaticSocketDataProvider::GetNextRead(); + if (current_read_.result == ERR_IO_PENDING) + current_read_ = StaticSocketDataProvider::GetNextRead(); + + if (!at_read_eof()) + next_read_seq_ = PeekRead().sequence_number; + + return next_read; +} + +MockWriteResult DeterministicSocketData::OnWrite(const std::string& data) { + NET_TRACE(INFO, " *** ") << "Stage " << sequence_number_ + << ": Write " << write_index(); + const MockWrite& next_write = StaticSocketDataProvider::PeekWrite(); + DCHECK_LE(next_write.sequence_number, sequence_number_); + if (print_debug_) + DumpMockRead(next_write); + ++sequence_number_; + current_write_ = next_write; + return StaticSocketDataProvider::OnWrite(data); +} + +void DeterministicSocketData::Reset(){ + NET_TRACE(INFO, " *** ") << "Stage " + << sequence_number_ << ": Reset()"; + sequence_number_ = 0; + StaticSocketDataProvider::Reset(); + NOTREACHED(); +} + +void DeterministicSocketData::Run(){ + 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); +} + +void DeterministicSocketData::InvokeCallbacks(){ + if (socket_ && socket_->write_pending() && + (current_write().sequence_number == sequence_number())) { + socket_->CompleteWrite(); + return; + } + if (socket_ && socket_->read_pending() && + (next_read_seq() == sequence_number())) { + socket_->CompleteRead(); + return; + } +} + void MockClientSocketFactory::AddSocketDataProvider( SocketDataProvider* data) { mock_data_.Add(data); @@ -698,6 +919,48 @@ SSLClientSocket* MockClientSocketFactory::CreateSSLClientSocket( return socket; } +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) { + 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 std::string& hostname, + const SSLConfig& ssl_config) { + MockSSLClientSocket* socket = + new MockSSLClientSocket(transport_socket, hostname, ssl_config, + mock_ssl_data_.GetNext()); + ssl_client_sockets_.push_back(socket); + return socket; +} + int TestSocketRequest::WaitForResult() { return callback_.WaitForResult(); } diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 9367349..0904dbe 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h @@ -17,6 +17,7 @@ #include "base/scoped_ptr.h" #include "base/scoped_vector.h" #include "base/string16.h" +#include "base/weak_ptr.h" #include "net/base/address_list.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -168,6 +169,7 @@ class StaticSocketDataProvider : public SocketDataProvider { write_index_(0), write_count_(writes_count) { } + virtual ~StaticSocketDataProvider() {} // SocketDataProvider methods: virtual MockRead GetNextRead(); @@ -343,6 +345,89 @@ class OrderedSocketData : public StaticSocketDataProvider, ScopedRunnableMethodFactory<OrderedSocketData> factory_; }; +class DeterministicMockTCPClientSocket; + +// This class gives the user full control over the mock socket reads and writes, +// including the timing of the callbacks. By default, synchronous reads and +// writes will force the callback for that read or write to complete before +// allowing another read or write to finish. +// +// Sequence numbers are preserved across both reads and writes. There should be +// no gaps in sequence numbers, and no repeated sequence numbers. i.e. +// MockWrite writes[] = { +// MockWrite(true, "first write", length, 0), +// MockWrite(false, "second write", length, 3), +// }; +// +// MockRead reads[] = { +// MockRead(false, "first read", length, 1) +// MockRead(false, "second read", length, 2) +// }; +// Example control flow: +// The first write completes. A call to read() returns ERR_IO_PENDING, since the +// first write's callback has not happened yet. The first write's callback is +// called. Now the first read's callback will be called. A call to write() will +// succeed, because the write() API requires this, but the callback will not be +// called until the second read has completed and its callback called. +class DeterministicSocketData : public StaticSocketDataProvider, + public base::RefCounted<DeterministicSocketData> { + public: + // |reads| the list of MockRead completions. + // |writes| the list of MockWrite completions. + DeterministicSocketData(MockRead* reads, size_t reads_count, + MockWrite* writes, size_t writes_count); + + // |connect| the result for the connect phase. + // |reads| the list of MockRead completions. + // |writes| the list of MockWrite completions. + DeterministicSocketData(const MockConnect& connect, + MockRead* reads, size_t reads_count, + MockWrite* writes, size_t writes_count); + + // When the socket calls Read(), that calls GetNextRead(), and expects either + // ERR_IO_PENDING or data. + virtual MockRead GetNextRead(); + + // When the socket calls Write(), it always completes synchronously. OnWrite() + // checks to make sure the written data matches the expected data. The + // callback will not be invoked until its sequence number is reached. + virtual MockWriteResult OnWrite(const std::string& data); + + virtual void Reset(); + + // Consume all the data up to the give stop point (via SetStop()). + void Run(); + + // Stop when Read() is about to consume a MockRead with sequence_number >= + // seq. Instead feed ERR_IO_PENDING to Read(). + virtual void SetStop(int seq) { stopping_sequence_number_ = seq; } + + void CompleteRead(); + bool stopped() const { return stopped_; } + void SetStopped(bool val) { stopped_ = val; } + MockRead& current_read() { return current_read_; } + MockRead& current_write() { return current_write_; } + int next_read_seq() const { return next_read_seq_; } + int sequence_number() const { return sequence_number_; } + void set_socket(base::WeakPtr<DeterministicMockTCPClientSocket> socket) { + socket_ = socket; + } + + private: + // Invoke the read and write callbacks, if the timing is appropriate. + void InvokeCallbacks(); + + int sequence_number_; + MockRead current_read_; + MockWrite current_write_; + int next_read_seq_; + int stopping_sequence_number_; + bool stopped_; + base::WeakPtr<DeterministicMockTCPClientSocket> socket_; + bool print_debug_; +}; + + // Holds an array of SocketDataProvider elements. As Mock{TCP,SSL}ClientSocket // objects get instantiated, they take their data from the i'th element of this // array. @@ -404,6 +489,12 @@ class MockClientSocketFactory : public ClientSocketFactory { ClientSocketHandle* transport_socket, const std::string& hostname, const SSLConfig& ssl_config); + SocketDataProviderArray<SocketDataProvider>& mock_data() { + return mock_data_; + } + std::vector<MockTCPClientSocket*>& tcp_client_sockets() { + return tcp_client_sockets_; + } private: SocketDataProviderArray<SocketDataProvider> mock_data_; @@ -417,7 +508,6 @@ class MockClientSocketFactory : public ClientSocketFactory { class MockClientSocket : public net::SSLClientSocket { public: explicit MockClientSocket(net::NetLog* net_log); - // ClientSocket methods: virtual int Connect(net::CompletionCallback* callback) = 0; virtual void Disconnect(); @@ -448,6 +538,7 @@ class MockClientSocket : public net::SSLClientSocket { virtual void OnReadComplete(const MockRead& data) = 0; protected: + virtual ~MockClientSocket() {} void RunCallbackAsync(net::CompletionCallback* callback, int result); void RunCallback(net::CompletionCallback*, int result); @@ -501,6 +592,40 @@ class MockTCPClientSocket : public MockClientSocket { net::CompletionCallback* pending_callback_; }; +class DeterministicMockTCPClientSocket : public MockClientSocket, + public base::SupportsWeakPtr<DeterministicMockTCPClientSocket> { + public: + DeterministicMockTCPClientSocket(net::NetLog* net_log, + net::DeterministicSocketData* data); + virtual int Write(net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback); + virtual int Read(net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback); + virtual void CompleteWrite(); + virtual int CompleteRead(); + virtual void OnReadComplete(const MockRead& data); + + virtual int Connect(net::CompletionCallback* callback); + virtual void Disconnect(); + virtual bool IsConnected() const; + virtual bool IsConnectedAndIdle() const { return IsConnected(); } + bool write_pending() { return write_pending_; } + bool read_pending() { return read_pending_; } + + private: + bool write_pending_; + net::CompletionCallback* write_callback_; + int write_result_; + + net::MockRead read_data_; + + net::IOBuffer* read_buf_; + int read_buf_len_; + bool read_pending_; + net::CompletionCallback* read_callback_; + net::DeterministicSocketData* data_; +}; + class MockSSLClientSocket : public MockClientSocket { public: MockSSLClientSocket( @@ -659,13 +784,47 @@ class MockTCPClientSocketPool : public TCPClientSocketPool { private: ClientSocketFactory* client_socket_factory_; + ScopedVector<MockConnectJob> job_list_; int release_count_; int cancel_count_; - ScopedVector<MockConnectJob> job_list_; DISALLOW_COPY_AND_ASSIGN(MockTCPClientSocketPool); }; +class DeterministicMockClientSocketFactory : public ClientSocketFactory { + public: + void AddSocketDataProvider(DeterministicSocketData* socket); + void AddSSLSocketDataProvider(SSLSocketDataProvider* socket); + void ResetNextMockIndexes(); + + // Return |index|-th MockSSLClientSocket (starting from 0) that the factory + // created. + MockSSLClientSocket* GetMockSSLClientSocket(size_t index) const; + + // ClientSocketFactory + virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses, + NetLog* net_log); + virtual SSLClientSocket* CreateSSLClientSocket( + ClientSocketHandle* transport_socket, + const std::string& hostname, + const SSLConfig& ssl_config); + + SocketDataProviderArray<DeterministicSocketData>& mock_data() { + return mock_data_; + } + std::vector<DeterministicMockTCPClientSocket*>& tcp_client_sockets() { + return tcp_client_sockets_; + } + + private: + SocketDataProviderArray<DeterministicSocketData> mock_data_; + SocketDataProviderArray<SSLSocketDataProvider> mock_ssl_data_; + + // Store pointers to handed out sockets in case the test wants to get them. + std::vector<DeterministicMockTCPClientSocket*> tcp_client_sockets_; + std::vector<MockSSLClientSocket*> ssl_client_sockets_; +}; + class MockSOCKSClientSocketPool : public SOCKSClientSocketPool { public: MockSOCKSClientSocketPool( diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index 1287820..5af7d52 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -27,7 +27,7 @@ class SpdyHttpStreamTest : public testing::Test { HostPortPair& host_port_pair) { HostPortProxyPair pair(host_port_pair, ""); data_ = new OrderedSocketData(reads, reads_count, writes, writes_count); - session_deps_.socket_factory.AddSocketDataProvider(data_.get()); + session_deps_.socket_factory->AddSocketDataProvider(data_.get()); http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); session_ = http_session_->spdy_session_pool()-> Get(pair, http_session_.get(), BoundNetLog()); diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index ca4f56c..a4bd90d 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc @@ -66,7 +66,8 @@ class SpdyNetworkTransactionTest session_(SpdySessionDependencies::SpdyCreateSession( session_deps_.get())), log_(log), - test_type_(test_type) { + test_type_(test_type), + deterministic_(false) { switch (test_type_) { case SPDYNOSSL: case SPDYSSL: @@ -80,6 +81,12 @@ class SpdyNetworkTransactionTest } } + void SetDeterministic() { + session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( + session_deps_.get()); + deterministic_ = true; + } + void RunPreTestSetup() { if (!session_deps_.get()) session_deps_.reset(new SpdySessionDependencies()); @@ -190,6 +197,7 @@ class SpdyNetworkTransactionTest } void AddData(StaticSocketDataProvider* data) { + DCHECK(!deterministic_); data_vector_.push_back(data); linked_ptr<SSLSocketDataProvider> ssl_( new SSLSocketDataProvider(true, OK)); @@ -200,14 +208,36 @@ class SpdyNetworkTransactionTest } ssl_vector_.push_back(ssl_); if(test_type_ == SPDYNPN || test_type_ == SPDYSSL) - session_deps_->socket_factory.AddSSLSocketDataProvider(ssl_.get()); - session_deps_->socket_factory.AddSocketDataProvider(data); + session_deps_->socket_factory->AddSSLSocketDataProvider(ssl_.get()); + session_deps_->socket_factory->AddSocketDataProvider(data); + } + + void AddDeterministicData(DeterministicSocketData* data) { + DCHECK(deterministic_); + data_vector_.push_back(data); + linked_ptr<SSLSocketDataProvider> ssl_( + new SSLSocketDataProvider(true, OK)); + if (test_type_ == SPDYNPN) { + ssl_->next_proto_status = SSLClientSocket::kNextProtoNegotiated; + ssl_->next_proto = "spdy/2"; + ssl_->was_npn_negotiated = true; + } + ssl_vector_.push_back(ssl_); + if(test_type_ == SPDYNPN || test_type_ == SPDYSSL) + session_deps_->deterministic_socket_factory-> + AddSSLSocketDataProvider(ssl_.get()); + session_deps_->deterministic_socket_factory->AddSocketDataProvider(data); } // This can only be called after RunPreTestSetup. It adds a Data Provider, // but not a corresponding SSL data provider void AddDataNoSSL(StaticSocketDataProvider* data) { - session_deps_->socket_factory.AddSocketDataProvider(data); + DCHECK(!deterministic_); + session_deps_->socket_factory->AddSocketDataProvider(data); + } + void AddDataNoSSL(DeterministicSocketData* data) { + DCHECK(deterministic_); + session_deps_->deterministic_socket_factory->AddSocketDataProvider(data); } void SetSession(const scoped_refptr<HttpNetworkSession>& session) { @@ -239,6 +269,7 @@ class SpdyNetworkTransactionTest const BoundNetLog& log_; SpdyNetworkTransactionTestTypes test_type_; int port_; + bool deterministic_; }; void ConnectStatusHelperWithExpectedStatus(const MockRead& status, @@ -1274,38 +1305,42 @@ TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) { // The client upon cancellation tries to send a RST_STREAM frame. The mock // socket causes the TCP write to return zero. This test checks that the client // tries to queue up the RST_STREAM frame again. -TEST_P(SpdyNetworkTransactionTest, DISABLED_SocketWriteReturnsZero) { +TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) { scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); scoped_ptr<spdy::SpdyFrame> rst( ConstructSpdyRstStream(1, spdy::CANCEL)); MockWrite writes[] = { - CreateMockWrite(*req.get(), 1), - MockWrite(true, 0, 0, 3), - CreateMockWrite(*rst.get(), 4), + CreateMockWrite(*req.get(), 0, false), + MockWrite(false, 0, 0, 2), + CreateMockWrite(*rst.get(), 3, false), }; scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); MockRead reads[] = { - CreateMockRead(*resp.get(), 2), - MockRead(true, 0, 0, 5) // EOF + CreateMockRead(*resp.get(), 1, false), + MockRead(false, 0, 0, 4) // EOF }; - scoped_refptr<OrderedSocketData> data( - new OrderedSocketData(reads, arraysize(reads), + scoped_refptr<DeterministicSocketData> data( + new DeterministicSocketData(reads, arraysize(reads), writes, arraysize(writes))); NormalSpdyTransactionHelper helper(CreateGetRequest(), BoundNetLog(), GetParam()); - helper.AddData(data.get()); + helper.SetDeterministic(); helper.RunPreTestSetup(); + helper.AddDeterministicData(data.get()); HttpNetworkTransaction* trans = helper.trans(); TestCompletionCallback callback; int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); + + data->SetStop(2); + data->Run(); helper.ResetTrans(); - MessageLoop::current()->RunAllPending(); - data->CompleteRead(); + data->SetStop(20); + data->Run(); + helper.VerifyDataConsumed(); } @@ -1687,42 +1722,44 @@ TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) { } // Verify that the client sends a Rst Frame upon cancelling the stream. -TEST_P(SpdyNetworkTransactionTest, DISABLED_CancelledTransactionSendRst) { +TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) { scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); scoped_ptr<spdy::SpdyFrame> rst( ConstructSpdyRstStream(1, spdy::CANCEL)); MockWrite writes[] = { - CreateMockWrite(*req, 1), - CreateMockWrite(*rst, 3), + CreateMockWrite(*req, 0, false), + CreateMockWrite(*rst, 2, false), }; scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(true, 0, 0, 4) // EOF + CreateMockRead(*resp, 1, false), + MockRead(false, 0, 0, 3) // EOF }; - scoped_refptr<OrderedSocketData> data( - new OrderedSocketData(reads, arraysize(reads), + scoped_refptr<DeterministicSocketData> data( + new DeterministicSocketData(reads, arraysize(reads), writes, arraysize(writes))); NormalSpdyTransactionHelper helper(CreateGetRequest(), BoundNetLog(), GetParam()); + helper.SetDeterministic(); helper.RunPreTestSetup(); - helper.AddData(data.get()); + helper.AddDeterministicData(data.get()); HttpNetworkTransaction* trans = helper.trans(); TestCompletionCallback callback; int rv = trans->Start(&CreateGetRequest(), &callback, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - helper.ResetTrans(); // Cancel the transaction. - // Finish running rest of tasks. - MessageLoop::current()->RunAllPending(); - data->CompleteRead(); + data->SetStop(2); + data->Run(); + helper.ResetTrans(); + data->SetStop(20); + data->Run(); + helper.VerifyDataConsumed(); } diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index b3659e7..83bb624 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -69,10 +69,10 @@ TEST_F(SpdySessionTest, GoAway) { }; StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); data.set_connect_data(connect_data); - session_deps.socket_factory.AddSocketDataProvider(&data); + session_deps.socket_factory->AddSocketDataProvider(&data); SSLSocketDataProvider ssl(false, OK); - session_deps.socket_factory.AddSSLSocketDataProvider(&ssl); + session_deps.socket_factory->AddSSLSocketDataProvider(&ssl); scoped_refptr<HttpNetworkSession> http_session( SpdySessionDependencies::SpdyCreateSession(&session_deps)); diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index 713b3cd..71664ad 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc @@ -188,7 +188,7 @@ TEST_F(SpdyStreamTest, SendDataAfterOpen) { MockConnect connect_data(false, OK); data->set_connect_data(connect_data); - session_deps.socket_factory.AddSocketDataProvider(data.get()); + session_deps.socket_factory->AddSocketDataProvider(data.get()); SpdySession::SetSSLMode(false); scoped_refptr<SpdySession> session(CreateSpdySession()); diff --git a/net/spdy/spdy_test_util.cc b/net/spdy/spdy_test_util.cc index 35e9968..f57fb18 100644 --- a/net/spdy/spdy_test_util.cc +++ b/net/spdy/spdy_test_util.cc @@ -701,8 +701,13 @@ MockWrite CreateMockWrite(const spdy::SpdyFrame& req) { // Create a MockWrite from the given SpdyFrame and sequence number. MockWrite CreateMockWrite(const spdy::SpdyFrame& req, int seq) { + return CreateMockWrite(req, seq, true); +} + +// Create a MockWrite from the given SpdyFrame and sequence number. +MockWrite CreateMockWrite(const spdy::SpdyFrame& req, int seq, bool async) { return MockWrite( - true, req.data(), req.length() + spdy::SpdyFrame::size(), seq); + async, req.data(), req.length() + spdy::SpdyFrame::size(), seq); } // Create a MockRead from the given SpdyFrame. @@ -713,8 +718,13 @@ MockRead CreateMockRead(const spdy::SpdyFrame& resp) { // Create a MockRead from the given SpdyFrame and sequence number. MockRead CreateMockRead(const spdy::SpdyFrame& resp, int seq) { + return CreateMockRead(resp, seq, true); +} + +// Create a MockRead from the given SpdyFrame and sequence number. +MockRead CreateMockRead(const spdy::SpdyFrame& resp, int seq, bool async) { return MockRead( - true, resp.data(), resp.length() + spdy::SpdyFrame::size(), seq); + async, resp.data(), resp.length() + spdy::SpdyFrame::size(), seq); } // Combines the given SpdyFrames into the given char array and returns diff --git a/net/spdy/spdy_test_util.h b/net/spdy/spdy_test_util.h index e7df3f67..79010e23 100644 --- a/net/spdy/spdy_test_util.h +++ b/net/spdy/spdy_test_util.h @@ -266,12 +266,16 @@ MockWrite CreateMockWrite(const spdy::SpdyFrame& req); // Create an async MockWrite from the given SpdyFrame and sequence number. MockWrite CreateMockWrite(const spdy::SpdyFrame& req, int seq); +MockWrite CreateMockWrite(const spdy::SpdyFrame& req, int seq, bool async); + // Create a MockRead from the given SpdyFrame. MockRead CreateMockRead(const spdy::SpdyFrame& resp); // Create a MockRead from the given SpdyFrame and sequence number. MockRead CreateMockRead(const spdy::SpdyFrame& resp, int seq); +MockRead CreateMockRead(const spdy::SpdyFrame& resp, int seq, bool async); + // Combines the given SpdyFrames into the given char array and returns // the total length. int CombineFrames(const spdy::SpdyFrame** frames, int num_frames, @@ -286,6 +290,8 @@ class SpdySessionDependencies { : host_resolver(new MockHostResolver), proxy_service(ProxyService::CreateNull()), ssl_config_service(new SSLConfigServiceDefaults), + socket_factory(new MockClientSocketFactory), + deterministic_socket_factory(new DeterministicMockClientSocketFactory), http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()), spdy_session_pool(new SpdySessionPool()) { // Note: The CancelledTransaction test does cleanup by running all @@ -302,13 +308,16 @@ class SpdySessionDependencies { : host_resolver(new MockHostResolver), proxy_service(proxy_service), ssl_config_service(new SSLConfigServiceDefaults), + socket_factory(new MockClientSocketFactory), + deterministic_socket_factory(new DeterministicMockClientSocketFactory), http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()), spdy_session_pool(new SpdySessionPool()) {} scoped_refptr<MockHostResolverBase> host_resolver; scoped_refptr<ProxyService> proxy_service; scoped_refptr<SSLConfigService> ssl_config_service; - MockClientSocketFactory socket_factory; + scoped_ptr<MockClientSocketFactory> socket_factory; + scoped_ptr<DeterministicMockClientSocketFactory> deterministic_socket_factory; scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory; scoped_refptr<SpdySessionPool> spdy_session_pool; @@ -316,13 +325,25 @@ class SpdySessionDependencies { SpdySessionDependencies* session_deps) { return new HttpNetworkSession(session_deps->host_resolver, session_deps->proxy_service, - &session_deps->socket_factory, + session_deps->socket_factory.get(), session_deps->ssl_config_service, session_deps->spdy_session_pool, session_deps->http_auth_handler_factory.get(), NULL, NULL); -} + } + static HttpNetworkSession* SpdyCreateSessionDeterministic( + SpdySessionDependencies* session_deps) { + return new HttpNetworkSession(session_deps->host_resolver, + session_deps->proxy_service, + session_deps-> + deterministic_socket_factory.get(), + session_deps->ssl_config_service, + session_deps->spdy_session_pool, + session_deps->http_auth_handler_factory.get(), + NULL, + NULL); + } }; class SpdyURLRequestContext : public URLRequestContext { |