This source file includes following definitions.
- RunOnDBThread
 
- DoneRunOnMainThread
 
- waiting_
 
- QueryTopSites
 
- QueryAllTopSites
 
- CancelRequest
 
- set_urls
 
- urls
 
- number_of_callbacks
 
- OnTopSitesAvailable
 
- ExtractThumbnail
 
- ThumbnailsAreEqual
 
- db_thread_
 
- SetUp
 
- TearDown
 
- CreateHistoryAndTopSites
 
- GetThumbnail
 
- CreateBitmap
 
- RefreshTopSitesAndRecreate
 
- WaitForHistory
 
- WaitForTopSites
 
- top_sites
 
- consumer
 
- profile
 
- history_service
 
- GetPrepopulatePages
 
- ContainsPrepopulatePages
 
- EmptyCallback
 
- QuitCallback
 
- AddPageToHistory
 
- AddPageToHistory
 
- AddPageToHistory
 
- DeleteURL
 
- ThumbnailEqualsBytes
 
- RecreateTopSitesAndBlock
 
- GetCanonicalURL
 
- SetTopSites
 
- AddForcedURL
 
- StartQueryForMostVisited
 
- SetLastNumUrlsChanged
 
- last_num_urls_changed
 
- GetUpdateDelay
 
- IsTopSitesLoaded
 
- AddPrepopulatedPages
 
- EmptyThreadSafeCache
 
- AppendMostVisitedURL
 
- AppendForcedMostVisitedURL
 
- AppendMostVisitedURLWithRedirect
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
- TEST_F
 
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/history/history_db_task.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/history_types.h"
#include "chrome/browser/history/history_unittest_base.h"
#include "chrome/browser/history/top_sites_cache.h"
#include "chrome/browser/history/top_sites_impl.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "url/gurl.h"
using content::BrowserThread;
namespace history {
namespace {
class WaitForHistoryTask : public HistoryDBTask {
 public:
  WaitForHistoryTask() {}
  virtual bool RunOnDBThread(HistoryBackend* backend,
                             HistoryDatabase* db) OVERRIDE {
    return true;
  }
  virtual void DoneRunOnMainThread() OVERRIDE {
    base::MessageLoop::current()->Quit();
  }
 private:
  virtual ~WaitForHistoryTask() {}
  DISALLOW_COPY_AND_ASSIGN(WaitForHistoryTask);
};
class TopSitesQuerier {
 public:
  TopSitesQuerier()
      : weak_ptr_factory_(this),
        number_of_callbacks_(0),
        waiting_(false) {}
  
  
  void QueryTopSites(TopSitesImpl* top_sites, bool wait) {
    QueryAllTopSites(top_sites, wait, false);
  }
  
  
  void QueryAllTopSites(TopSitesImpl* top_sites,
                        bool wait,
                        bool include_forced_urls) {
    int start_number_of_callbacks = number_of_callbacks_;
    top_sites->GetMostVisitedURLs(
        base::Bind(&TopSitesQuerier::OnTopSitesAvailable,
                   weak_ptr_factory_.GetWeakPtr()),
        include_forced_urls);
    if (wait && start_number_of_callbacks == number_of_callbacks_) {
      waiting_ = true;
      base::MessageLoop::current()->Run();
    }
  }
  void CancelRequest() {
    weak_ptr_factory_.InvalidateWeakPtrs();
  }
  void set_urls(const MostVisitedURLList& urls) { urls_ = urls; }
  const MostVisitedURLList& urls() const { return urls_; }
  int number_of_callbacks() const { return number_of_callbacks_; }
 private:
  
  void OnTopSitesAvailable(const history::MostVisitedURLList& data) {
    urls_ = data;
    number_of_callbacks_++;
    if (waiting_) {
      base::MessageLoop::current()->Quit();
      waiting_ = false;
    }
  }
  base::WeakPtrFactory<TopSitesQuerier> weak_ptr_factory_;
  MostVisitedURLList urls_;
  int number_of_callbacks_;
  bool waiting_;
  DISALLOW_COPY_AND_ASSIGN(TopSitesQuerier);
};
SkBitmap ExtractThumbnail(const base::RefCountedMemory& t1) {
  scoped_ptr<SkBitmap> image(gfx::JPEGCodec::Decode(t1.front(),
                                                    t1.size()));
  return image.get() ? *image : SkBitmap();
}
bool ThumbnailsAreEqual(base::RefCountedMemory* t1,
                        base::RefCountedMemory* t2) {
  if (!t1 || !t2)
    return false;
  if (t1->size() != t2->size())
    return false;
  return !memcmp(t1->front(), t2->front(), t1->size());
}
}  
class TopSitesImplTest : public HistoryUnitTestBase {
 public:
  TopSitesImplTest()
      : ui_thread_(BrowserThread::UI, &message_loop_),
        db_thread_(BrowserThread::DB, &message_loop_) {
  }
  virtual void SetUp() {
    profile_.reset(new TestingProfile);
    if (CreateHistoryAndTopSites()) {
      ASSERT_TRUE(profile_->CreateHistoryService(false, false));
      profile_->CreateTopSites();
      profile_->BlockUntilTopSitesLoaded();
    }
  }
  virtual void TearDown() {
    profile_.reset();
  }
  
  virtual bool CreateHistoryAndTopSites() {
    return true;
  }
  
  SkBitmap GetThumbnail(const GURL& url) {
    scoped_refptr<base::RefCountedMemory> data;
    return top_sites()->GetPageThumbnail(url, false, &data) ?
        ExtractThumbnail(*data.get()) : SkBitmap();
  }
  
  gfx::Image CreateBitmap(SkColor color) {
    SkBitmap thumbnail;
    thumbnail.setConfig(SkBitmap::kARGB_8888_Config, 4, 4);
    thumbnail.allocPixels();
    thumbnail.eraseColor(color);
    return gfx::Image::CreateFrom1xBitmap(thumbnail);  
  }
  
  
  
  void RefreshTopSitesAndRecreate() {
    StartQueryForMostVisited();
    WaitForHistory();
    RecreateTopSitesAndBlock();
  }
  
  
  void WaitForHistory() {
    history_service()->ScheduleDBTask(new WaitForHistoryTask(), &consumer_);
    base::MessageLoop::current()->Run();
  }
  
  
  void WaitForTopSites() {
    top_sites()->backend_->DoEmptyRequest(
        base::Bind(&TopSitesImplTest::QuitCallback, base::Unretained(this)),
        &cancelable_task_tracker_);
    base::MessageLoop::current()->Run();
  }
  TopSitesImpl* top_sites() {
    return static_cast<TopSitesImpl*>(profile_->GetTopSites());
  }
  CancelableRequestConsumer* consumer() { return &consumer_; }
  TestingProfile* profile() {return profile_.get();}
  HistoryService* history_service() {
    return HistoryServiceFactory::GetForProfile(profile_.get(),
                                                Profile::EXPLICIT_ACCESS);
  }
  MostVisitedURLList GetPrepopulatePages() {
    return top_sites()->GetPrepopulatePages();
  }
  
  
  void ContainsPrepopulatePages(const TopSitesQuerier& querier,
                                size_t start_index) {
    MostVisitedURLList prepopulate_urls = GetPrepopulatePages();
    ASSERT_LE(start_index + prepopulate_urls.size(), querier.urls().size());
    for (size_t i = 0; i < prepopulate_urls.size(); ++i) {
      EXPECT_EQ(prepopulate_urls[i].url.spec(),
                querier.urls()[start_index + i].url.spec()) << " @ index " <<
          i;
    }
  }
  
