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

Side by Side Diff: chrome/browser/net/dns_master_unittest.cc

Issue 15076: Clean up dns prefetch code, and also port it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: use scoper for init & free Created 11 years, 10 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Multi-threaded tests of DnsMaster and DnsPrefetch slave functionality.
6
7 #include <time.h> 5 #include <time.h>
8 #include <ws2tcpip.h>
9 #include <Wspiapi.h> // Needed for win2k compatibility
10 6
11 #include <algorithm> 7 #include <algorithm>
12 #include <map>
13 #include <sstream> 8 #include <sstream>
14 #include <string> 9 #include <string>
15 10
11 #include "base/message_loop.h"
16 #include "base/platform_thread.h" 12 #include "base/platform_thread.h"
17 #include "base/spin_wait.h" 13 #include "base/scoped_ptr.h"
14 #include "base/timer.h"
18 #include "chrome/browser/net/dns_global.h" 15 #include "chrome/browser/net/dns_global.h"
19 #include "chrome/browser/net/dns_host_info.h" 16 #include "chrome/browser/net/dns_host_info.h"
20 #include "chrome/browser/net/dns_slave.h" 17 #include "chrome/common/net/dns.h"
18 #include "net/base/address_list.h"
19 #include "net/base/host_resolver.h"
20 #include "net/base/host_resolver_unittest.h"
21 #include "net/base/winsock_init.h" 21 #include "net/base/winsock_init.h"
22 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
23 23
24
25 using base::Time; 24 using base::Time;
26 using base::TimeDelta; 25 using base::TimeDelta;
27 26
28 namespace { 27 namespace chrome_browser_net {
28
29 class WaitForResolutionHelper;
30
31 typedef base::RepeatingTimer<WaitForResolutionHelper> HelperTimer;
32
33 class WaitForResolutionHelper {
34 public:
35 WaitForResolutionHelper(DnsMaster* master, const NameList& hosts,
36 HelperTimer* timer)
37 : master_(master),
38 hosts_(hosts),
39 timer_(timer) {
40 }
41
42 void Run() {
43 for (NameList::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
44 if (master_->GetResolutionDuration(*i) == DnsHostInfo::kNullDuration)
45 return; // We don't have resolution for that host.
46
47 // When all hostnames have been resolved, exit the loop.
48 timer_->Stop();
49 MessageLoop::current()->Quit();
50 delete timer_;
51 delete this;
52 }
53
54 private:
55 DnsMaster* master_;
56 const NameList hosts_;
57 HelperTimer* timer_;
58 };
29 59
30 class DnsMasterTest : public testing::Test { 60 class DnsMasterTest : public testing::Test {
61 public:
62 DnsMasterTest()
63 : mapper_(new net::RuleBasedHostMapper()),
64 scoped_mapper_(mapper_.get()) {
65 }
66
67 protected:
68 virtual void SetUp() {
69 #if defined(OS_WIN)
70 net::EnsureWinsockInit();
71 #endif
72 mapper_->AddRuleWithLatency("www.google.com", "127.0.0.1", 50);
73 mapper_->AddRuleWithLatency("gmail.google.com.com", "127.0.0.1", 70);
74 mapper_->AddRuleWithLatency("mail.google.com", "127.0.0.1", 44);
75 mapper_->AddRuleWithLatency("gmail.com", "127.0.0.1", 63);
76 }
77
78 void WaitForResolution(DnsMaster* master, const NameList& hosts) {
79 HelperTimer* timer = new HelperTimer();
80 timer->Start(TimeDelta::FromMilliseconds(100),
81 new WaitForResolutionHelper(master, hosts, timer),
82 &WaitForResolutionHelper::Run);
83 MessageLoop::current()->Run();
84 }
85
86 private:
87 MessageLoop loop;
88 scoped_refptr<net::RuleBasedHostMapper> mapper_;
89 net::ScopedHostMapper scoped_mapper_;
31 }; 90 };
32 91
33 typedef chrome_browser_net::DnsMaster DnsMaster;
34 typedef chrome_browser_net::DnsPrefetcherInit DnsPrefetcherInit;
35 typedef chrome_browser_net::DnsHostInfo DnsHostInfo;
36 typedef chrome_browser_net::NameList NameList;
37
38
39 //------------------------------------------------------------------------------
40 // Provide network function stubs to run tests offline (and avoid the variance
41 // of real DNS lookups.
42 //------------------------------------------------------------------------------
43
44 static void __stdcall fake_free_addr_info(struct addrinfo* ai) {
45 // Kill off the dummy results.
46 EXPECT_TRUE(NULL != ai);
47 delete ai;
48 }
49
50 static int __stdcall fake_get_addr_info(const char* nodename,
51 const char* servname,
52 const struct addrinfo* hints,
53 struct addrinfo** result) {
54 static Lock lock;
55 int duration;
56 bool was_found;
57 std::string hostname(nodename);
58 // Dummy up *some* return results to pass along.
59 *result = new addrinfo;
60 EXPECT_TRUE(NULL != *result);
61 {
62 AutoLock autolock(lock);
63
64 static bool initialized = false;
65 typedef std::map<std::string, int> Latency;
66 static Latency latency;
67 static std::map<std::string, bool> found;
68 if (!initialized) {
69 initialized = true;
70 // List all known hostnames
71 latency["www.google.com"] = 50;
72 latency["gmail.google.com.com"] = 70;
73 latency["mail.google.com"] = 44;
74 latency["gmail.com"] = 63;
75
76 for (Latency::iterator it = latency.begin(); latency.end() != it; it++) {
77 found[it->first] = true;
78 }
79 } // End static initialization
80
81 was_found = found[hostname];
82
83 if (latency.end() != latency.find(hostname)) {
84 duration = latency[hostname];
85 } else {
86 duration = 500;
87 }
88 // Change latency to simulate cache warming (next latency will be short).
89 latency[hostname] = 1;
90 } // Release lock.
91
92 PlatformThread::Sleep(duration);
93
94 return was_found ? 0 : WSAHOST_NOT_FOUND;
95 }
96
97 static void SetupNetworkInfrastructure() {
98 bool kUseFakeNetwork = true;
99 if (kUseFakeNetwork)
100 chrome_browser_net::SetAddrinfoCallbacks(fake_get_addr_info,
101 fake_free_addr_info);
102 }
103
104 //------------------------------------------------------------------------------ 92 //------------------------------------------------------------------------------
105 // Provide a function to create unique (nonexistant) domains at *every* call. 93 // Provide a function to create unique (nonexistant) domains at *every* call.
106 //------------------------------------------------------------------------------ 94 //------------------------------------------------------------------------------
107 static std::string GetNonexistantDomain() { 95 static std::string GetNonexistantDomain() {
108 static std::string postfix = ".google.com"; 96 static std::string postfix = ".google.com";
109 static std::string prefix = "www."; 97 static std::string prefix = "www.";
110 static std::string mid = "datecount"; 98 static std::string mid = "datecount";
111 99
112 static int counter = 0; // Make sure its unique. 100 static int counter = 0; // Make sure its unique.
113 time_t number = time(NULL); 101 time_t number = time(NULL);
114 std::ostringstream result; 102 std::ostringstream result;
115 result << prefix << number << mid << ++counter << postfix; 103 result << prefix << number << mid << ++counter << postfix;
116 return result.str(); 104 return result.str();
117 } 105 }
118 106
119 //------------------------------------------------------------------------------ 107 //------------------------------------------------------------------------------
120 // Use a blocking function to contrast results we get via async services. 108 // Use a blocking function to contrast results we get via async services.
121 //------------------------------------------------------------------------------ 109 //------------------------------------------------------------------------------
122 TimeDelta BlockingDnsLookup(const std::string& hostname) { 110 TimeDelta BlockingDnsLookup(const std::string& hostname) {
123 char* port = "80"; // I may need to get the real port
124 struct addrinfo* result = NULL;
125 Time start = Time::Now(); 111 Time start = Time::Now();
126 112
127 // Use the same underlying methods as dns_prefetch_slave does 113 net::HostResolver resolver;
128 chrome_browser_net::get_getaddrinfo()(hostname.c_str(), port, 114 net::AddressList addresses;
129 NULL, &result); 115 resolver.Resolve(hostname, 80, &addresses, NULL);
130 116
131 TimeDelta duration = Time::Now() - start; 117 return Time::Now() - start;
132
133 if (result) {
134 chrome_browser_net::get_freeaddrinfo()(result);
135 result = NULL;
136 }
137
138 return duration;
139 } 118 }
140 119
141 //------------------------------------------------------------------------------ 120 //------------------------------------------------------------------------------
142 121
143 // First test to be sure the OS is caching lookups, which is the whole premise 122 // First test to be sure the OS is caching lookups, which is the whole premise
144 // of DNS prefetching. 123 // of DNS prefetching.
145 TEST(DnsMasterTest, OsCachesLookupsTest) { 124 TEST_F(DnsMasterTest, OsCachesLookupsTest) {
146 SetupNetworkInfrastructure(); 125 const Time start = Time::Now();
147 net::EnsureWinsockInit(); 126 int all_lookups = 0;
127 int lookups_with_improvement = 0;
128 // This test can be really flaky on Linux. It should run in much shorter time,
129 // but sometimes it won't and we don't like bogus failures.
130 while (Time::Now() - start < TimeDelta::FromMinutes(1)) {
131 std::string badname;
132 badname = GetNonexistantDomain();
148 133
149 // To avoid flaky nature of a timed test, we'll run an outer loop until we get 134 TimeDelta duration = BlockingDnsLookup(badname);
150 // 90% of the inner loop tests to pass. 135
151 // Originally we just did one set of 5 tests and demand 100%, but that proved 136 // Produce more than one result and remove the largest one
152 // flakey. With this set-looping approach, we always pass in one set (when it 137 // to reduce flakiness.
153 // used to pass). If we don't get that first set to pass, then we allow an 138 std::vector<TimeDelta> cached_results;
154 // average of one failure per two major sets. If the test runs too long, then 139 for (int j = 0; j < 3; j++)
155 // there probably is a real problem, and the test harness will terminate us 140 cached_results.push_back(BlockingDnsLookup(badname));
156 // with a failure. 141 std::sort(cached_results.begin(), cached_results.end());
157 int pass_count(0); 142 cached_results.pop_back();
158 int fail_count(0); 143
159 do { 144 TimeDelta cached_sum = TimeDelta::FromSeconds(0);
160 for (int i = 0; i < 5; i++) { 145 for (std::vector<TimeDelta>::const_iterator j = cached_results.begin();
161 std::string badname; 146 j != cached_results.end(); ++j)
162 badname = GetNonexistantDomain(); 147 cached_sum += *j;
163 TimeDelta duration = BlockingDnsLookup(badname); 148 TimeDelta cached_duration = cached_sum / cached_results.size();
164 TimeDelta cached_duration = BlockingDnsLookup(badname); 149
165 if (duration > cached_duration) 150 all_lookups++;
166 pass_count++; 151 if (cached_duration < duration)
167 else 152 lookups_with_improvement++;
168 fail_count++; 153 if (all_lookups >= 10)
169 } 154 if (lookups_with_improvement * 100 > all_lookups * 75)
170 } while (fail_count * 9 > pass_count); 155 // Okay, we see the improvement for more than 75% of all lookups.
156 return;
157 }
158 FAIL() << "No substantial improvement in lookup time.";
171 } 159 }
172 160
173 TEST(DnsMasterTest, StartupShutdownTest) { 161 TEST_F(DnsMasterTest, StartupShutdownTest) {
174 DnsMaster testing_master(TimeDelta::FromMilliseconds(5000)); 162 DnsMaster testing_master;
175 163 testing_master.Shutdown();
176 // With no threads, we should have no problem doing a shutdown.
177 EXPECT_TRUE(testing_master.ShutdownSlaves());
178 } 164 }
179 165
180 TEST(DnsMasterTest, BenefitLookupTest) { 166 TEST_F(DnsMasterTest, BenefitLookupTest) {
181 SetupNetworkInfrastructure(); 167 DnsMaster testing_master;
182 net::EnsureWinsockInit();
183 DnsPrefetcherInit dns_init(NULL); // Creates global service .
184 DnsMaster testing_master(TimeDelta::FromMilliseconds(5000));
185 168
186 std::string goog("www.google.com"), 169 std::string goog("www.google.com"),
187 goog2("gmail.google.com.com"), 170 goog2("gmail.google.com.com"),
188 goog3("mail.google.com"), 171 goog3("mail.google.com"),
189 goog4("gmail.com"); 172 goog4("gmail.com");
190 DnsHostInfo goog_info, goog2_info, goog3_info, goog4_info; 173 DnsHostInfo goog_info, goog2_info, goog3_info, goog4_info;
191 174
192 // Simulate getting similar names from a network observer 175 // Simulate getting similar names from a network observer
193 goog_info.SetHostname(goog); 176 goog_info.SetHostname(goog);
194 goog2_info.SetHostname(goog2); 177 goog2_info.SetHostname(goog2);
195 goog3_info.SetHostname(goog3); 178 goog3_info.SetHostname(goog3);
196 goog4_info.SetHostname(goog4); 179 goog4_info.SetHostname(goog4);
197 180
198 goog_info.SetStartedState(); 181 goog_info.SetStartedState();
199 goog2_info.SetStartedState(); 182 goog2_info.SetStartedState();
200 goog3_info.SetStartedState(); 183 goog3_info.SetStartedState();
201 goog4_info.SetStartedState(); 184 goog4_info.SetStartedState();
202 185
203 goog_info.SetFinishedState(true); 186 goog_info.SetFinishedState(true);
204 goog2_info.SetFinishedState(true); 187 goog2_info.SetFinishedState(true);
205 goog3_info.SetFinishedState(true); 188 goog3_info.SetFinishedState(true);
206 goog4_info.SetFinishedState(true); 189 goog4_info.SetFinishedState(true);
207 190
208 NameList names; 191 NameList names;
209 names.insert(names.end(), goog); 192 names.insert(names.end(), goog);
210 names.insert(names.end(), goog2); 193 names.insert(names.end(), goog2);
211 names.insert(names.end(), goog3); 194 names.insert(names.end(), goog3);
212 names.insert(names.end(), goog4); 195 names.insert(names.end(), goog4);
213 196
214 // First only cause a minimal set of threads to start up.
215 // Currently we actually start 4 threads when we get called with an array
216 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); 197 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED);
217 198
218 // Wait for some resoultion for each google. 199 WaitForResolution(&testing_master, names);
219 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
220 testing_master.GetResolutionDuration(goog).InMilliseconds());
221 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
222 testing_master.GetResolutionDuration(goog2).InMilliseconds());
223 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
224 testing_master.GetResolutionDuration(goog3).InMilliseconds());
225 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
226 testing_master.GetResolutionDuration(goog4).InMilliseconds());
227
228 EXPECT_EQ(std::min(names.size(),
229 4u /* chrome_browser_net::DnsMaster::kSlaveCountMin */ ),
230 testing_master.running_slave_count());
231 200
232 EXPECT_TRUE(testing_master.WasFound(goog)); 201 EXPECT_TRUE(testing_master.WasFound(goog));
233 EXPECT_TRUE(testing_master.WasFound(goog2)); 202 EXPECT_TRUE(testing_master.WasFound(goog2));
234 EXPECT_TRUE(testing_master.WasFound(goog3)); 203 EXPECT_TRUE(testing_master.WasFound(goog3));
235 EXPECT_TRUE(testing_master.WasFound(goog4)); 204 EXPECT_TRUE(testing_master.WasFound(goog4));
236 205
237 // With the mock DNS, each of these should have taken some time, and hence 206 // With the mock DNS, each of these should have taken some time, and hence
238 // shown a benefit (i.e., prefetch cost more than network access time). 207 // shown a benefit (i.e., prefetch cost more than network access time).
239 208
240 // Simulate actual navigation, and acrue the benefit for "helping" the DNS 209 // Simulate actual navigation, and acrue the benefit for "helping" the DNS
241 // part of the navigation. 210 // part of the navigation.
242 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog_info)); 211 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog_info));
243 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog2_info)); 212 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog2_info));
244 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog3_info)); 213 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog3_info));
245 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog4_info)); 214 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog4_info));
246 215
247 // Benefits can ONLY be reported once (for the first navigation). 216 // Benefits can ONLY be reported once (for the first navigation).
248 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog_info)); 217 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog_info));
249 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog2_info)); 218 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog2_info));
250 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog3_info)); 219 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog3_info));
251 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog4_info)); 220 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog4_info));
252 221
253 // Ensure a clean shutdown. 222 testing_master.Shutdown();
254 EXPECT_TRUE(testing_master.ShutdownSlaves());
255 } 223 }
256 224
257 TEST(DnsMasterTest, DISABLED_SingleSlaveLookupTest) { 225 TEST_F(DnsMasterTest, ShutdownWhenResolutionIsPendingTest) {
258 SetupNetworkInfrastructure(); 226 scoped_refptr<net::WaitingHostMapper> mapper = new net::WaitingHostMapper();
259 net::EnsureWinsockInit(); 227 net::ScopedHostMapper scoped_mapper(mapper.get());
260 DnsPrefetcherInit dns_init(NULL); // Creates global service. 228
261 DnsMaster testing_master(TimeDelta::FromMilliseconds(5000)); 229 DnsMaster testing_master;
230
231 std::string localhost("127.0.0.1");
232 NameList names;
233 names.insert(names.end(), localhost);
234
235 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED);
236
237 MessageLoop::current()->PostDelayedTask(FROM_HERE,
238 new MessageLoop::QuitTask(), 500);
239 MessageLoop::current()->Run();
240
241 EXPECT_FALSE(testing_master.WasFound(localhost));
242
243 testing_master.Shutdown();
244
245 // Clean up after ourselves.
246 mapper->Signal();
247 MessageLoop::current()->RunAllPending();
248 }
249
250 TEST_F(DnsMasterTest, SingleLookupTest) {
251 DnsMaster testing_master;
252
253 std::string goog("www.google.com");
254
255 NameList names;
256 names.insert(names.end(), goog);
257
258 // Try to flood the master with many concurrent requests.
259 for (int i = 0; i < 10; i++)
260 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED);
261
262 WaitForResolution(&testing_master, names);
263
264 EXPECT_TRUE(testing_master.WasFound(goog));
265
266 MessageLoop::current()->RunAllPending();
267
268 EXPECT_GT(testing_master.peak_pending_lookups(), names.size() / 2);
269 EXPECT_LE(testing_master.peak_pending_lookups(), names.size());
270 EXPECT_LE(testing_master.peak_pending_lookups(),
271 DnsMaster::kMaxConcurrentLookups);
272
273 testing_master.Shutdown();
274 }
275
276 TEST_F(DnsMasterTest, ConcurrentLookupTest) {
277 DnsMaster testing_master;
262 278
263 std::string goog("www.google.com"), 279 std::string goog("www.google.com"),
264 goog2("gmail.google.com.com"), 280 goog2("gmail.google.com.com"),
265 goog3("mail.google.com"),
266 goog4("gmail.com");
267 std::string bad1(GetNonexistantDomain()),
268 bad2(GetNonexistantDomain());
269
270 // Warm up local OS cache.
271 BlockingDnsLookup(goog);
272
273 NameList names;
274 names.insert(names.end(), goog);
275 names.insert(names.end(), bad1);
276 names.insert(names.end(), bad2);
277
278 // First only cause a single thread to start up
279 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED);
280
281 // Wait for some resoultion for google.
282 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
283 testing_master.GetResolutionDuration(goog).InMilliseconds());
284
285 EXPECT_TRUE(testing_master.WasFound(goog));
286 EXPECT_FALSE(testing_master.WasFound(bad1));
287 EXPECT_FALSE(testing_master.WasFound(bad2));
288 // Verify the reason it is not found is that it is still being proceessed.
289 // Negative time mean no resolution yet.
290 EXPECT_GT(0, testing_master.GetResolutionDuration(bad2).InMilliseconds());
291
292 // Spin long enough that we *do* find the resolution of bad2.
293 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
294 testing_master.GetResolutionDuration(bad2).InMilliseconds());
295
296 // Verify both fictitious names are resolved by now.
297 // Typical random name takes about 20-30 ms
298 EXPECT_LT(0, testing_master.GetResolutionDuration(bad1).InMilliseconds());
299 EXPECT_LT(0, testing_master.GetResolutionDuration(bad2).InMilliseconds());
300 EXPECT_FALSE(testing_master.WasFound(bad1));
301 EXPECT_FALSE(testing_master.WasFound(bad2));
302
303 EXPECT_EQ(1U, testing_master.running_slave_count());
304
305 // With just one thread (doing nothing now), ensure a clean shutdown.
306 EXPECT_TRUE(testing_master.ShutdownSlaves());
307 }
308
309 TEST(DnsMasterTest, DISABLED_MultiThreadedLookupTest) {
310 SetupNetworkInfrastructure();
311 net::EnsureWinsockInit();
312 DnsMaster testing_master(TimeDelta::FromSeconds(30));
313 DnsPrefetcherInit dns_init(NULL);
314
315 std::string goog("www.google.com"),
316 goog2("gmail.google.com.com"),
317 goog3("mail.google.com"), 281 goog3("mail.google.com"),
318 goog4("gmail.com"); 282 goog4("gmail.com");
319 std::string bad1(GetNonexistantDomain()), 283 std::string bad1(GetNonexistantDomain()),
320 bad2(GetNonexistantDomain()); 284 bad2(GetNonexistantDomain());
321 285
322 NameList names; 286 NameList names;
323 names.insert(names.end(), goog); 287 names.insert(names.end(), goog);
324 names.insert(names.end(), goog3); 288 names.insert(names.end(), goog3);
325 names.insert(names.end(), bad1); 289 names.insert(names.end(), bad1);
326 names.insert(names.end(), goog2); 290 names.insert(names.end(), goog2);
327 names.insert(names.end(), bad2); 291 names.insert(names.end(), bad2);
328 names.insert(names.end(), goog4); 292 names.insert(names.end(), goog4);
329 names.insert(names.end(), goog); 293 names.insert(names.end(), goog);
330 294
331 // Warm up the *OS* cache for all the goog domains. 295 // Warm up the *OS* cache for all the goog domains.
332 BlockingDnsLookup(goog); 296 BlockingDnsLookup(goog);
333 BlockingDnsLookup(goog2); 297 BlockingDnsLookup(goog2);
334 BlockingDnsLookup(goog3); 298 BlockingDnsLookup(goog3);
335 BlockingDnsLookup(goog4); 299 BlockingDnsLookup(goog4);
336 300
337 // Get all 8 threads running by calling many times before queue is handled. 301 // Try to flood the master with many concurrent requests.
338 for (int i = 0; i < 10; i++) { 302 for (int i = 0; i < 10; i++)
339 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); 303 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED);
340 }
341 304
342 Sleep(10); // Allow time for async DNS to get answers. 305 WaitForResolution(&testing_master, names);
343 306
344 EXPECT_TRUE(testing_master.WasFound(goog)); 307 EXPECT_TRUE(testing_master.WasFound(goog));
345 EXPECT_TRUE(testing_master.WasFound(goog3)); 308 EXPECT_TRUE(testing_master.WasFound(goog3));
346 EXPECT_TRUE(testing_master.WasFound(goog2)); 309 EXPECT_TRUE(testing_master.WasFound(goog2));
347 EXPECT_TRUE(testing_master.WasFound(goog4)); 310 EXPECT_TRUE(testing_master.WasFound(goog4));
348 EXPECT_FALSE(testing_master.WasFound(bad1)); 311 EXPECT_FALSE(testing_master.WasFound(bad1));
349 EXPECT_FALSE(testing_master.WasFound(bad2)); 312 EXPECT_FALSE(testing_master.WasFound(bad2));
350 313
351 EXPECT_EQ(8U, testing_master.running_slave_count()); 314 MessageLoop::current()->RunAllPending();
352 315
353 EXPECT_TRUE(testing_master.ShutdownSlaves()); 316 EXPECT_FALSE(testing_master.WasFound(bad1));
317 EXPECT_FALSE(testing_master.WasFound(bad2));
318
319 EXPECT_GT(testing_master.peak_pending_lookups(), names.size() / 2);
320 EXPECT_LE(testing_master.peak_pending_lookups(), names.size());
321 EXPECT_LE(testing_master.peak_pending_lookups(),
322 DnsMaster::kMaxConcurrentLookups);
323
324 testing_master.Shutdown();
354 } 325 }
355 326
356 TEST(DnsMasterTest, DISABLED_MultiThreadedSpeedupTest) { 327 TEST_F(DnsMasterTest, MassiveConcurrentLookupTest) {
357 SetupNetworkInfrastructure(); 328 DnsMaster testing_master;
358 net::EnsureWinsockInit();
359 DnsMaster testing_master(TimeDelta::FromSeconds(30));
360 DnsPrefetcherInit dns_init(NULL);
361
362 std::string goog("www.google.com"),
363 goog2("gmail.google.com.com"),
364 goog3("mail.google.com"),
365 goog4("gmail.com");
366 std::string bad1(GetNonexistantDomain()),
367 bad2(GetNonexistantDomain()),
368 bad3(GetNonexistantDomain()),
369 bad4(GetNonexistantDomain());
370 329
371 NameList names; 330 NameList names;
372 names.insert(names.end(), goog); 331 for (int i = 0; i < 100; i++)
373 names.insert(names.end(), bad1); 332 names.push_back(GetNonexistantDomain());
374 names.insert(names.end(), bad2);
375 names.insert(names.end(), goog3);
376 names.insert(names.end(), goog2);
377 names.insert(names.end(), bad3);
378 names.insert(names.end(), bad4);
379 names.insert(names.end(), goog4);
380 333
381 // First cause a lookup using a single thread. 334 // Try to flood the master with many concurrent requests.
382 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); 335 for (int i = 0; i < 10; i++)
336 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED);
383 337
384 // Wait for some resoultion for google. 338 WaitForResolution(&testing_master, names);
385 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
386 testing_master.GetResolutionDuration(goog).InMilliseconds());
387 339
388 EXPECT_TRUE(testing_master.WasFound(goog)); 340 MessageLoop::current()->RunAllPending();
389 EXPECT_FALSE(testing_master.WasFound(bad1));
390 EXPECT_FALSE(testing_master.WasFound(bad2));
391 // ...and due to delay in geting resolution of bad names, the single slave
392 // thread won't have time to finish the list.
393 EXPECT_FALSE(testing_master.WasFound(goog3));
394 EXPECT_FALSE(testing_master.WasFound(goog2));
395 EXPECT_FALSE(testing_master.WasFound(goog4));
396 341
397 EXPECT_EQ(1U, testing_master.running_slave_count()); 342 EXPECT_LE(testing_master.peak_pending_lookups(), names.size());
343 EXPECT_LE(testing_master.peak_pending_lookups(),
344 DnsMaster::kMaxConcurrentLookups);
398 345
399 // Get all 8 threads running by calling many times before queue is handled. 346 testing_master.Shutdown();
400 names.clear();
401 for (int i = 0; i < 10; i++)
402 testing_master.Resolve(GetNonexistantDomain(),
403 DnsHostInfo::PAGE_SCAN_MOTIVATED);
404
405 // Wait long enough for all the goog's to be resolved.
406 // They should all take about the same time, and run in parallel.
407 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
408 testing_master.GetResolutionDuration(goog2).InMilliseconds());
409 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
410 testing_master.GetResolutionDuration(goog3).InMilliseconds());
411 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
412 testing_master.GetResolutionDuration(goog4).InMilliseconds());
413
414 EXPECT_TRUE(testing_master.WasFound(goog3));
415 EXPECT_TRUE(testing_master.WasFound(goog2));
416 EXPECT_TRUE(testing_master.WasFound(goog4));
417
418 EXPECT_FALSE(testing_master.WasFound(bad1));
419 EXPECT_FALSE(testing_master.WasFound(bad2)); // Perhaps not even decided.
420
421 // Queue durations should be distinct from when 1 slave was working.
422 EXPECT_GT(testing_master.GetQueueDuration(goog3).InMilliseconds(),
423 testing_master.GetQueueDuration(goog).InMilliseconds());
424 EXPECT_GT(testing_master.GetQueueDuration(goog4).InMilliseconds(),
425 testing_master.GetQueueDuration(goog).InMilliseconds());
426
427 // Give bad names a chance to be determined as unresolved.
428 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
429 testing_master.GetResolutionDuration(bad1).InMilliseconds());
430 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <=
431 testing_master.GetResolutionDuration(bad2).InMilliseconds());
432
433
434 // Well known names should resolve faster than bad names.
435 EXPECT_GE(testing_master.GetResolutionDuration(bad1).InMilliseconds(),
436 testing_master.GetResolutionDuration(goog).InMilliseconds());
437
438 EXPECT_GE(testing_master.GetResolutionDuration(bad2).InMilliseconds(),
439 testing_master.GetResolutionDuration(goog4).InMilliseconds());
440
441 EXPECT_EQ(8U, testing_master.running_slave_count());
442
443 EXPECT_TRUE(testing_master.ShutdownSlaves());
444 } 347 }
445 348
446 //------------------------------------------------------------------------------ 349 //------------------------------------------------------------------------------
447 // Functions to help synthesize and test serializations of subresource referrer 350 // Functions to help synthesize and test serializations of subresource referrer
448 // lists. 351 // lists.
449 352
450 // Return a motivation_list if we can find one for the given motivating_host (or 353 // Return a motivation_list if we can find one for the given motivating_host (or
451 // NULL if a match is not found). 354 // NULL if a match is not found).
452 static ListValue* FindSerializationMotivation(const std::string& motivation, 355 static ListValue* FindSerializationMotivation(const std::string& motivation,
453 const ListValue& referral_list) { 356 const ListValue& referral_list) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 return latency; 420 return latency;
518 } 421 }
519 ++i; // Skip latency value. 422 ++i; // Skip latency value.
520 } 423 }
521 return kLatencyNotFound; 424 return kLatencyNotFound;
522 } 425 }
523 426
524 //------------------------------------------------------------------------------ 427 //------------------------------------------------------------------------------
525 428
526 // Make sure nil referral lists really have no entries, and no latency listed. 429 // Make sure nil referral lists really have no entries, and no latency listed.
527 TEST(DnsMasterTest, ReferrerSerializationNilTest) { 430 TEST_F(DnsMasterTest, ReferrerSerializationNilTest) {
528 DnsMaster master(TimeDelta::FromSeconds(30)); 431 DnsMaster master;
529 ListValue referral_list; 432 ListValue referral_list;
530 master.SerializeReferrers(&referral_list); 433 master.SerializeReferrers(&referral_list);
531 EXPECT_EQ(0, referral_list.GetSize()); 434 EXPECT_EQ(0U, referral_list.GetSize());
532 EXPECT_EQ(kLatencyNotFound, GetLatencyFromSerialization("a.com", "b.com", 435 EXPECT_EQ(kLatencyNotFound, GetLatencyFromSerialization("a.com", "b.com",
533 referral_list)); 436 referral_list));
437
438 master.Shutdown();
534 } 439 }
535 440
536 // Make sure that when a serialization list includes a value, that it can be 441 // Make sure that when a serialization list includes a value, that it can be
537 // deserialized into the database, and can be extracted back out via 442 // deserialized into the database, and can be extracted back out via
538 // serialization without being changed. 443 // serialization without being changed.
539 TEST(DnsMasterTest, ReferrerSerializationSingleReferrerTest) { 444 TEST_F(DnsMasterTest, ReferrerSerializationSingleReferrerTest) {
540 DnsMaster master(TimeDelta::FromSeconds(30)); 445 DnsMaster master;
541 std::string motivation_hostname = "www.google.com"; 446 std::string motivation_hostname = "www.google.com";
542 std::string subresource_hostname = "icons.google.com"; 447 std::string subresource_hostname = "icons.google.com";
543 const int kLatency = 3; 448 const int kLatency = 3;
544 ListValue referral_list; 449 ListValue referral_list;
545 450
546 AddToSerializedList(motivation_hostname, subresource_hostname, kLatency, 451 AddToSerializedList(motivation_hostname, subresource_hostname, kLatency,
547 &referral_list); 452 &referral_list);
548 453
549 master.DeserializeReferrers(referral_list); 454 master.DeserializeReferrers(referral_list);
550 455
551 ListValue recovered_referral_list; 456 ListValue recovered_referral_list;
552 master.SerializeReferrers(&recovered_referral_list); 457 master.SerializeReferrers(&recovered_referral_list);
553 EXPECT_EQ(1, recovered_referral_list.GetSize()); 458 EXPECT_EQ(1U, recovered_referral_list.GetSize());
554 EXPECT_EQ(kLatency, GetLatencyFromSerialization(motivation_hostname, 459 EXPECT_EQ(kLatency, GetLatencyFromSerialization(motivation_hostname,
555 subresource_hostname, 460 subresource_hostname,
556 recovered_referral_list)); 461 recovered_referral_list));
462
463 master.Shutdown();
557 } 464 }
558 465
559 // Make sure the Trim() functionality works as expected. 466 // Make sure the Trim() functionality works as expected.
560 TEST(DnsMasterTest, ReferrerSerializationTrimTest) { 467 TEST_F(DnsMasterTest, ReferrerSerializationTrimTest) {
561 DnsMaster master(TimeDelta::FromSeconds(30)); 468 DnsMaster master;
562 std::string motivation_hostname = "www.google.com"; 469 std::string motivation_hostname = "www.google.com";
563 std::string icon_subresource_hostname = "icons.google.com"; 470 std::string icon_subresource_hostname = "icons.google.com";
564 std::string img_subresource_hostname = "img.google.com"; 471 std::string img_subresource_hostname = "img.google.com";
565 ListValue referral_list; 472 ListValue referral_list;
566 473
567 AddToSerializedList(motivation_hostname, icon_subresource_hostname, 10, 474 AddToSerializedList(motivation_hostname, icon_subresource_hostname, 10,
568 &referral_list); 475 &referral_list);
569 AddToSerializedList(motivation_hostname, img_subresource_hostname, 3, 476 AddToSerializedList(motivation_hostname, img_subresource_hostname, 3,
570 &referral_list); 477 &referral_list);
571 478
572 master.DeserializeReferrers(referral_list); 479 master.DeserializeReferrers(referral_list);
573 480
574 ListValue recovered_referral_list; 481 ListValue recovered_referral_list;
575 master.SerializeReferrers(&recovered_referral_list); 482 master.SerializeReferrers(&recovered_referral_list);
576 EXPECT_EQ(1, recovered_referral_list.GetSize()); 483 EXPECT_EQ(1U, recovered_referral_list.GetSize());
577 EXPECT_EQ(10, GetLatencyFromSerialization(motivation_hostname, 484 EXPECT_EQ(10, GetLatencyFromSerialization(motivation_hostname,
578 icon_subresource_hostname, 485 icon_subresource_hostname,
579 recovered_referral_list)); 486 recovered_referral_list));
580 EXPECT_EQ(3, GetLatencyFromSerialization(motivation_hostname, 487 EXPECT_EQ(3, GetLatencyFromSerialization(motivation_hostname,
581 img_subresource_hostname, 488 img_subresource_hostname,
582 recovered_referral_list)); 489 recovered_referral_list));
583 490
584 // Each time we Trim, the latency figures should reduce by a factor of two, 491 // Each time we Trim, the latency figures should reduce by a factor of two,
585 // until they both are 0, an then a trim will delete the whole entry. 492 // until they both are 0, an then a trim will delete the whole entry.
586 master.TrimReferrers(); 493 master.TrimReferrers();
587 master.SerializeReferrers(&recovered_referral_list); 494 master.SerializeReferrers(&recovered_referral_list);
588 EXPECT_EQ(1, recovered_referral_list.GetSize()); 495 EXPECT_EQ(1U, recovered_referral_list.GetSize());
589 EXPECT_EQ(5, GetLatencyFromSerialization(motivation_hostname, 496 EXPECT_EQ(5, GetLatencyFromSerialization(motivation_hostname,
590 icon_subresource_hostname, 497 icon_subresource_hostname,
591 recovered_referral_list)); 498 recovered_referral_list));
592 EXPECT_EQ(1, GetLatencyFromSerialization(motivation_hostname, 499 EXPECT_EQ(1, GetLatencyFromSerialization(motivation_hostname,
593 img_subresource_hostname, 500 img_subresource_hostname,
594 recovered_referral_list)); 501 recovered_referral_list));
595 502
596 master.TrimReferrers(); 503 master.TrimReferrers();
597 master.SerializeReferrers(&recovered_referral_list); 504 master.SerializeReferrers(&recovered_referral_list);
598 EXPECT_EQ(1, recovered_referral_list.GetSize()); 505 EXPECT_EQ(1U, recovered_referral_list.GetSize());
599 EXPECT_EQ(2, GetLatencyFromSerialization(motivation_hostname, 506 EXPECT_EQ(2, GetLatencyFromSerialization(motivation_hostname,
600 icon_subresource_hostname, 507 icon_subresource_hostname,
601 recovered_referral_list)); 508 recovered_referral_list));
602 EXPECT_EQ(0, GetLatencyFromSerialization(motivation_hostname, 509 EXPECT_EQ(0, GetLatencyFromSerialization(motivation_hostname,
603 img_subresource_hostname, 510 img_subresource_hostname,
604 recovered_referral_list)); 511 recovered_referral_list));
605 512
606 master.TrimReferrers(); 513 master.TrimReferrers();
607 master.SerializeReferrers(&recovered_referral_list); 514 master.SerializeReferrers(&recovered_referral_list);
608 EXPECT_EQ(1, recovered_referral_list.GetSize()); 515 EXPECT_EQ(1U, recovered_referral_list.GetSize());
609 EXPECT_EQ(1, GetLatencyFromSerialization(motivation_hostname, 516 EXPECT_EQ(1, GetLatencyFromSerialization(motivation_hostname,
610 icon_subresource_hostname, 517 icon_subresource_hostname,
611 recovered_referral_list)); 518 recovered_referral_list));
612 EXPECT_EQ(0, GetLatencyFromSerialization(motivation_hostname, 519 EXPECT_EQ(0, GetLatencyFromSerialization(motivation_hostname,
613 img_subresource_hostname, 520 img_subresource_hostname,
614 recovered_referral_list)); 521 recovered_referral_list));
615 522
616 master.TrimReferrers(); 523 master.TrimReferrers();
617 master.SerializeReferrers(&recovered_referral_list); 524 master.SerializeReferrers(&recovered_referral_list);
618 EXPECT_EQ(0, recovered_referral_list.GetSize()); 525 EXPECT_EQ(0U, recovered_referral_list.GetSize());
619 EXPECT_EQ(kLatencyNotFound, 526 EXPECT_EQ(kLatencyNotFound,
620 GetLatencyFromSerialization(motivation_hostname, 527 GetLatencyFromSerialization(motivation_hostname,
621 icon_subresource_hostname, 528 icon_subresource_hostname,
622 recovered_referral_list)); 529 recovered_referral_list));
623 EXPECT_EQ(kLatencyNotFound, 530 EXPECT_EQ(kLatencyNotFound,
624 GetLatencyFromSerialization(motivation_hostname, 531 GetLatencyFromSerialization(motivation_hostname,
625 img_subresource_hostname, 532 img_subresource_hostname,
626 recovered_referral_list)); 533 recovered_referral_list));
534
535 master.Shutdown();
627 } 536 }
628 537
629 538 } // namespace chrome_browser_net
630 } // namespace
631
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698