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

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

Powered by Google App Engine
This is Rietveld 408576698