15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstdio>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/memory/shared_memory.h"
119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
13a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process_handle.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/run_loop.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/visitedlink/browser/visitedlink_delegate.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/visitedlink/browser/visitedlink_event_listener.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/visitedlink/browser/visitedlink_master.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/visitedlink/common/visitedlink_messages.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/visitedlink/renderer/visitedlink_slave.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/mock_render_process_host.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/test/test_browser_context.h"
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_renderer_host.h"
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/test/test_utils.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::MockRenderProcessHost;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHostTester;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace visitedlink {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef std::vector<GURL> URLs;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a nice long URL that we can append numbers to to get new URLs
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char g_test_prefix[] =
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "http://www.google.com/products/foo/index.html?id=45028640526508376&seq=";
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int g_test_count = 1000;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a test URL for index |i|
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL TestURL(int i) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GURL(base::StringPrintf("%s%d", g_test_prefix, i));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::vector<VisitedLinkSlave*> g_slaves;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestVisitedLinkDelegate : public VisitedLinkDelegate {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void RebuildTable(
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const scoped_refptr<URLEnumerator>& enumerator) OVERRIDE;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddURLForRebuild(const GURL& url);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLs rebuild_urls_;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TestVisitedLinkDelegate::RebuildTable(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const scoped_refptr<URLEnumerator>& enumerator) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (URLs::const_iterator itr = rebuild_urls_.begin();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       itr != rebuild_urls_.end();
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++itr)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enumerator->OnURL(*itr);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enumerator->OnComplete(true);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TestVisitedLinkDelegate::AddURLForRebuild(const GURL& url) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  rebuild_urls_.push_back(url);
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestURLIterator : public VisitedLinkMaster::URLIterator {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit TestURLIterator(const URLs& urls);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual const GURL& NextURL() OVERRIDE;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool HasNextURL() const OVERRIDE;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLs::const_iterator iterator_;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLs::const_iterator end_;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TestURLIterator::TestURLIterator(const URLs& urls)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : iterator_(urls.begin()),
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      end_(urls.end()) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const GURL& TestURLIterator::NextURL() {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return *(iterator_++);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TestURLIterator::HasNextURL() const {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return iterator_ != end_;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TrackingVisitedLinkEventListener : public VisitedLinkMaster::Listener {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrackingVisitedLinkEventListener()
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : reset_count_(0),
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_count_(0) {}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void NewTable(base::SharedMemory* table) OVERRIDE {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (table) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (std::vector<VisitedLinkSlave>::size_type i = 0;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           i < g_slaves.size(); i++) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        table->ShareToProcess(base::GetCurrentProcessHandle(), &new_handle);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        g_slaves[i]->OnUpdateVisitedLinks(new_handle);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Add(VisitedLinkCommon::Fingerprint) OVERRIDE { add_count_++; }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Reset() OVERRIDE { reset_count_++; }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetUp() {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reset_count_ = 0;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_count_ = 0;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reset_count() const { return reset_count_; }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int add_count() const { return add_count_; }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reset_count_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int add_count_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VisitedLinkTest : public testing::Test {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initializes the visited link objects. Pass in the size that you want a
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // freshly created table to be. 0 means use the default.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |suppress_rebuild| is set when we're not testing rebuilding, see
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the VisitedLinkMaster constructor.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool InitVisited(int initial_size, bool suppress_rebuild) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Initialize the visited link system.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_.reset(new VisitedLinkMaster(new TrackingVisitedLinkEventListener(),
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        &delegate_,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        true,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        suppress_rebuild, visited_file_,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        initial_size));
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return master_->Init();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // May be called multiple times (some tests will do this to clear things,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and TearDown will do this to make sure eveything is shiny before quitting.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearDB() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (master_.get())
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      master_.reset(NULL);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait for all pending file I/O to be completed.
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    content::RunAllBlockingPoolTasksUntilIdle();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads the database from disk and makes sure that the same URLs are present
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as were generated by TestIO_Create(). This also checks the URLs with a
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // slave to make sure it reads the data properly.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reload() {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clean up after our caller, who may have left the database open.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearDB();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(InitVisited(0, true));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->DebugValidate();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // check that the table has the proper number of entries
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int used_count = master_->GetUsedCount();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(used_count, g_test_count);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a slave database.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VisitedLinkSlave slave;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->shared_memory()->ShareToProcess(
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::GetCurrentProcessHandle(), &new_handle);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    slave.OnUpdateVisitedLinks(new_handle);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_slaves.push_back(&slave);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool found;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < g_test_count; i++) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL cur = TestURL(i);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found = master_->IsVisited(cur);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(found) << "URL " << i << "not found in master.";
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found = slave.IsVisited(cur);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(found) << "URL " << i << "not found in slave.";
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // test some random URL so we know that it returns false sometimes too
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = master_->IsVisited(GURL("http://unfound.site/"));
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(found);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = slave.IsVisited(GURL("http://unfound.site/"));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_FALSE(found);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->DebugValidate();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_slaves.clear();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // testing::Test
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history_dir_ = temp_dir_.path().AppendASCII("VisitedLinkTest");
213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(base::CreateDirectory(history_dir_));
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visited_file_ = history_dir_.Append(FILE_PATH_LITERAL("VisitedLinks"));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearDB();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir temp_dir_;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Filenames for the services;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath history_dir_;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath visited_file_;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<VisitedLinkMaster> master_;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestVisitedLinkDelegate delegate_;
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  content::TestBrowserThreadBundle thread_bundle_;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test creates and reads some databases to make sure the data is
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// preserved throughout those operations.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkTest, DatabaseIO) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(0, true));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < g_test_count; i++)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->AddURL(TestURL(i));
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that the database was written properly
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reload();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks that we can delete things properly when there are collisions.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkTest, Delete) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int32 kInitialSize = 17;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(kInitialSize, true));
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a cluster from 14-17 wrapping around to 0. These will all hash to the
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same value.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VisitedLinkCommon::Fingerprint kFingerprint0 = kInitialSize * 0 + 14;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VisitedLinkCommon::Fingerprint kFingerprint1 = kInitialSize * 1 + 14;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VisitedLinkCommon::Fingerprint kFingerprint2 = kInitialSize * 2 + 14;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VisitedLinkCommon::Fingerprint kFingerprint3 = kInitialSize * 3 + 14;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const VisitedLinkCommon::Fingerprint kFingerprint4 = kInitialSize * 4 + 14;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->AddFingerprint(kFingerprint0, false);  // @14
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->AddFingerprint(kFingerprint1, false);  // @15
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->AddFingerprint(kFingerprint2, false);  // @16
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->AddFingerprint(kFingerprint3, false);  // @0
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->AddFingerprint(kFingerprint4, false);  // @1
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deleting 14 should move the next value up one slot (we do not specify an
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // order).
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kFingerprint3, master_->hash_table_[0]);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DeleteFingerprint(kFingerprint3, false);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitedLinkCommon::Fingerprint zero_fingerprint = 0;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(zero_fingerprint, master_->hash_table_[1]);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(zero_fingerprint, master_->hash_table_[0]);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deleting the other four should leave the table empty.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DeleteFingerprint(kFingerprint0, false);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DeleteFingerprint(kFingerprint1, false);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DeleteFingerprint(kFingerprint2, false);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DeleteFingerprint(kFingerprint4, false);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, master_->used_items_);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kInitialSize; i++)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(zero_fingerprint, master_->hash_table_[i]) <<
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Hash table has values in it.";
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When we delete more than kBigDeleteThreshold we trigger different behavior
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// where the entire file is rewritten.
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkTest, BigDelete) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(16381, true));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the base set of URLs that won't be deleted.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reload() will test for these.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32 i = 0; i < g_test_count; i++)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->AddURL(TestURL(i));
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add more URLs than necessary to trigger this case.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kTestDeleteCount = VisitedLinkMaster::kBigDeleteThreshold + 2;
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLs urls_to_delete;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32 i = g_test_count; i < g_test_count + kTestDeleteCount; i++) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL url(TestURL(i));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->AddURL(url);
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    urls_to_delete.push_back(url);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestURLIterator iterator(urls_to_delete);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  master_->DeleteURLs(&iterator);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DebugValidate();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reload();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkTest, DeleteAll) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(0, true));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VisitedLinkSlave slave;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->shared_memory()->ShareToProcess(
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::GetCurrentProcessHandle(), &new_handle);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    slave.OnUpdateVisitedLinks(new_handle);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_slaves.push_back(&slave);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add the test URLs.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < g_test_count; i++) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      master_->AddURL(TestURL(i));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(i + 1, master_->GetUsedCount());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->DebugValidate();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure the slave picked up the adds.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < g_test_count; i++)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(slave.IsVisited(TestURL(i)));
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clear the table and make sure the slave picked it up.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->DeleteAllURLs();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, master_->GetUsedCount());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < g_test_count; i++) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(master_->IsVisited(TestURL(i)));
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(slave.IsVisited(TestURL(i)));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Close the database.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_slaves.clear();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearDB();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reopen and validate.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(0, true));
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DebugValidate();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, master_->GetUsedCount());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < g_test_count; i++)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(master_->IsVisited(TestURL(i)));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This tests that the master correctly resizes its tables when it gets too
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// full, notifies its slaves of the change, and updates the disk.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkTest, Resizing) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a very small database.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int32 initial_size = 17;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(initial_size, true));
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ...and a slave
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitedLinkSlave slave;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->shared_memory()->ShareToProcess(
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::GetCurrentProcessHandle(), &new_handle);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slave.OnUpdateVisitedLinks(new_handle);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_slaves.push_back(&slave);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 used_count = master_->GetUsedCount();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(used_count, 0);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < g_test_count; i++) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->AddURL(TestURL(i));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    used_count = master_->GetUsedCount();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(i + 1, used_count);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the table got resized sufficiently.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 table_size;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitedLinkCommon::Fingerprint* table;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->GetUsageStatistics(&table_size, &table);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  used_count = master_->GetUsedCount();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(table_size, used_count);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(used_count, g_test_count) <<
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "table count doesn't match the # of things we added";
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the slave got the resize message and has the same
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // table information.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 child_table_size;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitedLinkCommon::Fingerprint* child_table;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  slave.GetUsageStatistics(&child_table_size, &child_table);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(table_size, child_table_size);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int32 i = 0; i < table_size; i++) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(table[i], child_table[i]);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DebugValidate();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_slaves.clear();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This tests that the file is written correctly by reading it in using
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a new database.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reload();
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that if the database doesn't exist, it will be rebuilt from history.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkTest, Rebuild) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add half of our URLs to history. This needs to be done before we
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initialize the visited link DB.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int history_count = g_test_count / 2;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < history_count; i++)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delegate_.AddURLForRebuild(TestURL(i));
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the visited link DB. Since the visited links file doesn't exist
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and we don't suppress history rebuilding, this will load from history.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(0, false));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // While the table is rebuilding, add the rest of the URLs to the visited
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // link system. This isn't guaranteed to happen during the rebuild, so we
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can't be 100% sure we're testing the right thing, but in practice is.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All the adds above will generally take some time queuing up on the
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // history thread, and it will take a while to catch up to actually
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // processing the rebuild that has queued behind it. We will generally
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // finish adding all of the URLs before it has even found the first URL.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = history_count; i < g_test_count; i++)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->AddURL(TestURL(i));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add one more and then delete it.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->AddURL(TestURL(g_test_count));
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLs urls_to_delete;
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  urls_to_delete.push_back(TestURL(g_test_count));
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestURLIterator iterator(urls_to_delete);
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  master_->DeleteURLs(&iterator);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the rebuild to complete. The task will terminate the message
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // loop when the rebuild is done. There's no chance that the rebuild will
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // complete before we set the task because the rebuild completion message
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is posted to the message loop; until we Run() it, rebuild can not
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // complete.
437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RunLoop run_loop;
438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  master_->set_rebuild_complete_task(run_loop.QuitClosure());
439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  run_loop.Run();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that all URLs were written to the database properly.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reload();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the extra one was *not* written (Reload won't test this).
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(master_->IsVisited(TestURL(g_test_count)));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that importing a large number of URLs will work
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkTest, BigImport) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(0, false));
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Before the table rebuilds, add a large number of URLs
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int total_count = VisitedLinkMaster::kDefaultTableSize + 10;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < total_count; i++)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->AddURL(TestURL(i));
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the rebuild to complete.
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::RunLoop run_loop;
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  master_->set_rebuild_complete_task(run_loop.QuitClosure());
460868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  run_loop.Run();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the right number of URLs are present
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int used_count = master_->GetUsedCount();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(used_count, total_count);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkTest, Listener) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(InitVisited(0, true));
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add test URLs.
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < g_test_count; i++) {
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master_->AddURL(TestURL(i));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(i + 1, master_->GetUsedCount());
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Delete an URL.
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLs urls_to_delete;
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  urls_to_delete.push_back(TestURL(0));
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestURLIterator iterator(urls_to_delete);
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  master_->DeleteURLs(&iterator);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ... and all of the remaining ones.
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master_->DeleteAllURLs();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrackingVisitedLinkEventListener* listener =
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<TrackingVisitedLinkEventListener*>(master_->GetListener());
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that VisitedLinkMaster::Listener::Add was called for each added URL.
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(g_test_count, listener->add_count());
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that VisitedLinkMaster::Listener::Reset was called both when one and
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all URLs are deleted.
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2, listener->reset_count());
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class VisitCountingContext : public content::TestBrowserContext {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VisitCountingContext()
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : add_count_(0),
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        add_event_count_(0),
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        reset_event_count_(0),
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new_table_count_(0) {}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CountAddEvent(int by) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_count_ += by;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    add_event_count_++;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CountResetEvent() {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reset_event_count_++;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CountNewTable() {
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    new_table_count_++;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int add_count() const { return add_count_; }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int add_event_count() const { return add_event_count_; }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reset_event_count() const { return reset_event_count_; }
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int new_table_count() const { return new_table_count_; }
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int add_count_;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int add_event_count_;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int reset_event_count_;
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int new_table_count_;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stub out as little as possible, borrowing from RenderProcessHost.
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VisitRelayingRenderProcessHost : public MockRenderProcessHost {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit VisitRelayingRenderProcessHost(
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::BrowserContext* browser_context)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          : MockRenderProcessHost(browser_context), widgets_(0) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NOTIFICATION_RENDERER_PROCESS_CREATED,
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<RenderProcessHost>(this),
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NotificationService::NoDetails());
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~VisitRelayingRenderProcessHost() {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<content::RenderProcessHost>(this),
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::NotificationService::NoDetails());
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WidgetRestored() OVERRIDE { widgets_++; }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void WidgetHidden() OVERRIDE { widgets_--; }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int VisibleWidgetCount() const OVERRIDE { return widgets_; }
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool Send(IPC::Message* msg) OVERRIDE {
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VisitCountingContext* counting_context =
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<VisitCountingContext*>(
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            GetBrowserContext());
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (msg->type() == ChromeViewMsg_VisitedLink_Add::ID) {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PickleIterator iter(*msg);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<uint64> fingerprints;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK(IPC::ReadParam(msg, &iter, &fingerprints));
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      counting_context->CountAddEvent(fingerprints.size());
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (msg->type() == ChromeViewMsg_VisitedLink_Reset::ID) {
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      counting_context->CountResetEvent();
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (msg->type() == ChromeViewMsg_VisitedLink_NewTable::ID) {
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      counting_context->CountNewTable();
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete msg;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int widgets_;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(VisitRelayingRenderProcessHost);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VisitedLinkRenderProcessHostFactory
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public content::RenderProcessHostFactory {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitedLinkRenderProcessHostFactory()
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : content::RenderProcessHostFactory() {}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual content::RenderProcessHost* CreateRenderProcessHost(
582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      content::BrowserContext* browser_context,
583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      content::SiteInstance* site_instance) const OVERRIDE {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new VisitRelayingRenderProcessHost(browser_context);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(VisitedLinkRenderProcessHostFactory);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class VisitedLinkEventsTest : public content::RenderViewHostTestHarness {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetRenderProcessHostFactory(&vc_rph_factory_);
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    content::RenderViewHostTestHarness::SetUp();
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual content::BrowserContext* CreateBrowserContext() OVERRIDE {
5997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    VisitCountingContext* context = new VisitCountingContext();
6007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    master_.reset(new VisitedLinkMaster(context, &delegate_, true));
6017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    master_->Init();
6027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return context;
6037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
6047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
6057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  VisitCountingContext* context() {
6067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return static_cast<VisitCountingContext*>(browser_context());
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitedLinkMaster* master() const {
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return master_.get();
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForCoalescense() {
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Let the timer fire.
615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    //
616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // TODO(ajwong): This is horrid! What is the right synchronization method?
617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    base::RunLoop run_loop;
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        run_loop.QuitClosure(),
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(110));
622868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    run_loop.Run();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VisitedLinkRenderProcessHostFactory vc_rph_factory_;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestVisitedLinkDelegate delegate_;
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<VisitedLinkMaster> master_;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkEventsTest, Coalescense) {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // add some URLs to master.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a few URLs.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://acidtests.org/"));
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://google.com/"));
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://chromium.org/"));
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Just for kicks, add a duplicate URL. This shouldn't increase the resulting
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://acidtests.org/"));
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that coalescing actually occurs. There should be no links or
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // events received by the renderer.
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, context()->add_count());
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, context()->add_event_count());
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForCoalescense();
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We now should have 3 entries added in 1 event.
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(3, context()->add_count());
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->add_event_count());
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test whether the coalescing continues by adding a few more URLs.
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://google.com/chrome/"));
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://webkit.org/"));
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://acid3.acidtests.org/"));
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForCoalescense();
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have 6 entries added in 2 events.
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(6, context()->add_count());
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, context()->add_event_count());
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test whether duplicate entries produce add events.
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://acidtests.org/"));
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForCoalescense();
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have no change in results.
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(6, context()->add_count());
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, context()->add_event_count());
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the coalescing does not resume after resetting.
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://build.chromium.org/"));
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->DeleteAllURLs();
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForCoalescense();
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have no change in results except for one new reset event.
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(6, context()->add_count());
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(2, context()->add_event_count());
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->reset_event_count());
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkEventsTest, Basics) {
686cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RenderViewHostTester::For(rvh())->CreateRenderView(
687cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::string16(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, -1, false);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a few URLs.
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://acidtests.org/"));
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://google.com/"));
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://chromium.org/"));
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForCoalescense();
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We now should have 1 add event.
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->add_event_count());
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, context()->reset_event_count());
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->DeleteAllURLs();
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForCoalescense();
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have no change in add results, plus one new reset event.
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->add_event_count());
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->reset_event_count());
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(VisitedLinkEventsTest, TabVisibility) {
710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RenderViewHostTester::For(rvh())->CreateRenderView(
711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::string16(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, -1, false);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simulate tab becoming inactive.
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderViewHostTester::For(rvh())->SimulateWasHidden();
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a few URLs.
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://acidtests.org/"));
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://google.com/"));
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  master()->AddURL(GURL("http://chromium.org/"));
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForCoalescense();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We shouldn't have any events.
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, context()->add_event_count());
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, context()->reset_event_count());
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simulate the tab becoming active.
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderViewHostTester::For(rvh())->SimulateWasShown();
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should now have 3 add events, still no reset events.
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->add_event_count());
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, context()->reset_event_count());
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deactivate the tab again.
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderViewHostTester::For(rvh())->SimulateWasHidden();
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a bunch of URLs (over 50) to exhaust the link event buffer.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 100; i++)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    master()->AddURL(TestURL(i));
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForCoalescense();
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Again, no change in events until tab is active.
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->add_event_count());
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, context()->reset_event_count());
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Activate the tab.
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderViewHostTester::For(rvh())->SimulateWasShown();
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have only one more reset event.
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->add_event_count());
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(1, context()->reset_event_count());
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests that VisitedLink ignores renderer process creation notification for a
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// different context.
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(VisitedLinkEventsTest, IgnoreRendererCreationFromDifferentContext) {
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VisitCountingContext different_context;
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  VisitRelayingRenderProcessHost different_process_host(&different_context);
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::NotificationService::current()->Notify(
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::NOTIFICATION_RENDERER_PROCESS_CREATED,
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::Source<content::RenderProcessHost>(&different_process_host),
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::NotificationService::NoDetails());
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WaitForCoalescense();
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, different_context.new_table_count());
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
77090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace visitedlink
771