| 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 |