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