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.
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/singleton.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "net/base/ip_endpoint.h"
13 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
14 #include "net/quic/crypto/null_encrypter.h"
15 #include "net/quic/quic_framer.h"
16 #include "net/quic/quic_packet_creator.h"
17 #include "net/quic/quic_protocol.h"
18 #include "net/quic/test_tools/quic_connection_peer.h"
19 #include "net/quic/test_tools/quic_session_peer.h"
20 #include "net/quic/test_tools/quic_test_writer.h"
21 #include "net/quic/test_tools/reliable_quic_stream_peer.h"
22 #include "net/tools/quic/quic_epoll_connection_helper.h"
23 #include "net/tools/quic/quic_in_memory_cache.h"
24 #include "net/tools/quic/quic_server.h"
25 #include "net/tools/quic/quic_socket_utils.h"
26 #include "net/tools/quic/test_tools/http_message_test_utils.h"
27 #include "net/tools/quic/test_tools/packet_dropping_test_writer.h"
28 #include "net/tools/quic/test_tools/quic_client_peer.h"
29 #include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
30 #include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
31 #include "net/tools/quic/test_tools/quic_server_peer.h"
32 #include "net/tools/quic/test_tools/quic_test_client.h"
33 #include "net/tools/quic/test_tools/server_thread.h"
34 #include "testing/gtest/include/gtest/gtest.h"
36 using base::StringPiece
;
37 using base::WaitableEvent
;
38 using net::test::QuicConnectionPeer
;
39 using net::test::QuicSessionPeer
;
40 using net::test::QuicTestWriter
;
41 using net::test::ReliableQuicStreamPeer
;
42 using net::tools::test::PacketDroppingTestWriter
;
43 using net::tools::test::QuicDispatcherPeer
;
44 using net::tools::test::QuicServerPeer
;
52 const char* kFooResponseBody
= "Artichoke hearts make me happy.";
53 const char* kBarResponseBody
= "Palm hearts are pretty delicious, also.";
54 const size_t kCongestionFeedbackFrameSize
= 25;
55 // If kCongestionFeedbackFrameSize increase we need to expand this string
57 const char* kLargeRequest
=
58 "https://www.google.com/foo/test/a/request/string/longer/than/25/bytes";
60 void GenerateBody(string
* body
, int length
) {
62 body
->reserve(length
);
63 for (int i
= 0; i
< length
; ++i
) {
64 body
->append(1, static_cast<char>(32 + i
% (126 - 32)));
68 class EndToEndTest
: public ::testing::TestWithParam
<QuicVersion
> {
71 : server_hostname_("example.com"),
72 server_started_(false),
73 strike_register_no_startup_period_(false) {
74 net::IPAddressNumber ip
;
75 CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip
));
76 server_address_
= IPEndPoint(ip
, 0);
77 QuicConnection::g_acks_do_not_instigate_acks
= true;
78 FLAGS_track_retransmission_history
= true;
79 client_config_
.SetDefaults();
80 server_config_
.SetDefaults();
82 QuicInMemoryCachePeer::ResetForTests();
83 AddToCache("GET", kLargeRequest
, "HTTP/1.1", "200", "OK", kFooResponseBody
);
84 AddToCache("GET", "https://www.google.com/foo",
85 "HTTP/1.1", "200", "OK", kFooResponseBody
);
86 AddToCache("GET", "https://www.google.com/bar",
87 "HTTP/1.1", "200", "OK", kBarResponseBody
);
88 version_
= GetParam();
91 virtual ~EndToEndTest() {
92 QuicInMemoryCachePeer::ResetForTests();
95 virtual QuicTestClient
* CreateQuicClient(QuicTestWriter
* writer
) {
96 QuicTestClient
* client
= new QuicTestClient(server_address_
,
101 client
->UseWriter(writer
);
106 virtual bool Initialize() {
107 // Start the server first, because CreateQuicClient() attempts
108 // to connect to the server.
110 client_
.reset(CreateQuicClient(client_writer_
));
111 QuicEpollConnectionHelper
* helper
=
112 reinterpret_cast<QuicEpollConnectionHelper
*>(
113 QuicConnectionPeer::GetHelper(
114 client_
->client()->session()->connection()));
115 client_writer_
->SetConnectionHelper(helper
);
116 return client_
->client()->connected();
119 virtual void SetUp() {
120 // The ownership of these gets transferred to the QuicTestWriter and
121 // QuicDispatcher when Initialize() is executed.
122 client_writer_
= new PacketDroppingTestWriter();
123 server_writer_
= new PacketDroppingTestWriter();
126 virtual void TearDown() {
131 server_thread_
.reset(new ServerThread(server_address_
, server_config_
,
132 strike_register_no_startup_period_
));
133 server_thread_
->Start();
134 server_thread_
->listening()->Wait();
135 server_address_
= IPEndPoint(server_address_
.address(),
136 server_thread_
->GetPort());
137 QuicDispatcher
* dispatcher
= QuicServerPeer::GetDispatcher(
138 server_thread_
->server());
139 QuicDispatcherPeer::UseWriter(dispatcher
, server_writer_
);
140 server_started_
= true;
144 if (!server_started_
)
146 if (server_thread_
.get()) {
147 server_thread_
->quit()->Signal();
148 server_thread_
->Join();
152 void AddToCache(StringPiece method
,
155 StringPiece response_code
,
156 StringPiece response_detail
,
158 QuicInMemoryCache::GetInstance()->AddSimpleResponse(
159 method
, path
, version
, response_code
, response_detail
, body
);
162 void SetPacketLossPercentage(int32 loss
) {
163 // TODO(rtenneti): enable when we can do random packet loss tests in
165 // client_writer_->set_fake_packet_loss_percentage(loss);
166 // server_writer_->set_fake_packet_loss_percentage(loss);
169 IPEndPoint server_address_
;
170 string server_hostname_
;
171 scoped_ptr
<ServerThread
> server_thread_
;
172 scoped_ptr
<QuicTestClient
> client_
;
173 PacketDroppingTestWriter
* client_writer_
;
174 PacketDroppingTestWriter
* server_writer_
;
175 bool server_started_
;
176 QuicConfig client_config_
;
177 QuicConfig server_config_
;
178 QuicVersion version_
;
179 bool strike_register_no_startup_period_
;
182 // Run all end to end tests with all supported versions.
183 INSTANTIATE_TEST_CASE_P(EndToEndTests
,
185 ::testing::ValuesIn(kSupportedQuicVersions
));
187 TEST_P(EndToEndTest
, SimpleRequestResponse
) {
188 ASSERT_TRUE(Initialize());
190 EXPECT_EQ(kFooResponseBody
, client_
->SendSynchronousRequest("/foo"));
191 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
194 // TODO(rch): figure out how to detect missing v6 supprt (like on the linux
195 // try bots) and selectively disable this test.
196 TEST_P(EndToEndTest
, DISABLED_SimpleRequestResponsev6
) {
198 CHECK(net::ParseIPLiteralToNumber("::1", &ip
));
199 server_address_
= IPEndPoint(ip
, server_address_
.port());
200 ASSERT_TRUE(Initialize());
202 EXPECT_EQ(kFooResponseBody
, client_
->SendSynchronousRequest("/foo"));
203 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
206 TEST_P(EndToEndTest
, SeparateFinPacket
) {
207 ASSERT_TRUE(Initialize());
209 HTTPMessage
request(HttpConstants::HTTP_1_1
,
210 HttpConstants::POST
, "/foo");
211 request
.set_has_complete_message(false);
213 client_
->SendMessage(request
);
215 client_
->SendData(string(), true);
217 client_
->WaitForResponse();
218 EXPECT_EQ(kFooResponseBody
, client_
->response_body());
219 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
221 request
.AddBody("foo", true);
223 client_
->SendMessage(request
);
224 client_
->SendData(string(), true);
225 client_
->WaitForResponse();
226 EXPECT_EQ(kFooResponseBody
, client_
->response_body());
227 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
230 TEST_P(EndToEndTest
, MultipleRequestResponse
) {
231 ASSERT_TRUE(Initialize());
233 EXPECT_EQ(kFooResponseBody
, client_
->SendSynchronousRequest("/foo"));
234 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
235 EXPECT_EQ(kBarResponseBody
, client_
->SendSynchronousRequest("/bar"));
236 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
239 TEST_P(EndToEndTest
, MultipleClients
) {
240 ASSERT_TRUE(Initialize());
241 scoped_ptr
<QuicTestClient
> client2(CreateQuicClient(NULL
));
243 HTTPMessage
request(HttpConstants::HTTP_1_1
,
244 HttpConstants::POST
, "/foo");
245 request
.AddHeader("content-length", "3");
246 request
.set_has_complete_message(false);
248 client_
->SendMessage(request
);
249 client2
->SendMessage(request
);
251 client_
->SendData("bar", true);
252 client_
->WaitForResponse();
253 EXPECT_EQ(kFooResponseBody
, client_
->response_body());
254 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
256 client2
->SendData("eep", true);
257 client2
->WaitForResponse();
258 EXPECT_EQ(kFooResponseBody
, client2
->response_body());
259 EXPECT_EQ(200u, client2
->response_headers()->parsed_response_code());
262 TEST_P(EndToEndTest
, RequestOverMultiplePackets
) {
263 ASSERT_TRUE(Initialize());
264 // Set things up so we have a small payload, to guarantee fragmentation.
265 // A congestion feedback frame can't be split into multiple packets, make sure
266 // that our packet have room for at least this amount after the normal headers
269 // TODO(rch) handle this better when we have different encryption options.
270 const size_t kStreamDataLength
= 3;
271 const QuicStreamId kStreamId
= 1u;
272 const QuicStreamOffset kStreamOffset
= 0u;
273 size_t stream_payload_size
=
274 QuicFramer::GetMinStreamFrameSize(
275 GetParam(), kStreamId
, kStreamOffset
, true) + kStreamDataLength
;
276 size_t min_payload_size
=
277 std::max(kCongestionFeedbackFrameSize
, stream_payload_size
);
278 size_t ciphertext_size
=
279 NullEncrypter(GetParam()).GetCiphertextSize(min_payload_size
);
280 // TODO(satyashekhar): Fix this when versioning is implemented.
281 client_
->options()->max_packet_length
=
282 GetPacketHeaderSize(PACKET_8BYTE_GUID
, !kIncludeVersion
,
283 PACKET_6BYTE_SEQUENCE_NUMBER
, NOT_IN_FEC_GROUP
) +
286 // Make sure our request is too large to fit in one packet.
287 EXPECT_GT(strlen(kLargeRequest
), min_payload_size
);
288 EXPECT_EQ(kFooResponseBody
, client_
->SendSynchronousRequest(kLargeRequest
));
289 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
292 TEST_P(EndToEndTest
, MultipleFramesRandomOrder
) {
293 ASSERT_TRUE(Initialize());
294 // Set things up so we have a small payload, to guarantee fragmentation.
295 // A congestion feedback frame can't be split into multiple packets, make sure
296 // that our packet have room for at least this amount after the normal headers
299 // TODO(rch) handle this better when we have different encryption options.
300 const size_t kStreamDataLength
= 3;
301 const QuicStreamId kStreamId
= 1u;
302 const QuicStreamOffset kStreamOffset
= 0u;
303 size_t stream_payload_size
=
304 QuicFramer::GetMinStreamFrameSize(
305 GetParam(), kStreamId
, kStreamOffset
, true) + kStreamDataLength
;
306 size_t min_payload_size
=
307 std::max(kCongestionFeedbackFrameSize
, stream_payload_size
);
308 size_t ciphertext_size
=
309 NullEncrypter(GetParam()).GetCiphertextSize(min_payload_size
);
310 // TODO(satyashekhar): Fix this when versioning is implemented.
311 client_
->options()->max_packet_length
=
312 GetPacketHeaderSize(PACKET_8BYTE_GUID
, !kIncludeVersion
,
313 PACKET_6BYTE_SEQUENCE_NUMBER
, NOT_IN_FEC_GROUP
) +
315 client_
->options()->random_reorder
= true;
317 // Make sure our request is too large to fit in one packet.
318 EXPECT_GT(strlen(kLargeRequest
), min_payload_size
);
319 EXPECT_EQ(kFooResponseBody
, client_
->SendSynchronousRequest(kLargeRequest
));
320 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
323 TEST_P(EndToEndTest
, PostMissingBytes
) {
324 ASSERT_TRUE(Initialize());
326 // Add a content length header with no body.
327 HTTPMessage
request(HttpConstants::HTTP_1_1
,
328 HttpConstants::POST
, "/foo");
329 request
.AddHeader("content-length", "3");
330 request
.set_skip_message_validation(true);
332 // This should be detected as stream fin without complete request,
333 // triggering an error response.
334 client_
->SendCustomSynchronousRequest(request
);
335 EXPECT_EQ("bad", client_
->response_body());
336 EXPECT_EQ(500u, client_
->response_headers()->parsed_response_code());
339 TEST_P(EndToEndTest
, LargePostNoPacketLoss
) {
340 ASSERT_TRUE(Initialize());
342 client_
->client()->WaitForCryptoHandshakeConfirmed();
346 GenerateBody(&body
, 1024 * 1024);
348 HTTPMessage
request(HttpConstants::HTTP_1_1
,
349 HttpConstants::POST
, "/foo");
350 request
.AddBody(body
, true);
352 EXPECT_EQ(kFooResponseBody
, client_
->SendCustomSynchronousRequest(request
));
355 TEST_P(EndToEndTest
, LargePostWithPacketLoss
) {
356 // Connect with lower fake packet loss than we'd like to test. Until
357 // b/10126687 is fixed, losing handshake packets is pretty brutal.
358 SetPacketLossPercentage(5);
359 ASSERT_TRUE(Initialize());
361 // Wait for the server SHLO before upping the packet loss.
362 client_
->client()->WaitForCryptoHandshakeConfirmed();
363 SetPacketLossPercentage(30);
367 GenerateBody(&body
, 1024 * 10);
369 HTTPMessage
request(HttpConstants::HTTP_1_1
,
370 HttpConstants::POST
, "/foo");
371 request
.AddBody(body
, true);
373 EXPECT_EQ(kFooResponseBody
, client_
->SendCustomSynchronousRequest(request
));
376 TEST_P(EndToEndTest
, LargePostWithPacketLossAndBlocketSocket
) {
377 // Connect with lower fake packet loss than we'd like to test. Until
378 // b/10126687 is fixed, losing handshake packets is pretty brutal.
379 SetPacketLossPercentage(5);
380 ASSERT_TRUE(Initialize());
382 // Wait for the server SHLO before upping the packet loss.
383 client_
->client()->WaitForCryptoHandshakeConfirmed();
384 SetPacketLossPercentage(30);
385 client_writer_
->set_fake_blocked_socket_percentage(10);
389 GenerateBody(&body
, 1024 * 10);
391 HTTPMessage
request(HttpConstants::HTTP_1_1
,
392 HttpConstants::POST
, "/foo");
393 request
.AddBody(body
, true);
395 EXPECT_EQ(kFooResponseBody
, client_
->SendCustomSynchronousRequest(request
));
398 // TODO(rtenneti): rch is investigating the root cause. Will enable after we
400 TEST_P(EndToEndTest
, DISABLED_LargePostZeroRTTFailure
) {
401 // Have the server accept 0-RTT without waiting a startup period.
402 strike_register_no_startup_period_
= true;
404 // Send a request and then disconnect. This prepares the client to attempt
405 // a 0-RTT handshake for the next request.
406 ASSERT_TRUE(Initialize());
409 GenerateBody(&body
, 20480);
411 HTTPMessage
request(HttpConstants::HTTP_1_1
,
412 HttpConstants::POST
, "/foo");
413 request
.AddBody(body
, true);
415 EXPECT_EQ(kFooResponseBody
, client_
->SendCustomSynchronousRequest(request
));
416 EXPECT_EQ(2, client_
->client()->session()->GetNumSentClientHellos());
418 client_
->Disconnect();
420 // The 0-RTT handshake should succeed.
422 ASSERT_TRUE(client_
->client()->connected());
423 EXPECT_EQ(kFooResponseBody
, client_
->SendCustomSynchronousRequest(request
));
424 EXPECT_EQ(1, client_
->client()->session()->GetNumSentClientHellos());
426 client_
->Disconnect();
428 // Restart the server so that the 0-RTT handshake will take 1 RTT.
430 server_writer_
= new PacketDroppingTestWriter();
434 ASSERT_TRUE(client_
->client()->connected());
435 EXPECT_EQ(kFooResponseBody
, client_
->SendCustomSynchronousRequest(request
));
436 EXPECT_EQ(2, client_
->client()->session()->GetNumSentClientHellos());
439 // TODO(ianswett): Enable once b/9295090 is fixed.
440 TEST_P(EndToEndTest
, DISABLED_LargePostFEC
) {
441 SetPacketLossPercentage(30);
442 ASSERT_TRUE(Initialize());
443 client_
->options()->max_packets_per_fec_group
= 6;
446 GenerateBody(&body
, 10240);
448 HTTPMessage
request(HttpConstants::HTTP_1_1
,
449 HttpConstants::POST
, "/foo");
450 request
.AddBody(body
, true);
452 EXPECT_EQ(kFooResponseBody
, client_
->SendCustomSynchronousRequest(request
));
455 /*TEST_P(EndToEndTest, PacketTooLarge) {
456 FLAGS_quic_allow_oversized_packets_for_test = true;
457 ASSERT_TRUE(Initialize());
460 GenerateBody(&body, kMaxPacketSize);
462 HTTPMessage request(HttpConstants::HTTP_1_1,
463 HttpConstants::POST, "/foo");
464 request.AddBody(body, true);
465 client_->options()->max_packet_length = 20480;
467 EXPECT_EQ("", client_->SendCustomSynchronousRequest(request));
468 EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
469 EXPECT_EQ(QUIC_PACKET_TOO_LARGE, client_->connection_error());
472 TEST_P(EndToEndTest
, InvalidStream
) {
473 ASSERT_TRUE(Initialize());
476 GenerateBody(&body
, kMaxPacketSize
);
478 HTTPMessage
request(HttpConstants::HTTP_1_1
,
479 HttpConstants::POST
, "/foo");
480 request
.AddBody(body
, true);
481 // Force the client to write with a stream ID belonging to a nonexistent
482 // server-side stream.
483 QuicSessionPeer::SetNextStreamId(client_
->client()->session(), 2);
485 client_
->SendCustomSynchronousRequest(request
);
486 // EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
487 EXPECT_EQ(QUIC_PACKET_FOR_NONEXISTENT_STREAM
, client_
->connection_error());
490 // TODO(rch): this test seems to cause net_unittests timeouts :|
491 TEST_P(EndToEndTest
, DISABLED_MultipleTermination
) {
492 ASSERT_TRUE(Initialize());
494 HTTPMessage
request(HttpConstants::HTTP_1_1
,
495 HttpConstants::POST
, "/foo");
496 request
.AddHeader("content-length", "3");
497 request
.set_has_complete_message(false);
499 // Set the offset so we won't frame. Otherwise when we pick up termination
500 // before HTTP framing is complete, we send an error and close the stream,
501 // and the second write is picked up as writing on a closed stream.
502 QuicReliableClientStream
* stream
= client_
->GetOrCreateStream();
503 ASSERT_TRUE(stream
!= NULL
);
504 ReliableQuicStreamPeer::SetStreamBytesWritten(3, stream
);
506 client_
->SendData("bar", true);
508 // By default the stream protects itself from writes after terminte is set.
509 // Override this to test the server handling buggy clients.
510 ReliableQuicStreamPeer::SetWriteSideClosed(
511 false, client_
->GetOrCreateStream());
513 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
514 #if !defined(DCHECK_ALWAYS_ON)
516 client_
->SendData("eep", true);
517 client_
->WaitForResponse();
518 EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS
, client_
->stream_error());
520 "Check failed: !fin_buffered_");
523 client_
->SendData("eep", true);
524 client_
->WaitForResponse();
525 EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS
, client_
->stream_error());
527 "Check failed: !fin_buffered_");
532 TEST_P(EndToEndTest
, Timeout
) {
533 client_config_
.set_idle_connection_state_lifetime(
534 QuicTime::Delta::FromMicroseconds(500),
535 QuicTime::Delta::FromMicroseconds(500));
536 // Note: we do NOT ASSERT_TRUE: we may time out during initial handshake:
537 // that's enough to validate timeout in this case.
539 while (client_
->client()->connected()) {
540 client_
->client()->WaitForEvents();
544 TEST_P(EndToEndTest
, LimitMaxOpenStreams
) {
545 // Server limits the number of max streams to 2.
546 server_config_
.set_max_streams_per_connection(2, 2);
547 // Client tries to negotiate for 10.
548 client_config_
.set_max_streams_per_connection(10, 5);
550 ASSERT_TRUE(Initialize());
551 client_
->client()->WaitForCryptoHandshakeConfirmed();
552 QuicConfig
* client_negotiated_config
= client_
->client()->session()->config();
553 EXPECT_EQ(2u, client_negotiated_config
->max_streams_per_connection());
556 TEST_P(EndToEndTest
, ResetConnection
) {
557 ASSERT_TRUE(Initialize());
559 EXPECT_EQ(kFooResponseBody
, client_
->SendSynchronousRequest("/foo"));
560 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
561 client_
->ResetConnection();
562 EXPECT_EQ(kBarResponseBody
, client_
->SendSynchronousRequest("/bar"));
563 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
566 TEST_P(EndToEndTest
, MaxStreamsUberTest
) {
567 SetPacketLossPercentage(1);
568 ASSERT_TRUE(Initialize());
570 GenerateBody(&large_body
, 10240);
571 int max_streams
= 100;
573 AddToCache("GET", "/large_response", "HTTP/1.1", "200", "OK", large_body
);;
575 client_
->client()->WaitForCryptoHandshakeConfirmed();
576 SetPacketLossPercentage(10);
578 for (int i
= 0; i
< max_streams
; ++i
) {
579 EXPECT_LT(0, client_
->SendRequest("/large_response"));
582 // WaitForEvents waits 50ms and returns true if there are outstanding
584 while (client_
->client()->WaitForEvents() == true) {
588 class WrongAddressWriter
: public QuicTestWriter
{
590 WrongAddressWriter() {
592 CHECK(net::ParseIPLiteralToNumber("127.0.0.2", &ip
));
593 self_address_
= IPEndPoint(ip
, 0);
596 virtual WriteResult
WritePacket(
597 const char* buffer
, size_t buf_len
,
598 const IPAddressNumber
& real_self_address
,
599 const IPEndPoint
& peer_address
,
600 QuicBlockedWriterInterface
* blocked_writer
) OVERRIDE
{
601 return writer()->WritePacket(buffer
, buf_len
, self_address_
.address(),
602 peer_address
, blocked_writer
);
605 virtual bool IsWriteBlockedDataBuffered() const OVERRIDE
{
609 IPEndPoint self_address_
;
612 TEST_P(EndToEndTest
, ConnectionMigration
) {
613 ASSERT_TRUE(Initialize());
615 EXPECT_EQ(kFooResponseBody
, client_
->SendSynchronousRequest("/foo"));
616 EXPECT_EQ(200u, client_
->response_headers()->parsed_response_code());
618 scoped_ptr
<WrongAddressWriter
> writer(new WrongAddressWriter());
620 writer
->set_writer(new QuicDefaultPacketWriter(
621 QuicClientPeer::GetFd(client_
->client())));
622 QuicConnectionPeer::SetWriter(
623 client_
->client()->session()->connection(),
624 reinterpret_cast<QuicTestWriter
*>(writer
.get()));
626 client_
->SendSynchronousRequest("/bar");
628 EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR
, client_
->stream_error());
629 EXPECT_EQ(QUIC_ERROR_MIGRATING_ADDRESS
, client_
->connection_error());