OLD | NEW |
---|---|
(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 | |
OLD | NEW |