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