  void EmptyCallback() {
  }
  
  
  void QuitCallback() {
    base::MessageLoop::current()->Quit();
  }
  
  void AddPageToHistory(const GURL& url) {
    RedirectList redirects;
    redirects.push_back(url);
    history_service()->AddPage(
        url, base::Time::Now(), static_cast<void*>(this), 0, GURL(),
        redirects, content::PAGE_TRANSITION_TYPED, history::SOURCE_BROWSED,
        false);
  }
  
  void AddPageToHistory(const GURL& url, const base::string16& title) {
    RedirectList redirects;
    redirects.push_back(url);
    history_service()->AddPage(
        url, base::Time::Now(), static_cast<void*>(this), 0, GURL(),
        redirects, content::PAGE_TRANSITION_TYPED, history::SOURCE_BROWSED,
        false);
    history_service()->SetPageTitle(url, title);
  }
  
  void AddPageToHistory(const GURL& url,
                        const base::string16& title,
                        const history::RedirectList& redirects,
                        base::Time time) {
    history_service()->AddPage(
        url, time, static_cast<void*>(this), 0, GURL(),
        redirects, content::PAGE_TRANSITION_TYPED, history::SOURCE_BROWSED,
        false);
    history_service()->SetPageTitle(url, title);
  }
  
  void DeleteURL(const GURL& url) {
    history_service()->DeleteURL(url);
  }
  
  bool ThumbnailEqualsBytes(const gfx::Image& image,
                            base::RefCountedMemory* bytes) {
    scoped_refptr<base::RefCountedBytes> encoded_image;
    TopSitesImpl::EncodeBitmap(image, &encoded_image);
    return ThumbnailsAreEqual(encoded_image.get(), bytes);
  }
  
  void RecreateTopSitesAndBlock() {
    
    profile()->CreateTopSites();
    
    profile()->BlockUntilTopSitesLoaded();
  }
  
  
  GURL GetCanonicalURL(const GURL& url) {
    return top_sites()->cache_->GetCanonicalURL(url);
  }
  void SetTopSites(const MostVisitedURLList& new_top_sites) {
    top_sites()->SetTopSites(new_top_sites);
  }
  bool AddForcedURL(const GURL& url, base::Time time) {
    return top_sites()->AddForcedURL(url, time);
  }
  void StartQueryForMostVisited() {
    top_sites()->StartQueryForMostVisited();
  }
  void SetLastNumUrlsChanged(size_t value) {
    top_sites()->last_num_urls_changed_ = value;
  }
  size_t last_num_urls_changed() { return top_sites()->last_num_urls_changed_; }
  base::TimeDelta GetUpdateDelay() {
    return top_sites()->GetUpdateDelay();
  }
  bool IsTopSitesLoaded() { return top_sites()->loaded_; }
  bool AddPrepopulatedPages(MostVisitedURLList* urls) {
    return top_sites()->AddPrepopulatedPages(urls, 0u);
  }
  void EmptyThreadSafeCache() {
    base::AutoLock lock(top_sites()->lock_);
    MostVisitedURLList empty;
    top_sites()->thread_safe_cache_->SetTopSites(empty);
  }
 private:
  base::MessageLoopForUI message_loop_;
  content::TestBrowserThread ui_thread_;
  content::TestBrowserThread db_thread_;
  scoped_ptr<TestingProfile> profile_;
  
  CancelableRequestConsumer consumer_;
  
