diff options
author | mmenke <mmenke@chromium.org> | 2015-12-07 10:20:18 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-07 18:21:05 +0000 |
commit | cc2298e47b8a20cb279615dd2c80a7e0d93e6eae (patch) | |
tree | 801e320ce7e35f50660b83eab30e11edc03cd2a4 | |
parent | 2e0db32ee1947b7a48e723ad871077be5e385ed0 (diff) | |
download | chromium_src-cc2298e47b8a20cb279615dd2c80a7e0d93e6eae.zip chromium_src-cc2298e47b8a20cb279615dd2c80a7e0d93e6eae.tar.gz chromium_src-cc2298e47b8a20cb279615dd2c80a7e0d93e6eae.tar.bz2 |
Add integration tests for HttpStreamParser::CanReuseConnection logic.
This requires modifying a fair number of other tests and test
infrastructure to safely handle SocketDataProviders that are destroyed
before the mock socket that uses them.
BUG=565582,544255
Review URL: https://codereview.chromium.org/1499073002
Cr-Commit-Position: refs/heads/master@{#363516}
-rw-r--r-- | net/dns/dns_session_unittest.cc | 1 | ||||
-rw-r--r-- | net/dns/dns_transaction_unittest.cc | 6 | ||||
-rw-r--r-- | net/http/http_network_transaction_unittest.cc | 312 | ||||
-rw-r--r-- | net/http/http_stream_parser_unittest.cc | 1 | ||||
-rw-r--r-- | net/socket/socket_test_util.cc | 127 | ||||
-rw-r--r-- | net/socket/socket_test_util.h | 67 | ||||
-rw-r--r-- | net/spdy/spdy_network_transaction_unittest.cc | 8 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool_unittest.cc | 42 | ||||
-rw-r--r-- | net/url_request/url_request_http_job_unittest.cc | 25 |
9 files changed, 377 insertions, 212 deletions
diff --git a/net/dns/dns_session_unittest.cc b/net/dns/dns_session_unittest.cc index 46815e0..9ba920c 100644 --- a/net/dns/dns_session_unittest.cc +++ b/net/dns/dns_session_unittest.cc @@ -190,7 +190,6 @@ TestClientSocketFactory::CreateDatagramClientSocket( data_providers_.push_back(data_provider); scoped_ptr<MockUDPClientSocket> socket( new MockUDPClientSocket(data_provider, net_log)); - data_provider->set_socket(socket.get()); return socket.Pass(); } diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc index e875645..3f82110 100644 --- a/net/dns/dns_transaction_unittest.cc +++ b/net/dns/dns_transaction_unittest.cc @@ -196,7 +196,6 @@ class TestSocketFactory : public MockClientSocketFactory { SocketDataProvider* data_provider = mock_data().GetNext(); scoped_ptr<TestUDPClientSocket> socket( new TestUDPClientSocket(this, data_provider, net_log)); - data_provider->set_socket(socket.get()); return socket.Pass(); } @@ -519,11 +518,6 @@ TEST_F(DnsTransactionTest, CancelLookup) { helper1.StartTransaction(transaction_factory_.get()); helper0.Cancel(); - // Since the transaction has been cancelled, the assocaited socket has been - // destroyed, so make sure the data provide does not attempt to callback - // to the socket. - // TODO(rch): Make the SocketDataProvider and MockSocket do this by default. - socket_data_[0]->GetProvider()->set_socket(nullptr); base::MessageLoop::current()->RunUntilIdle(); diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 5512f55..bd538f5 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -1843,50 +1843,76 @@ TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) { session_deps_.net_log = &net_log; scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + const char* request_data = + "GET / HTTP/1.1\r\n" + "Host: www.foo.com\r\n" + "Connection: keep-alive\r\n\r\n"; + MockWrite data_writes[] = { + MockWrite(ASYNC, 0, request_data), MockWrite(ASYNC, 2, request_data), + MockWrite(ASYNC, 4, request_data), MockWrite(ASYNC, 6, request_data), + MockWrite(ASYNC, 8, request_data), MockWrite(ASYNC, 10, request_data), + MockWrite(ASYNC, 12, request_data), MockWrite(ASYNC, 14, request_data), + MockWrite(ASYNC, 17, request_data), MockWrite(ASYNC, 20, request_data), + }; + // Note that because all these reads happen in the same // StaticSocketDataProvider, it shows that the same socket is being reused for // all transactions. - MockRead data1_reads[] = { - MockRead("HTTP/1.1 204 No Content\r\n\r\n"), - MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"), - MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"), - MockRead("HTTP/1.1 302 Found\r\n" - "Content-Length: 0\r\n\r\n"), - MockRead("HTTP/1.1 302 Found\r\n" - "Content-Length: 5\r\n\r\n" - "hello"), - MockRead("HTTP/1.1 301 Moved Permanently\r\n" - "Content-Length: 0\r\n\r\n"), - MockRead("HTTP/1.1 301 Moved Permanently\r\n" - "Content-Length: 5\r\n\r\n" - "hello"), - MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), - MockRead("hello"), - }; - StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0); - session_deps_.socket_factory->AddSocketDataProvider(&data1); - - MockRead data2_reads[] = { - MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached. + MockRead data_reads[] = { + MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"), + MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"), + MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"), + MockRead(ASYNC, 7, + "HTTP/1.1 302 Found\r\n" + "Content-Length: 0\r\n\r\n"), + MockRead(ASYNC, 9, + "HTTP/1.1 302 Found\r\n" + "Content-Length: 5\r\n\r\n" + "hello"), + MockRead(ASYNC, 11, + "HTTP/1.1 301 Moved Permanently\r\n" + "Content-Length: 0\r\n\r\n"), + MockRead(ASYNC, 13, + "HTTP/1.1 301 Moved Permanently\r\n" + "Content-Length: 5\r\n\r\n" + "hello"), + + // In the next two rounds, IsConnectedAndIdle returns false, due to + // the set_busy_before_sync_reads(true) call, while the + // HttpNetworkTransaction is being shut down, but the socket is still + // reuseable. See http://crbug.com/544255. + MockRead(ASYNC, 15, + "HTTP/1.1 200 Hunky-Dory\r\n" + "Content-Length: 5\r\n\r\n"), + MockRead(SYNCHRONOUS, 16, "hello"), + + MockRead(ASYNC, 18, + "HTTP/1.1 200 Hunky-Dory\r\n" + "Content-Length: 5\r\n\r\n" + "he"), + MockRead(SYNCHRONOUS, 19, "llo"), + + // The body of the final request is actually read. + MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"), + MockRead(ASYNC, 22, "hello"), }; - StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); - session_deps_.socket_factory->AddSocketDataProvider(&data2); + SequencedSocketData data(data_reads, arraysize(data_reads), data_writes, + arraysize(data_writes)); + data.set_busy_before_sync_reads(true); + session_deps_.socket_factory->AddSocketDataProvider(&data); - const int kNumUnreadBodies = arraysize(data1_reads) - 2; + const int kNumUnreadBodies = arraysize(data_writes) - 1; std::string response_lines[kNumUnreadBodies]; uint32 first_socket_log_id = NetLog::Source::kInvalidId; - for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) { + for (size_t i = 0; i < kNumUnreadBodies; ++i) { TestCompletionCallback callback; scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); + EXPECT_EQ(OK, callback.GetResult(rv)); LoadTimingInfo load_timing_info; EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); @@ -1899,22 +1925,27 @@ TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) { } const HttpResponseInfo* response = trans->GetResponseInfo(); - ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response); - ASSERT_TRUE(response->headers.get() != NULL); + ASSERT_TRUE(response->headers); response_lines[i] = response->headers->GetStatusLine(); - // We intentionally don't read the response bodies. + // Delete the transaction without reading the response bodies. Then spin + // the message loop, so the response bodies are drained. + trans.reset(); + base::RunLoop().RunUntilIdle(); } const char* const kStatusLines[] = { - "HTTP/1.1 204 No Content", - "HTTP/1.1 205 Reset Content", - "HTTP/1.1 304 Not Modified", - "HTTP/1.1 302 Found", - "HTTP/1.1 302 Found", - "HTTP/1.1 301 Moved Permanently", - "HTTP/1.1 301 Moved Permanently", + "HTTP/1.1 204 No Content", + "HTTP/1.1 205 Reset Content", + "HTTP/1.1 304 Not Modified", + "HTTP/1.1 302 Found", + "HTTP/1.1 302 Found", + "HTTP/1.1 301 Moved Permanently", + "HTTP/1.1 301 Moved Permanently", + "HTTP/1.1 200 Hunky-Dory", + "HTTP/1.1 200 Hunky-Dory", }; static_assert(kNumUnreadBodies == arraysize(kStatusLines), @@ -1927,12 +1958,10 @@ TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) { scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); int rv = trans->Start(&request, callback.callback(), BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); + EXPECT_EQ(OK, callback.GetResult(rv)); const HttpResponseInfo* response = trans->GetResponseInfo(); - ASSERT_TRUE(response != NULL); - ASSERT_TRUE(response->headers.get() != NULL); + ASSERT_TRUE(response); + ASSERT_TRUE(response->headers); EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); std::string response_data; rv = ReadTransaction(trans.get(), &response_data); @@ -2215,106 +2244,96 @@ TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) { // Test the request-challenge-retry sequence for basic auth, over a keep-alive // connection. TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) { - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("http://www.example.org/"); - request.load_flags = 0; - - TestNetLog log; - session_deps_.net_log = &log; - scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - - MockWrite data_writes1[] = { - MockWrite( - "GET / HTTP/1.1\r\n" - "Host: www.example.org\r\n" - "Connection: keep-alive\r\n\r\n"), - - // After calling trans->RestartWithAuth(), this is the request we should - // be issuing -- the final header line contains the credentials. - MockWrite( - "GET / HTTP/1.1\r\n" - "Host: www.example.org\r\n" - "Connection: keep-alive\r\n" - "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), - }; - - MockRead data_reads1[] = { - MockRead("HTTP/1.1 401 Unauthorized\r\n"), - MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), - MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), - MockRead("Content-Length: 14\r\n\r\n"), - MockRead("Unauthorized\r\n"), + // On the second pass, the body read of the auth challenge is synchronous, so + // IsConnectedAndIdle returns false. The socket should still be drained and + // reused. See http://crbug.com/544255. + for (int i = 0; i < 2; ++i) { + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.example.org/"); + request.load_flags = 0; - // Lastly, the server responds with the actual content. - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), - MockRead("Content-Length: 5\r\n\r\n"), - MockRead("Hello"), - }; + TestNetLog log; + session_deps_.net_log = &log; + scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - // If there is a regression where we disconnect a Keep-Alive - // connection during an auth roundtrip, we'll end up reading this. - MockRead data_reads2[] = { - MockRead(SYNCHRONOUS, ERR_FAILED), - }; + MockWrite data_writes[] = { + MockWrite(ASYNC, 0, + "GET / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n\r\n"), - StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), - data_writes1, arraysize(data_writes1)); - StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), - NULL, 0); - session_deps_.socket_factory->AddSocketDataProvider(&data1); - session_deps_.socket_factory->AddSocketDataProvider(&data2); + // After calling trans->RestartWithAuth(), this is the request we should + // be issuing -- the final header line contains the credentials. + MockWrite(ASYNC, 6, + "GET / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n" + "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), + }; - TestCompletionCallback callback1; + MockRead data_reads[] = { + MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"), + MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), + MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"), + MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"), + + // Lastly, the server responds with the actual content. + MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"), + MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"), + MockRead(ASYNC, 10, "Hello"), + }; - scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); - EXPECT_EQ(ERR_IO_PENDING, rv); + SequencedSocketData data(data_reads, arraysize(data_reads), data_writes, + arraysize(data_writes)); + data.set_busy_before_sync_reads(true); + session_deps_.socket_factory->AddSocketDataProvider(&data); - rv = callback1.WaitForResult(); - EXPECT_EQ(OK, rv); + TestCompletionCallback callback1; - LoadTimingInfo load_timing_info1; - EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); - TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + int rv = trans->Start(&request, callback1.callback(), BoundNetLog()); + ASSERT_EQ(OK, callback1.GetResult(rv)); - const HttpResponseInfo* response = trans->GetResponseInfo(); - ASSERT_TRUE(response != NULL); - EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); + LoadTimingInfo load_timing_info1; + EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); + TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); - TestCompletionCallback callback2; + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); - rv = trans->RestartWithAuth( - AuthCredentials(kFoo, kBar), callback2.callback()); - EXPECT_EQ(ERR_IO_PENDING, rv); + TestCompletionCallback callback2; - rv = callback2.WaitForResult(); - EXPECT_EQ(OK, rv); + rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), + callback2.callback()); + ASSERT_EQ(OK, callback2.GetResult(rv)); - LoadTimingInfo load_timing_info2; - EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); - TestLoadTimingReused(load_timing_info2); - // The load timing after restart should have the same socket ID, and times - // those of the first load timing. - EXPECT_LE(load_timing_info1.receive_headers_end, - load_timing_info2.send_start); - EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); + LoadTimingInfo load_timing_info2; + EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); + TestLoadTimingReused(load_timing_info2); + // The load timing after restart should have the same socket ID, and times + // those of the first load timing. + EXPECT_LE(load_timing_info1.receive_headers_end, + load_timing_info2.send_start); + EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); - response = trans->GetResponseInfo(); - ASSERT_TRUE(response != NULL); - EXPECT_TRUE(response->auth_challenge.get() == NULL); - EXPECT_EQ(5, response->headers->GetContentLength()); + response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + EXPECT_FALSE(response->auth_challenge); + EXPECT_EQ(5, response->headers->GetContentLength()); - std::string response_data; - rv = ReadTransaction(trans.get(), &response_data); - EXPECT_EQ(OK, rv); + std::string response_data; + EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data)); - int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1)); - EXPECT_EQ(writes_size1, trans->GetTotalSentBytes()); - int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1)); - EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes()); + int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes)); + EXPECT_EQ(writes_size, trans->GetTotalSentBytes()); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes()); + } } // Test the request-challenge-retry sequence for basic auth, over a keep-alive @@ -5969,9 +5988,6 @@ TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) { scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - scoped_ptr<HttpTransaction> trans( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - MockRead data_reads[] = { MockRead("HTTP/1.1 204 No Content\r\n" "Content-Length: 0\r\n" @@ -5983,6 +5999,11 @@ TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) { StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data); + // Transaction must be created after the MockReads, so it's destroyed before + // them. + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + TestCompletionCallback callback; int rv = trans->Start(&request, callback.callback(), BoundNetLog()); @@ -10505,13 +10526,15 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING); - StaticSocketDataProvider hanging_socket( - NULL, 0, NULL, 0); - hanging_socket.set_connect_data(never_finishing_connect); + StaticSocketDataProvider hanging_socket1(NULL, 0, NULL, 0); + hanging_socket1.set_connect_data(never_finishing_connect); // Socket 2 and 3 are the hanging Alternate-Protocol and // non-Alternate-Protocol jobs from the 2nd transaction. - session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); - session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); + session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1); + + StaticSocketDataProvider hanging_socket2(NULL, 0, NULL, 0); + hanging_socket2.set_connect_data(never_finishing_connect); + session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2); SSLSocketDataProvider ssl(ASYNC, OK); ssl.SetNextProto(GetProtocol()); @@ -10544,7 +10567,9 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { session_deps_.socket_factory->AddSocketDataProvider(&spdy_data); // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3. - session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket); + StaticSocketDataProvider hanging_socket3(NULL, 0, NULL, 0); + hanging_socket3.set_connect_data(never_finishing_connect); + session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3); scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); TestCompletionCallback callback1; @@ -10633,7 +10658,9 @@ TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) { &hanging_alternate_protocol_socket); // 2nd request is just a copy of the first one, over HTTP again. - session_deps_.socket_factory->AddSocketDataProvider(&first_transaction); + StaticSocketDataProvider second_transaction(data_reads, arraysize(data_reads), + NULL, 0); + session_deps_.socket_factory->AddSocketDataProvider(&second_transaction); TestCompletionCallback callback; @@ -11287,7 +11314,6 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { request.load_flags = 0; scoped_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK); @@ -11329,6 +11355,10 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { data_providers.back()); } + // Transaction must be created after DataProviders, so it's destroyed before + // they are as well. + HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); + for (int round = 0; round < test_config.num_auth_rounds; ++round) { const TestRound& read_write_round = test_config.rounds[round]; // Start or restart the transaction. diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc index fbe964d..77da8b2 100644 --- a/net/http/http_stream_parser_unittest.cc +++ b/net/http/http_stream_parser_unittest.cc @@ -52,7 +52,6 @@ scoped_ptr<ClientSocketHandle> CreateConnectedSocketHandle( scoped_ptr<MockTCPClientSocket> socket( new MockTCPClientSocket(net::AddressList(), nullptr, data)); - data->set_socket(socket.get()); TestCompletionCallback callback; EXPECT_EQ(OK, socket->Connect(callback.callback())); diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index 93fcf3d..f4974ac 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc @@ -143,6 +143,29 @@ MockConnect::MockConnect(IoMode io_mode, int r, IPEndPoint addr) : MockConnect::~MockConnect() {} +bool SocketDataProvider::IsIdle() const { + return true; +} + +void SocketDataProvider::Initialize(AsyncSocket* socket) { + CHECK(!socket_); + CHECK(socket); + socket_ = socket; + Reset(); +} + +void SocketDataProvider::DetachSocket() { + CHECK(socket_); + socket_ = nullptr; +} + +SocketDataProvider::SocketDataProvider() : socket_(nullptr) {} + +SocketDataProvider::~SocketDataProvider() { + if (socket_) + socket_->OnDataProviderDestroyed(); +} + StaticSocketDataHelper::StaticSocketDataHelper(MockRead* reads, size_t reads_count, MockWrite* writes, @@ -247,10 +270,6 @@ MockWriteResult StaticSocketDataProvider::OnWrite(const std::string& data) { return MockWriteResult(next_write.mode, result); } -void StaticSocketDataProvider::Reset() { - helper_.Reset(); -} - bool StaticSocketDataProvider::AllReadDataConsumed() const { return helper_.AllReadDataConsumed(); } @@ -259,6 +278,10 @@ bool StaticSocketDataProvider::AllWriteDataConsumed() const { return helper_.AllWriteDataConsumed(); } +void StaticSocketDataProvider::Reset() { + helper_.Reset(); +} + SSLSocketDataProvider::SSLSocketDataProvider(IoMode mode, int result) : connect(mode, result), next_proto_status(SSLClientSocket::kNextProtoUnsupported), @@ -288,6 +311,7 @@ SequencedSocketData::SequencedSocketData(MockRead* reads, sequence_number_(0), read_state_(IDLE), write_state_(IDLE), + busy_before_sync_reads_(false), weak_factory_(this) { // Check that reads and writes have a contiguous set of sequence numbers // starting from 0 and working their way up, with no repeats and skipping @@ -411,14 +435,6 @@ MockWriteResult SequencedSocketData::OnWrite(const std::string& data) { return MockWriteResult(SYNCHRONOUS, ERR_IO_PENDING); } -void SequencedSocketData::Reset() { - helper_.Reset(); - sequence_number_ = 0; - read_state_ = IDLE; - write_state_ = IDLE; - weak_factory_.InvalidateWeakPtrs(); -} - bool SequencedSocketData::AllReadDataConsumed() const { return helper_.AllReadDataConsumed(); } @@ -427,6 +443,20 @@ bool SequencedSocketData::AllWriteDataConsumed() const { return helper_.AllWriteDataConsumed(); } +bool SequencedSocketData::IsIdle() const { + // If |busy_before_sync_reads_| is not set, always considered idle. If + // no reads left, or the next operation is a write, also consider it idle. + if (!busy_before_sync_reads_ || helper_.AllReadDataConsumed() || + helper_.PeekRead().sequence_number != sequence_number_) { + return true; + } + + // If the next operation is synchronous read, treat the socket as not idle. + if (helper_.PeekRead().mode == SYNCHRONOUS) + return false; + return true; +} + bool SequencedSocketData::IsReadPaused() { return read_state_ == PAUSED; } @@ -486,6 +516,14 @@ void SequencedSocketData::MaybePostWriteCompleteTask() { write_state_ = COMPLETING; } +void SequencedSocketData::Reset() { + helper_.Reset(); + sequence_number_ = 0; + read_state_ = IDLE; + write_state_ = IDLE; + weak_factory_.InvalidateWeakPtrs(); +} + void SequencedSocketData::OnReadComplete() { CHECK_EQ(COMPLETING, read_state_); NET_TRACE(1, " *** ") << "Completing read for: " << sequence_number_; @@ -777,7 +815,6 @@ MockClientSocketFactory::CreateDatagramClientSocket( SocketDataProvider* data_provider = mock_data_.GetNext(); scoped_ptr<MockUDPClientSocket> socket( new MockUDPClientSocket(data_provider, net_log)); - data_provider->set_socket(socket.get()); if (bind_type == DatagramSocket::RANDOM_BIND) socket->set_source_port(static_cast<uint16>(rand_int_cb.Run(1025, 65535))); return socket.Pass(); @@ -790,7 +827,6 @@ scoped_ptr<StreamSocket> MockClientSocketFactory::CreateTransportClientSocket( SocketDataProvider* data_provider = mock_data_.GetNext(); scoped_ptr<MockTCPClientSocket> socket( new MockTCPClientSocket(addresses, net_log, data_provider)); - data_provider->set_socket(socket.get()); return socket.Pass(); } @@ -937,14 +973,17 @@ MockTCPClientSocket::MockTCPClientSocket(const AddressList& addresses, was_used_to_convey_data_(false) { DCHECK(data_); peer_addr_ = data->connect_data().peer_addr; - data_->Reset(); + data_->Initialize(this); } -MockTCPClientSocket::~MockTCPClientSocket() {} +MockTCPClientSocket::~MockTCPClientSocket() { + if (data_) + data_->DetachSocket(); +} int MockTCPClientSocket::Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - if (!connected_) + if (!connected_ || !data_) return ERR_UNEXPECTED; // If the buffer is already in use, a read is already in progress! @@ -986,7 +1025,7 @@ int MockTCPClientSocket::Write(IOBuffer* buf, int buf_len, DCHECK(buf); DCHECK_GT(buf_len, 0); - if (!connected_) + if (!connected_ || !data_) return ERR_UNEXPECTED; std::string data(buf->data(), buf_len); @@ -1024,6 +1063,9 @@ void MockTCPClientSocket::AddConnectionAttempts( } int MockTCPClientSocket::Connect(const CompletionCallback& callback) { + if (!data_) + return ERR_UNEXPECTED; + if (connected_) return OK; connected_ = true; @@ -1055,11 +1097,15 @@ void MockTCPClientSocket::Disconnect() { } bool MockTCPClientSocket::IsConnected() const { + if (!data_) + return false; return connected_ && !peer_closed_connection_; } bool MockTCPClientSocket::IsConnectedAndIdle() const { - return IsConnected(); + if (!data_) + return false; + return IsConnected() && data_->IsIdle(); } int MockTCPClientSocket::GetPeerAddress(IPEndPoint* address) const { @@ -1087,6 +1133,10 @@ bool MockTCPClientSocket::GetSSLInfo(SSLInfo* ssl_info) { } void MockTCPClientSocket::OnReadComplete(const MockRead& data) { + // If |data_| has been destroyed, safest to just do nothing. + if (!data_) + return; + // There must be a read pending. DCHECK(pending_read_buf_.get()); // You can't complete a read with another ERR_IO_PENDING status code. @@ -1107,6 +1157,10 @@ void MockTCPClientSocket::OnReadComplete(const MockRead& data) { } void MockTCPClientSocket::OnWriteComplete(int rv) { + // If |data_| has been destroyed, safest to just do nothing. + if (!data_) + return; + // There must be a read pending. DCHECK(!pending_write_callback_.is_null()); CompletionCallback callback = pending_write_callback_; @@ -1114,10 +1168,18 @@ void MockTCPClientSocket::OnWriteComplete(int rv) { } void MockTCPClientSocket::OnConnectComplete(const MockConnect& data) { + // If |data_| has been destroyed, safest to just do nothing. + if (!data_) + return; + CompletionCallback callback = pending_connect_callback_; RunCallback(callback, data.result); } +void MockTCPClientSocket::OnDataProviderDestroyed() { + data_ = nullptr; +} + int MockTCPClientSocket::CompleteRead() { DCHECK(pending_read_buf_.get()); DCHECK(pending_read_buf_len_ > 0); @@ -1503,6 +1565,10 @@ bool MockSSLClientSocket::IsConnected() const { return transport_->socket()->IsConnected(); } +bool MockSSLClientSocket::IsConnectedAndIdle() const { + return transport_->socket()->IsConnectedAndIdle(); +} + bool MockSSLClientSocket::WasEverUsed() const { return transport_->socket()->WasEverUsed(); } @@ -1571,16 +1637,19 @@ MockUDPClientSocket::MockUDPClientSocket(SocketDataProvider* data, net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_NONE)), weak_factory_(this) { DCHECK(data_); - data_->Reset(); + data_->Initialize(this); peer_addr_ = data->connect_data().peer_addr; } -MockUDPClientSocket::~MockUDPClientSocket() {} +MockUDPClientSocket::~MockUDPClientSocket() { + if (data_) + data_->DetachSocket(); +} int MockUDPClientSocket::Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { - if (!connected_) + if (!connected_ || !data_) return ERR_UNEXPECTED; // If the buffer is already in use, a read is already in progress! @@ -1611,7 +1680,7 @@ int MockUDPClientSocket::Write(IOBuffer* buf, int buf_len, DCHECK(buf); DCHECK_GT(buf_len, 0); - if (!connected_) + if (!connected_ || !data_) return ERR_UNEXPECTED; std::string data(buf->data(), buf_len); @@ -1665,12 +1734,17 @@ int MockUDPClientSocket::BindToNetwork( } int MockUDPClientSocket::Connect(const IPEndPoint& address) { + if (!data_) + return ERR_UNEXPECTED; connected_ = true; peer_addr_ = address; return data_->connect_data().result; } void MockUDPClientSocket::OnReadComplete(const MockRead& data) { + if (!data_) + return; + // There must be a read pending. DCHECK(pending_read_buf_.get()); // You can't complete a read with another ERR_IO_PENDING status code. @@ -1691,6 +1765,9 @@ void MockUDPClientSocket::OnReadComplete(const MockRead& data) { } void MockUDPClientSocket::OnWriteComplete(int rv) { + if (!data_) + return; + // There must be a read pending. DCHECK(!pending_write_callback_.is_null()); CompletionCallback callback = pending_write_callback_; @@ -1701,6 +1778,10 @@ void MockUDPClientSocket::OnConnectComplete(const MockConnect& data) { NOTIMPLEMENTED(); } +void MockUDPClientSocket::OnDataProviderDestroyed() { + data_ = nullptr; +} + int MockUDPClientSocket::CompleteRead() { DCHECK(pending_read_buf_.get()); DCHECK(pending_read_buf_len_ > 0); diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 430b522..9d4ecfb 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h @@ -187,12 +187,13 @@ struct MockWriteResult { }; // The SocketDataProvider is an interface used by the MockClientSocket -// for getting data about individual reads and writes on the socket. +// for getting data about individual reads and writes on the socket. Can be +// used with at most one socket at a time. +// TODO(mmenke): Do these really need to be re-useable? class SocketDataProvider { public: - SocketDataProvider() : socket_(NULL) {} - - virtual ~SocketDataProvider() {} + SocketDataProvider(); + virtual ~SocketDataProvider(); // Returns the buffer and result code for the next simulated read. // If the |MockRead.result| is ERR_IO_PENDING, it informs the caller @@ -200,18 +201,32 @@ class SocketDataProvider { // function at a later time. virtual MockRead OnRead() = 0; virtual MockWriteResult OnWrite(const std::string& data) = 0; - virtual void Reset() = 0; virtual bool AllReadDataConsumed() const = 0; virtual bool AllWriteDataConsumed() const = 0; + // Returns true if the request should be considered idle, for the purposes of + // IsConnectedAndIdle. + virtual bool IsIdle() const; + + // Initializes the SocketDataProvider for use with |socket|. Must be called + // before use + void Initialize(AsyncSocket* socket); + // Detaches the socket associated with a SocketDataProvider. Must be called + // before |socket_| is destroyed, unless the SocketDataProvider has informed + // |socket_| it was destroyed. Must also be called before Initialize() may + // be called again with a new socket. + void DetachSocket(); + // Accessor for the socket which is using the SocketDataProvider. AsyncSocket* socket() { return socket_; } - void set_socket(AsyncSocket* socket) { socket_ = socket; } MockConnect connect_data() const { return connect_; } void set_connect_data(const MockConnect& connect) { connect_ = connect; } private: + // Called to inform subclasses of initialization. + virtual void Reset() = 0; + MockConnect connect_; AsyncSocket* socket_; @@ -235,6 +250,11 @@ class AsyncSocket { // is called to complete the asynchronous read operation. virtual void OnWriteComplete(int rv) = 0; virtual void OnConnectComplete(const MockConnect& data) = 0; + + // Called when the SocketDataProvider associated with the socket is destroyed. + // The socket may continue to be used after the data provider is destroyed, + // so it should be sure not to dereference the provider after this is called. + virtual void OnDataProviderDestroyed() = 0; }; // StaticSocketDataHelper manages a list of reads and writes. @@ -295,10 +315,9 @@ class StaticSocketDataProvider : public SocketDataProvider { virtual void CompleteRead() {} - // SocketDataProvider implementation. + // From SocketDataProvider: MockRead OnRead() override; MockWriteResult OnWrite(const std::string& data) override; - void Reset() override; bool AllReadDataConsumed() const override; bool AllWriteDataConsumed() const override; @@ -307,10 +326,10 @@ class StaticSocketDataProvider : public SocketDataProvider { size_t read_count() const { return helper_.read_count(); } size_t write_count() const { return helper_.write_count(); } - protected: - StaticSocketDataHelper* helper() { return &helper_; } - private: + // From SocketDataProvider: + void Reset() override; + StaticSocketDataHelper helper_; DISALLOW_COPY_AND_ASSIGN(StaticSocketDataProvider); @@ -358,16 +377,26 @@ class SequencedSocketData : public SocketDataProvider { ~SequencedSocketData() override; - // SocketDataProviderBase implementation. + // From SocketDataProvider: MockRead OnRead() override; MockWriteResult OnWrite(const std::string& data) override; - void Reset() override; bool AllReadDataConsumed() const override; bool AllWriteDataConsumed() const override; + bool IsIdle() const override; bool IsReadPaused(); void CompleteRead(); + // When true, IsConnectedAndIdle() will return false if the next event in the + // sequence is a synchronous. Otherwise, the socket claims to be idle as + // long as it's connected. Defaults to false. + // TODO(mmenke): See if this can be made the default behavior, and consider + // removing this mehtod. Need to make sure it doesn't change what code any + // tests are targetted at testing. + void set_busy_before_sync_reads(bool busy_before_sync_reads) { + busy_before_sync_reads_ = busy_before_sync_reads; + } + private: // Defines the state for the read or write path. enum IoState { @@ -378,6 +407,9 @@ class SequencedSocketData : public SocketDataProvider { PAUSED, // IO is paused until CompleteRead() is called. }; + // From SocketDataProvider: + void Reset() override; + void OnReadComplete(); void OnWriteComplete(); @@ -389,6 +421,8 @@ class SequencedSocketData : public SocketDataProvider { IoState read_state_; IoState write_state_; + bool busy_before_sync_reads_; + base::WeakPtrFactory<SequencedSocketData> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SequencedSocketData); @@ -717,6 +751,7 @@ class MockTCPClientSocket : public MockClientSocket, public AsyncSocket { void OnReadComplete(const MockRead& data) override; void OnWriteComplete(int rv) override; void OnConnectComplete(const MockConnect& data) override; + void OnDataProviderDestroyed() override; private: int CompleteRead(); @@ -898,6 +933,7 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket { int Connect(const CompletionCallback& callback) override; void Disconnect() override; bool IsConnected() const override; + bool IsConnectedAndIdle() const override; bool WasEverUsed() const override; bool UsingTCPFastOpen() const override; int GetPeerAddress(IPEndPoint* address) const override; @@ -911,6 +947,10 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket { void OnReadComplete(const MockRead& data) override; void OnWriteComplete(int rv) override; void OnConnectComplete(const MockConnect& data) override; + // SSL sockets don't need magic to deal with destruction of their data + // provider. + // TODO(mmenke): Probably a good idea to support it, anyways. + void OnDataProviderDestroyed() override {} ChannelIDService* GetChannelIDService() const override; @@ -954,6 +994,7 @@ class MockUDPClientSocket : public DatagramClientSocket, public AsyncSocket { void OnReadComplete(const MockRead& data) override; void OnWriteComplete(int rv) override; void OnConnectComplete(const MockConnect& data) override; + void OnDataProviderDestroyed() override; void set_source_port(uint16 port) { source_port_ = port;} diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index 8a54d72..d79f003 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc @@ -901,7 +901,8 @@ TEST_P(SpdyNetworkTransactionTest, ThreeGets) { MockRead(ASYNC, 0, 12), // EOF }; SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); - SequencedSocketData data_placeholder(NULL, 0, NULL, 0); + SequencedSocketData data_placeholder1(NULL, 0, NULL, 0); + SequencedSocketData data_placeholder2(NULL, 0, NULL, 0); BoundNetLog log; TransactionHelperResult out; @@ -912,8 +913,8 @@ TEST_P(SpdyNetworkTransactionTest, ThreeGets) { // We require placeholder data because three get requests are sent out at // the same time which results in three sockets being connected. The first // on will negotiate SPDY and will be used for all requests. - helper.AddData(&data_placeholder); - helper.AddData(&data_placeholder); + helper.AddData(&data_placeholder1); + helper.AddData(&data_placeholder2); scoped_ptr<HttpNetworkTransaction> trans1( new HttpNetworkTransaction(DEFAULT_PRIORITY, helper.session())); scoped_ptr<HttpNetworkTransaction> trans2( @@ -3550,7 +3551,6 @@ TEST_P(SpdyNetworkTransactionTest, DecompressFailureOnSynReply) { helper.RunToCompletion(&data); TransactionHelperResult out = helper.output(); EXPECT_EQ(ERR_SPDY_COMPRESSION_ERROR, out.rv); - data.Reset(); } // Test that the NetLog contains good data for a simple GET request. diff --git a/net/spdy/spdy_session_pool_unittest.cc b/net/spdy/spdy_session_pool_unittest.cc index 5543245..dd1e3ba 100644 --- a/net/spdy/spdy_session_pool_unittest.cc +++ b/net/spdy/spdy_session_pool_unittest.cc @@ -143,9 +143,9 @@ TEST_P(SpdySessionPoolTest, CloseCurrentIdleSessions) { session_deps_.host_resolver->set_synchronous_mode(true); - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); + StaticSocketDataProvider data1(reads, arraysize(reads), nullptr, 0); + data1.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data1); SSLSocketDataProvider ssl(SYNCHRONOUS, OK); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); @@ -166,7 +166,9 @@ TEST_P(SpdySessionPoolTest, CloseCurrentIdleSessions) { ASSERT_TRUE(spdy_stream1.get() != NULL); // Set up session 2 - session_deps_.socket_factory->AddSocketDataProvider(&data); + StaticSocketDataProvider data2(reads, arraysize(reads), nullptr, 0); + data2.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data2); const std::string kTestHost2("http://www.b.com"); HostPortPair test_host_port_pair2(kTestHost2, 80); SpdySessionKey key2(test_host_port_pair2, ProxyServer::Direct(), @@ -180,7 +182,9 @@ TEST_P(SpdySessionPoolTest, CloseCurrentIdleSessions) { ASSERT_TRUE(spdy_stream2.get() != NULL); // Set up session 3 - session_deps_.socket_factory->AddSocketDataProvider(&data); + StaticSocketDataProvider data3(reads, arraysize(reads), nullptr, 0); + data3.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data3); const std::string kTestHost3("http://www.c.com"); HostPortPair test_host_port_pair3(kTestHost3, 80); SpdySessionKey key3(test_host_port_pair3, ProxyServer::Direct(), @@ -363,9 +367,9 @@ void SpdySessionPoolTest::RunIPPoolingTest( MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. }; - StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); + StaticSocketDataProvider data1(reads, arraysize(reads), NULL, 0); + data1.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data1); SSLSocketDataProvider ssl(SYNCHRONOUS, OK); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); @@ -395,7 +399,9 @@ void SpdySessionPoolTest::RunIPPoolingTest( EXPECT_FALSE(HasSpdySession(spdy_session_pool_, test_hosts[2].key)); // Create a new session to host 2. - session_deps_.socket_factory->AddSocketDataProvider(&data); + StaticSocketDataProvider data2(reads, arraysize(reads), NULL, 0); + data2.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&data2); base::WeakPtr<SpdySession> session2 = CreateInsecureSpdySession( http_session_.get(), test_hosts[2].key, BoundNetLog()); @@ -523,10 +529,10 @@ TEST_P(SpdySessionPoolTest, IPAddressChanged) { spdy_util.ConstructSpdyGet("http://www.a.com", false, 1, MEDIUM)); MockWrite writes[] = {CreateMockWrite(*req, 1)}; - StaticSocketDataProvider data(reads, arraysize(reads), writes, - arraysize(writes)); - data.set_connect_data(connect_data); - session_deps_.socket_factory->AddSocketDataProvider(&data); + StaticSocketDataProvider dataA(reads, arraysize(reads), writes, + arraysize(writes)); + dataA.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&dataA); SSLSocketDataProvider ssl(SYNCHRONOUS, OK); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); @@ -534,7 +540,6 @@ TEST_P(SpdySessionPoolTest, IPAddressChanged) { CreateNetworkSession(); // Set up session A: Going away, but with an active stream. - session_deps_.socket_factory->AddSocketDataProvider(&data); const std::string kTestHostA("http://www.a.com"); HostPortPair test_host_port_pairA(kTestHostA, 80); SpdySessionKey keyA( @@ -561,6 +566,10 @@ TEST_P(SpdySessionPoolTest, IPAddressChanged) { EXPECT_FALSE(delegateA.StreamIsClosed()); // Set up session B: Available, with a created stream. + StaticSocketDataProvider dataB(reads, arraysize(reads), writes, + arraysize(writes)); + dataB.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&dataB); const std::string kTestHostB("http://www.b.com"); HostPortPair test_host_port_pairB(kTestHostB, 80); SpdySessionKey keyB( @@ -576,7 +585,10 @@ TEST_P(SpdySessionPoolTest, IPAddressChanged) { spdy_streamB->SetDelegate(&delegateB); // Set up session C: Draining. - session_deps_.socket_factory->AddSocketDataProvider(&data); + StaticSocketDataProvider dataC(reads, arraysize(reads), writes, + arraysize(writes)); + dataC.set_connect_data(connect_data); + session_deps_.socket_factory->AddSocketDataProvider(&dataC); const std::string kTestHostC("http://www.c.com"); HostPortPair test_host_port_pairC(kTestHostC, 80); SpdySessionKey keyC( diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc index dca3e8e..b4175ae 100644 --- a/net/url_request/url_request_http_job_unittest.cc +++ b/net/url_request/url_request_http_job_unittest.cc @@ -414,11 +414,23 @@ TEST_F(URLRequestHttpJobWithMockSocketsTest, BackoffHeaderUserGesture) { "Connection: keep-alive\r\n" "User-Agent:\r\n" "Accept-Encoding: gzip, deflate\r\n" - "Accept-Language: en-us,fr\r\n\r\n")}; - MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" - "Backoff: 3600\r\n" - "Content-Length: 9\r\n\r\n"), - MockRead("test.html")}; + "Accept-Language: en-us,fr\r\n\r\n"), + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "Connection: keep-alive\r\n" + "User-Agent:\r\n" + "Accept-Encoding: gzip, deflate\r\n" + "Accept-Language: en-us,fr\r\n\r\n"), + }; + MockRead reads[] = { + MockRead("HTTP/1.1 200 OK\r\n" + "Backoff: 3600\r\n" + "Content-Length: 9\r\n\r\n"), + MockRead("test.html"), MockRead("HTTP/1.1 200 OK\r\n" + "Backoff: 3600\r\n" + "Content-Length: 9\r\n\r\n"), + MockRead("test.html"), + }; net::SSLSocketDataProvider ssl_socket_data_provider(net::ASYNC, net::OK); ssl_socket_data_provider.SetNextProto(kProtoHTTP11); @@ -445,9 +457,6 @@ TEST_F(URLRequestHttpJobWithMockSocketsTest, BackoffHeaderUserGesture) { EXPECT_EQ(1, delegate1.received_before_network_start_count()); EXPECT_EQ(1, manager_.GetNumberOfEntriesForTests()); - // Reset socket data provider to replay socket data. - socket_data.Reset(); - // Issue a user-initiated request, backoff logic should not apply. TestDelegate delegate2; scoped_ptr<URLRequest> request2 = |