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 |