quic_network_transaction_unittest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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: 443:quic\r\n\r\n";
50
51// Returns a vector of NPN protocol strings for negotiating QUIC.
52std::vector<std::string> QuicNextProtos() {
53  std::vector<std::string> protos;
54  protos.push_back("http/1.1");
55  protos.push_back("quic");
56  return protos;
57}
58
59}  // namespace
60
61namespace net {
62namespace test {
63
64class QuicNetworkTransactionTest : public PlatformTest {
65 protected:
66  QuicNetworkTransactionTest()
67      : clock_(new MockClock),
68        ssl_config_service_(new SSLConfigServiceDefaults),
69        proxy_service_(ProxyService::CreateDirect()),
70        compressor_(new QuicSpdyCompressor()),
71        auth_handler_factory_(
72            HttpAuthHandlerFactory::CreateDefault(&host_resolver_)) {
73    request_.method = "GET";
74    request_.url = GURL("http://www.google.com/");
75    request_.load_flags = 0;
76  }
77
78  virtual void SetUp() {
79    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
80    base::MessageLoop::current()->RunUntilIdle();
81  }
82
83  virtual void TearDown() {
84    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
85    // Empty the current queue.
86    base::MessageLoop::current()->RunUntilIdle();
87    PlatformTest::TearDown();
88    NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
89    base::MessageLoop::current()->RunUntilIdle();
90    HttpStreamFactory::set_use_alternate_protocols(false);
91    HttpStreamFactory::SetNextProtos(std::vector<std::string>());
92  }
93
94  scoped_ptr<QuicEncryptedPacket> ConstructRstPacket(
95      QuicPacketSequenceNumber num,
96      QuicStreamId stream_id) {
97    QuicPacketHeader header;
98    header.public_header.guid = 0xDEADBEEF;
99    header.public_header.reset_flag = false;
100    header.public_header.version_flag = false;
101    header.packet_sequence_number = num;
102    header.entropy_flag = false;
103    header.fec_flag = false;
104    header.fec_group = 0;
105
106    QuicRstStreamFrame rst(stream_id, QUIC_STREAM_NO_ERROR);
107    return scoped_ptr<QuicEncryptedPacket>(
108        ConstructPacket(header, QuicFrame(&rst)));
109  }
110
111  scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket(
112      QuicPacketSequenceNumber num) {
113    QuicPacketHeader header;
114    header.public_header.guid = 0xDEADBEEF;
115    header.public_header.reset_flag = false;
116    header.public_header.version_flag = false;
117    header.packet_sequence_number = num;
118    header.entropy_flag = false;
119    header.fec_flag = false;
120    header.fec_group = 0;
121
122    QuicAckFrame ack_frame(0, QuicTime::Zero(), 0);
123    QuicConnectionCloseFrame close;
124    close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
125    close.error_details = "Time to panic!";
126    close.ack_frame = ack_frame;
127    return scoped_ptr<QuicEncryptedPacket>(
128        ConstructPacket(header, QuicFrame(&close)));
129  }
130
131  scoped_ptr<QuicEncryptedPacket> ConstructAckPacket(
132      QuicPacketSequenceNumber largest_received,
133      QuicPacketSequenceNumber least_unacked) {
134    QuicPacketHeader header;
135    header.public_header.guid = 0xDEADBEEF;
136    header.public_header.reset_flag = false;
137    header.public_header.version_flag = false;
138    header.packet_sequence_number = 2;
139    header.entropy_flag = false;
140    header.fec_flag = false;
141    header.fec_group = 0;
142
143    QuicAckFrame ack(largest_received, QuicTime::Zero(), least_unacked);
144
145    QuicCongestionFeedbackFrame feedback;
146    feedback.type = kTCP;
147    feedback.tcp.accumulated_number_of_lost_packets = 0;
148    feedback.tcp.receive_window = 256000;
149
150    QuicFramer framer(kQuicVersion1, QuicTime::Zero(), false);
151    QuicFrames frames;
152    frames.push_back(QuicFrame(&ack));
153    frames.push_back(QuicFrame(&feedback));
154    scoped_ptr<QuicPacket> packet(
155        framer.ConstructFrameDataPacket(header, frames).packet);
156    return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
157        ENCRYPTION_NONE, header.packet_sequence_number, *packet));
158  }
159
160  std::string GetRequestString(const std::string& method,
161                               const std::string& path) {
162    SpdyHeaderBlock headers;
163    headers[":method"] = method;
164    headers[":host"] = "www.google.com";
165    headers[":path"] = path;
166    headers[":scheme"] = "http";
167    headers[":version"] = "HTTP/1.1";
168    return SerializeHeaderBlock(headers);
169  }
170
171  std::string GetResponseString(const std::string& status,
172                                const std::string& body) {
173    SpdyHeaderBlock headers;
174    headers[":status"] = status;
175    headers[":version"] = "HTTP/1.1";
176    headers["content-type"] = "text/plain";
177    return compressor_->CompressHeaders(headers) + body;
178  }
179
180  std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
181    QuicSpdyCompressor compressor;
182    return compressor.CompressHeaders(headers);
183  }
184
185  // Returns a newly created packet to send kData on stream 1.
186  QuicEncryptedPacket* ConstructDataPacket(
187      QuicPacketSequenceNumber sequence_number,
188      QuicStreamId stream_id,
189      bool should_include_version,
190      bool fin,
191      QuicStreamOffset offset,
192      base::StringPiece data) {
193    InitializeHeader(sequence_number, should_include_version);
194    QuicStreamFrame frame(stream_id, fin, offset, data);
195    return ConstructPacket(header_, QuicFrame(&frame)).release();
196  }
197
198  scoped_ptr<QuicEncryptedPacket> ConstructPacket(
199      const QuicPacketHeader& header,
200      const QuicFrame& frame) {
201    QuicFramer framer(kQuicVersion1, QuicTime::Zero(), false);
202    QuicFrames frames;
203    frames.push_back(frame);
204    scoped_ptr<QuicPacket> packet(
205        framer.ConstructFrameDataPacket(header, frames).packet);
206    return scoped_ptr<QuicEncryptedPacket>(framer.EncryptPacket(
207        ENCRYPTION_NONE, header.packet_sequence_number, *packet));
208  }
209
210  void InitializeHeader(QuicPacketSequenceNumber sequence_number,
211                        bool should_include_version) {
212    header_.public_header.guid = random_generator_.RandUint64();
213    header_.public_header.reset_flag = false;
214    header_.public_header.version_flag = should_include_version;
215    header_.packet_sequence_number = sequence_number;
216    header_.fec_group = 0;
217    header_.entropy_flag = false;
218    header_.fec_flag = false;
219  }
220
221  void CreateSession() {
222    params_.enable_quic = true;
223    params_.quic_clock = clock_;
224    params_.quic_random = &random_generator_;
225    params_.client_socket_factory = &socket_factory_;
226    params_.quic_crypto_client_stream_factory = &crypto_client_stream_factory_;
227    params_.host_resolver = &host_resolver_;
228    params_.cert_verifier = &cert_verifier_;
229    params_.transport_security_state = &transport_security_state_;
230    params_.proxy_service = proxy_service_.get();
231    params_.ssl_config_service = ssl_config_service_.get();
232    params_.http_auth_handler_factory = auth_handler_factory_.get();
233    params_.http_server_properties = &http_server_properties;
234
235    session_ = new HttpNetworkSession(params_);
236  }
237
238  void CheckWasQuicResponse(const scoped_ptr<HttpNetworkTransaction>& trans) {
239    const HttpResponseInfo* response = trans->GetResponseInfo();
240    ASSERT_TRUE(response != NULL);
241    ASSERT_TRUE(response->headers.get() != NULL);
242    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
243    EXPECT_TRUE(response->was_fetched_via_spdy);
244    EXPECT_TRUE(response->was_npn_negotiated);
245    EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3,
246              response->connection_info);
247  }
248
249  void CheckWasHttpResponse(const scoped_ptr<HttpNetworkTransaction>& trans) {
250    const HttpResponseInfo* response = trans->GetResponseInfo();
251    ASSERT_TRUE(response != NULL);
252    ASSERT_TRUE(response->headers.get() != NULL);
253    EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
254    EXPECT_FALSE(response->was_fetched_via_spdy);
255    EXPECT_FALSE(response->was_npn_negotiated);
256    EXPECT_EQ(HttpResponseInfo::CONNECTION_INFO_HTTP1,
257              response->connection_info);
258  }
259
260  void CheckResponseData(HttpNetworkTransaction* trans,
261                         const std::string& expected) {
262    std::string response_data;
263    ASSERT_EQ(OK, ReadTransaction(trans, &response_data));
264    EXPECT_EQ(expected, response_data);
265  }
266
267  void RunTransaction(HttpNetworkTransaction* trans) {
268    TestCompletionCallback callback;
269    int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
270    EXPECT_EQ(ERR_IO_PENDING, rv);
271    EXPECT_EQ(OK, callback.WaitForResult());
272  }
273
274  void SendRequestAndExpectHttpResponse(const std::string& expected) {
275    scoped_ptr<HttpNetworkTransaction> trans(
276        new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
277    RunTransaction(trans.get());
278    CheckWasHttpResponse(trans);
279    CheckResponseData(trans.get(), expected);
280  }
281
282  void SendRequestAndExpectQuicResponse(const std::string& expected) {
283    scoped_ptr<HttpNetworkTransaction> trans(
284        new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
285    RunTransaction(trans.get());
286    CheckWasQuicResponse(trans);
287    CheckResponseData(trans.get(), expected);
288  }
289
290  void AddQuicAlternateProtocolMapping(
291      MockCryptoClientStream::HandshakeMode handshake_mode) {
292    crypto_client_stream_factory_.set_handshake_mode(handshake_mode);
293    session_->http_server_properties()->SetAlternateProtocol(
294        HostPortPair::FromURL(request_.url), 80, QUIC);
295  }
296
297  void ExpectBrokenAlternateProtocolMapping() {
298    ASSERT_TRUE(session_->http_server_properties()->HasAlternateProtocol(
299        HostPortPair::FromURL(request_.url)));
300    const PortAlternateProtocolPair alternate =
301        session_->http_server_properties()->GetAlternateProtocol(
302            HostPortPair::FromURL(request_.url));
303    EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
304  }
305
306  void AddHangingNonAlternateProtocolSocketData() {
307    MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
308    StaticSocketDataProvider data(NULL, 0, NULL, 0);
309    data.set_connect_data(never_finishing_connect);
310    socket_factory_.AddSocketDataProvider(&data);
311  }
312
313  QuicPacketHeader header_;
314  scoped_refptr<HttpNetworkSession> session_;
315  MockClientSocketFactory socket_factory_;
316  MockCryptoClientStreamFactory crypto_client_stream_factory_;
317  MockClock* clock_;  // Owned by QuicStreamFactory after CreateSession.
318  MockHostResolver host_resolver_;
319  MockCertVerifier cert_verifier_;
320  TransportSecurityState transport_security_state_;
321  scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
322  scoped_ptr<ProxyService> proxy_service_;
323  scoped_ptr<QuicSpdyCompressor> compressor_;
324  scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
325  MockRandom random_generator_;
326  HttpServerPropertiesImpl http_server_properties;
327  HttpNetworkSession::Params params_;
328  HttpRequestInfo request_;
329  CapturingBoundNetLog net_log_;
330};
331
332TEST_F(QuicNetworkTransactionTest, ForceQuic) {
333  params_.origin_to_force_quic_on =
334      HostPortPair::FromString("www.google.com:80");
335
336  QuicStreamId stream_id = 3;
337  scoped_ptr<QuicEncryptedPacket> req(
338      ConstructDataPacket(1, stream_id, true, true, 0,
339                          GetRequestString("GET", "/")));
340  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
341
342  MockWrite quic_writes[] = {
343    MockWrite(SYNCHRONOUS, req->data(), req->length()),
344    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
345  };
346
347  scoped_ptr<QuicEncryptedPacket> resp(
348      ConstructDataPacket(
349          1, stream_id, false, true, 0, GetResponseString("200 OK", "hello!")));
350  MockRead quic_reads[] = {
351    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
352    MockRead(ASYNC, OK),  // EOF
353  };
354
355  DelayedSocketData quic_data(
356      1,  // wait for one write to finish before reading.
357      quic_reads, arraysize(quic_reads),
358      quic_writes, arraysize(quic_writes));
359
360  socket_factory_.AddSocketDataProvider(&quic_data);
361
362  // The non-alternate protocol job needs to hang in order to guarantee that
363  // the alternate-protocol job will "win".
364  AddHangingNonAlternateProtocolSocketData();
365
366  CreateSession();
367
368  SendRequestAndExpectQuicResponse("hello!");
369
370  // Check that the NetLog was filled reasonably.
371  net::CapturingNetLog::CapturedEntryList entries;
372  net_log_.GetEntries(&entries);
373  EXPECT_LT(0u, entries.size());
374
375  // Check that we logged a QUIC_SESSION_PACKET_RECEIVED.
376  int pos = net::ExpectLogContainsSomewhere(
377      entries, 0,
378      net::NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED,
379      net::NetLog::PHASE_NONE);
380  EXPECT_LT(0, pos);
381
382  // ... and also a TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED.
383  pos = net::ExpectLogContainsSomewhere(
384      entries, 0,
385      net::NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED,
386      net::NetLog::PHASE_NONE);
387  EXPECT_LT(0, pos);
388
389  std::string packet_sequence_number;
390  ASSERT_TRUE(entries[pos].GetStringValue(
391      "packet_sequence_number", &packet_sequence_number));
392  EXPECT_EQ("1", packet_sequence_number);
393
394  // ... and also a QUIC_SESSION_STREAM_FRAME_RECEIVED.
395  pos = net::ExpectLogContainsSomewhere(
396      entries, 0,
397      net::NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED,
398      net::NetLog::PHASE_NONE);
399  EXPECT_LT(0, pos);
400
401  int log_stream_id;
402  ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &log_stream_id));
403  EXPECT_EQ(stream_id, static_cast<QuicStreamId>(log_stream_id));
404}
405
406TEST_F(QuicNetworkTransactionTest, ForceQuicWithErrorConnecting) {
407  params_.origin_to_force_quic_on =
408      HostPortPair::FromString("www.google.com:80");
409
410  MockRead quic_reads[] = {
411    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
412  };
413  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
414                                     NULL, 0);
415  socket_factory_.AddSocketDataProvider(&quic_data);
416
417  CreateSession();
418
419  scoped_ptr<HttpNetworkTransaction> trans(
420      new HttpNetworkTransaction(DEFAULT_PRIORITY, session_.get()));
421  TestCompletionCallback callback;
422  int rv = trans->Start(&request_, callback.callback(), net_log_.bound());
423  EXPECT_EQ(ERR_IO_PENDING, rv);
424  EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, callback.WaitForResult());
425}
426
427TEST_F(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
428  // Attempt to "force" quic on 443, which will not be honored.
429  params_.origin_to_force_quic_on =
430      HostPortPair::FromString("www.google.com:443");
431
432  MockRead http_reads[] = {
433    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
434    MockRead("hello world"),
435    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
436    MockRead(ASYNC, OK)
437  };
438
439  StaticSocketDataProvider data(http_reads, arraysize(http_reads), NULL, 0);
440  socket_factory_.AddSocketDataProvider(&data);
441  SSLSocketDataProvider ssl(ASYNC, OK);
442  socket_factory_.AddSSLSocketDataProvider(&ssl);
443
444  CreateSession();
445
446  SendRequestAndExpectHttpResponse("hello world");
447}
448
449TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
450  HttpStreamFactory::set_use_alternate_protocols(true);
451  HttpStreamFactory::SetNextProtos(QuicNextProtos());
452
453  MockRead http_reads[] = {
454    MockRead("HTTP/1.1 200 OK\r\n"),
455    MockRead(kQuicAlternateProtocolHttpHeader),
456    MockRead("hello world"),
457    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
458    MockRead(ASYNC, OK)
459  };
460
461  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
462                                     NULL, 0);
463  socket_factory_.AddSocketDataProvider(&http_data);
464
465  scoped_ptr<QuicEncryptedPacket> req(
466      ConstructDataPacket(1, 3, true, true, 0, GetRequestString("GET", "/")));
467  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
468
469  MockWrite quic_writes[] = {
470    MockWrite(SYNCHRONOUS, req->data(), req->length()),
471    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
472  };
473
474  scoped_ptr<QuicEncryptedPacket> resp(
475      ConstructDataPacket(
476          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
477  MockRead quic_reads[] = {
478    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
479    MockRead(ASYNC, OK),  // EOF
480  };
481
482  DelayedSocketData quic_data(
483      1,  // wait for one write to finish before reading.
484      quic_reads, arraysize(quic_reads),
485      quic_writes, arraysize(quic_writes));
486
487  socket_factory_.AddSocketDataProvider(&quic_data);
488
489  // The non-alternate protocol job needs to hang in order to guarantee that
490  // the alternate-protocol job will "win".
491  AddHangingNonAlternateProtocolSocketData();
492
493  CreateSession();
494
495  SendRequestAndExpectHttpResponse("hello world");
496  SendRequestAndExpectQuicResponse("hello!");
497}
498
499TEST_F(QuicNetworkTransactionTest, DontUseAlternateProtocolForQuicHttps) {
500  HttpStreamFactory::set_use_alternate_protocols(true);
501  HttpStreamFactory::SetNextProtos(QuicNextProtos());
502
503  MockRead http_reads[] = {
504    MockRead("HTTP/1.1 200 OK\r\n"),
505    MockRead("Content-length: 11\r\n"),
506    MockRead(kQuicAlternateProtocolHttpHeader),
507    MockRead("hello world"),
508
509    MockRead("HTTP/1.1 200 OK\r\n"),
510    MockRead("Content-length: 6\r\n"),
511    MockRead(kQuicAlternateProtocolHttpHeader),
512    MockRead("hello!"),
513  };
514
515  StaticSocketDataProvider data(http_reads, arraysize(http_reads), NULL, 0);
516  socket_factory_.AddSocketDataProvider(&data);
517  SSLSocketDataProvider ssl(ASYNC, OK);
518  socket_factory_.AddSSLSocketDataProvider(&ssl);
519
520  request_.url = GURL("https://www.google.com/");
521
522  CreateSession();
523
524  SendRequestAndExpectHttpResponse("hello world");
525  SendRequestAndExpectHttpResponse("hello!");
526}
527
528TEST_F(QuicNetworkTransactionTest, ZeroRTT) {
529  HttpStreamFactory::set_use_alternate_protocols(true);
530  HttpStreamFactory::SetNextProtos(QuicNextProtos());
531
532  scoped_ptr<QuicEncryptedPacket> req(
533      ConstructDataPacket(1, 3, true, true, 0, GetRequestString("GET", "/")));
534  scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
535
536  MockWrite quic_writes[] = {
537    MockWrite(SYNCHRONOUS, req->data(), req->length()),
538    MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
539  };
540
541  scoped_ptr<QuicEncryptedPacket> resp(
542      ConstructDataPacket(
543          1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
544  MockRead quic_reads[] = {
545    MockRead(SYNCHRONOUS, resp->data(), resp->length()),
546    MockRead(ASYNC, OK),  // EOF
547  };
548
549  DelayedSocketData quic_data(
550      1,  // wait for one write to finish before reading.
551      quic_reads, arraysize(quic_reads),
552      quic_writes, arraysize(quic_writes));
553
554  socket_factory_.AddSocketDataProvider(&quic_data);
555
556  CreateSession();
557  AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
558  SendRequestAndExpectQuicResponse("hello!");
559}
560
561TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
562  HttpStreamFactory::set_use_alternate_protocols(true);
563  HttpStreamFactory::SetNextProtos(QuicNextProtos());
564
565  // Alternate-protocol job
566  scoped_ptr<QuicEncryptedPacket> close(ConstructConnectionClosePacket(1));
567  MockRead quic_reads[] = {
568    MockRead(ASYNC, close->data(), close->length()),
569    MockRead(ASYNC, OK),  // EOF
570  };
571  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
572                                     NULL, 0);
573  socket_factory_.AddSocketDataProvider(&quic_data);
574
575  // Main job which will succeed even though the alternate job fails.
576  MockRead http_reads[] = {
577    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
578    MockRead("hello from http"),
579    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
580    MockRead(ASYNC, OK)
581  };
582
583  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
584                                     NULL, 0);
585  socket_factory_.AddSocketDataProvider(&http_data);
586
587  CreateSession();
588  AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
589  SendRequestAndExpectHttpResponse("hello from http");
590  ExpectBrokenAlternateProtocolMapping();
591}
592
593TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
594  HttpStreamFactory::set_use_alternate_protocols(true);
595  HttpStreamFactory::SetNextProtos(QuicNextProtos());
596
597  // Alternate-protocol job
598  MockRead quic_reads[] = {
599    MockRead(ASYNC, ERR_SOCKET_NOT_CONNECTED),
600  };
601  StaticSocketDataProvider quic_data(quic_reads, arraysize(quic_reads),
602                                     NULL, 0);
603  socket_factory_.AddSocketDataProvider(&quic_data);
604
605  // Main job which will succeed even though the alternate job fails.
606  MockRead http_reads[] = {
607    MockRead("HTTP/1.1 200 OK\r\n\r\n"),
608    MockRead("hello from http"),
609    MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
610    MockRead(ASYNC, OK)
611  };
612
613  StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
614                                     NULL, 0);
615  socket_factory_.AddSocketDataProvider(&http_data);
616
617  CreateSession();
618
619  AddQuicAlternateProtocolMapping(MockCryptoClientStream::COLD_START);
620  SendRequestAndExpectHttpResponse("hello from http");
621  ExpectBrokenAlternateProtocolMapping();
622}
623
624}  // namespace test
625}  // namespace net
626