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.h"
15 #include "net/proxy/proxy_resolver_factory.h"
16 #include "net/proxy/proxy_resolver_v8.h"
17 #include "net/test/spawned_test_server/spawned_test_server.h"
18 #include "testing/gtest/include/gtest/gtest.h"
21 #include "net/proxy/proxy_resolver_winhttp.h"
22 #elif defined(OS_MACOSX)
23 #include "net/proxy/proxy_resolver_mac.h"
30 // This class holds the URL to use for resolving, and the expected result.
31 // We track the expected result in order to make sure the performance
32 // test is actually resolving URLs properly, otherwise the perf numbers
33 // are meaningless :-)
35 const char* query_url
;
36 const char* expected_result
;
39 // Entry listing which PAC scripts to load, and which URLs to try resolving.
40 // |queries| should be terminated by {NULL, NULL}. A sentinel is used
41 // rather than a length, to simplify using initializer lists.
44 PacQuery queries
[100];
46 // Returns the actual number of entries in |queries| (assumes NULL sentinel).
47 int NumQueries() const;
50 // List of performance tests.
51 static PacPerfTest kPerfTests
[] = {
52 // This test uses an ad-blocker PAC script. This script is very heavily
53 // regular expression oriented, and has no dependencies on the current
54 // IP address, or DNS resolving of hosts.
57 {"http://www.google.com", "DIRECT"},
58 {"http://www.imdb.com/photos/cmsicons/x", "PROXY 0.0.0.0:3421"},
59 {"http://www.imdb.com/x", "DIRECT"},
60 {"http://www.staples.com/", "DIRECT"},
61 {"http://www.staples.com/pixeltracker/x", "PROXY 0.0.0.0:3421"},
62 {"http://www.staples.com/pixel/x", "DIRECT"},
63 {"http://www.foobar.com", "DIRECT"},
64 {"http://www.foobarbaz.com/x/y/z", "DIRECT"},
65 {"http://www.testurl1.com/index.html", "DIRECT"},
66 {"http://www.testurl2.com", "DIRECT"},
67 {"https://www.sample/pirate/arrrrrr", "DIRECT"},
73 int PacPerfTest::NumQueries() const {
74 for (size_t i
= 0; i
< arraysize(queries
); ++i
) {
75 if (queries
[i
].query_url
== NULL
)
78 NOTREACHED(); // Bad definition.
82 // The number of URLs to resolve when testing a PAC script.
83 const int kNumIterations
= 500;
85 // Helper class to run through all the performance tests using the specified
86 // proxy resolver implementation.
87 class PacPerfSuiteRunner
{
89 // |resolver_name| is the label used when logging the results.
90 PacPerfSuiteRunner(ProxyResolverFactory
* factory
,
91 const std::string
& resolver_name
)
93 resolver_name_(resolver_name
),
94 test_server_(SpawnedTestServer::TYPE_HTTP
,
95 SpawnedTestServer::kLocalhost
,
96 base::FilePath(FILE_PATH_LITERAL(
97 "net/data/proxy_resolver_perftest"))) {}
100 ASSERT_TRUE(test_server_
.Start());
101 for (size_t i
= 0; i
< arraysize(kPerfTests
); ++i
) {
102 const PacPerfTest
& test_data
= kPerfTests
[i
];
103 RunTest(test_data
.pac_name
,
105 test_data
.NumQueries());
110 void RunTest(const std::string
& script_name
,
111 const PacQuery
* queries
,
113 scoped_ptr
<ProxyResolver
> resolver
;
114 if (!factory_
->expects_pac_bytes()) {
116 test_server_
.GetURL(std::string("files/") + script_name
);
117 int rv
= factory_
->CreateProxyResolver(
118 ProxyResolverScriptData::FromURL(pac_url
), &resolver
,
119 CompletionCallback(), nullptr);
122 resolver
= LoadPacScriptAndCreateResolver(script_name
);
124 ASSERT_TRUE(resolver
);
126 // Do a query to warm things up. In the case of internal-fetch proxy
127 // resolvers, the first resolve will be slow since it has to download
130 ProxyInfo proxy_info
;
132 resolver
->GetProxyForURL(GURL("http://www.warmup.com"), &proxy_info
,
133 CompletionCallback(), NULL
, BoundNetLog());
134 ASSERT_EQ(OK
, result
);
137 // Start the perf timer.
138 std::string perf_test_name
= resolver_name_
+ "_" + script_name
;
139 base::PerfTimeLogger
timer(perf_test_name
.c_str());
141 for (int i
= 0; i
< kNumIterations
; ++i
) {
142 // Round-robin between URLs to resolve.
143 const PacQuery
& query
= queries
[i
% queries_len
];
146 ProxyInfo proxy_info
;
148 resolver
->GetProxyForURL(GURL(query
.query_url
), &proxy_info
,
149 CompletionCallback(), NULL
, BoundNetLog());
151 // Check that the result was correct. Note that ToPacString() and
152 // ASSERT_EQ() are fast, so they won't skew the results.
153 ASSERT_EQ(OK
, result
);
154 ASSERT_EQ(query
.expected_result
, proxy_info
.ToPacString());
157 // Print how long the test ran for.
161 // Read the PAC script from disk and initialize the proxy resolver with it.
162 scoped_ptr
<ProxyResolver
> LoadPacScriptAndCreateResolver(
163 const std::string
& script_name
) {
165 PathService::Get(base::DIR_SOURCE_ROOT
, &path
);
166 path
= path
.AppendASCII("net");
167 path
= path
.AppendASCII("data");
168 path
= path
.AppendASCII("proxy_resolver_perftest");
169 path
= path
.AppendASCII(script_name
);
171 // Try to read the file from disk.
172 std::string file_contents
;
173 bool ok
= base::ReadFileToString(path
, &file_contents
);
175 // If we can't load the file from disk, something is misconfigured.
176 LOG_IF(ERROR
, !ok
) << "Failed to read file: " << path
.value();
180 // Load the PAC script into the ProxyResolver.
181 scoped_ptr
<ProxyResolver
> resolver
;
182 int rv
= factory_
->CreateProxyResolver(
183 ProxyResolverScriptData::FromUTF8(file_contents
), &resolver
,
184 CompletionCallback(), nullptr);
189 ProxyResolverFactory
* factory_
;
190 std::string resolver_name_
;
191 SpawnedTestServer test_server_
;
195 TEST(ProxyResolverPerfTest
, ProxyResolverWinHttp
) {
196 ProxyResolverFactoryWinHttp factory
;
197 PacPerfSuiteRunner
runner(&factory
, "ProxyResolverWinHttp");
198 runner
.RunAllTests();
200 #elif defined(OS_MACOSX)
201 TEST(ProxyResolverPerfTest
, ProxyResolverMac
) {
202 ProxyResolverFactoryMac factory
;
203 PacPerfSuiteRunner
runner(&factory
, "ProxyResolverMac");
204 runner
.RunAllTests();
208 class MockJSBindings
: public ProxyResolverV8::JSBindings
{
212 void Alert(const base::string16
& message
) override
{ CHECK(false); }
214 bool ResolveDns(const std::string
& host
,
215 ResolveDnsOperation op
,
217 bool* terminate
) override
{
222 void OnError(int line_number
, const base::string16
& message
) override
{
227 class ProxyResolverV8Wrapper
: public ProxyResolver
{
229 ProxyResolverV8Wrapper(scoped_ptr
<ProxyResolverV8
> resolver
,
230 scoped_ptr
<MockJSBindings
> bindings
)
231 : resolver_(resolver
.Pass()), bindings_(bindings
.Pass()) {}
233 int GetProxyForURL(const GURL
& url
,
235 const CompletionCallback
& /*callback*/,
236 RequestHandle
* /*request*/,
237 const BoundNetLog
& net_log
) override
{
238 return resolver_
->GetProxyForURL(url
, results
, bindings_
.get());
241 void CancelRequest(RequestHandle request
) override
{ NOTREACHED(); }
243 LoadState
GetLoadState(RequestHandle request
) const override
{
245 return LOAD_STATE_IDLE
;
249 scoped_ptr
<ProxyResolverV8
> resolver_
;
250 scoped_ptr
<MockJSBindings
> bindings_
;
252 DISALLOW_COPY_AND_ASSIGN(ProxyResolverV8Wrapper
);
255 class ProxyResolverV8Factory
: public ProxyResolverFactory
{
257 ProxyResolverV8Factory() : ProxyResolverFactory(true) {}
258 int CreateProxyResolver(
259 const scoped_refptr
<ProxyResolverScriptData
>& pac_script
,
260 scoped_ptr
<ProxyResolver
>* resolver
,
261 const net::CompletionCallback
& callback
,
262 scoped_ptr
<Request
>* request
) override
{
263 scoped_ptr
<ProxyResolverV8
> v8_resolver
;
264 scoped_ptr
<MockJSBindings
> js_bindings_(new MockJSBindings
);
266 ProxyResolverV8::Create(pac_script
, js_bindings_
.get(), &v8_resolver
);
269 new ProxyResolverV8Wrapper(v8_resolver
.Pass(), js_bindings_
.Pass()));
275 DISALLOW_COPY_AND_ASSIGN(ProxyResolverV8Factory
);
278 TEST(ProxyResolverPerfTest
, ProxyResolverV8
) {
279 base::MessageLoop message_loop
;
280 ProxyResolverV8Factory factory
;
281 PacPerfSuiteRunner
runner(&factory
, "ProxyResolverV8");
282 runner
.RunAllTests();