OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include <utility> | |
6 | |
7 #include "base/base_paths.h" | |
8 #include "base/compiler_specific.h" | |
9 #include "base/files/file_util.h" | |
10 #include "base/macros.h" | |
11 #include "base/message_loop/message_loop.h" | |
12 #include "base/path_service.h" | |
13 #include "base/strings/string_util.h" | |
14 #include "base/test/perf_time_logger.h" | |
15 #include "net/base/net_errors.h" | |
16 #include "net/dns/mock_host_resolver.h" | |
17 #include "net/log/net_log_with_source.h" | |
18 #include "net/proxy/proxy_info.h" | |
19 #include "net/proxy/proxy_resolver.h" | |
20 #include "net/proxy/proxy_resolver_factory.h" | |
21 #include "net/proxy/proxy_resolver_v8.h" | |
22 #include "net/test/embedded_test_server/embedded_test_server.h" | |
23 #include "net/test/gtest_util.h" | |
24 #include "testing/gmock/include/gmock/gmock.h" | |
25 #include "testing/gtest/include/gtest/gtest.h" | |
26 | |
27 #if defined(OS_WIN) | |
28 #include "net/proxy/proxy_resolver_winhttp.h" | |
29 #elif defined(OS_MACOSX) | |
30 #include "net/proxy/proxy_resolver_mac.h" | |
31 #endif | |
32 | |
33 using net::test::IsOk; | |
34 | |
35 namespace net { | |
36 | |
37 namespace { | |
38 | |
39 // This class holds the URL to use for resolving, and the expected result. | |
40 // We track the expected result in order to make sure the performance | |
41 // test is actually resolving URLs properly, otherwise the perf numbers | |
42 // are meaningless :-) | |
43 struct PacQuery { | |
44 const char* query_url; | |
45 const char* expected_result; | |
46 }; | |
47 | |
48 // Entry listing which PAC scripts to load, and which URLs to try resolving. | |
49 // |queries| should be terminated by {NULL, NULL}. A sentinel is used | |
50 // rather than a length, to simplify using initializer lists. | |
51 struct PacPerfTest { | |
52 const char* pac_name; | |
53 PacQuery queries[100]; | |
54 | |
55 // Returns the actual number of entries in |queries| (assumes NULL sentinel). | |
56 int NumQueries() const; | |
57 }; | |
58 | |
59 // List of performance tests. | |
60 static PacPerfTest kPerfTests[] = { | |
61 // This test uses an ad-blocker PAC script. This script is very heavily | |
62 // regular expression oriented, and has no dependencies on the current | |
63 // IP address, or DNS resolving of hosts. | |
64 { "no-ads.pac", | |
65 { // queries: | |
66 {"http://www.google.com", "DIRECT"}, | |
67 {"http://www.imdb.com/photos/cmsicons/x", "PROXY 0.0.0.0:3421"}, | |
68 {"http://www.imdb.com/x", "DIRECT"}, | |
69 {"http://www.staples.com/", "DIRECT"}, | |
70 {"http://www.staples.com/pixeltracker/x", "PROXY 0.0.0.0:3421"}, | |
71 {"http://www.staples.com/pixel/x", "DIRECT"}, | |
72 {"http://www.foobar.com", "DIRECT"}, | |
73 {"http://www.foobarbaz.com/x/y/z", "DIRECT"}, | |
74 {"http://www.testurl1.com/index.html", "DIRECT"}, | |
75 {"http://www.testurl2.com", "DIRECT"}, | |
76 {"https://www.sample/pirate/arrrrrr", "DIRECT"}, | |
77 {NULL, NULL} | |
78 }, | |
79 }, | |
80 }; | |
81 | |
82 int PacPerfTest::NumQueries() const { | |
83 for (size_t i = 0; i < arraysize(queries); ++i) { | |
84 if (queries[i].query_url == NULL) | |
85 return i; | |
86 } | |
87 NOTREACHED(); // Bad definition. | |
88 return 0; | |
89 } | |
90 | |
91 // The number of URLs to resolve when testing a PAC script. | |
92 const int kNumIterations = 500; | |
93 | |
94 // Helper class to run through all the performance tests using the specified | |
95 // proxy resolver implementation. | |
96 class PacPerfSuiteRunner { | |
97 public: | |
98 // |resolver_name| is the label used when logging the results. | |
99 PacPerfSuiteRunner(ProxyResolverFactory* factory, | |
100 const std::string& resolver_name) | |
101 : factory_(factory), resolver_name_(resolver_name) { | |
102 test_server_.ServeFilesFromSourceDirectory( | |
103 "net/data/proxy_resolver_perftest"); | |
104 } | |
105 | |
106 void RunAllTests() { | |
107 ASSERT_TRUE(test_server_.Start()); | |
108 for (size_t i = 0; i < arraysize(kPerfTests); ++i) { | |
109 const PacPerfTest& test_data = kPerfTests[i]; | |
110 RunTest(test_data.pac_name, | |
111 test_data.queries, | |
112 test_data.NumQueries()); | |
113 } | |
114 } | |
115 | |
116 private: | |
117 void RunTest(const std::string& script_name, | |
118 const PacQuery* queries, | |
119 int queries_len) { | |
120 std::unique_ptr<ProxyResolver> resolver; | |
121 if (!factory_->expects_pac_bytes()) { | |
122 GURL pac_url = test_server_.GetURL(std::string("/") + script_name); | |
123 int rv = factory_->CreateProxyResolver( | |
124 ProxyResolverScriptData::FromURL(pac_url), &resolver, | |
125 CompletionCallback(), nullptr); | |
126 EXPECT_THAT(rv, IsOk()); | |
127 } else { | |
128 resolver = LoadPacScriptAndCreateResolver(script_name); | |
129 } | |
130 ASSERT_TRUE(resolver); | |
131 | |
132 // Do a query to warm things up. In the case of internal-fetch proxy | |
133 // resolvers, the first resolve will be slow since it has to download | |
134 // the PAC script. | |
135 { | |
136 ProxyInfo proxy_info; | |
137 int result = resolver->GetProxyForURL(GURL("http://www.warmup.com"), | |
138 &proxy_info, CompletionCallback(), | |
139 NULL, NetLogWithSource()); | |
140 ASSERT_THAT(result, IsOk()); | |
141 } | |
142 | |
143 // Start the perf timer. | |
144 std::string perf_test_name = resolver_name_ + "_" + script_name; | |
145 base::PerfTimeLogger timer(perf_test_name.c_str()); | |
146 | |
147 for (int i = 0; i < kNumIterations; ++i) { | |
148 // Round-robin between URLs to resolve. | |
149 const PacQuery& query = queries[i % queries_len]; | |
150 | |
151 // Resolve. | |
152 ProxyInfo proxy_info; | |
153 int result = resolver->GetProxyForURL(GURL(query.query_url), &proxy_info, | |
154 CompletionCallback(), NULL, | |
155 NetLogWithSource()); | |
156 | |
157 // Check that the result was correct. Note that ToPacString() and | |
158 // ASSERT_EQ() are fast, so they won't skew the results. | |
159 ASSERT_THAT(result, IsOk()); | |
160 ASSERT_EQ(query.expected_result, proxy_info.ToPacString()); | |
161 } | |
162 | |
163 // Print how long the test ran for. | |
164 timer.Done(); | |
165 } | |
166 | |
167 // Read the PAC script from disk and initialize the proxy resolver with it. | |
168 std::unique_ptr<ProxyResolver> LoadPacScriptAndCreateResolver( | |
169 const std::string& script_name) { | |
170 base::FilePath path; | |
171 PathService::Get(base::DIR_SOURCE_ROOT, &path); | |
172 path = path.AppendASCII("net"); | |
173 path = path.AppendASCII("data"); | |
174 path = path.AppendASCII("proxy_resolver_perftest"); | |
175 path = path.AppendASCII(script_name); | |
176 | |
177 // Try to read the file from disk. | |
178 std::string file_contents; | |
179 bool ok = base::ReadFileToString(path, &file_contents); | |
180 | |
181 // If we can't load the file from disk, something is misconfigured. | |
182 LOG_IF(ERROR, !ok) << "Failed to read file: " << path.value(); | |
183 if (!ok) | |
184 return nullptr; | |
185 | |
186 // Load the PAC script into the ProxyResolver. | |
187 std::unique_ptr<ProxyResolver> resolver; | |
188 int rv = factory_->CreateProxyResolver( | |
189 ProxyResolverScriptData::FromUTF8(file_contents), &resolver, | |
190 CompletionCallback(), nullptr); | |
191 EXPECT_THAT(rv, IsOk()); | |
192 return resolver; | |
193 } | |
194 | |
195 ProxyResolverFactory* factory_; | |
196 std::string resolver_name_; | |
197 EmbeddedTestServer test_server_; | |
198 }; | |
199 | |
200 #if defined(OS_WIN) | |
201 TEST(ProxyResolverPerfTest, ProxyResolverWinHttp) { | |
202 ProxyResolverFactoryWinHttp factory; | |
203 PacPerfSuiteRunner runner(&factory, "ProxyResolverWinHttp"); | |
204 runner.RunAllTests(); | |
205 } | |
206 #elif defined(OS_MACOSX) | |
207 TEST(ProxyResolverPerfTest, ProxyResolverMac) { | |
208 ProxyResolverFactoryMac factory; | |
209 PacPerfSuiteRunner runner(&factory, "ProxyResolverMac"); | |
210 runner.RunAllTests(); | |
211 } | |
212 #endif | |
213 | |
214 class MockJSBindings : public ProxyResolverV8::JSBindings { | |
215 public: | |
216 MockJSBindings() {} | |
217 | |
218 void Alert(const base::string16& message) override { CHECK(false); } | |
219 | |
220 bool ResolveDns(const std::string& host, | |
221 ResolveDnsOperation op, | |
222 std::string* output, | |
223 bool* terminate) override { | |
224 CHECK(false); | |
225 return false; | |
226 } | |
227 | |
228 void OnError(int line_number, const base::string16& message) override { | |
229 CHECK(false); | |
230 } | |
231 }; | |
232 | |
233 class ProxyResolverV8Wrapper : public ProxyResolver { | |
234 public: | |
235 ProxyResolverV8Wrapper(std::unique_ptr<ProxyResolverV8> resolver, | |
236 std::unique_ptr<MockJSBindings> bindings) | |
237 : resolver_(std::move(resolver)), bindings_(std::move(bindings)) {} | |
238 | |
239 int GetProxyForURL(const GURL& url, | |
240 ProxyInfo* results, | |
241 const CompletionCallback& /*callback*/, | |
242 std::unique_ptr<Request>* /*request*/, | |
243 const NetLogWithSource& net_log) override { | |
244 return resolver_->GetProxyForURL(url, results, bindings_.get()); | |
245 } | |
246 | |
247 private: | |
248 std::unique_ptr<ProxyResolverV8> resolver_; | |
249 std::unique_ptr<MockJSBindings> bindings_; | |
250 | |
251 DISALLOW_COPY_AND_ASSIGN(ProxyResolverV8Wrapper); | |
252 }; | |
253 | |
254 class ProxyResolverV8Factory : public ProxyResolverFactory { | |
255 public: | |
256 ProxyResolverV8Factory() : ProxyResolverFactory(true) {} | |
257 int CreateProxyResolver( | |
258 const scoped_refptr<ProxyResolverScriptData>& pac_script, | |
259 std::unique_ptr<ProxyResolver>* resolver, | |
260 const net::CompletionCallback& callback, | |
261 std::unique_ptr<Request>* request) override { | |
262 std::unique_ptr<ProxyResolverV8> v8_resolver; | |
263 std::unique_ptr<MockJSBindings> js_bindings_(new MockJSBindings); | |
264 int result = | |
265 ProxyResolverV8::Create(pac_script, js_bindings_.get(), &v8_resolver); | |
266 if (result == OK) { | |
267 resolver->reset(new ProxyResolverV8Wrapper(std::move(v8_resolver), | |
268 std::move(js_bindings_))); | |
269 } | |
270 return result; | |
271 } | |
272 | |
273 private: | |
274 DISALLOW_COPY_AND_ASSIGN(ProxyResolverV8Factory); | |
275 }; | |
276 | |
277 TEST(ProxyResolverPerfTest, ProxyResolverV8) { | |
278 base::MessageLoop message_loop; | |
279 ProxyResolverV8Factory factory; | |
280 PacPerfSuiteRunner runner(&factory, "ProxyResolverV8"); | |
281 runner.RunAllTests(); | |
282 } | |
283 | |
284 } // namespace | |
285 | |
286 } // namespace net | |
OLD | NEW |