quic_network_transaction_unittest.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
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 "base/basictypes.h"
6#include "base/compiler_specific.h"
7#include "base/memory/scoped_ptr.h"
8#include "base/stl_util.h"
9#include "net/base/capturing_net_log.h"
10#include "net/base/net_log_unittest.h"
11#include "net/base/test_completion_callback.h"
12#include "net/cert/mock_cert_verifier.h"
13#include "net/dns/mock_host_resolver.h"
14#include "net/http/http_auth_handler_factory.h"
15#include "net/http/http_network_session.h"
16#include "net/http/http_network_transaction.h"
17#include "net/http/http_server_properties_impl.h"
18#include "net/http/http_stream.h"
19#include "net/http/http_stream_factory.h"
20#include "net/http/http_transaction_unittest.h"
21#include "net/http/transport_security_state.h"
22#include "net/proxy/proxy_config_service_fixed.h"
23#include "net/proxy/proxy_resolver.h"
24#include "net/proxy/proxy_service.h"
25#include "net/quic/crypto/quic_decrypter.h"
26#include "net/quic/crypto/quic_encrypter.h"
27#include "net/quic/quic_framer.h"
28#include "net/quic/test_tools/crypto_test_utils.h"
29#include "net/quic/test_tools/mock_clock.h"
30#include "net/quic/test_tools/mock_crypto_client_stream_factory.h"
31#include "net/quic/test_tools/mock_random.h"
32#include "net/quic/test_tools/quic_test_utils.h"
33#include "net/socket/client_socket_factory.h"
34#include "net/socket/mock_client_socket_pool_manager.h"
35#include "net/socket/socket_test_util.h"
36#include "net/socket/ssl_client_socket.h"
37#include "net/spdy/spdy_frame_builder.h"
38#include "net/spdy/spdy_framer.h"
39#include "net/ssl/ssl_config_service_defaults.h"
40#include "testing/gtest/include/gtest/gtest.h"
41#include "testing/platform_test.h"
42
43//-----------------------------------------------------------------------------
44
45namespace {
46
47// This is the expected return from a current server advertising QUIC.
48static const char kQuicAlternateProtocolHttpHeader[] =
49    "Alternate-Protocol: 80:quic\r\n\r\n";
50static const char kQuicAlternateProtocolHttpsHeader[] =
51    "Alternate-Protocol: 443:quic\r\n\r\n";
52}  // namespace
53
54namespace net {
55namespace test {
56
57class QuicNetworkTransactionTest : public PlatformTest {
58 protected:
59  QuicNetworkTransactionTest()
60      : clock_(new MockClock),
61        ssl_config_service_(new SSLConfigServiceDefaults),
62        proxy_service_(ProxyService::CreateDirect()),
63        compressor_(new QuicSpdyCompressor()),
64        auth_handler_factory_(
65            HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
66        hanging_data_(NULL, 0, NULL, 0) {
67    request_.method = "GET";
68    request_.url = GURL("http://www.google.com/");
69    request_.load_flags = 0;
70  }
71
72  virtual void SetUp() {
73    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
74    base::MessageLoop::current()->RunUntilIdle();
75  }
76
77  virtual void TearDown() {
78    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
79    // Empty the current queue.
80    base::MessageLoop::current()->RunUntilIdle();
81    PlatformTest::TearDown();
82    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
83    base::MessageLoop::current()->RunUntilIdle();
84    HttpStreamFactory::set_use_alternate_protocols(false);
85    HttpStreamFactory::SetNextProtos(std::vector<NextProto>());
86  }
87
88  scoped_ptr<QuicEncryptedPacket> ConstructRstPacket(
89      QuicPacketSequenceNumber num,
90      QuicStreamId stream_id) {
91    QuicPacketHeader header;
92    header.public_header.guid = 0xDEADBEEF;
93    header.public_header.reset_flag = false;
94    header.public_header.version_flag = false;
95    header.packet_sequence_number = num;
96    header.entropy_flag = false;
97    header.fec_flag = false;
98    header.fec_group = 0;
99
100    QuicRstStreamFrame rst(stream_id, QUIC_STREAM_NO_ERROR);
101    return scoped_ptr<QuicEncryptedPacket>(
102        ConstructPacket(header, QuicFrame(&rst)));
103  }
104
105  scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket(
106      QuicPacketSequenceNumber num) {
107    QuicPacketHeader header;
108    header.public_header.guid = 0xDEADBEEF;
109    header.public_header.reset_flag = false;
110    header.public_header.version_flag = false;
111    header.packet_sequence_number = num;
112    header.entropy_flag = false;
113    header.fec_flag = false;
114    header.fec_group = 0;
115
116    QuicAckFrame ack_frame(0, QuicTime::Zero(), 0);
117    QuicConnectionCloseFrame close;
118    close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
119    close.error_details = "Time to panic!";
120    close.ack_frame = ack_frame;
121    return scoped_ptr<QuicEncryptedPacket>(
122        ConstructPacket(header, QuicFrame(&close)));
123  }
124
125  scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
126      QuicPacketSequenceNumber largest_received,
127      QuicPacketSequenceNumber least_unacked) {
128    QuicPacketHeader header;
129    header.public_header.guid = 0xDEADBEEF;
130    header.public_header.reset_flag = false;
131    header.public_header.version_flag = false;
132    header.packet_sequence_number = 2;
133    header.entropy_flag = false;
134    header.fec_flag = false;
135    header.fec_group = 0;
136
137    QuicAckFrame ack(largest_received, QuicTime::Zero(), least_unacked);
138
139    QuicCongestionFeedbackFrame feedback;
140    feedback.type = kTCP;
141    feedback.tcp.accumulated_number_of_lost_packets = 0;
142    feedback.tcp.receive_window = 256000;
143
144    QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
145    QuicFrames frames;
146    frames.push_back(QuicFrame(&ack));
147    frames.push_back(QuicFrame(&feedback));
148    scoped_ptr<QuicPacket> packet(
149        framer.ConstructFrameDataPacket(header, frames).packet);
150    return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
151        ENCRYPTION_NONE, header.packet_sequence_number, *packet));
152  }
153
154  std::string GetRequestString(const std::string& method,
155                               const std::string& scheme,
156                               const std::string& path) {
157    SpdyHeaderBlock headers;
158    headers[":method"] = method;
159    headers[":host"] = "www.google.com";
160    headers[":path"] = path;
161    headers[":scheme"] = scheme;
162    headers[":version"] = "HTTP/1.1";
163    return SerializeHeaderBlock(headers);
164  }
165
166  std::string GetResponseString(const std::string& status,
167                                const std::string& body) {
168    SpdyHeaderBlock headers;
169    headers[":status"] = status;
170    headers[":version"] = "HTTP/1.1";
171    headers["content-type"] = "text/plain";
172    return compressor_->CompressHeaders(headers) + body;
173  }
174
175  std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
176    QuicSpdyCompressor compressor;
177    return compressor.CompressHeaders(headers);
178  }
179
180  // Returns a newly created packet to send kData on stream 1.
181  QuicEncryptedPacket* ConstructDataPacket(
182      QuicPacketSequenceNumber sequence_number,
183      QuicStreamId stream_id,
184      bool should_include_version,
185      bool fin,
186      QuicStreamOffset offset,
187      base::StringPiece data) {
188    InitializeHeader(sequence_number, should_include_version);
189    QuicStreamFrame frame(stream_id, fin, offset, data);
190    return ConstructPacket(header_, QuicFrame(&frame)).release();
191  }
192
193  scoped_ptr<QuicEncryptedPacket> ConstructPacket(
194      const QuicPacketHeader& header,
195      const QuicFrame& frame) {
196    QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
197    QuicFrames frames;
198    frames.push_back(frame);
199    scoped_ptr<QuicPacket> packet(
200        framer.ConstructFrameDataPacket(header, frames).packet);
201    return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
202        ENCRYPTION_NONE, header.packet_sequence_number, *packet));
203  }
204
205  void InitializeHeader(QuicPacketSequenceNumber sequence_number,
206                        bool should_include_version) {
207    header_.public_header.guid = random_generator_.RandUint64();
208    header_.public_header.reset_flag = false;
209    header_.public_header.version_flag = should_include_version;
210    header_.packet_sequence_number = sequence_number;
211    header_.fec_group = 0;
212    header_.entropy_flag = false;
213    header_.fec_flag = false;
214  }
215
216  void CreateSession() {
217    CreateSessionWithFactory(&socket_factory_);
218  }
219
220  void CreateSessionWithFactory(ClientSocketFactory* socket_factory) {
221    params_.enable_quic = true;
222    params_.quic_clock = clock_;
223    params_.quic_random = &random_generator_;
224    params_.client_socket_factory = socket_factory;
225    params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
226    params_.host_resolver = &host_resolver_;
227    params_.cert_verifier = &cert_verifier_;
228    params_.transport_security_state = &transport_security_state_;
229    params_.proxy_service = proxy_service_.get();
230    params_.ssl_config_service = ssl_config_service_.get();
231    params_.http_auth_handler_factory = auth_handler_factory_.get();
232    params_.http_server_properties = http_server_properties.GetWeakPtr();
233
234    session_ = new HttpNetworkSession(params_);
235  }
236
237  void CheckWasQuicResponse(const scoped_ptr<HttpNetworkTransaction>& trans) {
238    const HttpResponseInfo* response = trans->GetResponseInfo();
239    ASSERT_TRUE(response != NULL);
240    ASSERT_TRUE(response->headers.get() != NULL);
241    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
242    EXPECT_TRUE(response->was_fetched_via_spdy);
243    EXPECT_TRUE(response->was_npn_negotiated);
244    EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3,
245              response->connection_info);
246  }
247
248  void CheckWasHttpResponse(const scoped_ptr<HttpNetworkTransaction>& trans) {
249    const HttpResponseInfo* response = trans->GetResponseInfo();
250    ASSERT_TRUE(response != NULL);
251    ASSERT_TRUE(response->headers.get() != NULL);
252    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
253    EXPECT_FALSE(response->was_fetched_via_spdy);
254    EXPECT_FALSE(response->was_npn_negotiated);
255    EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
256              response->connection_info);
257  }
258
259  void CheckResponseData(HttpNetworkTransaction* trans,
260                         const std::string& expected) {
261    std::string response_data;
262    ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
263    EXPECT_EQ(expected, response_data);
264  }
265
266  void RunTransaction(HttpNetworkTransaction* trans) {
267    TestCompletionCallback callback;
268    int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
269    EXPECT_EQ(ERR_IO_PENDING, rv);
270    EXPECT_EQ(OK, callback.WaitForResult());
271  }
272
273  void SendRequestAndExpectHttpResponse(const std::string& expected) {
274    scoped_ptr<HttpNetworkTransaction> trans(
275        new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
276    RunTransaction(trans.get());
277    CheckWasHttpResponse(trans);
278    CheckResponseData(trans.get(), expected);
279  }
280
281  void SendRequestAndExpectQuicResponse(const std::string& expected) {
282    scoped_ptr<HttpNetworkTransaction> trans(
283        new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
284    RunTransaction(trans.get());
285    CheckWasQuicResponse(trans);
286    CheckResponseData(trans.get(), expected);
287  }
288
289  void AddQuicAlternateProtocolMapping(
290      MockCryptoClientStream::HandshakeMode handshake_mode) {
291    crypto_client_stream_factory_.set_handshake_mode(handshake_mode);
292    session_->http_server_properties()->SetAlternateProtocol(
293        HostPortPair::FromURL(request_.url), 80, QUIC);
294  }
295
296  void ExpectBrokenAlternateProtocolMapping() {
297    ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
298        HostPortPair::FromURL(request_.url)));
299    const PortAlternateProtocolPair alternate =
300        session_->http_server_properties()->GetAlternateProtocol(
301            HostPortPair::FromURL(request_.url));
302    EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
303  }
304
305  void AddHangingNonAlternateProtocolSocketData() {
306    MockConnect hanging_connect(SYNCHRONOUS, ERR_IO_PENDING);
307    hanging_data_.set_connect_data(hanging_connect);
308    socket_factory_.AddSocketDataProvider(&hanging_data_);
309  }
310
311  QuicPacketHeader header_;
312  scoped_refptr<HttpNetworkSession> session_;
313  MockClientSocketFactory socket_factory_;
314  MockCryptoClientStreamFactory crypto_client_stream_factory_;
315  MockClock* clock_;  // Owned by QuicStreamFactory after CreateSession.
316  MockHostResolver host_resolver_;
317  MockCertVerifier cert_verifier_;
318  TransportSecurityState transport_security_state_;
319  scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
320  scoped_ptr<ProxyService> proxy_service_;
321  scoped_ptr<QuicSpdyCompressor> compressor_;
322  scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
323  MockRandom random_generator_;
324  HttpServerPropertiesImpl http_server_properties;
325  HttpNetworkSession::Params params_;
326  HttpRequestInfo request_;
327  CapturingBoundNetLog net_log_;
328  StaticSocketDataProvider hanging_data_;
329};
330
331TEST_F(QuicNetworkTransactionTest, ForceQuic) {
332  params_.origin_to_force_quic_on =
333      HostPortPair::FromString("www.google.com:80");
334
335  QuicStreamId stream_id = 3;
336  scoped_ptr<QuicEncryptedPacket> req(
337      ConstructDataPacket(1, stream_id, true, true, 0,
338                          GetRequestString("GET", "http", "/")));
339  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
340
341  MockWrite quic_writes[] = {
342    MockWrite(SYNCHRONOUS, req->data(), req->length()),
343    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
344  };
345
346  scoped_ptr<QuicEncryptedPacket> resp(
347      ConstructDataPacket(
348          1, stream_id, false, true, 0, GetResponseString("200 OK", "hello!")));
349  MockRead quic_reads[] = {
350    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
351    MockRead(ASYNC, OK),  // EOF
352  };
353
354  DelayedSocketData quic_data(
355      1,  // wait for one write to finish before reading.
356      quic_reads, arraysize(quic_reads),
357      quic_writes, arraysize(quic_writes));
358
359  socket_factory_.AddSocketDataProvider(&quic_data);
360
361  // The non-alternate protocol job needs to hang in order to guarantee that
362  // the alternate-protocol job will "win".
363  AddHangingNonAlternateProtocolSocketData();
364
365  CreateSession();
366
367  SendRequestAndExpectQuicResponse("hello!");
368
369  // Check that the NetLog was filled reasonably.
370  net::CapturingNetLog::CapturedEntryList entries;
371  net_log_.GetEntries(&entries);
372  EXPECT_LT(0u, entries.size());
373
374  // Check that we logged a QUIC_SESSION_PACKET_RECEIVED.
375  int pos = net::ExpectLogContainsSomewhere(
376      entries, 0,
377      net::NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED,
378      net::NetLog::PHASE_NONE);
379  EXPECT_LT(0, pos);
380
381  // ... and also a TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED.
382  pos = net::ExpectLogContainsSomewhere(
383      entries, 0,
384      net::NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED,
385      net::NetLog::PHASE_NONE);
386  EXPECT_LT(0, pos);
387
388  std::string packet_sequence_number;
389  ASSERT_TRUE(entries[pos].GetStringValue(
390      "packet_sequence_number", &packet_sequence_number));
391  EXPECT_EQ("1", packet_sequence_number);
392
393  // ... and also a QUIC_SESSION_STREAM_FRAME_RECEIVED.
394  pos = net::ExpectLogContainsSomewhere(
395      entries, 0,
396      net::NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED,
397      net::NetLog::PHASE_NONE);
398  EXPECT_LT(0, pos);
399
400  int log_stream_id;
401  ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &log_stream_id));
402  EXPECT_EQ(stream_id, static_cast<QuicStreamId>(log_stream_id));
403}
404
405TEST_F(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
406  params_.origin_to_force_quic_on =
407      HostPortPair::FromString("www.google.com:80");
408
409  MockRead quic_reads[] = {
410    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
411  };
412  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
413                                     NULL, 0);
414  socket_factory_.AddSocketDataProvider(&quic_data);
415
416  CreateSession();
417
418  scoped_ptr<HttpNetworkTransaction> trans(
419      new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
420  TestCompletionCallback callback;
421  int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
422  EXPECT_EQ(ERR_IO_PENDING, rv);
423  EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
424}
425
426TEST_F(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
427  // Attempt to "force" quic on 443, which will not be honored.
428  params_.origin_to_force_quic_on =
429      HostPortPair::FromString("www.google.com:443");
430
431  MockRead http_reads[] = {
432    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
433    MockRead("hello world"),
434    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
435    MockRead(ASYNC, OK)
436  };
437
438  StaticSocketDataProvider data(http_reads, arraysize(http_reads), NULL, 0);
439  socket_factory_.AddSocketDataProvider(&data);
440  SSLSocketDataProvider ssl(ASYNC, OK);
441  socket_factory_.AddSSLSocketDataProvider(&ssl);
442
443  CreateSession();
444
445  SendRequestAndExpectHttpResponse("hello world");
446}
447
448TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
449  HttpStreamFactory::EnableNpnSpdy();  // Enables QUIC too.
450
451  MockRead http_reads[] = {
452    MockRead("HTTP/1.1 200 OK\r\n"),
453    MockRead(kQuicAlternateProtocolHttpHeader),
454    MockRead("hello world"),
455    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
456    MockRead(ASYNC, OK)
457  };
458
459  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
460                                     NULL, 0);
461  socket_factory_.AddSocketDataProvider(&http_data);
462
463  scoped_ptr<QuicEncryptedPacket> req(
464      ConstructDataPacket(1, 3, true, true, 0,
465                          GetRequestString("GET", "http", "/")));
466  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
467
468  MockWrite quic_writes[] = {
469    MockWrite(SYNCHRONOUS, req->data(), req->length()),
470    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
471  };
472
473  scoped_ptr<QuicEncryptedPacket> resp(
474      ConstructDataPacket(
475          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
476  MockRead quic_reads[] = {
477    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
478    MockRead(ASYNC, OK),  // EOF
479  };
480
481  DelayedSocketData quic_data(
482      1,  // wait for one write to finish before reading.
483      quic_reads, arraysize(quic_reads),
484      quic_writes, arraysize(quic_writes));
485
486  socket_factory_.AddSocketDataProvider(&quic_data);
487
488  // The non-alternate protocol job needs to hang in order to guarantee that
489  // the alternate-protocol job will "win".
490  AddHangingNonAlternateProtocolSocketData();
491
492  CreateSession();
493
494  SendRequestAndExpectHttpResponse("hello world");
495  SendRequestAndExpectQuicResponse("hello!");
496}
497
498TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
499  params_.origin_to_force_quic_on =
500      HostPortPair::FromString("www.google.com:443");
501  params_.enable_quic_https = true;
502  HttpStreamFactory::EnableNpnSpdy();  // Enables QUIC too.
503
504  MockRead http_reads[] = {
505    MockRead("HTTP/1.1 200 OK\r\n"),
506    MockRead(kQuicAlternateProtocolHttpsHeader),
507    MockRead("hello world"),
508    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
509    MockRead(ASYNC, OK)
510  };
511
512  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
513                                     NULL, 0);
514  socket_factory_.AddSocketDataProvider(&http_data);
515
516  scoped_ptr<QuicEncryptedPacket> req(
517      ConstructDataPacket(1, 3, true, true, 0,
518                          GetRequestString("GET", "https", "/")));
519  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
520
521  MockWrite quic_writes[] = {
522    MockWrite(SYNCHRONOUS, req->data(), req->length()),
523    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
524  };
525
526  scoped_ptr<QuicEncryptedPacket> resp(
527      ConstructDataPacket(
528          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
529  MockRead quic_reads[] = {
530    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
531    MockRead(ASYNC, OK),  // EOF
532  };
533
534  DelayedSocketData quic_data(
535      1,  // wait for one write to finish before reading.
536      quic_reads, arraysize(quic_reads),
537      quic_writes, arraysize(quic_writes));
538
539  socket_factory_.AddSocketDataProvider(&quic_data);
540
541  // The non-alternate protocol job needs to hang in order to guarantee that
542  // the alternate-protocol job will "win".
543  AddHangingNonAlternateProtocolSocketData();
544
545  CreateSession();
546
547  // TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo().
548  SendRequestAndExpectHttpResponse("hello world");
549}
550
551TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
552  HttpStreamFactory::EnableNpnSpdy();  // Enables QUIC too.
553  crypto_client_stream_factory_.set_handshake_mode(
554      MockCryptoClientStream::COLD_START);
555
556  MockWrite http_writes[] = {
557    MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"),
558    MockWrite(SYNCHRONOUS, 1, "Host: www.google.com\r\n"),
559    MockWrite(SYNCHRONOUS, 2, "Connection: keep-alive\r\n\r\n")
560  };
561
562  MockRead http_reads[] = {
563    MockRead(SYNCHRONOUS, 3, "HTTP/1.1 200 OK\r\n"),
564    MockRead(SYNCHRONOUS, 4, kQuicAlternateProtocolHttpHeader),
565    MockRead(SYNCHRONOUS, 5, "hello world"),
566    MockRead(SYNCHRONOUS, OK, 6)
567  };
568
569  DeterministicMockClientSocketFactory socket_factory;
570
571  DeterministicSocketData http_data(http_reads, arraysize(http_reads),
572                                    http_writes, arraysize(http_writes));
573  socket_factory.AddSocketDataProvider(&http_data);
574
575  // The QUIC transaction will not be allowed to complete.
576  MockWrite quic_writes[] = {
577    MockWrite(ASYNC, ERR_IO_PENDING, 0)
578  };
579  MockRead quic_reads[] = {
580    MockRead(ASYNC, ERR_IO_PENDING, 1),
581  };
582  DeterministicSocketData quic_data(quic_reads, arraysize(quic_reads),
583                                    quic_writes, arraysize(quic_writes));
584  socket_factory.AddSocketDataProvider(&quic_data);
585
586  // The HTTP transaction will complete.
587  DeterministicSocketData http_data2(http_reads, arraysize(http_reads),
588                                     http_writes, arraysize(http_writes));
589  socket_factory.AddSocketDataProvider(&http_data2);
590
591  CreateSessionWithFactory(&socket_factory);
592
593  // Run the first request.
594  http_data.StopAfter(arraysize(http_reads) + arraysize(http_writes));
595  SendRequestAndExpectHttpResponse("hello world");
596  ASSERT_TRUE(http_data.at_read_eof());
597  ASSERT_TRUE(http_data.at_write_eof());
598
599  // Now run the second request in which the QUIC socket hangs,
600  // and verify the the transaction continues over HTTP.
601  http_data2.StopAfter(arraysize(http_reads) + arraysize(http_writes));
602  SendRequestAndExpectHttpResponse("hello world");
603
604  ASSERT_TRUE(http_data2.at_read_eof());
605  ASSERT_TRUE(http_data2.at_write_eof());
606  ASSERT_TRUE(!quic_data.at_read_eof());
607  ASSERT_TRUE(!quic_data.at_write_eof());
608}
609
610TEST_F(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
611  HttpStreamFactory::EnableNpnSpdy();  // Enables QUIC too.
612
613  scoped_ptr<QuicEncryptedPacket> req(
614      ConstructDataPacket(1, 3, true, true, 0,
615                          GetRequestString("GET", "http", "/")));
616  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
617
618  MockWrite quic_writes[] = {
619    MockWrite(SYNCHRONOUS, req->data(), req->length()),
620    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
621  };
622
623  scoped_ptr<QuicEncryptedPacket> resp(
624      ConstructDataPacket(
625          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
626  MockRead quic_reads[] = {
627    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
628    MockRead(ASYNC, OK),  // EOF
629  };
630
631  DelayedSocketData quic_data(
632      1,  // wait for one write to finish before reading.
633      quic_reads, arraysize(quic_reads),
634      quic_writes, arraysize(quic_writes));
635
636  socket_factory_.AddSocketDataProvider(&quic_data);
637
638  // The non-alternate protocol job needs to hang in order to guarantee that
639  // the alternate-protocol job will "win".
640  AddHangingNonAlternateProtocolSocketData();
641
642  CreateSession();
643  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
644  SendRequestAndExpectQuicResponse("hello!");
645}
646
647TEST_F(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
648  HttpStreamFactory::EnableNpnSpdy();  // Enables QUIC too.
649
650  scoped_ptr<QuicEncryptedPacket> req(
651      ConstructDataPacket(1, 3, true, true, 0,
652                          GetRequestString("GET", "http", "/")));
653  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
654
655  MockWrite quic_writes[] = {
656    MockWrite(SYNCHRONOUS, req->data(), req->length()),
657    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
658  };
659
660  scoped_ptr<QuicEncryptedPacket> resp(
661      ConstructDataPacket(
662          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
663  MockRead quic_reads[] = {
664    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
665    MockRead(ASYNC, OK),  // EOF
666  };
667
668  DelayedSocketData quic_data(
669      1,  // wait for one write to finish before reading.
670      quic_reads, arraysize(quic_reads),
671      quic_writes, arraysize(quic_writes));
672
673  socket_factory_.AddSocketDataProvider(&quic_data);
674
675  // In order for a new QUIC session to be established via alternate-protocol
676  // without racing an HTTP connection, we need the host resolution to happen
677  // synchronously.
678  host_resolver_.set_synchronous_mode(true);
679  host_resolver_.rules()->AddIPLiteralRule("www.google.com", "192.168.0.1", "");
680  HostResolver::RequestInfo info(HostPortPair("www.google.com", 80));
681  AddressList address;
682  host_resolver_.Resolve(info, &address, CompletionCallback(), NULL,
683                         net_log_.bound());
684
685  CreateSession();
686  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
687  SendRequestAndExpectQuicResponse("hello!");
688}
689
690TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
691  HttpStreamFactory::EnableNpnSpdy();  // Enables QUIC too.
692
693  // Alternate-protocol job
694  scoped_ptr<QuicEncryptedPacket> close(ConstructConnectionClosePacket(1));
695  MockRead quic_reads[] = {
696    MockRead(ASYNC, close->data(), close->length()),
697    MockRead(ASYNC, OK),  // EOF
698  };
699  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
700                                     NULL, 0);
701  socket_factory_.AddSocketDataProvider(&quic_data);
702
703  // Main job which will succeed even though the alternate job fails.
704  MockRead http_reads[] = {
705    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
706    MockRead("hello from http"),
707    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
708    MockRead(ASYNC, OK)
709  };
710
711  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
712                                     NULL, 0);
713  socket_factory_.AddSocketDataProvider(&http_data);
714
715  CreateSession();
716  AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
717  SendRequestAndExpectHttpResponse("hello from http");
718  ExpectBrokenAlternateProtocolMapping();
719}
720
721TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
722  HttpStreamFactory::EnableNpnSpdy();  // Enables QUIC too.
723
724  // Alternate-protocol job
725  MockRead quic_reads[] = {
726    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
727  };
728  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
729                                     NULL, 0);
730  socket_factory_.AddSocketDataProvider(&quic_data);
731
732  // Main job which will succeed even though the alternate job fails.
733  MockRead http_reads[] = {
734    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
735    MockRead("hello from http"),
736    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
737    MockRead(ASYNC, OK)
738  };
739
740  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
741                                     NULL, 0);
742  socket_factory_.AddSocketDataProvider(&http_data);
743
744  CreateSession();
745
746  AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
747  SendRequestAndExpectHttpResponse("hello from http");
748  ExpectBrokenAlternateProtocolMapping();
749}
750
751}  // namespace test
752}  // namespace net
753