blob: 6820bd9a4c11ecc283d666cddd7b122c1dd67476 [file] [log] [blame]
xunjieli100937eb52016-09-15 20:09:371// Copyright 2016 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
xunjieli100937eb52016-09-15 20:09:375#include "base/files/file_path.h"
6#include "base/macros.h"
xunjieli100937eb52016-09-15 20:09:377#include "base/run_loop.h"
8#include "base/strings/string_number_conversions.h"
9#include "base/strings/stringprintf.h"
10#include "net/base/load_timing_info.h"
11#include "net/base/network_delegate.h"
12#include "net/cert/mock_cert_verifier.h"
13#include "net/dns/mapped_host_resolver.h"
14#include "net/dns/mock_host_resolver.h"
zhongyid7dd2db12017-04-14 17:01:2515#include "net/log/net_log_event_type.h"
16#include "net/log/test_net_log.h"
17#include "net/log/test_net_log_entry.h"
xunjieli100937eb52016-09-15 20:09:3718#include "net/quic/chromium/crypto/proof_source_chromium.h"
19#include "net/quic/test_tools/crypto_test_utils.h"
20#include "net/test/cert_test_util.h"
21#include "net/test/gtest_util.h"
22#include "net/test/test_data_directory.h"
zhongyid7dd2db12017-04-14 17:01:2523#include "net/tools/quic/quic_dispatcher.h"
vasilvv28270e8f2016-12-01 21:38:0924#include "net/tools/quic/quic_http_response_cache.h"
zhongyid7dd2db12017-04-14 17:01:2525#include "net/tools/quic/quic_simple_dispatcher.h"
xunjieli100937eb52016-09-15 20:09:3726#include "net/tools/quic/quic_simple_server.h"
rhalavatib7bd7c792017-04-27 05:25:1627#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
xunjieli100937eb52016-09-15 20:09:3728#include "net/url_request/url_request.h"
29#include "net/url_request/url_request_test_util.h"
30#include "testing/gmock/include/gmock/gmock.h"
31#include "testing/gtest/include/gtest/gtest.h"
32#include "url/gurl.h"
33
34namespace net {
35
36namespace {
37
38// This must match the certificate used (quic_test.example.com.crt and
39// quic_test.example.com.key.pkcs8).
40const int kTestServerPort = 6121;
zhongyi6f20e71d2017-02-14 23:20:3941const char kTestServerHost[] = "test.example.com";
xunjieli100937eb52016-09-15 20:09:3742// Used as a simple response from the server.
43const char kHelloPath[] = "/hello.txt";
44const char kHelloBodyValue[] = "Hello from QUIC Server";
45const int kHelloStatus = 200;
46
47class URLRequestQuicTest : public ::testing::Test {
48 protected:
49 URLRequestQuicTest() : context_(new TestURLRequestContext(true)) {
50 StartQuicServer();
51
52 std::unique_ptr<HttpNetworkSession::Params> params(
53 new HttpNetworkSession::Params);
54 CertVerifyResult verify_result;
55 verify_result.verified_cert = ImportCertFromFile(
56 GetTestCertsDirectory(), "quic_test.example.com.crt");
57 cert_verifier_.AddResultForCertAndHost(verify_result.verified_cert.get(),
58 "test.example.com", verify_result,
59 OK);
60 verify_result.verified_cert = ImportCertFromFile(
61 GetTestCertsDirectory(), "quic_test_ecc.example.com.crt");
62 cert_verifier_.AddResultForCertAndHost(verify_result.verified_cert.get(),
63 "test.example.com", verify_result,
64 OK);
65 // To simplify the test, and avoid the race with the HTTP request, we force
66 // QUIC for these requests.
zhongyi6f20e71d2017-02-14 23:20:3967 params->origins_to_force_quic_on.insert(HostPortPair(kTestServerHost, 443));
xunjieli100937eb52016-09-15 20:09:3768 params->enable_quic = true;
zhongyid7dd2db12017-04-14 17:01:2569 params->enable_server_push_cancellation = true;
zhongyi6f20e71d2017-02-14 23:20:3970 context_->set_host_resolver(host_resolver_.get());
xunjieli100937eb52016-09-15 20:09:3771 context_->set_http_network_session_params(std::move(params));
72 context_->set_cert_verifier(&cert_verifier_);
zhongyid7dd2db12017-04-14 17:01:2573 context_->set_net_log(&net_log_);
xunjieli100937eb52016-09-15 20:09:3774 }
75
76 void TearDown() override {
zhongyid7dd2db12017-04-14 17:01:2577 if (server_) {
xunjieli100937eb52016-09-15 20:09:3778 server_->Shutdown();
zhongyid7dd2db12017-04-14 17:01:2579 // If possible, deliver the conncetion close packet to the client before
80 // destruct the TestURLRequestContext.
81 base::RunLoop().RunUntilIdle();
82 }
xunjieli100937eb52016-09-15 20:09:3783 }
84
85 // Sets a NetworkDelegate to use for |context_|. Must be done before Init().
86 void SetNetworkDelegate(NetworkDelegate* network_delegate) {
87 context_->set_network_delegate(network_delegate);
88 }
89
90 // Initializes the TestURLRequestContext |context_|.
91 void Init() { context_->Init(); }
92
93 std::unique_ptr<URLRequest> CreateRequest(const GURL& url,
94 RequestPriority priority,
95 URLRequest::Delegate* delegate) {
rhalavatib7bd7c792017-04-27 05:25:1696 return context_->CreateRequest(url, priority, delegate,
97 TRAFFIC_ANNOTATION_FOR_TESTS);
xunjieli100937eb52016-09-15 20:09:3798 }
99
zhongyid7dd2db12017-04-14 17:01:25100 void ExtractNetLog(NetLogEventType type,
101 TestNetLogEntry::List* entry_list) const {
102 net::TestNetLogEntry::List entries;
103 net_log_.GetEntries(&entries);
104
105 for (const auto& entry : entries) {
106 if (entry.type == type)
107 entry_list->push_back(entry);
108 }
109 }
110
111 unsigned int GetRstErrorCountReceivedByServer(
112 QuicRstStreamErrorCode error_code) const {
113 return (static_cast<QuicSimpleDispatcher*>(server_->dispatcher()))
114 ->GetRstErrorCount(error_code);
115 }
116
xunjieli100937eb52016-09-15 20:09:37117 private:
118 void StartQuicServer() {
119 // Set up in-memory cache.
vasilvv28270e8f2016-12-01 21:38:09120 response_cache_.AddSimpleResponse(kTestServerHost, kHelloPath, kHelloStatus,
121 kHelloBodyValue);
zhongyid7dd2db12017-04-14 17:01:25122 response_cache_.InitializeFromDirectory(ServerPushCacheDirectory());
xunjieli100937eb52016-09-15 20:09:37123 net::QuicConfig config;
124 // Set up server certs.
125 std::unique_ptr<net::ProofSourceChromium> proof_source(
126 new net::ProofSourceChromium());
127 base::FilePath directory = GetTestCertsDirectory();
128 CHECK(proof_source->Initialize(
129 directory.Append(FILE_PATH_LITERAL("quic_test.example.com.crt")),
130 directory.Append(FILE_PATH_LITERAL("quic_test.example.com.key.pkcs8")),
131 directory.Append(FILE_PATH_LITERAL("quic_test.example.com.key.sct"))));
132 server_.reset(new QuicSimpleServer(
fayangf5f4cd512017-02-07 16:57:11133 test::crypto_test_utils::ProofSourceForTesting(), config,
Michael Warres74ee3ce2017-10-09 15:26:37134 net::QuicCryptoServerConfig::ConfigOptions(),
135 AllSupportedTransportVersions(), &response_cache_));
xunjieli100937eb52016-09-15 20:09:37136 int rv = server_->Listen(
137 net::IPEndPoint(net::IPAddress::IPv4AllZeros(), kTestServerPort));
138 EXPECT_GE(rv, 0) << "Quic server fails to start";
139
140 std::unique_ptr<MockHostResolver> resolver(new MockHostResolver());
141 resolver->rules()->AddRule("test.example.com", "127.0.0.1");
142 host_resolver_.reset(new MappedHostResolver(std::move(resolver)));
zhongyi6f20e71d2017-02-14 23:20:39143 // Use a mapped host resolver so that request for test.example.com
xunjieli100937eb52016-09-15 20:09:37144 // reach the server running on localhost.
145 std::string map_rule = "MAP test.example.com test.example.com:" +
146 base::IntToString(server_->server_address().port());
147 EXPECT_TRUE(host_resolver_->AddRuleFromString(map_rule));
148 }
149
zhongyid7dd2db12017-04-14 17:01:25150 std::string ServerPushCacheDirectory() {
151 base::FilePath path;
152 PathService::Get(base::DIR_SOURCE_ROOT, &path);
153 path = path.AppendASCII("net").AppendASCII("data").AppendASCII(
154 "quic_http_response_cache_data_with_push");
155 // The file path is known to be an ascii string.
156 return path.MaybeAsASCII();
157 }
158
xunjieli100937eb52016-09-15 20:09:37159 std::unique_ptr<MappedHostResolver> host_resolver_;
160 std::unique_ptr<QuicSimpleServer> server_;
161 std::unique_ptr<TestURLRequestContext> context_;
zhongyid7dd2db12017-04-14 17:01:25162 TestNetLog net_log_;
vasilvv28270e8f2016-12-01 21:38:09163 QuicHttpResponseCache response_cache_;
xunjieli100937eb52016-09-15 20:09:37164 MockCertVerifier cert_verifier_;
165};
166
167// A URLRequest::Delegate that checks LoadTimingInfo when response headers are
168// received.
169class CheckLoadTimingDelegate : public TestDelegate {
170 public:
171 CheckLoadTimingDelegate(bool session_reused)
172 : session_reused_(session_reused) {}
173 void OnResponseStarted(URLRequest* request, int error) override {
174 TestDelegate::OnResponseStarted(request, error);
175 LoadTimingInfo load_timing_info;
176 request->GetLoadTimingInfo(&load_timing_info);
177 assertLoadTimingValid(load_timing_info, session_reused_);
178 }
179
180 private:
181 void assertLoadTimingValid(const LoadTimingInfo& load_timing_info,
182 bool session_reused) {
183 EXPECT_EQ(session_reused, load_timing_info.socket_reused);
184
185 // If |session_reused| is true, these fields should all be null, non-null
186 // otherwise.
187 EXPECT_EQ(session_reused,
188 load_timing_info.connect_timing.connect_start.is_null());
189 EXPECT_EQ(session_reused,
190 load_timing_info.connect_timing.connect_end.is_null());
191 EXPECT_EQ(session_reused,
192 load_timing_info.connect_timing.ssl_start.is_null());
193 EXPECT_EQ(session_reused,
194 load_timing_info.connect_timing.ssl_end.is_null());
195 EXPECT_EQ(load_timing_info.connect_timing.connect_start,
196 load_timing_info.connect_timing.ssl_start);
197 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
198 load_timing_info.connect_timing.ssl_end);
199 EXPECT_EQ(session_reused,
200 load_timing_info.connect_timing.dns_start.is_null());
201 EXPECT_EQ(session_reused,
202 load_timing_info.connect_timing.dns_end.is_null());
203 }
204
205 bool session_reused_;
206
207 DISALLOW_COPY_AND_ASSIGN(CheckLoadTimingDelegate);
208};
209
210// A TestNetworkDelegate that invokes |all_requests_completed_callback| when
211// |num_expected_requests| requests are completed.
212class WaitForCompletionNetworkDelegate : public net::TestNetworkDelegate {
213 public:
214 WaitForCompletionNetworkDelegate(
215 const base::Closure& all_requests_completed_callback,
216 size_t num_expected_requests)
217 : all_requests_completed_callback_(all_requests_completed_callback),
218 num_expected_requests_(num_expected_requests) {}
219
220 void OnCompleted(URLRequest* request, bool started, int net_error) override {
221 net::TestNetworkDelegate::OnCompleted(request, started, net_error);
222 num_expected_requests_--;
223 if (num_expected_requests_ == 0)
224 all_requests_completed_callback_.Run();
225 }
226
227 private:
228 const base::Closure all_requests_completed_callback_;
229 size_t num_expected_requests_;
230 DISALLOW_COPY_AND_ASSIGN(WaitForCompletionNetworkDelegate);
231};
232
233} // namespace
234
235TEST_F(URLRequestQuicTest, TestGetRequest) {
236 Init();
237 CheckLoadTimingDelegate delegate(false);
238 std::string url =
239 base::StringPrintf("https://%s%s", kTestServerHost, kHelloPath);
240 std::unique_ptr<URLRequest> request =
241 CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
242
243 request->Start();
244 ASSERT_TRUE(request->is_pending());
245 base::RunLoop().Run();
246
247 EXPECT_TRUE(request->status().is_success());
248 EXPECT_EQ(kHelloBodyValue, delegate.data_received());
249}
250
zhongyid7dd2db12017-04-14 17:01:25251TEST_F(URLRequestQuicTest, CancelPushIfCached) {
252 base::RunLoop run_loop;
253 Init();
254
255 // Send a request to the pushed url: /kitten-1.jpg to pull the resource into
256 // cache.
257 CheckLoadTimingDelegate delegate_0(false);
258 std::string url_0 =
259 base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
260 std::unique_ptr<URLRequest> request_0 =
261 CreateRequest(GURL(url_0), DEFAULT_PRIORITY, &delegate_0);
262
263 request_0->Start();
264 ASSERT_TRUE(request_0->is_pending());
265
266 // Spin the message loop until the client receives the response for the first
267 // request.
268 do {
269 base::RunLoop().RunUntilIdle();
270 } while (request_0->status().is_io_pending());
271 EXPECT_TRUE(request_0->status().is_success());
272
273 // Send a request to /index2.html which pushes /kitten-1.jpg and /favicon.ico.
274 // Should cancel push for /kitten-1.jpg.
275 CheckLoadTimingDelegate delegate(true);
276 std::string url =
277 base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html");
278 std::unique_ptr<URLRequest> request =
279 CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
280
281 request->Start();
282 ASSERT_TRUE(request->is_pending());
283
284 // Spin the message loop until the client receives the response for the second
285 // request.
286 do {
287 base::RunLoop().RunUntilIdle();
288 } while (request->status().is_io_pending());
289 EXPECT_TRUE(request->status().is_success());
290
291 // Extract net logs on client side to verify push lookup transactions.
292 net::TestNetLogEntry::List entries;
293 ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries);
294
295 EXPECT_EQ(4u, entries.size());
296
297 std::string value;
298 int net_error;
299 std::string push_url_1 =
300 base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
301 std::string push_url_2 =
302 base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico");
303
304 EXPECT_TRUE(entries[0].GetStringValue("push_url", &value));
305 EXPECT_EQ(value, push_url_1);
shivanisha8061c4202017-06-13 23:35:52306 EXPECT_TRUE(entries[1].GetStringValue("push_url", &value));
zhongyid7dd2db12017-04-14 17:01:25307 EXPECT_EQ(value, push_url_2);
308 // Net error code -400 is found for this lookup transaction, the push is not
309 // found in the cache.
shivanisha8061c4202017-06-13 23:35:52310 EXPECT_TRUE(entries[2].GetIntegerValue("net_error", &net_error));
zhongyid7dd2db12017-04-14 17:01:25311 EXPECT_EQ(net_error, -400);
shivanisha8061c4202017-06-13 23:35:52312 // No net error code for this lookup transaction, the push is found.
313 EXPECT_FALSE(entries[3].GetIntegerValue("net_error", &net_error));
zhongyid7dd2db12017-04-14 17:01:25314
315 // Verify the reset error count received on the server side.
316 EXPECT_LE(1u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED));
317}
318
319TEST_F(URLRequestQuicTest, CancelPushIfCached2) {
320 base::RunLoop run_loop;
321 Init();
322
323 // Send a request to the pushed url: /kitten-1.jpg to pull the resource into
324 // cache.
325 CheckLoadTimingDelegate delegate_0(false);
326 std::string url_0 =
327 base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
328 std::unique_ptr<URLRequest> request_0 =
329 CreateRequest(GURL(url_0), DEFAULT_PRIORITY, &delegate_0);
330
331 request_0->Start();
332 ASSERT_TRUE(request_0->is_pending());
333
334 // Spin the message loop until the client receives the response for the first
335 // request.
336 do {
337 base::RunLoop().RunUntilIdle();
338 } while (request_0->status().is_io_pending());
339 EXPECT_TRUE(request_0->status().is_success());
340
341 // Send a request to the pushed url: /favicon.ico to pull the resource into
342 // cache.
343 CheckLoadTimingDelegate delegate_1(true);
344 std::string url_1 =
345 base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico");
346 std::unique_ptr<URLRequest> request_1 =
347 CreateRequest(GURL(url_1), DEFAULT_PRIORITY, &delegate_1);
348
349 request_1->Start();
350 ASSERT_TRUE(request_1->is_pending());
351
352 // Spin the message loop until the client receives the response for the second
353 // request.
354 do {
355 base::RunLoop().RunUntilIdle();
356 } while (request_1->status().is_io_pending());
357 EXPECT_TRUE(request_1->status().is_success());
358
359 // Send a request to /index2.html which pushes /kitten-1.jpg and /favicon.ico.
360 // Should cancel push for /kitten-1.jpg.
361 CheckLoadTimingDelegate delegate(true);
362 std::string url =
363 base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html");
364 std::unique_ptr<URLRequest> request =
365 CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
366
367 request->Start();
368 ASSERT_TRUE(request->is_pending());
369
370 // Spin the message loop until the client receives the response for the third
371 // request.
372 do {
373 base::RunLoop().RunUntilIdle();
374 } while (request->status().is_io_pending());
375 EXPECT_TRUE(request->status().is_success());
376
377 // Extract net logs on client side to verify push lookup transactions.
378 net::TestNetLogEntry::List entries;
379 ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries);
380
381 EXPECT_EQ(4u, entries.size());
382
383 std::string value;
384 int net_error;
385 std::string push_url_1 =
386 base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
387 std::string push_url_2 =
388 base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico");
389
390 EXPECT_TRUE(entries[0].GetStringValue("push_url", &value));
391 EXPECT_EQ(value, push_url_1);
shivanisha1e2e3472017-04-26 20:09:12392
shivanisha8061c4202017-06-13 23:35:52393 EXPECT_TRUE(entries[1].GetStringValue("push_url", &value));
warxae7fa092017-04-27 02:45:58394 EXPECT_EQ(value, push_url_2);
shivanisha8061c4202017-06-13 23:35:52395
396 // No net error code for this lookup transaction, the push is found.
397 EXPECT_FALSE(entries[2].GetIntegerValue("net_error", &net_error));
398
zhongyid7dd2db12017-04-14 17:01:25399 // No net error code for this lookup transaction, the push is found.
400 EXPECT_FALSE(entries[3].GetIntegerValue("net_error", &net_error));
401
402 // Verify the reset error count received on the server side.
403 EXPECT_LE(2u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED));
404}
405
406TEST_F(URLRequestQuicTest, DoNotCancelPushIfNotFoundInCache) {
407 base::RunLoop run_loop;
408 Init();
409
410 // Send a request to /index2.hmtl which pushes /kitten-1.jpg and /favicon.ico
411 // and shouldn't cancel any since neither is in cache.
412 CheckLoadTimingDelegate delegate(false);
413 std::string url =
414 base::StringPrintf("https://%s%s", kTestServerHost, "/index2.html");
415 std::unique_ptr<URLRequest> request =
416 CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
417
418 request->Start();
419 ASSERT_TRUE(request->is_pending());
420
421 // Spin the message loop until the client receives response.
422 do {
423 base::RunLoop().RunUntilIdle();
424 } while (request->status().is_io_pending());
425 EXPECT_TRUE(request->status().is_success());
426
427 // Extract net logs on client side to verify push lookup transactions.
428 net::TestNetLogEntry::List entries;
429 ExtractNetLog(NetLogEventType::SERVER_PUSH_LOOKUP_TRANSACTION, &entries);
430
431 EXPECT_EQ(4u, entries.size());
432
433 std::string value;
434 int net_error;
435 std::string push_url_1 =
436 base::StringPrintf("https://%s%s", kTestServerHost, "/kitten-1.jpg");
437 std::string push_url_2 =
438 base::StringPrintf("https://%s%s", kTestServerHost, "/favicon.ico");
439
440 EXPECT_TRUE(entries[0].GetStringValue("push_url", &value));
441 EXPECT_EQ(value, push_url_1);
442 EXPECT_TRUE(entries[1].GetIntegerValue("net_error", &net_error));
443 EXPECT_EQ(net_error, -400);
444
445 EXPECT_TRUE(entries[2].GetStringValue("push_url", &value));
446 EXPECT_EQ(value, push_url_2);
447 EXPECT_TRUE(entries[3].GetIntegerValue("net_error", &net_error));
448 EXPECT_EQ(net_error, -400);
449
450 // Verify the reset error count received on the server side.
451 EXPECT_EQ(0u, GetRstErrorCountReceivedByServer(QUIC_STREAM_CANCELLED));
452}
453
xunjieli100937eb52016-09-15 20:09:37454// Tests that if two requests use the same QUIC session, the second request
455// should not have |LoadTimingInfo::connect_timing|.
456TEST_F(URLRequestQuicTest, TestTwoRequests) {
457 base::RunLoop run_loop;
458 WaitForCompletionNetworkDelegate network_delegate(
459 run_loop.QuitClosure(), /*num_expected_requests=*/2);
460 SetNetworkDelegate(&network_delegate);
461 Init();
462 CheckLoadTimingDelegate delegate(false);
463 delegate.set_quit_on_complete(false);
464 std::string url =
465 base::StringPrintf("https://%s%s", kTestServerHost, kHelloPath);
466 std::unique_ptr<URLRequest> request =
467 CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
468
469 CheckLoadTimingDelegate delegate2(true);
470 delegate2.set_quit_on_complete(false);
471 std::unique_ptr<URLRequest> request2 =
472 CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate2);
473 request->Start();
474 request2->Start();
475 ASSERT_TRUE(request->is_pending());
476 ASSERT_TRUE(request2->is_pending());
477 run_loop.Run();
478
479 EXPECT_TRUE(request->status().is_success());
480 EXPECT_TRUE(request2->status().is_success());
481 EXPECT_EQ(kHelloBodyValue, delegate.data_received());
482 EXPECT_EQ(kHelloBodyValue, delegate2.data_received());
483}
484
Andrey Kosyakov83a6eee2017-08-14 19:20:04485TEST_F(URLRequestQuicTest, RequestHeadersCallback) {
486 Init();
487 HttpRawRequestHeaders raw_headers;
488 TestDelegate delegate;
489 TestURLRequestContext context;
490 HttpRequestHeaders extra_headers;
491 extra_headers.SetHeader("X-Foo", "bar");
492
493 std::string url =
494 base::StringPrintf("https://%s%s", kTestServerHost, kHelloPath);
495 std::unique_ptr<URLRequest> request =
496 CreateRequest(GURL(url), DEFAULT_PRIORITY, &delegate);
497
498 request->SetExtraRequestHeaders(extra_headers);
499 request->SetRequestHeadersCallback(base::Bind(
500 &HttpRawRequestHeaders::Assign, base::Unretained(&raw_headers)));
501 request->Start();
502 ASSERT_TRUE(request->is_pending());
503 do {
504 base::RunLoop().RunUntilIdle();
505 } while (!delegate.response_started_count());
506 EXPECT_FALSE(raw_headers.headers().empty());
507 std::string value;
508 EXPECT_TRUE(raw_headers.FindHeaderForTest("x-foo", &value));
509 EXPECT_EQ("bar", value);
510 EXPECT_TRUE(raw_headers.FindHeaderForTest("accept-encoding", &value));
511 EXPECT_EQ("gzip, deflate", value);
512 EXPECT_TRUE(raw_headers.FindHeaderForTest(":path", &value));
513 EXPECT_EQ("/hello.txt", value);
514 EXPECT_TRUE(raw_headers.FindHeaderForTest(":authority", &value));
515 EXPECT_EQ("test.example.com", value);
516 EXPECT_TRUE(raw_headers.request_line().empty());
517}
518
xunjieli100937eb52016-09-15 20:09:37519} // namespace net