| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <time.h> | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <sstream> | |
| 9 #include <string> | |
| 10 | |
| 11 #include "base/message_loop.h" | |
| 12 #include "base/scoped_ptr.h" | |
| 13 #include "base/string_util.h" | |
| 14 #include "base/timer.h" | |
| 15 #include "chrome/browser/chrome_thread.h" | |
| 16 #include "chrome/browser/net/dns_global.h" | |
| 17 #include "chrome/browser/net/dns_host_info.h" | |
| 18 #include "chrome/common/net/dns.h" | |
| 19 #include "net/base/address_list.h" | |
| 20 #include "net/base/mock_host_resolver.h" | |
| 21 #include "net/base/winsock_init.h" | |
| 22 #include "testing/gtest/include/gtest/gtest.h" | |
| 23 | |
| 24 using base::Time; | |
| 25 using base::TimeDelta; | |
| 26 | |
| 27 namespace chrome_browser_net { | |
| 28 | |
| 29 class WaitForResolutionHelper; | |
| 30 | |
| 31 typedef base::RepeatingTimer<WaitForResolutionHelper> HelperTimer; | |
| 32 | |
| 33 class WaitForResolutionHelper { | |
| 34 public: | |
| 35 WaitForResolutionHelper(Predictor* predictor, const UrlList& hosts, | |
| 36 HelperTimer* timer) | |
| 37 : predictor_(predictor), | |
| 38 hosts_(hosts), | |
| 39 timer_(timer) { | |
| 40 } | |
| 41 | |
| 42 void Run() { | |
| 43 for (UrlList::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i) | |
| 44 if (predictor_->GetResolutionDuration(*i) == | |
| 45 UrlInfo::kNullDuration) | |
| 46 return; // We don't have resolution for that host. | |
| 47 | |
| 48 // When all hostnames have been resolved, exit the loop. | |
| 49 timer_->Stop(); | |
| 50 MessageLoop::current()->Quit(); | |
| 51 delete timer_; | |
| 52 delete this; | |
| 53 } | |
| 54 | |
| 55 private: | |
| 56 Predictor* predictor_; | |
| 57 const UrlList hosts_; | |
| 58 HelperTimer* timer_; | |
| 59 }; | |
| 60 | |
| 61 class PredictorTest : public testing::Test { | |
| 62 public: | |
| 63 PredictorTest() | |
| 64 : io_thread_(ChromeThread::IO, &loop_), | |
| 65 host_resolver_(new net::MockCachingHostResolver()), | |
| 66 default_max_queueing_delay_(TimeDelta::FromMilliseconds( | |
| 67 PredictorInit::kMaxPrefetchQueueingDelayMs)) { | |
| 68 } | |
| 69 | |
| 70 protected: | |
| 71 virtual void SetUp() { | |
| 72 #if defined(OS_WIN) | |
| 73 net::EnsureWinsockInit(); | |
| 74 #endif | |
| 75 // Since we are using a caching HostResolver, the following latencies will | |
| 76 // only be incurred by the first request, after which the result will be | |
| 77 // cached internally by |host_resolver_|. | |
| 78 net::RuleBasedHostResolverProc* rules = host_resolver_->rules(); | |
| 79 rules->AddRuleWithLatency("www.google.com", "127.0.0.1", 50); | |
| 80 rules->AddRuleWithLatency("gmail.google.com.com", "127.0.0.1", 70); | |
| 81 rules->AddRuleWithLatency("mail.google.com", "127.0.0.1", 44); | |
| 82 rules->AddRuleWithLatency("gmail.com", "127.0.0.1", 63); | |
| 83 } | |
| 84 | |
| 85 void WaitForResolution(Predictor* predictor, const UrlList& hosts) { | |
| 86 HelperTimer* timer = new HelperTimer(); | |
| 87 timer->Start(TimeDelta::FromMilliseconds(100), | |
| 88 new WaitForResolutionHelper(predictor, hosts, timer), | |
| 89 &WaitForResolutionHelper::Run); | |
| 90 MessageLoop::current()->Run(); | |
| 91 } | |
| 92 | |
| 93 private: | |
| 94 // IMPORTANT: do not move this below |host_resolver_|; the host resolver | |
| 95 // must not outlive the message loop, otherwise bad things can happen | |
| 96 // (like posting to a deleted message loop). | |
| 97 MessageLoop loop_; | |
| 98 ChromeThread io_thread_; | |
| 99 | |
| 100 protected: | |
| 101 scoped_refptr<net::MockCachingHostResolver> host_resolver_; | |
| 102 | |
| 103 // Shorthand to access TimeDelta of PredictorInit::kMaxQueueingDelayMs. | |
| 104 // (It would be a static constant... except style rules preclude that :-/ ). | |
| 105 const TimeDelta default_max_queueing_delay_; | |
| 106 }; | |
| 107 | |
| 108 //------------------------------------------------------------------------------ | |
| 109 | |
| 110 TEST_F(PredictorTest, StartupShutdownTest) { | |
| 111 scoped_refptr<Predictor> testing_master = new Predictor(host_resolver_, | |
| 112 default_max_queueing_delay_, | |
| 113 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 114 false); | |
| 115 testing_master->Shutdown(); | |
| 116 } | |
| 117 | |
| 118 TEST_F(PredictorTest, BenefitLookupTest) { | |
| 119 scoped_refptr<Predictor> testing_master = new Predictor( | |
| 120 host_resolver_, | |
| 121 default_max_queueing_delay_, | |
| 122 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 123 false); | |
| 124 | |
| 125 GURL goog("http://www.google.com:80"), | |
| 126 goog2("http://gmail.google.com.com:80"), | |
| 127 goog3("http://mail.google.com:80"), | |
| 128 goog4("http://gmail.com:80"); | |
| 129 UrlInfo goog_info, goog2_info, goog3_info, goog4_info; | |
| 130 | |
| 131 // Simulate getting similar names from a network observer | |
| 132 goog_info.SetUrl(goog); | |
| 133 goog2_info.SetUrl(goog2); | |
| 134 goog3_info.SetUrl(goog3); | |
| 135 goog4_info.SetUrl(goog4); | |
| 136 | |
| 137 goog_info.SetStartedState(); | |
| 138 goog2_info.SetStartedState(); | |
| 139 goog3_info.SetStartedState(); | |
| 140 goog4_info.SetStartedState(); | |
| 141 | |
| 142 goog_info.SetFinishedState(true); | |
| 143 goog2_info.SetFinishedState(true); | |
| 144 goog3_info.SetFinishedState(true); | |
| 145 goog4_info.SetFinishedState(true); | |
| 146 | |
| 147 UrlList names; | |
| 148 names.push_back(goog); | |
| 149 names.push_back(goog2); | |
| 150 names.push_back(goog3); | |
| 151 names.push_back(goog4); | |
| 152 | |
| 153 testing_master->ResolveList(names, UrlInfo::PAGE_SCAN_MOTIVATED); | |
| 154 | |
| 155 WaitForResolution(testing_master, names); | |
| 156 | |
| 157 EXPECT_TRUE(testing_master->WasFound(goog)); | |
| 158 EXPECT_TRUE(testing_master->WasFound(goog2)); | |
| 159 EXPECT_TRUE(testing_master->WasFound(goog3)); | |
| 160 EXPECT_TRUE(testing_master->WasFound(goog4)); | |
| 161 | |
| 162 // With the mock DNS, each of these should have taken some time, and hence | |
| 163 // shown a benefit (i.e., prefetch cost more than network access time). | |
| 164 | |
| 165 GURL referer; // Null host. | |
| 166 | |
| 167 // Simulate actual navigation, and acrue the benefit for "helping" the DNS | |
| 168 // part of the navigation. | |
| 169 EXPECT_TRUE(testing_master->AccruePrefetchBenefits(referer, &goog_info)); | |
| 170 EXPECT_TRUE(testing_master->AccruePrefetchBenefits(referer, &goog2_info)); | |
| 171 EXPECT_TRUE(testing_master->AccruePrefetchBenefits(referer, &goog3_info)); | |
| 172 EXPECT_TRUE(testing_master->AccruePrefetchBenefits(referer, &goog4_info)); | |
| 173 | |
| 174 // Benefits can ONLY be reported once (for the first navigation). | |
| 175 EXPECT_FALSE(testing_master->AccruePrefetchBenefits(referer, &goog_info)); | |
| 176 EXPECT_FALSE(testing_master->AccruePrefetchBenefits(referer, &goog2_info)); | |
| 177 EXPECT_FALSE(testing_master->AccruePrefetchBenefits(referer, &goog3_info)); | |
| 178 EXPECT_FALSE(testing_master->AccruePrefetchBenefits(referer, &goog4_info)); | |
| 179 | |
| 180 testing_master->Shutdown(); | |
| 181 } | |
| 182 | |
| 183 TEST_F(PredictorTest, ShutdownWhenResolutionIsPendingTest) { | |
| 184 scoped_refptr<net::WaitingHostResolverProc> resolver_proc = | |
| 185 new net::WaitingHostResolverProc(NULL); | |
| 186 host_resolver_->Reset(resolver_proc); | |
| 187 | |
| 188 scoped_refptr<Predictor> testing_master = new Predictor(host_resolver_, | |
| 189 default_max_queueing_delay_, | |
| 190 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 191 false); | |
| 192 | |
| 193 GURL localhost("http://127.0.0.1:80"); | |
| 194 UrlList names; | |
| 195 names.push_back(localhost); | |
| 196 | |
| 197 testing_master->ResolveList(names, UrlInfo::PAGE_SCAN_MOTIVATED); | |
| 198 | |
| 199 MessageLoop::current()->PostDelayedTask(FROM_HERE, | |
| 200 new MessageLoop::QuitTask(), 500); | |
| 201 MessageLoop::current()->Run(); | |
| 202 | |
| 203 EXPECT_FALSE(testing_master->WasFound(localhost)); | |
| 204 | |
| 205 testing_master->Shutdown(); | |
| 206 | |
| 207 // Clean up after ourselves. | |
| 208 resolver_proc->Signal(); | |
| 209 MessageLoop::current()->RunAllPending(); | |
| 210 } | |
| 211 | |
| 212 TEST_F(PredictorTest, SingleLookupTest) { | |
| 213 scoped_refptr<Predictor> testing_master = new Predictor(host_resolver_, | |
| 214 default_max_queueing_delay_, | |
| 215 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 216 false); | |
| 217 | |
| 218 GURL goog("http://www.google.com:80"); | |
| 219 | |
| 220 UrlList names; | |
| 221 names.push_back(goog); | |
| 222 | |
| 223 // Try to flood the predictor with many concurrent requests. | |
| 224 for (int i = 0; i < 10; i++) | |
| 225 testing_master->ResolveList(names, UrlInfo::PAGE_SCAN_MOTIVATED); | |
| 226 | |
| 227 WaitForResolution(testing_master, names); | |
| 228 | |
| 229 EXPECT_TRUE(testing_master->WasFound(goog)); | |
| 230 | |
| 231 MessageLoop::current()->RunAllPending(); | |
| 232 | |
| 233 EXPECT_GT(testing_master->peak_pending_lookups(), names.size() / 2); | |
| 234 EXPECT_LE(testing_master->peak_pending_lookups(), names.size()); | |
| 235 EXPECT_LE(testing_master->peak_pending_lookups(), | |
| 236 testing_master->max_concurrent_dns_lookups()); | |
| 237 | |
| 238 testing_master->Shutdown(); | |
| 239 } | |
| 240 | |
| 241 TEST_F(PredictorTest, ConcurrentLookupTest) { | |
| 242 host_resolver_->rules()->AddSimulatedFailure("*.notfound"); | |
| 243 | |
| 244 scoped_refptr<Predictor> testing_master = new Predictor(host_resolver_, | |
| 245 default_max_queueing_delay_, | |
| 246 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 247 false); | |
| 248 | |
| 249 GURL goog("http://www.google.com:80"), | |
| 250 goog2("http://gmail.google.com.com:80"), | |
| 251 goog3("http://mail.google.com:80"), | |
| 252 goog4("http://gmail.com:80"); | |
| 253 GURL bad1("http://bad1.notfound:80"), | |
| 254 bad2("http://bad2.notfound:80"); | |
| 255 | |
| 256 UrlList names; | |
| 257 names.push_back(goog); | |
| 258 names.push_back(goog3); | |
| 259 names.push_back(bad1); | |
| 260 names.push_back(goog2); | |
| 261 names.push_back(bad2); | |
| 262 names.push_back(goog4); | |
| 263 names.push_back(goog); | |
| 264 | |
| 265 // Try to flood the predictor with many concurrent requests. | |
| 266 for (int i = 0; i < 10; i++) | |
| 267 testing_master->ResolveList(names, UrlInfo::PAGE_SCAN_MOTIVATED); | |
| 268 | |
| 269 WaitForResolution(testing_master, names); | |
| 270 | |
| 271 EXPECT_TRUE(testing_master->WasFound(goog)); | |
| 272 EXPECT_TRUE(testing_master->WasFound(goog3)); | |
| 273 EXPECT_TRUE(testing_master->WasFound(goog2)); | |
| 274 EXPECT_TRUE(testing_master->WasFound(goog4)); | |
| 275 EXPECT_FALSE(testing_master->WasFound(bad1)); | |
| 276 EXPECT_FALSE(testing_master->WasFound(bad2)); | |
| 277 | |
| 278 MessageLoop::current()->RunAllPending(); | |
| 279 | |
| 280 EXPECT_FALSE(testing_master->WasFound(bad1)); | |
| 281 EXPECT_FALSE(testing_master->WasFound(bad2)); | |
| 282 | |
| 283 EXPECT_GT(testing_master->peak_pending_lookups(), names.size() / 2); | |
| 284 EXPECT_LE(testing_master->peak_pending_lookups(), names.size()); | |
| 285 EXPECT_LE(testing_master->peak_pending_lookups(), | |
| 286 testing_master->max_concurrent_dns_lookups()); | |
| 287 | |
| 288 testing_master->Shutdown(); | |
| 289 } | |
| 290 | |
| 291 TEST_F(PredictorTest, MassiveConcurrentLookupTest) { | |
| 292 host_resolver_->rules()->AddSimulatedFailure("*.notfound"); | |
| 293 | |
| 294 scoped_refptr<Predictor> testing_master = new Predictor( | |
| 295 host_resolver_, | |
| 296 default_max_queueing_delay_, | |
| 297 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 298 false); | |
| 299 | |
| 300 UrlList names; | |
| 301 for (int i = 0; i < 100; i++) | |
| 302 names.push_back(GURL("http://host" + IntToString(i) + ".notfound:80")); | |
| 303 | |
| 304 // Try to flood the predictor with many concurrent requests. | |
| 305 for (int i = 0; i < 10; i++) | |
| 306 testing_master->ResolveList(names, UrlInfo::PAGE_SCAN_MOTIVATED); | |
| 307 | |
| 308 WaitForResolution(testing_master, names); | |
| 309 | |
| 310 MessageLoop::current()->RunAllPending(); | |
| 311 | |
| 312 EXPECT_LE(testing_master->peak_pending_lookups(), names.size()); | |
| 313 EXPECT_LE(testing_master->peak_pending_lookups(), | |
| 314 testing_master->max_concurrent_dns_lookups()); | |
| 315 | |
| 316 testing_master->Shutdown(); | |
| 317 } | |
| 318 | |
| 319 //------------------------------------------------------------------------------ | |
| 320 // Functions to help synthesize and test serializations of subresource referrer | |
| 321 // lists. | |
| 322 | |
| 323 // Return a motivation_list if we can find one for the given motivating_host (or | |
| 324 // NULL if a match is not found). | |
| 325 static ListValue* FindSerializationMotivation( | |
| 326 const GURL& motivation, const ListValue& referral_list) { | |
| 327 CHECK_LT(0u, referral_list.GetSize()); // Room for version. | |
| 328 int format_version = -1; | |
| 329 CHECK(referral_list.GetInteger(0, &format_version)); | |
| 330 CHECK_EQ(Predictor::DNS_REFERRER_VERSION, format_version); | |
| 331 ListValue* motivation_list(NULL); | |
| 332 for (size_t i = 1; i < referral_list.GetSize(); ++i) { | |
| 333 referral_list.GetList(i, &motivation_list); | |
| 334 std::string existing_spec; | |
| 335 EXPECT_TRUE(motivation_list->GetString(0, &existing_spec)); | |
| 336 if (motivation == GURL(existing_spec)) | |
| 337 return motivation_list; | |
| 338 } | |
| 339 return NULL; | |
| 340 } | |
| 341 | |
| 342 // Create a new empty serialization list. | |
| 343 static ListValue* NewEmptySerializationList() { | |
| 344 ListValue* list = new ListValue; | |
| 345 list->Append(new FundamentalValue(Predictor::DNS_REFERRER_VERSION)); | |
| 346 return list; | |
| 347 } | |
| 348 | |
| 349 // Add a motivating_host and a subresource_host to a serialized list, using | |
| 350 // this given latency. This is a helper function for quickly building these | |
| 351 // lists. | |
| 352 static void AddToSerializedList(const GURL& motivation, | |
| 353 const GURL& subresource, | |
| 354 int latency, | |
| 355 double rate, | |
| 356 ListValue* referral_list ) { | |
| 357 // Find the motivation if it is already used. | |
| 358 ListValue* motivation_list = FindSerializationMotivation(motivation, | |
| 359 *referral_list); | |
| 360 if (!motivation_list) { | |
| 361 // This is the first mention of this motivation, so build a list. | |
| 362 motivation_list = new ListValue; | |
| 363 motivation_list->Append(new StringValue(motivation.spec())); | |
| 364 // Provide empty subresource list. | |
| 365 motivation_list->Append(new ListValue()); | |
| 366 | |
| 367 // ...and make it part of the serialized referral_list. | |
| 368 referral_list->Append(motivation_list); | |
| 369 } | |
| 370 | |
| 371 ListValue* subresource_list(NULL); | |
| 372 // 0 == url; 1 == subresource_list. | |
| 373 EXPECT_TRUE(motivation_list->GetList(1, &subresource_list)); | |
| 374 | |
| 375 // We won't bother to check for the subresource being there already. Worst | |
| 376 // case, during deserialization, the latency value we supply plus the | |
| 377 // existing value(s) will be added to the referrer. | |
| 378 | |
| 379 subresource_list->Append(new StringValue(subresource.spec())); | |
| 380 subresource_list->Append(new FundamentalValue(latency)); | |
| 381 subresource_list->Append(new FundamentalValue(rate)); | |
| 382 } | |
| 383 | |
| 384 static const int kLatencyNotFound = -1; | |
| 385 | |
| 386 // For a given motivation, and subresource, find what latency is currently | |
| 387 // listed. This assume a well formed serialization, which has at most one such | |
| 388 // entry for any pair of names. If no such pair is found, then return false. | |
| 389 // Data is written into rate and latency arguments. | |
| 390 static bool GetDataFromSerialization(const GURL& motivation, | |
| 391 const GURL& subresource, | |
| 392 const ListValue& referral_list, | |
| 393 double* rate, | |
| 394 int* latency) { | |
| 395 ListValue* motivation_list = FindSerializationMotivation(motivation, | |
| 396 referral_list); | |
| 397 if (!motivation_list) | |
| 398 return false; | |
| 399 ListValue* subresource_list; | |
| 400 EXPECT_TRUE(motivation_list->GetList(1, &subresource_list)); | |
| 401 for (size_t i = 0; i < subresource_list->GetSize();) { | |
| 402 std::string url_spec; | |
| 403 EXPECT_TRUE(subresource_list->GetString(i++, &url_spec)); | |
| 404 EXPECT_TRUE(subresource_list->GetInteger(i++, latency)); | |
| 405 EXPECT_TRUE(subresource_list->GetReal(i++, rate)); | |
| 406 if (subresource == GURL(url_spec)) { | |
| 407 return true; | |
| 408 } | |
| 409 } | |
| 410 return false; | |
| 411 } | |
| 412 | |
| 413 //------------------------------------------------------------------------------ | |
| 414 | |
| 415 // Make sure nil referral lists really have no entries, and no latency listed. | |
| 416 TEST_F(PredictorTest, ReferrerSerializationNilTest) { | |
| 417 scoped_refptr<Predictor> predictor = new Predictor(host_resolver_, | |
| 418 default_max_queueing_delay_, | |
| 419 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 420 false); | |
| 421 scoped_ptr<ListValue> referral_list(NewEmptySerializationList()); | |
| 422 predictor->SerializeReferrers(referral_list.get()); | |
| 423 EXPECT_EQ(1U, referral_list->GetSize()); | |
| 424 EXPECT_FALSE(GetDataFromSerialization( | |
| 425 GURL("http://a.com:79"), GURL("http://b.com:78"), | |
| 426 *referral_list.get(), NULL, NULL)); | |
| 427 | |
| 428 predictor->Shutdown(); | |
| 429 } | |
| 430 | |
| 431 // Make sure that when a serialization list includes a value, that it can be | |
| 432 // deserialized into the database, and can be extracted back out via | |
| 433 // serialization without being changed. | |
| 434 TEST_F(PredictorTest, ReferrerSerializationSingleReferrerTest) { | |
| 435 scoped_refptr<Predictor> predictor = new Predictor(host_resolver_, | |
| 436 default_max_queueing_delay_, | |
| 437 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 438 false); | |
| 439 const GURL motivation_url("http://www.google.com:91"); | |
| 440 const GURL subresource_url("http://icons.google.com:90"); | |
| 441 const int kLatency = 3; | |
| 442 const double kRate = 23.4; | |
| 443 scoped_ptr<ListValue> referral_list(NewEmptySerializationList()); | |
| 444 | |
| 445 AddToSerializedList(motivation_url, subresource_url, | |
| 446 kLatency, kRate, referral_list.get()); | |
| 447 | |
| 448 predictor->DeserializeReferrers(*referral_list.get()); | |
| 449 | |
| 450 ListValue recovered_referral_list; | |
| 451 predictor->SerializeReferrers(&recovered_referral_list); | |
| 452 EXPECT_EQ(2U, recovered_referral_list.GetSize()); | |
| 453 int latency; | |
| 454 double rate; | |
| 455 EXPECT_TRUE(GetDataFromSerialization( | |
| 456 motivation_url, subresource_url, recovered_referral_list, &rate, | |
| 457 &latency)); | |
| 458 EXPECT_EQ(rate, kRate); | |
| 459 EXPECT_EQ(latency, kLatency); | |
| 460 | |
| 461 predictor->Shutdown(); | |
| 462 } | |
| 463 | |
| 464 // Make sure the Trim() functionality works as expected. | |
| 465 TEST_F(PredictorTest, ReferrerSerializationTrimTest) { | |
| 466 scoped_refptr<Predictor> predictor = new Predictor(host_resolver_, | |
| 467 default_max_queueing_delay_, | |
| 468 PredictorInit::kMaxPrefetchConcurrentLookups, | |
| 469 false); | |
| 470 GURL motivation_url("http://www.google.com:110"); | |
| 471 | |
| 472 GURL icon_subresource_url("http://icons.google.com:111"); | |
| 473 const int kLatencyIcon = 10; | |
| 474 const double kRateIcon = 0.; // User low rate, so latency will dominate. | |
| 475 GURL img_subresource_url("http://img.google.com:118"); | |
| 476 const int kLatencyImg = 3; | |
| 477 const double kRateImg = 0.; | |
| 478 | |
| 479 scoped_ptr<ListValue> referral_list(NewEmptySerializationList()); | |
| 480 AddToSerializedList( | |
| 481 motivation_url, icon_subresource_url, | |
| 482 kLatencyIcon, kRateIcon, referral_list.get()); | |
| 483 AddToSerializedList( | |
| 484 motivation_url, img_subresource_url, | |
| 485 kLatencyImg, kRateImg, referral_list.get()); | |
| 486 | |
| 487 predictor->DeserializeReferrers(*referral_list.get()); | |
| 488 | |
| 489 ListValue recovered_referral_list; | |
| 490 predictor->SerializeReferrers(&recovered_referral_list); | |
| 491 EXPECT_EQ(2U, recovered_referral_list.GetSize()); | |
| 492 int latency; | |
| 493 double rate; | |
| 494 EXPECT_TRUE(GetDataFromSerialization( | |
| 495 motivation_url, icon_subresource_url, recovered_referral_list, | |
| 496 &rate, &latency)); | |
| 497 EXPECT_EQ(latency, kLatencyIcon); | |
| 498 EXPECT_EQ(rate, kRateIcon); | |
| 499 | |
| 500 EXPECT_TRUE(GetDataFromSerialization( | |
| 501 motivation_url, img_subresource_url, recovered_referral_list, | |
| 502 &rate, &latency)); | |
| 503 EXPECT_EQ(latency, kLatencyImg); | |
| 504 EXPECT_EQ(rate, kRateImg); | |
| 505 | |
| 506 // Each time we Trim, the latency figures should reduce by a factor of two, | |
| 507 // until they both are 0, an then a trim will delete the whole entry. | |
| 508 predictor->TrimReferrers(); | |
| 509 predictor->SerializeReferrers(&recovered_referral_list); | |
| 510 EXPECT_EQ(2U, recovered_referral_list.GetSize()); | |
| 511 EXPECT_TRUE(GetDataFromSerialization( | |
| 512 motivation_url, icon_subresource_url, recovered_referral_list, | |
| 513 &rate, &latency)); | |
| 514 EXPECT_EQ(latency, kLatencyIcon / 2); | |
| 515 EXPECT_EQ(rate, kRateIcon); | |
| 516 | |
| 517 EXPECT_TRUE(GetDataFromSerialization( | |
| 518 motivation_url, img_subresource_url, recovered_referral_list, | |
| 519 &rate, &latency)); | |
| 520 EXPECT_EQ(latency, kLatencyImg / 2); | |
| 521 EXPECT_EQ(rate, kRateImg); | |
| 522 | |
| 523 predictor->TrimReferrers(); | |
| 524 predictor->SerializeReferrers(&recovered_referral_list); | |
| 525 EXPECT_EQ(2U, recovered_referral_list.GetSize()); | |
| 526 EXPECT_TRUE(GetDataFromSerialization( | |
| 527 motivation_url, icon_subresource_url, recovered_referral_list, | |
| 528 &rate, &latency)); | |
| 529 EXPECT_EQ(latency, kLatencyIcon / 4); | |
| 530 EXPECT_EQ(rate, kRateIcon); | |
| 531 // Img is down to zero, but we don't delete it yet. | |
| 532 EXPECT_TRUE(GetDataFromSerialization( | |
| 533 motivation_url, img_subresource_url, recovered_referral_list, | |
| 534 &rate, &latency)); | |
| 535 EXPECT_EQ(kLatencyImg / 4, 0); | |
| 536 EXPECT_EQ(latency, kLatencyImg / 4); | |
| 537 EXPECT_EQ(rate, kRateImg); | |
| 538 | |
| 539 predictor->TrimReferrers(); | |
| 540 predictor->SerializeReferrers(&recovered_referral_list); | |
| 541 EXPECT_EQ(2U, recovered_referral_list.GetSize()); | |
| 542 EXPECT_TRUE(GetDataFromSerialization( | |
| 543 motivation_url, icon_subresource_url, recovered_referral_list, | |
| 544 &rate, &latency)); | |
| 545 EXPECT_EQ(latency, kLatencyIcon / 8); | |
| 546 EXPECT_EQ(rate, kRateIcon); | |
| 547 | |
| 548 // Img is down to zero, but we don't delete it yet. | |
| 549 EXPECT_TRUE(GetDataFromSerialization( | |
| 550 motivation_url, img_subresource_url, recovered_referral_list, | |
| 551 &rate, &latency)); | |
| 552 EXPECT_EQ(kLatencyImg / 8, 0); | |
| 553 EXPECT_EQ(latency, kLatencyImg / 8); | |
| 554 EXPECT_EQ(rate, kRateImg); | |
| 555 | |
| 556 predictor->TrimReferrers(); | |
| 557 predictor->SerializeReferrers(&recovered_referral_list); | |
| 558 // Icon is also trimmed away, so entire set gets discarded. | |
| 559 EXPECT_EQ(1U, recovered_referral_list.GetSize()); | |
| 560 EXPECT_FALSE(GetDataFromSerialization( | |
| 561 motivation_url, icon_subresource_url, recovered_referral_list, | |
| 562 &rate, &latency)); | |
| 563 EXPECT_FALSE(GetDataFromSerialization( | |
| 564 motivation_url, img_subresource_url, recovered_referral_list, | |
| 565 &rate, &latency)); | |
| 566 | |
| 567 predictor->Shutdown(); | |
| 568 } | |
| 569 | |
| 570 | |
| 571 TEST_F(PredictorTest, PriorityQueuePushPopTest) { | |
| 572 Predictor::HostNameQueue queue; | |
| 573 | |
| 574 GURL first("http://first:80"), second("http://second:90"); | |
| 575 | |
| 576 // First check high priority queue FIFO functionality. | |
| 577 EXPECT_TRUE(queue.IsEmpty()); | |
| 578 queue.Push(first, UrlInfo::LEARNED_REFERAL_MOTIVATED); | |
| 579 EXPECT_FALSE(queue.IsEmpty()); | |
| 580 queue.Push(second, UrlInfo::MOUSE_OVER_MOTIVATED); | |
| 581 EXPECT_FALSE(queue.IsEmpty()); | |
| 582 EXPECT_EQ(queue.Pop(), first); | |
| 583 EXPECT_FALSE(queue.IsEmpty()); | |
| 584 EXPECT_EQ(queue.Pop(), second); | |
| 585 EXPECT_TRUE(queue.IsEmpty()); | |
| 586 | |
| 587 // Then check low priority queue FIFO functionality. | |
| 588 queue.Push(first, UrlInfo::PAGE_SCAN_MOTIVATED); | |
| 589 EXPECT_FALSE(queue.IsEmpty()); | |
| 590 queue.Push(second, UrlInfo::OMNIBOX_MOTIVATED); | |
| 591 EXPECT_FALSE(queue.IsEmpty()); | |
| 592 EXPECT_EQ(queue.Pop(), first); | |
| 593 EXPECT_FALSE(queue.IsEmpty()); | |
| 594 EXPECT_EQ(queue.Pop(), second); | |
| 595 EXPECT_TRUE(queue.IsEmpty()); | |
| 596 } | |
| 597 | |
| 598 TEST_F(PredictorTest, PriorityQueueReorderTest) { | |
| 599 Predictor::HostNameQueue queue; | |
| 600 | |
| 601 // Push all the low priority items. | |
| 602 GURL low1("http://low1:80"), | |
| 603 low2("http://low2:80"), | |
| 604 low3("http://low3:443"), | |
| 605 low4("http://low4:80"), | |
| 606 low5("http://low5:80"), | |
| 607 hi1("http://hi1:80"), | |
| 608 hi2("http://hi2:80"), | |
| 609 hi3("http://hi3:80"); | |
| 610 | |
| 611 EXPECT_TRUE(queue.IsEmpty()); | |
| 612 queue.Push(low1, UrlInfo::PAGE_SCAN_MOTIVATED); | |
| 613 queue.Push(low2, UrlInfo::UNIT_TEST_MOTIVATED); | |
| 614 queue.Push(low3, UrlInfo::LINKED_MAX_MOTIVATED); | |
| 615 queue.Push(low4, UrlInfo::OMNIBOX_MOTIVATED); | |
| 616 queue.Push(low5, UrlInfo::STARTUP_LIST_MOTIVATED); | |
| 617 queue.Push(low4, UrlInfo::OMNIBOX_MOTIVATED); | |
| 618 | |
| 619 // Push all the high prority items | |
| 620 queue.Push(hi1, UrlInfo::LEARNED_REFERAL_MOTIVATED); | |
| 621 queue.Push(hi2, UrlInfo::STATIC_REFERAL_MOTIVATED); | |
| 622 queue.Push(hi3, UrlInfo::MOUSE_OVER_MOTIVATED); | |
| 623 | |
| 624 // Check that high priority stuff comes out first, and in FIFO order. | |
| 625 EXPECT_EQ(queue.Pop(), hi1); | |
| 626 EXPECT_EQ(queue.Pop(), hi2); | |
| 627 EXPECT_EQ(queue.Pop(), hi3); | |
| 628 | |
| 629 // ...and then low priority strings. | |
| 630 EXPECT_EQ(queue.Pop(), low1); | |
| 631 EXPECT_EQ(queue.Pop(), low2); | |
| 632 EXPECT_EQ(queue.Pop(), low3); | |
| 633 EXPECT_EQ(queue.Pop(), low4); | |
| 634 EXPECT_EQ(queue.Pop(), low5); | |
| 635 EXPECT_EQ(queue.Pop(), low4); | |
| 636 | |
| 637 EXPECT_TRUE(queue.IsEmpty()); | |
| 638 } | |
| 639 | |
| 640 } // namespace chrome_browser_net | |
| OLD | NEW |