OLD | NEW |
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 Loading... |
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 | |
OLD | NEW |