Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(821)

Side by Side Diff: net/proxy/proxy_resolver_v8_tracing_unittest.cc

Issue 11885009: Improve performance of proxy resolver by tracing DNS dependencies. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase off trunk Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 "net/proxy/proxy_resolver_v8_tracing.h"
6
7 #include "base/file_util.h"
8 #include "base/json/json_writer.h"
9 #include "base/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/stl_util.h"
12 #include "base/string_util.h"
13 #include "base/stringprintf.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/threading/platform_thread.h"
16 #include "base/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "googleurl/src/gurl.h"
19 #include "net/base/mock_host_resolver.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/net_log.h"
22 #include "net/base/net_log_unittest.h"
23 #include "net/base/test_completion_callback.h"
24 #include "net/proxy/proxy_info.h"
25 #include "net/proxy/proxy_resolver_error_observer.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 namespace net {
29
30 namespace {
31
32 scoped_refptr<ProxyResolverScriptData> LoadData(const char* filename) {
33 FilePath path;
34 PathService::Get(base::DIR_SOURCE_ROOT, &path);
35 path = path.AppendASCII("net");
36 path = path.AppendASCII("data");
37 path = path.AppendASCII("proxy_resolver_v8_tracing_unittest");
38 path = path.AppendASCII(filename);
39
40 // Try to read the file from disk.
41 std::string file_contents;
42 bool ok = file_util::ReadFileToString(path, &file_contents);
43
44 // If we can't load the file from disk, something is misconfigured.
45 if (!ok)
46 LOG(ERROR) << "Failed to read file: " << path.value();
47 EXPECT_TRUE(ok);
mmenke 2013/01/18 19:59:40 Can't you just do: EXPECT_TRUE(ok) << "Failed to
eroman 2013/01/23 03:26:02 Done.
48
49 // Load the PAC script into the ProxyResolver.
50 return ProxyResolverScriptData::FromUTF8(file_contents);
51 }
52
53 std::string GetParamsJson(const CapturingNetLog::CapturedEntry& entry) {
54 if (!entry.params)
55 return std::string();
56 std::string json;
57 base::JSONWriter::Write(entry.params.get(), &json);
58 return json;
59 }
60
61 void InitResolver(ProxyResolverV8Tracing* resolver, const char* filename) {
62 TestCompletionCallback callback;
63 int rv =
64 resolver->SetPacScript(LoadData(filename), callback.callback());
65 EXPECT_EQ(ERR_IO_PENDING, rv);
66 EXPECT_EQ(OK, callback.WaitForResult());
67 }
68
69 class MockErrorObserver : public ProxyResolverErrorObserver {
70 public:
71 virtual void OnPACScriptError(int line_number,
72 const string16& error) OVERRIDE {
73 output += StringPrintf("Error: line %d: %s\n", line_number,
74 UTF16ToASCII(error).c_str());
75 }
76 std::string output;
77 };
78
79 TEST(ProxyResolverV8TracingTest, Simple) {
80 CapturingNetLog log;
81 CapturingBoundNetLog req_log;
82 MockHostResolver host_resolver;
83 MockErrorObserver* error_observer = new MockErrorObserver;
84 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
85
86 InitResolver(&resolver, "simple.js");
87
88 TestCompletionCallback callback;
89 ProxyInfo proxy_info;
90
91 int rv = resolver.GetProxyForURL(
92 GURL("http://foo/"), &proxy_info, callback.callback(),
93 NULL, req_log.bound());
94
95 EXPECT_EQ(ERR_IO_PENDING, rv);
96 EXPECT_EQ(OK, callback.WaitForResult());
97
98 EXPECT_EQ("foo:99",
99 proxy_info.proxy_server().ToURI());
100
101 EXPECT_EQ(0u, host_resolver.num_resolve());
102 EXPECT_EQ(0u, host_resolver.num_resolve_from_cache());
103
104 // There were no errors.
105 EXPECT_EQ("", error_observer->output);
106
107 // Check the NetLogs -- nothing was logged.
108 EXPECT_EQ(0u, log.GetSize());
109 EXPECT_EQ(0u, req_log.GetSize());
110 }
111
112 TEST(ProxyResolverV8TracingTest, JavascriptError) {
113 CapturingNetLog log;
114 CapturingBoundNetLog req_log;
115 MockHostResolver host_resolver;
116 MockErrorObserver* error_observer = new MockErrorObserver;
117 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
118
119 InitResolver(&resolver, "error.js");
120
121 TestCompletionCallback callback;
122 ProxyInfo proxy_info;
123
124 int rv = resolver.GetProxyForURL(
125 GURL("http://foo/"), &proxy_info, callback.callback(), NULL,
126 req_log.bound());
127
128 EXPECT_EQ(ERR_IO_PENDING, rv);
129 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult());
130
131 EXPECT_EQ(0u, host_resolver.num_resolve());
132 EXPECT_EQ(0u, host_resolver.num_resolve_from_cache());
133
134 EXPECT_EQ("Error: line 3: Uncaught TypeError: Cannot call method 'split' "
135 "of null\n", error_observer->output);
136
137 // Check the NetLogs -- there was 1 javascript error, and it was output to
138 // both the global log, and per-request log.
139 CapturingNetLog::CapturedEntryList entries_list[2];
140 log.GetEntries(&entries_list[0]);
141 req_log.GetEntries(&entries_list[1]);
142
143 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
144 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
145 EXPECT_EQ(1u, entries.size());
146 EXPECT_TRUE(
147 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
148 NetLog::PHASE_NONE));
149 EXPECT_EQ("{\"line_number\":3,\"message\":\"Uncaught TypeError: Cannot "
150 "call method 'split' of null\"}", GetParamsJson(entries[0]));
151 }
152 }
153
154 TEST(ProxyResolverV8TracingTest, TooManyAlerts) {
155 CapturingNetLog log;
156 CapturingBoundNetLog req_log;
157 MockHostResolver host_resolver;
158 MockErrorObserver* error_observer = new MockErrorObserver;
159 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
160
161 InitResolver(&resolver, "too_many_alerts.js");
162
163 TestCompletionCallback callback;
164 ProxyInfo proxy_info;
165
166 int rv = resolver.GetProxyForURL(
167 GURL("http://foo/"),
168 &proxy_info,
169 callback.callback(),
170 NULL,
171 req_log.bound());
172
173 EXPECT_EQ(ERR_IO_PENDING, rv);
174 EXPECT_EQ(OK, callback.WaitForResult());
175
176 EXPECT_EQ("foo:99",
177 proxy_info.proxy_server().ToURI());
178
179 EXPECT_EQ(1u, host_resolver.num_resolve());
180 EXPECT_EQ(1u, host_resolver.num_resolve_from_cache());
181
182 // No errors.
183 EXPECT_EQ("", error_observer->output);
184
185 // Check the NetLogs -- the script generated 50 alerts, which were mirrored
186 // to both the global and per-request logs.
187 CapturingNetLog::CapturedEntryList entries_list[2];
188 log.GetEntries(&entries_list[0]);
189 req_log.GetEntries(&entries_list[1]);
190
191 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
192 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
193 EXPECT_EQ(50u, entries.size());
194 for (size_t i = 0; i < 50u; ++i) {
195 EXPECT_TRUE(
196 LogContainsEvent(entries, i, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
197 NetLog::PHASE_NONE));
198 }
199 }
200 }
201
202 // This test runs a PAC script that issues a sequence of DNS resolves. The test
203 // verifies the final result, and that the underlying DNS resolver received
204 // the correct set of queries.
205 TEST(ProxyResolverV8TracingTest, Dns) {
206 CapturingNetLog log;
207 CapturingBoundNetLog req_log;
208 MockHostResolver host_resolver;
209 MockErrorObserver* error_observer = new MockErrorObserver;
210 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
211
212 host_resolver.rules()->AddRule("host1", "166.155.144.11");
213 host_resolver.rules()->AddSimulatedFailure("host2");
214 host_resolver.rules()->AddRule("host3", "166.155.144.33");
215 host_resolver.rules()->AddRule("host4", "166.155.144.44");
216 host_resolver.rules()->AddRule("host5", "166.155.144.55");
217 host_resolver.rules()->AddRule("*", "122.133.144.155");
218
219 InitResolver(&resolver, "dns.js");
220
221 TestCompletionCallback callback;
222 ProxyInfo proxy_info;
223
224 int rv = resolver.GetProxyForURL(
225 GURL("http://foo/"),
226 &proxy_info,
227 callback.callback(),
228 NULL,
229 req_log.bound());
230
231 EXPECT_EQ(ERR_IO_PENDING, rv);
232 EXPECT_EQ(OK, callback.WaitForResult());
233
234 // The test does 11 DNS resolution, however only 5 of them are unique.
235 EXPECT_EQ(5u, host_resolver.num_resolve());
236 EXPECT_EQ(5u, host_resolver.num_resolve_from_cache());
237
238 const char* kExpectedResult =
239 "122.133.144.155-" // myIpAddress()
240 "null-" // dnsResolve('')
241 "166.155.144.11-" // dnsResolve('host1')
242 "null-" // dnsResolve('host2')
243 "166.155.144.33-" // dnsResolve('host3')
244 "122.133.144.155-" // myIpAddress()
245 "166.155.144.33-" // dnsResolve('host3')
246 "166.155.144.11-" // dnsResolve('host1')
247 "122.133.144.155-" // myIpAddress()
248 "null-" // dnsResolve('host2')
249 "166.155.144.44" // dnsResolve('host4')
250 ":99";
251
252 EXPECT_EQ(kExpectedResult, proxy_info.proxy_server().ToURI());
253
254 // No errors.
255 EXPECT_EQ("", error_observer->output);
256
257 // Check the NetLogs -- the script generated 1 alert, mirrored to both
258 // the per-request and global logs.
259 CapturingNetLog::CapturedEntryList entries_list[2];
260 log.GetEntries(&entries_list[0]);
261 req_log.GetEntries(&entries_list[1]);
262
263 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
264 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
265 EXPECT_EQ(1u, entries.size());
266 EXPECT_TRUE(
267 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
268 NetLog::PHASE_NONE));
269 EXPECT_EQ("{\"message\":\"iteration: 5\"}", GetParamsJson(entries[0]));
270 }
271 }
272
273 // This test runs a weird PAC script that was designed to defeat the DNS tracing
274 // optimization. The proxy resolver should detect the inconsistency and
275 // fall-back to synchronous mode execution.
276 TEST(ProxyResolverV8TracingTest, FallBackToSynchronous1) {
277 CapturingNetLog log;
278 CapturingBoundNetLog req_log;
279 MockHostResolver host_resolver;
280 MockErrorObserver* error_observer = new MockErrorObserver;
281 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
282
283 host_resolver.rules()->AddRule("host1", "166.155.144.11");
284 host_resolver.rules()->AddRule("crazy4", "133.199.111.4");
285 host_resolver.rules()->AddRule("*", "122.133.144.155");
286
287 InitResolver(&resolver, "global_sideffects1.js");
288
289 TestCompletionCallback callback;
290 ProxyInfo proxy_info;
291
292 int rv = resolver.GetProxyForURL(GURL("http://foo/"), &proxy_info,
293 callback.callback(), NULL, req_log.bound());
294 EXPECT_EQ(ERR_IO_PENDING, rv);
295 EXPECT_EQ(OK, callback.WaitForResult());
296
297 // The script itself only does 2 DNS resolves, however it constructs the
298 // hostname using a global counter which changes on each invocation.
299 EXPECT_EQ(3u, host_resolver.num_resolve());
300 EXPECT_EQ(2u, host_resolver.num_resolve_from_cache());
301
302 EXPECT_EQ("166.155.144.11-133.199.111.4:100",
303 proxy_info.proxy_server().ToURI());
304
305 // No errors.
306 EXPECT_EQ("", error_observer->output);
307
308 // Check the NetLogs -- the script generated 1 alert, mirrored to both
309 // the per-request and global logs.
310 CapturingNetLog::CapturedEntryList entries_list[2];
311 log.GetEntries(&entries_list[0]);
312 req_log.GetEntries(&entries_list[1]);
313
314 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
315 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
316 EXPECT_EQ(1u, entries.size());
317 EXPECT_TRUE(
318 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
319 NetLog::PHASE_NONE));
320 EXPECT_EQ("{\"message\":\"iteration: 4\"}", GetParamsJson(entries[0]));
321 }
322 }
323
324 // This test runs a weird PAC script that was designed to defeat the DNS tracing
325 // optimization. The proxy resolver should detect the inconsistency and
326 // fall-back to synchronous mode execution.
327 TEST(ProxyResolverV8TracingTest, FallBackToSynchronous2) {
328 CapturingNetLog log;
329 CapturingBoundNetLog req_log;
330 MockHostResolver host_resolver;
331 MockErrorObserver* error_observer = new MockErrorObserver;
332 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
333
334 host_resolver.rules()->AddRule("host1", "166.155.144.11");
335 host_resolver.rules()->AddRule("host2", "166.155.144.22");
336 host_resolver.rules()->AddRule("host3", "166.155.144.33");
337 host_resolver.rules()->AddRule("host4", "166.155.144.44");
338 host_resolver.rules()->AddRule("*", "122.133.144.155");
339
340 InitResolver(&resolver, "global_sideffects2.js");
341
342 TestCompletionCallback callback;
343 ProxyInfo proxy_info;
344
345 int rv = resolver.GetProxyForURL(GURL("http://foo/"), &proxy_info,
346 callback.callback(), NULL, req_log.bound());
347 EXPECT_EQ(ERR_IO_PENDING, rv);
348 EXPECT_EQ(OK, callback.WaitForResult());
349
350 EXPECT_EQ(3u, host_resolver.num_resolve());
351 EXPECT_EQ(2u, host_resolver.num_resolve_from_cache());
352
353 EXPECT_EQ("166.155.144.44:100",
354 proxy_info.proxy_server().ToURI());
355
356 // No errors.
357 EXPECT_EQ("", error_observer->output);
358
359 // Check the NetLogs -- nothing was logged.
360 EXPECT_EQ(0u, log.GetSize());
361 EXPECT_EQ(0u, req_log.GetSize());
362 }
363
364 // Tests a PAC script which does DNS resolves during initialization.
365 TEST(ProxyResolverV8TracingTest, DnsDuringInit) {
366 CapturingNetLog log;
367 CapturingBoundNetLog req_log;
368 MockHostResolver host_resolver;
369 MockErrorObserver* error_observer = new MockErrorObserver;
370 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
371
372 host_resolver.rules()->AddRule("host1", "91.13.12.1");
373 host_resolver.rules()->AddRule("host2", "91.13.12.2");
374
375 InitResolver(&resolver, "dns_during_init.js");
376
377 // Initialization did 2 dnsResolves.
378 EXPECT_EQ(2u, host_resolver.num_resolve());
379 EXPECT_EQ(0u, host_resolver.num_resolve_from_cache());
380
381 host_resolver.rules()->ClearRules();
382
383 host_resolver.rules()->AddRule("host1", "145.88.13.3");
384 host_resolver.rules()->AddRule("host2", "137.89.8.45");
385
386 TestCompletionCallback callback;
387 ProxyInfo proxy_info;
388
389 int rv = resolver.GetProxyForURL(GURL("http://foo/"), &proxy_info,
390 callback.callback(), NULL, req_log.bound());
391 EXPECT_EQ(ERR_IO_PENDING, rv);
392 EXPECT_EQ(OK, callback.WaitForResult());
393
394 // Fetched host1 and host2 again, since the ones done during initialization
395 // should not have been cached.
396 EXPECT_EQ(4u, host_resolver.num_resolve());
397
398 EXPECT_EQ("91.13.12.1-91.13.12.2-145.88.13.3-137.89.8.45:99",
399 proxy_info.proxy_server().ToURI());
400
401 // Check the NetLogs -- the script generated 2 alerts during initialization.
402 EXPECT_EQ(0u, req_log.GetSize());
403 CapturingNetLog::CapturedEntryList entries;
404 log.GetEntries(&entries);
405
406 ASSERT_EQ(2u, entries.size());
407 EXPECT_TRUE(
408 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
409 NetLog::PHASE_NONE));
410 EXPECT_TRUE(
411 LogContainsEvent(entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
412 NetLog::PHASE_NONE));
413
414 EXPECT_EQ("{\"message\":\"Watsup\"}", GetParamsJson(entries[0]));
415 EXPECT_EQ("{\"message\":\"Watsup2\"}", GetParamsJson(entries[1]));
416 }
417
418 void CrashCallback(int) {
419 // Be extra sure that if the callback ever gets invoked, the test will fail.
420 CHECK(false);
421 }
422
423 // Start some requests, cancel them all, and then destroy the resolver.
424 // Note the execution order for this test can vary. Since multiple
425 // threads are involved, the cancellation may be received a different
426 // times.
427 TEST(ProxyResolverV8TracingTest, CancelAll) {
428 MockHostResolver host_resolver;
429 MockErrorObserver* error_observer = new MockErrorObserver;
430 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
431
432 host_resolver.rules()->AddSimulatedFailure("*");
433
434 InitResolver(&resolver, "dns.js");
435
436 const size_t kNumRequests = 5;
437 ProxyInfo proxy_info[kNumRequests];
438 ProxyResolver::RequestHandle request[kNumRequests];
439
440 for (size_t i = 0; i < kNumRequests; ++i) {
441 int rv = resolver.GetProxyForURL(
442 GURL("http://foo/"), &proxy_info[i],
443 base::Bind(&CrashCallback), &request[i], BoundNetLog());
444 EXPECT_EQ(ERR_IO_PENDING, rv);
445 }
446
447 for (size_t i = 0; i < kNumRequests; ++i) {
448 resolver.CancelRequest(request[i]);
449 }
450 }
451
452 // Note the execution order for this test can vary. Since multiple
453 // threads are involved, the cancellation may be received a different
454 // times.
455 TEST(ProxyResolverV8TracingTest, CancelSome) {
456 MockHostResolver host_resolver;
457 MockErrorObserver* error_observer = new MockErrorObserver;
458 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
459
460 host_resolver.rules()->AddSimulatedFailure("*");
461
462 InitResolver(&resolver, "dns.js");
463
464 ProxyInfo proxy_info1;
465 ProxyInfo proxy_info2;
466 ProxyResolver::RequestHandle request1;
467 ProxyResolver::RequestHandle request2;
468 TestCompletionCallback callback;
469
470 int rv = resolver.GetProxyForURL(
471 GURL("http://foo/"), &proxy_info1,
472 base::Bind(&CrashCallback), &request1, BoundNetLog());
473
474 rv = resolver.GetProxyForURL(
475 GURL("http://foo/"), &proxy_info2,
476 callback.callback(), &request2, BoundNetLog());
477 EXPECT_EQ(ERR_IO_PENDING, rv);
478
479 resolver.CancelRequest(request1);
480
481 EXPECT_EQ(OK, callback.WaitForResult());
482 }
483
484 // This implementation of HostResolver allows blocking until a resolve request
485 // has been received. The resolve requests it receives will never be completed.
486 class BlockableHostResolver : public HostResolver {
487 public:
488 BlockableHostResolver()
489 : was_request_cancelled_(false) {
490 }
491
492 virtual int Resolve(const RequestInfo& info,
493 AddressList* addresses,
494 const CompletionCallback& callback,
495 RequestHandle* out_req,
496 const BoundNetLog& net_log) OVERRIDE {
497 EXPECT_FALSE(callback.is_null());
498 EXPECT_TRUE(out_req);
499 *out_req = reinterpret_cast<RequestHandle*>(1); // Magic value.
500
501 // Indicate to the caller that a request was received.
502 MessageLoop::current()->Quit();
503
504 // Return ERR_IO_PENDING as this request will NEVER be completed.
505 // Expectation is for the caller to later cancel the request.
506 return ERR_IO_PENDING;
507 }
508
509 virtual int ResolveFromCache(const RequestInfo& info,
510 AddressList* addresses,
511 const BoundNetLog& net_log) OVERRIDE {
512 return ERR_DNS_CACHE_MISS;
513 }
514
515 virtual void CancelRequest(RequestHandle req) OVERRIDE {
516 EXPECT_EQ(reinterpret_cast<RequestHandle*>(1), req);
517 was_request_cancelled_ = true;
518 }
519
520 // Waits until Resolve() has been called.
521 void WaitUntilRequestIsReceived() {
522 MessageLoop::current()->Run();
523 }
524
525 bool was_request_cancelled() const {
526 return was_request_cancelled_;
527 }
528
529 private:
530 bool was_request_cancelled_;
531 };
532
533 // This cancellation test exercises a more predictable cancellation codepath --
534 // when the request has an outstanding DNS request in flight.
535 TEST(ProxyResolverV8TracingTest, CancelWhileOutstandingNonBlockingDns) {
536 BlockableHostResolver host_resolver;
537 MockErrorObserver* error_observer = new MockErrorObserver;
538 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
539
540 InitResolver(&resolver, "dns.js");
541
542 ProxyInfo proxy_info;
543 ProxyResolver::RequestHandle request;
544
545 int rv = resolver.GetProxyForURL(
546 GURL("http://foo/"), &proxy_info,
547 base::Bind(&CrashCallback), &request, BoundNetLog());
548
549 EXPECT_EQ(ERR_IO_PENDING, rv);
550
551 host_resolver.WaitUntilRequestIsReceived();
552
553 resolver.CancelRequest(request);
554
555 EXPECT_TRUE(host_resolver.was_request_cancelled());
556
557 // After leaving this scope, the ProxyResolver is destroyed.
558 // This should not cause any problems, as the outstanding work
559 // should have been cancelled.
560 }
561
562 TEST(ProxyResolverV8TracingTest, CancelWhileOutstandingBlockingDns) {
563 BlockableHostResolver host_resolver;
564 MockErrorObserver* error_observer = new MockErrorObserver;
565
566 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
567
568 int rv =
569 resolver.SetPacScript(LoadData("dns_during_init.js"),
570 base::Bind(&CrashCallback));
571 EXPECT_EQ(ERR_IO_PENDING, rv);
572
573 host_resolver.WaitUntilRequestIsReceived();
574
575 resolver.CancelSetPacScript();
576 EXPECT_TRUE(host_resolver.was_request_cancelled());
577 }
578
579 } // namespace
580
581 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698