  base::CancelableTaskTracker cancelable_task_tracker_;
  DISALLOW_COPY_AND_ASSIGN(TopSitesImplTest);
};  
static void AppendMostVisitedURL(std::vector<MostVisitedURL>* list,
                                 const GURL& url) {
  MostVisitedURL mv;
  mv.url = url;
  mv.redirects.push_back(url);
  list->push_back(mv);
}
static void AppendForcedMostVisitedURL(std::vector<MostVisitedURL>* list,
                                       const GURL& url,
                                       double last_forced_time) {
  MostVisitedURL mv;
  mv.url = url;
  mv.last_forced_time = base::Time::FromJsTime(last_forced_time);
  mv.redirects.push_back(url);
  list->push_back(mv);
}
static void AppendMostVisitedURLWithRedirect(
    std::vector<MostVisitedURL>* list,
    const GURL& redirect_source, const GURL& redirect_dest) {
  MostVisitedURL mv;
  mv.url = redirect_dest;
  mv.redirects.push_back(redirect_source);
  mv.redirects.push_back(redirect_dest);
  list->push_back(mv);
}
TEST_F(TopSitesImplTest, GetCanonicalURL) {
  
  
  
  GURL news("http://news.google.com/");
  GURL source("http://google.com/");
  GURL dest("http://www.google.com/");
  std::vector<MostVisitedURL> most_visited;
  AppendMostVisitedURLWithRedirect(&most_visited, source, dest);
  AppendMostVisitedURL(&most_visited, news);
  SetTopSites(most_visited);
  
  GURL result = GetCanonicalURL(GURL("http://fark.com/"));
  EXPECT_EQ(GURL("http://fark.com/"), result);
  
  result = GetCanonicalURL(news);
  EXPECT_EQ(news, result);
  
  result = GetCanonicalURL(source);
  EXPECT_EQ(dest, result);
  
  result = GetCanonicalURL(dest);
  EXPECT_EQ(dest, result);
}
TEST_F(TopSitesImplTest, DiffMostVisited) {
  GURL stays_the_same("http://staysthesame/");
  GURL gets_added_1("http://getsadded1/");
  GURL gets_added_2("http://getsadded2/");
  GURL gets_deleted_1("http://getsdeleted1/");
  GURL gets_moved_1("http://getsmoved1/");
  std::vector<MostVisitedURL> old_list;
  AppendMostVisitedURL(&old_list, stays_the_same);  
  AppendMostVisitedURL(&old_list, gets_deleted_1);  
  AppendMostVisitedURL(&old_list, gets_moved_1);    
  std::vector<MostVisitedURL> new_list;
  AppendMostVisitedURL(&new_list, stays_the_same);  
  AppendMostVisitedURL(&new_list, gets_added_1);    
  AppendMostVisitedURL(&new_list, gets_added_2);    
  AppendMostVisitedURL(&new_list, gets_moved_1);    
  history::TopSitesDelta delta;
  history::TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
  ASSERT_EQ(2u, delta.added.size());
  EXPECT_TRUE(gets_added_1 == delta.added[0].url.url);
  EXPECT_EQ(1, delta.added[0].rank);
  EXPECT_TRUE(gets_added_2 == delta.added[1].url.url);
  EXPECT_EQ(2, delta.added[1].rank);
  ASSERT_EQ(1u, delta.deleted.size());
  EXPECT_TRUE(gets_deleted_1 == delta.deleted[0].url);
  ASSERT_EQ(1u, delta.moved.size());
  EXPECT_TRUE(gets_moved_1 == delta.moved[0].url.url);
  EXPECT_EQ(3, delta.moved[0].rank);
}
TEST_F(TopSitesImplTest, DiffMostVisitedWithForced) {
  
  GURL stays_the_same_1("http://staysthesame1/");
  GURL new_last_forced_time("http://newlastforcedtime/");
  GURL stays_the_same_2("http://staysthesame2/");
  GURL move_to_nonforced("http://movetononforced/");
  GURL gets_added_1("http://getsadded1/");
  GURL gets_deleted_1("http://getsdeleted1/");
  
  GURL move_to_forced("http://movetoforced/");
  GURL stays_the_same_3("http://staysthesame3/");
  GURL gets_added_2("http://getsadded2/");
  GURL gets_deleted_2("http://getsdeleted2/");
  GURL gets_moved_1("http://getsmoved1/");
  std::vector<MostVisitedURL> old_list;
  AppendForcedMostVisitedURL(&old_list, stays_the_same_1, 1000);
  AppendForcedMostVisitedURL(&old_list, new_last_forced_time, 2000);
  AppendForcedMostVisitedURL(&old_list, stays_the_same_2, 3000);
  AppendForcedMostVisitedURL(&old_list, move_to_nonforced, 4000);
  AppendForcedMostVisitedURL(&old_list, gets_deleted_1, 5000);
  AppendMostVisitedURL(&old_list, move_to_forced);
  AppendMostVisitedURL(&old_list, stays_the_same_3);
  AppendMostVisitedURL(&old_list, gets_deleted_2);
  AppendMostVisitedURL(&old_list, gets_moved_1);
  std::vector<MostVisitedURL> new_list;
  AppendForcedMostVisitedURL(&new_list, stays_the_same_1, 1000);
  AppendForcedMostVisitedURL(&new_list, stays_the_same_2, 3000);
  AppendForcedMostVisitedURL(&new_list, new_last_forced_time, 4000);
  AppendForcedMostVisitedURL(&new_list, gets_added_1, 5000);
  AppendForcedMostVisitedURL(&new_list, move_to_forced, 6000);
  AppendMostVisitedURL(&new_list, move_to_nonforced);
  AppendMostVisitedURL(&new_list, stays_the_same_3);
  AppendMostVisitedURL(&new_list, gets_added_2);
  AppendMostVisitedURL(&new_list, gets_moved_1);
  history::TopSitesDelta delta;
  history::TopSitesImpl::DiffMostVisited(old_list, new_list, &delta);
  ASSERT_EQ(2u, delta.added.size());
  EXPECT_TRUE(gets_added_1 == delta.added[0].url.url);
  EXPECT_EQ(-1, delta.added[0].rank);
  EXPECT_TRUE(gets_added_2 == delta.added[1].url.url);
  EXPECT_EQ(2, delta.added[1].rank);
  ASSERT_EQ(2u, delta.deleted.size());
  EXPECT_TRUE(gets_deleted_1 == delta.deleted[0].url);
  EXPECT_TRUE(gets_deleted_2 == delta.deleted[1].url);
  ASSERT_EQ(3u, delta.moved.size());
  EXPECT_TRUE(new_last_forced_time == delta.moved[0].url.url);
  EXPECT_EQ(-1, delta.moved[0].rank);
  EXPECT_EQ(base::Time::FromJsTime(4000), delta.moved[0].url.last_forced_time);
  EXPECT_TRUE(move_to_forced == delta.moved[1].url.url);
  EXPECT_EQ(-1, delta.moved[1].rank);
  EXPECT_EQ(base::Time::FromJsTime(6000), delta.moved[1].url.last_forced_time);
  EXPECT_TRUE(move_to_nonforced == delta.moved[2].url.url);
  EXPECT_EQ(0, delta.moved[2].rank);
  EXPECT_TRUE(delta.moved[2].url.last_forced_time.is_null());
}
TEST_F(TopSitesImplTest, SetPageThumbnail) {
  GURL url1a("http://google.com/");
  GURL url1b("http://www.google.com/");
  GURL url2("http://images.google.com/");
  GURL invalid_url("chrome://favicon/http://google.com/");
  std::vector<MostVisitedURL> list;
  AppendMostVisitedURL(&list, url2);
  MostVisitedURL mv;
  mv.url = url1b;
  mv.redirects.push_back(url1a);
  mv.redirects.push_back(url1b);
  list.push_back(mv);
  
  SetTopSites(list);
  
  gfx::Image thumbnail(CreateBitmap(SK_ColorWHITE));
  base::Time now = base::Time::Now();
  ThumbnailScore low_score(1.0, true, true, now);
  ThumbnailScore medium_score(0.5, true, true, now);
  ThumbnailScore high_score(0.0, true, true, now);
  
  EXPECT_FALSE(top_sites()->SetPageThumbnail(invalid_url,
                                             thumbnail, medium_score));
  
  
  EXPECT_TRUE(top_sites()->SetPageThumbnail(url2, thumbnail, medium_score));
  EXPECT_FALSE(top_sites()->SetPageThumbnail(url2, thumbnail, low_score));
  EXPECT_TRUE(top_sites()->SetPageThumbnail(url2, thumbnail, high_score));
  
  
  
  EXPECT_TRUE(top_sites()->SetPageThumbnail(url1a, thumbnail, medium_score));
  EXPECT_TRUE(top_sites()->SetPageThumbnail(url1b, thumbnail, medium_score));
  EXPECT_FALSE(top_sites()->SetPageThumbnail(url1a, thumbnail, medium_score));
}
TEST_F(TopSitesImplTest, ThumbnailRemoved) {
  GURL url("http://google.com/");
  
  std::vector<MostVisitedURL> list;
  AppendMostVisitedURL(&list, url);
  SetTopSites(list);
  
  gfx::Image thumbnail(CreateBitmap(SK_ColorRED));
  base::Time now = base::Time::Now();
  ThumbnailScore low_score(1.0, true, true, now);
  ThumbnailScore medium_score(0.5, true, true, now);
  ThumbnailScore high_score(0.0, true, true, now);
  
  EXPECT_TRUE(top_sites()->SetPageThumbnail(url, thumbnail, medium_score));
  
  scoped_refptr<base::RefCountedMemory> result;
  EXPECT_TRUE(top_sites()->GetPageThumbnail(url, false, &result));
  EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, result.get()));
  
  SetTopSites(MostVisitedURLList());
  RefreshTopSitesAndRecreate();
  EXPECT_FALSE(top_sites()->GetPageThumbnail(url, false, &result));
}
TEST_F(TopSitesImplTest, GetPageThumbnail) {
  MostVisitedURLList url_list;
  MostVisitedURL url1;
  url1.url = GURL("http://asdf.com");
  url1.redirects.push_back(url1.url);
  url_list.push_back(url1);
  MostVisitedURL url2;
  url2.url = GURL("http://gmail.com");
  url2.redirects.push_back(url2.url);
  url2.redirects.push_back(GURL("http://mail.google.com"));
  url_list.push_back(url2);
  SetTopSites(url_list);
  
  gfx::Image thumbnail(CreateBitmap(SK_ColorWHITE));
  ThumbnailScore score(0.5, true, true, base::Time::Now());
  scoped_refptr<base::RefCountedMemory> result;
  EXPECT_TRUE(top_sites()->SetPageThumbnail(url1.url, thumbnail, score));
  EXPECT_TRUE(top_sites()->GetPageThumbnail(url1.url, false, &result));
  EXPECT_TRUE(top_sites()->SetPageThumbnail(GURL("http://gmail.com"),
                                            thumbnail, score));
  EXPECT_TRUE(top_sites()->GetPageThumbnail(GURL("http://gmail.com"),
                                            false,
                                            &result));
  
  EXPECT_TRUE(top_sites()->GetPageThumbnail(GURL("http://mail.google.com"),
                                            false,
                                            &result));
  EXPECT_TRUE(top_sites()->SetPageThumbnail(GURL("http://mail.google.com"),
                                            thumbnail, score));
  EXPECT_TRUE(top_sites()->GetPageThumbnail(url2.url, false, &result));
  EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, result.get()));
}
TEST_F(TopSitesImplTest, GetMostVisited) {
  GURL news("http://news.google.com/");
  GURL google("http://google.com/");
  AddPageToHistory(news);
  AddPageToHistory(google);
  StartQueryForMostVisited();
  WaitForHistory();
  TopSitesQuerier querier;
  querier.QueryTopSites(top_sites(), false);
  ASSERT_EQ(1, querier.number_of_callbacks());
  
  ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
  EXPECT_EQ(news, querier.urls()[0].url);
  EXPECT_EQ(google, querier.urls()[1].url);
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
}
TEST_F(TopSitesImplTest, SaveToDB) {
  MostVisitedURL url;
  GURL asdf_url("http://asdf.com");
  base::string16 asdf_title(base::ASCIIToUTF16("ASDF"));
  GURL google_url("http://google.com");
  base::string16 google_title(base::ASCIIToUTF16("Google"));
  GURL news_url("http://news.google.com");
  base::string16 news_title(base::ASCIIToUTF16("Google News"));
  
  AddPageToHistory(asdf_url, asdf_title);
  
  StartQueryForMostVisited();
  WaitForHistory();
  
  gfx::Image tmp_bitmap(CreateBitmap(SK_ColorBLUE));
  ASSERT_TRUE(top_sites()->SetPageThumbnail(asdf_url, tmp_bitmap,
                                            ThumbnailScore()));
  RecreateTopSitesAndBlock();
  {
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
    EXPECT_EQ(asdf_url, querier.urls()[0].url);
    EXPECT_EQ(asdf_title, querier.urls()[0].title);
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
    scoped_refptr<base::RefCountedMemory> read_data;
    EXPECT_TRUE(top_sites()->GetPageThumbnail(asdf_url, false, &read_data));
    EXPECT_TRUE(ThumbnailEqualsBytes(tmp_bitmap, read_data.get()));
  }
  MostVisitedURL url2;
  url2.url = google_url;
  url2.title = google_title;
  url2.redirects.push_back(url2.url);
  AddPageToHistory(url2.url, url2.title);
  
  ASSERT_TRUE(top_sites()->SetPageThumbnail(google_url,
                                            tmp_bitmap,
                                            ThumbnailScore()));
  
  RefreshTopSitesAndRecreate();
  {
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
    EXPECT_EQ(asdf_url, querier.urls()[0].url);
    EXPECT_EQ(asdf_title, querier.urls()[0].title);
    EXPECT_EQ(google_url, querier.urls()[1].url);
    EXPECT_EQ(google_title, querier.urls()[1].title);
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
  }
}
TEST_F(TopSitesImplTest, SaveForcedToDB) {
  MostVisitedURL url;
  GURL asdf_url("http://asdf.com");
  base::string16 asdf_title(base::ASCIIToUTF16("ASDF"));
  GURL google_url("http://google.com");
  base::string16 google_title(base::ASCIIToUTF16("Google"));
  GURL news_url("http://news.google.com");
  base::string16 news_title(base::ASCIIToUTF16("Google News"));
  
  std::vector<MostVisitedURL> list;
  AppendForcedMostVisitedURL(&list, GURL("http://forced1"), 1000);
  list[0].title = base::ASCIIToUTF16("forced1");
  AppendForcedMostVisitedURL(&list, GURL("http://forced2"), 2000);
  AppendForcedMostVisitedURL(&list, GURL("http://forced3"), 3000);
  AppendForcedMostVisitedURL(&list, GURL("http://forced4"), 4000);
  SetTopSites(list);
  
  gfx::Image red_thumbnail(CreateBitmap(SK_ColorRED));
  ASSERT_TRUE(top_sites()->SetPageThumbnail(
                  GURL("http://forced1"), red_thumbnail, ThumbnailScore()));
  
  
  SkBitmap orig_thumbnail = GetThumbnail(GURL("http://forced1"));
  
  EmptyThreadSafeCache();
  
  StartQueryForMostVisited();
  WaitForHistory();
  TopSitesQuerier querier;
  querier.QueryAllTopSites(top_sites(), true, true);
  ASSERT_EQ(4u + GetPrepopulatePages().size(), querier.urls().size());
  EXPECT_EQ(GURL("http://forced1"), querier.urls()[0].url);
  EXPECT_EQ(base::ASCIIToUTF16("forced1"), querier.urls()[0].title);
  SkBitmap thumbnail = GetThumbnail(GURL("http://forced1"));
  ASSERT_EQ(orig_thumbnail.getSize(), thumbnail.getSize());
  orig_thumbnail.lockPixels();
  thumbnail.lockPixels();
  EXPECT_EQ(0, memcmp(orig_thumbnail.getPixels(), thumbnail.getPixels(),
                      orig_thumbnail.getSize()));
  thumbnail.unlockPixels();
  orig_thumbnail.unlockPixels();
  EXPECT_EQ(base::Time::FromJsTime(1000), querier.urls()[0].last_forced_time);
  EXPECT_EQ(GURL("http://forced2"), querier.urls()[1].url);
  EXPECT_EQ(base::Time::FromJsTime(2000), querier.urls()[1].last_forced_time);
  EXPECT_EQ(GURL("http://forced3"), querier.urls()[2].url);
  EXPECT_EQ(base::Time::FromJsTime(3000), querier.urls()[2].last_forced_time);
  EXPECT_EQ(GURL("http://forced4"), querier.urls()[3].url);
  EXPECT_EQ(base::Time::FromJsTime(4000), querier.urls()[3].last_forced_time);
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 4));
}
TEST_F(TopSitesImplTest, RealDatabase) {
  MostVisitedURL url;
  GURL asdf_url("http://asdf.com");
  base::string16 asdf_title(base::ASCIIToUTF16("ASDF"));
  GURL google1_url("http://google.com");
  GURL google2_url("http://google.com/redirect");
  GURL google3_url("http://www.google.com");
  base::string16 google_title(base::ASCIIToUTF16("Google"));
  GURL news_url("http://news.google.com");
  base::string16 news_title(base::ASCIIToUTF16("Google News"));
  url.url = asdf_url;
  url.title = asdf_title;
  url.redirects.push_back(url.url);
  gfx::Image asdf_thumbnail(CreateBitmap(SK_ColorRED));
  ASSERT_TRUE(top_sites()->SetPageThumbnail(
                  asdf_url, asdf_thumbnail, ThumbnailScore()));
  base::Time add_time(base::Time::Now());
  AddPageToHistory(url.url, url.title, url.redirects, add_time);
  RefreshTopSitesAndRecreate();
  {
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
    EXPECT_EQ(asdf_url, querier.urls()[0].url);
    EXPECT_EQ(asdf_title, querier.urls()[0].title);
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
    scoped_refptr<base::RefCountedMemory> read_data;
    EXPECT_TRUE(top_sites()->GetPageThumbnail(asdf_url, false, &read_data));
    EXPECT_TRUE(ThumbnailEqualsBytes(asdf_thumbnail, read_data.get()));
  }
  MostVisitedURL url2;
  url2.url = google3_url;
  url2.title = google_title;
  url2.redirects.push_back(google1_url);
  url2.redirects.push_back(google2_url);
  url2.redirects.push_back(google3_url);
  AddPageToHistory(google3_url, url2.title, url2.redirects,
                   add_time - base::TimeDelta::FromMinutes(1));
  
  AddPageToHistory(google3_url, url2.title, url2.redirects,
                   add_time - base::TimeDelta::FromMinutes(2));
  gfx::Image google_thumbnail(CreateBitmap(SK_ColorBLUE));
  ASSERT_TRUE(top_sites()->SetPageThumbnail(
                  url2.url, google_thumbnail, ThumbnailScore()));
  RefreshTopSitesAndRecreate();
  {
    scoped_refptr<base::RefCountedMemory> read_data;
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(2u + GetPrepopulatePages().size(), querier.urls().size());
    EXPECT_EQ(google1_url, querier.urls()[0].url);
    EXPECT_EQ(google_title, querier.urls()[0].title);
    ASSERT_EQ(3u, querier.urls()[0].redirects.size());
    EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, false, &read_data));
    EXPECT_TRUE(ThumbnailEqualsBytes(google_thumbnail, read_data.get()));
    EXPECT_EQ(asdf_url, querier.urls()[1].url);
    EXPECT_EQ(asdf_title, querier.urls()[1].title);
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 2));
  }
  gfx::Image weewar_bitmap(CreateBitmap(SK_ColorYELLOW));
  base::Time thumbnail_time(base::Time::Now());
  ThumbnailScore low_score(1.0, true, true, thumbnail_time);
  ThumbnailScore medium_score(0.5, true, true, thumbnail_time);
  ThumbnailScore high_score(0.0, true, true, thumbnail_time);
  
  EXPECT_TRUE(top_sites()->SetPageThumbnail(google3_url,
                                            weewar_bitmap,
                                            medium_score));
  RefreshTopSitesAndRecreate();
  {
    scoped_refptr<base::RefCountedMemory> read_data;
    EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, false, &read_data));
    EXPECT_TRUE(ThumbnailEqualsBytes(weewar_bitmap, read_data.get()));
  }
  gfx::Image green_bitmap(CreateBitmap(SK_ColorGREEN));
  
  EXPECT_FALSE(top_sites()->SetPageThumbnail(google3_url,
                                             green_bitmap,
                                             low_score));
  
  EXPECT_TRUE(top_sites()->SetPageThumbnail(google1_url,
                                            green_bitmap,
                                            high_score));
  
  RefreshTopSitesAndRecreate();
  {
    scoped_refptr<base::RefCountedMemory> read_data;
    EXPECT_TRUE(top_sites()->GetPageThumbnail(google3_url, false, &read_data));
    EXPECT_FALSE(ThumbnailEqualsBytes(weewar_bitmap, read_data.get()));
    EXPECT_TRUE(ThumbnailEqualsBytes(green_bitmap, read_data.get()));
  }
}
TEST_F(TopSitesImplTest, DeleteNotifications) {
  GURL google1_url("http://google.com");
  GURL google2_url("http://google.com/redirect");
  GURL google3_url("http://www.google.com");
  base::string16 google_title(base::ASCIIToUTF16("Google"));
  GURL news_url("http://news.google.com");
  base::string16 news_title(base::ASCIIToUTF16("Google News"));
  AddPageToHistory(google1_url, google_title);
  AddPageToHistory(news_url, news_title);
  RefreshTopSitesAndRecreate();
  {
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(GetPrepopulatePages().size() + 2, querier.urls().size());
  }
  DeleteURL(news_url);
  
  WaitForHistory();
  {
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
    EXPECT_EQ(google_title, querier.urls()[0].title);
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
  }
  
  RefreshTopSitesAndRecreate();
  {
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(1u + GetPrepopulatePages().size(), querier.urls().size());
    EXPECT_EQ(google_title, querier.urls()[0].title);
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 1));
  }
  DeleteURL(google1_url);
  
  WaitForHistory();
  {
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
  }
  
  RefreshTopSitesAndRecreate();
  {
    TopSitesQuerier querier;
    querier.QueryTopSites(top_sites(), false);
    ASSERT_EQ(GetPrepopulatePages().size(), querier.urls().size());
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 0));
  }
}
TEST_F(TopSitesImplTest, GetUpdateDelay) {
  SetLastNumUrlsChanged(0);
  EXPECT_EQ(30, GetUpdateDelay().InSeconds());
  MostVisitedURLList url_list;
  url_list.resize(20);
  GURL tmp_url(GURL("http://x"));
  for (size_t i = 0; i < url_list.size(); ++i) {
    url_list[i].url = tmp_url;
    url_list[i].redirects.push_back(tmp_url);
  }
  SetTopSites(url_list);
  EXPECT_EQ(20u, last_num_urls_changed());
  SetLastNumUrlsChanged(0);
  EXPECT_EQ(60, GetUpdateDelay().InMinutes());
  SetLastNumUrlsChanged(3);
  EXPECT_EQ(52, GetUpdateDelay().InMinutes());
  SetLastNumUrlsChanged(20);
  EXPECT_EQ(1, GetUpdateDelay().InMinutes());
}
TEST_F(TopSitesImplTest, NotifyCallbacksWhenLoaded) {
  
  profile()->CreateTopSites();
  EXPECT_FALSE(IsTopSitesLoaded());
  TopSitesQuerier querier1;
  TopSitesQuerier querier2;
  TopSitesQuerier querier3;
  
  querier1.QueryTopSites(top_sites(), false);
  querier2.QueryTopSites(top_sites(), false);
  querier3.QueryTopSites(top_sites(), false);
  
  EXPECT_EQ(0, querier1.number_of_callbacks());
  EXPECT_EQ(0, querier2.number_of_callbacks());
  EXPECT_EQ(0, querier3.number_of_callbacks());
  
  profile()->BlockUntilTopSitesLoaded();
  
  EXPECT_EQ(1, querier1.number_of_callbacks());
  EXPECT_EQ(GetPrepopulatePages().size(), querier1.urls().size());
  EXPECT_EQ(1, querier2.number_of_callbacks());
  EXPECT_EQ(GetPrepopulatePages().size(), querier2.urls().size());
  EXPECT_EQ(1, querier3.number_of_callbacks());
  EXPECT_EQ(GetPrepopulatePages().size(), querier3.urls().size());
  
  MostVisitedURLList pages;
  MostVisitedURL url;
  url.url = GURL("http://1.com/");
  url.redirects.push_back(url.url);
  pages.push_back(url);
  url.url = GURL("http://2.com/");
  url.redirects.push_back(url.url);
  pages.push_back(url);
  SetTopSites(pages);
  
  profile()->CreateTopSites();
  EXPECT_FALSE(IsTopSitesLoaded());
  TopSitesQuerier querier4;
  
  querier4.QueryTopSites(top_sites(), false);
  
  EXPECT_EQ(0, querier4.number_of_callbacks());
  
  profile()->BlockUntilTopSitesLoaded();
  
  EXPECT_EQ(1, querier4.number_of_callbacks());
  ASSERT_EQ(2u + GetPrepopulatePages().size(), querier4.urls().size());
  EXPECT_EQ("http://1.com/", querier4.urls()[0].url.spec());
  EXPECT_EQ("http://2.com/", querier4.urls()[1].url.spec());
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier4, 2));
  
  url.url = GURL("http://3.com/");
  url.redirects.push_back(url.url);
  pages.push_back(url);
  SetTopSites(pages);
  
  TopSitesQuerier querier5;
  querier5.QueryTopSites(top_sites(), true);
  EXPECT_EQ(1, querier5.number_of_callbacks());
  ASSERT_EQ(3u + GetPrepopulatePages().size(), querier5.urls().size());
  EXPECT_EQ("http://1.com/", querier5.urls()[0].url.spec());
  EXPECT_EQ("http://2.com/", querier5.urls()[1].url.spec());
  EXPECT_EQ("http://3.com/", querier5.urls()[2].url.spec());
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier5, 3));
}
TEST_F(TopSitesImplTest, CancelingRequestsForTopSites) {
  
  profile()->CreateTopSites();
  EXPECT_FALSE(IsTopSitesLoaded());
  TopSitesQuerier querier1;
  TopSitesQuerier querier2;
  
  querier1.QueryTopSites(top_sites(), false);
  querier2.QueryTopSites(top_sites(), false);
  
  EXPECT_EQ(0, querier1.number_of_callbacks());
  EXPECT_EQ(0, querier2.number_of_callbacks());
  querier2.CancelRequest();
  
  profile()->BlockUntilTopSitesLoaded();
  
  EXPECT_EQ(1, querier1.number_of_callbacks());
  EXPECT_EQ(GetPrepopulatePages().size(), querier1.urls().size());
  
  EXPECT_EQ(0, querier2.number_of_callbacks());
}
TEST_F(TopSitesImplTest, AddTemporaryThumbnail) {
  GURL unknown_url("http://news.google.com/");
  GURL invalid_url("chrome://thumb/http://google.com/");
  GURL url1a("http://google.com/");
  GURL url1b("http://www.google.com/");
  
  gfx::Image thumbnail(CreateBitmap(SK_ColorRED));
  ThumbnailScore medium_score(0.5, true, true, base::Time::Now());
  
  EXPECT_FALSE(top_sites()->SetPageThumbnail(invalid_url,
                                             thumbnail,
                                             medium_score));
  
  
  EXPECT_TRUE(top_sites()->SetPageThumbnail(unknown_url,
                                            thumbnail,
                                            medium_score));
  
  scoped_refptr<base::RefCountedMemory> out;
  EXPECT_FALSE(top_sites()->GetPageThumbnail(unknown_url, false, &out));
  
  ThumbnailScore out_score;
  EXPECT_TRUE(top_sites()->GetTemporaryPageThumbnailScore(unknown_url,
                                                          &out_score));
  EXPECT_TRUE(medium_score.Equals(out_score));
  std::vector<MostVisitedURL> list;
  MostVisitedURL mv;
  mv.url = unknown_url;
  mv.redirects.push_back(mv.url);
  mv.redirects.push_back(url1a);
  mv.redirects.push_back(url1b);
  list.push_back(mv);
  
  SetTopSites(list);
  ASSERT_TRUE(top_sites()->GetPageThumbnail(unknown_url, false, &out));
  EXPECT_TRUE(ThumbnailEqualsBytes(thumbnail, out.get()));
}
TEST_F(TopSitesImplTest, Blacklisting) {
  MostVisitedURLList pages;
  MostVisitedURL url, url1;
  url.url = GURL("http://bbc.com/");
  url.redirects.push_back(url.url);
  pages.push_back(url);
  url1.url = GURL("http://google.com/");
  url1.redirects.push_back(url1.url);
  pages.push_back(url1);
  SetTopSites(pages);
  EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://bbc.com/")));
  
  top_sites()->AddBlacklistedURL(GURL("http://google.com/"));
  GURL prepopulate_url = GetPrepopulatePages()[0].url;
  EXPECT_TRUE(top_sites()->HasBlacklistedItems());
  EXPECT_TRUE(top_sites()->IsBlacklisted(GURL("http://google.com/")));
  EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://bbc.com/")));
  EXPECT_FALSE(top_sites()->IsBlacklisted(prepopulate_url));
  
  {
    TopSitesQuerier q;
    q.QueryTopSites(top_sites(), true);
    ASSERT_EQ(1u + GetPrepopulatePages().size(), q.urls().size());
    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
  }
  
  RecreateTopSitesAndBlock();
  {
    TopSitesQuerier q;
    q.QueryTopSites(top_sites(), true);
    ASSERT_EQ(1u + GetPrepopulatePages().size(), q.urls().size());
    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 1));
  }
  
  top_sites()->AddBlacklistedURL(prepopulate_url);
  EXPECT_TRUE(top_sites()->HasBlacklistedItems());
  
  {
    TopSitesQuerier q;
    q.QueryTopSites(top_sites(), true);
    ASSERT_EQ(1u + GetPrepopulatePages().size() - 1, q.urls().size());
    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
    for (size_t i = 1; i < q.urls().size(); ++i)
      EXPECT_NE(prepopulate_url.spec(), q.urls()[i].url.spec());
  }
  
  top_sites()->RemoveBlacklistedURL(GURL("http://google.com/"));
  EXPECT_TRUE(top_sites()->HasBlacklistedItems());
  EXPECT_FALSE(top_sites()->IsBlacklisted(GURL("http://google.com/")));
  
  {
    TopSitesQuerier q;
    q.QueryTopSites(top_sites(), true);
    ASSERT_EQ(2u + GetPrepopulatePages().size() - 1, q.urls().size());
    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
    EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
    
    
    if (q.urls().size() > 2)
      EXPECT_NE(prepopulate_url.spec(), q.urls()[2].url.spec());
    else
      EXPECT_EQ(1u, GetPrepopulatePages().size());
  }
  
  top_sites()->ClearBlacklistedURLs();
  EXPECT_FALSE(top_sites()->HasBlacklistedItems());
  {
    TopSitesQuerier q;
    q.QueryTopSites(top_sites(), true);
    ASSERT_EQ(2u + GetPrepopulatePages().size(), q.urls().size());
    EXPECT_EQ("http://bbc.com/", q.urls()[0].url.spec());
    EXPECT_EQ("http://google.com/", q.urls()[1].url.spec());
    ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 2));
  }
}
TEST_F(TopSitesImplTest, AddPrepopulatedPages) {
  TopSitesQuerier q;
  q.QueryTopSites(top_sites(), true);
  EXPECT_EQ(GetPrepopulatePages().size(), q.urls().size());
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
  MostVisitedURLList pages = q.urls();
  EXPECT_FALSE(AddPrepopulatedPages(&pages));
  EXPECT_EQ(GetPrepopulatePages().size(), pages.size());
  q.set_urls(pages);
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(q, 0));
}
TEST_F(TopSitesImplTest, SetForcedTopSites) {
  
  MostVisitedURLList old_url_list;
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/0"), 1000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/1"), 4000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/2"), 7000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/3"), 10000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/4"), 11000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/5"), 12000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/6"), 13000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/7"), 18000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://oldforced/8"), 21000);
  const size_t kNumOldForcedURLs = 9;
  
  MostVisitedURLList new_url_list;
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/0"), 2000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/1"), 3000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/2"), 5000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/3"), 6000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/4"), 8000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/5"), 9000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/6"), 14000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/7"), 15000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/8"), 16000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/9"), 17000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/10"), 19000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/11"), 20000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://newforced/12"), 22000);
  
  const size_t kNumNonForcedURLs = 20;  
  for (size_t i = 0; i < kNumNonForcedURLs; ++i) {
    std::ostringstream url;
    url << "http://oldnonforced/" << i;
    AppendMostVisitedURL(&old_url_list, GURL(url.str()));
    url.str("");
    url << "http://newnonforced/" << i;
    AppendMostVisitedURL(&new_url_list, GURL(url.str()));
  }
  
  SetTopSites(old_url_list);
  EXPECT_EQ(kNumOldForcedURLs + kNumNonForcedURLs, last_num_urls_changed());
  TopSitesQuerier querier;
  
  querier.QueryTopSites(top_sites(), false);
  ASSERT_EQ(kNumNonForcedURLs, querier.urls().size());
  
  EXPECT_EQ("http://oldnonforced/0", querier.urls()[0].url.spec());
  
  querier.QueryAllTopSites(top_sites(), false, true);
  EXPECT_EQ(kNumOldForcedURLs + kNumNonForcedURLs, querier.urls().size());
  
  EXPECT_EQ("http://oldforced/0", querier.urls()[0].url.spec());
  EXPECT_EQ("http://oldnonforced/0",
            querier.urls()[kNumOldForcedURLs].url.spec());
  
  SetTopSites(new_url_list);
  
  querier.QueryAllTopSites(top_sites(), false, true);
  
  ASSERT_EQ(20 + kNumNonForcedURLs, querier.urls().size());
  
  
  EXPECT_EQ("http://newforced/1", querier.urls()[0].url.spec());
  EXPECT_EQ(3000, querier.urls()[0].last_forced_time.ToJsTime());
  EXPECT_EQ("http://oldforced/1", querier.urls()[1].url.spec());
  EXPECT_EQ(4000, querier.urls()[1].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/2", querier.urls()[2].url.spec());
  EXPECT_EQ(5000, querier.urls()[2].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/3", querier.urls()[3].url.spec());
  EXPECT_EQ(6000, querier.urls()[3].last_forced_time.ToJsTime());
  EXPECT_EQ("http://oldforced/2", querier.urls()[4].url.spec());
  EXPECT_EQ(7000, querier.urls()[4].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/4", querier.urls()[5].url.spec());
  EXPECT_EQ(8000, querier.urls()[5].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/5", querier.urls()[6].url.spec());
  EXPECT_EQ(9000, querier.urls()[6].last_forced_time.ToJsTime());
  EXPECT_EQ("http://oldforced/3", querier.urls()[7].url.spec());
  EXPECT_EQ(10000, querier.urls()[7].last_forced_time.ToJsTime());
  EXPECT_EQ("http://oldforced/4", querier.urls()[8].url.spec());
  EXPECT_EQ(11000, querier.urls()[8].last_forced_time.ToJsTime());
  EXPECT_EQ("http://oldforced/5", querier.urls()[9].url.spec());
  EXPECT_EQ(12000, querier.urls()[9].last_forced_time.ToJsTime());
  EXPECT_EQ("http://oldforced/6", querier.urls()[10].url.spec());
  EXPECT_EQ(13000, querier.urls()[10].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/6", querier.urls()[11].url.spec());
  EXPECT_EQ(14000, querier.urls()[11].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/7", querier.urls()[12].url.spec());
  EXPECT_EQ(15000, querier.urls()[12].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/8", querier.urls()[13].url.spec());
  EXPECT_EQ(16000, querier.urls()[13].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/9", querier.urls()[14].url.spec());
  EXPECT_EQ(17000, querier.urls()[14].last_forced_time.ToJsTime());
  EXPECT_EQ("http://oldforced/7", querier.urls()[15].url.spec());
  EXPECT_EQ(18000, querier.urls()[15].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/10", querier.urls()[16].url.spec());
  EXPECT_EQ(19000, querier.urls()[16].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/11", querier.urls()[17].url.spec());
  EXPECT_EQ(20000, querier.urls()[17].last_forced_time.ToJsTime());
  EXPECT_EQ("http://oldforced/8", querier.urls()[18].url.spec());
  EXPECT_EQ(21000, querier.urls()[18].last_forced_time.ToJsTime());
  EXPECT_EQ("http://newforced/12", querier.urls()[19].url.spec());
  EXPECT_EQ(22000, querier.urls()[19].last_forced_time.ToJsTime());
  
  EXPECT_EQ("http://newnonforced/0", querier.urls()[20].url.spec());
  EXPECT_TRUE(querier.urls()[20].last_forced_time.is_null());
  EXPECT_EQ("http://newnonforced/19", querier.urls()[39].url.spec());
  EXPECT_TRUE(querier.urls()[39].last_forced_time.is_null());
}
TEST_F(TopSitesImplTest, SetForcedTopSitesWithCollisions) {
  
  MostVisitedURLList old_url_list;
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://url/0"), 1000);
  
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/0"), 4000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/1"), 6000);
  AppendForcedMostVisitedURL(&old_url_list, GURL("http://collision/2"), 7000);
  
  
  AppendMostVisitedURL(&old_url_list, GURL("http://noncollision/0"));
  SetTopSites(old_url_list);
  
  MostVisitedURLList new_url_list;
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://collision/1"), 2000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://url/2"), 3000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://collision/0"), 5000);
  AppendForcedMostVisitedURL(&new_url_list, GURL("http://noncollision/0"),
                             9000);
  AppendMostVisitedURL(&new_url_list, GURL("http://collision/2"));
  AppendMostVisitedURL(&new_url_list, GURL("http://url/3"));
  SetTopSites(new_url_list);
  
  TopSitesQuerier querier;
  querier.QueryAllTopSites(top_sites(), false, true);
  
  ASSERT_EQ(7u + GetPrepopulatePages().size(), querier.urls().size());
  EXPECT_EQ("http://url/0", querier.urls()[0].url.spec());
  EXPECT_EQ(1000u, querier.urls()[0].last_forced_time.ToJsTime());
  EXPECT_EQ("http://collision/1", querier.urls()[1].url.spec());
  EXPECT_EQ(2000u, querier.urls()[1].last_forced_time.ToJsTime());
  EXPECT_EQ("http://url/2", querier.urls()[2].url.spec());
  EXPECT_EQ(3000u, querier.urls()[2].last_forced_time.ToJsTime());
  EXPECT_EQ("http://collision/0", querier.urls()[3].url.spec());
  EXPECT_EQ(5000u, querier.urls()[3].last_forced_time.ToJsTime());
  EXPECT_EQ("http://noncollision/0", querier.urls()[4].url.spec());
  EXPECT_EQ(9000u, querier.urls()[4].last_forced_time.ToJsTime());
  EXPECT_EQ("http://collision/2", querier.urls()[5].url.spec());
  EXPECT_TRUE(querier.urls()[5].last_forced_time.is_null());
  EXPECT_EQ("http://url/3", querier.urls()[6].url.spec());
  EXPECT_TRUE(querier.urls()[6].last_forced_time.is_null());
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 7));
}
TEST_F(TopSitesImplTest, SetTopSitesIdentical) {
  
  MostVisitedURLList url_list;
  AppendForcedMostVisitedURL(&url_list, GURL("http://url/0"), 1000);
  AppendMostVisitedURL(&url_list, GURL("http://url/1"));
  AppendMostVisitedURL(&url_list, GURL("http://url/2"));
  SetTopSites(url_list);
  
  SetTopSites(MostVisitedURLList(url_list));
  
  TopSitesQuerier querier;
  querier.QueryAllTopSites(top_sites(), false, true);
  
  ASSERT_EQ(3u + GetPrepopulatePages().size(), querier.urls().size());
  EXPECT_EQ("http://url/0", querier.urls()[0].url.spec());
  EXPECT_EQ(1000u, querier.urls()[0].last_forced_time.ToJsTime());
  EXPECT_EQ("http://url/1", querier.urls()[1].url.spec());
  EXPECT_EQ("http://url/2", querier.urls()[2].url.spec());
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 3));
}
TEST_F(TopSitesImplTest, AddForcedURL) {
  
  MostVisitedURLList url_list;
  AppendForcedMostVisitedURL(&url_list, GURL("http://forced/0"), 2000);
  AppendForcedMostVisitedURL(&url_list, GURL("http://forced/1"), 4000);
  AppendMostVisitedURL(&url_list, GURL("http://nonforced/0"));
  AppendMostVisitedURL(&url_list, GURL("http://nonforced/1"));
  AppendMostVisitedURL(&url_list, GURL("http://nonforced/2"));
  SetTopSites(url_list);
  
  EXPECT_TRUE(AddForcedURL(GURL("http://forced/2"),
                           base::Time::FromJsTime(5000)));
  EXPECT_TRUE(AddForcedURL(GURL("http://forced/3"),
                           base::Time::FromJsTime(1000)));
  EXPECT_TRUE(AddForcedURL(GURL("http://forced/4"),
                           base::Time::FromJsTime(3000)));
  
  TopSitesQuerier querier;
  querier.QueryAllTopSites(top_sites(), false, true);
  ASSERT_EQ(8u + GetPrepopulatePages().size(), querier.urls().size());
  EXPECT_EQ("http://forced/3", querier.urls()[0].url.spec());
  EXPECT_EQ(1000u, querier.urls()[0].last_forced_time.ToJsTime());
  EXPECT_EQ("http://forced/0", querier.urls()[1].url.spec());
  EXPECT_EQ(2000u, querier.urls()[1].last_forced_time.ToJsTime());
  EXPECT_EQ("http://forced/4", querier.urls()[2].url.spec());
  EXPECT_EQ(3000u, querier.urls()[2].last_forced_time.ToJsTime());
  EXPECT_EQ("http://forced/1", querier.urls()[3].url.spec());
  EXPECT_EQ(4000u, querier.urls()[3].last_forced_time.ToJsTime());
  EXPECT_EQ("http://forced/2", querier.urls()[4].url.spec());
  EXPECT_EQ(5000u, querier.urls()[4].last_forced_time.ToJsTime());
  EXPECT_EQ("http://nonforced/0", querier.urls()[5].url.spec());
  EXPECT_TRUE(querier.urls()[5].last_forced_time.is_null());
  EXPECT_EQ("http://nonforced/1", querier.urls()[6].url.spec());
  EXPECT_TRUE(querier.urls()[6].last_forced_time.is_null());
  EXPECT_EQ("http://nonforced/2", querier.urls()[7].url.spec());
  EXPECT_TRUE(querier.urls()[7].last_forced_time.is_null());
  ASSERT_NO_FATAL_FAILURE(ContainsPrepopulatePages(querier, 8));
  
  
  EXPECT_TRUE(AddForcedURL(GURL("http://forced/3"),
                           base::Time::FromJsTime(4000)));
  EXPECT_TRUE(AddForcedURL(GURL("http://forced/1"),
                            base::Time::FromJsTime(1000)));
  EXPECT_FALSE(AddForcedURL(GURL("http://nonforced/0"),
                            base::Time::FromJsTime(6000)));
  
  querier.QueryAllTopSites(top_sites(), false, true);
  ASSERT_EQ(8u + GetPrepopulatePages().size(), querier.urls().size());
  EXPECT_EQ("http://forced/1", querier.urls()[0].url.spec());
  EXPECT_EQ(1000u, querier.urls()[0].last_forced_time.ToJsTime());
  EXPECT_EQ("http://forced/3", querier.urls()[3].url.spec());
  EXPECT_EQ(4000u, querier.urls()[3].last_forced_time.ToJsTime());
  EXPECT_EQ("http://nonforced/0", querier.urls()[5].url.spec());
  EXPECT_TRUE(querier.urls()[5].last_forced_time.is_null());
  
  EXPECT_TRUE(AddForcedURL(GURL("http://forced/5"),
                           base::Time::FromJsTime(4000)));
  querier.QueryAllTopSites(top_sites(), false, true);
  ASSERT_EQ(9u + GetPrepopulatePages().size(), querier.urls().size());
  EXPECT_EQ(4000u, querier.urls()[3].last_forced_time.ToJsTime());
  EXPECT_EQ(4000u, querier.urls()[4].last_forced_time.ToJsTime());
  
  if (querier.urls()[3].url.spec() == "http://forced/3") {
    EXPECT_EQ("http://forced/3", querier.urls()[3].url.spec());
    EXPECT_EQ("http://forced/5", querier.urls()[4].url.spec());
  } else {
    EXPECT_EQ("http://forced/5", querier.urls()[3].url.spec());
    EXPECT_EQ("http://forced/3", querier.urls()[4].url.spec());
  }
  
  gfx::Image red_thumbnail(CreateBitmap(SK_ColorRED));
  ASSERT_TRUE(top_sites()->SetPageThumbnail(
                  GURL("http://forced/5"), red_thumbnail, ThumbnailScore()));
  
  
  SkBitmap orig_thumbnail = GetThumbnail(GURL("http://forced/5"));
  EXPECT_TRUE(AddForcedURL(GURL("http://forced/5"),
                           base::Time::FromJsTime(6000)));
  
  querier.QueryAllTopSites(top_sites(), false, true);
  EXPECT_EQ("http://forced/5", querier.urls()[5].url.spec());
  EXPECT_EQ(6000u, querier.urls()[5].last_forced_time.ToJsTime());
  SkBitmap thumbnail = GetThumbnail(GURL("http://forced/5"));
  ASSERT_EQ(orig_thumbnail.getSize(), thumbnail.getSize());
  orig_thumbnail.lockPixels();
  thumbnail.lockPixels();
  EXPECT_EQ(0, memcmp(orig_thumbnail.getPixels(), thumbnail.getPixels(),
                      orig_thumbnail.getSize()));
  thumbnail.unlockPixels();
  orig_thumbnail.unlockPixels();
}
}