diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-12 03:38:43 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-12 03:38:43 +0000 |
commit | 6fe2e9952f1eb1ca1e52bb1f1080577f10772474 (patch) | |
tree | 66a591f3884a3e7b427246cc8a6cbdeef49be035 | |
parent | 1ead4aab1101e2c48b2c65a83dd8c873b253871b (diff) | |
download | chromium_src-6fe2e9952f1eb1ca1e52bb1f1080577f10772474.zip chromium_src-6fe2e9952f1eb1ca1e52bb1f1080577f10772474.tar.gz chromium_src-6fe2e9952f1eb1ca1e52bb1f1080577f10772474.tar.bz2 |
[SPDY] Merge the SpdyHttpStream unit tests and parametrize them on a NextProto
Add (partial) support for SPDY/3.1 and SPDY/4a2 for SpdyHttpStream
unit tests.
BUG=226192
R=rch@chromium.org
Review URL: https://codereview.chromium.org/16705004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205702 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/net.gyp | 3 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream_spdy2_unittest.cc | 540 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream_unittest.cc (renamed from net/spdy/spdy_http_stream_spdy3_unittest.cc) | 197 | ||||
-rw-r--r-- | net/spdy/spdy_session_unittest.cc | 1 | ||||
-rw-r--r-- | net/spdy/spdy_stream_unittest.cc | 1 |
5 files changed, 99 insertions, 643 deletions
diff --git a/net/net.gyp b/net/net.gyp index 62839f2..096dab0 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -1754,8 +1754,7 @@ 'spdy/spdy_frame_reader_test.cc', 'spdy/spdy_framer_test.cc', 'spdy/spdy_header_block_unittest.cc', - 'spdy/spdy_http_stream_spdy3_unittest.cc', - 'spdy/spdy_http_stream_spdy2_unittest.cc', + 'spdy/spdy_http_stream_unittest.cc', 'spdy/spdy_http_utils_unittest.cc', 'spdy/spdy_network_transaction_spdy3_unittest.cc', 'spdy/spdy_network_transaction_spdy2_unittest.cc', diff --git a/net/spdy/spdy_http_stream_spdy2_unittest.cc b/net/spdy/spdy_http_stream_spdy2_unittest.cc deleted file mode 100644 index 581d530..0000000 --- a/net/spdy/spdy_http_stream_spdy2_unittest.cc +++ /dev/null @@ -1,540 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/spdy/spdy_http_stream.h" - -#include "crypto/ec_private_key.h" -#include "crypto/ec_signature_creator.h" -#include "crypto/signature_creator.h" -#include "net/base/capturing_net_log.h" -#include "net/base/load_timing_info.h" -#include "net/base/load_timing_info_test_util.h" -#include "net/base/upload_data_stream.h" -#include "net/base/upload_element_reader.h" -#include "net/cert/asn1_util.h" -#include "net/http/http_request_info.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_response_info.h" -#include "net/socket/next_proto.h" -#include "net/spdy/spdy_session.h" -#include "net/spdy/spdy_test_util_spdy2.h" -#include "net/ssl/default_server_bound_cert_store.h" -#include "testing/gtest/include/gtest/gtest.h" - -using namespace net::test_spdy2; - -namespace net { - -namespace { - -// Tests the load timing of a stream that's connected and is not the first -// request sent on a connection. -void TestLoadTimingReused(const HttpStream& stream) { - LoadTimingInfo load_timing_info; - EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info)); - - EXPECT_TRUE(load_timing_info.socket_reused); - EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); - - ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); - ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); -} - -// Tests the load timing of a stream that's connected and using a fresh -// connection. -void TestLoadTimingNotReused(const HttpStream& stream) { - LoadTimingInfo load_timing_info; - EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info)); - - EXPECT_FALSE(load_timing_info.socket_reused); - EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); - - ExpectConnectTimingHasTimes(load_timing_info.connect_timing, - CONNECT_TIMING_HAS_DNS_TIMES); - ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); -} - -} // namespace - -class SpdyHttpStreamSpdy2Test : public testing::Test { - public: - SpdyHttpStreamSpdy2Test() - : spdy_util_(kProtoSPDY2), - session_deps_(kProtoSPDY2) { - session_deps_.net_log = &net_log_; - } - - DeterministicSocketData* deterministic_data() { - return deterministic_data_.get(); - } - - OrderedSocketData* data() { return data_.get(); } - - protected: - virtual void TearDown() OVERRIDE { - crypto::ECSignatureCreator::SetFactoryForTesting(NULL); - base::MessageLoop::current()->RunUntilIdle(); - } - - // Initializes the session using DeterministicSocketData. It's advisable - // to use this function rather than the OrderedSocketData, since the - // DeterministicSocketData behaves in a reasonable manner. - int InitSessionDeterministic(MockRead* reads, size_t reads_count, - MockWrite* writes, size_t writes_count, - HostPortPair& host_port_pair) { - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); - deterministic_data_.reset( - new DeterministicSocketData(reads, reads_count, writes, writes_count)); - session_deps_.deterministic_socket_factory->AddSocketDataProvider( - deterministic_data_.get()); - http_session_ = - SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_); - session_ = http_session_->spdy_session_pool()->Get(key, BoundNetLog()); - transport_params_ = new TransportSocketParams(host_port_pair, - MEDIUM, false, false, - OnHostResolutionCallback()); - TestCompletionCallback callback; - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - transport_params_, - MEDIUM, - callback.callback(), - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, callback.WaitForResult()); - return session_->InitializeWithSocket(connection.release(), false, OK); - } - - // Initializes the session using the finicky OrderedSocketData class. - int InitSession(MockRead* reads, size_t reads_count, - MockWrite* writes, size_t writes_count, - HostPortPair& host_port_pair) { - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); - data_.reset(new OrderedSocketData(reads, reads_count, - writes, writes_count)); - session_deps_.socket_factory->AddSocketDataProvider(data_.get()); - http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_); - session_ = http_session_->spdy_session_pool()->Get(key, BoundNetLog()); - transport_params_ = new TransportSocketParams(host_port_pair, - MEDIUM, false, false, - OnHostResolutionCallback()); - TestCompletionCallback callback; - scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); - EXPECT_EQ(ERR_IO_PENDING, - connection->Init(host_port_pair.ToString(), - transport_params_, - MEDIUM, - callback.callback(), - http_session_->GetTransportSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL), - BoundNetLog())); - EXPECT_EQ(OK, callback.WaitForResult()); - return session_->InitializeWithSocket(connection.release(), false, OK); - } - - SpdyTestUtil spdy_util_; - CapturingNetLog net_log_; - SpdySessionDependencies session_deps_; - scoped_ptr<OrderedSocketData> data_; - scoped_ptr<DeterministicSocketData> deterministic_data_; - scoped_refptr<HttpNetworkSession> http_session_; - scoped_refptr<SpdySession> session_; - scoped_refptr<TransportSocketParams> transport_params_; -}; - -// SpdyHttpStream::GetUploadProgress() should still work even before the -// stream is initialized. -TEST_F(SpdyHttpStreamSpdy2Test, GetUploadProgressBeforeInitialization) { - SpdyHttpStream stream(NULL, false); - UploadProgress progress = stream.GetUploadProgress(); - EXPECT_EQ(0u, progress.size()); - EXPECT_EQ(0u, progress.position()); -} - -TEST_F(SpdyHttpStreamSpdy2Test, SendRequest) { - scoped_ptr<SpdyFrame> req( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); - MockWrite writes[] = { - CreateMockWrite(*req.get(), 1), - }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(SYNCHRONOUS, 0, 3) // EOF - }; - - HostPortPair host_port_pair("www.google.com", 80); - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), - host_port_pair)); - - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("http://www.google.com/"); - TestCompletionCallback callback; - HttpResponseInfo response; - HttpRequestHeaders headers; - BoundNetLog net_log; - scoped_ptr<SpdyHttpStream> http_stream( - new SpdyHttpStream(session_.get(), true)); - // Make sure getting load timing information the stream early does not crash. - LoadTimingInfo load_timing_info; - EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info)); - - ASSERT_EQ( - OK, - http_stream->InitializeStream(&request, DEFAULT_PRIORITY, - net_log, CompletionCallback())); - EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info)); - - EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response, - callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); - EXPECT_FALSE(http_stream->GetLoadTimingInfo(&load_timing_info)); - - // This triggers the MockWrite and read 2 - callback.WaitForResult(); - - // Can get timing information once the stream connects. - TestLoadTimingNotReused(*http_stream); - - // This triggers read 3. The empty read causes the session to shut down. - data()->CompleteRead(); - - // Because we abandoned the stream, we don't expect to find a session in the - // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(key)); - EXPECT_TRUE(data()->at_read_eof()); - EXPECT_TRUE(data()->at_write_eof()); - - TestLoadTimingNotReused(*http_stream); - http_stream->Close(true); - // Test that there's no crash when trying to get the load timing after the - // stream has been closed. - TestLoadTimingNotReused(*http_stream); -} - -TEST_F(SpdyHttpStreamSpdy2Test, LoadTimingTwoRequests) { - scoped_ptr<SpdyFrame> req1( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); - scoped_ptr<SpdyFrame> req2( - spdy_util_.ConstructSpdyGet(NULL, 0, false, 3, LOWEST, true)); - MockWrite writes[] = { - CreateMockWrite(*req1, 0), - CreateMockWrite(*req2, 1), - }; - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, "", 0, true)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); - scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, "", 0, true)); - MockRead reads[] = { - CreateMockRead(*resp1, 2), - CreateMockRead(*body1, 3), - CreateMockRead(*resp2, 4), - CreateMockRead(*body2, 5), - MockRead(ASYNC, 0, 6) // EOF - }; - - HostPortPair host_port_pair("www.google.com", 80); - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); - ASSERT_EQ(OK, InitSessionDeterministic(reads, arraysize(reads), - writes, arraysize(writes), - host_port_pair)); - - HttpRequestInfo request1; - request1.method = "GET"; - request1.url = GURL("http://www.google.com/"); - TestCompletionCallback callback1; - HttpResponseInfo response1; - HttpRequestHeaders headers1; - scoped_ptr<SpdyHttpStream> http_stream1( - new SpdyHttpStream(session_.get(), true)); - - ASSERT_EQ(OK, - http_stream1->InitializeStream(&request1, DEFAULT_PRIORITY, - BoundNetLog(), - CompletionCallback())); - EXPECT_EQ(ERR_IO_PENDING, http_stream1->SendRequest(headers1, &response1, - callback1.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); - - HttpRequestInfo request2; - request2.method = "GET"; - request2.url = GURL("http://www.google.com/"); - TestCompletionCallback callback2; - HttpResponseInfo response2; - HttpRequestHeaders headers2; - scoped_ptr<SpdyHttpStream> http_stream2( - new SpdyHttpStream(session_.get(), true)); - - ASSERT_EQ(OK, - http_stream2->InitializeStream(&request2, DEFAULT_PRIORITY, - BoundNetLog(), - CompletionCallback())); - EXPECT_EQ(ERR_IO_PENDING, http_stream2->SendRequest(headers2, &response2, - callback2.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); - - // First write. - deterministic_data()->RunFor(1); - EXPECT_LE(0, callback1.WaitForResult()); - - TestLoadTimingNotReused(*http_stream1); - LoadTimingInfo load_timing_info1; - LoadTimingInfo load_timing_info2; - EXPECT_TRUE(http_stream1->GetLoadTimingInfo(&load_timing_info1)); - EXPECT_FALSE(http_stream2->GetLoadTimingInfo(&load_timing_info2)); - - // Second write. - deterministic_data()->RunFor(1); - EXPECT_LE(0, callback2.WaitForResult()); - TestLoadTimingReused(*http_stream2); - EXPECT_TRUE(http_stream2->GetLoadTimingInfo(&load_timing_info2)); - EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); - - // All the reads. - deterministic_data()->RunFor(6); - - // Read stream 1 to completion, before making sure we can still read load - // timing from both streams. - scoped_refptr<IOBuffer> buf1(new IOBuffer(1)); - ASSERT_EQ( - 0, http_stream1->ReadResponseBody(buf1.get(), 1, callback1.callback())); - - // Stream 1 has been read to completion. - TestLoadTimingNotReused(*http_stream1); - // Stream 2 still has queued body data. - TestLoadTimingReused(*http_stream2); -} - -TEST_F(SpdyHttpStreamSpdy2Test, SendChunkedPost) { - scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); - scoped_ptr<SpdyFrame> body(ConstructSpdyBodyFrame(1, true)); - MockWrite writes[] = { - CreateMockWrite(*req.get(), 0), - CreateMockWrite(*body, 1), // POST upload frame - }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - CreateMockRead(*body, 3), - MockRead(SYNCHRONOUS, 0, 4) // EOF - }; - - HostPortPair host_port_pair("www.google.com", 80); - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), - host_port_pair)); - - UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); - const int kFirstChunkSize = kUploadDataSize/2; - upload_stream.AppendChunk(kUploadData, kFirstChunkSize, false); - upload_stream.AppendChunk(kUploadData + kFirstChunkSize, - kUploadDataSize - kFirstChunkSize, true); - - HttpRequestInfo request; - request.method = "POST"; - request.url = GURL("http://www.google.com/"); - request.upload_data_stream = &upload_stream; - - ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); - - TestCompletionCallback callback; - HttpResponseInfo response; - HttpRequestHeaders headers; - BoundNetLog net_log; - SpdyHttpStream http_stream(session_.get(), true); - ASSERT_EQ( - OK, - http_stream.InitializeStream(&request, DEFAULT_PRIORITY, - net_log, CompletionCallback())); - - EXPECT_EQ(ERR_IO_PENDING, http_stream.SendRequest( - headers, &response, callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); - - // This results in writing the post body and reading the response headers. - callback.WaitForResult(); - - // This triggers reading the body and the EOF, causing the session to shut - // down. - data()->CompleteRead(); - base::MessageLoop::current()->RunUntilIdle(); - - // Because we abandoned the stream, we don't expect to find a session in the - // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(key)); - EXPECT_TRUE(data()->at_read_eof()); - EXPECT_TRUE(data()->at_write_eof()); -} - -// Test to ensure the SpdyStream state machine does not get confused when a -// chunk becomes available while a write is pending. -TEST_F(SpdyHttpStreamSpdy2Test, DelayedSendChunkedPost) { - const char kUploadData1[] = "12345678"; - const int kUploadData1Size = arraysize(kUploadData1)-1; - scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); - scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false)); - scoped_ptr<SpdyFrame> chunk2( - ConstructSpdyBodyFrame(1, kUploadData1, kUploadData1Size, false)); - scoped_ptr<SpdyFrame> chunk3(ConstructSpdyBodyFrame(1, true)); - MockWrite writes[] = { - CreateMockWrite(*req.get(), 0), - CreateMockWrite(*chunk1, 1), // POST upload frames - CreateMockWrite(*chunk2, 2), - CreateMockWrite(*chunk3, 3), - }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); - MockRead reads[] = { - CreateMockRead(*resp, 4), - CreateMockRead(*chunk1, 5), - CreateMockRead(*chunk2, 6), - CreateMockRead(*chunk3, 7), - MockRead(ASYNC, 0, 8) // EOF - }; - - HostPortPair host_port_pair("www.google.com", 80); - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); - - ASSERT_EQ(OK, InitSessionDeterministic(reads, arraysize(reads), - writes, arraysize(writes), - host_port_pair)); - - UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); - - HttpRequestInfo request; - request.method = "POST"; - request.url = GURL("http://www.google.com/"); - request.upload_data_stream = &upload_stream; - - ASSERT_EQ(OK, upload_stream.Init(CompletionCallback())); - upload_stream.AppendChunk(kUploadData, kUploadDataSize, false); - - BoundNetLog net_log; - scoped_ptr<SpdyHttpStream> http_stream( - new SpdyHttpStream(session_.get(), true)); - ASSERT_EQ(OK, http_stream->InitializeStream(&request, DEFAULT_PRIORITY, - net_log, CompletionCallback())); - - HttpRequestHeaders headers; - HttpResponseInfo response; - TestCompletionCallback callback; - // This will attempt to Write() the initial request and headers, which will - // complete asynchronously. - EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response, - callback.callback())); - EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(key)); - - // Complete the initial request write and the first chunk. - deterministic_data()->RunFor(2); - ASSERT_TRUE(callback.have_result()); - EXPECT_EQ(OK, callback.WaitForResult()); - - // Now append the final two chunks which will enqueue two more writes. - upload_stream.AppendChunk(kUploadData1, kUploadData1Size, false); - upload_stream.AppendChunk(kUploadData, kUploadDataSize, true); - - // Finish writing all the chunks. - deterministic_data()->RunFor(2); - - // Read response headers. - deterministic_data()->RunFor(1); - ASSERT_EQ(OK, http_stream->ReadResponseHeaders(callback.callback())); - - // Read and check |chunk1| response. - deterministic_data()->RunFor(1); - scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize)); - ASSERT_EQ(kUploadDataSize, - http_stream->ReadResponseBody( - buf1.get(), kUploadDataSize, callback.callback())); - EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize)); - - // Read and check |chunk2| response. - deterministic_data()->RunFor(1); - scoped_refptr<IOBuffer> buf2(new IOBuffer(kUploadData1Size)); - ASSERT_EQ(kUploadData1Size, - http_stream->ReadResponseBody( - buf2.get(), kUploadData1Size, callback.callback())); - EXPECT_EQ(kUploadData1, std::string(buf2->data(), kUploadData1Size)); - - // Read and check |chunk3| response. - deterministic_data()->RunFor(1); - scoped_refptr<IOBuffer> buf3(new IOBuffer(kUploadDataSize)); - ASSERT_EQ(kUploadDataSize, - http_stream->ReadResponseBody( - buf3.get(), kUploadDataSize, callback.callback())); - EXPECT_EQ(kUploadData, std::string(buf3->data(), kUploadDataSize)); - - // Finish reading the |EOF|. - deterministic_data()->RunFor(1); - ASSERT_TRUE(response.headers.get()); - ASSERT_EQ(200, response.headers->response_code()); - EXPECT_TRUE(deterministic_data()->at_read_eof()); - EXPECT_TRUE(deterministic_data()->at_write_eof()); -} - -// Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058 -TEST_F(SpdyHttpStreamSpdy2Test, SpdyURLTest) { - const char * const full_url = "http://www.google.com/foo?query=what#anchor"; - const char * const base_url = "http://www.google.com/foo?query=what"; - scoped_ptr<SpdyFrame> req( - spdy_util_.ConstructSpdyGet(base_url, false, 1, LOWEST)); - MockWrite writes[] = { - CreateMockWrite(*req.get(), 1), - }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); - MockRead reads[] = { - CreateMockRead(*resp, 2), - MockRead(SYNCHRONOUS, 0, 3) // EOF - }; - - HostPortPair host_port_pair("www.google.com", 80); - SpdySessionKey key(host_port_pair, ProxyServer::Direct(), - kPrivacyModeDisabled); - EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), - host_port_pair)); - - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL(full_url); - TestCompletionCallback callback; - HttpResponseInfo response; - HttpRequestHeaders headers; - BoundNetLog net_log; - scoped_ptr<SpdyHttpStream> http_stream( - new SpdyHttpStream(session_.get(), true)); - ASSERT_EQ(OK, - http_stream->InitializeStream( - &request, DEFAULT_PRIORITY, net_log, CompletionCallback())); - - EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response, - callback.callback())); - - EXPECT_EQ(base_url, http_stream->stream()->GetUrl().spec()); - - // This triggers the MockWrite and read 2 - callback.WaitForResult(); - - // This triggers read 3. The empty read causes the session to shut down. - data()->CompleteRead(); - - // Because we abandoned the stream, we don't expect to find a session in the - // pool anymore. - EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(key)); - EXPECT_TRUE(data()->at_read_eof()); - EXPECT_TRUE(data()->at_write_eof()); -} - -// TODO(willchan): Write a longer test for SpdyStream that exercises all -// methods. - -} // namespace net diff --git a/net/spdy/spdy_http_stream_spdy3_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index b14606b..6405b8f 100644 --- a/net/spdy/spdy_http_stream_spdy3_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -22,15 +22,14 @@ #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/socket/next_proto.h" +#include "net/socket/socket_test_util.h" #include "net/spdy/spdy_credential_builder.h" #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_session.h" -#include "net/spdy/spdy_test_util_spdy3.h" +#include "net/spdy/spdy_test_util_common.h" #include "net/ssl/default_server_bound_cert_store.h" #include "testing/gtest/include/gtest/gtest.h" -using namespace net::test_spdy3; - namespace net { namespace { @@ -64,11 +63,12 @@ void TestLoadTimingNotReused(const HttpStream& stream) { } // namespace -class SpdyHttpStreamSpdy3Test : public testing::Test { +class SpdyHttpStreamSpdy2Test : public testing::Test, + public testing::WithParamInterface<NextProto> { public: - SpdyHttpStreamSpdy3Test() - : spdy_util_(kProtoSPDY3), - session_deps_(kProtoSPDY3) { + SpdyHttpStreamSpdy2Test() + : spdy_util_(GetParam()), + session_deps_(GetParam()) { session_deps_.net_log = &net_log_; } @@ -80,6 +80,7 @@ class SpdyHttpStreamSpdy3Test : public testing::Test { protected: virtual void TearDown() OVERRIDE { + crypto::ECSignatureCreator::SetFactoryForTesting(NULL); base::MessageLoop::current()->RunUntilIdle(); } @@ -157,32 +158,40 @@ class SpdyHttpStreamSpdy3Test : public testing::Test { scoped_refptr<SpdySession> session_; scoped_refptr<TransportSocketParams> transport_params_; - // The SendChunkedPost test is run with SPDY/3 and SPDY/4. - // - // TODO(akalin): Find a less clunky way to do this once we unfork - // the SPDY tests. - void RunSendChunkedPostTest(SpdyMajorVersion spdy_version); - private: MockECSignatureCreatorFactory ec_signature_creator_factory_; }; +INSTANTIATE_TEST_CASE_P( + NextProto, + SpdyHttpStreamSpdy2Test, + testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2)); + +// TODO(akalin): Don't early-exit in the tests below for values > +// kProtoSPDY3. + // SpdyHttpStream::GetUploadProgress() should still work even before the // stream is initialized. -TEST_F(SpdyHttpStreamSpdy3Test, GetUploadProgressBeforeInitialization) { +TEST_P(SpdyHttpStreamSpdy2Test, GetUploadProgressBeforeInitialization) { + if (GetParam() > kProtoSPDY3) + return; + SpdyHttpStream stream(NULL, false); UploadProgress progress = stream.GetUploadProgress(); EXPECT_EQ(0u, progress.size()); EXPECT_EQ(0u, progress.position()); } -TEST_F(SpdyHttpStreamSpdy3Test, SendRequest) { +TEST_P(SpdyHttpStreamSpdy2Test, SendRequest) { + if (GetParam() > kProtoSPDY3) + return; + scoped_ptr<SpdyFrame> req( spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); MockWrite writes[] = { CreateMockWrite(*req.get(), 1), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); MockRead reads[] = { CreateMockRead(*resp, 2), MockRead(SYNCHRONOUS, 0, 3) // EOF @@ -240,7 +249,10 @@ TEST_F(SpdyHttpStreamSpdy3Test, SendRequest) { TestLoadTimingNotReused(*http_stream); } -TEST_F(SpdyHttpStreamSpdy3Test, LoadTimingTwoRequests) { +TEST_P(SpdyHttpStreamSpdy2Test, LoadTimingTwoRequests) { + if (GetParam() > kProtoSPDY3) + return; + scoped_ptr<SpdyFrame> req1( spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); scoped_ptr<SpdyFrame> req2( @@ -249,10 +261,14 @@ TEST_F(SpdyHttpStreamSpdy3Test, LoadTimingTwoRequests) { CreateMockWrite(*req1, 0), CreateMockWrite(*req2, 1), }; - scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> body1(ConstructSpdyBodyFrame(1, "", 0, true)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); - scoped_ptr<SpdyFrame> body2(ConstructSpdyBodyFrame(3, "", 0, true)); + scoped_ptr<SpdyFrame> resp1( + spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> body1( + spdy_util_.ConstructSpdyBodyFrame(1, "", 0, true)); + scoped_ptr<SpdyFrame> resp2( + spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> body2( + spdy_util_.ConstructSpdyBodyFrame(3, "", 0, true)); MockRead reads[] = { CreateMockRead(*resp1, 2), CreateMockRead(*body1, 3), @@ -334,28 +350,26 @@ TEST_F(SpdyHttpStreamSpdy3Test, LoadTimingTwoRequests) { TestLoadTimingReused(*http_stream2); } -void SpdyHttpStreamSpdy3Test::RunSendChunkedPostTest( - SpdyMajorVersion spdy_version) { - BufferedSpdyFramer framer(spdy_version, false); +TEST_P(SpdyHttpStreamSpdy2Test, SendChunkedPost) { + BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); scoped_ptr<SpdyFrame> initial_window_update( framer.CreateWindowUpdate( kSessionFlowControlStreamId, kDefaultInitialRecvWindowSize - kSpdySessionInitialWindowSize)); scoped_ptr<SpdyFrame> req( - ConstructChunkedSpdyPostWithVersion(spdy_version, NULL, 0)); + spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); scoped_ptr<SpdyFrame> body( framer.CreateDataFrame(1, kUploadData, kUploadDataSize, DATA_FLAG_FIN)); std::vector<MockWrite> writes; int seq = 0; - if (spdy_version == SPDY4) { + if (GetParam() >= kProtoSPDY31) { writes.push_back(CreateMockWrite(*initial_window_update, seq++)); } writes.push_back(CreateMockWrite(*req, seq++)); writes.push_back(CreateMockWrite(*body, seq++)); // POST upload frame - scoped_ptr<SpdyFrame> resp( - ConstructSpdyPostSynReplyWithVersion(spdy_version, NULL, 0)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); std::vector<MockRead> reads; reads.push_back(CreateMockRead(*resp, seq++)); reads.push_back(CreateMockRead(*body, seq++)); @@ -367,7 +381,7 @@ void SpdyHttpStreamSpdy3Test::RunSendChunkedPostTest( EXPECT_EQ(OK, InitSession(vector_as_array(&reads), reads.size(), vector_as_array(&writes), writes.size(), host_port_pair)); - EXPECT_EQ(spdy_version, session_->GetProtocolVersion()); + EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion()); UploadDataStream upload_stream(UploadDataStream::CHUNKED, 0); const int kFirstChunkSize = kUploadDataSize/2; @@ -411,32 +425,27 @@ void SpdyHttpStreamSpdy3Test::RunSendChunkedPostTest( EXPECT_TRUE(data()->at_write_eof()); } -TEST_F(SpdyHttpStreamSpdy3Test, SendChunkedPost) { - RunSendChunkedPostTest(SPDY3); -} - -TEST_F(SpdyHttpStreamSpdy3Test, SendChunkedPost4) { - session_deps_.protocol = kProtoSPDY4a2; - RunSendChunkedPostTest(SPDY4); -} - // Test to ensure the SpdyStream state machine does not get confused when a // chunk becomes available while a write is pending. -TEST_F(SpdyHttpStreamSpdy3Test, DelayedSendChunkedPost) { +TEST_P(SpdyHttpStreamSpdy2Test, DelayedSendChunkedPost) { + if (GetParam() > kProtoSPDY3) + return; + const char kUploadData1[] = "12345678"; const int kUploadData1Size = arraysize(kUploadData1)-1; - scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); - scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false)); + scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); + scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, false)); scoped_ptr<SpdyFrame> chunk2( - ConstructSpdyBodyFrame(1, kUploadData1, kUploadData1Size, false)); - scoped_ptr<SpdyFrame> chunk3(ConstructSpdyBodyFrame(1, true)); + spdy_util_.ConstructSpdyBodyFrame( + 1, kUploadData1, kUploadData1Size, false)); + scoped_ptr<SpdyFrame> chunk3(spdy_util_.ConstructSpdyBodyFrame(1, true)); MockWrite writes[] = { CreateMockWrite(*req.get(), 0), CreateMockWrite(*chunk1, 1), // POST upload frames CreateMockWrite(*chunk2, 2), CreateMockWrite(*chunk3, 3), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); MockRead reads[] = { CreateMockRead(*resp, 4), CreateMockRead(*chunk1, 5), @@ -528,14 +537,17 @@ TEST_F(SpdyHttpStreamSpdy3Test, DelayedSendChunkedPost) { // Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be // made available is handled correctly. -TEST_F(SpdyHttpStreamSpdy3Test, DelayedSendChunkedPostWithWindowUpdate) { - scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); - scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, true)); +TEST_P(SpdyHttpStreamSpdy2Test, DelayedSendChunkedPostWithWindowUpdate) { + if (GetParam() != kProtoSPDY3) + return; + + scoped_ptr<SpdyFrame> req(spdy_util_.ConstructChunkedSpdyPost(NULL, 0)); + scoped_ptr<SpdyFrame> chunk1(spdy_util_.ConstructSpdyBodyFrame(1, true)); MockWrite writes[] = { CreateMockWrite(*req.get(), 0), CreateMockWrite(*chunk1, 1), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyPostSynReply(NULL, 0)); scoped_ptr<SpdyFrame> window_update( spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize)); MockRead reads[] = { @@ -642,7 +654,10 @@ TEST_F(SpdyHttpStreamSpdy3Test, DelayedSendChunkedPostWithWindowUpdate) { } // Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058 -TEST_F(SpdyHttpStreamSpdy3Test, SpdyURLTest) { +TEST_P(SpdyHttpStreamSpdy2Test, SpdyURLTest) { + if (GetParam() > kProtoSPDY3) + return; + const char * const full_url = "http://www.google.com/foo?query=what#anchor"; const char * const base_url = "http://www.google.com/foo?query=what"; scoped_ptr<SpdyFrame> req( @@ -650,7 +665,7 @@ TEST_F(SpdyHttpStreamSpdy3Test, SpdyURLTest) { MockWrite writes[] = { CreateMockWrite(*req.get(), 1), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); MockRead reads[] = { CreateMockRead(*resp, 2), MockRead(SYNCHRONOUS, 0, 3) // EOF @@ -714,20 +729,22 @@ void GetECServerBoundCertAndProof( EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, cert_type); SpdyCredential credential; - SpdyCredentialBuilder::Build(MockClientSocket::kTlsUnique, cert_type, key, - *cert, 2, &credential); + EXPECT_EQ(OK, + SpdyCredentialBuilder::Build( + MockClientSocket::kTlsUnique, cert_type, key, + *cert, 2, &credential)); + ASSERT_FALSE(credential.certs.empty()); cert->assign(credential.certs[0]); proof->assign(credential.proof); } -} // namespace - // Constructs a standard SPDY SYN_STREAM frame for a GET request with // a credential set. -SpdyFrame* ConstructCredentialRequestFrame(size_t slot, const GURL& url, +SpdyFrame* ConstructCredentialRequestFrame(NextProto next_proto, + size_t slot, const GURL& url, SpdyStreamId stream_id) { - SpdyTestUtil util(kProtoSPDY3); + SpdyTestUtil util(next_proto); const SpdyHeaderInfo syn_headers = { SYN_STREAM, @@ -743,47 +760,19 @@ SpdyFrame* ConstructCredentialRequestFrame(size_t slot, const GURL& url, DATA_FLAG_NONE }; - // TODO(rch): this is ugly. Clean up. - std::string str_path = url.PathForRequest(); - std::string str_scheme = url.scheme(); - std::string str_host = url.host(); - if (url.has_port()) { - str_host += ":"; - str_host += url.port(); - } - scoped_ptr<char[]> req(new char[str_path.size() + 1]); - scoped_ptr<char[]> scheme(new char[str_scheme.size() + 1]); - scoped_ptr<char[]> host(new char[str_host.size() + 1]); - memcpy(req.get(), str_path.c_str(), str_path.size()); - memcpy(scheme.get(), str_scheme.c_str(), str_scheme.size()); - memcpy(host.get(), str_host.c_str(), str_host.size()); - req.get()[str_path.size()] = '\0'; - scheme.get()[str_scheme.size()] = '\0'; - host.get()[str_host.size()] = '\0'; - - const char* const headers[] = { - ":method", - "GET", - ":path", - req.get(), - ":host", - host.get(), - ":scheme", - scheme.get(), - ":version", - "HTTP/1.1" - }; - return util.ConstructSpdyFrame( - syn_headers, NULL, 0, headers, arraysize(headers)/2); + scoped_ptr<SpdyHeaderBlock> headers(util.ConstructGetHeaderBlock(url.spec())); + return util.ConstructSpdyFrame(syn_headers, headers.Pass()); } +} // namespace + // TODO(rch): When openssl supports server bound certifictes, this // guard can be removed #if !defined(USE_OPENSSL) // Test that if we request a resource for a new origin on a session that // used domain bound certificates, that we send a CREDENTIAL frame for // the new domain before we send the new request. -void SpdyHttpStreamSpdy3Test::TestSendCredentials( +void SpdyHttpStreamSpdy2Test::TestSendCredentials( ServerBoundCertService* server_bound_cert_service, const std::string& cert, const std::string& proof) { @@ -796,19 +785,19 @@ void SpdyHttpStreamSpdy3Test::TestSendCredentials( cred.certs.push_back(cert); scoped_ptr<SpdyFrame> req(ConstructCredentialRequestFrame( - 1, GURL(kUrl1), 1)); + GetParam(), 1, GURL(kUrl1), 1)); scoped_ptr<SpdyFrame> credential( spdy_util_.ConstructSpdyCredential(cred)); scoped_ptr<SpdyFrame> req2(ConstructCredentialRequestFrame( - 2, GURL(kUrl2), 3)); + GetParam(), 2, GURL(kUrl2), 3)); MockWrite writes[] = { CreateMockWrite(*req.get(), 0), CreateMockWrite(*credential.get(), 2), CreateMockWrite(*req2.get(), 3), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); MockRead reads[] = { CreateMockRead(*resp, 1), CreateMockRead(*resp2, 4), @@ -827,7 +816,7 @@ void SpdyHttpStreamSpdy3Test::TestSendCredentials( SSLSocketDataProvider ssl(SYNCHRONOUS, OK); ssl.channel_id_sent = true; ssl.server_bound_cert_service = server_bound_cert_service; - ssl.protocol_negotiated = kProtoSPDY3; + ssl.protocol_negotiated = GetParam(); socket_factory->AddSSLSocketDataProvider(&ssl); http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( &session_deps_); @@ -907,7 +896,10 @@ void SpdyHttpStreamSpdy3Test::TestSendCredentials( ASSERT_EQ(200, response.headers->response_code()); } -TEST_F(SpdyHttpStreamSpdy3Test, SendCredentialsEC) { +TEST_P(SpdyHttpStreamSpdy2Test, SendCredentialsEC) { + if (GetParam() != kProtoSPDY3) + return; + scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool = new base::SequencedWorkerPool(1, "SpdyHttpStreamSpdy3Test"); scoped_ptr<ServerBoundCertService> server_bound_cert_service( @@ -924,7 +916,10 @@ TEST_F(SpdyHttpStreamSpdy3Test, SendCredentialsEC) { sequenced_worker_pool->Shutdown(); } -TEST_F(SpdyHttpStreamSpdy3Test, DontSendCredentialsForHttpUrlsEC) { +TEST_P(SpdyHttpStreamSpdy2Test, DontSendCredentialsForHttpUrlsEC) { + if (GetParam() != kProtoSPDY3) + return; + scoped_refptr<base::SequencedWorkerPool> sequenced_worker_pool = new base::SequencedWorkerPool(1, "SpdyHttpStreamSpdy3Test"); scoped_ptr<ServerBoundCertService> server_bound_cert_service( @@ -945,16 +940,16 @@ TEST_F(SpdyHttpStreamSpdy3Test, DontSendCredentialsForHttpUrlsEC) { cred.certs.push_back(cert); scoped_ptr<SpdyFrame> req(ConstructCredentialRequestFrame( - 0, GURL(kUrl1), 1)); + GetParam(), 0, GURL(kUrl1), 1)); scoped_ptr<SpdyFrame> req2(ConstructCredentialRequestFrame( - 0, GURL(kUrl2), 3)); + GetParam(), 0, GURL(kUrl2), 3)); MockWrite writes[] = { CreateMockWrite(*req.get(), 0), CreateMockWrite(*req2.get(), 2), }; - scoped_ptr<SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); - scoped_ptr<SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); MockRead reads[] = { CreateMockRead(*resp, 1), CreateMockRead(*resp2, 3), @@ -975,7 +970,7 @@ TEST_F(SpdyHttpStreamSpdy3Test, DontSendCredentialsForHttpUrlsEC) { SSLSocketDataProvider ssl(SYNCHRONOUS, OK); ssl.channel_id_sent = true; ssl.server_bound_cert_service = server_bound_cert_service.get(); - ssl.protocol_negotiated = kProtoSPDY3; + ssl.protocol_negotiated = GetParam(); socket_factory->AddSSLSocketDataProvider(&ssl); http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( &session_deps_); diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index b189220..df66fe3a 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -17,6 +17,7 @@ #include "net/dns/host_cache.h" #include "net/socket/client_socket_pool_manager.h" #include "net/socket/next_proto.h" +#include "net/socket/socket_test_util.h" #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_session_pool.h" #include "net/spdy/spdy_session_test_util.h" diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index 9992c18..df3c372 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc @@ -14,6 +14,7 @@ #include "net/base/net_log_unittest.h" #include "net/base/request_priority.h" #include "net/socket/next_proto.h" +#include "net/socket/socket_test_util.h" #include "net/spdy/buffered_spdy_framer.h" #include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_protocol.h" |