| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <vector> | |
| 6 | |
| 7 #include "base/basictypes.h" | |
| 8 #include "base/compiler_specific.h" | |
| 9 #include "base/memory/scoped_ptr.h" | |
| 10 #include "base/stl_util.h" | |
| 11 #include "net/base/capturing_net_log.h" | |
| 12 #include "net/base/net_log_unittest.h" | |
| 13 #include "net/base/test_completion_callback.h" | |
| 14 #include "net/cert/mock_cert_verifier.h" | |
| 15 #include "net/dns/mock_host_resolver.h" | |
| 16 #include "net/http/http_auth_handler_factory.h" | |
| 17 #include "net/http/http_network_session.h" | |
| 18 #include "net/http/http_network_transaction.h" | |
| 19 #include "net/http/http_server_properties_impl.h" | |
| 20 #include "net/http/http_stream.h" | |
| 21 #include "net/http/http_stream_factory.h" | |
| 22 #include "net/http/http_transaction_test_util.h" | |
| 23 #include "net/http/transport_security_state.h" | |
| 24 #include "net/proxy/proxy_config_service_fixed.h" | |
| 25 #include "net/proxy/proxy_resolver.h" | |
| 26 #include "net/proxy/proxy_service.h" | |
| 27 #include "net/quic/crypto/quic_decrypter.h" | |
| 28 #include "net/quic/crypto/quic_encrypter.h" | |
| 29 #include "net/quic/quic_framer.h" | |
| 30 #include "net/quic/quic_http_utils.h" | |
| 31 #include "net/quic/test_tools/crypto_test_utils.h" | |
| 32 #include "net/quic/test_tools/mock_clock.h" | |
| 33 #include "net/quic/test_tools/mock_crypto_client_stream_factory.h" | |
| 34 #include "net/quic/test_tools/mock_random.h" | |
| 35 #include "net/quic/test_tools/quic_test_packet_maker.h" | |
| 36 #include "net/quic/test_tools/quic_test_utils.h" | |
| 37 #include "net/socket/client_socket_factory.h" | |
| 38 #include "net/socket/mock_client_socket_pool_manager.h" | |
| 39 #include "net/socket/socket_test_util.h" | |
| 40 #include "net/socket/ssl_client_socket.h" | |
| 41 #include "net/spdy/spdy_frame_builder.h" | |
| 42 #include "net/spdy/spdy_framer.h" | |
| 43 #include "net/ssl/ssl_config_service_defaults.h" | |
| 44 #include "testing/gtest/include/gtest/gtest.h" | |
| 45 #include "testing/platform_test.h" | |
| 46 | |
| 47 //----------------------------------------------------------------------------- | |
| 48 | |
| 49 namespace { | |
| 50 | |
| 51 // This is the expected return from a current server advertising QUIC. | |
| 52 static const char kQuicAlternateProtocolHttpHeader[] = | |
| 53 "Alternate-Protocol: 80:quic\r\n\r\n"; | |
| 54 static const char kQuicAlternateProtocol50pctHttpHeader[] = | |
| 55 "Alternate-Protocol: 80:quic,p=.5\r\n\r\n"; | |
| 56 static const char kQuicAlternateProtocolHttpsHeader[] = | |
| 57 "Alternate-Protocol: 443:quic\r\n\r\n"; | |
| 58 | |
| 59 } // namespace | |
| 60 | |
| 61 namespace net { | |
| 62 namespace test { | |
| 63 | |
| 64 // Helper class to encapsulate MockReads and MockWrites for QUIC. | |
| 65 // Simplify ownership issues and the interaction with the MockSocketFactory. | |
| 66 class MockQuicData { | |
| 67 public: | |
| 68 ~MockQuicData() { | |
| 69 STLDeleteElements(&packets_); | |
| 70 } | |
| 71 | |
| 72 void AddRead(scoped_ptr<QuicEncryptedPacket> packet) { | |
| 73 reads_.push_back(MockRead(SYNCHRONOUS, packet->data(), packet->length(), | |
| 74 sequence_number_++)); | |
| 75 packets_.push_back(packet.release()); | |
| 76 } | |
| 77 | |
| 78 void AddRead(IoMode mode, int rv) { | |
| 79 reads_.push_back(MockRead(mode, rv)); | |
| 80 } | |
| 81 | |
| 82 void AddWrite(scoped_ptr<QuicEncryptedPacket> packet) { | |
| 83 writes_.push_back(MockWrite(SYNCHRONOUS, packet->data(), packet->length(), | |
| 84 sequence_number_++)); | |
| 85 packets_.push_back(packet.release()); | |
| 86 } | |
| 87 | |
| 88 void AddDelayedSocketDataToFactory(MockClientSocketFactory* factory, | |
| 89 size_t delay) { | |
| 90 MockRead* reads = reads_.empty() ? nullptr : &reads_[0]; | |
| 91 MockWrite* writes = writes_.empty() ? nullptr : &writes_[0]; | |
| 92 socket_data_.reset(new DelayedSocketData( | |
| 93 delay, reads, reads_.size(), writes, writes_.size())); | |
| 94 factory->AddSocketDataProvider(socket_data_.get()); | |
| 95 } | |
| 96 | |
| 97 private: | |
| 98 std::vector<QuicEncryptedPacket*> packets_; | |
| 99 std::vector<MockWrite> writes_; | |
| 100 std::vector<MockRead> reads_; | |
| 101 size_t sequence_number_; | |
| 102 scoped_ptr<SocketDataProvider> socket_data_; | |
| 103 }; | |
| 104 | |
| 105 class ProxyHeadersHandler { | |
| 106 public: | |
| 107 ProxyHeadersHandler() : was_called_(false) {} | |
| 108 | |
| 109 bool was_called() { return was_called_; } | |
| 110 | |
| 111 void OnBeforeProxyHeadersSent(const ProxyInfo& proxy_info, | |
| 112 HttpRequestHeaders* request_headers) { | |
| 113 was_called_ = true; | |
| 114 } | |
| 115 | |
| 116 private: | |
| 117 bool was_called_; | |
| 118 }; | |
| 119 | |
| 120 class QuicNetworkTransactionTest | |
| 121 : public PlatformTest, | |
| 122 public ::testing::WithParamInterface<QuicVersion> { | |
| 123 protected: | |
| 124 QuicNetworkTransactionTest() | |
| 125 : clock_(new MockClock), | |
| 126 maker_(GetParam(), 0, clock_), | |
| 127 ssl_config_service_(new SSLConfigServiceDefaults), | |
| 128 proxy_service_(ProxyService::CreateDirect()), | |
| 129 auth_handler_factory_( | |
| 130 HttpAuthHandlerFactory::CreateDefault(&host_resolver_)), | |
| 131 random_generator_(0), | |
| 132 hanging_data_(nullptr, 0, nullptr, 0) { | |
| 133 request_.method = "GET"; | |
| 134 request_.url = GURL("http://www.google.com/"); | |
| 135 request_.load_flags = 0; | |
| 136 clock_->AdvanceTime(QuicTime::Delta::FromMilliseconds(20)); | |
| 137 } | |
| 138 | |
| 139 void SetUp() override { | |
| 140 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | |
| 141 base::MessageLoop::current()->RunUntilIdle(); | |
| 142 } | |
| 143 | |
| 144 void TearDown() override { | |
| 145 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | |
| 146 // Empty the current queue. | |
| 147 base::MessageLoop::current()->RunUntilIdle(); | |
| 148 PlatformTest::TearDown(); | |
| 149 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | |
| 150 base::MessageLoop::current()->RunUntilIdle(); | |
| 151 } | |
| 152 | |
| 153 scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket( | |
| 154 QuicPacketSequenceNumber num) { | |
| 155 return maker_.MakeConnectionClosePacket(num); | |
| 156 } | |
| 157 | |
| 158 scoped_ptr<QuicEncryptedPacket> ConstructAckPacket( | |
| 159 QuicPacketSequenceNumber largest_received, | |
| 160 QuicPacketSequenceNumber least_unacked) { | |
| 161 return maker_.MakeAckPacket(2, largest_received, least_unacked, true); | |
| 162 } | |
| 163 | |
| 164 SpdyHeaderBlock GetRequestHeaders(const std::string& method, | |
| 165 const std::string& scheme, | |
| 166 const std::string& path) { | |
| 167 return maker_.GetRequestHeaders(method, scheme, path); | |
| 168 } | |
| 169 | |
| 170 SpdyHeaderBlock GetResponseHeaders(const std::string& status) { | |
| 171 return maker_.GetResponseHeaders(status); | |
| 172 } | |
| 173 | |
| 174 scoped_ptr<QuicEncryptedPacket> ConstructDataPacket( | |
| 175 QuicPacketSequenceNumber sequence_number, | |
| 176 QuicStreamId stream_id, | |
| 177 bool should_include_version, | |
| 178 bool fin, | |
| 179 QuicStreamOffset offset, | |
| 180 base::StringPiece data) { | |
| 181 return maker_.MakeDataPacket( | |
| 182 sequence_number, stream_id, should_include_version, fin, offset, data); | |
| 183 } | |
| 184 | |
| 185 scoped_ptr<QuicEncryptedPacket> ConstructRequestHeadersPacket( | |
| 186 QuicPacketSequenceNumber sequence_number, | |
| 187 QuicStreamId stream_id, | |
| 188 bool should_include_version, | |
| 189 bool fin, | |
| 190 const SpdyHeaderBlock& headers) { | |
| 191 QuicPriority priority = | |
| 192 ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY); | |
| 193 return maker_.MakeRequestHeadersPacket(sequence_number, stream_id, | |
| 194 should_include_version, fin, | |
| 195 priority, headers); | |
| 196 } | |
| 197 | |
| 198 scoped_ptr<QuicEncryptedPacket> ConstructResponseHeadersPacket( | |
| 199 QuicPacketSequenceNumber sequence_number, | |
| 200 QuicStreamId stream_id, | |
| 201 bool should_include_version, | |
| 202 bool fin, | |
| 203 const SpdyHeaderBlock& headers) { | |
| 204 return maker_.MakeResponseHeadersPacket( | |
| 205 sequence_number, stream_id, should_include_version, fin, headers); | |
| 206 } | |
| 207 | |
| 208 void CreateSession() { | |
| 209 CreateSessionWithFactory(&socket_factory_, false); | |
| 210 } | |
| 211 | |
| 212 void CreateSessionWithNextProtos() { | |
| 213 CreateSessionWithFactory(&socket_factory_, true); | |
| 214 } | |
| 215 | |
| 216 // If |use_next_protos| is true, enables SPDY and QUIC. | |
| 217 void CreateSessionWithFactory(ClientSocketFactory* socket_factory, | |
| 218 bool use_next_protos) { | |
| 219 params_.enable_quic = true; | |
| 220 params_.quic_clock = clock_; | |
| 221 params_.quic_random = &random_generator_; | |
| 222 params_.client_socket_factory = socket_factory; | |
| 223 params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_; | |
| 224 params_.host_resolver = &host_resolver_; | |
| 225 params_.cert_verifier = &cert_verifier_; | |
| 226 params_.transport_security_state = &transport_security_state_; | |
| 227 params_.proxy_service = proxy_service_.get(); | |
| 228 params_.ssl_config_service = ssl_config_service_.get(); | |
| 229 params_.http_auth_handler_factory = auth_handler_factory_.get(); | |
| 230 params_.http_server_properties = http_server_properties.GetWeakPtr(); | |
| 231 params_.quic_supported_versions = SupportedVersions(GetParam()); | |
| 232 | |
| 233 if (use_next_protos) { | |
| 234 params_.use_alternate_protocols = true; | |
| 235 params_.next_protos = NextProtosWithSpdyAndQuic(true, true); | |
| 236 } | |
| 237 | |
| 238 session_ = new HttpNetworkSession(params_); | |
| 239 session_->quic_stream_factory()->set_require_confirmation(false); | |
| 240 } | |
| 241 | |
| 242 void CheckWasQuicResponse(const scoped_ptr<HttpNetworkTransaction>& trans) { | |
| 243 const HttpResponseInfo* response = trans->GetResponseInfo(); | |
| 244 ASSERT_TRUE(response != nullptr); | |
| 245 ASSERT_TRUE(response->headers.get() != nullptr); | |
| 246 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); | |
| 247 EXPECT_TRUE(response->was_fetched_via_spdy); | |
| 248 EXPECT_TRUE(response->was_npn_negotiated); | |
| 249 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3, | |
| 250 response->connection_info); | |
| 251 } | |
| 252 | |
| 253 void CheckWasHttpResponse(const scoped_ptr<HttpNetworkTransaction>& trans) { | |
| 254 const HttpResponseInfo* response = trans->GetResponseInfo(); | |
| 255 ASSERT_TRUE(response != nullptr); | |
| 256 ASSERT_TRUE(response->headers.get() != nullptr); | |
| 257 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); | |
| 258 EXPECT_FALSE(response->was_fetched_via_spdy); | |
| 259 EXPECT_FALSE(response->was_npn_negotiated); | |
| 260 EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1, | |
| 261 response->connection_info); | |
| 262 } | |
| 263 | |
| 264 void CheckResponseData(HttpNetworkTransaction* trans, | |
| 265 const std::string& expected) { | |
| 266 std::string response_data; | |
| 267 ASSERT_EQ(OK, ReadTransaction(trans, &response_data)); | |
| 268 EXPECT_EQ(expected, response_data); | |
| 269 } | |
| 270 | |
| 271 void RunTransaction(HttpNetworkTransaction* trans) { | |
| 272 TestCompletionCallback callback; | |
| 273 int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); | |
| 274 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 275 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 276 } | |
| 277 | |
| 278 void SendRequestAndExpectHttpResponse(const std::string& expected) { | |
| 279 scoped_ptr<HttpNetworkTransaction> trans( | |
| 280 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); | |
| 281 RunTransaction(trans.get()); | |
| 282 CheckWasHttpResponse(trans); | |
| 283 CheckResponseData(trans.get(), expected); | |
| 284 } | |
| 285 | |
| 286 void SendRequestAndExpectQuicResponse(const std::string& expected) { | |
| 287 SendRequestAndExpectQuicResponseMaybeFromProxy(expected, false); | |
| 288 } | |
| 289 | |
| 290 void SendRequestAndExpectQuicResponseFromProxy(const std::string& expected) { | |
| 291 SendRequestAndExpectQuicResponseMaybeFromProxy(expected, true); | |
| 292 } | |
| 293 | |
| 294 void AddQuicAlternateProtocolMapping( | |
| 295 MockCryptoClientStream::HandshakeMode handshake_mode) { | |
| 296 crypto_client_stream_factory_.set_handshake_mode(handshake_mode); | |
| 297 session_->http_server_properties()->SetAlternateProtocol( | |
| 298 HostPortPair::FromURL(request_.url), 80, QUIC, 1); | |
| 299 } | |
| 300 | |
| 301 void ExpectBrokenAlternateProtocolMapping() { | |
| 302 const AlternateProtocolInfo alternate = | |
| 303 session_->http_server_properties()->GetAlternateProtocol( | |
| 304 HostPortPair::FromURL(request_.url)); | |
| 305 EXPECT_NE(UNINITIALIZED_ALTERNATE_PROTOCOL, alternate.protocol); | |
| 306 EXPECT_TRUE(alternate.is_broken); | |
| 307 } | |
| 308 | |
| 309 void ExpectQuicAlternateProtocolMapping() { | |
| 310 const AlternateProtocolInfo alternate = | |
| 311 session_->http_server_properties()->GetAlternateProtocol( | |
| 312 HostPortPair::FromURL(request_.url)); | |
| 313 EXPECT_EQ(QUIC, alternate.protocol); | |
| 314 } | |
| 315 | |
| 316 void AddHangingNonAlternateProtocolSocketData() { | |
| 317 MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING); | |
| 318 hanging_data_.set_connect_data(hanging_connect); | |
| 319 socket_factory_.AddSocketDataProvider(&hanging_data_); | |
| 320 } | |
| 321 | |
| 322 MockClock* clock_; // Owned by QuicStreamFactory after CreateSession. | |
| 323 QuicTestPacketMaker maker_; | |
| 324 scoped_refptr<HttpNetworkSession> session_; | |
| 325 MockClientSocketFactory socket_factory_; | |
| 326 MockCryptoClientStreamFactory crypto_client_stream_factory_; | |
| 327 MockHostResolver host_resolver_; | |
| 328 MockCertVerifier cert_verifier_; | |
| 329 TransportSecurityState transport_security_state_; | |
| 330 scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_; | |
| 331 scoped_ptr<ProxyService> proxy_service_; | |
| 332 scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_; | |
| 333 MockRandom random_generator_; | |
| 334 HttpServerPropertiesImpl http_server_properties; | |
| 335 HttpNetworkSession::Params params_; | |
| 336 HttpRequestInfo request_; | |
| 337 CapturingBoundNetLog net_log_; | |
| 338 StaticSocketDataProvider hanging_data_; | |
| 339 | |
| 340 private: | |
| 341 void SendRequestAndExpectQuicResponseMaybeFromProxy( | |
| 342 const std::string& expected, | |
| 343 bool used_proxy) { | |
| 344 scoped_ptr<HttpNetworkTransaction> trans( | |
| 345 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); | |
| 346 ProxyHeadersHandler proxy_headers_handler; | |
| 347 trans->SetBeforeProxyHeadersSentCallback( | |
| 348 base::Bind(&ProxyHeadersHandler::OnBeforeProxyHeadersSent, | |
| 349 base::Unretained(&proxy_headers_handler))); | |
| 350 RunTransaction(trans.get()); | |
| 351 CheckWasQuicResponse(trans); | |
| 352 CheckResponseData(trans.get(), expected); | |
| 353 EXPECT_EQ(used_proxy, proxy_headers_handler.was_called()); | |
| 354 } | |
| 355 }; | |
| 356 | |
| 357 INSTANTIATE_TEST_CASE_P(Version, QuicNetworkTransactionTest, | |
| 358 ::testing::ValuesIn(QuicSupportedVersions())); | |
| 359 | |
| 360 TEST_P(QuicNetworkTransactionTest, ForceQuic) { | |
| 361 params_.origin_to_force_quic_on = | |
| 362 HostPortPair::FromString("www.google.com:80"); | |
| 363 | |
| 364 MockQuicData mock_quic_data; | |
| 365 mock_quic_data.AddWrite( | |
| 366 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 367 GetRequestHeaders("GET", "http", "/"))); | |
| 368 mock_quic_data.AddRead( | |
| 369 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, | |
| 370 GetResponseHeaders("200 OK"))); | |
| 371 mock_quic_data.AddRead( | |
| 372 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); | |
| 373 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 374 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF | |
| 375 | |
| 376 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); | |
| 377 | |
| 378 // The non-alternate protocol job needs to hang in order to guarantee that | |
| 379 // the alternate-protocol job will "win". | |
| 380 AddHangingNonAlternateProtocolSocketData(); | |
| 381 | |
| 382 CreateSession(); | |
| 383 | |
| 384 SendRequestAndExpectQuicResponse("hello!"); | |
| 385 | |
| 386 // Check that the NetLog was filled reasonably. | |
| 387 net::CapturingNetLog::CapturedEntryList entries; | |
| 388 net_log_.GetEntries(&entries); | |
| 389 EXPECT_LT(0u, entries.size()); | |
| 390 | |
| 391 // Check that we logged a QUIC_SESSION_PACKET_RECEIVED. | |
| 392 int pos = net::ExpectLogContainsSomewhere( | |
| 393 entries, 0, | |
| 394 net::NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED, | |
| 395 net::NetLog::PHASE_NONE); | |
| 396 EXPECT_LT(0, pos); | |
| 397 | |
| 398 // ... and also a TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED. | |
| 399 pos = net::ExpectLogContainsSomewhere( | |
| 400 entries, 0, | |
| 401 net::NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED, | |
| 402 net::NetLog::PHASE_NONE); | |
| 403 EXPECT_LT(0, pos); | |
| 404 | |
| 405 std::string packet_sequence_number; | |
| 406 ASSERT_TRUE(entries[pos].GetStringValue( | |
| 407 "packet_sequence_number", &packet_sequence_number)); | |
| 408 EXPECT_EQ("1", packet_sequence_number); | |
| 409 | |
| 410 // ... and also a QUIC_SESSION_STREAM_FRAME_RECEIVED. | |
| 411 pos = net::ExpectLogContainsSomewhere( | |
| 412 entries, 0, | |
| 413 net::NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED, | |
| 414 net::NetLog::PHASE_NONE); | |
| 415 EXPECT_LT(0, pos); | |
| 416 | |
| 417 int log_stream_id; | |
| 418 ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &log_stream_id)); | |
| 419 EXPECT_EQ(3, log_stream_id); | |
| 420 } | |
| 421 | |
| 422 TEST_P(QuicNetworkTransactionTest, QuicProxy) { | |
| 423 proxy_service_.reset( | |
| 424 ProxyService::CreateFixedFromPacResult("QUIC myproxy:70")); | |
| 425 | |
| 426 MockQuicData mock_quic_data; | |
| 427 mock_quic_data.AddWrite( | |
| 428 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 429 GetRequestHeaders("GET", "http", "/"))); | |
| 430 mock_quic_data.AddRead( | |
| 431 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, | |
| 432 GetResponseHeaders("200 OK"))); | |
| 433 mock_quic_data.AddRead( | |
| 434 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); | |
| 435 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 436 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF | |
| 437 | |
| 438 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); | |
| 439 | |
| 440 // There is no need to set up an alternate protocol job, because | |
| 441 // no attempt will be made to speak to the proxy over TCP. | |
| 442 | |
| 443 CreateSession(); | |
| 444 | |
| 445 SendRequestAndExpectQuicResponseFromProxy("hello!"); | |
| 446 } | |
| 447 | |
| 448 TEST_P(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) { | |
| 449 params_.origin_to_force_quic_on = | |
| 450 HostPortPair::FromString("www.google.com:80"); | |
| 451 | |
| 452 MockQuicData mock_quic_data; | |
| 453 mock_quic_data.AddRead(ASYNC, ERR_SOCKET_NOT_CONNECTED); | |
| 454 | |
| 455 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 0); | |
| 456 | |
| 457 CreateSession(); | |
| 458 | |
| 459 scoped_ptr<HttpNetworkTransaction> trans( | |
| 460 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); | |
| 461 TestCompletionCallback callback; | |
| 462 int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); | |
| 463 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 464 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult()); | |
| 465 } | |
| 466 | |
| 467 TEST_P(QuicNetworkTransactionTest, DoNotForceQuicForHttps) { | |
| 468 // Attempt to "force" quic on 443, which will not be honored. | |
| 469 params_.origin_to_force_quic_on = | |
| 470 HostPortPair::FromString("www.google.com:443"); | |
| 471 | |
| 472 MockRead http_reads[] = { | |
| 473 MockRead("HTTP/1.1 200 OK\r\n\r\n"), | |
| 474 MockRead("hello world"), | |
| 475 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 476 MockRead(ASYNC, OK) | |
| 477 }; | |
| 478 | |
| 479 StaticSocketDataProvider data(http_reads, arraysize(http_reads), nullptr, 0); | |
| 480 socket_factory_.AddSocketDataProvider(&data); | |
| 481 SSLSocketDataProvider ssl(ASYNC, OK); | |
| 482 socket_factory_.AddSSLSocketDataProvider(&ssl); | |
| 483 | |
| 484 CreateSession(); | |
| 485 | |
| 486 SendRequestAndExpectHttpResponse("hello world"); | |
| 487 } | |
| 488 | |
| 489 TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) { | |
| 490 MockRead http_reads[] = { | |
| 491 MockRead("HTTP/1.1 200 OK\r\n"), | |
| 492 MockRead(kQuicAlternateProtocolHttpHeader), | |
| 493 MockRead("hello world"), | |
| 494 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 495 MockRead(ASYNC, OK) | |
| 496 }; | |
| 497 | |
| 498 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 499 nullptr, 0); | |
| 500 socket_factory_.AddSocketDataProvider(&http_data); | |
| 501 | |
| 502 MockQuicData mock_quic_data; | |
| 503 mock_quic_data.AddWrite( | |
| 504 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 505 GetRequestHeaders("GET", "http", "/"))); | |
| 506 mock_quic_data.AddRead( | |
| 507 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, | |
| 508 GetResponseHeaders("200 OK"))); | |
| 509 mock_quic_data.AddRead( | |
| 510 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); | |
| 511 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 512 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF | |
| 513 | |
| 514 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); | |
| 515 | |
| 516 // The non-alternate protocol job needs to hang in order to guarantee that | |
| 517 // the alternate-protocol job will "win". | |
| 518 AddHangingNonAlternateProtocolSocketData(); | |
| 519 | |
| 520 CreateSessionWithNextProtos(); | |
| 521 | |
| 522 SendRequestAndExpectHttpResponse("hello world"); | |
| 523 SendRequestAndExpectQuicResponse("hello!"); | |
| 524 } | |
| 525 | |
| 526 TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolProbabilityForQuic) { | |
| 527 MockRead http_reads[] = { | |
| 528 MockRead("HTTP/1.1 200 OK\r\n"), | |
| 529 MockRead(kQuicAlternateProtocol50pctHttpHeader), | |
| 530 MockRead("hello world"), | |
| 531 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 532 MockRead(ASYNC, OK) | |
| 533 }; | |
| 534 | |
| 535 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 536 nullptr, 0); | |
| 537 socket_factory_.AddSocketDataProvider(&http_data); | |
| 538 | |
| 539 MockQuicData mock_quic_data; | |
| 540 mock_quic_data.AddWrite( | |
| 541 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 542 GetRequestHeaders("GET", "http", "/"))); | |
| 543 mock_quic_data.AddRead( | |
| 544 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, | |
| 545 GetResponseHeaders("200 OK"))); | |
| 546 mock_quic_data.AddRead( | |
| 547 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); | |
| 548 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 549 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF | |
| 550 | |
| 551 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); | |
| 552 | |
| 553 // The non-alternate protocol job needs to hang in order to guarantee that | |
| 554 // the alternate-protocol job will "win". | |
| 555 AddHangingNonAlternateProtocolSocketData(); | |
| 556 | |
| 557 params_.alternate_protocol_probability_threshold = .25; | |
| 558 CreateSessionWithNextProtos(); | |
| 559 | |
| 560 SendRequestAndExpectHttpResponse("hello world"); | |
| 561 SendRequestAndExpectQuicResponse("hello!"); | |
| 562 } | |
| 563 | |
| 564 TEST_P(QuicNetworkTransactionTest, DontUseAlternateProtocolProbabilityForQuic) { | |
| 565 MockRead http_reads[] = { | |
| 566 MockRead("HTTP/1.1 200 OK\r\n"), | |
| 567 MockRead(kQuicAlternateProtocol50pctHttpHeader), | |
| 568 MockRead("hello world"), | |
| 569 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 570 MockRead(ASYNC, OK) | |
| 571 }; | |
| 572 | |
| 573 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 574 nullptr, 0); | |
| 575 socket_factory_.AddSocketDataProvider(&http_data); | |
| 576 socket_factory_.AddSocketDataProvider(&http_data); | |
| 577 | |
| 578 params_.alternate_protocol_probability_threshold = .75; | |
| 579 CreateSessionWithNextProtos(); | |
| 580 | |
| 581 SendRequestAndExpectHttpResponse("hello world"); | |
| 582 SendRequestAndExpectHttpResponse("hello world"); | |
| 583 } | |
| 584 | |
| 585 TEST_P(QuicNetworkTransactionTest, | |
| 586 DontUseAlternateProtocolWithBadProbabilityForQuic) { | |
| 587 MockRead http_reads[] = { | |
| 588 MockRead("HTTP/1.1 200 OK\r\n"), | |
| 589 MockRead("Alternate-Protocol: 443:quic,p=2\r\n\r\n"), | |
| 590 MockRead("hello world"), | |
| 591 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 592 MockRead(ASYNC, OK) | |
| 593 }; | |
| 594 | |
| 595 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 596 nullptr, 0); | |
| 597 socket_factory_.AddSocketDataProvider(&http_data); | |
| 598 socket_factory_.AddSocketDataProvider(&http_data); | |
| 599 | |
| 600 params_.alternate_protocol_probability_threshold = .75; | |
| 601 CreateSessionWithNextProtos(); | |
| 602 | |
| 603 SendRequestAndExpectHttpResponse("hello world"); | |
| 604 SendRequestAndExpectHttpResponse("hello world"); | |
| 605 } | |
| 606 | |
| 607 TEST_P(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) { | |
| 608 params_.origin_to_force_quic_on = | |
| 609 HostPortPair::FromString("www.google.com:443"); | |
| 610 | |
| 611 MockRead http_reads[] = { | |
| 612 MockRead("HTTP/1.1 200 OK\r\n"), | |
| 613 MockRead(kQuicAlternateProtocolHttpsHeader), | |
| 614 MockRead("hello world"), | |
| 615 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 616 MockRead(ASYNC, OK) | |
| 617 }; | |
| 618 | |
| 619 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 620 nullptr, 0); | |
| 621 socket_factory_.AddSocketDataProvider(&http_data); | |
| 622 | |
| 623 MockQuicData mock_quic_data; | |
| 624 mock_quic_data.AddWrite( | |
| 625 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 626 GetRequestHeaders("GET", "http", "/"))); | |
| 627 mock_quic_data.AddRead( | |
| 628 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, | |
| 629 GetResponseHeaders("200 OK"))); | |
| 630 mock_quic_data.AddRead( | |
| 631 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); | |
| 632 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 633 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF | |
| 634 | |
| 635 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); | |
| 636 | |
| 637 // The non-alternate protocol job needs to hang in order to guarantee that | |
| 638 // the alternate-protocol job will "win". | |
| 639 AddHangingNonAlternateProtocolSocketData(); | |
| 640 | |
| 641 CreateSessionWithNextProtos(); | |
| 642 | |
| 643 // TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo(). | |
| 644 SendRequestAndExpectHttpResponse("hello world"); | |
| 645 } | |
| 646 | |
| 647 TEST_P(QuicNetworkTransactionTest, HungAlternateProtocol) { | |
| 648 crypto_client_stream_factory_.set_handshake_mode( | |
| 649 MockCryptoClientStream::COLD_START); | |
| 650 | |
| 651 MockWrite http_writes[] = { | |
| 652 MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), | |
| 653 MockWrite(SYNCHRONOUS, 1, "Host: www.google.com\r\n"), | |
| 654 MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n") | |
| 655 }; | |
| 656 | |
| 657 MockRead http_reads[] = { | |
| 658 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"), | |
| 659 MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHttpHeader), | |
| 660 MockRead(SYNCHRONOUS, 5, "hello world"), | |
| 661 MockRead(SYNCHRONOUS, OK, 6) | |
| 662 }; | |
| 663 | |
| 664 DeterministicMockClientSocketFactory socket_factory; | |
| 665 | |
| 666 DeterministicSocketData http_data(http_reads, arraysize(http_reads), | |
| 667 http_writes, arraysize(http_writes)); | |
| 668 socket_factory.AddSocketDataProvider(&http_data); | |
| 669 | |
| 670 // The QUIC transaction will not be allowed to complete. | |
| 671 MockWrite quic_writes[] = { | |
| 672 MockWrite(ASYNC, ERR_IO_PENDING, 0) | |
| 673 }; | |
| 674 MockRead quic_reads[] = { | |
| 675 MockRead(ASYNC, ERR_IO_PENDING, 1), | |
| 676 }; | |
| 677 DeterministicSocketData quic_data(quic_reads, arraysize(quic_reads), | |
| 678 quic_writes, arraysize(quic_writes)); | |
| 679 socket_factory.AddSocketDataProvider(&quic_data); | |
| 680 | |
| 681 // The HTTP transaction will complete. | |
| 682 DeterministicSocketData http_data2(http_reads, arraysize(http_reads), | |
| 683 http_writes, arraysize(http_writes)); | |
| 684 socket_factory.AddSocketDataProvider(&http_data2); | |
| 685 | |
| 686 CreateSessionWithFactory(&socket_factory, true); | |
| 687 | |
| 688 // Run the first request. | |
| 689 http_data.StopAfter(arraysize(http_reads) + arraysize(http_writes)); | |
| 690 SendRequestAndExpectHttpResponse("hello world"); | |
| 691 ASSERT_TRUE(http_data.at_read_eof()); | |
| 692 ASSERT_TRUE(http_data.at_write_eof()); | |
| 693 | |
| 694 // Now run the second request in which the QUIC socket hangs, | |
| 695 // and verify the the transaction continues over HTTP. | |
| 696 http_data2.StopAfter(arraysize(http_reads) + arraysize(http_writes)); | |
| 697 SendRequestAndExpectHttpResponse("hello world"); | |
| 698 | |
| 699 ASSERT_TRUE(http_data2.at_read_eof()); | |
| 700 ASSERT_TRUE(http_data2.at_write_eof()); | |
| 701 ASSERT_TRUE(!quic_data.at_read_eof()); | |
| 702 ASSERT_TRUE(!quic_data.at_write_eof()); | |
| 703 } | |
| 704 | |
| 705 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) { | |
| 706 MockQuicData mock_quic_data; | |
| 707 mock_quic_data.AddWrite( | |
| 708 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 709 GetRequestHeaders("GET", "http", "/"))); | |
| 710 mock_quic_data.AddRead( | |
| 711 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, | |
| 712 GetResponseHeaders("200 OK"))); | |
| 713 mock_quic_data.AddRead( | |
| 714 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); | |
| 715 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 716 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF | |
| 717 | |
| 718 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); | |
| 719 | |
| 720 // The non-alternate protocol job needs to hang in order to guarantee that | |
| 721 // the alternate-protocol job will "win". | |
| 722 AddHangingNonAlternateProtocolSocketData(); | |
| 723 | |
| 724 CreateSessionWithNextProtos(); | |
| 725 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); | |
| 726 SendRequestAndExpectQuicResponse("hello!"); | |
| 727 } | |
| 728 | |
| 729 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) { | |
| 730 MockQuicData mock_quic_data; | |
| 731 mock_quic_data.AddWrite( | |
| 732 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 733 GetRequestHeaders("GET", "http", "/"))); | |
| 734 mock_quic_data.AddRead( | |
| 735 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, | |
| 736 GetResponseHeaders("200 OK"))); | |
| 737 mock_quic_data.AddRead( | |
| 738 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); | |
| 739 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 740 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF | |
| 741 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); | |
| 742 | |
| 743 // In order for a new QUIC session to be established via alternate-protocol | |
| 744 // without racing an HTTP connection, we need the host resolution to happen | |
| 745 // synchronously. | |
| 746 host_resolver_.set_synchronous_mode(true); | |
| 747 host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", ""); | |
| 748 HostResolver::RequestInfo info(HostPortPair("www.google.com", 80)); | |
| 749 AddressList address; | |
| 750 host_resolver_.Resolve(info, | |
| 751 DEFAULT_PRIORITY, | |
| 752 &address, | |
| 753 CompletionCallback(), | |
| 754 nullptr, | |
| 755 net_log_.bound()); | |
| 756 | |
| 757 CreateSessionWithNextProtos(); | |
| 758 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); | |
| 759 SendRequestAndExpectQuicResponse("hello!"); | |
| 760 } | |
| 761 | |
| 762 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) { | |
| 763 proxy_service_.reset( | |
| 764 ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); | |
| 765 | |
| 766 // Since we are using a proxy, the QUIC job will not succeed. | |
| 767 MockWrite http_writes[] = { | |
| 768 MockWrite(SYNCHRONOUS, 0, "GET http://www.google.com/ HTTP/1.1\r\n"), | |
| 769 MockWrite(SYNCHRONOUS, 1, "Host: www.google.com\r\n"), | |
| 770 MockWrite(SYNCHRONOUS, 2, "Proxy-Connection: keep-alive\r\n\r\n") | |
| 771 }; | |
| 772 | |
| 773 MockRead http_reads[] = { | |
| 774 MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"), | |
| 775 MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHttpHeader), | |
| 776 MockRead(SYNCHRONOUS, 5, "hello world"), | |
| 777 MockRead(SYNCHRONOUS, OK, 6) | |
| 778 }; | |
| 779 | |
| 780 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 781 http_writes, arraysize(http_writes)); | |
| 782 socket_factory_.AddSocketDataProvider(&http_data); | |
| 783 | |
| 784 // In order for a new QUIC session to be established via alternate-protocol | |
| 785 // without racing an HTTP connection, we need the host resolution to happen | |
| 786 // synchronously. | |
| 787 host_resolver_.set_synchronous_mode(true); | |
| 788 host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", ""); | |
| 789 HostResolver::RequestInfo info(HostPortPair("www.google.com", 80)); | |
| 790 AddressList address; | |
| 791 host_resolver_.Resolve(info, | |
| 792 DEFAULT_PRIORITY, | |
| 793 &address, | |
| 794 CompletionCallback(), | |
| 795 nullptr, | |
| 796 net_log_.bound()); | |
| 797 | |
| 798 CreateSessionWithNextProtos(); | |
| 799 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); | |
| 800 SendRequestAndExpectHttpResponse("hello world"); | |
| 801 } | |
| 802 | |
| 803 TEST_P(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) { | |
| 804 MockQuicData mock_quic_data; | |
| 805 mock_quic_data.AddWrite( | |
| 806 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 807 GetRequestHeaders("GET", "http", "/"))); | |
| 808 mock_quic_data.AddRead( | |
| 809 ConstructResponseHeadersPacket(1, kClientDataStreamId1, false, false, | |
| 810 GetResponseHeaders("200 OK"))); | |
| 811 mock_quic_data.AddRead( | |
| 812 ConstructDataPacket(2, kClientDataStreamId1, false, true, 0, "hello!")); | |
| 813 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 814 mock_quic_data.AddRead(SYNCHRONOUS, 0); // EOF | |
| 815 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 1); | |
| 816 | |
| 817 // The non-alternate protocol job needs to hang in order to guarantee that | |
| 818 // the alternate-protocol job will "win". | |
| 819 AddHangingNonAlternateProtocolSocketData(); | |
| 820 | |
| 821 // In order for a new QUIC session to be established via alternate-protocol | |
| 822 // without racing an HTTP connection, we need the host resolution to happen | |
| 823 // synchronously. Of course, even though QUIC *could* perform a 0-RTT | |
| 824 // connection to the the server, in this test we require confirmation | |
| 825 // before encrypting so the HTTP job will still start. | |
| 826 host_resolver_.set_synchronous_mode(true); | |
| 827 host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", ""); | |
| 828 HostResolver::RequestInfo info(HostPortPair("www.google.com", 80)); | |
| 829 AddressList address; | |
| 830 host_resolver_.Resolve(info, DEFAULT_PRIORITY, &address, | |
| 831 CompletionCallback(), nullptr, net_log_.bound()); | |
| 832 | |
| 833 CreateSessionWithNextProtos(); | |
| 834 session_->quic_stream_factory()->set_require_confirmation(true); | |
| 835 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); | |
| 836 | |
| 837 scoped_ptr<HttpNetworkTransaction> trans( | |
| 838 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); | |
| 839 TestCompletionCallback callback; | |
| 840 int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); | |
| 841 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 842 | |
| 843 crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent( | |
| 844 QuicSession::HANDSHAKE_CONFIRMED); | |
| 845 EXPECT_EQ(OK, callback.WaitForResult()); | |
| 846 } | |
| 847 | |
| 848 TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocol) { | |
| 849 // Alternate-protocol job | |
| 850 scoped_ptr<QuicEncryptedPacket> close(ConstructConnectionClosePacket(1)); | |
| 851 MockRead quic_reads[] = { | |
| 852 MockRead(ASYNC, close->data(), close->length()), | |
| 853 MockRead(ASYNC, OK), // EOF | |
| 854 }; | |
| 855 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), | |
| 856 nullptr, 0); | |
| 857 socket_factory_.AddSocketDataProvider(&quic_data); | |
| 858 | |
| 859 // Main job which will succeed even though the alternate job fails. | |
| 860 MockRead http_reads[] = { | |
| 861 MockRead("HTTP/1.1 200 OK\r\n\r\n"), | |
| 862 MockRead("hello from http"), | |
| 863 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 864 MockRead(ASYNC, OK) | |
| 865 }; | |
| 866 | |
| 867 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 868 nullptr, 0); | |
| 869 socket_factory_.AddSocketDataProvider(&http_data); | |
| 870 | |
| 871 CreateSessionWithNextProtos(); | |
| 872 AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START); | |
| 873 SendRequestAndExpectHttpResponse("hello from http"); | |
| 874 ExpectBrokenAlternateProtocolMapping(); | |
| 875 } | |
| 876 | |
| 877 TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) { | |
| 878 // Alternate-protocol job | |
| 879 MockRead quic_reads[] = { | |
| 880 MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED), | |
| 881 }; | |
| 882 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), | |
| 883 nullptr, 0); | |
| 884 socket_factory_.AddSocketDataProvider(&quic_data); | |
| 885 | |
| 886 // Main job which will succeed even though the alternate job fails. | |
| 887 MockRead http_reads[] = { | |
| 888 MockRead("HTTP/1.1 200 OK\r\n\r\n"), | |
| 889 MockRead("hello from http"), | |
| 890 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 891 MockRead(ASYNC, OK) | |
| 892 }; | |
| 893 | |
| 894 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 895 nullptr, 0); | |
| 896 socket_factory_.AddSocketDataProvider(&http_data); | |
| 897 | |
| 898 CreateSessionWithNextProtos(); | |
| 899 | |
| 900 AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START); | |
| 901 SendRequestAndExpectHttpResponse("hello from http"); | |
| 902 ExpectBrokenAlternateProtocolMapping(); | |
| 903 } | |
| 904 | |
| 905 TEST_P(QuicNetworkTransactionTest, NoBrokenAlternateProtocolIfTcpFails) { | |
| 906 // Alternate-protocol job will fail when the session attempts to read. | |
| 907 MockRead quic_reads[] = { | |
| 908 MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED), | |
| 909 }; | |
| 910 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), | |
| 911 nullptr, 0); | |
| 912 socket_factory_.AddSocketDataProvider(&quic_data); | |
| 913 | |
| 914 // Main job will also fail. | |
| 915 MockRead http_reads[] = { | |
| 916 MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED), | |
| 917 }; | |
| 918 | |
| 919 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 920 nullptr, 0); | |
| 921 http_data.set_connect_data(MockConnect(ASYNC, ERR_SOCKET_NOT_CONNECTED)); | |
| 922 socket_factory_.AddSocketDataProvider(&http_data); | |
| 923 | |
| 924 CreateSessionWithNextProtos(); | |
| 925 | |
| 926 AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START); | |
| 927 scoped_ptr<HttpNetworkTransaction> trans( | |
| 928 new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get())); | |
| 929 TestCompletionCallback callback; | |
| 930 int rv = trans->Start(&request_, callback.callback(), net_log_.bound()); | |
| 931 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 932 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, callback.WaitForResult()); | |
| 933 ExpectQuicAlternateProtocolMapping(); | |
| 934 } | |
| 935 | |
| 936 TEST_P(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) { | |
| 937 // Alternate-protocol job | |
| 938 MockRead quic_reads[] = { | |
| 939 MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED), | |
| 940 }; | |
| 941 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), | |
| 942 nullptr, 0); | |
| 943 socket_factory_.AddSocketDataProvider(&quic_data); | |
| 944 | |
| 945 AddHangingNonAlternateProtocolSocketData(); | |
| 946 | |
| 947 // Second Alternate-protocol job which will race with the TCP job. | |
| 948 StaticSocketDataProvider quic_data2(quic_reads, arraysize(quic_reads), | |
| 949 nullptr, 0); | |
| 950 socket_factory_.AddSocketDataProvider(&quic_data2); | |
| 951 | |
| 952 // Final job that will proceed when the QUIC job fails. | |
| 953 MockRead http_reads[] = { | |
| 954 MockRead("HTTP/1.1 200 OK\r\n\r\n"), | |
| 955 MockRead("hello from http"), | |
| 956 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 957 MockRead(ASYNC, OK) | |
| 958 }; | |
| 959 | |
| 960 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 961 nullptr, 0); | |
| 962 socket_factory_.AddSocketDataProvider(&http_data); | |
| 963 | |
| 964 CreateSessionWithNextProtos(); | |
| 965 | |
| 966 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); | |
| 967 | |
| 968 SendRequestAndExpectHttpResponse("hello from http"); | |
| 969 | |
| 970 ExpectBrokenAlternateProtocolMapping(); | |
| 971 | |
| 972 EXPECT_TRUE(quic_data.at_read_eof()); | |
| 973 EXPECT_TRUE(quic_data.at_write_eof()); | |
| 974 } | |
| 975 | |
| 976 TEST_P(QuicNetworkTransactionTest, DISABLED_HangingZeroRttFallback) { | |
| 977 // Alternate-protocol job | |
| 978 MockRead quic_reads[] = { | |
| 979 MockRead(ASYNC, ERR_IO_PENDING), | |
| 980 }; | |
| 981 StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads), | |
| 982 nullptr, 0); | |
| 983 socket_factory_.AddSocketDataProvider(&quic_data); | |
| 984 | |
| 985 // Main job that will proceed when the QUIC job fails. | |
| 986 MockRead http_reads[] = { | |
| 987 MockRead("HTTP/1.1 200 OK\r\n\r\n"), | |
| 988 MockRead("hello from http"), | |
| 989 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 990 MockRead(ASYNC, OK) | |
| 991 }; | |
| 992 | |
| 993 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 994 nullptr, 0); | |
| 995 socket_factory_.AddSocketDataProvider(&http_data); | |
| 996 | |
| 997 CreateSessionWithNextProtos(); | |
| 998 | |
| 999 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); | |
| 1000 | |
| 1001 SendRequestAndExpectHttpResponse("hello from http"); | |
| 1002 } | |
| 1003 | |
| 1004 TEST_P(QuicNetworkTransactionTest, BrokenAlternateProtocolOnConnectFailure) { | |
| 1005 // Alternate-protocol job will fail before creating a QUIC session. | |
| 1006 StaticSocketDataProvider quic_data(nullptr, 0, nullptr, 0); | |
| 1007 quic_data.set_connect_data(MockConnect(SYNCHRONOUS, | |
| 1008 ERR_INTERNET_DISCONNECTED)); | |
| 1009 socket_factory_.AddSocketDataProvider(&quic_data); | |
| 1010 | |
| 1011 // Main job which will succeed even though the alternate job fails. | |
| 1012 MockRead http_reads[] = { | |
| 1013 MockRead("HTTP/1.1 200 OK\r\n\r\n"), | |
| 1014 MockRead("hello from http"), | |
| 1015 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 1016 MockRead(ASYNC, OK) | |
| 1017 }; | |
| 1018 | |
| 1019 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 1020 nullptr, 0); | |
| 1021 socket_factory_.AddSocketDataProvider(&http_data); | |
| 1022 | |
| 1023 CreateSessionWithNextProtos(); | |
| 1024 AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START); | |
| 1025 SendRequestAndExpectHttpResponse("hello from http"); | |
| 1026 | |
| 1027 ExpectBrokenAlternateProtocolMapping(); | |
| 1028 } | |
| 1029 | |
| 1030 TEST_P(QuicNetworkTransactionTest, ConnectionCloseDuringConnect) { | |
| 1031 MockQuicData mock_quic_data; | |
| 1032 mock_quic_data.AddRead(ConstructConnectionClosePacket(1)); | |
| 1033 mock_quic_data.AddWrite( | |
| 1034 ConstructRequestHeadersPacket(1, kClientDataStreamId1, true, true, | |
| 1035 GetRequestHeaders("GET", "http", "/"))); | |
| 1036 mock_quic_data.AddWrite(ConstructAckPacket(2, 1)); | |
| 1037 mock_quic_data.AddDelayedSocketDataToFactory(&socket_factory_, 0); | |
| 1038 | |
| 1039 // When the QUIC connection fails, we will try the request again over HTTP. | |
| 1040 MockRead http_reads[] = { | |
| 1041 MockRead("HTTP/1.1 200 OK\r\n"), | |
| 1042 MockRead(kQuicAlternateProtocolHttpHeader), | |
| 1043 MockRead("hello world"), | |
| 1044 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), | |
| 1045 MockRead(ASYNC, OK) | |
| 1046 }; | |
| 1047 | |
| 1048 StaticSocketDataProvider http_data(http_reads, arraysize(http_reads), | |
| 1049 nullptr, 0); | |
| 1050 socket_factory_.AddSocketDataProvider(&http_data); | |
| 1051 | |
| 1052 // In order for a new QUIC session to be established via alternate-protocol | |
| 1053 // without racing an HTTP connection, we need the host resolution to happen | |
| 1054 // synchronously. | |
| 1055 host_resolver_.set_synchronous_mode(true); | |
| 1056 host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", ""); | |
| 1057 HostResolver::RequestInfo info(HostPortPair("www.google.com", 80)); | |
| 1058 AddressList address; | |
| 1059 host_resolver_.Resolve(info, | |
| 1060 DEFAULT_PRIORITY, | |
| 1061 &address, | |
| 1062 CompletionCallback(), | |
| 1063 nullptr, | |
| 1064 net_log_.bound()); | |
| 1065 | |
| 1066 CreateSessionWithNextProtos(); | |
| 1067 AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT); | |
| 1068 SendRequestAndExpectHttpResponse("hello world"); | |
| 1069 } | |
| 1070 | |
| 1071 } // namespace test | |
| 1072 } // namespace net | |
| OLD | NEW |