1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/base_paths.h"
6 #include "base/compiler_specific.h"
7 #include "base/files/file_util.h"
8 #include "base/path_service.h"
9 #include "base/strings/string_util.h"
10 #include "base/test/perf_time_logger.h"
11 #include "net/base/net_errors.h"
12 #include "net/dns/mock_host_resolver.h"
13 #include "net/proxy/proxy_info.h"
14 #include "net/proxy/proxy_resolver_v8.h"
15 #include "net/test/spawned_test_server/spawned_test_server.h"
16 #include "testing/gtest/include/gtest/gtest.h"
19 #include "net/proxy/proxy_resolver_winhttp.h"
20 #elif defined(OS_MACOSX)
21 #include "net/proxy/proxy_resolver_mac.h"
24 // This class holds the URL to use for resolving, and the expected result.
25 // We track the expected result in order to make sure the performance
26 // test is actually resolving URLs properly, otherwise the perf numbers
27 // are meaningless :-)
29 const char* query_url
;
30 const char* expected_result
;
33 // Entry listing which PAC scripts to load, and which URLs to try resolving.
34 // |queries| should be terminated by {NULL, NULL}. A sentinel is used
35 // rather than a length, to simplify using initializer lists.
38 PacQuery queries
[100];
40 // Returns the actual number of entries in |queries| (assumes NULL sentinel).
41 int NumQueries() const;
44 // List of performance tests.
45 static PacPerfTest kPerfTests
[] = {
46 // This test uses an ad-blocker PAC script. This script is very heavily
47 // regular expression oriented, and has no dependencies on the current
48 // IP address, or DNS resolving of hosts.
51 {"http://www.google.com", "DIRECT"},
52 {"http://www.imdb.com/photos/cmsicons/x", "PROXY 0.0.0.0:3421"},
53 {"http://www.imdb.com/x", "DIRECT"},
54 {"http://www.staples.com/", "DIRECT"},
55 {"http://www.staples.com/pixeltracker/x", "PROXY 0.0.0.0:3421"},
56 {"http://www.staples.com/pixel/x", "DIRECT"},
57 {"http://www.foobar.com", "DIRECT"},
58 {"http://www.foobarbaz.com/x/y/z", "DIRECT"},
59 {"http://www.testurl1.com/index.html", "DIRECT"},
60 {"http://www.testurl2.com", "DIRECT"},
61 {"https://www.sample/pirate/arrrrrr", "DIRECT"},
67 int PacPerfTest::NumQueries() const {
68 for (size_t i
= 0; i
< arraysize(queries
); ++i
) {
69 if (queries
[i
].query_url
== NULL
)
72 NOTREACHED(); // Bad definition.
76 // The number of URLs to resolve when testing a PAC script.
77 const int kNumIterations
= 500;
79 // Helper class to run through all the performance tests using the specified
80 // proxy resolver implementation.
81 class PacPerfSuiteRunner
{
83 // |resolver_name| is the label used when logging the results.
84 PacPerfSuiteRunner(net::ProxyResolver
* resolver
,
85 const std::string
& resolver_name
)
86 : resolver_(resolver
),
87 resolver_name_(resolver_name
),
89 net::SpawnedTestServer::TYPE_HTTP
,
90 net::SpawnedTestServer::kLocalhost
,
92 FILE_PATH_LITERAL("net/data/proxy_resolver_perftest"))) {
96 ASSERT_TRUE(test_server_
.Start());
97 for (size_t i
= 0; i
< arraysize(kPerfTests
); ++i
) {
98 const PacPerfTest
& test_data
= kPerfTests
[i
];
99 RunTest(test_data
.pac_name
,
101 test_data
.NumQueries());
106 void RunTest(const std::string
& script_name
,
107 const PacQuery
* queries
,
109 if (!resolver_
->expects_pac_bytes()) {
111 test_server_
.GetURL(std::string("files/") + script_name
);
112 int rv
= resolver_
->SetPacScript(
113 net::ProxyResolverScriptData::FromURL(pac_url
),
114 net::CompletionCallback());
115 EXPECT_EQ(net::OK
, rv
);
117 LoadPacScriptIntoResolver(script_name
);
120 // Do a query to warm things up. In the case of internal-fetch proxy
121 // resolvers, the first resolve will be slow since it has to download
124 net::ProxyInfo proxy_info
;
125 int result
= resolver_
->GetProxyForURL(
126 GURL("http://www.warmup.com"), &proxy_info
, net::CompletionCallback(),
127 NULL
, net::BoundNetLog());
128 ASSERT_EQ(net::OK
, result
);
131 // Start the perf timer.
132 std::string perf_test_name
= resolver_name_
+ "_" + script_name
;
133 base::PerfTimeLogger
timer(perf_test_name
.c_str());
135 for (int i
= 0; i
< kNumIterations
; ++i
) {
136 // Round-robin between URLs to resolve.
137 const PacQuery
& query
= queries
[i
% queries_len
];
140 net::ProxyInfo proxy_info
;
141 int result
= resolver_
->GetProxyForURL(
142 GURL(query
.query_url
), &proxy_info
, net::CompletionCallback(), NULL
,
145 // Check that the result was correct. Note that ToPacString() and
146 // ASSERT_EQ() are fast, so they won't skew the results.
147 ASSERT_EQ(net::OK
, result
);
148 ASSERT_EQ(query
.expected_result
, proxy_info
.ToPacString());
151 // Print how long the test ran for.
155 // Read the PAC script from disk and initialize the proxy resolver with it.
156 void LoadPacScriptIntoResolver(const std::string
& script_name
) {
158 PathService::Get(base::DIR_SOURCE_ROOT
, &path
);
159 path
= path
.AppendASCII("net");
160 path
= path
.AppendASCII("data");
161 path
= path
.AppendASCII("proxy_resolver_perftest");
162 path
= path
.AppendASCII(script_name
);
164 // Try to read the file from disk.
165 std::string file_contents
;
166 bool ok
= base::ReadFileToString(path
, &file_contents
);
168 // If we can't load the file from disk, something is misconfigured.
169 LOG_IF(ERROR
, !ok
) << "Failed to read file: " << path
.value();
172 // Load the PAC script into the ProxyResolver.
173 int rv
= resolver_
->SetPacScript(
174 net::ProxyResolverScriptData::FromUTF8(file_contents
),
175 net::CompletionCallback());
176 EXPECT_EQ(net::OK
, rv
);
179 net::ProxyResolver
* resolver_
;
180 std::string resolver_name_
;
181 net::SpawnedTestServer test_server_
;
185 TEST(ProxyResolverPerfTest
, ProxyResolverWinHttp
) {
186 net::ProxyResolverWinHttp resolver
;
187 PacPerfSuiteRunner
runner(&resolver
, "ProxyResolverWinHttp");
188 runner
.RunAllTests();
190 #elif defined(OS_MACOSX)
191 TEST(ProxyResolverPerfTest
, ProxyResolverMac
) {
192 net::ProxyResolverMac resolver
;
193 PacPerfSuiteRunner
runner(&resolver
, "ProxyResolverMac");
194 runner
.RunAllTests();
198 class MockJSBindings
: public net::ProxyResolverV8::JSBindings
{
202 void Alert(const base::string16
& message
) override
{ CHECK(false); }
204 bool ResolveDns(const std::string
& host
,
205 ResolveDnsOperation op
,
207 bool* terminate
) override
{
212 void OnError(int line_number
, const base::string16
& message
) override
{
217 TEST(ProxyResolverPerfTest
, ProxyResolverV8
) {
218 MockJSBindings js_bindings
;
219 net::ProxyResolverV8 resolver
;
220 resolver
.set_js_bindings(&js_bindings
);
221 PacPerfSuiteRunner
runner(&resolver
, "ProxyResolverV8");
222 runner
.RunAllTests();