| 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 |