Windows should animate when they are about to get docked at screen edges.
[chromium-blink-merge.git] / net / tools / quic / end_to_end_test.cc
blob3903df965ee87d6ca14af49f8ae1f5e83a102541
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.
5 #include <stddef.h>
6 #include <string>
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 "base/threading/simple_thread.h"
13 #include "net/base/ip_endpoint.h"
14 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
15 #include "net/quic/crypto/null_encrypter.h"
16 #include "net/quic/quic_framer.h"
17 #include "net/quic/quic_packet_creator.h"
18 #include "net/quic/quic_protocol.h"
19 #include "net/quic/test_tools/quic_connection_peer.h"
20 #include "net/quic/test_tools/quic_session_peer.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/quic_client_peer.h"
28 #include "net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h"
29 #include "net/tools/quic/test_tools/quic_test_client.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 using base::StringPiece;
33 using base::WaitableEvent;
34 using net::test::QuicConnectionPeer;
35 using net::test::QuicSessionPeer;
36 using net::test::ReliableQuicStreamPeer;
37 using std::string;
39 namespace net {
40 namespace tools {
41 namespace test {
42 namespace {
44 const char* kFooResponseBody = "Artichoke hearts make me happy.";
45 const char* kBarResponseBody = "Palm hearts are pretty delicious, also.";
46 const size_t kCongestionFeedbackFrameSize = 25;
47 // If kCongestionFeedbackFrameSize increase we need to expand this string
48 // accordingly.
49 const char* kLargeRequest =
50 "https://www.google.com/foo/test/a/request/string/longer/than/25/bytes";
52 void GenerateBody(string* body, int length) {
53 body->clear();
54 body->reserve(length);
55 for (int i = 0; i < length; ++i) {
56 body->append(1, static_cast<char>(32 + i % (126 - 32)));
61 // Simple wrapper class to run server in a thread.
62 class ServerThread : public base::SimpleThread {
63 public:
64 explicit ServerThread(IPEndPoint address, const QuicConfig& config)
65 : SimpleThread("server_thread"),
66 listening_(true, false),
67 quit_(true, false),
68 server_(config),
69 address_(address),
70 port_(0) {
72 virtual ~ServerThread() {
75 virtual void Run() OVERRIDE {
76 server_.Listen(address_);
78 port_lock_.Acquire();
79 port_ = server_.port();
80 port_lock_.Release();
82 listening_.Signal();
83 while (!quit_.IsSignaled()) {
84 server_.WaitForEvents();
86 server_.Shutdown();
89 int GetPort() {
90 port_lock_.Acquire();
91 int rc = port_;
92 port_lock_.Release();
93 return rc;
96 WaitableEvent* listening() { return &listening_; }
97 WaitableEvent* quit() { return &quit_; }
99 private:
100 WaitableEvent listening_;
101 WaitableEvent quit_;
102 base::Lock port_lock_;
103 QuicServer server_;
104 IPEndPoint address_;
105 int port_;
107 DISALLOW_COPY_AND_ASSIGN(ServerThread);
110 class EndToEndTest : public ::testing::TestWithParam<QuicVersion> {
111 public:
112 static void SetUpTestCase() {
113 QuicInMemoryCache::GetInstance()->ResetForTests();
116 protected:
117 EndToEndTest()
118 : server_hostname_("example.com"),
119 server_started_(false) {
120 net::IPAddressNumber ip;
121 CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
122 server_address_ = IPEndPoint(ip, 0);
123 client_config_.SetDefaults();
124 server_config_.SetDefaults();
126 AddToCache("GET", kLargeRequest, "HTTP/1.1", "200", "OK", kFooResponseBody);
127 AddToCache("GET", "https://www.google.com/foo",
128 "HTTP/1.1", "200", "OK", kFooResponseBody);
129 AddToCache("GET", "https://www.google.com/bar",
130 "HTTP/1.1", "200", "OK", kBarResponseBody);
131 version_ = GetParam();
134 virtual QuicTestClient* CreateQuicClient() {
135 QuicTestClient* client = new QuicTestClient(server_address_,
136 server_hostname_,
137 false, // not secure
138 client_config_,
139 version_);
140 client->Connect();
141 return client;
144 virtual bool Initialize() {
145 // Start the server first, because CreateQuicClient() attempts
146 // to connect to the server.
147 StartServer();
148 client_.reset(CreateQuicClient());
149 return client_->client()->connected();
152 virtual void TearDown() {
153 StopServer();
156 void StartServer() {
157 server_thread_.reset(new ServerThread(server_address_, server_config_));
158 server_thread_->Start();
159 server_thread_->listening()->Wait();
160 server_address_ = IPEndPoint(server_address_.address(),
161 server_thread_->GetPort());
162 server_started_ = true;
165 void StopServer() {
166 if (!server_started_)
167 return;
168 if (server_thread_.get()) {
169 server_thread_->quit()->Signal();
170 server_thread_->Join();
174 void AddToCache(const StringPiece& method,
175 const StringPiece& path,
176 const StringPiece& version,
177 const StringPiece& response_code,
178 const StringPiece& response_detail,
179 const StringPiece& body) {
180 BalsaHeaders request_headers, response_headers;
181 request_headers.SetRequestFirstlineFromStringPieces(method,
182 path,
183 version);
184 response_headers.SetRequestFirstlineFromStringPieces(version,
185 response_code,
186 response_detail);
187 response_headers.AppendHeader("content-length",
188 base::IntToString(body.length()));
190 // Check if response already exists and matches.
191 QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
192 const QuicInMemoryCache::Response* cached_response =
193 cache->GetResponse(request_headers);
194 if (cached_response != NULL) {
195 string cached_response_headers_str, response_headers_str;
196 cached_response->headers().DumpToString(&cached_response_headers_str);
197 response_headers.DumpToString(&response_headers_str);
198 CHECK_EQ(cached_response_headers_str, response_headers_str);
199 CHECK_EQ(cached_response->body(), body);
200 return;
202 cache->AddResponse(request_headers, response_headers, body);
205 IPEndPoint server_address_;
206 string server_hostname_;
207 scoped_ptr<ServerThread> server_thread_;
208 scoped_ptr<QuicTestClient> client_;
209 bool server_started_;
210 QuicConfig client_config_;
211 QuicConfig server_config_;
212 QuicVersion version_;
215 // Run all end to end tests with all supported versions.
216 INSTANTIATE_TEST_CASE_P(EndToEndTests,
217 EndToEndTest,
218 ::testing::ValuesIn(kSupportedQuicVersions));
220 TEST_P(EndToEndTest, SimpleRequestResponse) {
221 // TODO(rtenneti): Delete this when NSS is supported.
222 if (!Aes128Gcm12Encrypter::IsSupported()) {
223 LOG(INFO) << "AES GCM not supported. Test skipped.";
224 return;
227 ASSERT_TRUE(Initialize());
229 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
230 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
233 // TODO(rch): figure out how to detect missing v6 supprt (like on the linux
234 // try bots) and selectively disable this test.
235 TEST_P(EndToEndTest, DISABLED_SimpleRequestResponsev6) {
236 // TODO(rtenneti): Delete this when NSS is supported.
237 if (!Aes128Gcm12Encrypter::IsSupported()) {
238 LOG(INFO) << "AES GCM not supported. Test skipped.";
239 return;
242 IPAddressNumber ip;
243 CHECK(net::ParseIPLiteralToNumber("::1", &ip));
244 server_address_ = IPEndPoint(ip, server_address_.port());
245 ASSERT_TRUE(Initialize());
247 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
248 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
251 TEST_P(EndToEndTest, SeparateFinPacket) {
252 // TODO(rtenneti): Delete this when NSS is supported.
253 if (!Aes128Gcm12Encrypter::IsSupported()) {
254 LOG(INFO) << "AES GCM not supported. Test skipped.";
255 return;
258 ASSERT_TRUE(Initialize());
260 HTTPMessage request(HttpConstants::HTTP_1_1,
261 HttpConstants::POST, "/foo");
262 request.set_has_complete_message(false);
264 client_->SendMessage(request);
266 client_->SendData(string(), true);
268 client_->WaitForResponse();
269 EXPECT_EQ(kFooResponseBody, client_->response_body());
270 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
272 request.AddBody("foo", true);
274 client_->SendMessage(request);
275 client_->SendData(string(), true);
276 client_->WaitForResponse();
277 EXPECT_EQ(kFooResponseBody, client_->response_body());
278 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
281 TEST_P(EndToEndTest, MultipleRequestResponse) {
282 // TODO(rtenneti): Delete this when NSS is supported.
283 if (!Aes128Gcm12Encrypter::IsSupported()) {
284 LOG(INFO) << "AES GCM not supported. Test skipped.";
285 return;
288 ASSERT_TRUE(Initialize());
290 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
291 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
292 EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
293 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
296 TEST_P(EndToEndTest, MultipleClients) {
297 // TODO(rtenneti): Delete this when NSS is supported.
298 if (!Aes128Gcm12Encrypter::IsSupported()) {
299 LOG(INFO) << "AES GCM not supported. Test skipped.";
300 return;
303 ASSERT_TRUE(Initialize());
304 scoped_ptr<QuicTestClient> client2(CreateQuicClient());
306 HTTPMessage request(HttpConstants::HTTP_1_1,
307 HttpConstants::POST, "/foo");
308 request.AddHeader("content-length", "3");
309 request.set_has_complete_message(false);
311 client_->SendMessage(request);
312 client2->SendMessage(request);
314 client_->SendData("bar", true);
315 client_->WaitForResponse();
316 EXPECT_EQ(kFooResponseBody, client_->response_body());
317 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
319 client2->SendData("eep", true);
320 client2->WaitForResponse();
321 EXPECT_EQ(kFooResponseBody, client2->response_body());
322 EXPECT_EQ(200u, client2->response_headers()->parsed_response_code());
325 TEST_P(EndToEndTest, RequestOverMultiplePackets) {
326 // TODO(rtenneti): Delete this when NSS is supported.
327 if (!Aes128Gcm12Encrypter::IsSupported()) {
328 LOG(INFO) << "AES GCM not supported. Test skipped.";
329 return;
332 ASSERT_TRUE(Initialize());
333 // Set things up so we have a small payload, to guarantee fragmentation.
334 // A congestion feedback frame can't be split into multiple packets, make sure
335 // that our packet have room for at least this amount after the normal headers
336 // are added.
338 // TODO(rch) handle this better when we have different encryption options.
339 const size_t kStreamDataLength = 3;
340 const QuicStreamId kStreamId = 1u;
341 const QuicStreamOffset kStreamOffset = 0u;
342 size_t stream_payload_size =
343 QuicFramer::GetMinStreamFrameSize(
344 GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength;
345 size_t min_payload_size =
346 std::max(kCongestionFeedbackFrameSize, stream_payload_size);
347 size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size);
348 // TODO(satyashekhar): Fix this when versioning is implemented.
349 client_->options()->max_packet_length =
350 GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
351 PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
352 ciphertext_size;
354 // Make sure our request is too large to fit in one packet.
355 EXPECT_GT(strlen(kLargeRequest), min_payload_size);
356 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest));
357 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
360 TEST_P(EndToEndTest, MultipleFramesRandomOrder) {
361 // TODO(rtenneti): Delete this when NSS is supported.
362 if (!Aes128Gcm12Encrypter::IsSupported()) {
363 LOG(INFO) << "AES GCM not supported. Test skipped.";
364 return;
367 ASSERT_TRUE(Initialize());
368 // Set things up so we have a small payload, to guarantee fragmentation.
369 // A congestion feedback frame can't be split into multiple packets, make sure
370 // that our packet have room for at least this amount after the normal headers
371 // are added.
373 // TODO(rch) handle this better when we have different encryption options.
374 const size_t kStreamDataLength = 3;
375 const QuicStreamId kStreamId = 1u;
376 const QuicStreamOffset kStreamOffset = 0u;
377 size_t stream_payload_size =
378 QuicFramer::GetMinStreamFrameSize(
379 GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength;
380 size_t min_payload_size =
381 std::max(kCongestionFeedbackFrameSize, stream_payload_size);
382 size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size);
383 // TODO(satyashekhar): Fix this when versioning is implemented.
384 client_->options()->max_packet_length =
385 GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
386 PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
387 ciphertext_size;
388 client_->options()->random_reorder = true;
390 // Make sure our request is too large to fit in one packet.
391 EXPECT_GT(strlen(kLargeRequest), min_payload_size);
392 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest));
393 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
396 TEST_P(EndToEndTest, PostMissingBytes) {
397 // TODO(rtenneti): Delete this when NSS is supported.
398 if (!Aes128Gcm12Encrypter::IsSupported()) {
399 LOG(INFO) << "AES GCM not supported. Test skipped.";
400 return;
403 ASSERT_TRUE(Initialize());
405 // Add a content length header with no body.
406 HTTPMessage request(HttpConstants::HTTP_1_1,
407 HttpConstants::POST, "/foo");
408 request.AddHeader("content-length", "3");
409 request.set_skip_message_validation(true);
411 // This should be detected as stream fin without complete request,
412 // triggering an error response.
413 client_->SendCustomSynchronousRequest(request);
414 EXPECT_EQ("bad", client_->response_body());
415 EXPECT_EQ(500u, client_->response_headers()->parsed_response_code());
418 TEST_P(EndToEndTest, LargePost) {
419 // TODO(rtenneti): Delete this when NSS is supported.
420 if (!Aes128Gcm12Encrypter::IsSupported()) {
421 LOG(INFO) << "AES GCM not supported. Test skipped.";
422 return;
425 // Connect with lower fake packet loss than we'd like to test. Until
426 // b/10126687 is fixed, losing handshake packets is pretty brutal.
427 // FLAGS_fake_packet_loss_percentage = 5;
428 ASSERT_TRUE(Initialize());
430 // Wait for the server SHLO before upping the packet loss.
431 client_->client()->WaitForCryptoHandshakeConfirmed();
432 // FLAGS_fake_packet_loss_percentage = 30;
434 string body;
435 GenerateBody(&body, 10240);
437 HTTPMessage request(HttpConstants::HTTP_1_1,
438 HttpConstants::POST, "/foo");
439 request.AddBody(body, true);
441 EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
444 // TODO(ianswett): Enable once b/9295090 is fixed.
445 TEST_P(EndToEndTest, DISABLED_LargePostFEC) {
446 // FLAGS_fake_packet_loss_percentage = 30;
447 ASSERT_TRUE(Initialize());
448 client_->options()->max_packets_per_fec_group = 6;
450 // TODO(rtenneti): Delete this when NSS is supported.
451 if (!Aes128Gcm12Encrypter::IsSupported()) {
452 LOG(INFO) << "AES GCM not supported. Test skipped.";
453 return;
456 // FLAGS_fake_packet_loss_percentage = 30;
457 ASSERT_TRUE(Initialize());
458 client_->options()->max_packets_per_fec_group = 6;
460 string body;
461 GenerateBody(&body, 10240);
463 HTTPMessage request(HttpConstants::HTTP_1_1,
464 HttpConstants::POST, "/foo");
465 request.AddBody(body, true);
467 EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
470 /*TEST_P(EndToEndTest, PacketTooLarge) {
471 FLAGS_quic_allow_oversized_packets_for_test = true;
472 ASSERT_TRUE(Initialize());
474 string body;
475 GenerateBody(&body, kMaxPacketSize);
477 HTTPMessage request(HttpConstants::HTTP_1_1,
478 HttpConstants::POST, "/foo");
479 request.AddBody(body, true);
480 client_->options()->max_packet_length = 20480;
482 EXPECT_EQ("", client_->SendCustomSynchronousRequest(request));
483 EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
484 EXPECT_EQ(QUIC_PACKET_TOO_LARGE, client_->connection_error());
487 TEST_P(EndToEndTest, InvalidStream) {
488 // TODO(rtenneti): Delete this when NSS is supported.
489 if (!Aes128Gcm12Encrypter::IsSupported()) {
490 LOG(INFO) << "AES GCM not supported. Test skipped.";
491 return;
494 ASSERT_TRUE(Initialize());
496 string body;
497 GenerateBody(&body, kMaxPacketSize);
499 HTTPMessage request(HttpConstants::HTTP_1_1,
500 HttpConstants::POST, "/foo");
501 request.AddBody(body, true);
502 // Force the client to write with a stream ID belonging to a nonexistent
503 // server-side stream.
504 QuicSessionPeer::SetNextStreamId(client_->client()->session(), 2);
506 client_->SendCustomSynchronousRequest(request);
507 // EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
508 EXPECT_EQ(QUIC_PACKET_FOR_NONEXISTENT_STREAM, client_->connection_error());
511 // TODO(rch): this test seems to cause net_unittests timeouts :|
512 TEST_P(EndToEndTest, DISABLED_MultipleTermination) {
513 // TODO(rtenneti): Delete this when NSS is supported.
514 if (!Aes128Gcm12Encrypter::IsSupported()) {
515 LOG(INFO) << "AES GCM not supported. Test skipped.";
516 return;
519 ASSERT_TRUE(Initialize());
520 scoped_ptr<QuicTestClient> client2(CreateQuicClient());
522 HTTPMessage request(HttpConstants::HTTP_1_1,
523 HttpConstants::POST, "/foo");
524 request.AddHeader("content-length", "3");
525 request.set_has_complete_message(false);
527 // Set the offset so we won't frame. Otherwise when we pick up termination
528 // before HTTP framing is complete, we send an error and close the stream,
529 // and the second write is picked up as writing on a closed stream.
530 QuicReliableClientStream* stream = client_->GetOrCreateStream();
531 ASSERT_TRUE(stream != NULL);
532 ReliableQuicStreamPeer::SetStreamBytesWritten(3, stream);
534 client_->SendData("bar", true);
536 // By default the stream protects itself from writes after terminte is set.
537 // Override this to test the server handling buggy clients.
538 ReliableQuicStreamPeer::SetWriteSideClosed(
539 false, client_->GetOrCreateStream());
541 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
542 #if !defined(DCHECK_ALWAYS_ON)
543 EXPECT_DEBUG_DEATH({
544 client_->SendData("eep", true);
545 client_->WaitForResponse();
546 EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS, client_->stream_error());
548 "Check failed: !fin_buffered_");
549 #else
550 EXPECT_DEATH({
551 client_->SendData("eep", true);
552 client_->WaitForResponse();
553 EXPECT_EQ(QUIC_MULTIPLE_TERMINATION_OFFSETS, client_->stream_error());
555 "Check failed: !fin_buffered_");
556 #endif
557 #endif
560 TEST_P(EndToEndTest, Timeout) {
561 client_config_.set_idle_connection_state_lifetime(
562 QuicTime::Delta::FromMicroseconds(500),
563 QuicTime::Delta::FromMicroseconds(500));
564 // Note: we do NOT ASSERT_TRUE: we may time out during initial handshake:
565 // that's enough to validate timeout in this case.
566 Initialize();
567 while (client_->client()->connected()) {
568 client_->client()->WaitForEvents();
572 TEST_P(EndToEndTest, LimitMaxOpenStreams) {
573 // Server limits the number of max streams to 2.
574 server_config_.set_max_streams_per_connection(2, 2);
575 // Client tries to negotiate for 10.
576 client_config_.set_max_streams_per_connection(10, 5);
578 ASSERT_TRUE(Initialize());
579 client_->client()->WaitForCryptoHandshakeConfirmed();
580 QuicConfig* client_negotiated_config = client_->client()->session()->config();
581 EXPECT_EQ(2u, client_negotiated_config->max_streams_per_connection());
584 TEST_P(EndToEndTest, ResetConnection) {
585 // TODO(rtenneti): Delete this when NSS is supported.
586 if (!Aes128Gcm12Encrypter::IsSupported()) {
587 LOG(INFO) << "AES GCM not supported. Test skipped.";
588 return;
591 ASSERT_TRUE(Initialize());
593 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
594 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
595 client_->ResetConnection();
596 EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest("/bar"));
597 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
600 class WrongAddressWriter : public QuicPacketWriter {
601 public:
602 explicit WrongAddressWriter(int fd) : fd_(fd) {
603 IPAddressNumber ip;
604 CHECK(net::ParseIPLiteralToNumber("127.0.0.2", &ip));
605 self_address_ = IPEndPoint(ip, 0);
608 virtual int WritePacket(const char* buffer, size_t buf_len,
609 const IPAddressNumber& real_self_address,
610 const IPEndPoint& peer_address,
611 QuicBlockedWriterInterface* blocked_writer,
612 int* error) OVERRIDE {
613 return QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
614 self_address_.address(), peer_address,
615 error);
618 IPEndPoint self_address_;
619 int fd_;
622 TEST_P(EndToEndTest, ConnectionMigration) {
623 // TODO(rtenneti): Delete this when NSS is supported.
624 if (!Aes128Gcm12Encrypter::IsSupported()) {
625 LOG(INFO) << "AES GCM not supported. Test skipped.";
626 return;
629 ASSERT_TRUE(Initialize());
631 EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
632 EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
634 WrongAddressWriter writer(QuicClientPeer::GetFd(client_->client()));
635 QuicEpollConnectionHelper* helper =
636 reinterpret_cast<QuicEpollConnectionHelper*>(
637 QuicConnectionPeer::GetHelper(
638 client_->client()->session()->connection()));
639 QuicEpollConnectionHelperPeer::SetWriter(helper, &writer);
641 client_->SendSynchronousRequest("/bar");
642 QuicEpollConnectionHelperPeer::SetWriter(helper, NULL);
644 EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
645 EXPECT_EQ(QUIC_ERROR_MIGRATING_ADDRESS, client_->connection_error());
648 } // namespace
649 } // namespace test
650 } // namespace tools
651 } // namespace net