Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(915)

Unified Diff: net/http/http_stream_factory_impl_unittest.cc

Issue 1744693002: Implement QUIC-based net::BidirectionalStream (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@basecl
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/http/http_stream_factory_impl_unittest.cc
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index 002e3609fe3d60c282f5678ff2e13050f073a6b9..3b394793c0d5b5be3445c7c8814c71a090f50cfc 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -11,8 +11,10 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "net/base/port_util.h"
#include "net/base/test_completion_callback.h"
+#include "net/base/test_data_directory.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
@@ -28,8 +30,14 @@
#include "net/net_features.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_service.h"
+#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_server_id.h"
+#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
+#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_stream_factory_peer.h"
+#include "net/quic/test_tools/quic_test_packet_maker.h"
+#include "net/quic/test_tools/quic_test_utils.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/mock_client_socket_pool_manager.h"
#include "net/socket/next_proto.h"
@@ -39,6 +47,8 @@
#include "net/spdy/spdy_test_util_common.h"
#include "net/ssl/ssl_config_service.h"
#include "net/ssl/ssl_config_service_defaults.h"
+#include "net/test/cert_test_util.h"
+
// This file can be included from net/http even though
// it is in net/websockets because it doesn't
// introduce any link dependency to net/websockets.
@@ -47,6 +57,7 @@
#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
#include "net/http/bidirectional_stream_job.h"
+#include "net/http/bidirectional_stream_request_info.h"
#endif
namespace net {
@@ -738,6 +749,72 @@ TEST_P(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) {
}
}
+#if BUILDFLAG(ENABLE_BIDIRECTIONAL_STREAM)
+// a BidirectionalStreamJob::Delegate to wait until response headers are
+// received.
+class TestBidirectionalDelegate : public BidirectionalStreamJob::Delegate {
+ public:
+ void WaitUntilDone() { loop_.Run(); }
+
+ const SpdyHeaderBlock& response_headers() const { return response_headers_; }
+
+ private:
+ void OnHeadersSent() override {}
+ void OnHeadersReceived(const SpdyHeaderBlock& response_headers) override {
+ response_headers_ = response_headers;
+ loop_.Quit();
+ }
+ void OnDataRead(int bytes_read) override { NOTREACHED(); }
+ void OnDataSent() override { NOTREACHED(); }
+ void OnTrailersReceived(const SpdyHeaderBlock& trailers) override {
+ NOTREACHED();
+ }
+ void OnFailed(int error) override { NOTREACHED(); }
+ base::RunLoop loop_;
+ SpdyHeaderBlock response_headers_;
+};
+
+// Helper class to encapsulate MockReads and MockWrites for QUIC.
+// Simplify ownership issues and the interaction with the MockSocketFactory.
+class MockQuicData {
+ public:
+ MockQuicData() : packet_number_(0) {}
+
+ ~MockQuicData() { STLDeleteElements(&packets_); }
+
+ void AddRead(scoped_ptr<QuicEncryptedPacket> packet) {
+ reads_.push_back(
+ MockRead(ASYNC, packet->data(), packet->length(), packet_number_++));
+ packets_.push_back(packet.release());
+ }
+
+ void AddRead(IoMode mode, int rv) {
+ reads_.push_back(MockRead(mode, rv, packet_number_++));
+ }
+
+ void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) {
+ writes_.push_back(MockWrite(SYNCHRONOUS, packet->data(), packet->length(),
+ packet_number_++));
+ packets_.push_back(packet.release());
+ }
+
+ void AddSocketDataToFactory(MockClientSocketFactory* factory) {
+ MockRead* reads = reads_.empty() ? nullptr : &reads_[0];
+ MockWrite* writes = writes_.empty() ? nullptr : &writes_[0];
+ socket_data_.reset(
+ new SequencedSocketData(reads, reads_.size(), writes, writes_.size()));
+ factory->AddSocketDataProvider(socket_data_.get());
+ }
+
+ private:
+ std::vector<QuicEncryptedPacket*> packets_;
+ std::vector<MockWrite> writes_;
+ std::vector<MockRead> reads_;
+ size_t packet_number_;
+ scoped_ptr<SequencedSocketData> socket_data_;
+};
+#endif
+
} // namespace
TEST_P(HttpStreamFactoryTest, QuicLossyProxyMarkedAsBad) {
@@ -1440,6 +1517,160 @@ TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJob) {
->num_orphaned_jobs());
}
+class HttpStreamFactoryBidirectionalQuicTest
+ : public ::testing::Test,
+ public ::testing::WithParamInterface<QuicVersion> {
+ protected:
+ HttpStreamFactoryBidirectionalQuicTest()
+ : clock_(new MockClock),
+ maker_(GetParam(), 0, clock_, "www.example.org"),
+ random_generator_(0),
+ proxy_service_(ProxyService::CreateDirect()),
+ ssl_config_service_(new SSLConfigServiceDefaults) {
+ clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
+ }
+
+ void Initialize() {
+ params_.enable_quic = true;
+ params_.http_server_properties = http_server_properties_.GetWeakPtr();
+ params_.quic_host_whitelist.insert("www.example.org");
+ params_.quic_random = &random_generator_;
+ params_.quic_clock = clock_;
+
+ // Load a certificate that is valid for *.example.org
+ scoped_refptr<X509Certificate> test_cert(
+ ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
+ EXPECT_TRUE(test_cert.get());
+ verify_details_.cert_verify_result.verified_cert = test_cert;
+ verify_details_.cert_verify_result.is_issued_by_known_root = true;
+ crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details_);
+ crypto_client_stream_factory_.set_handshake_mode(
+ MockCryptoClientStream::CONFIRM_HANDSHAKE);
+ params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
+ params_.quic_supported_versions = test::SupportedVersions(GetParam());
+ params_.transport_security_state = &transport_security_state_;
+ params_.host_resolver = &host_resolver_;
+ params_.proxy_service = proxy_service_.get();
+ params_.ssl_config_service = ssl_config_service_.get();
+ params_.client_socket_factory = &socket_factory_;
+ session_.reset(new HttpNetworkSession(params_));
+ session_->quic_stream_factory()->set_require_confirmation(false);
+ }
+
+ void AddQuicAlternativeService() {
+ const AlternativeService alternative_service(QUIC, "www.example.org", 443);
+ AlternativeServiceInfoVector alternative_service_info_vector;
+ base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
+ alternative_service_info_vector.push_back(
+ AlternativeServiceInfo(alternative_service, 1.0, expiration));
+ HostPortPair host_port_pair(alternative_service.host_port_pair());
+ http_server_properties_.SetAlternativeServices(
+ host_port_pair, alternative_service_info_vector);
+ };
+
+ test::QuicTestPacketMaker& maker() { return maker_; }
+
+ MockClientSocketFactory& socket_factory() { return socket_factory_; }
+
+ HttpNetworkSession* session() { return session_.get(); }
+
+ private:
+ MockClock* clock_; // Owned by QuicStreamFactory
+ test::QuicTestPacketMaker maker_;
+ MockClientSocketFactory socket_factory_;
+ scoped_ptr<HttpNetworkSession> session_;
+ test::MockRandom random_generator_;
+ ProofVerifyDetailsChromium verify_details_;
+ MockCryptoClientStreamFactory crypto_client_stream_factory_;
+ HttpServerPropertiesImpl http_server_properties_;
+ TransportSecurityState transport_security_state_;
+ MockHostResolver host_resolver_;
+ scoped_ptr<ProxyService> proxy_service_;
+ scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
+ HttpNetworkSession::Params params_;
+};
+
+INSTANTIATE_TEST_CASE_P(Version,
+ HttpStreamFactoryBidirectionalQuicTest,
+ ::testing::ValuesIn(QuicSupportedVersions()));
+
+TEST_P(HttpStreamFactoryBidirectionalQuicTest,
+ RequestBidirectionalStreamJobQuicAlternative) {
+ GURL url = GURL("https://www.example.org");
+
+ MockQuicData mock_quic_data;
+ SpdyPriority priority =
+ ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY);
+ size_t spdy_headers_frame_length;
+ mock_quic_data.AddWrite(maker().MakeRequestHeadersPacket(
+ 1, test::kClientDataStreamId1, /*should_include_version=*/true,
+ /*fin=*/true, priority, maker().GetRequestHeaders("GET", "https", "/"),
+ &spdy_headers_frame_length));
+ size_t spdy_response_headers_frame_length;
+ mock_quic_data.AddRead(maker().MakeResponseHeadersPacket(
+ 1, test::kClientDataStreamId1, /*should_include_version=*/false,
+ /*fin=*/true, maker().GetResponseHeaders("200"),
+ &spdy_response_headers_frame_length));
+ mock_quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // No more read data.
+ mock_quic_data.AddSocketDataToFactory(&socket_factory());
+
+ // Add hanging data for http job.
+ scoped_ptr<StaticSocketDataProvider> hanging_data;
+ hanging_data.reset(new StaticSocketDataProvider());
+ MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
+ hanging_data->set_connect_data(hanging_connect);
+ socket_factory().AddSocketDataProvider(hanging_data.get());
+ SSLSocketDataProvider ssl_data(ASYNC, OK);
+ socket_factory().AddSSLSocketDataProvider(&ssl_data);
+
+ // Set up QUIC as alternative_service.
+ AddQuicAlternativeService();
+ Initialize();
+
+ // Now request a stream.
+ SSLConfig ssl_config;
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("https://www.example.org");
+ request_info.load_flags = 0;
+
+ StreamRequestWaiter waiter;
+ scoped_ptr<HttpStreamRequest> request(
+ session()->http_stream_factory()->RequestBidirectionalStreamJob(
+ request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter,
+ BoundNetLog()));
+
+ waiter.WaitForStream();
+ EXPECT_TRUE(waiter.stream_done());
+ EXPECT_FALSE(waiter.websocket_stream());
+ ASSERT_FALSE(waiter.stream());
+ ASSERT_TRUE(waiter.bidirectional_stream_job());
+ BidirectionalStreamJob* job = waiter.bidirectional_stream_job();
+
+ BidirectionalStreamRequestInfo bidi_request_info;
+ bidi_request_info.method = "GET";
+ bidi_request_info.url = GURL("https://www.example.org/");
+ bidi_request_info.end_stream_on_headers = true;
+ bidi_request_info.priority = LOWEST;
+
+ TestBidirectionalDelegate delegate;
+ job->Start(&bidi_request_info, BoundNetLog(), &delegate, nullptr);
+ delegate.WaitUntilDone();
+
+ scoped_refptr<IOBuffer> buffer = new net::IOBuffer(1);
+ EXPECT_EQ(OK, job->ReadData(buffer.get(), 1));
+ EXPECT_EQ("200", delegate.response_headers().find(":status")->second);
+ EXPECT_EQ(1, GetSocketPoolGroupCount(session()->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL)));
+ EXPECT_EQ(1, GetSocketPoolGroupCount(session()->GetSSLSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL)));
+ EXPECT_EQ(0, GetSocketPoolGroupCount(session()->GetTransportSocketPool(
+ HttpNetworkSession::WEBSOCKET_SOCKET_POOL)));
+ EXPECT_EQ(0, GetSocketPoolGroupCount(session()->GetSSLSocketPool(
+ HttpNetworkSession::WEBSOCKET_SOCKET_POOL)));
+ EXPECT_TRUE(waiter.used_proxy_info().is_direct());
+}
+
TEST_P(HttpStreamFactoryTest, RequestBidirectionalStreamJobFailure) {
SpdySessionDependencies session_deps(GetParam(),
ProxyService::CreateDirect());

Powered by Google App Engine
This is Rietveld 408576698