Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: net/proxy/proxy_resolver_js_bindings_unittest.cc

Issue 11885009: Improve performance of proxy resolver by tracing DNS dependencies. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: rebase off trunk Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "net/proxy/proxy_resolver_js_bindings.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/string_util.h"
10 #include "net/base/address_list.h"
11 #include "net/base/host_cache.h"
12 #include "net/base/mock_host_resolver.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/net_log.h"
15 #include "net/base/net_log_unittest.h"
16 #include "net/base/net_util.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/proxy/proxy_resolver_request_context.h"
19 #include "net/proxy/sync_host_resolver.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace net {
23
24 namespace {
25
26 // This is a HostResolver that synchronously resolves all hosts to the
27 // following address list of length 3:
28 // 192.168.1.1
29 // 172.22.34.1
30 // 200.100.1.2
31 class MockHostResolverWithMultipleResults : public SyncHostResolver {
32 public:
33 // HostResolver methods:
34 virtual int Resolve(const HostResolver::RequestInfo& info,
35 AddressList* addresses,
36 const BoundNetLog& bound_net_log) OVERRIDE {
37 return ParseAddressList("192.168.1.1,172.22.34.1,200.100.1.2", "",
38 addresses);
39 }
40
41 virtual void Shutdown() OVERRIDE {}
42
43 private:
44 virtual ~MockHostResolverWithMultipleResults() {}
45 };
46
47 class MockFailingHostResolver : public SyncHostResolver {
48 public:
49 MockFailingHostResolver() : count_(0) {}
50
51 // HostResolver methods:
52 virtual int Resolve(const HostResolver::RequestInfo& info,
53 AddressList* addresses,
54 const BoundNetLog& bound_net_log) OVERRIDE {
55 count_++;
56 return ERR_NAME_NOT_RESOLVED;
57 }
58
59 virtual void Shutdown() OVERRIDE {}
60
61 // Returns the number of times Resolve() has been called.
62 int count() const { return count_; }
63 void ResetCount() { count_ = 0; }
64
65 private:
66 int count_;
67 };
68
69 class MockSyncHostResolver : public SyncHostResolver {
70 public:
71 MockSyncHostResolver() {
72 resolver_.set_synchronous_mode(true);
73 }
74
75 virtual int Resolve(const HostResolver::RequestInfo& info,
76 AddressList* addresses,
77 const BoundNetLog& bound_net_log) OVERRIDE {
78 return resolver_.Resolve(info, addresses, CompletionCallback(), NULL,
79 bound_net_log);
80 }
81
82 virtual void Shutdown() OVERRIDE {}
83
84 RuleBasedHostResolverProc* rules() {
85 return resolver_.rules();
86 }
87
88 private:
89 MockHostResolver resolver_;
90 };
91
92 TEST(ProxyResolverJSBindingsTest, DnsResolve) {
93 MockSyncHostResolver* host_resolver = new MockSyncHostResolver;
94
95 // Get a hold of a DefaultJSBindings* (it is a hidden impl class).
96 scoped_ptr<ProxyResolverJSBindings> bindings(
97 ProxyResolverJSBindings::CreateDefault(host_resolver, NULL, NULL));
98
99 std::string ip_address;
100
101 // Empty string is not considered a valid host (even though on some systems
102 // requesting this will resolve to localhost).
103 host_resolver->rules()->AddSimulatedFailure("");
104 EXPECT_FALSE(bindings->DnsResolve("", &ip_address));
105
106 // Should call through to the HostResolver.
107 host_resolver->rules()->AddRule("google.com", "192.168.1.1");
108 EXPECT_TRUE(bindings->DnsResolve("google.com", &ip_address));
109 EXPECT_EQ("192.168.1.1", ip_address);
110
111 // Resolve failures should give empty string.
112 host_resolver->rules()->AddSimulatedFailure("fail");
113 EXPECT_FALSE(bindings->DnsResolve("fail", &ip_address));
114
115 // TODO(eroman): would be nice to have an IPV6 test here too, but that
116 // won't work on all systems.
117 }
118
119 TEST(ProxyResolverJSBindingsTest, MyIpAddress) {
120 MockSyncHostResolver* host_resolver = new MockSyncHostResolver;
121
122 // Get a hold of a DefaultJSBindings* (it is a hidden impl class).
123 scoped_ptr<ProxyResolverJSBindings> bindings(
124 ProxyResolverJSBindings::CreateDefault(host_resolver, NULL, NULL));
125
126 // Our IP address is always going to be 127.0.0.1, since we are using a
127 // mock host resolver.
128 std::string my_ip_address;
129 EXPECT_TRUE(bindings->MyIpAddress(&my_ip_address));
130
131 EXPECT_EQ("127.0.0.1", my_ip_address);
132 }
133
134 // Tests that the regular PAC functions restrict results to IPv4,
135 // but that the Microsoft extensions to PAC do not. We test this
136 // by seeing whether ADDRESS_FAMILY_IPV4 or ADDRESS_FAMILY_UNSPECIFIED
137 // was passed into to the host resolver.
138 //
139 // Restricted to IPv4 address family:
140 // myIpAddress()
141 // dnsResolve()
142 //
143 // Unrestricted address family:
144 // myIpAddressEx()
145 // dnsResolveEx()
146 TEST(ProxyResolverJSBindingsTest, RestrictAddressFamily) {
147 MockSyncHostResolver* host_resolver = new MockSyncHostResolver;
148
149 // Get a hold of a DefaultJSBindings* (it is a hidden impl class).
150 scoped_ptr<ProxyResolverJSBindings> bindings(
151 ProxyResolverJSBindings::CreateDefault(host_resolver, NULL, NULL));
152
153 // Make it so requests resolve to particular address patterns based on family:
154 // IPV4_ONLY --> 192.168.1.*
155 // UNSPECIFIED --> 192.168.2.1
156 host_resolver->rules()->AddRuleForAddressFamily(
157 "foo", ADDRESS_FAMILY_IPV4, "192.168.1.1");
158 host_resolver->rules()->AddRuleForAddressFamily(
159 "*", ADDRESS_FAMILY_IPV4, "192.168.1.2");
160 host_resolver->rules()->AddRuleForAddressFamily(
161 "foo", ADDRESS_FAMILY_UNSPECIFIED, "192.168.2.1");
162 host_resolver->rules()->AddRuleForAddressFamily(
163 "*", ADDRESS_FAMILY_UNSPECIFIED, "192.168.2.2");
164
165 // Verify that our mock setups works as expected, and we get different results
166 // depending if the address family was IPV4_ONLY or not.
167 HostResolver::RequestInfo info(HostPortPair("foo", 80));
168 AddressList address_list;
169 EXPECT_EQ(OK, host_resolver->Resolve(info, &address_list, BoundNetLog()));
170 ASSERT_FALSE(address_list.empty());
171 EXPECT_EQ("192.168.2.1", address_list.front().ToStringWithoutPort());
172
173 info.set_address_family(ADDRESS_FAMILY_IPV4);
174 EXPECT_EQ(OK, host_resolver->Resolve(info, &address_list, BoundNetLog()));
175 ASSERT_FALSE(address_list.empty());
176 EXPECT_EQ("192.168.1.1", address_list.front().ToStringWithoutPort());
177
178 std::string ip_address;
179 // Now the actual test.
180 EXPECT_TRUE(bindings->MyIpAddress(&ip_address));
181 EXPECT_EQ("192.168.1.2", ip_address); // IPv4 restricted.
182
183 EXPECT_TRUE(bindings->DnsResolve("foo", &ip_address));
184 EXPECT_EQ("192.168.1.1", ip_address); // IPv4 restricted.
185
186 EXPECT_TRUE(bindings->DnsResolve("foo2", &ip_address));
187 EXPECT_EQ("192.168.1.2", ip_address); // IPv4 restricted.
188
189 EXPECT_TRUE(bindings->MyIpAddressEx(&ip_address));
190 EXPECT_EQ("192.168.2.2", ip_address); // Unrestricted.
191
192 EXPECT_TRUE(bindings->DnsResolveEx("foo", &ip_address));
193 EXPECT_EQ("192.168.2.1", ip_address); // Unrestricted.
194
195 EXPECT_TRUE(bindings->DnsResolveEx("foo2", &ip_address));
196 EXPECT_EQ("192.168.2.2", ip_address); // Unrestricted.
197 }
198
199 // Test that myIpAddressEx() and dnsResolveEx() both return a semi-colon
200 // separated list of addresses (as opposed to the non-Ex versions which
201 // just return the first result).
202 TEST(ProxyResolverJSBindingsTest, ExFunctionsReturnList) {
203 SyncHostResolver* host_resolver =
204 new MockHostResolverWithMultipleResults;
205
206 // Get a hold of a DefaultJSBindings* (it is a hidden impl class).
207 scoped_ptr<ProxyResolverJSBindings> bindings(
208 ProxyResolverJSBindings::CreateDefault(host_resolver, NULL, NULL));
209
210 std::string ip_addresses;
211
212 EXPECT_TRUE(bindings->MyIpAddressEx(&ip_addresses));
213 EXPECT_EQ("192.168.1.1;172.22.34.1;200.100.1.2", ip_addresses);
214
215 EXPECT_TRUE(bindings->DnsResolveEx("FOO", &ip_addresses));
216 EXPECT_EQ("192.168.1.1;172.22.34.1;200.100.1.2", ip_addresses);
217 }
218
219 TEST(ProxyResolverJSBindingsTest, PerRequestDNSCache) {
220 MockFailingHostResolver* host_resolver = new MockFailingHostResolver;
221
222 // Get a hold of a DefaultJSBindings* (it is a hidden impl class).
223 scoped_ptr<ProxyResolverJSBindings> bindings(
224 ProxyResolverJSBindings::CreateDefault(host_resolver, NULL, NULL));
225
226 std::string ip_address;
227
228 // Call DnsResolve() 4 times for the same hostname -- this should issue
229 // 4 separate calls to the underlying host resolver, since there is no
230 // current request context.
231 EXPECT_FALSE(bindings->DnsResolve("foo", &ip_address));
232 EXPECT_FALSE(bindings->DnsResolve("foo", &ip_address));
233 EXPECT_FALSE(bindings->DnsResolve("foo", &ip_address));
234 EXPECT_FALSE(bindings->DnsResolve("foo", &ip_address));
235 EXPECT_EQ(4, host_resolver->count());
236
237 host_resolver->ResetCount();
238
239 // Now setup a per-request context, and try the same experiment -- we
240 // expect the underlying host resolver to receive only 1 request this time,
241 // since it will service the others from the per-request DNS cache.
242 const unsigned kMaxCacheEntries = 50;
243 HostCache cache(kMaxCacheEntries);
244 ProxyResolverRequestContext context(NULL, &cache);
245 bindings->set_current_request_context(&context);
246
247 EXPECT_FALSE(bindings->DnsResolve("foo", &ip_address));
248 EXPECT_FALSE(bindings->DnsResolve("foo", &ip_address));
249 EXPECT_FALSE(bindings->DnsResolve("foo", &ip_address));
250 EXPECT_FALSE(bindings->DnsResolve("foo", &ip_address));
251 EXPECT_EQ(1, host_resolver->count());
252
253 host_resolver->ResetCount();
254
255 // The "Ex" version shares this same cache, however since the flags
256 // are different it won't reuse this particular entry.
257 EXPECT_FALSE(bindings->DnsResolveEx("foo", &ip_address));
258 EXPECT_EQ(1, host_resolver->count());
259 EXPECT_FALSE(bindings->DnsResolveEx("foo", &ip_address));
260 EXPECT_FALSE(bindings->DnsResolveEx("foo", &ip_address));
261 EXPECT_EQ(1, host_resolver->count());
262
263 bindings->set_current_request_context(NULL);
264 }
265
266 // Test that when a binding is called, it logs to the per-request NetLog.
267 TEST(ProxyResolverJSBindingsTest, NetLog) {
268 MockFailingHostResolver* host_resolver = new MockFailingHostResolver;
269
270 CapturingNetLog global_log;
271
272 // Get a hold of a DefaultJSBindings* (it is a hidden impl class).
273 scoped_ptr<ProxyResolverJSBindings> bindings(
274 ProxyResolverJSBindings::CreateDefault(
275 host_resolver, &global_log, NULL));
276
277 // Attach a capturing NetLog as the current request's log stream.
278 CapturingNetLog log;
279 BoundNetLog bound_log(BoundNetLog::Make(&log, NetLog::SOURCE_NONE));
280 ProxyResolverRequestContext context(&bound_log, NULL);
281 bindings->set_current_request_context(&context);
282
283 std::string ip_address;
284 net::CapturingNetLog::CapturedEntryList entries;
285 log.GetEntries(&entries);
286 ASSERT_EQ(0u, entries.size());
287
288 // Call all the bindings. Each call should be logging something to
289 // our NetLog.
290
291 bindings->MyIpAddress(&ip_address);
292
293 log.GetEntries(&entries);
294 EXPECT_EQ(2u, entries.size());
295 EXPECT_TRUE(LogContainsBeginEvent(
296 entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS));
297 EXPECT_TRUE(LogContainsEndEvent(
298 entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS));
299
300 bindings->MyIpAddressEx(&ip_address);
301
302 log.GetEntries(&entries);
303 EXPECT_EQ(4u, entries.size());
304 EXPECT_TRUE(LogContainsBeginEvent(
305 entries, 2, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX));
306 EXPECT_TRUE(LogContainsEndEvent(
307 entries, 3, NetLog::TYPE_PAC_JAVASCRIPT_MY_IP_ADDRESS_EX));
308
309 bindings->DnsResolve("foo", &ip_address);
310
311 log.GetEntries(&entries);
312 EXPECT_EQ(6u, entries.size());
313 EXPECT_TRUE(LogContainsBeginEvent(
314 entries, 4, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE));
315 EXPECT_TRUE(LogContainsEndEvent(
316 entries, 5, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE));
317
318 bindings->DnsResolveEx("foo", &ip_address);
319
320 log.GetEntries(&entries);
321 EXPECT_EQ(8u, entries.size());
322 EXPECT_TRUE(LogContainsBeginEvent(
323 entries, 6, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX));
324 EXPECT_TRUE(LogContainsEndEvent(
325 entries, 7, NetLog::TYPE_PAC_JAVASCRIPT_DNS_RESOLVE_EX));
326
327 // Nothing has been emitted globally yet.
328 net::CapturingNetLog::CapturedEntryList global_log_entries;
329 global_log.GetEntries(&global_log_entries);
330 EXPECT_EQ(0u, global_log_entries.size());
331
332 bindings->OnError(30, string16());
333
334 log.GetEntries(&entries);
335 EXPECT_EQ(9u, entries.size());
336 EXPECT_TRUE(LogContainsEvent(
337 entries, 8, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
338 NetLog::PHASE_NONE));
339
340 // We also emit errors to the top-level log stream.
341 global_log.GetEntries(&global_log_entries);
342 EXPECT_EQ(1u, global_log_entries.size());
343 EXPECT_TRUE(LogContainsEvent(
344 global_log_entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
345 NetLog::PHASE_NONE));
346
347 bindings->Alert(string16());
348
349 log.GetEntries(&entries);
350 EXPECT_EQ(10u, entries.size());
351 EXPECT_TRUE(LogContainsEvent(
352 entries, 9, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
353 NetLog::PHASE_NONE));
354
355 // We also emit javascript alerts to the top-level log stream.
356 global_log.GetEntries(&global_log_entries);
357 EXPECT_EQ(2u, global_log_entries.size());
358 EXPECT_TRUE(LogContainsEvent(
359 global_log_entries, 1, NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
360 NetLog::PHASE_NONE));
361 }
362
363 } // namespace
364
365 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698