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

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: re-upload due to failure last time Created 7 years, 10 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
« no previous file with comments | « net/proxy/proxy_resolver_v8_tracing.cc ('k') | net/proxy/proxy_resolver_v8_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/message_loop.h"
9 #include "base/path_service.h"
10 #include "base/stl_util.h"
11 #include "base/string_util.h"
12 #include "base/stringprintf.h"
13 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/platform_thread.h"
15 #include "base/utf_string_conversions.h"
16 #include "base/values.h"
17 #include "googleurl/src/gurl.h"
18 #include "net/base/host_cache.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 class ProxyResolverV8TracingTest : public testing::Test {
33 public:
34 virtual void TearDown() OVERRIDE {
35 // Drain any pending messages, which may be left over from cancellation.
36 // This way they get reliably run as part of the current test, rather than
37 // spilling into the next test's execution.
38 MessageLoop::current()->RunUntilIdle();
39 }
40 };
41
42 scoped_refptr<ProxyResolverScriptData> LoadScriptData(const char* filename) {
43 FilePath path;
44 PathService::Get(base::DIR_SOURCE_ROOT, &path);
45 path = path.AppendASCII("net");
46 path = path.AppendASCII("data");
47 path = path.AppendASCII("proxy_resolver_v8_tracing_unittest");
48 path = path.AppendASCII(filename);
49
50 // Try to read the file from disk.
51 std::string file_contents;
52 bool ok = file_util::ReadFileToString(path, &file_contents);
53
54 // If we can't load the file from disk, something is misconfigured.
55 EXPECT_TRUE(ok) << "Failed to read file: " << path.value();
56
57 // Load the PAC script into the ProxyResolver.
58 return ProxyResolverScriptData::FromUTF8(file_contents);
59 }
60
61 void InitResolver(ProxyResolverV8Tracing* resolver, const char* filename) {
62 TestCompletionCallback callback;
63 int rv =
64 resolver->SetPacScript(LoadScriptData(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 MockErrorObserver() : event_(true, false) {}
72
73 virtual void OnPACScriptError(int line_number,
74 const string16& error) OVERRIDE {
75 {
76 base::AutoLock l(lock_);
77 output += StringPrintf("Error: line %d: %s\n", line_number,
78 UTF16ToASCII(error).c_str());
79 }
80 event_.Signal();
81 }
82
83 std::string GetOutput() {
84 base::AutoLock l(lock_);
85 return output;
86 }
87
88 void WaitForOutput() {
89 event_.Wait();
90 }
91
92 private:
93 base::Lock lock_;
94 std::string output;
95
96 base::WaitableEvent event_;
97 };
98
99 TEST_F(ProxyResolverV8TracingTest, Simple) {
100 CapturingNetLog log;
101 CapturingBoundNetLog request_log;
102 MockCachingHostResolver host_resolver;
103 MockErrorObserver* error_observer = new MockErrorObserver;
104 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
105
106 InitResolver(&resolver, "simple.js");
107
108 TestCompletionCallback callback;
109 ProxyInfo proxy_info;
110
111 int rv = resolver.GetProxyForURL(
112 GURL("http://foo/"), &proxy_info, callback.callback(),
113 NULL, request_log.bound());
114
115 EXPECT_EQ(ERR_IO_PENDING, rv);
116 EXPECT_EQ(OK, callback.WaitForResult());
117
118 EXPECT_EQ("foo:99", proxy_info.proxy_server().ToURI());
119
120 EXPECT_EQ(0u, host_resolver.num_resolve());
121
122 // There were no errors.
123 EXPECT_EQ("", error_observer->GetOutput());
124
125 // Check the NetLogs -- nothing was logged.
126 EXPECT_EQ(0u, log.GetSize());
127 EXPECT_EQ(0u, request_log.GetSize());
128 }
129
130 TEST_F(ProxyResolverV8TracingTest, JavascriptError) {
131 CapturingNetLog log;
132 CapturingBoundNetLog request_log;
133 MockCachingHostResolver host_resolver;
134 MockErrorObserver* error_observer = new MockErrorObserver;
135 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
136
137 InitResolver(&resolver, "error.js");
138
139 TestCompletionCallback callback;
140 ProxyInfo proxy_info;
141
142 int rv = resolver.GetProxyForURL(
143 GURL("http://throw-an-error/"), &proxy_info, callback.callback(), NULL,
144 request_log.bound());
145
146 EXPECT_EQ(ERR_IO_PENDING, rv);
147 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult());
148
149 EXPECT_EQ(0u, host_resolver.num_resolve());
150
151 EXPECT_EQ("Error: line 5: Uncaught TypeError: Cannot call method 'split' "
152 "of null\n", error_observer->GetOutput());
153
154 // Check the NetLogs -- there was 1 alert and 1 javascript error, and they
155 // were output to both the global log, and per-request log.
156 CapturingNetLog::CapturedEntryList entries_list[2];
157 log.GetEntries(&entries_list[0]);
158 request_log.GetEntries(&entries_list[1]);
159
160 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
161 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
162 EXPECT_EQ(2u, entries.size());
163 EXPECT_TRUE(
164 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
165 NetLog::PHASE_NONE));
166 EXPECT_TRUE(
167 LogContainsEvent(entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
168 NetLog::PHASE_NONE));
169
170 EXPECT_EQ("{\"message\":\"Prepare to DIE!\"}", entries[0].GetParamsJson());
171 EXPECT_EQ("{\"line_number\":5,\"message\":\"Uncaught TypeError: Cannot "
172 "call method 'split' of null\"}", entries[1].GetParamsJson());
173 }
174 }
175
176 TEST_F(ProxyResolverV8TracingTest, TooManyAlerts) {
177 CapturingNetLog log;
178 CapturingBoundNetLog request_log;
179 MockCachingHostResolver host_resolver;
180 MockErrorObserver* error_observer = new MockErrorObserver;
181 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
182
183 InitResolver(&resolver, "too_many_alerts.js");
184
185 TestCompletionCallback callback;
186 ProxyInfo proxy_info;
187
188 int rv = resolver.GetProxyForURL(
189 GURL("http://foo/"),
190 &proxy_info,
191 callback.callback(),
192 NULL,
193 request_log.bound());
194
195 EXPECT_EQ(ERR_IO_PENDING, rv);
196 EXPECT_EQ(OK, callback.WaitForResult());
197
198 // Iteration1 does a DNS resolve
199 // Iteration2 exceeds the alert buffer
200 // Iteration3 runs in blocking mode and completes
201 EXPECT_EQ("foo:3", proxy_info.proxy_server().ToURI());
202
203 EXPECT_EQ(1u, host_resolver.num_resolve());
204
205 // No errors.
206 EXPECT_EQ("", error_observer->GetOutput());
207
208 // Check the NetLogs -- the script generated 50 alerts, which were mirrored
209 // to both the global and per-request logs.
210 CapturingNetLog::CapturedEntryList entries_list[2];
211 log.GetEntries(&entries_list[0]);
212 request_log.GetEntries(&entries_list[1]);
213
214 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
215 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
216 EXPECT_EQ(50u, entries.size());
217 for (size_t i = 0; i < entries.size(); ++i) {
218 ASSERT_TRUE(
219 LogContainsEvent(entries, i, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
220 NetLog::PHASE_NONE));
221 }
222 }
223 }
224
225 // Verify that buffered alerts cannot grow unboundedly, even when the message is
226 // empty string.
227 TEST_F(ProxyResolverV8TracingTest, TooManyEmptyAlerts) {
228 CapturingNetLog log;
229 CapturingBoundNetLog request_log;
230 MockCachingHostResolver host_resolver;
231 MockErrorObserver* error_observer = new MockErrorObserver;
232 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
233
234 InitResolver(&resolver, "too_many_empty_alerts.js");
235
236 TestCompletionCallback callback;
237 ProxyInfo proxy_info;
238
239 int rv = resolver.GetProxyForURL(
240 GURL("http://foo/"),
241 &proxy_info,
242 callback.callback(),
243 NULL,
244 request_log.bound());
245
246 EXPECT_EQ(ERR_IO_PENDING, rv);
247 EXPECT_EQ(OK, callback.WaitForResult());
248
249 EXPECT_EQ("foo:3", proxy_info.proxy_server().ToURI());
250
251 EXPECT_EQ(1u, host_resolver.num_resolve());
252
253 // No errors.
254 EXPECT_EQ("", error_observer->GetOutput());
255
256 // Check the NetLogs -- the script generated 50 alerts, which were mirrored
257 // to both the global and per-request logs.
258 CapturingNetLog::CapturedEntryList entries_list[2];
259 log.GetEntries(&entries_list[0]);
260 request_log.GetEntries(&entries_list[1]);
261
262 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
263 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
264 EXPECT_EQ(1000u, entries.size());
265 for (size_t i = 0; i < entries.size(); ++i) {
266 ASSERT_TRUE(
267 LogContainsEvent(entries, i, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
268 NetLog::PHASE_NONE));
269 }
270 }
271 }
272
273 // This test runs a PAC script that issues a sequence of DNS resolves. The test
274 // verifies the final result, and that the underlying DNS resolver received
275 // the correct set of queries.
276 TEST_F(ProxyResolverV8TracingTest, Dns) {
277 CapturingNetLog log;
278 CapturingBoundNetLog request_log;
279 MockCachingHostResolver host_resolver;
280 MockErrorObserver* error_observer = new MockErrorObserver;
281 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
282
283 host_resolver.rules()->AddRuleForAddressFamily(
284 "host1", ADDRESS_FAMILY_IPV4, "166.155.144.44");
285 host_resolver.rules()->AddIPLiteralRule("host1", "::1,192.168.1.1", "");
286 host_resolver.rules()->AddSimulatedFailure("host2");
287 host_resolver.rules()->AddRule("host3", "166.155.144.33");
288 host_resolver.rules()->AddRule("host5", "166.155.144.55");
289 host_resolver.rules()->AddSimulatedFailure("host6");
290 host_resolver.rules()->AddRuleForAddressFamily(
291 "*", ADDRESS_FAMILY_IPV4, "122.133.144.155");
292 host_resolver.rules()->AddRule("*", "133.122.100.200");
293
294 InitResolver(&resolver, "dns.js");
295
296 TestCompletionCallback callback;
297 ProxyInfo proxy_info;
298
299 int rv = resolver.GetProxyForURL(
300 GURL("http://foo/"),
301 &proxy_info,
302 callback.callback(),
303 NULL,
304 request_log.bound());
305
306 EXPECT_EQ(ERR_IO_PENDING, rv);
307 EXPECT_EQ(OK, callback.WaitForResult());
308
309 // The test does 13 DNS resolution, however only 7 of them are unique.
310 EXPECT_EQ(7u, host_resolver.num_resolve());
311
312 const char* kExpectedResult =
313 "122.133.144.155-" // myIpAddress()
314 "null-" // dnsResolve('')
315 "__1_192.168.1.1-" // dnsResolveEx('host1')
316 "null-" // dnsResolve('host2')
317 "166.155.144.33-" // dnsResolve('host3')
318 "122.133.144.155-" // myIpAddress()
319 "166.155.144.33-" // dnsResolve('host3')
320 "__1_192.168.1.1-" // dnsResolveEx('host1')
321 "122.133.144.155-" // myIpAddress()
322 "null-" // dnsResolve('host2')
323 "-" // dnsResolveEx('host6')
324 "133.122.100.200-" // myIpAddressEx()
325 "166.155.144.44" // dnsResolve('host1')
326 ":99";
327
328 EXPECT_EQ(kExpectedResult, proxy_info.proxy_server().ToURI());
329
330 // No errors.
331 EXPECT_EQ("", error_observer->GetOutput());
332
333 // Check the NetLogs -- the script generated 1 alert, mirrored to both
334 // the per-request and global logs.
335 CapturingNetLog::CapturedEntryList entries_list[2];
336 log.GetEntries(&entries_list[0]);
337 request_log.GetEntries(&entries_list[1]);
338
339 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
340 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
341 EXPECT_EQ(1u, entries.size());
342 EXPECT_TRUE(
343 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
344 NetLog::PHASE_NONE));
345 EXPECT_EQ("{\"message\":\"iteration: 7\"}", entries[0].GetParamsJson());
346 }
347 }
348
349 // This test runs a PAC script that does "myIpAddress()" followed by
350 // "dnsResolve()". This requires 2 restarts. However once the HostResolver's
351 // cache is warmed, subsequent calls should take 0 restarts.
352 TEST_F(ProxyResolverV8TracingTest, DnsChecksCache) {
353 CapturingNetLog log;
354 CapturingBoundNetLog request_log;
355 MockCachingHostResolver host_resolver;
356 MockErrorObserver* error_observer = new MockErrorObserver;
357 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
358
359 host_resolver.rules()->AddRule("foopy", "166.155.144.11");
360 host_resolver.rules()->AddRule("*", "122.133.144.155");
361
362 InitResolver(&resolver, "simple_dns.js");
363
364 TestCompletionCallback callback1;
365 TestCompletionCallback callback2;
366 ProxyInfo proxy_info;
367
368 int rv = resolver.GetProxyForURL(
369 GURL("http://foopy/req1"),
370 &proxy_info,
371 callback1.callback(),
372 NULL,
373 request_log.bound());
374
375 EXPECT_EQ(ERR_IO_PENDING, rv);
376 EXPECT_EQ(OK, callback1.WaitForResult());
377
378 // The test does 2 DNS resolutions.
379 EXPECT_EQ(2u, host_resolver.num_resolve());
380
381 // The first request took 2 restarts, hence on g_iteration=3.
382 EXPECT_EQ("166.155.144.11:3", proxy_info.proxy_server().ToURI());
383
384 rv = resolver.GetProxyForURL(
385 GURL("http://foopy/req2"),
386 &proxy_info,
387 callback2.callback(),
388 NULL,
389 request_log.bound());
390
391 EXPECT_EQ(ERR_IO_PENDING, rv);
392 EXPECT_EQ(OK, callback2.WaitForResult());
393
394 EXPECT_EQ(4u, host_resolver.num_resolve());
395
396 // This time no restarts were required, so g_iteration incremented by 1.
397 EXPECT_EQ("166.155.144.11:4", proxy_info.proxy_server().ToURI());
398
399 // No errors.
400 EXPECT_EQ("", error_observer->GetOutput());
401
402 EXPECT_EQ(0u, log.GetSize());
403 EXPECT_EQ(0u, request_log.GetSize());
404 }
405
406 // This test runs a weird PAC script that was designed to defeat the DNS tracing
407 // optimization. The proxy resolver should detect the inconsistency and
408 // fall-back to synchronous mode execution.
409 TEST_F(ProxyResolverV8TracingTest, FallBackToSynchronous1) {
410 CapturingNetLog log;
411 CapturingBoundNetLog request_log;
412 MockCachingHostResolver host_resolver;
413 MockErrorObserver* error_observer = new MockErrorObserver;
414 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
415
416 host_resolver.rules()->AddRule("host1", "166.155.144.11");
417 host_resolver.rules()->AddRule("crazy4", "133.199.111.4");
418 host_resolver.rules()->AddRule("*", "122.133.144.155");
419
420 InitResolver(&resolver, "global_sideffects1.js");
421
422 TestCompletionCallback callback;
423 ProxyInfo proxy_info;
424
425 int rv = resolver.GetProxyForURL(
426 GURL("http://foo/"), &proxy_info, callback.callback(), NULL,
427 request_log.bound());
428 EXPECT_EQ(ERR_IO_PENDING, rv);
429 EXPECT_EQ(OK, callback.WaitForResult());
430
431 // The script itself only does 2 DNS resolves per execution, however it
432 // constructs the hostname using a global counter which changes on each
433 // invocation.
434 EXPECT_EQ(3u, host_resolver.num_resolve());
435
436 EXPECT_EQ("166.155.144.11-133.199.111.4:100",
437 proxy_info.proxy_server().ToURI());
438
439 // No errors.
440 EXPECT_EQ("", error_observer->GetOutput());
441
442 // Check the NetLogs -- the script generated 1 alert, mirrored to both
443 // the per-request and global logs.
444 CapturingNetLog::CapturedEntryList entries_list[2];
445 log.GetEntries(&entries_list[0]);
446 request_log.GetEntries(&entries_list[1]);
447
448 for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
449 const CapturingNetLog::CapturedEntryList& entries = entries_list[list_i];
450 EXPECT_EQ(1u, entries.size());
451 EXPECT_TRUE(
452 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
453 NetLog::PHASE_NONE));
454 EXPECT_EQ("{\"message\":\"iteration: 4\"}", entries[0].GetParamsJson());
455 }
456 }
457
458 // This test runs a weird PAC script that was designed to defeat the DNS tracing
459 // optimization. The proxy resolver should detect the inconsistency and
460 // fall-back to synchronous mode execution.
461 TEST_F(ProxyResolverV8TracingTest, FallBackToSynchronous2) {
462 CapturingNetLog log;
463 CapturingBoundNetLog request_log;
464 MockCachingHostResolver host_resolver;
465 MockErrorObserver* error_observer = new MockErrorObserver;
466 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
467
468 host_resolver.rules()->AddRule("host1", "166.155.144.11");
469 host_resolver.rules()->AddRule("host2", "166.155.144.22");
470 host_resolver.rules()->AddRule("host3", "166.155.144.33");
471 host_resolver.rules()->AddRule("host4", "166.155.144.44");
472 host_resolver.rules()->AddRule("*", "122.133.144.155");
473
474 InitResolver(&resolver, "global_sideffects2.js");
475
476 TestCompletionCallback callback;
477 ProxyInfo proxy_info;
478
479 int rv = resolver.GetProxyForURL(
480 GURL("http://foo/"), &proxy_info, callback.callback(), NULL,
481 request_log.bound());
482 EXPECT_EQ(ERR_IO_PENDING, rv);
483 EXPECT_EQ(OK, callback.WaitForResult());
484
485 EXPECT_EQ(3u, host_resolver.num_resolve());
486
487 EXPECT_EQ("166.155.144.44:100", proxy_info.proxy_server().ToURI());
488
489 // No errors.
490 EXPECT_EQ("", error_observer->GetOutput());
491
492 // Check the NetLogs -- nothing was logged.
493 EXPECT_EQ(0u, log.GetSize());
494 EXPECT_EQ(0u, request_log.GetSize());
495 }
496
497 // This test runs a weird PAC script that yields a never ending sequence
498 // of DNS resolves when restarting. Running it will hit the maximum
499 // DNS resolves per request limit (20) after which every DNS resolve will
500 // fail.
501 TEST_F(ProxyResolverV8TracingTest, InfiniteDNSSequence) {
502 CapturingNetLog log;
503 CapturingBoundNetLog request_log;
504 MockCachingHostResolver host_resolver;
505 MockErrorObserver* error_observer = new MockErrorObserver;
506 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
507
508 host_resolver.rules()->AddRule("host*", "166.155.144.11");
509 host_resolver.rules()->AddRule("*", "122.133.144.155");
510
511 InitResolver(&resolver, "global_sideffects3.js");
512
513 TestCompletionCallback callback;
514 ProxyInfo proxy_info;
515
516 int rv = resolver.GetProxyForURL(
517 GURL("http://foo/"), &proxy_info, callback.callback(), NULL,
518 request_log.bound());
519 EXPECT_EQ(ERR_IO_PENDING, rv);
520 EXPECT_EQ(OK, callback.WaitForResult());
521
522 EXPECT_EQ(20u, host_resolver.num_resolve());
523
524 EXPECT_EQ(
525 "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
526 "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
527 "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
528 "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
529 "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
530 "null:21", proxy_info.proxy_server().ToURI());
531
532 // No errors.
533 EXPECT_EQ("", error_observer->GetOutput());
534
535 // Check the NetLogs -- 1 alert was logged.
536 EXPECT_EQ(1u, log.GetSize());
537 EXPECT_EQ(1u, request_log.GetSize());
538 }
539
540 // This test runs a weird PAC script that yields a never ending sequence
541 // of DNS resolves when restarting. Running it will hit the maximum
542 // DNS resolves per request limit (20) after which every DNS resolve will
543 // fail.
544 TEST_F(ProxyResolverV8TracingTest, InfiniteDNSSequence2) {
545 CapturingNetLog log;
546 CapturingBoundNetLog request_log;
547 MockCachingHostResolver host_resolver;
548 MockErrorObserver* error_observer = new MockErrorObserver;
549 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
550
551 host_resolver.rules()->AddRule("host*", "166.155.144.11");
552 host_resolver.rules()->AddRule("*", "122.133.144.155");
553
554 InitResolver(&resolver, "global_sideffects4.js");
555
556 TestCompletionCallback callback;
557 ProxyInfo proxy_info;
558
559 int rv = resolver.GetProxyForURL(
560 GURL("http://foo/"), &proxy_info, callback.callback(), NULL,
561 request_log.bound());
562 EXPECT_EQ(ERR_IO_PENDING, rv);
563 EXPECT_EQ(OK, callback.WaitForResult());
564
565 EXPECT_EQ(20u, host_resolver.num_resolve());
566
567 EXPECT_EQ("null21:34", proxy_info.proxy_server().ToURI());
568
569 // No errors.
570 EXPECT_EQ("", error_observer->GetOutput());
571
572 // Check the NetLogs -- 1 alert was logged.
573 EXPECT_EQ(1u, log.GetSize());
574 EXPECT_EQ(1u, request_log.GetSize());
575 }
576
577 // Tests a PAC script which does DNS resolves during initialization.
578 TEST_F(ProxyResolverV8TracingTest, DnsDuringInit) {
579 CapturingNetLog log;
580 CapturingBoundNetLog request_log;
581 MockCachingHostResolver host_resolver;
582 MockErrorObserver* error_observer = new MockErrorObserver;
583 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
584
585 host_resolver.rules()->AddRule("host1", "91.13.12.1");
586 host_resolver.rules()->AddRule("host2", "91.13.12.2");
587
588 InitResolver(&resolver, "dns_during_init.js");
589
590 // Initialization did 2 dnsResolves.
591 EXPECT_EQ(2u, host_resolver.num_resolve());
592
593 host_resolver.rules()->ClearRules();
594 host_resolver.GetHostCache()->clear();
595
596 host_resolver.rules()->AddRule("host1", "145.88.13.3");
597 host_resolver.rules()->AddRule("host2", "137.89.8.45");
598
599 TestCompletionCallback callback;
600 ProxyInfo proxy_info;
601
602 int rv = resolver.GetProxyForURL(
603 GURL("http://foo/"), &proxy_info, callback.callback(), NULL,
604 request_log.bound());
605 EXPECT_EQ(ERR_IO_PENDING, rv);
606 EXPECT_EQ(OK, callback.WaitForResult());
607
608 // Fetched host1 and host2 again, since the ones done during initialization
609 // should not have been cached.
610 EXPECT_EQ(4u, host_resolver.num_resolve());
611
612 EXPECT_EQ("91.13.12.1-91.13.12.2-145.88.13.3-137.89.8.45:99",
613 proxy_info.proxy_server().ToURI());
614
615 // Check the NetLogs -- the script generated 2 alerts during initialization.
616 EXPECT_EQ(0u, request_log.GetSize());
617 CapturingNetLog::CapturedEntryList entries;
618 log.GetEntries(&entries);
619
620 ASSERT_EQ(2u, entries.size());
621 EXPECT_TRUE(
622 LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
623 NetLog::PHASE_NONE));
624 EXPECT_TRUE(
625 LogContainsEvent(entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
626 NetLog::PHASE_NONE));
627
628 EXPECT_EQ("{\"message\":\"Watsup\"}", entries[0].GetParamsJson());
629 EXPECT_EQ("{\"message\":\"Watsup2\"}", entries[1].GetParamsJson());
630 }
631
632 void CrashCallback(int) {
633 // Be extra sure that if the callback ever gets invoked, the test will fail.
634 CHECK(false);
635 }
636
637 // Start some requests, cancel them all, and then destroy the resolver.
638 // Note the execution order for this test can vary. Since multiple
639 // threads are involved, the cancellation may be received a different
640 // times.
641 TEST_F(ProxyResolverV8TracingTest, CancelAll) {
642 MockCachingHostResolver host_resolver;
643 MockErrorObserver* error_observer = new MockErrorObserver;
644 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
645
646 host_resolver.rules()->AddSimulatedFailure("*");
647
648 InitResolver(&resolver, "dns.js");
649
650 const size_t kNumRequests = 5;
651 ProxyInfo proxy_info[kNumRequests];
652 ProxyResolver::RequestHandle request[kNumRequests];
653
654 for (size_t i = 0; i < kNumRequests; ++i) {
655 int rv = resolver.GetProxyForURL(
656 GURL("http://foo/"), &proxy_info[i],
657 base::Bind(&CrashCallback), &request[i], BoundNetLog());
658 EXPECT_EQ(ERR_IO_PENDING, rv);
659 }
660
661 for (size_t i = 0; i < kNumRequests; ++i) {
662 resolver.CancelRequest(request[i]);
663 }
664 }
665
666 // Note the execution order for this test can vary. Since multiple
667 // threads are involved, the cancellation may be received a different
668 // times.
669 TEST_F(ProxyResolverV8TracingTest, CancelSome) {
670 MockCachingHostResolver host_resolver;
671 MockErrorObserver* error_observer = new MockErrorObserver;
672 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
673
674 host_resolver.rules()->AddSimulatedFailure("*");
675
676 InitResolver(&resolver, "dns.js");
677
678 ProxyInfo proxy_info1;
679 ProxyInfo proxy_info2;
680 ProxyResolver::RequestHandle request1;
681 ProxyResolver::RequestHandle request2;
682 TestCompletionCallback callback;
683
684 int rv = resolver.GetProxyForURL(
685 GURL("http://foo/"), &proxy_info1,
686 base::Bind(&CrashCallback), &request1, BoundNetLog());
687 EXPECT_EQ(ERR_IO_PENDING, rv);
688
689 rv = resolver.GetProxyForURL(
690 GURL("http://foo/"), &proxy_info2,
691 callback.callback(), &request2, BoundNetLog());
692 EXPECT_EQ(ERR_IO_PENDING, rv);
693
694 resolver.CancelRequest(request1);
695
696 EXPECT_EQ(OK, callback.WaitForResult());
697 }
698
699 // Cancel a request after it has finished running on the worker thread, and has
700 // posted a task the completion task back to origin thread.
701 TEST_F(ProxyResolverV8TracingTest, CancelWhilePendingCompletionTask) {
702 MockCachingHostResolver host_resolver;
703 MockErrorObserver* error_observer = new MockErrorObserver;
704 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
705
706 host_resolver.rules()->AddSimulatedFailure("*");
707
708 InitResolver(&resolver, "error.js");
709
710 ProxyInfo proxy_info1;
711 ProxyInfo proxy_info2;
712 ProxyInfo proxy_info3;
713 ProxyResolver::RequestHandle request1;
714 ProxyResolver::RequestHandle request2;
715 ProxyResolver::RequestHandle request3;
716 TestCompletionCallback callback;
717
718 int rv = resolver.GetProxyForURL(
719 GURL("http://foo/"), &proxy_info1,
720 base::Bind(&CrashCallback), &request1, BoundNetLog());
721 EXPECT_EQ(ERR_IO_PENDING, rv);
722
723 rv = resolver.GetProxyForURL(
724 GURL("http://throw-an-error/"), &proxy_info2,
725 callback.callback(), &request2, BoundNetLog());
726 EXPECT_EQ(ERR_IO_PENDING, rv);
727
728 // Wait until the first request has finished running on the worker thread.
729 // (The second request will output an error).
730 error_observer->WaitForOutput();
731
732 // Cancel the first request, while it has a pending completion task on
733 // the origin thread.
734 resolver.CancelRequest(request1);
735
736 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult());
737
738 // Start another request, to make sure it is able to complete.
739 rv = resolver.GetProxyForURL(
740 GURL("http://i-have-no-idea-what-im-doing/"), &proxy_info3,
741 callback.callback(), &request3, BoundNetLog());
742 EXPECT_EQ(ERR_IO_PENDING, rv);
743
744 EXPECT_EQ(OK, callback.WaitForResult());
745
746 EXPECT_EQ("i-approve-this-message:42",
747 proxy_info3.proxy_server().ToURI());
748 }
749
750 // This implementation of HostResolver allows blocking until a resolve request
751 // has been received. The resolve requests it receives will never be completed.
752 class BlockableHostResolver : public HostResolver {
753 public:
754 BlockableHostResolver()
755 : num_cancelled_requests_(0), waiting_for_resolve_(false) {}
756
757 virtual int Resolve(const RequestInfo& info,
758 AddressList* addresses,
759 const CompletionCallback& callback,
760 RequestHandle* out_req,
761 const BoundNetLog& net_log) OVERRIDE {
762 EXPECT_FALSE(callback.is_null());
763 EXPECT_TRUE(out_req);
764 *out_req = reinterpret_cast<RequestHandle*>(1); // Magic value.
765
766 if (!action_.is_null())
767 action_.Run();
768
769 // Indicate to the caller that a request was received.
770 EXPECT_TRUE(waiting_for_resolve_);
771 MessageLoop::current()->Quit();
772
773 // Return ERR_IO_PENDING as this request will NEVER be completed.
774 // Expectation is for the caller to later cancel the request.
775 return ERR_IO_PENDING;
776 }
777
778 virtual int ResolveFromCache(const RequestInfo& info,
779 AddressList* addresses,
780 const BoundNetLog& net_log) OVERRIDE {
781 NOTREACHED();
782 return ERR_DNS_CACHE_MISS;
783 }
784
785 virtual void CancelRequest(RequestHandle req) OVERRIDE {
786 EXPECT_EQ(reinterpret_cast<RequestHandle*>(1), req);
787 num_cancelled_requests_++;
788 }
789
790 void SetAction(const base::Callback<void(void)>& action) {
791 action_ = action;
792 }
793
794 // Waits until Resolve() has been called.
795 void WaitUntilRequestIsReceived() {
796 waiting_for_resolve_ = true;
797 MessageLoop::current()->Run();
798 DCHECK(waiting_for_resolve_);
799 waiting_for_resolve_ = false;
800 }
801
802 int num_cancelled_requests() const {
803 return num_cancelled_requests_;
804 }
805
806 private:
807 int num_cancelled_requests_;
808 bool waiting_for_resolve_;
809 base::Callback<void(void)> action_;
810 };
811
812 // This cancellation test exercises a more predictable cancellation codepath --
813 // when the request has an outstanding DNS request in flight.
814 TEST_F(ProxyResolverV8TracingTest, CancelWhileOutstandingNonBlockingDns) {
815 BlockableHostResolver host_resolver;
816 MockErrorObserver* error_observer = new MockErrorObserver;
817 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
818
819 InitResolver(&resolver, "dns.js");
820
821 ProxyInfo proxy_info1;
822 ProxyInfo proxy_info2;
823 ProxyResolver::RequestHandle request1;
824 ProxyResolver::RequestHandle request2;
825
826 int rv = resolver.GetProxyForURL(
827 GURL("http://foo/req1"), &proxy_info1,
828 base::Bind(&CrashCallback), &request1, BoundNetLog());
829
830 EXPECT_EQ(ERR_IO_PENDING, rv);
831
832 host_resolver.WaitUntilRequestIsReceived();
833
834 rv = resolver.GetProxyForURL(
835 GURL("http://foo/req2"), &proxy_info2,
836 base::Bind(&CrashCallback), &request2, BoundNetLog());
837
838 EXPECT_EQ(ERR_IO_PENDING, rv);
839
840 host_resolver.WaitUntilRequestIsReceived();
841
842 resolver.CancelRequest(request1);
843 resolver.CancelRequest(request2);
844
845 EXPECT_EQ(2, host_resolver.num_cancelled_requests());
846
847 // After leaving this scope, the ProxyResolver is destroyed.
848 // This should not cause any problems, as the outstanding work
849 // should have been cancelled.
850 }
851
852 // In non-blocking mode, the worker thread actually does block for
853 // a short time to see if the result is in the DNS cache. Test
854 // cancellation while the worker thread is waiting on this event.
855 TEST_F(ProxyResolverV8TracingTest, CancelWhileBlockedInNonBlockingDns) {
856 BlockableHostResolver host_resolver;
857 MockErrorObserver* error_observer = new MockErrorObserver;
858 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
859
860 InitResolver(&resolver, "dns.js");
861
862 ProxyInfo proxy_info;
863 ProxyResolver::RequestHandle request;
864
865 int rv = resolver.GetProxyForURL(
866 GURL("http://foo/"), &proxy_info,
867 base::Bind(&CrashCallback), &request, BoundNetLog());
868
869 EXPECT_EQ(ERR_IO_PENDING, rv);
870
871 host_resolver.SetAction(base::Bind(&ProxyResolverV8Tracing::CancelRequest,
872 base::Unretained(&resolver), request));
873
874 host_resolver.WaitUntilRequestIsReceived();
875
876 // At this point the host resolver ran Resolve(), and should have cancelled
877 // the request.
878
879 EXPECT_EQ(1, host_resolver.num_cancelled_requests());
880 }
881
882 // Cancel the request while there is a pending DNS request, however before
883 // the request is sent to the host resolver.
884 TEST_F(ProxyResolverV8TracingTest, CancelWhileBlockedInNonBlockingDns2) {
885 MockCachingHostResolver host_resolver;
886 MockErrorObserver* error_observer = new MockErrorObserver;
887 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
888
889 InitResolver(&resolver, "dns.js");
890
891 ProxyInfo proxy_info;
892 ProxyResolver::RequestHandle request;
893
894 int rv = resolver.GetProxyForURL(
895 GURL("http://foo/"), &proxy_info,
896 base::Bind(&CrashCallback), &request, BoundNetLog());
897
898 EXPECT_EQ(ERR_IO_PENDING, rv);
899
900 // Wait a bit, so the DNS task has hopefully been posted. The test will
901 // work whatever the delay is here, but it is most useful if the delay
902 // is large enough to allow a task to be posted back.
903 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
904 resolver.CancelRequest(request);
905
906 EXPECT_EQ(0u, host_resolver.num_resolve());
907 }
908
909 TEST_F(ProxyResolverV8TracingTest, CancelSetPacWhileOutstandingBlockingDns) {
910 BlockableHostResolver host_resolver;
911 MockErrorObserver* error_observer = new MockErrorObserver;
912
913 ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
914
915 int rv =
916 resolver.SetPacScript(LoadScriptData("dns_during_init.js"),
917 base::Bind(&CrashCallback));
918 EXPECT_EQ(ERR_IO_PENDING, rv);
919
920 host_resolver.WaitUntilRequestIsReceived();
921
922 resolver.CancelSetPacScript();
923 EXPECT_EQ(1, host_resolver.num_cancelled_requests());
924 }
925
926 } // namespace
927
928 } // namespace net
OLDNEW
« no previous file with comments | « net/proxy/proxy_resolver_v8_tracing.cc ('k') | net/proxy/proxy_resolver_v8_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698