Index: net/spdy/spdy_http_stream_unittest.cc |
=================================================================== |
--- net/spdy/spdy_http_stream_unittest.cc (revision 124866) |
+++ net/spdy/spdy_http_stream_unittest.cc (working copy) |
@@ -1,465 +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/asn1_util.h" |
-#include "net/base/default_origin_bound_cert_store.h" |
-#include "net/http/http_response_headers.h" |
-#include "net/http/http_response_info.h" |
-#include "net/spdy/spdy_session.h" |
-#include "net/spdy/spdy_test_util.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-namespace net { |
- |
-class SpdyHttpStreamTest : public testing::Test { |
- public: |
- OrderedSocketData* data() { return data_.get(); } |
- protected: |
- SpdyHttpStreamTest() {} |
- |
- void EnableCompression(bool enabled) { |
- spdy::SpdyFramer::set_enable_compression_default(enabled); |
- } |
- |
- virtual void TearDown() { |
- crypto::ECSignatureCreator::SetFactoryForTesting(NULL); |
- MessageLoop::current()->RunAllPending(); |
- } |
- int InitSession(MockRead* reads, size_t reads_count, |
- MockWrite* writes, size_t writes_count, |
- HostPortPair& host_port_pair) { |
- HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); |
- 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(pair, BoundNetLog()); |
- transport_params_ = new TransportSocketParams(host_port_pair, |
- MEDIUM, false, false); |
- 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(), |
- BoundNetLog())); |
- EXPECT_EQ(OK, callback.WaitForResult()); |
- return session_->InitializeWithSocket(connection.release(), false, OK); |
- } |
- |
- void TestSendCredentials( |
- OriginBoundCertService* obc_service, |
- const std::string& cert, |
- const std::string& proof, |
- SSLClientCertType type); |
- |
- SpdySessionDependencies session_deps_; |
- scoped_ptr<OrderedSocketData> data_; |
- scoped_refptr<HttpNetworkSession> http_session_; |
- scoped_refptr<SpdySession> session_; |
- scoped_refptr<TransportSocketParams> transport_params_; |
-}; |
- |
-TEST_F(SpdyHttpStreamTest, SendRequest) { |
- EnableCompression(false); |
- SpdySession::SetSSLMode(false); |
- |
- scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |
- MockWrite writes[] = { |
- CreateMockWrite(*req.get(), 1), |
- }; |
- scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |
- MockRead reads[] = { |
- CreateMockRead(*resp, 2), |
- MockRead(SYNCHRONOUS, 0, 3) // EOF |
- }; |
- |
- HostPortPair host_port_pair("www.google.com", 80); |
- HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); |
- 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)); |
- ASSERT_EQ( |
- OK, |
- http_stream->InitializeStream(&request, net_log, CompletionCallback())); |
- |
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, NULL, &response, |
- callback.callback())); |
- EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair)); |
- |
- // 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(pair)); |
- EXPECT_TRUE(data()->at_read_eof()); |
- EXPECT_TRUE(data()->at_write_eof()); |
-} |
- |
-TEST_F(SpdyHttpStreamTest, SendChunkedPost) { |
- EnableCompression(false); |
- SpdySession::SetSSLMode(false); |
- UploadDataStream::set_merge_chunks(false); |
- |
- scoped_ptr<spdy::SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); |
- scoped_ptr<spdy::SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false)); |
- scoped_ptr<spdy::SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true)); |
- MockWrite writes[] = { |
- CreateMockWrite(*req.get(), 1), |
- CreateMockWrite(*chunk1, 2), // POST upload frames |
- CreateMockWrite(*chunk2, 3), |
- }; |
- scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); |
- MockRead reads[] = { |
- CreateMockRead(*resp, 4), |
- CreateMockRead(*chunk1, 5), |
- CreateMockRead(*chunk2, 5), |
- MockRead(SYNCHRONOUS, 0, 6) // EOF |
- }; |
- |
- HostPortPair host_port_pair("www.google.com", 80); |
- HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); |
- EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes), |
- host_port_pair)); |
- |
- HttpRequestInfo request; |
- request.method = "POST"; |
- request.url = GURL("http://www.google.com/"); |
- request.upload_data = new UploadData(); |
- request.upload_data->set_is_chunked(true); |
- request.upload_data->AppendChunk(kUploadData, kUploadDataSize, false); |
- request.upload_data->AppendChunk(kUploadData, kUploadDataSize, true); |
- TestCompletionCallback callback; |
- HttpResponseInfo response; |
- HttpRequestHeaders headers; |
- BoundNetLog net_log; |
- SpdyHttpStream http_stream(session_.get(), true); |
- ASSERT_EQ( |
- OK, |
- http_stream.InitializeStream(&request, net_log, CompletionCallback())); |
- |
- // http_stream.SendRequest() will take ownership of upload_stream. |
- UploadDataStream* upload_stream = new UploadDataStream(request.upload_data); |
- ASSERT_EQ(OK, upload_stream->Init()); |
- EXPECT_EQ(ERR_IO_PENDING, http_stream.SendRequest( |
- headers, upload_stream, &response, callback.callback())); |
- EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair)); |
- |
- // This triggers the MockWrite and read 2 |
- callback.WaitForResult(); |
- |
- // This triggers read 3. The empty read causes the session to shut down. |
- data()->CompleteRead(); |
- MessageLoop::current()->RunAllPending(); |
- |
- // 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(pair)); |
- EXPECT_TRUE(data()->at_read_eof()); |
- EXPECT_TRUE(data()->at_write_eof()); |
-} |
- |
-// Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058 |
-TEST_F(SpdyHttpStreamTest, SpdyURLTest) { |
- EnableCompression(false); |
- SpdySession::SetSSLMode(false); |
- |
- 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<spdy::SpdyFrame> req(ConstructSpdyGet(base_url, false, 1, LOWEST)); |
- MockWrite writes[] = { |
- CreateMockWrite(*req.get(), 1), |
- }; |
- scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |
- MockRead reads[] = { |
- CreateMockRead(*resp, 2), |
- MockRead(SYNCHRONOUS, 0, 3) // EOF |
- }; |
- |
- HostPortPair host_port_pair("www.google.com", 80); |
- HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); |
- 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_, true)); |
- ASSERT_EQ( |
- OK, |
- http_stream->InitializeStream(&request, net_log, CompletionCallback())); |
- |
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, NULL, &response, |
- callback.callback())); |
- |
- spdy::SpdyHeaderBlock* spdy_header = |
- http_stream->stream()->spdy_headers().get(); |
- EXPECT_TRUE(spdy_header != NULL); |
- if (spdy_header->find("url") != spdy_header->end()) |
- EXPECT_EQ("/foo?query=what", spdy_header->find("url")->second); |
- else |
- FAIL() << "No url is set in spdy_header!"; |
- |
- // 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(pair)); |
- EXPECT_TRUE(data()->at_read_eof()); |
- EXPECT_TRUE(data()->at_write_eof()); |
-} |
- |
-void GetECOriginBoundCertAndProof(const std::string& origin, |
- OriginBoundCertService* obc_service, |
- std::string* cert, |
- std::string* proof) { |
- TestCompletionCallback callback; |
- std::vector<uint8> requested_cert_types; |
- requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN); |
- SSLClientCertType cert_type; |
- std::string key; |
- OriginBoundCertService::RequestHandle request_handle; |
- int rv = obc_service->GetOriginBoundCert(origin, requested_cert_types, |
- &cert_type, &key, cert, |
- callback.callback(), |
- &request_handle); |
- EXPECT_EQ(ERR_IO_PENDING, rv); |
- EXPECT_EQ(OK, callback.WaitForResult()); |
- EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, cert_type); |
- |
- unsigned char secret[32]; |
- memset(secret, 'A', arraysize(secret)); |
- |
- // Convert the key string into a vector<unit8> |
- std::vector<uint8> key_data(key.begin(), key.end()); |
- |
- base::StringPiece spki_piece; |
- ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(*cert, &spki_piece)); |
- std::vector<uint8> spki(spki_piece.data(), |
- spki_piece.data() + spki_piece.size()); |
- |
- std::vector<uint8> proof_data; |
- scoped_ptr<crypto::ECPrivateKey> private_key( |
- crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
- OriginBoundCertService::kEPKIPassword, key_data, spki)); |
- scoped_ptr<crypto::ECSignatureCreator> creator( |
- crypto::ECSignatureCreator::Create(private_key.get())); |
- creator->Sign(secret, arraysize(secret), &proof_data); |
- proof->assign(proof_data.begin(), proof_data.end()); |
-} |
- |
-// TODO(rch): When openssl supports origin 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 origin bound certificates, that we send a CREDENTIAL frame for |
-// the new origin before we send the new request. |
-void SpdyHttpStreamTest::TestSendCredentials( |
- OriginBoundCertService* obc_service, |
- const std::string& cert, |
- const std::string& proof, |
- SSLClientCertType type) { |
- EnableCompression(false); |
- |
- spdy::SpdyCredential cred; |
- cred.slot = 1; |
- cred.proof = proof; |
- cred.certs.push_back(cert); |
- |
- scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST)); |
- scoped_ptr<spdy::SpdyFrame> credential(ConstructSpdyCredential(cred)); |
- scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet("http://www.gmail.com", |
- false, 3, LOWEST)); |
- MockWrite writes[] = { |
- CreateMockWrite(*req.get(), 0), |
- CreateMockWrite(*credential.get(), 2), |
- CreateMockWrite(*req2.get(), 3), |
- }; |
- |
- scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1)); |
- scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3)); |
- MockRead reads[] = { |
- CreateMockRead(*resp, 1), |
- CreateMockRead(*resp2, 4), |
- MockRead(SYNCHRONOUS, 0, 5) // EOF |
- }; |
- |
- HostPortPair host_port_pair("www.google.com", 80); |
- HostPortProxyPair pair(host_port_pair, ProxyServer::Direct()); |
- |
- DeterministicMockClientSocketFactory* socket_factory = |
- session_deps_.deterministic_socket_factory.get(); |
- scoped_refptr<DeterministicSocketData> data( |
- new DeterministicSocketData(reads, arraysize(reads), |
- writes, arraysize(writes))); |
- socket_factory->AddSocketDataProvider(data.get()); |
- SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
- ssl.origin_bound_cert_type = type; |
- ssl.origin_bound_cert_service = obc_service; |
- ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY3; |
- socket_factory->AddSSLSocketDataProvider(&ssl); |
- http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic( |
- &session_deps_); |
- session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog()); |
- transport_params_ = new TransportSocketParams(host_port_pair, |
- MEDIUM, false, false); |
- TestCompletionCallback callback; |
- scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle); |
- SSLConfig ssl_config; |
- scoped_refptr<SOCKSSocketParams> socks_params; |
- scoped_refptr<HttpProxySocketParams> http_proxy_params; |
- scoped_refptr<SSLSocketParams> ssl_params( |
- new SSLSocketParams(transport_params_, |
- socks_params, |
- http_proxy_params, |
- ProxyServer::SCHEME_DIRECT, |
- host_port_pair, |
- ssl_config, |
- 0, |
- false, |
- false)); |
- EXPECT_EQ(ERR_IO_PENDING, |
- connection->Init(host_port_pair.ToString(), |
- ssl_params, |
- MEDIUM, |
- callback.callback(), |
- http_session_->GetSSLSocketPool(), |
- BoundNetLog())); |
- callback.WaitForResult(); |
- EXPECT_EQ(OK, |
- session_->InitializeWithSocket(connection.release(), true, OK)); |
- |
- HttpRequestInfo request; |
- request.method = "GET"; |
- request.url = GURL("http://www.google.com/"); |
- HttpResponseInfo response; |
- HttpRequestHeaders headers; |
- BoundNetLog net_log; |
- scoped_ptr<SpdyHttpStream> http_stream( |
- new SpdyHttpStream(session_.get(), true)); |
- ASSERT_EQ( |
- OK, |
- http_stream->InitializeStream(&request, net_log, CompletionCallback())); |
- |
- EXPECT_FALSE(session_->NeedsCredentials(host_port_pair)); |
- HostPortPair new_host_port_pair("www.gmail.com", 80); |
- EXPECT_TRUE(session_->NeedsCredentials(new_host_port_pair)); |
- |
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, NULL, &response, |
- callback.callback())); |
- EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair)); |
- |
- data->RunFor(2); |
- callback.WaitForResult(); |
- |
- // Start up second request for resource on a new origin. |
- scoped_ptr<SpdyHttpStream> http_stream2( |
- new SpdyHttpStream(session_.get(), true)); |
- request.url = GURL("http://www.gmail.com/"); |
- ASSERT_EQ( |
- OK, |
- http_stream2->InitializeStream(&request, net_log, CompletionCallback())); |
- EXPECT_EQ(ERR_IO_PENDING, http_stream2->SendRequest(headers, NULL, &response, |
- callback.callback())); |
- data->RunFor(2); |
- callback.WaitForResult(); |
- |
- EXPECT_EQ(ERR_IO_PENDING, http_stream2->ReadResponseHeaders( |
- callback.callback())); |
- data->RunFor(1); |
- EXPECT_EQ(OK, callback.WaitForResult()); |
- ASSERT_TRUE(response.headers.get() != NULL); |
- ASSERT_EQ(200, response.headers->response_code()); |
-} |
- |
-class MockECSignatureCreator : public crypto::ECSignatureCreator { |
- public: |
- explicit MockECSignatureCreator(crypto::ECPrivateKey* key) : key_(key) {} |
- |
- virtual bool Sign(const uint8* data, |
- int data_len, |
- std::vector<uint8>* signature) OVERRIDE { |
- std::vector<uint8> private_key_value; |
- key_->ExportValue(&private_key_value); |
- std::string head = "fakesignature"; |
- std::string tail = "/fakesignature"; |
- |
- signature->clear(); |
- signature->insert(signature->end(), head.begin(), head.end()); |
- signature->insert(signature->end(), private_key_value.begin(), |
- private_key_value.end()); |
- signature->insert(signature->end(), '-'); |
- signature->insert(signature->end(), data, data + data_len); |
- signature->insert(signature->end(), tail.begin(), tail.end()); |
- return true; |
- } |
- |
- private: |
- crypto::ECPrivateKey* key_; |
- DISALLOW_COPY_AND_ASSIGN(MockECSignatureCreator); |
-}; |
- |
-class MockECSignatureCreatorFactory : public crypto::ECSignatureCreatorFactory { |
- public: |
- MockECSignatureCreatorFactory() {} |
- virtual ~MockECSignatureCreatorFactory() {} |
- |
- virtual crypto::ECSignatureCreator* Create( |
- crypto::ECPrivateKey* key) OVERRIDE { |
- return new MockECSignatureCreator(key); |
- } |
- private: |
- DISALLOW_COPY_AND_ASSIGN(MockECSignatureCreatorFactory); |
-}; |
- |
-TEST_F(SpdyHttpStreamTest, SendCredentialsEC) { |
- scoped_ptr<crypto::ECSignatureCreatorFactory> ec_signature_creator_factory( |
- new MockECSignatureCreatorFactory()); |
- crypto::ECSignatureCreator::SetFactoryForTesting( |
- ec_signature_creator_factory.get()); |
- |
- scoped_ptr<OriginBoundCertService> obc_service( |
- new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL))); |
- std::string cert; |
- std::string proof; |
- GetECOriginBoundCertAndProof("http://www.gmail.com/", obc_service.get(), |
- &cert, &proof); |
- |
- TestSendCredentials(obc_service.get(), cert, proof, CLIENT_CERT_ECDSA_SIGN); |
-} |
- |
-#endif // !defined(USE_OPENSSL) |
- |
-// TODO(willchan): Write a longer test for SpdyStream that exercises all |
-// methods. |
- |
-} // namespace net |