This source file includes following definitions.
- should_terminate
- Alert
- ResolveDns
- OnError
- mock_js_bindings
- SetPacScriptFromDisk
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
- TEST
#include "base/compiler_specific.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
#include "net/base/net_log_unittest.h"
#include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_resolver_v8.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace net {
namespace {
class MockJSBindings : public ProxyResolverV8::JSBindings {
public:
MockJSBindings() : my_ip_address_count(0), my_ip_address_ex_count(0),
should_terminate(false) {}
virtual void Alert(const base::string16& message) OVERRIDE {
VLOG(1) << "PAC-alert: " << message;
alerts.push_back(base::UTF16ToUTF8(message));
}
virtual bool ResolveDns(const std::string& host,
ResolveDnsOperation op,
std::string* output,
bool* terminate) OVERRIDE {
*terminate = should_terminate;
if (op == MY_IP_ADDRESS) {
my_ip_address_count++;
*output = my_ip_address_result;
return !my_ip_address_result.empty();
}
if (op == MY_IP_ADDRESS_EX) {
my_ip_address_ex_count++;
*output = my_ip_address_ex_result;
return !my_ip_address_ex_result.empty();
}
if (op == DNS_RESOLVE) {
dns_resolves.push_back(host);
*output = dns_resolve_result;
return !dns_resolve_result.empty();
}
if (op == DNS_RESOLVE_EX) {
dns_resolves_ex.push_back(host);
*output = dns_resolve_ex_result;
return !dns_resolve_ex_result.empty();
}
CHECK(false);
return false;
}
virtual void OnError(int line_number,
const base::string16& message) OVERRIDE {
VLOG(1) << "PAC-error: [" << line_number << "] " << message;
errors.push_back(base::UTF16ToUTF8(message));
errors_line_number.push_back(line_number);
}
std::string my_ip_address_result;
std::string my_ip_address_ex_result;
std::string dns_resolve_result;
std::string dns_resolve_ex_result;
std::vector<std::string> alerts;
std::vector<std::string> errors;
std::vector<int> errors_line_number;
std::vector<std::string> dns_resolves;
std::vector<std::string> dns_resolves_ex;
int my_ip_address_count;
int my_ip_address_ex_count;
bool should_terminate;
};
class ProxyResolverV8WithMockBindings : public ProxyResolverV8 {
public:
ProxyResolverV8WithMockBindings() {
set_js_bindings(&mock_js_bindings_);
}
virtual ~ProxyResolverV8WithMockBindings() {
}
MockJSBindings* mock_js_bindings() {
return &mock_js_bindings_;
}
int SetPacScriptFromDisk(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_unittest");
path = path.AppendASCII(filename);
std::string file_contents;
bool ok = base::ReadFileToString(path, &file_contents);
if (!ok) {
LOG(ERROR) << "Failed to read file: " << path.value();
return ERR_UNEXPECTED;
}
return SetPacScript(ProxyResolverScriptData::FromUTF8(file_contents),
CompletionCallback());
}
private:
MockJSBindings mock_js_bindings_;
};
const GURL kQueryUrl("http://www.google.com");
const GURL kPacUrl;
TEST(ProxyResolverV8Test, Direct) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("direct.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
CapturingBoundNetLog log;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, log.bound());
EXPECT_EQ(OK, result);
EXPECT_TRUE(proxy_info.is_direct());
EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
net::CapturingNetLog::CapturedEntryList entries;
log.GetEntries(&entries);
EXPECT_EQ(0u, entries.size());
}
TEST(ProxyResolverV8Test, ReturnEmptyString) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("return_empty_string.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_TRUE(proxy_info.is_direct());
EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
}
TEST(ProxyResolverV8Test, Basic) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("passthrough.js");
EXPECT_EQ(OK, result);
{
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(GURL("http://query.com/path"), &proxy_info,
CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_EQ("http.query.com.path.query.com:80",
proxy_info.proxy_server().ToURI());
}
{
ProxyInfo proxy_info;
int result = resolver.GetProxyForURL(
GURL("ftp://query.com:90/path"), &proxy_info, CompletionCallback(),
NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_EQ("ftp.query.com.90.path.query.com:80",
proxy_info.proxy_server().ToURI());
EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
}
}
TEST(ProxyResolverV8Test, BadReturnType) {
static const char* const filenames[] = {
"return_undefined.js",
"return_integer.js",
"return_function.js",
"return_object.js",
"return_null.js"
};
for (size_t i = 0; i < arraysize(filenames); ++i) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk(filenames[i]);
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
MockJSBindings* bindings = resolver.mock_js_bindings();
EXPECT_EQ(0U, bindings->alerts.size());
ASSERT_EQ(1U, bindings->errors.size());
EXPECT_EQ("FindProxyForURL() did not return a string.",
bindings->errors[0]);
EXPECT_EQ(-1, bindings->errors_line_number[0]);
}
}
TEST(ProxyResolverV8Test, NoEntryPoint) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("no_entrypoint.js");
EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(ERR_FAILED, result);
}
TEST(ProxyResolverV8Test, ParseError) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("missing_close_brace.js");
EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(ERR_FAILED, result);
MockJSBindings* bindings = resolver.mock_js_bindings();
EXPECT_EQ(0U, bindings->alerts.size());
ASSERT_EQ(1U, bindings->errors.size());
EXPECT_EQ("Uncaught SyntaxError: Unexpected end of input",
bindings->errors[0]);
EXPECT_EQ(0, bindings->errors_line_number[0]);
}
TEST(ProxyResolverV8Test, SideEffects) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("side_effects.js");
for (int i = 0; i < 3; ++i) {
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_EQ(base::StringPrintf("sideffect_%d:80", i),
proxy_info.proxy_server().ToURI());
}
result = resolver.SetPacScriptFromDisk("side_effects.js");
EXPECT_EQ(OK, result);
for (int i = 0; i < 3; ++i) {
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_EQ(base::StringPrintf("sideffect_%d:80", i),
proxy_info.proxy_server().ToURI());
}
}
TEST(ProxyResolverV8Test, UnhandledException) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("unhandled_exception.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
MockJSBindings* bindings = resolver.mock_js_bindings();
EXPECT_EQ(0U, bindings->alerts.size());
ASSERT_EQ(1U, bindings->errors.size());
EXPECT_EQ("Uncaught ReferenceError: undefined_variable is not defined",
bindings->errors[0]);
EXPECT_EQ(3, bindings->errors_line_number[0]);
}
TEST(ProxyResolverV8Test, ReturnUnicode) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("return_unicode.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
}
TEST(ProxyResolverV8Test, JavascriptLibrary) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("pac_library_unittest.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI());
EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
}
TEST(ProxyResolverV8Test, NoSetPacScript) {
ProxyResolverV8WithMockBindings resolver;
ProxyInfo proxy_info;
int result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(ERR_FAILED, result);
result = resolver.SetPacScriptFromDisk("direct.js");
EXPECT_EQ(OK, result);
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
resolver.SetPacScript(
ProxyResolverScriptData::FromUTF16(base::string16()),
CompletionCallback());
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(ERR_FAILED, result);
result = resolver.SetPacScriptFromDisk("direct.js");
EXPECT_EQ(OK, result);
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
}
TEST(ProxyResolverV8Test, V8Bindings) {
ProxyResolverV8WithMockBindings resolver;
MockJSBindings* bindings = resolver.mock_js_bindings();
bindings->dns_resolve_result = "127.0.0.1";
int result = resolver.SetPacScriptFromDisk("bindings.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_TRUE(proxy_info.is_direct());
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
ASSERT_EQ(5U, bindings->alerts.size());
EXPECT_EQ("undefined", bindings->alerts[0]);
EXPECT_EQ("null", bindings->alerts[1]);
EXPECT_EQ("undefined", bindings->alerts[2]);
EXPECT_EQ("[object Object]", bindings->alerts[3]);
EXPECT_EQ("exception from calling toString()", bindings->alerts[4]);
ASSERT_EQ(2U, bindings->dns_resolves.size());
EXPECT_EQ("", bindings->dns_resolves[0]);
EXPECT_EQ("arg1", bindings->dns_resolves[1]);
EXPECT_EQ(2, bindings->my_ip_address_count);
EXPECT_EQ(1, bindings->my_ip_address_ex_count);
ASSERT_EQ(2U, bindings->dns_resolves_ex.size());
EXPECT_EQ("is_resolvable", bindings->dns_resolves_ex[0]);
EXPECT_EQ("foobar", bindings->dns_resolves_ex[1]);
}
TEST(ProxyResolverV8Test, BindingCalledDuringInitialization) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("binding_from_global.js");
EXPECT_EQ(OK, result);
MockJSBindings* bindings = resolver.mock_js_bindings();
EXPECT_EQ(1, bindings->my_ip_address_count);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_FALSE(proxy_info.is_direct());
EXPECT_EQ("127.0.0.1:80", proxy_info.proxy_server().ToURI());
EXPECT_EQ(0U, bindings->errors.size());
ASSERT_EQ(0U, bindings->alerts.size());
ASSERT_EQ(0U, bindings->dns_resolves.size());
EXPECT_EQ(0, bindings->my_ip_address_ex_count);
ASSERT_EQ(0U, bindings->dns_resolves_ex.size());
}
TEST(ProxyResolverV8Test, EndsWithCommentNoNewline) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("ends_with_comment.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_FALSE(proxy_info.is_direct());
EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI());
}
TEST(ProxyResolverV8Test, EndsWithStatementNoNewline) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk(
"ends_with_statement_no_semicolon.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_FALSE(proxy_info.is_direct());
EXPECT_EQ("success:3", proxy_info.proxy_server().ToURI());
}
TEST(ProxyResolverV8Test, DNSResolutionFailure) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("dns_fail.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_FALSE(proxy_info.is_direct());
EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI());
}
TEST(ProxyResolverV8Test, DNSResolutionOfInternationDomainName) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("international_domain_names.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_TRUE(proxy_info.is_direct());
MockJSBindings* bindings = resolver.mock_js_bindings();
ASSERT_EQ(1u, bindings->dns_resolves.size());
EXPECT_EQ("xn--bcher-kva.ch", bindings->dns_resolves[0]);
ASSERT_EQ(1u, bindings->dns_resolves_ex.size());
EXPECT_EQ("xn--bcher-kva.ch", bindings->dns_resolves_ex[0]);
}
TEST(ProxyResolverV8Test, IPv6HostnamesNotBracketed) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("resolve_host.js");
EXPECT_EQ(OK, result);
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
GURL("http://[abcd::efff]:99/watsupdawg"), &proxy_info,
CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_TRUE(proxy_info.is_direct());
ASSERT_EQ(1U, resolver.mock_js_bindings()->dns_resolves_ex.size());
EXPECT_EQ("abcd::efff", resolver.mock_js_bindings()->dns_resolves_ex[0]);
}
TEST(ProxyResolverV8Test, Terminate) {
ProxyResolverV8WithMockBindings resolver;
int result = resolver.SetPacScriptFromDisk("terminate.js");
EXPECT_EQ(OK, result);
MockJSBindings* bindings = resolver.mock_js_bindings();
bindings->should_terminate = true;
ProxyInfo proxy_info;
result = resolver.GetProxyForURL(
GURL("http://hang/"), &proxy_info,
CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result);
EXPECT_EQ(1U, resolver.mock_js_bindings()->dns_resolves.size());
EXPECT_GE(2U, resolver.mock_js_bindings()->dns_resolves_ex.size());
EXPECT_GE(1U, bindings->alerts.size());
EXPECT_EQ(1U, bindings->errors.size());
EXPECT_EQ("", bindings->errors[0]);
bindings->errors.clear();
result = resolver.GetProxyForURL(
GURL("http://kittens/"), &proxy_info,
CompletionCallback(), NULL, BoundNetLog());
EXPECT_EQ(OK, result);
EXPECT_EQ(0u, bindings->errors.size());
EXPECT_EQ("kittens:88", proxy_info.proxy_server().ToURI());
}
}
}