| 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 |
| 5 #include <time.h> | 7 #include <time.h> |
| 8 #include <ws2tcpip.h> |
| 9 #include <Wspiapi.h> // Needed for win2k compatibility |
| 6 | 10 |
| 7 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <map> |
| 8 #include <sstream> | 13 #include <sstream> |
| 9 #include <string> | 14 #include <string> |
| 10 | 15 |
| 11 #include "base/message_loop.h" | |
| 12 #include "base/platform_thread.h" | 16 #include "base/platform_thread.h" |
| 13 #include "base/scoped_ptr.h" | 17 #include "base/spin_wait.h" |
| 14 #include "base/timer.h" | |
| 15 #include "chrome/browser/net/dns_global.h" | 18 #include "chrome/browser/net/dns_global.h" |
| 16 #include "chrome/browser/net/dns_host_info.h" | 19 #include "chrome/browser/net/dns_host_info.h" |
| 17 #include "chrome/common/net/dns.h" | 20 #include "chrome/browser/net/dns_slave.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 |
| 24 using base::Time; | 25 using base::Time; |
| 25 using base::TimeDelta; | 26 using base::TimeDelta; |
| 26 | 27 |
| 27 namespace chrome_browser_net { | 28 namespace { |
| 28 | 29 |
| 29 class WaitForResolutionHelper; | 30 class DnsMasterTest : public testing::Test { |
| 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 }; | 31 }; |
| 59 | 32 |
| 60 class DnsMasterTest : public testing::Test { | 33 typedef chrome_browser_net::DnsMaster DnsMaster; |
| 61 public: | 34 typedef chrome_browser_net::DnsPrefetcherInit DnsPrefetcherInit; |
| 62 DnsMasterTest() | 35 typedef chrome_browser_net::DnsHostInfo DnsHostInfo; |
| 63 : loop_(new MessageLoop()), | 36 typedef chrome_browser_net::NameList NameList; |
| 64 mapper_(new net::RuleBasedHostMapper()), | |
| 65 scoped_mapper_(mapper_.get()) { | |
| 66 } | |
| 67 | 37 |
| 68 protected: | |
| 69 virtual void SetUp() { | |
| 70 #if defined(OS_WIN) | |
| 71 net::EnsureWinsockInit(); | |
| 72 #endif | |
| 73 mapper_->AddRuleWithLatency("www.google.com", "127.0.0.1", 50); | |
| 74 mapper_->AddRuleWithLatency("gmail.google.com.com", "127.0.0.1", 70); | |
| 75 mapper_->AddRuleWithLatency("mail.google.com", "127.0.0.1", 44); | |
| 76 mapper_->AddRuleWithLatency("gmail.com", "127.0.0.1", 63); | |
| 77 } | |
| 78 | 38 |
| 79 void WaitForResolution(DnsMaster* master, const NameList& hosts) { | 39 //------------------------------------------------------------------------------ |
| 80 HelperTimer* timer = new HelperTimer(); | 40 // Provide network function stubs to run tests offline (and avoid the variance |
| 81 timer->Start(TimeDelta::FromMilliseconds(100), | 41 // of real DNS lookups. |
| 82 new WaitForResolutionHelper(master, hosts, timer), | 42 //------------------------------------------------------------------------------ |
| 83 &WaitForResolutionHelper::Run); | |
| 84 MessageLoop::current()->Run(); | |
| 85 } | |
| 86 | 43 |
| 87 void DestroyMessageLoop() { | 44 static void __stdcall fake_free_addr_info(struct addrinfo* ai) { |
| 88 loop_.reset(); | 45 // Kill off the dummy results. |
| 89 } | 46 EXPECT_TRUE(NULL != ai); |
| 47 delete ai; |
| 48 } |
| 90 | 49 |
| 91 private: | 50 static int __stdcall fake_get_addr_info(const char* nodename, |
| 92 scoped_ptr<MessageLoop> loop_; | 51 const char* servname, |
| 93 scoped_refptr<net::RuleBasedHostMapper> mapper_; | 52 const struct addrinfo* hints, |
| 94 net::ScopedHostMapper scoped_mapper_; | 53 struct addrinfo** result) { |
| 95 }; | 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 } |
| 96 | 103 |
| 97 //------------------------------------------------------------------------------ | 104 //------------------------------------------------------------------------------ |
| 98 // Provide a function to create unique (nonexistant) domains at *every* call. | 105 // Provide a function to create unique (nonexistant) domains at *every* call. |
| 99 //------------------------------------------------------------------------------ | 106 //------------------------------------------------------------------------------ |
| 100 static std::string GetNonexistantDomain() { | 107 static std::string GetNonexistantDomain() { |
| 101 static std::string postfix = ".google.com"; | 108 static std::string postfix = ".google.com"; |
| 102 static std::string prefix = "www."; | 109 static std::string prefix = "www."; |
| 103 static std::string mid = "datecount"; | 110 static std::string mid = "datecount"; |
| 104 | 111 |
| 105 static int counter = 0; // Make sure its unique. | 112 static int counter = 0; // Make sure its unique. |
| 106 time_t number = time(NULL); | 113 time_t number = time(NULL); |
| 107 std::ostringstream result; | 114 std::ostringstream result; |
| 108 result << prefix << number << mid << ++counter << postfix; | 115 result << prefix << number << mid << ++counter << postfix; |
| 109 return result.str(); | 116 return result.str(); |
| 110 } | 117 } |
| 111 | 118 |
| 112 //------------------------------------------------------------------------------ | 119 //------------------------------------------------------------------------------ |
| 113 // Use a blocking function to contrast results we get via async services. | 120 // Use a blocking function to contrast results we get via async services. |
| 114 //------------------------------------------------------------------------------ | 121 //------------------------------------------------------------------------------ |
| 115 TimeDelta BlockingDnsLookup(const std::string& hostname) { | 122 TimeDelta BlockingDnsLookup(const std::string& hostname) { |
| 123 char* port = "80"; // I may need to get the real port |
| 124 struct addrinfo* result = NULL; |
| 116 Time start = Time::Now(); | 125 Time start = Time::Now(); |
| 117 | 126 |
| 118 net::HostResolver resolver; | 127 // Use the same underlying methods as dns_prefetch_slave does |
| 119 net::AddressList addresses; | 128 chrome_browser_net::get_getaddrinfo()(hostname.c_str(), port, |
| 120 resolver.Resolve(hostname, 80, &addresses, NULL); | 129 NULL, &result); |
| 121 | 130 |
| 122 return Time::Now() - start; | 131 TimeDelta duration = Time::Now() - start; |
| 132 |
| 133 if (result) { |
| 134 chrome_browser_net::get_freeaddrinfo()(result); |
| 135 result = NULL; |
| 136 } |
| 137 |
| 138 return duration; |
| 123 } | 139 } |
| 124 | 140 |
| 125 //------------------------------------------------------------------------------ | 141 //------------------------------------------------------------------------------ |
| 126 | 142 |
| 127 // First test to be sure the OS is caching lookups, which is the whole premise | 143 // First test to be sure the OS is caching lookups, which is the whole premise |
| 128 // of DNS prefetching. | 144 // of DNS prefetching. |
| 129 TEST_F(DnsMasterTest, OsCachesLookupsTest) { | 145 TEST(DnsMasterTest, OsCachesLookupsTest) { |
| 130 const Time start = Time::Now(); | 146 SetupNetworkInfrastructure(); |
| 131 int all_lookups = 0; | 147 net::EnsureWinsockInit(); |
| 132 int lookups_with_improvement = 0; | 148 |
| 133 // This test can be really flaky on Linux. It should run in much shorter time, | 149 for (int i = 0; i < 5; i++) { |
| 134 // but sometimes it won't and we don't like bogus failures. | |
| 135 while (Time::Now() - start < TimeDelta::FromMinutes(1)) { | |
| 136 std::string badname; | 150 std::string badname; |
| 137 badname = GetNonexistantDomain(); | 151 badname = GetNonexistantDomain(); |
| 138 | |
| 139 TimeDelta duration = BlockingDnsLookup(badname); | 152 TimeDelta duration = BlockingDnsLookup(badname); |
| 140 | 153 TimeDelta cached_duration = BlockingDnsLookup(badname); |
| 141 // Produce more than one result and remove the largest one | 154 EXPECT_TRUE(duration > cached_duration); |
| 142 // to reduce flakiness. | |
| 143 std::vector<TimeDelta> cached_results; | |
| 144 for (int j = 0; j < 3; j++) | |
| 145 cached_results.push_back(BlockingDnsLookup(badname)); | |
| 146 std::sort(cached_results.begin(), cached_results.end()); | |
| 147 cached_results.pop_back(); | |
| 148 | |
| 149 TimeDelta cached_sum = TimeDelta::FromSeconds(0); | |
| 150 for (std::vector<TimeDelta>::const_iterator j = cached_results.begin(); | |
| 151 j != cached_results.end(); ++j) | |
| 152 cached_sum += *j; | |
| 153 TimeDelta cached_duration = cached_sum / cached_results.size(); | |
| 154 | |
| 155 all_lookups++; | |
| 156 if (cached_duration < duration) | |
| 157 lookups_with_improvement++; | |
| 158 if (all_lookups >= 10) | |
| 159 if (lookups_with_improvement * 100 > all_lookups * 75) | |
| 160 // Okay, we see the improvement for more than 75% of all lookups. | |
| 161 return; | |
| 162 } | 155 } |
| 163 FAIL() << "No substantial improvement in lookup time."; | |
| 164 } | 156 } |
| 165 | 157 |
| 166 TEST_F(DnsMasterTest, StartupShutdownTest) { | 158 TEST(DnsMasterTest, StartupShutdownTest) { |
| 167 DnsMaster testing_master; | 159 DnsMaster testing_master(TimeDelta::FromMilliseconds(5000)); |
| 168 // We do shutdown on destruction. | 160 |
| 161 // With no threads, we should have no problem doing a shutdown. |
| 162 EXPECT_TRUE(testing_master.ShutdownSlaves()); |
| 169 } | 163 } |
| 170 | 164 |
| 171 TEST_F(DnsMasterTest, BenefitLookupTest) { | 165 TEST(DnsMasterTest, BenefitLookupTest) { |
| 172 DnsMaster testing_master; | 166 SetupNetworkInfrastructure(); |
| 167 net::EnsureWinsockInit(); |
| 168 DnsPrefetcherInit dns_init(NULL); // Creates global service . |
| 169 DnsMaster testing_master(TimeDelta::FromMilliseconds(5000)); |
| 173 | 170 |
| 174 std::string goog("www.google.com"), | 171 std::string goog("www.google.com"), |
| 175 goog2("gmail.google.com.com"), | 172 goog2("gmail.google.com.com"), |
| 176 goog3("mail.google.com"), | 173 goog3("mail.google.com"), |
| 177 goog4("gmail.com"); | 174 goog4("gmail.com"); |
| 178 DnsHostInfo goog_info, goog2_info, goog3_info, goog4_info; | 175 DnsHostInfo goog_info, goog2_info, goog3_info, goog4_info; |
| 179 | 176 |
| 180 // Simulate getting similar names from a network observer | 177 // Simulate getting similar names from a network observer |
| 181 goog_info.SetHostname(goog); | 178 goog_info.SetHostname(goog); |
| 182 goog2_info.SetHostname(goog2); | 179 goog2_info.SetHostname(goog2); |
| 183 goog3_info.SetHostname(goog3); | 180 goog3_info.SetHostname(goog3); |
| 184 goog4_info.SetHostname(goog4); | 181 goog4_info.SetHostname(goog4); |
| 185 | 182 |
| 186 goog_info.SetStartedState(); | 183 goog_info.SetStartedState(); |
| 187 goog2_info.SetStartedState(); | 184 goog2_info.SetStartedState(); |
| 188 goog3_info.SetStartedState(); | 185 goog3_info.SetStartedState(); |
| 189 goog4_info.SetStartedState(); | 186 goog4_info.SetStartedState(); |
| 190 | 187 |
| 191 goog_info.SetFinishedState(true); | 188 goog_info.SetFinishedState(true); |
| 192 goog2_info.SetFinishedState(true); | 189 goog2_info.SetFinishedState(true); |
| 193 goog3_info.SetFinishedState(true); | 190 goog3_info.SetFinishedState(true); |
| 194 goog4_info.SetFinishedState(true); | 191 goog4_info.SetFinishedState(true); |
| 195 | 192 |
| 196 NameList names; | 193 NameList names; |
| 197 names.insert(names.end(), goog); | 194 names.insert(names.end(), goog); |
| 198 names.insert(names.end(), goog2); | 195 names.insert(names.end(), goog2); |
| 199 names.insert(names.end(), goog3); | 196 names.insert(names.end(), goog3); |
| 200 names.insert(names.end(), goog4); | 197 names.insert(names.end(), goog4); |
| 201 | 198 |
| 199 // First only cause a minimal set of threads to start up. |
| 200 // Currently we actually start 4 threads when we get called with an array |
| 202 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); | 201 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); |
| 203 | 202 |
| 204 WaitForResolution(&testing_master, names); | 203 // Wait for some resoultion for each google. |
| 204 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 205 testing_master.GetResolutionDuration(goog).InMilliseconds()); |
| 206 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 207 testing_master.GetResolutionDuration(goog2).InMilliseconds()); |
| 208 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 209 testing_master.GetResolutionDuration(goog3).InMilliseconds()); |
| 210 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 211 testing_master.GetResolutionDuration(goog4).InMilliseconds()); |
| 212 |
| 213 EXPECT_EQ(std::min(names.size(), |
| 214 4u /* chrome_browser_net::DnsMaster::kSlaveCountMin */ ), |
| 215 testing_master.running_slave_count()); |
| 205 | 216 |
| 206 EXPECT_TRUE(testing_master.WasFound(goog)); | 217 EXPECT_TRUE(testing_master.WasFound(goog)); |
| 207 EXPECT_TRUE(testing_master.WasFound(goog2)); | 218 EXPECT_TRUE(testing_master.WasFound(goog2)); |
| 208 EXPECT_TRUE(testing_master.WasFound(goog3)); | 219 EXPECT_TRUE(testing_master.WasFound(goog3)); |
| 209 EXPECT_TRUE(testing_master.WasFound(goog4)); | 220 EXPECT_TRUE(testing_master.WasFound(goog4)); |
| 210 | 221 |
| 211 // With the mock DNS, each of these should have taken some time, and hence | 222 // With the mock DNS, each of these should have taken some time, and hence |
| 212 // shown a benefit (i.e., prefetch cost more than network access time). | 223 // shown a benefit (i.e., prefetch cost more than network access time). |
| 213 | 224 |
| 214 // Simulate actual navigation, and acrue the benefit for "helping" the DNS | 225 // Simulate actual navigation, and acrue the benefit for "helping" the DNS |
| 215 // part of the navigation. | 226 // part of the navigation. |
| 216 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog_info)); | 227 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog_info)); |
| 217 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog2_info)); | 228 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog2_info)); |
| 218 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog3_info)); | 229 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog3_info)); |
| 219 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog4_info)); | 230 EXPECT_TRUE(testing_master.AccruePrefetchBenefits(GURL(), &goog4_info)); |
| 220 | 231 |
| 221 // Benefits can ONLY be reported once (for the first navigation). | 232 // Benefits can ONLY be reported once (for the first navigation). |
| 222 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog_info)); | 233 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog_info)); |
| 223 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog2_info)); | 234 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog2_info)); |
| 224 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog3_info)); | 235 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog3_info)); |
| 225 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog4_info)); | 236 EXPECT_FALSE(testing_master.AccruePrefetchBenefits(GURL(), &goog4_info)); |
| 237 |
| 238 // Ensure a clean shutdown. |
| 239 EXPECT_TRUE(testing_master.ShutdownSlaves()); |
| 226 } | 240 } |
| 227 | 241 |
| 228 TEST_F(DnsMasterTest, DestroyMessageLoop) { | 242 TEST(DnsMasterTest, DISABLED_SingleSlaveLookupTest) { |
| 229 scoped_refptr<net::WaitingHostMapper> mapper = new net::WaitingHostMapper(); | 243 SetupNetworkInfrastructure(); |
| 230 net::ScopedHostMapper scoped_mapper(mapper.get()); | 244 net::EnsureWinsockInit(); |
| 245 DnsPrefetcherInit dns_init(NULL); // Creates global service. |
| 246 DnsMaster testing_master(TimeDelta::FromMilliseconds(5000)); |
| 231 | 247 |
| 232 { | 248 std::string goog("www.google.com"), |
| 233 DnsMaster testing_master; | 249 goog2("gmail.google.com.com"), |
| 250 goog3("mail.google.com"), |
| 251 goog4("gmail.com"); |
| 252 std::string bad1(GetNonexistantDomain()), |
| 253 bad2(GetNonexistantDomain()); |
| 234 | 254 |
| 235 std::string localhost("127.0.0.1"); | 255 // Warm up local OS cache. |
| 236 NameList names; | 256 BlockingDnsLookup(goog); |
| 237 names.insert(names.end(), localhost); | |
| 238 | |
| 239 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); | |
| 240 | |
| 241 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
| 242 new MessageLoop::QuitTask(), 500); | |
| 243 MessageLoop::current()->Run(); | |
| 244 | |
| 245 DestroyMessageLoop(); | |
| 246 ASSERT_TRUE(MessageLoop::current() == NULL); | |
| 247 } | |
| 248 | |
| 249 // Trigger the internal callback (for HostResolver). It should not crash. | |
| 250 mapper->Signal(); | |
| 251 } | |
| 252 | |
| 253 TEST_F(DnsMasterTest, ShutdownWhenResolutionIsPendingTest) { | |
| 254 scoped_refptr<net::WaitingHostMapper> mapper = new net::WaitingHostMapper(); | |
| 255 net::ScopedHostMapper scoped_mapper(mapper.get()); | |
| 256 | |
| 257 { | |
| 258 DnsMaster testing_master; | |
| 259 | |
| 260 std::string localhost("127.0.0.1"); | |
| 261 NameList names; | |
| 262 names.insert(names.end(), localhost); | |
| 263 | |
| 264 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); | |
| 265 | |
| 266 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
| 267 new MessageLoop::QuitTask(), 500); | |
| 268 MessageLoop::current()->Run(); | |
| 269 | |
| 270 EXPECT_FALSE(testing_master.WasFound(localhost)); | |
| 271 } | |
| 272 | |
| 273 // Clean up after ourselves. | |
| 274 mapper->Signal(); | |
| 275 MessageLoop::current()->RunAllPending(); | |
| 276 } | |
| 277 | |
| 278 TEST_F(DnsMasterTest, SingleLookupTest) { | |
| 279 DnsMaster testing_master; | |
| 280 | |
| 281 std::string goog("www.google.com"); | |
| 282 | 257 |
| 283 NameList names; | 258 NameList names; |
| 284 names.insert(names.end(), goog); | 259 names.insert(names.end(), goog); |
| 260 names.insert(names.end(), bad1); |
| 261 names.insert(names.end(), bad2); |
| 285 | 262 |
| 286 // Try to flood the master with many concurrent requests. | 263 // First only cause a single thread to start up |
| 287 for (int i = 0; i < 10; i++) | 264 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); |
| 288 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); | |
| 289 | 265 |
| 290 WaitForResolution(&testing_master, names); | 266 // Wait for some resoultion for google. |
| 267 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 268 testing_master.GetResolutionDuration(goog).InMilliseconds()); |
| 291 | 269 |
| 292 EXPECT_TRUE(testing_master.WasFound(goog)); | 270 EXPECT_TRUE(testing_master.WasFound(goog)); |
| 271 EXPECT_FALSE(testing_master.WasFound(bad1)); |
| 272 EXPECT_FALSE(testing_master.WasFound(bad2)); |
| 273 // Verify the reason it is not found is that it is still being proceessed. |
| 274 // Negative time mean no resolution yet. |
| 275 EXPECT_GT(0, testing_master.GetResolutionDuration(bad2).InMilliseconds()); |
| 293 | 276 |
| 294 MessageLoop::current()->RunAllPending(); | 277 // Spin long enough that we *do* find the resolution of bad2. |
| 278 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 279 testing_master.GetResolutionDuration(bad2).InMilliseconds()); |
| 295 | 280 |
| 296 EXPECT_GT(testing_master.peak_pending_lookups(), names.size() / 2); | 281 // Verify both fictitious names are resolved by now. |
| 297 EXPECT_LE(testing_master.peak_pending_lookups(), names.size()); | 282 // Typical random name takes about 20-30 ms |
| 298 EXPECT_LE(testing_master.peak_pending_lookups(), | 283 EXPECT_LT(0, testing_master.GetResolutionDuration(bad1).InMilliseconds()); |
| 299 DnsMaster::kMaxConcurrentLookups); | 284 EXPECT_LT(0, testing_master.GetResolutionDuration(bad2).InMilliseconds()); |
| 285 EXPECT_FALSE(testing_master.WasFound(bad1)); |
| 286 EXPECT_FALSE(testing_master.WasFound(bad2)); |
| 287 |
| 288 EXPECT_EQ(1U, testing_master.running_slave_count()); |
| 289 |
| 290 // With just one thread (doing nothing now), ensure a clean shutdown. |
| 291 EXPECT_TRUE(testing_master.ShutdownSlaves()); |
| 300 } | 292 } |
| 301 | 293 |
| 302 TEST_F(DnsMasterTest, ConcurrentLookupTest) { | 294 TEST(DnsMasterTest, DISABLED_MultiThreadedLookupTest) { |
| 303 DnsMaster testing_master; | 295 SetupNetworkInfrastructure(); |
| 296 net::EnsureWinsockInit(); |
| 297 DnsMaster testing_master(TimeDelta::FromSeconds(30)); |
| 298 DnsPrefetcherInit dns_init(NULL); |
| 304 | 299 |
| 305 std::string goog("www.google.com"), | 300 std::string goog("www.google.com"), |
| 306 goog2("gmail.google.com.com"), | 301 goog2("gmail.google.com.com"), |
| 307 goog3("mail.google.com"), | 302 goog3("mail.google.com"), |
| 308 goog4("gmail.com"); | 303 goog4("gmail.com"); |
| 309 std::string bad1(GetNonexistantDomain()), | 304 std::string bad1(GetNonexistantDomain()), |
| 310 bad2(GetNonexistantDomain()); | 305 bad2(GetNonexistantDomain()); |
| 311 | 306 |
| 312 NameList names; | 307 NameList names; |
| 313 names.insert(names.end(), goog); | 308 names.insert(names.end(), goog); |
| 314 names.insert(names.end(), goog3); | 309 names.insert(names.end(), goog3); |
| 315 names.insert(names.end(), bad1); | 310 names.insert(names.end(), bad1); |
| 316 names.insert(names.end(), goog2); | 311 names.insert(names.end(), goog2); |
| 317 names.insert(names.end(), bad2); | 312 names.insert(names.end(), bad2); |
| 318 names.insert(names.end(), goog4); | 313 names.insert(names.end(), goog4); |
| 319 names.insert(names.end(), goog); | 314 names.insert(names.end(), goog); |
| 320 | 315 |
| 321 // Warm up the *OS* cache for all the goog domains. | 316 // Warm up the *OS* cache for all the goog domains. |
| 322 BlockingDnsLookup(goog); | 317 BlockingDnsLookup(goog); |
| 323 BlockingDnsLookup(goog2); | 318 BlockingDnsLookup(goog2); |
| 324 BlockingDnsLookup(goog3); | 319 BlockingDnsLookup(goog3); |
| 325 BlockingDnsLookup(goog4); | 320 BlockingDnsLookup(goog4); |
| 326 | 321 |
| 327 // Try to flood the master with many concurrent requests. | 322 // Get all 8 threads running by calling many times before queue is handled. |
| 328 for (int i = 0; i < 10; i++) | 323 for (int i = 0; i < 10; i++) { |
| 329 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); | 324 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); |
| 325 } |
| 330 | 326 |
| 331 WaitForResolution(&testing_master, names); | 327 Sleep(10); // Allow time for async DNS to get answers. |
| 332 | 328 |
| 333 EXPECT_TRUE(testing_master.WasFound(goog)); | 329 EXPECT_TRUE(testing_master.WasFound(goog)); |
| 334 EXPECT_TRUE(testing_master.WasFound(goog3)); | 330 EXPECT_TRUE(testing_master.WasFound(goog3)); |
| 335 EXPECT_TRUE(testing_master.WasFound(goog2)); | 331 EXPECT_TRUE(testing_master.WasFound(goog2)); |
| 336 EXPECT_TRUE(testing_master.WasFound(goog4)); | 332 EXPECT_TRUE(testing_master.WasFound(goog4)); |
| 337 EXPECT_FALSE(testing_master.WasFound(bad1)); | 333 EXPECT_FALSE(testing_master.WasFound(bad1)); |
| 338 EXPECT_FALSE(testing_master.WasFound(bad2)); | 334 EXPECT_FALSE(testing_master.WasFound(bad2)); |
| 339 | 335 |
| 340 MessageLoop::current()->RunAllPending(); | 336 EXPECT_EQ(8U, testing_master.running_slave_count()); |
| 337 |
| 338 EXPECT_TRUE(testing_master.ShutdownSlaves()); |
| 339 } |
| 340 |
| 341 TEST(DnsMasterTest, DISABLED_MultiThreadedSpeedupTest) { |
| 342 SetupNetworkInfrastructure(); |
| 343 net::EnsureWinsockInit(); |
| 344 DnsMaster testing_master(TimeDelta::FromSeconds(30)); |
| 345 DnsPrefetcherInit dns_init(NULL); |
| 346 |
| 347 std::string goog("www.google.com"), |
| 348 goog2("gmail.google.com.com"), |
| 349 goog3("mail.google.com"), |
| 350 goog4("gmail.com"); |
| 351 std::string bad1(GetNonexistantDomain()), |
| 352 bad2(GetNonexistantDomain()), |
| 353 bad3(GetNonexistantDomain()), |
| 354 bad4(GetNonexistantDomain()); |
| 355 |
| 356 NameList names; |
| 357 names.insert(names.end(), goog); |
| 358 names.insert(names.end(), bad1); |
| 359 names.insert(names.end(), bad2); |
| 360 names.insert(names.end(), goog3); |
| 361 names.insert(names.end(), goog2); |
| 362 names.insert(names.end(), bad3); |
| 363 names.insert(names.end(), bad4); |
| 364 names.insert(names.end(), goog4); |
| 365 |
| 366 // First cause a lookup using a single thread. |
| 367 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); |
| 368 |
| 369 // Wait for some resoultion for google. |
| 370 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 371 testing_master.GetResolutionDuration(goog).InMilliseconds()); |
| 372 |
| 373 EXPECT_TRUE(testing_master.WasFound(goog)); |
| 374 EXPECT_FALSE(testing_master.WasFound(bad1)); |
| 375 EXPECT_FALSE(testing_master.WasFound(bad2)); |
| 376 // ...and due to delay in geting resolution of bad names, the single slave |
| 377 // thread won't have time to finish the list. |
| 378 EXPECT_FALSE(testing_master.WasFound(goog3)); |
| 379 EXPECT_FALSE(testing_master.WasFound(goog2)); |
| 380 EXPECT_FALSE(testing_master.WasFound(goog4)); |
| 381 |
| 382 EXPECT_EQ(1U, testing_master.running_slave_count()); |
| 383 |
| 384 // Get all 8 threads running by calling many times before queue is handled. |
| 385 names.clear(); |
| 386 for (int i = 0; i < 10; i++) |
| 387 testing_master.Resolve(GetNonexistantDomain(), |
| 388 DnsHostInfo::PAGE_SCAN_MOTIVATED); |
| 389 |
| 390 // Wait long enough for all the goog's to be resolved. |
| 391 // They should all take about the same time, and run in parallel. |
| 392 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 393 testing_master.GetResolutionDuration(goog2).InMilliseconds()); |
| 394 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 395 testing_master.GetResolutionDuration(goog3).InMilliseconds()); |
| 396 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 397 testing_master.GetResolutionDuration(goog4).InMilliseconds()); |
| 398 |
| 399 EXPECT_TRUE(testing_master.WasFound(goog3)); |
| 400 EXPECT_TRUE(testing_master.WasFound(goog2)); |
| 401 EXPECT_TRUE(testing_master.WasFound(goog4)); |
| 341 | 402 |
| 342 EXPECT_FALSE(testing_master.WasFound(bad1)); | 403 EXPECT_FALSE(testing_master.WasFound(bad1)); |
| 343 EXPECT_FALSE(testing_master.WasFound(bad2)); | 404 EXPECT_FALSE(testing_master.WasFound(bad2)); // Perhaps not even decided. |
| 344 | 405 |
| 345 EXPECT_GT(testing_master.peak_pending_lookups(), names.size() / 2); | 406 // Queue durations should be distinct from when 1 slave was working. |
| 346 EXPECT_LE(testing_master.peak_pending_lookups(), names.size()); | 407 EXPECT_GT(testing_master.GetQueueDuration(goog3).InMilliseconds(), |
| 347 EXPECT_LE(testing_master.peak_pending_lookups(), | 408 testing_master.GetQueueDuration(goog).InMilliseconds()); |
| 348 DnsMaster::kMaxConcurrentLookups); | 409 EXPECT_GT(testing_master.GetQueueDuration(goog4).InMilliseconds(), |
| 410 testing_master.GetQueueDuration(goog).InMilliseconds()); |
| 411 |
| 412 // Give bad names a chance to be determined as unresolved. |
| 413 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 414 testing_master.GetResolutionDuration(bad1).InMilliseconds()); |
| 415 SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(0 <= |
| 416 testing_master.GetResolutionDuration(bad2).InMilliseconds()); |
| 417 |
| 418 |
| 419 // Well known names should resolve faster than bad names. |
| 420 EXPECT_GE(testing_master.GetResolutionDuration(bad1).InMilliseconds(), |
| 421 testing_master.GetResolutionDuration(goog).InMilliseconds()); |
| 422 |
| 423 EXPECT_GE(testing_master.GetResolutionDuration(bad2).InMilliseconds(), |
| 424 testing_master.GetResolutionDuration(goog4).InMilliseconds()); |
| 425 |
| 426 EXPECT_EQ(8U, testing_master.running_slave_count()); |
| 427 |
| 428 EXPECT_TRUE(testing_master.ShutdownSlaves()); |
| 349 } | 429 } |
| 350 | 430 |
| 351 TEST_F(DnsMasterTest, MassiveConcurrentLookupTest) { | 431 } // namespace |
| 352 DnsMaster testing_master; | |
| 353 | 432 |
| 354 NameList names; | |
| 355 for (int i = 0; i < 100; i++) | |
| 356 names.push_back(GetNonexistantDomain()); | |
| 357 | |
| 358 // Try to flood the master with many concurrent requests. | |
| 359 for (int i = 0; i < 10; i++) | |
| 360 testing_master.ResolveList(names, DnsHostInfo::PAGE_SCAN_MOTIVATED); | |
| 361 | |
| 362 WaitForResolution(&testing_master, names); | |
| 363 | |
| 364 MessageLoop::current()->RunAllPending(); | |
| 365 | |
| 366 EXPECT_LE(testing_master.peak_pending_lookups(), names.size()); | |
| 367 EXPECT_LE(testing_master.peak_pending_lookups(), | |
| 368 DnsMaster::kMaxConcurrentLookups); | |
| 369 } | |
| 370 | |
| 371 } // namespace chrome_browser_net | |
| OLD | NEW |