OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "base/compiler_specific.h" | |
6 #include "base/files/file_util.h" | |
7 #include "base/path_service.h" | |
8 #include "base/strings/string_util.h" | |
9 #include "base/strings/stringprintf.h" | |
10 #include "base/strings/utf_string_conversions.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/base/net_log_unittest.h" | |
13 #include "net/proxy/proxy_info.h" | |
14 #include "net/proxy/proxy_resolver_v8.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 #include "url/gurl.h" | |
17 | |
18 namespace net { | |
19 namespace { | |
20 | |
21 // Javascript bindings for ProxyResolverV8, which returns mock values. | |
22 // Each time one of the bindings is called into, we push the input into a | |
23 // list, for later verification. | |
24 class MockJSBindings : public ProxyResolverV8::JSBindings { | |
25 public: | |
26 MockJSBindings() : my_ip_address_count(0), my_ip_address_ex_count(0), | |
27 should_terminate(false) {} | |
28 | |
29 void Alert(const base::string16& message) override { | |
30 VLOG(1) << "PAC-alert: " << message; // Helpful when debugging. | |
31 alerts.push_back(base::UTF16ToUTF8(message)); | |
32 } | |
33 | |
34 bool ResolveDns(const std::string& host, | |
35 ResolveDnsOperation op, | |
36 std::string* output, | |
37 bool* terminate) override { | |
38 *terminate = should_terminate; | |
39 | |
40 if (op == MY_IP_ADDRESS) { | |
41 my_ip_address_count++; | |
42 *output = my_ip_address_result; | |
43 return !my_ip_address_result.empty(); | |
44 } | |
45 | |
46 if (op == MY_IP_ADDRESS_EX) { | |
47 my_ip_address_ex_count++; | |
48 *output = my_ip_address_ex_result; | |
49 return !my_ip_address_ex_result.empty(); | |
50 } | |
51 | |
52 if (op == DNS_RESOLVE) { | |
53 dns_resolves.push_back(host); | |
54 *output = dns_resolve_result; | |
55 return !dns_resolve_result.empty(); | |
56 } | |
57 | |
58 if (op == DNS_RESOLVE_EX) { | |
59 dns_resolves_ex.push_back(host); | |
60 *output = dns_resolve_ex_result; | |
61 return !dns_resolve_ex_result.empty(); | |
62 } | |
63 | |
64 CHECK(false); | |
65 return false; | |
66 } | |
67 | |
68 void OnError(int line_number, const base::string16& message) override { | |
69 // Helpful when debugging. | |
70 VLOG(1) << "PAC-error: [" << line_number << "] " << message; | |
71 | |
72 errors.push_back(base::UTF16ToUTF8(message)); | |
73 errors_line_number.push_back(line_number); | |
74 } | |
75 | |
76 // Mock values to return. | |
77 std::string my_ip_address_result; | |
78 std::string my_ip_address_ex_result; | |
79 std::string dns_resolve_result; | |
80 std::string dns_resolve_ex_result; | |
81 | |
82 // Inputs we got called with. | |
83 std::vector<std::string> alerts; | |
84 std::vector<std::string> errors; | |
85 std::vector<int> errors_line_number; | |
86 std::vector<std::string> dns_resolves; | |
87 std::vector<std::string> dns_resolves_ex; | |
88 int my_ip_address_count; | |
89 int my_ip_address_ex_count; | |
90 | |
91 // Whether ResolveDns() should terminate script execution. | |
92 bool should_terminate; | |
93 }; | |
94 | |
95 // This is the same as ProxyResolverV8, but it uses mock bindings in place of | |
96 // the default bindings, and has a helper function to load PAC scripts from | |
97 // disk. | |
98 class ProxyResolverV8WithMockBindings : public ProxyResolverV8 { | |
99 public: | |
100 ProxyResolverV8WithMockBindings() { | |
101 set_js_bindings(&mock_js_bindings_); | |
102 } | |
103 | |
104 ~ProxyResolverV8WithMockBindings() override {} | |
105 | |
106 MockJSBindings* mock_js_bindings() { | |
107 return &mock_js_bindings_; | |
108 } | |
109 | |
110 // Initialize with the PAC script data at |filename|. | |
111 int SetPacScriptFromDisk(const char* filename) { | |
112 base::FilePath path; | |
113 PathService::Get(base::DIR_SOURCE_ROOT, &path); | |
114 path = path.AppendASCII("net"); | |
115 path = path.AppendASCII("data"); | |
116 path = path.AppendASCII("proxy_resolver_v8_unittest"); | |
117 path = path.AppendASCII(filename); | |
118 | |
119 // Try to read the file from disk. | |
120 std::string file_contents; | |
121 bool ok = base::ReadFileToString(path, &file_contents); | |
122 | |
123 // If we can't load the file from disk, something is misconfigured. | |
124 if (!ok) { | |
125 LOG(ERROR) << "Failed to read file: " << path.value(); | |
126 return ERR_UNEXPECTED; | |
127 } | |
128 | |
129 // Load the PAC script into the ProxyResolver. | |
130 return SetPacScript(ProxyResolverScriptData::FromUTF8(file_contents), | |
131 CompletionCallback()); | |
132 } | |
133 | |
134 private: | |
135 MockJSBindings mock_js_bindings_; | |
136 }; | |
137 | |
138 // Doesn't really matter what these values are for many of the tests. | |
139 const GURL kQueryUrl("http://www.google.com"); | |
140 const GURL kPacUrl; | |
141 | |
142 TEST(ProxyResolverV8Test, Direct) { | |
143 ProxyResolverV8WithMockBindings resolver; | |
144 int result = resolver.SetPacScriptFromDisk("direct.js"); | |
145 EXPECT_EQ(OK, result); | |
146 | |
147 ProxyInfo proxy_info; | |
148 CapturingBoundNetLog log; | |
149 result = resolver.GetProxyForURL( | |
150 kQueryUrl, &proxy_info, CompletionCallback(), NULL, log.bound()); | |
151 | |
152 EXPECT_EQ(OK, result); | |
153 EXPECT_TRUE(proxy_info.is_direct()); | |
154 | |
155 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); | |
156 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); | |
157 | |
158 net::CapturingNetLog::CapturedEntryList entries; | |
159 log.GetEntries(&entries); | |
160 // No bindings were called, so no log entries. | |
161 EXPECT_EQ(0u, entries.size()); | |
162 } | |
163 | |
164 TEST(ProxyResolverV8Test, ReturnEmptyString) { | |
165 ProxyResolverV8WithMockBindings resolver; | |
166 int result = resolver.SetPacScriptFromDisk("return_empty_string.js"); | |
167 EXPECT_EQ(OK, result); | |
168 | |
169 ProxyInfo proxy_info; | |
170 result = resolver.GetProxyForURL( | |
171 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
172 | |
173 EXPECT_EQ(OK, result); | |
174 EXPECT_TRUE(proxy_info.is_direct()); | |
175 | |
176 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); | |
177 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); | |
178 } | |
179 | |
180 TEST(ProxyResolverV8Test, Basic) { | |
181 ProxyResolverV8WithMockBindings resolver; | |
182 int result = resolver.SetPacScriptFromDisk("passthrough.js"); | |
183 EXPECT_EQ(OK, result); | |
184 | |
185 // The "FindProxyForURL" of this PAC script simply concatenates all of the | |
186 // arguments into a pseudo-host. The purpose of this test is to verify that | |
187 // the correct arguments are being passed to FindProxyForURL(). | |
188 { | |
189 ProxyInfo proxy_info; | |
190 result = resolver.GetProxyForURL(GURL("http://query.com/path"), &proxy_info, | |
191 CompletionCallback(), NULL, BoundNetLog()); | |
192 EXPECT_EQ(OK, result); | |
193 EXPECT_EQ("http.query.com.path.query.com:80", | |
194 proxy_info.proxy_server().ToURI()); | |
195 } | |
196 { | |
197 ProxyInfo proxy_info; | |
198 int result = resolver.GetProxyForURL( | |
199 GURL("ftp://query.com:90/path"), &proxy_info, CompletionCallback(), | |
200 NULL, BoundNetLog()); | |
201 EXPECT_EQ(OK, result); | |
202 // Note that FindProxyForURL(url, host) does not expect |host| to contain | |
203 // the port number. | |
204 EXPECT_EQ("ftp.query.com.90.path.query.com:80", | |
205 proxy_info.proxy_server().ToURI()); | |
206 | |
207 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); | |
208 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); | |
209 } | |
210 } | |
211 | |
212 TEST(ProxyResolverV8Test, BadReturnType) { | |
213 // These are the filenames of PAC scripts which each return a non-string | |
214 // types for FindProxyForURL(). They should all fail with | |
215 // ERR_PAC_SCRIPT_FAILED. | |
216 static const char* const filenames[] = { | |
217 "return_undefined.js", | |
218 "return_integer.js", | |
219 "return_function.js", | |
220 "return_object.js", | |
221 // TODO(eroman): Should 'null' be considered equivalent to "DIRECT" ? | |
222 "return_null.js" | |
223 }; | |
224 | |
225 for (size_t i = 0; i < arraysize(filenames); ++i) { | |
226 ProxyResolverV8WithMockBindings resolver; | |
227 int result = resolver.SetPacScriptFromDisk(filenames[i]); | |
228 EXPECT_EQ(OK, result); | |
229 | |
230 ProxyInfo proxy_info; | |
231 result = resolver.GetProxyForURL( | |
232 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
233 | |
234 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result); | |
235 | |
236 MockJSBindings* bindings = resolver.mock_js_bindings(); | |
237 EXPECT_EQ(0U, bindings->alerts.size()); | |
238 ASSERT_EQ(1U, bindings->errors.size()); | |
239 EXPECT_EQ("FindProxyForURL() did not return a string.", | |
240 bindings->errors[0]); | |
241 EXPECT_EQ(-1, bindings->errors_line_number[0]); | |
242 } | |
243 } | |
244 | |
245 // Try using a PAC script which defines no "FindProxyForURL" function. | |
246 TEST(ProxyResolverV8Test, NoEntryPoint) { | |
247 ProxyResolverV8WithMockBindings resolver; | |
248 int result = resolver.SetPacScriptFromDisk("no_entrypoint.js"); | |
249 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result); | |
250 | |
251 ProxyInfo proxy_info; | |
252 result = resolver.GetProxyForURL( | |
253 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
254 | |
255 EXPECT_EQ(ERR_FAILED, result); | |
256 } | |
257 | |
258 // Try loading a malformed PAC script. | |
259 TEST(ProxyResolverV8Test, ParseError) { | |
260 ProxyResolverV8WithMockBindings resolver; | |
261 int result = resolver.SetPacScriptFromDisk("missing_close_brace.js"); | |
262 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result); | |
263 | |
264 ProxyInfo proxy_info; | |
265 result = resolver.GetProxyForURL( | |
266 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
267 | |
268 EXPECT_EQ(ERR_FAILED, result); | |
269 | |
270 MockJSBindings* bindings = resolver.mock_js_bindings(); | |
271 EXPECT_EQ(0U, bindings->alerts.size()); | |
272 | |
273 // We get one error during compilation. | |
274 ASSERT_EQ(1U, bindings->errors.size()); | |
275 | |
276 EXPECT_EQ("Uncaught SyntaxError: Unexpected end of input", | |
277 bindings->errors[0]); | |
278 EXPECT_EQ(0, bindings->errors_line_number[0]); | |
279 } | |
280 | |
281 // Run a PAC script several times, which has side-effects. | |
282 TEST(ProxyResolverV8Test, SideEffects) { | |
283 ProxyResolverV8WithMockBindings resolver; | |
284 int result = resolver.SetPacScriptFromDisk("side_effects.js"); | |
285 | |
286 // The PAC script increments a counter each time we invoke it. | |
287 for (int i = 0; i < 3; ++i) { | |
288 ProxyInfo proxy_info; | |
289 result = resolver.GetProxyForURL( | |
290 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
291 EXPECT_EQ(OK, result); | |
292 EXPECT_EQ(base::StringPrintf("sideffect_%d:80", i), | |
293 proxy_info.proxy_server().ToURI()); | |
294 } | |
295 | |
296 // Reload the script -- the javascript environment should be reset, hence | |
297 // the counter starts over. | |
298 result = resolver.SetPacScriptFromDisk("side_effects.js"); | |
299 EXPECT_EQ(OK, result); | |
300 | |
301 for (int i = 0; i < 3; ++i) { | |
302 ProxyInfo proxy_info; | |
303 result = resolver.GetProxyForURL( | |
304 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
305 EXPECT_EQ(OK, result); | |
306 EXPECT_EQ(base::StringPrintf("sideffect_%d:80", i), | |
307 proxy_info.proxy_server().ToURI()); | |
308 } | |
309 } | |
310 | |
311 // Execute a PAC script which throws an exception in FindProxyForURL. | |
312 TEST(ProxyResolverV8Test, UnhandledException) { | |
313 ProxyResolverV8WithMockBindings resolver; | |
314 int result = resolver.SetPacScriptFromDisk("unhandled_exception.js"); | |
315 EXPECT_EQ(OK, result); | |
316 | |
317 ProxyInfo proxy_info; | |
318 result = resolver.GetProxyForURL( | |
319 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
320 | |
321 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result); | |
322 | |
323 MockJSBindings* bindings = resolver.mock_js_bindings(); | |
324 EXPECT_EQ(0U, bindings->alerts.size()); | |
325 ASSERT_EQ(1U, bindings->errors.size()); | |
326 EXPECT_EQ("Uncaught ReferenceError: undefined_variable is not defined", | |
327 bindings->errors[0]); | |
328 EXPECT_EQ(3, bindings->errors_line_number[0]); | |
329 } | |
330 | |
331 TEST(ProxyResolverV8Test, ReturnUnicode) { | |
332 ProxyResolverV8WithMockBindings resolver; | |
333 int result = resolver.SetPacScriptFromDisk("return_unicode.js"); | |
334 EXPECT_EQ(OK, result); | |
335 | |
336 ProxyInfo proxy_info; | |
337 result = resolver.GetProxyForURL( | |
338 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
339 | |
340 // The result from this resolve was unparseable, because it | |
341 // wasn't ASCII. | |
342 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result); | |
343 } | |
344 | |
345 // Test the PAC library functions that we expose in the JS environment. | |
346 TEST(ProxyResolverV8Test, JavascriptLibrary) { | |
347 ProxyResolverV8WithMockBindings resolver; | |
348 int result = resolver.SetPacScriptFromDisk("pac_library_unittest.js"); | |
349 EXPECT_EQ(OK, result); | |
350 | |
351 ProxyInfo proxy_info; | |
352 result = resolver.GetProxyForURL( | |
353 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
354 | |
355 // If the javascript side of this unit-test fails, it will throw a javascript | |
356 // exception. Otherwise it will return "PROXY success:80". | |
357 EXPECT_EQ(OK, result); | |
358 EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI()); | |
359 | |
360 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); | |
361 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); | |
362 } | |
363 | |
364 // Try resolving when SetPacScriptByData() has not been called. | |
365 TEST(ProxyResolverV8Test, NoSetPacScript) { | |
366 ProxyResolverV8WithMockBindings resolver; | |
367 | |
368 ProxyInfo proxy_info; | |
369 | |
370 // Resolve should fail, as we are not yet initialized with a script. | |
371 int result = resolver.GetProxyForURL( | |
372 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
373 EXPECT_EQ(ERR_FAILED, result); | |
374 | |
375 // Initialize it. | |
376 result = resolver.SetPacScriptFromDisk("direct.js"); | |
377 EXPECT_EQ(OK, result); | |
378 | |
379 // Resolve should now succeed. | |
380 result = resolver.GetProxyForURL( | |
381 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
382 EXPECT_EQ(OK, result); | |
383 | |
384 // Clear it, by initializing with an empty string. | |
385 resolver.SetPacScript( | |
386 ProxyResolverScriptData::FromUTF16(base::string16()), | |
387 CompletionCallback()); | |
388 | |
389 // Resolve should fail again now. | |
390 result = resolver.GetProxyForURL( | |
391 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
392 EXPECT_EQ(ERR_FAILED, result); | |
393 | |
394 // Load a good script once more. | |
395 result = resolver.SetPacScriptFromDisk("direct.js"); | |
396 EXPECT_EQ(OK, result); | |
397 result = resolver.GetProxyForURL( | |
398 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
399 EXPECT_EQ(OK, result); | |
400 | |
401 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); | |
402 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); | |
403 } | |
404 | |
405 // Test marshalling/un-marshalling of values between C++/V8. | |
406 TEST(ProxyResolverV8Test, V8Bindings) { | |
407 ProxyResolverV8WithMockBindings resolver; | |
408 MockJSBindings* bindings = resolver.mock_js_bindings(); | |
409 bindings->dns_resolve_result = "127.0.0.1"; | |
410 int result = resolver.SetPacScriptFromDisk("bindings.js"); | |
411 EXPECT_EQ(OK, result); | |
412 | |
413 ProxyInfo proxy_info; | |
414 result = resolver.GetProxyForURL( | |
415 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
416 | |
417 EXPECT_EQ(OK, result); | |
418 EXPECT_TRUE(proxy_info.is_direct()); | |
419 | |
420 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); | |
421 | |
422 // Alert was called 5 times. | |
423 ASSERT_EQ(5U, bindings->alerts.size()); | |
424 EXPECT_EQ("undefined", bindings->alerts[0]); | |
425 EXPECT_EQ("null", bindings->alerts[1]); | |
426 EXPECT_EQ("undefined", bindings->alerts[2]); | |
427 EXPECT_EQ("[object Object]", bindings->alerts[3]); | |
428 EXPECT_EQ("exception from calling toString()", bindings->alerts[4]); | |
429 | |
430 // DnsResolve was called 8 times, however only 2 of those were string | |
431 // parameters. (so 6 of them failed immediately). | |
432 ASSERT_EQ(2U, bindings->dns_resolves.size()); | |
433 EXPECT_EQ("", bindings->dns_resolves[0]); | |
434 EXPECT_EQ("arg1", bindings->dns_resolves[1]); | |
435 | |
436 // MyIpAddress was called two times. | |
437 EXPECT_EQ(2, bindings->my_ip_address_count); | |
438 | |
439 // MyIpAddressEx was called once. | |
440 EXPECT_EQ(1, bindings->my_ip_address_ex_count); | |
441 | |
442 // DnsResolveEx was called 2 times. | |
443 ASSERT_EQ(2U, bindings->dns_resolves_ex.size()); | |
444 EXPECT_EQ("is_resolvable", bindings->dns_resolves_ex[0]); | |
445 EXPECT_EQ("foobar", bindings->dns_resolves_ex[1]); | |
446 } | |
447 | |
448 // Test calling a binding (myIpAddress()) from the script's global scope. | |
449 // http://crbug.com/40026 | |
450 TEST(ProxyResolverV8Test, BindingCalledDuringInitialization) { | |
451 ProxyResolverV8WithMockBindings resolver; | |
452 | |
453 int result = resolver.SetPacScriptFromDisk("binding_from_global.js"); | |
454 EXPECT_EQ(OK, result); | |
455 | |
456 MockJSBindings* bindings = resolver.mock_js_bindings(); | |
457 | |
458 // myIpAddress() got called during initialization of the script. | |
459 EXPECT_EQ(1, bindings->my_ip_address_count); | |
460 | |
461 ProxyInfo proxy_info; | |
462 result = resolver.GetProxyForURL( | |
463 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
464 | |
465 EXPECT_EQ(OK, result); | |
466 EXPECT_FALSE(proxy_info.is_direct()); | |
467 EXPECT_EQ("127.0.0.1:80", proxy_info.proxy_server().ToURI()); | |
468 | |
469 // Check that no other bindings were called. | |
470 EXPECT_EQ(0U, bindings->errors.size()); | |
471 ASSERT_EQ(0U, bindings->alerts.size()); | |
472 ASSERT_EQ(0U, bindings->dns_resolves.size()); | |
473 EXPECT_EQ(0, bindings->my_ip_address_ex_count); | |
474 ASSERT_EQ(0U, bindings->dns_resolves_ex.size()); | |
475 } | |
476 | |
477 // Try loading a PAC script that ends with a comment and has no terminal | |
478 // newline. This should not cause problems with the PAC utility functions | |
479 // that we add to the script's environment. | |
480 // http://crbug.com/22864 | |
481 TEST(ProxyResolverV8Test, EndsWithCommentNoNewline) { | |
482 ProxyResolverV8WithMockBindings resolver; | |
483 int result = resolver.SetPacScriptFromDisk("ends_with_comment.js"); | |
484 EXPECT_EQ(OK, result); | |
485 | |
486 ProxyInfo proxy_info; | |
487 result = resolver.GetProxyForURL( | |
488 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
489 | |
490 EXPECT_EQ(OK, result); | |
491 EXPECT_FALSE(proxy_info.is_direct()); | |
492 EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI()); | |
493 } | |
494 | |
495 // Try loading a PAC script that ends with a statement and has no terminal | |
496 // newline. This should not cause problems with the PAC utility functions | |
497 // that we add to the script's environment. | |
498 // http://crbug.com/22864 | |
499 TEST(ProxyResolverV8Test, EndsWithStatementNoNewline) { | |
500 ProxyResolverV8WithMockBindings resolver; | |
501 int result = resolver.SetPacScriptFromDisk( | |
502 "ends_with_statement_no_semicolon.js"); | |
503 EXPECT_EQ(OK, result); | |
504 | |
505 ProxyInfo proxy_info; | |
506 result = resolver.GetProxyForURL( | |
507 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
508 | |
509 EXPECT_EQ(OK, result); | |
510 EXPECT_FALSE(proxy_info.is_direct()); | |
511 EXPECT_EQ("success:3", proxy_info.proxy_server().ToURI()); | |
512 } | |
513 | |
514 // Test the return values from myIpAddress(), myIpAddressEx(), dnsResolve(), | |
515 // dnsResolveEx(), isResolvable(), isResolvableEx(), when the the binding | |
516 // returns empty string (failure). This simulates the return values from | |
517 // those functions when the underlying DNS resolution fails. | |
518 TEST(ProxyResolverV8Test, DNSResolutionFailure) { | |
519 ProxyResolverV8WithMockBindings resolver; | |
520 int result = resolver.SetPacScriptFromDisk("dns_fail.js"); | |
521 EXPECT_EQ(OK, result); | |
522 | |
523 ProxyInfo proxy_info; | |
524 result = resolver.GetProxyForURL( | |
525 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
526 | |
527 EXPECT_EQ(OK, result); | |
528 EXPECT_FALSE(proxy_info.is_direct()); | |
529 EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI()); | |
530 } | |
531 | |
532 TEST(ProxyResolverV8Test, DNSResolutionOfInternationDomainName) { | |
533 ProxyResolverV8WithMockBindings resolver; | |
534 int result = resolver.SetPacScriptFromDisk("international_domain_names.js"); | |
535 EXPECT_EQ(OK, result); | |
536 | |
537 // Execute FindProxyForURL(). | |
538 ProxyInfo proxy_info; | |
539 result = resolver.GetProxyForURL( | |
540 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | |
541 | |
542 EXPECT_EQ(OK, result); | |
543 EXPECT_TRUE(proxy_info.is_direct()); | |
544 | |
545 // Check that the international domain name was converted to punycode | |
546 // before passing it onto the bindings layer. | |
547 MockJSBindings* bindings = resolver.mock_js_bindings(); | |
548 | |
549 ASSERT_EQ(1u, bindings->dns_resolves.size()); | |
550 EXPECT_EQ("xn--bcher-kva.ch", bindings->dns_resolves[0]); | |
551 | |
552 ASSERT_EQ(1u, bindings->dns_resolves_ex.size()); | |
553 EXPECT_EQ("xn--bcher-kva.ch", bindings->dns_resolves_ex[0]); | |
554 } | |
555 | |
556 // Test that when resolving a URL which contains an IPv6 string literal, the | |
557 // brackets are removed from the host before passing it down to the PAC script. | |
558 // If we don't do this, then subsequent calls to dnsResolveEx(host) will be | |
559 // doomed to fail since it won't correspond with a valid name. | |
560 TEST(ProxyResolverV8Test, IPv6HostnamesNotBracketed) { | |
561 ProxyResolverV8WithMockBindings resolver; | |
562 int result = resolver.SetPacScriptFromDisk("resolve_host.js"); | |
563 EXPECT_EQ(OK, result); | |
564 | |
565 ProxyInfo proxy_info; | |
566 result = resolver.GetProxyForURL( | |
567 GURL("http://[abcd::efff]:99/watsupdawg"), &proxy_info, | |
568 CompletionCallback(), NULL, BoundNetLog()); | |
569 | |
570 EXPECT_EQ(OK, result); | |
571 EXPECT_TRUE(proxy_info.is_direct()); | |
572 | |
573 // We called dnsResolveEx() exactly once, by passing through the "host" | |
574 // argument to FindProxyForURL(). The brackets should have been stripped. | |
575 ASSERT_EQ(1U, resolver.mock_js_bindings()->dns_resolves_ex.size()); | |
576 EXPECT_EQ("abcd::efff", resolver.mock_js_bindings()->dns_resolves_ex[0]); | |
577 } | |
578 | |
579 // Test that terminating a script within DnsResolve() leads to eventual | |
580 // termination of the script. Also test that repeatedly calling terminate is | |
581 // safe, and running the script again after termination still works. | |
582 TEST(ProxyResolverV8Test, Terminate) { | |
583 ProxyResolverV8WithMockBindings resolver; | |
584 int result = resolver.SetPacScriptFromDisk("terminate.js"); | |
585 EXPECT_EQ(OK, result); | |
586 | |
587 MockJSBindings* bindings = resolver.mock_js_bindings(); | |
588 | |
589 // Terminate script execution upon reaching dnsResolve(). Note that | |
590 // termination may not take effect right away (so the subsequent dnsResolve() | |
591 // and alert() may be run). | |
592 bindings->should_terminate = true; | |
593 | |
594 ProxyInfo proxy_info; | |
595 result = resolver.GetProxyForURL( | |
596 GURL("http://hang/"), &proxy_info, | |
597 CompletionCallback(), NULL, BoundNetLog()); | |
598 | |
599 // The script execution was terminated. | |
600 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result); | |
601 | |
602 EXPECT_EQ(1U, resolver.mock_js_bindings()->dns_resolves.size()); | |
603 EXPECT_GE(2U, resolver.mock_js_bindings()->dns_resolves_ex.size()); | |
604 EXPECT_GE(1U, bindings->alerts.size()); | |
605 | |
606 EXPECT_EQ(1U, bindings->errors.size()); | |
607 | |
608 // Termination shows up as an uncaught exception without any message. | |
609 EXPECT_EQ("", bindings->errors[0]); | |
610 | |
611 bindings->errors.clear(); | |
612 | |
613 // Try running the script again, this time with a different input which won't | |
614 // cause a termination+hang. | |
615 result = resolver.GetProxyForURL( | |
616 GURL("http://kittens/"), &proxy_info, | |
617 CompletionCallback(), NULL, BoundNetLog()); | |
618 | |
619 EXPECT_EQ(OK, result); | |
620 EXPECT_EQ(0u, bindings->errors.size()); | |
621 EXPECT_EQ("kittens:88", proxy_info.proxy_server().ToURI()); | |
622 } | |
623 | |
624 } // namespace | |
625 } // namespace net | |
OLD | NEW |