Dismiss autofill popup on screen orientation change.
[chromium-blink-merge.git] / net / proxy / proxy_resolver_v8_unittest.cc
blob67e77397a8c0d1f0c6425c7bfeb4418febf6696b
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(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(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 MockJSBindings* mock_js_bindings() {
106 return &mock_js_bindings_;
109 // Initialize with the PAC script data at |filename|.
110 int SetPacScriptFromDisk(const char* filename) {
111 base::FilePath path;
112 PathService::Get(base::DIR_SOURCE_ROOT, &path);
113 path = path.AppendASCII("net");
114 path = path.AppendASCII("data");
115 path = path.AppendASCII("proxy_resolver_v8_unittest");
116 path = path.AppendASCII(filename);
118 // Try to read the file from disk.
119 std::string file_contents;
120 bool ok = file_util::ReadFileToString(path, &file_contents);
122 // If we can't load the file from disk, something is misconfigured.
123 if (!ok) {
124 LOG(ERROR) << "Failed to read file: " << path.value();
125 return ERR_UNEXPECTED;
128 // Load the PAC script into the ProxyResolver.
129 return SetPacScript(ProxyResolverScriptData::FromUTF8(file_contents),
130 CompletionCallback());
133 private:
134 MockJSBindings mock_js_bindings_;
137 // Doesn't really matter what these values are for many of the tests.
138 const GURL kQueryUrl("http://www.google.com");
139 const GURL kPacUrl;
141 TEST(ProxyResolverV8Test, Direct) {
142 ProxyResolverV8WithMockBindings resolver;
143 int result = resolver.SetPacScriptFromDisk("direct.js");
144 EXPECT_EQ(OK, result);
146 ProxyInfo proxy_info;
147 CapturingBoundNetLog log;
148 result = resolver.GetProxyForURL(
149 kQueryUrl, &proxy_info, CompletionCallback(), NULL, log.bound());
151 EXPECT_EQ(OK, result);
152 EXPECT_TRUE(proxy_info.is_direct());
154 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
155 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
157 net::CapturingNetLog::CapturedEntryList entries;
158 log.GetEntries(&entries);
159 // No bindings were called, so no log entries.
160 EXPECT_EQ(0u, entries.size());
163 TEST(ProxyResolverV8Test, ReturnEmptyString) {
164 ProxyResolverV8WithMockBindings resolver;
165 int result = resolver.SetPacScriptFromDisk("return_empty_string.js");
166 EXPECT_EQ(OK, result);
168 ProxyInfo proxy_info;
169 result = resolver.GetProxyForURL(
170 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
172 EXPECT_EQ(OK, result);
173 EXPECT_TRUE(proxy_info.is_direct());
175 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
176 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
179 TEST(ProxyResolverV8Test, Basic) {
180 ProxyResolverV8WithMockBindings resolver;
181 int result = resolver.SetPacScriptFromDisk("passthrough.js");
182 EXPECT_EQ(OK, result);
184 // The "FindProxyForURL" of this PAC script simply concatenates all of the
185 // arguments into a pseudo-host. The purpose of this test is to verify that
186 // the correct arguments are being passed to FindProxyForURL().
188 ProxyInfo proxy_info;
189 result = resolver.GetProxyForURL(GURL("http://query.com/path"), &proxy_info,
190 CompletionCallback(), NULL, BoundNetLog());
191 EXPECT_EQ(OK, result);
192 EXPECT_EQ("http.query.com.path.query.com:80",
193 proxy_info.proxy_server().ToURI());
196 ProxyInfo proxy_info;
197 int result = resolver.GetProxyForURL(
198 GURL("ftp://query.com:90/path"), &proxy_info, CompletionCallback(),
199 NULL, BoundNetLog());
200 EXPECT_EQ(OK, result);
201 // Note that FindProxyForURL(url, host) does not expect |host| to contain
202 // the port number.
203 EXPECT_EQ("ftp.query.com.90.path.query.com:80",
204 proxy_info.proxy_server().ToURI());
206 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
207 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
210 // We call this so we'll have code coverage of the function and valgrind will
211 // make sure nothing bad happens.
213 // NOTE: This is here instead of in its own test so that we'll be calling it
214 // after having done something, in hopes it won't be a no-op.
215 resolver.PurgeMemory();
218 TEST(ProxyResolverV8Test, BadReturnType) {
219 // These are the filenames of PAC scripts which each return a non-string
220 // types for FindProxyForURL(). They should all fail with
221 // ERR_PAC_SCRIPT_FAILED.
222 static const char* const filenames[] = {
223 "return_undefined.js",
224 "return_integer.js",
225 "return_function.js",
226 "return_object.js",
227 // TODO(eroman): Should 'null' be considered equivalent to "DIRECT" ?
228 "return_null.js"
231 for (size_t i = 0; i < arraysize(filenames); ++i) {
232 ProxyResolverV8WithMockBindings resolver;
233 int result = resolver.SetPacScriptFromDisk(filenames[i]);
234 EXPECT_EQ(OK, result);
236 ProxyInfo proxy_info;
237 result = resolver.GetProxyForURL(
238 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
240 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
242 MockJSBindings* bindings = resolver.mock_js_bindings();
243 EXPECT_EQ(0U, bindings->alerts.size());
244 ASSERT_EQ(1U, bindings->errors.size());
245 EXPECT_EQ("FindProxyForURL() did not return a string.",
246 bindings->errors[0]);
247 EXPECT_EQ(-1, bindings->errors_line_number[0]);
251 // Try using a PAC script which defines no "FindProxyForURL" function.
252 TEST(ProxyResolverV8Test, NoEntryPoint) {
253 ProxyResolverV8WithMockBindings resolver;
254 int result = resolver.SetPacScriptFromDisk("no_entrypoint.js");
255 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
257 ProxyInfo proxy_info;
258 result = resolver.GetProxyForURL(
259 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
261 EXPECT_EQ(ERR_FAILED, result);
264 // Try loading a malformed PAC script.
265 TEST(ProxyResolverV8Test, ParseError) {
266 ProxyResolverV8WithMockBindings resolver;
267 int result = resolver.SetPacScriptFromDisk("missing_close_brace.js");
268 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
270 ProxyInfo proxy_info;
271 result = resolver.GetProxyForURL(
272 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
274 EXPECT_EQ(ERR_FAILED, result);
276 MockJSBindings* bindings = resolver.mock_js_bindings();
277 EXPECT_EQ(0U, bindings->alerts.size());
279 // We get one error during compilation.
280 ASSERT_EQ(1U, bindings->errors.size());
282 EXPECT_EQ("Uncaught SyntaxError: Unexpected end of input",
283 bindings->errors[0]);
284 EXPECT_EQ(0, bindings->errors_line_number[0]);
287 // Run a PAC script several times, which has side-effects.
288 TEST(ProxyResolverV8Test, SideEffects) {
289 ProxyResolverV8WithMockBindings resolver;
290 int result = resolver.SetPacScriptFromDisk("side_effects.js");
292 // The PAC script increments a counter each time we invoke it.
293 for (int i = 0; i < 3; ++i) {
294 ProxyInfo proxy_info;
295 result = resolver.GetProxyForURL(
296 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
297 EXPECT_EQ(OK, result);
298 EXPECT_EQ(base::StringPrintf("sideffect_%d:80", i),
299 proxy_info.proxy_server().ToURI());
302 // Reload the script -- the javascript environment should be reset, hence
303 // the counter starts over.
304 result = resolver.SetPacScriptFromDisk("side_effects.js");
305 EXPECT_EQ(OK, result);
307 for (int i = 0; i < 3; ++i) {
308 ProxyInfo proxy_info;
309 result = resolver.GetProxyForURL(
310 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
311 EXPECT_EQ(OK, result);
312 EXPECT_EQ(base::StringPrintf("sideffect_%d:80", i),
313 proxy_info.proxy_server().ToURI());
317 // Execute a PAC script which throws an exception in FindProxyForURL.
318 TEST(ProxyResolverV8Test, UnhandledException) {
319 ProxyResolverV8WithMockBindings resolver;
320 int result = resolver.SetPacScriptFromDisk("unhandled_exception.js");
321 EXPECT_EQ(OK, result);
323 ProxyInfo proxy_info;
324 result = resolver.GetProxyForURL(
325 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
327 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
329 MockJSBindings* bindings = resolver.mock_js_bindings();
330 EXPECT_EQ(0U, bindings->alerts.size());
331 ASSERT_EQ(1U, bindings->errors.size());
332 EXPECT_EQ("Uncaught ReferenceError: undefined_variable is not defined",
333 bindings->errors[0]);
334 EXPECT_EQ(3, bindings->errors_line_number[0]);
337 TEST(ProxyResolverV8Test, ReturnUnicode) {
338 ProxyResolverV8WithMockBindings resolver;
339 int result = resolver.SetPacScriptFromDisk("return_unicode.js");
340 EXPECT_EQ(OK, result);
342 ProxyInfo proxy_info;
343 result = resolver.GetProxyForURL(
344 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
346 // The result from this resolve was unparseable, because it
347 // wasn't ASCII.
348 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
351 // Test the PAC library functions that we expose in the JS environment.
352 TEST(ProxyResolverV8Test, JavascriptLibrary) {
353 ProxyResolverV8WithMockBindings resolver;
354 int result = resolver.SetPacScriptFromDisk("pac_library_unittest.js");
355 EXPECT_EQ(OK, result);
357 ProxyInfo proxy_info;
358 result = resolver.GetProxyForURL(
359 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
361 // If the javascript side of this unit-test fails, it will throw a javascript
362 // exception. Otherwise it will return "PROXY success:80".
363 EXPECT_EQ(OK, result);
364 EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI());
366 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
367 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
370 // Try resolving when SetPacScriptByData() has not been called.
371 TEST(ProxyResolverV8Test, NoSetPacScript) {
372 ProxyResolverV8WithMockBindings resolver;
374 ProxyInfo proxy_info;
376 // Resolve should fail, as we are not yet initialized with a script.
377 int result = resolver.GetProxyForURL(
378 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
379 EXPECT_EQ(ERR_FAILED, result);
381 // Initialize it.
382 result = resolver.SetPacScriptFromDisk("direct.js");
383 EXPECT_EQ(OK, result);
385 // Resolve should now succeed.
386 result = resolver.GetProxyForURL(
387 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
388 EXPECT_EQ(OK, result);
390 // Clear it, by initializing with an empty string.
391 resolver.SetPacScript(
392 ProxyResolverScriptData::FromUTF16(base::string16()),
393 CompletionCallback());
395 // Resolve should fail again now.
396 result = resolver.GetProxyForURL(
397 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
398 EXPECT_EQ(ERR_FAILED, result);
400 // Load a good script once more.
401 result = resolver.SetPacScriptFromDisk("direct.js");
402 EXPECT_EQ(OK, result);
403 result = resolver.GetProxyForURL(
404 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
405 EXPECT_EQ(OK, result);
407 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
408 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
411 // Test marshalling/un-marshalling of values between C++/V8.
412 TEST(ProxyResolverV8Test, V8Bindings) {
413 ProxyResolverV8WithMockBindings resolver;
414 MockJSBindings* bindings = resolver.mock_js_bindings();
415 bindings->dns_resolve_result = "127.0.0.1";
416 int result = resolver.SetPacScriptFromDisk("bindings.js");
417 EXPECT_EQ(OK, result);
419 ProxyInfo proxy_info;
420 result = resolver.GetProxyForURL(
421 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
423 EXPECT_EQ(OK, result);
424 EXPECT_TRUE(proxy_info.is_direct());
426 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
428 // Alert was called 5 times.
429 ASSERT_EQ(5U, bindings->alerts.size());
430 EXPECT_EQ("undefined", bindings->alerts[0]);
431 EXPECT_EQ("null", bindings->alerts[1]);
432 EXPECT_EQ("undefined", bindings->alerts[2]);
433 EXPECT_EQ("[object Object]", bindings->alerts[3]);
434 EXPECT_EQ("exception from calling toString()", bindings->alerts[4]);
436 // DnsResolve was called 8 times, however only 2 of those were string
437 // parameters. (so 6 of them failed immediately).
438 ASSERT_EQ(2U, bindings->dns_resolves.size());
439 EXPECT_EQ("", bindings->dns_resolves[0]);
440 EXPECT_EQ("arg1", bindings->dns_resolves[1]);
442 // MyIpAddress was called two times.
443 EXPECT_EQ(2, bindings->my_ip_address_count);
445 // MyIpAddressEx was called once.
446 EXPECT_EQ(1, bindings->my_ip_address_ex_count);
448 // DnsResolveEx was called 2 times.
449 ASSERT_EQ(2U, bindings->dns_resolves_ex.size());
450 EXPECT_EQ("is_resolvable", bindings->dns_resolves_ex[0]);
451 EXPECT_EQ("foobar", bindings->dns_resolves_ex[1]);
454 // Test calling a binding (myIpAddress()) from the script's global scope.
455 // http://crbug.com/40026
456 TEST(ProxyResolverV8Test, BindingCalledDuringInitialization) {
457 ProxyResolverV8WithMockBindings resolver;
459 int result = resolver.SetPacScriptFromDisk("binding_from_global.js");
460 EXPECT_EQ(OK, result);
462 MockJSBindings* bindings = resolver.mock_js_bindings();
464 // myIpAddress() got called during initialization of the script.
465 EXPECT_EQ(1, bindings->my_ip_address_count);
467 ProxyInfo proxy_info;
468 result = resolver.GetProxyForURL(
469 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
471 EXPECT_EQ(OK, result);
472 EXPECT_FALSE(proxy_info.is_direct());
473 EXPECT_EQ("127.0.0.1:80", proxy_info.proxy_server().ToURI());
475 // Check that no other bindings were called.
476 EXPECT_EQ(0U, bindings->errors.size());
477 ASSERT_EQ(0U, bindings->alerts.size());
478 ASSERT_EQ(0U, bindings->dns_resolves.size());
479 EXPECT_EQ(0, bindings->my_ip_address_ex_count);
480 ASSERT_EQ(0U, bindings->dns_resolves_ex.size());
483 // Try loading a PAC script that ends with a comment and has no terminal
484 // newline. This should not cause problems with the PAC utility functions
485 // that we add to the script's environment.
486 // http://crbug.com/22864
487 TEST(ProxyResolverV8Test, EndsWithCommentNoNewline) {
488 ProxyResolverV8WithMockBindings resolver;
489 int result = resolver.SetPacScriptFromDisk("ends_with_comment.js");
490 EXPECT_EQ(OK, result);
492 ProxyInfo proxy_info;
493 result = resolver.GetProxyForURL(
494 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
496 EXPECT_EQ(OK, result);
497 EXPECT_FALSE(proxy_info.is_direct());
498 EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI());
501 // Try loading a PAC script that ends with a statement and has no terminal
502 // newline. This should not cause problems with the PAC utility functions
503 // that we add to the script's environment.
504 // http://crbug.com/22864
505 TEST(ProxyResolverV8Test, EndsWithStatementNoNewline) {
506 ProxyResolverV8WithMockBindings resolver;
507 int result = resolver.SetPacScriptFromDisk(
508 "ends_with_statement_no_semicolon.js");
509 EXPECT_EQ(OK, result);
511 ProxyInfo proxy_info;
512 result = resolver.GetProxyForURL(
513 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
515 EXPECT_EQ(OK, result);
516 EXPECT_FALSE(proxy_info.is_direct());
517 EXPECT_EQ("success:3", proxy_info.proxy_server().ToURI());
520 // Test the return values from myIpAddress(), myIpAddressEx(), dnsResolve(),
521 // dnsResolveEx(), isResolvable(), isResolvableEx(), when the the binding
522 // returns empty string (failure). This simulates the return values from
523 // those functions when the underlying DNS resolution fails.
524 TEST(ProxyResolverV8Test, DNSResolutionFailure) {
525 ProxyResolverV8WithMockBindings resolver;
526 int result = resolver.SetPacScriptFromDisk("dns_fail.js");
527 EXPECT_EQ(OK, result);
529 ProxyInfo proxy_info;
530 result = resolver.GetProxyForURL(
531 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
533 EXPECT_EQ(OK, result);
534 EXPECT_FALSE(proxy_info.is_direct());
535 EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI());
538 TEST(ProxyResolverV8Test, DNSResolutionOfInternationDomainName) {
539 ProxyResolverV8WithMockBindings resolver;
540 int result = resolver.SetPacScriptFromDisk("international_domain_names.js");
541 EXPECT_EQ(OK, result);
543 // Execute FindProxyForURL().
544 ProxyInfo proxy_info;
545 result = resolver.GetProxyForURL(
546 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
548 EXPECT_EQ(OK, result);
549 EXPECT_TRUE(proxy_info.is_direct());
551 // Check that the international domain name was converted to punycode
552 // before passing it onto the bindings layer.
553 MockJSBindings* bindings = resolver.mock_js_bindings();
555 ASSERT_EQ(1u, bindings->dns_resolves.size());
556 EXPECT_EQ("xn--bcher-kva.ch", bindings->dns_resolves[0]);
558 ASSERT_EQ(1u, bindings->dns_resolves_ex.size());
559 EXPECT_EQ("xn--bcher-kva.ch", bindings->dns_resolves_ex[0]);
562 // Test that when resolving a URL which contains an IPv6 string literal, the
563 // brackets are removed from the host before passing it down to the PAC script.
564 // If we don't do this, then subsequent calls to dnsResolveEx(host) will be
565 // doomed to fail since it won't correspond with a valid name.
566 TEST(ProxyResolverV8Test, IPv6HostnamesNotBracketed) {
567 ProxyResolverV8WithMockBindings resolver;
568 int result = resolver.SetPacScriptFromDisk("resolve_host.js");
569 EXPECT_EQ(OK, result);
571 ProxyInfo proxy_info;
572 result = resolver.GetProxyForURL(
573 GURL("http://[abcd::efff]:99/watsupdawg"), &proxy_info,
574 CompletionCallback(), NULL, BoundNetLog());
576 EXPECT_EQ(OK, result);
577 EXPECT_TRUE(proxy_info.is_direct());
579 // We called dnsResolveEx() exactly once, by passing through the "host"
580 // argument to FindProxyForURL(). The brackets should have been stripped.
581 ASSERT_EQ(1U, resolver.mock_js_bindings()->dns_resolves_ex.size());
582 EXPECT_EQ("abcd::efff", resolver.mock_js_bindings()->dns_resolves_ex[0]);
585 // Test that terminating a script within DnsResolve() leads to eventual
586 // termination of the script. Also test that repeatedly calling terminate is
587 // safe, and running the script again after termination still works.
588 TEST(ProxyResolverV8Test, Terminate) {
589 ProxyResolverV8WithMockBindings resolver;
590 int result = resolver.SetPacScriptFromDisk("terminate.js");
591 EXPECT_EQ(OK, result);
593 MockJSBindings* bindings = resolver.mock_js_bindings();
595 // Terminate script execution upon reaching dnsResolve(). Note that
596 // termination may not take effect right away (so the subsequent dnsResolve()
597 // and alert() may be run).
598 bindings->should_terminate = true;
600 ProxyInfo proxy_info;
601 result = resolver.GetProxyForURL(
602 GURL("http://hang/"), &proxy_info,
603 CompletionCallback(), NULL, BoundNetLog());
605 // The script execution was terminated.
606 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
608 EXPECT_EQ(1U, resolver.mock_js_bindings()->dns_resolves.size());
609 EXPECT_GE(2U, resolver.mock_js_bindings()->dns_resolves_ex.size());
610 EXPECT_GE(1U, bindings->alerts.size());
612 EXPECT_EQ(1U, bindings->errors.size());
614 // Termination shows up as an uncaught exception without any message.
615 EXPECT_EQ("", bindings->errors[0]);
617 bindings->errors.clear();
619 // Try running the script again, this time with a different input which won't
620 // cause a termination+hang.
621 result = resolver.GetProxyForURL(
622 GURL("http://kittens/"), &proxy_info,
623 CompletionCallback(), NULL, BoundNetLog());
625 EXPECT_EQ(OK, result);
626 EXPECT_EQ(0u, bindings->errors.size());
627 EXPECT_EQ("kittens:88", proxy_info.proxy_server().ToURI());
630 } // namespace
631 } // namespace net