This source file includes following definitions.
- TearDown
- LoadScriptData
- InitResolver
- OnPACScriptError
- GetOutput
- WaitForOutput
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- DnsDuringInitHelper
- TEST_F
- CrashCallback
- TEST_F
- TEST_F
- TEST_F
- waiting_for_resolve_
- Resolve
- ResolveFromCache
- CancelRequest
- SetAction
- WaitUntilRequestIsReceived
- num_cancelled_requests
- TEST_F
- CancelRequestAndPause
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "net/proxy/proxy_resolver_v8_tracing.h"
#include "base/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/net_log.h"
#include "net/base/net_log_unittest.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/host_cache.h"
#include "net/dns/mock_host_resolver.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 ProxyResolverV8TracingTest : public testing::Test {
public:
virtual void TearDown() OVERRIDE {
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);
std::string file_contents;
bool ok = base::ReadFileToString(path, &file_contents);
EXPECT_TRUE(ok) << "Failed to read file: " << path.value();
return ProxyResolverScriptData::FromUTF8(file_contents);
}
void InitResolver(ProxyResolverV8Tracing* resolver, const char* filename) {
TestCompletionCallback callback;
int rv =
resolver->SetPacScript(LoadScriptData(filename), callback.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_EQ(OK, callback.WaitForResult());
}
class MockErrorObserver : public ProxyResolverErrorObserver {
public:
MockErrorObserver() : event_(true, false) {}
virtual 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(ProxyResolverV8TracingTest, Simple) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
InitResolver(&resolver, "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());
EXPECT_EQ("", error_observer->GetOutput());
EXPECT_EQ(0u, log.GetSize());
EXPECT_EQ(0u, request_log.GetSize());
}
TEST_F(ProxyResolverV8TracingTest, JavascriptError) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
InitResolver(&resolver, "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());
CapturingNetLog::CapturedEntryList 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 CapturingNetLog::CapturedEntryList& 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(ProxyResolverV8TracingTest, TooManyAlerts) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
InitResolver(&resolver, "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());
EXPECT_EQ("foo:3", proxy_info.proxy_server().ToURI());
EXPECT_EQ(1u, host_resolver.num_resolve());
EXPECT_EQ("", error_observer->GetOutput());
CapturingNetLog::CapturedEntryList 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 CapturingNetLog::CapturedEntryList& 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));
}
}
}
TEST_F(ProxyResolverV8TracingTest, TooManyEmptyAlerts) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
InitResolver(&resolver, "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());
EXPECT_EQ("", error_observer->GetOutput());
CapturingNetLog::CapturedEntryList 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 CapturingNetLog::CapturedEntryList& 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));
}
}
}
TEST_F(ProxyResolverV8TracingTest, Dns) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
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");
InitResolver(&resolver, "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());
EXPECT_EQ(7u, host_resolver.num_resolve());
const char* kExpectedResult =
"122.133.144.155-"
"null-"
"__1_192.168.1.1-"
"null-"
"166.155.144.33-"
"122.133.144.155-"
"166.155.144.33-"
"__1_192.168.1.1-"
"122.133.144.155-"
"null-"
"-"
"133.122.100.200-"
"166.155.144.44"
":99";
EXPECT_EQ(kExpectedResult, proxy_info.proxy_server().ToURI());
EXPECT_EQ("", error_observer->GetOutput());
CapturingNetLog::CapturedEntryList 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 CapturingNetLog::CapturedEntryList& 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());
}
}
TEST_F(ProxyResolverV8TracingTest, DnsChecksCache) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
host_resolver.rules()->AddRule("foopy", "166.155.144.11");
host_resolver.rules()->AddRule("*", "122.133.144.155");
InitResolver(&resolver, "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());
EXPECT_EQ(2u, host_resolver.num_resolve());
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());
EXPECT_EQ("166.155.144.11:4", proxy_info.proxy_server().ToURI());
EXPECT_EQ("", error_observer->GetOutput());
EXPECT_EQ(0u, log.GetSize());
EXPECT_EQ(0u, request_log.GetSize());
}
TEST_F(ProxyResolverV8TracingTest, FallBackToSynchronous1) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
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");
InitResolver(&resolver, "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());
EXPECT_EQ(3u, host_resolver.num_resolve());
EXPECT_EQ("166.155.144.11-133.199.111.4:100",
proxy_info.proxy_server().ToURI());
EXPECT_EQ("", error_observer->GetOutput());
CapturingNetLog::CapturedEntryList 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 CapturingNetLog::CapturedEntryList& 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());
}
}
TEST_F(ProxyResolverV8TracingTest, FallBackToSynchronous2) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
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");
InitResolver(&resolver, "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());
EXPECT_EQ("", error_observer->GetOutput());
EXPECT_EQ(0u, log.GetSize());
EXPECT_EQ(0u, request_log.GetSize());
}
TEST_F(ProxyResolverV8TracingTest, InfiniteDNSSequence) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
host_resolver.rules()->AddRule("host*", "166.155.144.11");
host_resolver.rules()->AddRule("*", "122.133.144.155");
InitResolver(&resolver, "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());
EXPECT_EQ("", error_observer->GetOutput());
EXPECT_EQ(1u, log.GetSize());
EXPECT_EQ(1u, request_log.GetSize());
}
TEST_F(ProxyResolverV8TracingTest, InfiniteDNSSequence2) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
host_resolver.rules()->AddRule("host*", "166.155.144.11");
host_resolver.rules()->AddRule("*", "122.133.144.155");
InitResolver(&resolver, "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());
EXPECT_EQ("", error_observer->GetOutput());
EXPECT_EQ(1u, log.GetSize());
EXPECT_EQ(1u, request_log.GetSize());
}
void DnsDuringInitHelper(bool synchronous_host_resolver) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
host_resolver.set_synchronous_mode(synchronous_host_resolver);
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
host_resolver.rules()->AddRule("host1", "91.13.12.1");
host_resolver.rules()->AddRule("host2", "91.13.12.2");
InitResolver(&resolver, "dns_during_init.js");
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());
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());
EXPECT_EQ(0u, request_log.GetSize());
CapturingNetLog::CapturedEntryList 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());
}
TEST_F(ProxyResolverV8TracingTest, DnsDuringInit) {
DnsDuringInitHelper(false);
DnsDuringInitHelper(true);
}
void CrashCallback(int) {
CHECK(false);
}
TEST_F(ProxyResolverV8TracingTest, CancelAll) {
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
host_resolver.rules()->AddSimulatedFailure("*");
InitResolver(&resolver, "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]);
}
}
TEST_F(ProxyResolverV8TracingTest, CancelSome) {
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
host_resolver.rules()->AddSimulatedFailure("*");
InitResolver(&resolver, "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());
}
TEST_F(ProxyResolverV8TracingTest, CancelWhilePendingCompletionTask) {
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
host_resolver.rules()->AddSimulatedFailure("*");
InitResolver(&resolver, "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);
error_observer->WaitForOutput();
resolver.CancelRequest(request1);
EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, callback.WaitForResult());
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());
}
class BlockableHostResolver : public HostResolver {
public:
BlockableHostResolver()
: num_cancelled_requests_(0), waiting_for_resolve_(false) {}
virtual 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();
EXPECT_TRUE(waiting_for_resolve_);
base::MessageLoop::current()->Quit();
*out_req = reinterpret_cast<RequestHandle*>(1);
return ERR_IO_PENDING;
}
virtual int ResolveFromCache(const RequestInfo& info,
AddressList* addresses,
const BoundNetLog& net_log) OVERRIDE {
NOTREACHED();
return ERR_DNS_CACHE_MISS;
}
virtual 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;
}
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_;
};
TEST_F(ProxyResolverV8TracingTest, CancelWhileOutstandingNonBlockingDns) {
BlockableHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
InitResolver(&resolver, "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());
}
void CancelRequestAndPause(ProxyResolverV8Tracing* resolver,
ProxyResolver::RequestHandle request) {
resolver->CancelRequest(request);
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(30));
}
TEST_F(ProxyResolverV8TracingTest, CancelWhileBlockedInNonBlockingDns) {
BlockableHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
InitResolver(&resolver, "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, request));
host_resolver.WaitUntilRequestIsReceived();
EXPECT_EQ(1, host_resolver.num_cancelled_requests());
}
TEST_F(ProxyResolverV8TracingTest, CancelWhileBlockedInNonBlockingDns2) {
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
InitResolver(&resolver, "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);
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
resolver.CancelRequest(request);
EXPECT_EQ(0u, host_resolver.num_resolve());
}
TEST_F(ProxyResolverV8TracingTest, CancelSetPacWhileOutstandingBlockingDns) {
BlockableHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, NULL);
int rv =
resolver.SetPacScript(LoadScriptData("dns_during_init.js"),
base::Bind(&CrashCallback));
EXPECT_EQ(ERR_IO_PENDING, rv);
host_resolver.WaitUntilRequestIsReceived();
resolver.CancelSetPacScript();
EXPECT_EQ(1, host_resolver.num_cancelled_requests());
}
TEST_F(ProxyResolverV8TracingTest, Terminate) {
CapturingNetLog log;
CapturingBoundNetLog request_log;
MockCachingHostResolver host_resolver;
MockErrorObserver* error_observer = new MockErrorObserver;
ProxyResolverV8Tracing resolver(&host_resolver, error_observer, &log);
host_resolver.rules()->AddRule("host1", "182.111.0.222");
host_resolver.rules()->AddRule("host2", "111.33.44.55");
InitResolver(&resolver, "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());
EXPECT_EQ(2u, host_resolver.num_resolve());
EXPECT_EQ("foopy:3", proxy_info.proxy_server().ToURI());
EXPECT_EQ("", error_observer->GetOutput());
EXPECT_EQ(0u, log.GetSize());
EXPECT_EQ(0u, request_log.GetSize());
}
TEST_F(ProxyResolverV8TracingTest, MultipleResolvers) {
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");
ProxyResolverV8Tracing resolver0(
&host_resolver0, new MockErrorObserver, NULL);
InitResolver(&resolver0, "dns.js");
ProxyResolverV8Tracing resolver1(
&host_resolver0, new MockErrorObserver, NULL);
InitResolver(&resolver1, "dns.js");
ProxyResolverV8Tracing resolver2(
&host_resolver0, new MockErrorObserver, NULL);
InitResolver(&resolver2, "simple.js");
MockHostResolver host_resolver3;
host_resolver3.rules()->AddRule("foo", "166.155.144.33");
ProxyResolverV8Tracing resolver3(
&host_resolver3, new MockErrorObserver, NULL);
InitResolver(&resolver3, "simple_dns.js");
ProxyResolverV8Tracing* resolver[] = {
&resolver0, &resolver1, &resolver2, &resolver3,
};
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);
}
const char* kExpectedForDnsJs =
"122.133.144.155-"
"null-"
"__1_192.168.1.1-"
"null-"
"166.155.144.33-"
"122.133.144.155-"
"166.155.144.33-"
"__1_192.168.1.1-"
"122.133.144.155-"
"null-"
"-"
"133.122.100.200-"
"166.155.144.44"
":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();
}
}
}
}
}