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