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