Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(322)

Unified Diff: net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc

Issue 1145153004: Split ProxyResolverV8Tracing into an implementation and a wrapper. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc
diff --git a/net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc b/net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f9fdca69151ccdd7e669581e1ac9c0a2ab11a557
--- /dev/null
+++ b/net/proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc
@@ -0,0 +1,1146 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
eroman 2015/06/26 15:37:25 Any way to get this file to show up with better di
Sam McNally 2015/06/29 01:33:51 Done.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/proxy/proxy_resolver_v8_tracing_wrapper.h"
+
+#include <string>
+
+#include "base/files/file_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/platform_thread.h"
+#include "base/values.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/dns/host_cache.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/log/net_log.h"
+#include "net/log/test_net_log.h"
+#include "net/log/test_net_log_entry.h"
+#include "net/log/test_net_log_util.h"
+#include "net/proxy/proxy_info.h"
+#include "net/proxy/proxy_resolver_error_observer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace net {
+
+namespace {
+
+class ProxyResolverV8TracingWrapperTest : public testing::Test {
+ public:
+ void TearDown() override {
+ // Drain any pending messages, which may be left over from cancellation.
+ // This way they get reliably run as part of the current test, rather than
+ // spilling into the next test's execution.
+ base::MessageLoop::current()->RunUntilIdle();
+ }
+};
+
+scoped_refptr<ProxyResolverScriptData> LoadScriptData(const char* filename) {
+ base::FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.AppendASCII("net");
+ path = path.AppendASCII("data");
+ path = path.AppendASCII("proxy_resolver_v8_tracing_unittest");
+ path = path.AppendASCII(filename);
+
+ // Try to read the file from disk.
+ std::string file_contents;
+ bool ok = base::ReadFileToString(path, &file_contents);
+
+ // If we can't load the file from disk, something is misconfigured.
+ EXPECT_TRUE(ok) << "Failed to read file: " << path.value();
+
+ // Load the PAC script into the ProxyResolver.
+ return ProxyResolverScriptData::FromUTF8(file_contents);
+}
+
+scoped_ptr<ProxyResolverErrorObserver> ReturnErrorObserver(
+ scoped_ptr<ProxyResolverErrorObserver> error_observer) {
+ return error_observer;
+}
+
+scoped_ptr<ProxyResolver> CreateResolver(
+ NetLog* net_log,
+ HostResolver* host_resolver,
+ scoped_ptr<ProxyResolverErrorObserver> error_observer,
+ const char* filename) {
+ scoped_ptr<ProxyResolver> resolver;
+ ProxyResolverFactoryV8TracingWrapper factory(
+ host_resolver, net_log,
+ base::Bind(&ReturnErrorObserver, base::Passed(&error_observer)));
+ TestCompletionCallback callback;
+ scoped_ptr<ProxyResolverFactory::Request> request;
+ int rv = factory.CreateProxyResolver(LoadScriptData(filename), &resolver,
+ callback.callback(), &request);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+ EXPECT_TRUE(resolver);
+ return resolver.Pass();
+}
+
+class MockErrorObserver : public ProxyResolverErrorObserver {
+ public:
+ MockErrorObserver() : event_(true, false) {}
+
+ void OnPACScriptError(int line_number, const base::string16& error) override {
+ {
+ base::AutoLock l(lock_);
+ output += base::StringPrintf("Error: line %d: %s\n", line_number,
+ base::UTF16ToASCII(error).c_str());
+ }
+ event_.Signal();
+ }
+
+ std::string GetOutput() {
+ base::AutoLock l(lock_);
+ return output;
+ }
+
+ void WaitForOutput() { event_.Wait(); }
+
+ private:
+ base::Lock lock_;
+ std::string output;
+
+ base::WaitableEvent event_;
+};
+
+TEST_F(ProxyResolverV8TracingWrapperTest, Simple) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ &log, &host_resolver, make_scoped_ptr(error_observer), "simple.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ EXPECT_EQ("foo:99", proxy_info.proxy_server().ToURI());
+
+ EXPECT_EQ(0u, host_resolver.num_resolve());
+
+ // There were no errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ // Check the NetLogs -- nothing was logged.
+ EXPECT_EQ(0u, log.GetSize());
+ EXPECT_EQ(0u, request_log.GetSize());
+}
+
+TEST_F(ProxyResolverV8TracingWrapperTest, JavascriptError) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ &log, &host_resolver, make_scoped_ptr(error_observer), "error.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://throw-an-error/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult());
+
+ EXPECT_EQ(0u, host_resolver.num_resolve());
+
+ EXPECT_EQ(
+ "Error: line 5: Uncaught TypeError: Cannot read property 'split' "
+ "of null\n",
+ error_observer->GetOutput());
+
+ // Check the NetLogs -- there was 1 alert and 1 javascript error, and they
+ // were output to both the global log, and per-request log.
+ TestNetLogEntry::List entries_list[2];
+ log.GetEntries(&entries_list[0]);
+ request_log.GetEntries(&entries_list[1]);
+
+ for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
+ const TestNetLogEntry::List& entries = entries_list[list_i];
+ EXPECT_EQ(2u, entries.size());
+ EXPECT_TRUE(LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
+ NetLog::PHASE_NONE));
+ EXPECT_TRUE(LogContainsEvent(entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
+ NetLog::PHASE_NONE));
+
+ EXPECT_EQ("{\"message\":\"Prepare to DIE!\"}", entries[0].GetParamsJson());
+ EXPECT_EQ(
+ "{\"line_number\":5,\"message\":\"Uncaught TypeError: Cannot "
+ "read property 'split' of null\"}",
+ entries[1].GetParamsJson());
+ }
+}
+
+TEST_F(ProxyResolverV8TracingWrapperTest, TooManyAlerts) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ scoped_ptr<ProxyResolver> resolver =
+ CreateResolver(&log, &host_resolver, make_scoped_ptr(error_observer),
+ "too_many_alerts.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // Iteration1 does a DNS resolve
+ // Iteration2 exceeds the alert buffer
+ // Iteration3 runs in blocking mode and completes
+ EXPECT_EQ("foo:3", proxy_info.proxy_server().ToURI());
+
+ EXPECT_EQ(1u, host_resolver.num_resolve());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ // Check the NetLogs -- the script generated 50 alerts, which were mirrored
+ // to both the global and per-request logs.
+ TestNetLogEntry::List entries_list[2];
+ log.GetEntries(&entries_list[0]);
+ request_log.GetEntries(&entries_list[1]);
+
+ for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
+ const TestNetLogEntry::List& entries = entries_list[list_i];
+ EXPECT_EQ(50u, entries.size());
+ for (size_t i = 0; i < entries.size(); ++i) {
+ ASSERT_TRUE(LogContainsEvent(
+ entries, i, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, NetLog::PHASE_NONE));
+ }
+ }
+}
+
+// Verify that buffered alerts cannot grow unboundedly, even when the message is
+// empty string.
+TEST_F(ProxyResolverV8TracingWrapperTest, TooManyEmptyAlerts) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ scoped_ptr<ProxyResolver> resolver =
+ CreateResolver(&log, &host_resolver, make_scoped_ptr(error_observer),
+ "too_many_empty_alerts.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ EXPECT_EQ("foo:3", proxy_info.proxy_server().ToURI());
+
+ EXPECT_EQ(1u, host_resolver.num_resolve());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ // Check the NetLogs -- the script generated 50 alerts, which were mirrored
+ // to both the global and per-request logs.
+ TestNetLogEntry::List entries_list[2];
+ log.GetEntries(&entries_list[0]);
+ request_log.GetEntries(&entries_list[1]);
+
+ for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
+ const TestNetLogEntry::List& entries = entries_list[list_i];
+ EXPECT_EQ(1000u, entries.size());
+ for (size_t i = 0; i < entries.size(); ++i) {
+ ASSERT_TRUE(LogContainsEvent(
+ entries, i, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, NetLog::PHASE_NONE));
+ }
+ }
+}
+
+// This test runs a PAC script that issues a sequence of DNS resolves. The test
+// verifies the final result, and that the underlying DNS resolver received
+// the correct set of queries.
+TEST_F(ProxyResolverV8TracingWrapperTest, Dns) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddRuleForAddressFamily("host1", ADDRESS_FAMILY_IPV4,
+ "166.155.144.44");
+ host_resolver.rules()->AddIPLiteralRule("host1", "::1,192.168.1.1",
+ std::string());
+ host_resolver.rules()->AddSimulatedFailure("host2");
+ host_resolver.rules()->AddRule("host3", "166.155.144.33");
+ host_resolver.rules()->AddRule("host5", "166.155.144.55");
+ host_resolver.rules()->AddSimulatedFailure("host6");
+ host_resolver.rules()->AddRuleForAddressFamily("*", ADDRESS_FAMILY_IPV4,
+ "122.133.144.155");
+ host_resolver.rules()->AddRule("*", "133.122.100.200");
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ &log, &host_resolver, make_scoped_ptr(error_observer), "dns.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // The test does 13 DNS resolution, however only 7 of them are unique.
+ EXPECT_EQ(7u, host_resolver.num_resolve());
+
+ const char* kExpectedResult =
+ "122.133.144.155-" // myIpAddress()
+ "null-" // dnsResolve('')
+ "__1_192.168.1.1-" // dnsResolveEx('host1')
+ "null-" // dnsResolve('host2')
+ "166.155.144.33-" // dnsResolve('host3')
+ "122.133.144.155-" // myIpAddress()
+ "166.155.144.33-" // dnsResolve('host3')
+ "__1_192.168.1.1-" // dnsResolveEx('host1')
+ "122.133.144.155-" // myIpAddress()
+ "null-" // dnsResolve('host2')
+ "-" // dnsResolveEx('host6')
+ "133.122.100.200-" // myIpAddressEx()
+ "166.155.144.44" // dnsResolve('host1')
+ ":99";
+
+ EXPECT_EQ(kExpectedResult, proxy_info.proxy_server().ToURI());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ // Check the NetLogs -- the script generated 1 alert, mirrored to both
+ // the per-request and global logs.
+ TestNetLogEntry::List entries_list[2];
+ log.GetEntries(&entries_list[0]);
+ request_log.GetEntries(&entries_list[1]);
+
+ for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
+ const TestNetLogEntry::List& entries = entries_list[list_i];
+ EXPECT_EQ(1u, entries.size());
+ EXPECT_TRUE(LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
+ NetLog::PHASE_NONE));
+ EXPECT_EQ("{\"message\":\"iteration: 7\"}", entries[0].GetParamsJson());
+ }
+}
+
+// This test runs a PAC script that does "myIpAddress()" followed by
+// "dnsResolve()". This requires 2 restarts. However once the HostResolver's
+// cache is warmed, subsequent calls should take 0 restarts.
+TEST_F(ProxyResolverV8TracingWrapperTest, DnsChecksCache) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddRule("foopy", "166.155.144.11");
+ host_resolver.rules()->AddRule("*", "122.133.144.155");
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ &log, &host_resolver, make_scoped_ptr(error_observer), "simple_dns.js");
+
+ TestCompletionCallback callback1;
+ TestCompletionCallback callback2;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foopy/req1"), &proxy_info,
+ callback1.callback(), NULL, request_log.bound());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback1.WaitForResult());
+
+ // The test does 2 DNS resolutions.
+ EXPECT_EQ(2u, host_resolver.num_resolve());
+
+ // The first request took 2 restarts, hence on g_iteration=3.
+ EXPECT_EQ("166.155.144.11:3", proxy_info.proxy_server().ToURI());
+
+ rv =
+ resolver->GetProxyForURL(GURL("http://foopy/req2"), &proxy_info,
+ callback2.callback(), NULL, request_log.bound());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback2.WaitForResult());
+
+ EXPECT_EQ(4u, host_resolver.num_resolve());
+
+ // This time no restarts were required, so g_iteration incremented by 1.
+ EXPECT_EQ("166.155.144.11:4", proxy_info.proxy_server().ToURI());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ EXPECT_EQ(0u, log.GetSize());
+ EXPECT_EQ(0u, request_log.GetSize());
+}
+
+// This test runs a weird PAC script that was designed to defeat the DNS tracing
+// optimization. The proxy resolver should detect the inconsistency and
+// fall-back to synchronous mode execution.
+TEST_F(ProxyResolverV8TracingWrapperTest, FallBackToSynchronous1) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddRule("host1", "166.155.144.11");
+ host_resolver.rules()->AddRule("crazy4", "133.199.111.4");
+ host_resolver.rules()->AddRule("*", "122.133.144.155");
+
+ scoped_ptr<ProxyResolver> resolver =
+ CreateResolver(&log, &host_resolver, make_scoped_ptr(error_observer),
+ "global_sideffects1.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // The script itself only does 2 DNS resolves per execution, however it
+ // constructs the hostname using a global counter which changes on each
+ // invocation.
+ EXPECT_EQ(3u, host_resolver.num_resolve());
+
+ EXPECT_EQ("166.155.144.11-133.199.111.4:100",
+ proxy_info.proxy_server().ToURI());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ // Check the NetLogs -- the script generated 1 alert, mirrored to both
+ // the per-request and global logs.
+ TestNetLogEntry::List entries_list[2];
+ log.GetEntries(&entries_list[0]);
+ request_log.GetEntries(&entries_list[1]);
+
+ for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) {
+ const TestNetLogEntry::List& entries = entries_list[list_i];
+ EXPECT_EQ(1u, entries.size());
+ EXPECT_TRUE(LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
+ NetLog::PHASE_NONE));
+ EXPECT_EQ("{\"message\":\"iteration: 4\"}", entries[0].GetParamsJson());
+ }
+}
+
+// This test runs a weird PAC script that was designed to defeat the DNS tracing
+// optimization. The proxy resolver should detect the inconsistency and
+// fall-back to synchronous mode execution.
+TEST_F(ProxyResolverV8TracingWrapperTest, FallBackToSynchronous2) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddRule("host1", "166.155.144.11");
+ host_resolver.rules()->AddRule("host2", "166.155.144.22");
+ host_resolver.rules()->AddRule("host3", "166.155.144.33");
+ host_resolver.rules()->AddRule("host4", "166.155.144.44");
+ host_resolver.rules()->AddRule("*", "122.133.144.155");
+
+ scoped_ptr<ProxyResolver> resolver =
+ CreateResolver(&log, &host_resolver, make_scoped_ptr(error_observer),
+ "global_sideffects2.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ EXPECT_EQ(3u, host_resolver.num_resolve());
+
+ EXPECT_EQ("166.155.144.44:100", proxy_info.proxy_server().ToURI());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ // Check the NetLogs -- nothing was logged.
+ EXPECT_EQ(0u, log.GetSize());
+ EXPECT_EQ(0u, request_log.GetSize());
+}
+
+// This test runs a weird PAC script that yields a never ending sequence
+// of DNS resolves when restarting. Running it will hit the maximum
+// DNS resolves per request limit (20) after which every DNS resolve will
+// fail.
+TEST_F(ProxyResolverV8TracingWrapperTest, InfiniteDNSSequence) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddRule("host*", "166.155.144.11");
+ host_resolver.rules()->AddRule("*", "122.133.144.155");
+
+ scoped_ptr<ProxyResolver> resolver =
+ CreateResolver(&log, &host_resolver, make_scoped_ptr(error_observer),
+ "global_sideffects3.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ EXPECT_EQ(20u, host_resolver.num_resolve());
+
+ EXPECT_EQ(
+ "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
+ "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
+ "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
+ "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
+ "166.155.144.11-166.155.144.11-166.155.144.11-166.155.144.11-"
+ "null:21",
+ proxy_info.proxy_server().ToURI());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ // Check the NetLogs -- 1 alert was logged.
+ EXPECT_EQ(1u, log.GetSize());
+ EXPECT_EQ(1u, request_log.GetSize());
+}
+
+// This test runs a weird PAC script that yields a never ending sequence
+// of DNS resolves when restarting. Running it will hit the maximum
+// DNS resolves per request limit (20) after which every DNS resolve will
+// fail.
+TEST_F(ProxyResolverV8TracingWrapperTest, InfiniteDNSSequence2) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddRule("host*", "166.155.144.11");
+ host_resolver.rules()->AddRule("*", "122.133.144.155");
+
+ scoped_ptr<ProxyResolver> resolver =
+ CreateResolver(&log, &host_resolver, make_scoped_ptr(error_observer),
+ "global_sideffects4.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ EXPECT_EQ(20u, host_resolver.num_resolve());
+
+ EXPECT_EQ("null21:34", proxy_info.proxy_server().ToURI());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ // Check the NetLogs -- 1 alert was logged.
+ EXPECT_EQ(1u, log.GetSize());
+ EXPECT_EQ(1u, request_log.GetSize());
+}
+
+void DnsDuringInitHelper(bool synchronous_host_resolver) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ host_resolver.set_synchronous_mode(synchronous_host_resolver);
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddRule("host1", "91.13.12.1");
+ host_resolver.rules()->AddRule("host2", "91.13.12.2");
+
+ scoped_ptr<ProxyResolver> resolver =
+ CreateResolver(&log, &host_resolver, make_scoped_ptr(error_observer),
+ "dns_during_init.js");
+
+ // Initialization did 2 dnsResolves.
+ EXPECT_EQ(2u, host_resolver.num_resolve());
+
+ host_resolver.rules()->ClearRules();
+ host_resolver.GetHostCache()->clear();
+
+ host_resolver.rules()->AddRule("host1", "145.88.13.3");
+ host_resolver.rules()->AddRule("host2", "137.89.8.45");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // Fetched host1 and host2 again, since the ones done during initialization
+ // should not have been cached.
+ EXPECT_EQ(4u, host_resolver.num_resolve());
+
+ EXPECT_EQ("91.13.12.1-91.13.12.2-145.88.13.3-137.89.8.45:99",
+ proxy_info.proxy_server().ToURI());
+
+ // Check the NetLogs -- the script generated 2 alerts during initialization.
+ EXPECT_EQ(0u, request_log.GetSize());
+ TestNetLogEntry::List entries;
+ log.GetEntries(&entries);
+
+ ASSERT_EQ(2u, entries.size());
+ EXPECT_TRUE(LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
+ NetLog::PHASE_NONE));
+ EXPECT_TRUE(LogContainsEvent(entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
+ NetLog::PHASE_NONE));
+
+ EXPECT_EQ("{\"message\":\"Watsup\"}", entries[0].GetParamsJson());
+ EXPECT_EQ("{\"message\":\"Watsup2\"}", entries[1].GetParamsJson());
+}
+
+// Tests a PAC script which does DNS resolves during initialization.
+TEST_F(ProxyResolverV8TracingWrapperTest, DnsDuringInit) {
+ // Test with both both a host resolver that always completes asynchronously,
+ // and then again with one that completes synchronously.
+ DnsDuringInitHelper(false);
+ DnsDuringInitHelper(true);
+}
+
+void CrashCallback(int) {
+ // Be extra sure that if the callback ever gets invoked, the test will fail.
+ CHECK(false);
+}
+
+// Start some requests, cancel them all, and then destroy the resolver.
+// Note the execution order for this test can vary. Since multiple
+// threads are involved, the cancellation may be received a different
+// times.
+TEST_F(ProxyResolverV8TracingWrapperTest, CancelAll) {
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddSimulatedFailure("*");
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ nullptr, &host_resolver, make_scoped_ptr(error_observer), "dns.js");
+
+ const size_t kNumRequests = 5;
+ ProxyInfo proxy_info[kNumRequests];
+ ProxyResolver::RequestHandle request[kNumRequests];
+
+ for (size_t i = 0; i < kNumRequests; ++i) {
+ int rv = resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info[i],
+ base::Bind(&CrashCallback), &request[i],
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ }
+
+ for (size_t i = 0; i < kNumRequests; ++i) {
+ resolver->CancelRequest(request[i]);
+ }
+}
+
+// Note the execution order for this test can vary. Since multiple
+// threads are involved, the cancellation may be received a different
+// times.
+TEST_F(ProxyResolverV8TracingWrapperTest, CancelSome) {
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddSimulatedFailure("*");
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ nullptr, &host_resolver, make_scoped_ptr(error_observer), "dns.js");
+
+ ProxyInfo proxy_info1;
+ ProxyInfo proxy_info2;
+ ProxyResolver::RequestHandle request1;
+ ProxyResolver::RequestHandle request2;
+ TestCompletionCallback callback;
+
+ int rv = resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info1,
+ base::Bind(&CrashCallback), &request1,
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info2,
+ callback.callback(), &request2, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ resolver->CancelRequest(request1);
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+}
+
+// Cancel a request after it has finished running on the worker thread, and has
+// posted a task the completion task back to origin thread.
+TEST_F(ProxyResolverV8TracingWrapperTest, CancelWhilePendingCompletionTask) {
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddSimulatedFailure("*");
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ nullptr, &host_resolver, make_scoped_ptr(error_observer), "error.js");
+
+ ProxyInfo proxy_info1;
+ ProxyInfo proxy_info2;
+ ProxyInfo proxy_info3;
+ ProxyResolver::RequestHandle request1;
+ ProxyResolver::RequestHandle request2;
+ ProxyResolver::RequestHandle request3;
+ TestCompletionCallback callback;
+
+ int rv = resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info1,
+ base::Bind(&CrashCallback), &request1,
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ rv = resolver->GetProxyForURL(GURL("http://throw-an-error/"), &proxy_info2,
+ callback.callback(), &request2, BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Wait until the first request has finished running on the worker thread.
+ // (The second request will output an error).
+ error_observer->WaitForOutput();
+
+ // Cancel the first request, while it has a pending completion task on
+ // the origin thread.
+ resolver->CancelRequest(request1);
+
+ EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult());
+
+ // Start another request, to make sure it is able to complete.
+ rv = resolver->GetProxyForURL(GURL("http://i-have-no-idea-what-im-doing/"),
+ &proxy_info3, callback.callback(), &request3,
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ EXPECT_EQ("i-approve-this-message:42", proxy_info3.proxy_server().ToURI());
+}
+
+// This implementation of HostResolver allows blocking until a resolve request
+// has been received. The resolve requests it receives will never be completed.
+class BlockableHostResolver : public HostResolver {
+ public:
+ BlockableHostResolver()
+ : num_cancelled_requests_(0), waiting_for_resolve_(false) {}
+
+ int Resolve(const RequestInfo& info,
+ RequestPriority priority,
+ AddressList* addresses,
+ const CompletionCallback& callback,
+ RequestHandle* out_req,
+ const BoundNetLog& net_log) override {
+ EXPECT_FALSE(callback.is_null());
+ EXPECT_TRUE(out_req);
+
+ if (!action_.is_null())
+ action_.Run();
+
+ // Indicate to the caller that a request was received.
+ EXPECT_TRUE(waiting_for_resolve_);
+ base::MessageLoop::current()->Quit();
+
+ // This line is intentionally after action_.Run(), since one of the
+ // tests does a cancellation inside of Resolve(), and it is more
+ // interesting if *out_req hasn't been written yet at that point.
+ *out_req = reinterpret_cast<RequestHandle*>(1); // Magic value.
+
+ // Return ERR_IO_PENDING as this request will NEVER be completed.
+ // Expectation is for the caller to later cancel the request.
+ return ERR_IO_PENDING;
+ }
+
+ int ResolveFromCache(const RequestInfo& info,
+ AddressList* addresses,
+ const BoundNetLog& net_log) override {
+ NOTREACHED();
+ return ERR_DNS_CACHE_MISS;
+ }
+
+ void CancelRequest(RequestHandle req) override {
+ EXPECT_EQ(reinterpret_cast<RequestHandle*>(1), req);
+ num_cancelled_requests_++;
+ }
+
+ void SetAction(const base::Callback<void(void)>& action) { action_ = action; }
+
+ // Waits until Resolve() has been called.
+ void WaitUntilRequestIsReceived() {
+ waiting_for_resolve_ = true;
+ base::MessageLoop::current()->Run();
+ DCHECK(waiting_for_resolve_);
+ waiting_for_resolve_ = false;
+ }
+
+ int num_cancelled_requests() const { return num_cancelled_requests_; }
+
+ private:
+ int num_cancelled_requests_;
+ bool waiting_for_resolve_;
+ base::Callback<void(void)> action_;
+};
+
+// This cancellation test exercises a more predictable cancellation codepath --
+// when the request has an outstanding DNS request in flight.
+TEST_F(ProxyResolverV8TracingWrapperTest,
+ CancelWhileOutstandingNonBlockingDns) {
+ BlockableHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ nullptr, &host_resolver, make_scoped_ptr(error_observer), "dns.js");
+
+ ProxyInfo proxy_info1;
+ ProxyInfo proxy_info2;
+ ProxyResolver::RequestHandle request1;
+ ProxyResolver::RequestHandle request2;
+
+ int rv = resolver->GetProxyForURL(GURL("http://foo/req1"), &proxy_info1,
+ base::Bind(&CrashCallback), &request1,
+ BoundNetLog());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ host_resolver.WaitUntilRequestIsReceived();
+
+ rv = resolver->GetProxyForURL(GURL("http://foo/req2"), &proxy_info2,
+ base::Bind(&CrashCallback), &request2,
+ BoundNetLog());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ host_resolver.WaitUntilRequestIsReceived();
+
+ resolver->CancelRequest(request1);
+ resolver->CancelRequest(request2);
+
+ EXPECT_EQ(2, host_resolver.num_cancelled_requests());
+
+ // After leaving this scope, the ProxyResolver is destroyed.
+ // This should not cause any problems, as the outstanding work
+ // should have been cancelled.
+}
+
+void CancelRequestAndPause(ProxyResolver* resolver,
+ ProxyResolver::RequestHandle request) {
+ resolver->CancelRequest(request);
+
+ // Sleep for a little bit. This makes it more likely for the worker
+ // thread to have returned from its call, and serves as a regression
+ // test for http://crbug.com/173373.
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(30));
+}
+
+// In non-blocking mode, the worker thread actually does block for
+// a short time to see if the result is in the DNS cache. Test
+// cancellation while the worker thread is waiting on this event.
+TEST_F(ProxyResolverV8TracingWrapperTest, CancelWhileBlockedInNonBlockingDns) {
+ BlockableHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ nullptr, &host_resolver, make_scoped_ptr(error_observer), "dns.js");
+
+ ProxyInfo proxy_info;
+ ProxyResolver::RequestHandle request;
+
+ int rv = resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ base::Bind(&CrashCallback), &request,
+ BoundNetLog());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ host_resolver.SetAction(
+ base::Bind(CancelRequestAndPause, resolver.get(), request));
+
+ host_resolver.WaitUntilRequestIsReceived();
+
+ // At this point the host resolver ran Resolve(), and should have cancelled
+ // the request.
+
+ EXPECT_EQ(1, host_resolver.num_cancelled_requests());
+}
+
+// Cancel the request while there is a pending DNS request, however before
+// the request is sent to the host resolver.
+TEST_F(ProxyResolverV8TracingWrapperTest, CancelWhileBlockedInNonBlockingDns2) {
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ nullptr, &host_resolver, make_scoped_ptr(error_observer), "dns.js");
+
+ ProxyInfo proxy_info;
+ ProxyResolver::RequestHandle request;
+
+ int rv = resolver->GetProxyForURL(GURL("http://foo/"), &proxy_info,
+ base::Bind(&CrashCallback), &request,
+ BoundNetLog());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Wait a bit, so the DNS task has hopefully been posted. The test will
+ // work whatever the delay is here, but it is most useful if the delay
+ // is large enough to allow a task to be posted back.
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
+ resolver->CancelRequest(request);
+
+ EXPECT_EQ(0u, host_resolver.num_resolve());
+}
+
+TEST_F(ProxyResolverV8TracingWrapperTest,
+ CancelCreateResolverWhileOutstandingBlockingDns) {
+ BlockableHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ ProxyResolverFactoryV8TracingWrapper factory(
+ &host_resolver, nullptr,
+ base::Bind(&ReturnErrorObserver,
+ base::Passed(make_scoped_ptr(error_observer))));
+
+ scoped_ptr<ProxyResolver> resolver;
+ scoped_ptr<ProxyResolverFactory::Request> request;
+ int rv = factory.CreateProxyResolver(LoadScriptData("dns_during_init.js"),
+ &resolver, base::Bind(&CrashCallback),
+ &request);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ host_resolver.WaitUntilRequestIsReceived();
+
+ request.reset();
+ EXPECT_EQ(1, host_resolver.num_cancelled_requests());
+}
+
+TEST_F(ProxyResolverV8TracingWrapperTest,
+ DeleteFactoryWhileOutstandingBlockingDns) {
+ BlockableHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ scoped_ptr<ProxyResolver> resolver;
+ scoped_ptr<ProxyResolverFactory::Request> request;
+ {
+ ProxyResolverFactoryV8TracingWrapper factory(
+ &host_resolver, nullptr,
+ base::Bind(&ReturnErrorObserver,
+ base::Passed(make_scoped_ptr(error_observer))));
+
+ int rv = factory.CreateProxyResolver(LoadScriptData("dns_during_init.js"),
+ &resolver, base::Bind(&CrashCallback),
+ &request);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ host_resolver.WaitUntilRequestIsReceived();
+ }
+ EXPECT_EQ(1, host_resolver.num_cancelled_requests());
+}
+
+TEST_F(ProxyResolverV8TracingWrapperTest, ErrorLoadingScript) {
+ BlockableHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ ProxyResolverFactoryV8TracingWrapper factory(
+ &host_resolver, nullptr,
+ base::Bind(&ReturnErrorObserver,
+ base::Passed(make_scoped_ptr(error_observer))));
+
+ scoped_ptr<ProxyResolver> resolver;
+ scoped_ptr<ProxyResolverFactory::Request> request;
+ TestCompletionCallback callback;
+ int rv =
+ factory.CreateProxyResolver(LoadScriptData("error_on_load.js"), &resolver,
+ callback.callback(), &request);
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult());
+ EXPECT_FALSE(resolver);
+}
+
+// This tests that the execution of a PAC script is terminated when the DNS
+// dependencies are missing. If the test fails, then it will hang.
+TEST_F(ProxyResolverV8TracingWrapperTest, Terminate) {
+ TestNetLog log;
+ BoundTestNetLog request_log;
+ MockCachingHostResolver host_resolver;
+ MockErrorObserver* error_observer = new MockErrorObserver;
+
+ host_resolver.rules()->AddRule("host1", "182.111.0.222");
+ host_resolver.rules()->AddRule("host2", "111.33.44.55");
+
+ scoped_ptr<ProxyResolver> resolver = CreateResolver(
+ &log, &host_resolver, make_scoped_ptr(error_observer), "terminate.js");
+
+ TestCompletionCallback callback;
+ ProxyInfo proxy_info;
+
+ int rv =
+ resolver->GetProxyForURL(GURL("http://foopy/req1"), &proxy_info,
+ callback.callback(), NULL, request_log.bound());
+
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ // The test does 2 DNS resolutions.
+ EXPECT_EQ(2u, host_resolver.num_resolve());
+
+ EXPECT_EQ("foopy:3", proxy_info.proxy_server().ToURI());
+
+ // No errors.
+ EXPECT_EQ("", error_observer->GetOutput());
+
+ EXPECT_EQ(0u, log.GetSize());
+ EXPECT_EQ(0u, request_log.GetSize());
+}
+
+// Tests that multiple instances of ProxyResolverV8TracingWrapper can coexist
+// and run
+// correctly at the same time. This is relevant because at the moment (time
+// this test was written) each ProxyResolverV8TracingWrapper creates its own
+// thread to
+// run V8 on, however each thread is operating on the same v8::Isolate.
+TEST_F(ProxyResolverV8TracingWrapperTest, MultipleResolvers) {
+ // ------------------------
+ // Setup resolver0
+ // ------------------------
+ MockHostResolver host_resolver0;
+ host_resolver0.rules()->AddRuleForAddressFamily("host1", ADDRESS_FAMILY_IPV4,
+ "166.155.144.44");
+ host_resolver0.rules()->AddIPLiteralRule("host1", "::1,192.168.1.1",
+ std::string());
+ host_resolver0.rules()->AddSimulatedFailure("host2");
+ host_resolver0.rules()->AddRule("host3", "166.155.144.33");
+ host_resolver0.rules()->AddRule("host5", "166.155.144.55");
+ host_resolver0.rules()->AddSimulatedFailure("host6");
+ host_resolver0.rules()->AddRuleForAddressFamily("*", ADDRESS_FAMILY_IPV4,
+ "122.133.144.155");
+ host_resolver0.rules()->AddRule("*", "133.122.100.200");
+ scoped_ptr<ProxyResolver> resolver0 =
+ CreateResolver(nullptr, &host_resolver0,
+ make_scoped_ptr(new MockErrorObserver), "dns.js");
+
+ // ------------------------
+ // Setup resolver1
+ // ------------------------
+ scoped_ptr<ProxyResolver> resolver1 =
+ CreateResolver(nullptr, &host_resolver0,
+ make_scoped_ptr(new MockErrorObserver), "dns.js");
+
+ // ------------------------
+ // Setup resolver2
+ // ------------------------
+ scoped_ptr<ProxyResolver> resolver2 =
+ CreateResolver(nullptr, &host_resolver0,
+ make_scoped_ptr(new MockErrorObserver), "simple.js");
+
+ // ------------------------
+ // Setup resolver3
+ // ------------------------
+ MockHostResolver host_resolver3;
+ host_resolver3.rules()->AddRule("foo", "166.155.144.33");
+ scoped_ptr<ProxyResolver> resolver3 =
+ CreateResolver(nullptr, &host_resolver3,
+ make_scoped_ptr(new MockErrorObserver), "simple_dns.js");
+
+ // ------------------------
+ // Queue up work for each resolver (which will be running in parallel).
+ // ------------------------
+
+ ProxyResolver* resolver[] = {
+ resolver0.get(), resolver1.get(), resolver2.get(), resolver3.get(),
+ };
+
+ const size_t kNumResolvers = arraysize(resolver);
+ const size_t kNumIterations = 20;
+ const size_t kNumResults = kNumResolvers * kNumIterations;
+ TestCompletionCallback callback[kNumResults];
+ ProxyInfo proxy_info[kNumResults];
+
+ for (size_t i = 0; i < kNumResults; ++i) {
+ size_t resolver_i = i % kNumResolvers;
+ int rv = resolver[resolver_i]->GetProxyForURL(
+ GURL("http://foo/"), &proxy_info[i], callback[i].callback(), NULL,
+ BoundNetLog());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ }
+
+ // ------------------------
+ // Verify all of the results.
+ // ------------------------
+
+ const char* kExpectedForDnsJs =
+ "122.133.144.155-" // myIpAddress()
+ "null-" // dnsResolve('')
+ "__1_192.168.1.1-" // dnsResolveEx('host1')
+ "null-" // dnsResolve('host2')
+ "166.155.144.33-" // dnsResolve('host3')
+ "122.133.144.155-" // myIpAddress()
+ "166.155.144.33-" // dnsResolve('host3')
+ "__1_192.168.1.1-" // dnsResolveEx('host1')
+ "122.133.144.155-" // myIpAddress()
+ "null-" // dnsResolve('host2')
+ "-" // dnsResolveEx('host6')
+ "133.122.100.200-" // myIpAddressEx()
+ "166.155.144.44" // dnsResolve('host1')
+ ":99";
+
+ for (size_t i = 0; i < kNumResults; ++i) {
+ size_t resolver_i = i % kNumResolvers;
+ EXPECT_EQ(OK, callback[i].WaitForResult());
+
+ std::string proxy_uri = proxy_info[i].proxy_server().ToURI();
+
+ if (resolver_i == 0 || resolver_i == 1) {
+ EXPECT_EQ(kExpectedForDnsJs, proxy_uri);
+ } else if (resolver_i == 2) {
+ EXPECT_EQ("foo:99", proxy_uri);
+ } else if (resolver_i == 3) {
+ EXPECT_EQ("166.155.144.33:",
+ proxy_uri.substr(0, proxy_uri.find(':') + 1));
+ } else {
+ NOTREACHED();
+ }
+ }
+}
+
+} // namespace
+
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698