Index: chrome/browser/history/history_unittest.cc |
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc |
deleted file mode 100644 |
index edd9ddfb30979736b16690779dbebe329f582e57..0000000000000000000000000000000000000000 |
--- a/chrome/browser/history/history_unittest.cc |
+++ /dev/null |
@@ -1,1866 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-// History unit tests come in two flavors: |
-// |
-// 1. The more complicated style is that the unit test creates a full history |
-// service. This spawns a background thread for the history backend, and |
-// all communication is asynchronous. This is useful for testing more |
-// complicated things or end-to-end behavior. |
-// |
-// 2. The simpler style is to create a history backend on this thread and |
-// access it directly without a HistoryService object. This is much simpler |
-// because communication is synchronous. Generally, sets should go through |
-// the history backend (since there is a lot of logic) but gets can come |
-// directly from the HistoryDatabase. This is because the backend generally |
-// has no logic in the getter except threading stuff, which we don't want |
-// to run. |
- |
-#include <time.h> |
- |
-#include <algorithm> |
-#include <string> |
- |
-#include "base/basictypes.h" |
-#include "base/bind.h" |
-#include "base/bind_helpers.h" |
-#include "base/callback.h" |
-#include "base/command_line.h" |
-#include "base/compiler_specific.h" |
-#include "base/files/file_path.h" |
-#include "base/files/file_util.h" |
-#include "base/files/scoped_temp_dir.h" |
-#include "base/logging.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/memory/scoped_vector.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/path_service.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/task/cancelable_task_tracker.h" |
-#include "base/threading/platform_thread.h" |
-#include "base/time/time.h" |
-#include "chrome/common/chrome_constants.h" |
-#include "chrome/common/chrome_paths.h" |
-#include "components/history/content/browser/download_constants_utils.h" |
-#include "components/history/content/browser/history_database_helper.h" |
-#include "components/history/core/browser/download_constants.h" |
-#include "components/history/core/browser/download_row.h" |
-#include "components/history/core/browser/history_backend.h" |
-#include "components/history/core/browser/history_constants.h" |
-#include "components/history/core/browser/history_database.h" |
-#include "components/history/core/browser/history_database_params.h" |
-#include "components/history/core/browser/history_db_task.h" |
-#include "components/history/core/browser/history_service.h" |
-#include "components/history/core/browser/in_memory_database.h" |
-#include "components/history/core/browser/in_memory_history_backend.h" |
-#include "components/history/core/browser/page_usage_data.h" |
-#include "components/history/core/common/thumbnail_score.h" |
-#include "components/history/core/test/history_unittest_base.h" |
-#include "components/history/core/test/test_history_database.h" |
-#include "components/history/core/test/thumbnail-inl.h" |
-#include "content/public/browser/download_item.h" |
-#include "content/public/browser/notification_details.h" |
-#include "content/public/browser/notification_source.h" |
-#include "sql/connection.h" |
-#include "sql/statement.h" |
-#include "sync/api/attachments/attachment_id.h" |
-#include "sync/api/fake_sync_change_processor.h" |
-#include "sync/api/sync_change.h" |
-#include "sync/api/sync_change_processor.h" |
-#include "sync/api/sync_change_processor_wrapper_for_test.h" |
-#include "sync/api/sync_error.h" |
-#include "sync/api/sync_error_factory.h" |
-#include "sync/api/sync_merge_result.h" |
-#include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h" |
-#include "sync/protocol/history_delete_directive_specifics.pb.h" |
-#include "sync/protocol/sync.pb.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
-#include "third_party/skia/include/core/SkBitmap.h" |
-#include "ui/gfx/codec/jpeg_codec.h" |
- |
-using base::Time; |
-using base::TimeDelta; |
-using content::DownloadItem; |
- |
-namespace history { |
-class HistoryBackendDBTest; |
- |
-// Delegate class for when we create a backend without a HistoryService. |
-// |
-// This must be outside the anonymous namespace for the friend statement in |
-// HistoryBackendDBTest to work. |
-class BackendDelegate : public HistoryBackend::Delegate { |
- public: |
- explicit BackendDelegate(HistoryBackendDBTest* history_test) |
- : history_test_(history_test) { |
- } |
- |
- void NotifyProfileError(sql::InitStatus init_status) override {} |
- void SetInMemoryBackend(scoped_ptr<InMemoryHistoryBackend> backend) override; |
- void NotifyFaviconChanged(const std::set<GURL>& url) override {} |
- void NotifyURLVisited(ui::PageTransition transition, |
- const URLRow& row, |
- const RedirectList& redirects, |
- base::Time visit_time) override {} |
- void NotifyURLsModified(const URLRows& changed_urls) override {} |
- void NotifyURLsDeleted(bool all_history, |
- bool expired, |
- const URLRows& deleted_rows, |
- const std::set<GURL>& favicon_urls) override {} |
- void NotifyKeywordSearchTermUpdated(const URLRow& row, |
- KeywordID keyword_id, |
- const base::string16& term) override {} |
- void NotifyKeywordSearchTermDeleted(URLID url_id) override {} |
- void DBLoaded() override {} |
- |
- private: |
- HistoryBackendDBTest* history_test_; |
-}; |
- |
-// This must be outside the anonymous namespace for the friend statement in |
-// HistoryBackend to work. |
-class HistoryBackendDBTest : public HistoryUnitTestBase { |
- public: |
- HistoryBackendDBTest() : db_(NULL) { |
- } |
- |
- ~HistoryBackendDBTest() override {} |
- |
- protected: |
- friend class BackendDelegate; |
- |
- // Creates the HistoryBackend and HistoryDatabase on the current thread, |
- // assigning the values to backend_ and db_. |
- void CreateBackendAndDatabase() { |
- backend_ = new HistoryBackend(new BackendDelegate(this), nullptr); |
- backend_->Init(std::string(), false, |
- HistoryDatabaseParamsForPath(history_dir_)); |
- db_ = backend_->db_.get(); |
- DCHECK(in_mem_backend_) << "Mem backend should have been set by " |
- "HistoryBackend::Init"; |
- } |
- |
- void CreateDBVersion(int version) { |
- base::FilePath data_path; |
- ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); |
- data_path = data_path.AppendASCII("History"); |
- data_path = |
- data_path.AppendASCII(base::StringPrintf("history.%d.sql", version)); |
- ASSERT_NO_FATAL_FAILURE( |
- ExecuteSQLScript(data_path, history_dir_.Append(kHistoryFilename))); |
- } |
- |
- void CreateArchivedDB() { |
- base::FilePath data_path; |
- ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_path)); |
- data_path = data_path.AppendASCII("History"); |
- data_path = data_path.AppendASCII("archived_history.4.sql"); |
- ASSERT_NO_FATAL_FAILURE(ExecuteSQLScript( |
- data_path, history_dir_.Append(kArchivedHistoryFilename))); |
- } |
- |
- // testing::Test |
- void SetUp() override { |
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
- history_dir_ = temp_dir_.path().AppendASCII("HistoryBackendDBTest"); |
- ASSERT_TRUE(base::CreateDirectory(history_dir_)); |
- } |
- |
- void DeleteBackend() { |
- if (backend_.get()) { |
- backend_->Closing(); |
- backend_ = NULL; |
- } |
- } |
- |
- void TearDown() override { |
- DeleteBackend(); |
- |
- // Make sure we don't have any event pending that could disrupt the next |
- // test. |
- base::MessageLoop::current()->PostTask(FROM_HERE, |
- base::MessageLoop::QuitClosure()); |
- base::MessageLoop::current()->Run(); |
- } |
- |
- bool AddDownload(uint32 id, DownloadState state, const Time& time) { |
- std::vector<GURL> url_chain; |
- url_chain.push_back(GURL("foo-url")); |
- |
- DownloadRow download(base::FilePath(FILE_PATH_LITERAL("current-path")), |
- base::FilePath(FILE_PATH_LITERAL("target-path")), |
- url_chain, |
- GURL("http://referrer.com/"), |
- "application/vnd.oasis.opendocument.text", |
- "application/octet-stream", |
- time, |
- time, |
- std::string(), |
- std::string(), |
- 0, |
- 512, |
- state, |
- DownloadDangerType::NOT_DANGEROUS, |
- ToHistoryDownloadInterruptReason( |
- content::DOWNLOAD_INTERRUPT_REASON_NONE), |
- id, |
- false, |
- "by_ext_id", |
- "by_ext_name"); |
- return db_->CreateDownload(download); |
- } |
- |
- base::ScopedTempDir temp_dir_; |
- |
- base::MessageLoopForUI message_loop_; |
- |
- // names of the database files |
- base::FilePath history_dir_; |
- |
- // Created via CreateBackendAndDatabase. |
- scoped_refptr<HistoryBackend> backend_; |
- scoped_ptr<InMemoryHistoryBackend> in_mem_backend_; |
- HistoryDatabase* db_; // Cached reference to the backend's database. |
-}; |
- |
-void BackendDelegate::SetInMemoryBackend( |
- scoped_ptr<InMemoryHistoryBackend> backend) { |
- // Save the in-memory backend to the history test object, this happens |
- // synchronously, so we don't have to do anything fancy. |
- history_test_->in_mem_backend_.swap(backend); |
-} |
- |
-TEST_F(HistoryBackendDBTest, ClearBrowsingData_Downloads) { |
- CreateBackendAndDatabase(); |
- |
- // Initially there should be nothing in the downloads database. |
- std::vector<DownloadRow> downloads; |
- db_->QueryDownloads(&downloads); |
- EXPECT_EQ(0U, downloads.size()); |
- |
- // Add a download, test that it was added correctly, remove it, test that it |
- // was removed. |
- Time now = Time(); |
- uint32 id = 1; |
- EXPECT_TRUE(AddDownload(id, DownloadState::COMPLETE, Time())); |
- db_->QueryDownloads(&downloads); |
- EXPECT_EQ(1U, downloads.size()); |
- |
- EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("current-path")), |
- downloads[0].current_path); |
- EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("target-path")), |
- downloads[0].target_path); |
- EXPECT_EQ(1UL, downloads[0].url_chain.size()); |
- EXPECT_EQ(GURL("foo-url"), downloads[0].url_chain[0]); |
- EXPECT_EQ(std::string("http://referrer.com/"), |
- std::string(downloads[0].referrer_url.spec())); |
- EXPECT_EQ(now, downloads[0].start_time); |
- EXPECT_EQ(now, downloads[0].end_time); |
- EXPECT_EQ(0, downloads[0].received_bytes); |
- EXPECT_EQ(512, downloads[0].total_bytes); |
- EXPECT_EQ(DownloadState::COMPLETE, downloads[0].state); |
- EXPECT_EQ(DownloadDangerType::NOT_DANGEROUS, downloads[0].danger_type); |
- EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, |
- downloads[0].interrupt_reason); |
- EXPECT_FALSE(downloads[0].opened); |
- EXPECT_EQ("by_ext_id", downloads[0].by_ext_id); |
- EXPECT_EQ("by_ext_name", downloads[0].by_ext_name); |
- EXPECT_EQ("application/vnd.oasis.opendocument.text", downloads[0].mime_type); |
- EXPECT_EQ("application/octet-stream", downloads[0].original_mime_type); |
- |
- db_->QueryDownloads(&downloads); |
- EXPECT_EQ(1U, downloads.size()); |
- db_->RemoveDownload(id); |
- db_->QueryDownloads(&downloads); |
- EXPECT_EQ(0U, downloads.size()); |
-} |
- |
-TEST_F(HistoryBackendDBTest, MigrateDownloadsState) { |
- // Create the db we want. |
- ASSERT_NO_FATAL_FAILURE(CreateDBVersion(22)); |
- { |
- // Open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- |
- // Manually insert corrupted rows; there's infrastructure in place now to |
- // make this impossible, at least according to the test above. |
- for (int state = 0; state < 5; ++state) { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads (id, full_path, url, start_time, " |
- "received_bytes, total_bytes, state, end_time, opened) VALUES " |
- "(?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
- s.BindInt64(0, 1 + state); |
- s.BindString(1, "path"); |
- s.BindString(2, "url"); |
- s.BindInt64(3, base::Time::Now().ToTimeT()); |
- s.BindInt64(4, 100); |
- s.BindInt64(5, 100); |
- s.BindInt(6, state); |
- s.BindInt64(7, base::Time::Now().ToTimeT()); |
- s.BindInt(8, state % 2); |
- ASSERT_TRUE(s.Run()); |
- } |
- } |
- |
- // Re-open the db using the HistoryDatabase, which should migrate from version |
- // 22 to the current version, fixing just the row whose state was 3. |
- // Then close the db so that we can re-open it directly. |
- CreateBackendAndDatabase(); |
- DeleteBackend(); |
- { |
- // Re-open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- { |
- // The version should have been updated. |
- int cur_version = HistoryDatabase::GetCurrentVersion(); |
- ASSERT_LT(22, cur_version); |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT value FROM meta WHERE key = 'version'")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(cur_version, s.ColumnInt(0)); |
- } |
- { |
- sql::Statement statement(db.GetUniqueStatement( |
- "SELECT id, state, opened " |
- "FROM downloads " |
- "ORDER BY id")); |
- int counter = 0; |
- while (statement.Step()) { |
- EXPECT_EQ(1 + counter, statement.ColumnInt64(0)); |
- // The only thing that migration should have changed was state from 3 to |
- // 4. |
- EXPECT_EQ(((counter == 3) ? 4 : counter), statement.ColumnInt(1)); |
- EXPECT_EQ(counter % 2, statement.ColumnInt(2)); |
- ++counter; |
- } |
- EXPECT_EQ(5, counter); |
- } |
- } |
-} |
- |
-TEST_F(HistoryBackendDBTest, MigrateDownloadsReasonPathsAndDangerType) { |
- Time now(base::Time::Now()); |
- |
- // Create the db we want. The schema didn't change from 22->23, so just |
- // re-use the v22 file. |
- ASSERT_NO_FATAL_FAILURE(CreateDBVersion(22)); |
- { |
- // Re-open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- |
- // Manually insert some rows. |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads (id, full_path, url, start_time, " |
- "received_bytes, total_bytes, state, end_time, opened) VALUES " |
- "(?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
- |
- int64 id = 0; |
- // Null path. |
- s.BindInt64(0, ++id); |
- s.BindString(1, std::string()); |
- s.BindString(2, "http://whatever.com/index.html"); |
- s.BindInt64(3, now.ToTimeT()); |
- s.BindInt64(4, 100); |
- s.BindInt64(5, 100); |
- s.BindInt(6, 1); |
- s.BindInt64(7, now.ToTimeT()); |
- s.BindInt(8, 1); |
- ASSERT_TRUE(s.Run()); |
- s.Reset(true); |
- |
- // Non-null path. |
- s.BindInt64(0, ++id); |
- s.BindString(1, "/path/to/some/file"); |
- s.BindString(2, "http://whatever.com/index1.html"); |
- s.BindInt64(3, now.ToTimeT()); |
- s.BindInt64(4, 100); |
- s.BindInt64(5, 100); |
- s.BindInt(6, 1); |
- s.BindInt64(7, now.ToTimeT()); |
- s.BindInt(8, 1); |
- ASSERT_TRUE(s.Run()); |
- } |
- |
- // Re-open the db using the HistoryDatabase, which should migrate from version |
- // 23 to 24, creating the new tables and creating the new path, reason, |
- // and danger columns. |
- CreateBackendAndDatabase(); |
- DeleteBackend(); |
- { |
- // Re-open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- { |
- // The version should have been updated. |
- int cur_version = HistoryDatabase::GetCurrentVersion(); |
- ASSERT_LT(23, cur_version); |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT value FROM meta WHERE key = 'version'")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(cur_version, s.ColumnInt(0)); |
- } |
- { |
- base::Time nowish(base::Time::FromTimeT(now.ToTimeT())); |
- |
- // Confirm downloads table is valid. |
- sql::Statement statement(db.GetUniqueStatement( |
- "SELECT id, interrupt_reason, current_path, target_path, " |
- " danger_type, start_time, end_time " |
- "FROM downloads ORDER BY id")); |
- EXPECT_TRUE(statement.Step()); |
- EXPECT_EQ(1, statement.ColumnInt64(0)); |
- EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, |
- statement.ColumnInt(1)); |
- EXPECT_EQ("", statement.ColumnString(2)); |
- EXPECT_EQ("", statement.ColumnString(3)); |
- // Implicit dependence on value of kDangerTypeNotDangerous from |
- // download_database.cc. |
- EXPECT_EQ(0, statement.ColumnInt(4)); |
- EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(5)); |
- EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(6)); |
- |
- EXPECT_TRUE(statement.Step()); |
- EXPECT_EQ(2, statement.ColumnInt64(0)); |
- EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, |
- statement.ColumnInt(1)); |
- EXPECT_EQ("/path/to/some/file", statement.ColumnString(2)); |
- EXPECT_EQ("/path/to/some/file", statement.ColumnString(3)); |
- EXPECT_EQ(0, statement.ColumnInt(4)); |
- EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(5)); |
- EXPECT_EQ(nowish.ToInternalValue(), statement.ColumnInt64(6)); |
- |
- EXPECT_FALSE(statement.Step()); |
- } |
- { |
- // Confirm downloads_url_chains table is valid. |
- sql::Statement statement(db.GetUniqueStatement( |
- "SELECT id, chain_index, url FROM downloads_url_chains " |
- " ORDER BY id, chain_index")); |
- EXPECT_TRUE(statement.Step()); |
- EXPECT_EQ(1, statement.ColumnInt64(0)); |
- EXPECT_EQ(0, statement.ColumnInt(1)); |
- EXPECT_EQ("http://whatever.com/index.html", statement.ColumnString(2)); |
- |
- EXPECT_TRUE(statement.Step()); |
- EXPECT_EQ(2, statement.ColumnInt64(0)); |
- EXPECT_EQ(0, statement.ColumnInt(1)); |
- EXPECT_EQ("http://whatever.com/index1.html", statement.ColumnString(2)); |
- |
- EXPECT_FALSE(statement.Step()); |
- } |
- } |
-} |
- |
-TEST_F(HistoryBackendDBTest, MigrateReferrer) { |
- Time now(base::Time::Now()); |
- ASSERT_NO_FATAL_FAILURE(CreateDBVersion(22)); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads (id, full_path, url, start_time, " |
- "received_bytes, total_bytes, state, end_time, opened) VALUES " |
- "(?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
- int64 db_handle = 0; |
- s.BindInt64(0, ++db_handle); |
- s.BindString(1, "full_path"); |
- s.BindString(2, "http://whatever.com/index.html"); |
- s.BindInt64(3, now.ToTimeT()); |
- s.BindInt64(4, 100); |
- s.BindInt64(5, 100); |
- s.BindInt(6, 1); |
- s.BindInt64(7, now.ToTimeT()); |
- s.BindInt(8, 1); |
- ASSERT_TRUE(s.Run()); |
- } |
- // Re-open the db using the HistoryDatabase, which should migrate to version |
- // 26, creating the referrer column. |
- CreateBackendAndDatabase(); |
- DeleteBackend(); |
- { |
- // Re-open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- // The version should have been updated. |
- int cur_version = HistoryDatabase::GetCurrentVersion(); |
- ASSERT_LE(26, cur_version); |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT value FROM meta WHERE key = 'version'")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(cur_version, s.ColumnInt(0)); |
- } |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT referrer from downloads")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(std::string(), s.ColumnString(0)); |
- } |
- } |
-} |
- |
-TEST_F(HistoryBackendDBTest, MigrateDownloadedByExtension) { |
- Time now(base::Time::Now()); |
- ASSERT_NO_FATAL_FAILURE(CreateDBVersion(26)); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads (id, current_path, target_path, start_time, " |
- "received_bytes, total_bytes, state, danger_type, interrupt_reason, " |
- "end_time, opened, referrer) VALUES " |
- "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
- s.BindInt64(0, 1); |
- s.BindString(1, "current_path"); |
- s.BindString(2, "target_path"); |
- s.BindInt64(3, now.ToTimeT()); |
- s.BindInt64(4, 100); |
- s.BindInt64(5, 100); |
- s.BindInt(6, 1); |
- s.BindInt(7, 0); |
- s.BindInt(8, 0); |
- s.BindInt64(9, now.ToTimeT()); |
- s.BindInt(10, 1); |
- s.BindString(11, "referrer"); |
- ASSERT_TRUE(s.Run()); |
- } |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads_url_chains (id, chain_index, url) VALUES " |
- "(?, ?, ?)")); |
- s.BindInt64(0, 4); |
- s.BindInt64(1, 0); |
- s.BindString(2, "url"); |
- ASSERT_TRUE(s.Run()); |
- } |
- } |
- // Re-open the db using the HistoryDatabase, which should migrate to version |
- // 27, creating the by_ext_id and by_ext_name columns. |
- CreateBackendAndDatabase(); |
- DeleteBackend(); |
- { |
- // Re-open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- // The version should have been updated. |
- int cur_version = HistoryDatabase::GetCurrentVersion(); |
- ASSERT_LE(27, cur_version); |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT value FROM meta WHERE key = 'version'")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(cur_version, s.ColumnInt(0)); |
- } |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT by_ext_id, by_ext_name from downloads")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(std::string(), s.ColumnString(0)); |
- EXPECT_EQ(std::string(), s.ColumnString(1)); |
- } |
- } |
-} |
- |
-TEST_F(HistoryBackendDBTest, MigrateDownloadValidators) { |
- Time now(base::Time::Now()); |
- ASSERT_NO_FATAL_FAILURE(CreateDBVersion(27)); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads (id, current_path, target_path, start_time, " |
- "received_bytes, total_bytes, state, danger_type, interrupt_reason, " |
- "end_time, opened, referrer, by_ext_id, by_ext_name) VALUES " |
- "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
- s.BindInt64(0, 1); |
- s.BindString(1, "current_path"); |
- s.BindString(2, "target_path"); |
- s.BindInt64(3, now.ToTimeT()); |
- s.BindInt64(4, 100); |
- s.BindInt64(5, 100); |
- s.BindInt(6, 1); |
- s.BindInt(7, 0); |
- s.BindInt(8, 0); |
- s.BindInt64(9, now.ToTimeT()); |
- s.BindInt(10, 1); |
- s.BindString(11, "referrer"); |
- s.BindString(12, "by extension ID"); |
- s.BindString(13, "by extension name"); |
- ASSERT_TRUE(s.Run()); |
- } |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads_url_chains (id, chain_index, url) VALUES " |
- "(?, ?, ?)")); |
- s.BindInt64(0, 4); |
- s.BindInt64(1, 0); |
- s.BindString(2, "url"); |
- ASSERT_TRUE(s.Run()); |
- } |
- } |
- // Re-open the db using the HistoryDatabase, which should migrate to the |
- // current version, creating the etag and last_modified columns. |
- CreateBackendAndDatabase(); |
- DeleteBackend(); |
- { |
- // Re-open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- // The version should have been updated. |
- int cur_version = HistoryDatabase::GetCurrentVersion(); |
- ASSERT_LE(28, cur_version); |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT value FROM meta WHERE key = 'version'")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(cur_version, s.ColumnInt(0)); |
- } |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT etag, last_modified from downloads")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(std::string(), s.ColumnString(0)); |
- EXPECT_EQ(std::string(), s.ColumnString(1)); |
- } |
- } |
-} |
- |
-TEST_F(HistoryBackendDBTest, PurgeArchivedDatabase) { |
- ASSERT_NO_FATAL_FAILURE(CreateDBVersion(27)); |
- ASSERT_NO_FATAL_FAILURE(CreateArchivedDB()); |
- |
- ASSERT_TRUE(base::PathExists(history_dir_.Append(kArchivedHistoryFilename))); |
- |
- CreateBackendAndDatabase(); |
- DeleteBackend(); |
- |
- // We do not retain expired history entries in an archived database as of M37. |
- // Verify that any legacy archived database is deleted on start-up. |
- ASSERT_FALSE(base::PathExists(history_dir_.Append(kArchivedHistoryFilename))); |
-} |
- |
-TEST_F(HistoryBackendDBTest, MigrateDownloadMimeType) { |
- Time now(base::Time::Now()); |
- ASSERT_NO_FATAL_FAILURE(CreateDBVersion(28)); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads (id, current_path, target_path, start_time, " |
- "received_bytes, total_bytes, state, danger_type, interrupt_reason, " |
- "end_time, opened, referrer, by_ext_id, by_ext_name, etag, " |
- "last_modified) VALUES " |
- "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); |
- s.BindInt64(0, 1); |
- s.BindString(1, "current_path"); |
- s.BindString(2, "target_path"); |
- s.BindInt64(3, now.ToTimeT()); |
- s.BindInt64(4, 100); |
- s.BindInt64(5, 100); |
- s.BindInt(6, 1); |
- s.BindInt(7, 0); |
- s.BindInt(8, 0); |
- s.BindInt64(9, now.ToTimeT()); |
- s.BindInt(10, 1); |
- s.BindString(11, "referrer"); |
- s.BindString(12, "by extension ID"); |
- s.BindString(13, "by extension name"); |
- s.BindString(14, "etag"); |
- s.BindInt64(15, now.ToTimeT()); |
- ASSERT_TRUE(s.Run()); |
- } |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO downloads_url_chains (id, chain_index, url) VALUES " |
- "(?, ?, ?)")); |
- s.BindInt64(0, 4); |
- s.BindInt64(1, 0); |
- s.BindString(2, "url"); |
- ASSERT_TRUE(s.Run()); |
- } |
- } |
- // Re-open the db using the HistoryDatabase, which should migrate to the |
- // current version, creating themime_type abd original_mime_type columns. |
- CreateBackendAndDatabase(); |
- DeleteBackend(); |
- { |
- // Re-open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- // The version should have been updated. |
- int cur_version = HistoryDatabase::GetCurrentVersion(); |
- ASSERT_LE(29, cur_version); |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT value FROM meta WHERE key = 'version'")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(cur_version, s.ColumnInt(0)); |
- } |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "SELECT mime_type, original_mime_type from downloads")); |
- EXPECT_TRUE(s.Step()); |
- EXPECT_EQ(std::string(), s.ColumnString(0)); |
- EXPECT_EQ(std::string(), s.ColumnString(1)); |
- } |
- } |
-} |
- |
-TEST_F(HistoryBackendDBTest, ConfirmDownloadRowCreateAndDelete) { |
- // Create the DB. |
- CreateBackendAndDatabase(); |
- |
- base::Time now(base::Time::Now()); |
- |
- // Add some downloads. |
- uint32 id1 = 1, id2 = 2, id3 = 3; |
- AddDownload(id1, DownloadState::COMPLETE, now); |
- AddDownload(id2, DownloadState::COMPLETE, now + base::TimeDelta::FromDays(2)); |
- AddDownload(id3, DownloadState::COMPLETE, now - base::TimeDelta::FromDays(2)); |
- |
- // Confirm that resulted in the correct number of rows in the DB. |
- DeleteBackend(); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- sql::Statement statement(db.GetUniqueStatement( |
- "Select Count(*) from downloads")); |
- EXPECT_TRUE(statement.Step()); |
- EXPECT_EQ(3, statement.ColumnInt(0)); |
- |
- sql::Statement statement1(db.GetUniqueStatement( |
- "Select Count(*) from downloads_url_chains")); |
- EXPECT_TRUE(statement1.Step()); |
- EXPECT_EQ(3, statement1.ColumnInt(0)); |
- } |
- |
- // Delete some rows and make sure the results are still correct. |
- CreateBackendAndDatabase(); |
- db_->RemoveDownload(id2); |
- db_->RemoveDownload(id3); |
- DeleteBackend(); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- sql::Statement statement(db.GetUniqueStatement( |
- "Select Count(*) from downloads")); |
- EXPECT_TRUE(statement.Step()); |
- EXPECT_EQ(1, statement.ColumnInt(0)); |
- |
- sql::Statement statement1(db.GetUniqueStatement( |
- "Select Count(*) from downloads_url_chains")); |
- EXPECT_TRUE(statement1.Step()); |
- EXPECT_EQ(1, statement1.ColumnInt(0)); |
- } |
-} |
- |
-TEST_F(HistoryBackendDBTest, DownloadNukeRecordsMissingURLs) { |
- CreateBackendAndDatabase(); |
- base::Time now(base::Time::Now()); |
- std::vector<GURL> url_chain; |
- DownloadRow download(base::FilePath(FILE_PATH_LITERAL("foo-path")), |
- base::FilePath(FILE_PATH_LITERAL("foo-path")), |
- url_chain, |
- GURL(std::string()), |
- "application/octet-stream", |
- "application/octet-stream", |
- now, |
- now, |
- std::string(), |
- std::string(), |
- 0, |
- 512, |
- DownloadState::COMPLETE, |
- DownloadDangerType::NOT_DANGEROUS, |
- ToHistoryDownloadInterruptReason( |
- content::DOWNLOAD_INTERRUPT_REASON_NONE), |
- 1, |
- 0, |
- "by_ext_id", |
- "by_ext_name"); |
- |
- // Creating records without any urls should fail. |
- EXPECT_FALSE(db_->CreateDownload(download)); |
- |
- download.url_chain.push_back(GURL("foo-url")); |
- EXPECT_TRUE(db_->CreateDownload(download)); |
- |
- // Pretend that the URLs were dropped. |
- DeleteBackend(); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- sql::Statement statement(db.GetUniqueStatement( |
- "DELETE FROM downloads_url_chains WHERE id=1")); |
- ASSERT_TRUE(statement.Run()); |
- } |
- CreateBackendAndDatabase(); |
- std::vector<DownloadRow> downloads; |
- db_->QueryDownloads(&downloads); |
- EXPECT_EQ(0U, downloads.size()); |
- |
- // QueryDownloads should have nuked the corrupt record. |
- DeleteBackend(); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- { |
- sql::Statement statement(db.GetUniqueStatement( |
- "SELECT count(*) from downloads")); |
- ASSERT_TRUE(statement.Step()); |
- EXPECT_EQ(0, statement.ColumnInt(0)); |
- } |
- } |
-} |
- |
-TEST_F(HistoryBackendDBTest, ConfirmDownloadInProgressCleanup) { |
- // Create the DB. |
- CreateBackendAndDatabase(); |
- |
- base::Time now(base::Time::Now()); |
- |
- // Put an IN_PROGRESS download in the DB. |
- AddDownload(1, DownloadState::IN_PROGRESS, now); |
- |
- // Confirm that they made it into the DB unchanged. |
- DeleteBackend(); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- sql::Statement statement(db.GetUniqueStatement( |
- "Select Count(*) from downloads")); |
- EXPECT_TRUE(statement.Step()); |
- EXPECT_EQ(1, statement.ColumnInt(0)); |
- |
- sql::Statement statement1(db.GetUniqueStatement( |
- "Select state, interrupt_reason from downloads")); |
- EXPECT_TRUE(statement1.Step()); |
- EXPECT_EQ(DownloadStateToInt(DownloadState::IN_PROGRESS), |
- statement1.ColumnInt(0)); |
- EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, statement1.ColumnInt(1)); |
- EXPECT_FALSE(statement1.Step()); |
- } |
- |
- // Read in the DB through query downloads, then test that the |
- // right transformation was returned. |
- CreateBackendAndDatabase(); |
- std::vector<DownloadRow> results; |
- db_->QueryDownloads(&results); |
- ASSERT_EQ(1u, results.size()); |
- EXPECT_EQ(DownloadState::INTERRUPTED, results[0].state); |
- EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_CRASH, |
- results[0].interrupt_reason); |
- |
- // Allow the update to propagate, shut down the DB, and confirm that |
- // the query updated the on disk database as well. |
- base::MessageLoop::current()->RunUntilIdle(); |
- DeleteBackend(); |
- { |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- sql::Statement statement(db.GetUniqueStatement( |
- "Select Count(*) from downloads")); |
- EXPECT_TRUE(statement.Step()); |
- EXPECT_EQ(1, statement.ColumnInt(0)); |
- |
- sql::Statement statement1(db.GetUniqueStatement( |
- "Select state, interrupt_reason from downloads")); |
- EXPECT_TRUE(statement1.Step()); |
- EXPECT_EQ(DownloadStateToInt(DownloadState::INTERRUPTED), |
- statement1.ColumnInt(0)); |
- EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_CRASH, |
- statement1.ColumnInt(1)); |
- EXPECT_FALSE(statement1.Step()); |
- } |
-} |
- |
-struct InterruptReasonAssociation { |
- std::string name; |
- int value; |
-}; |
- |
-// Test is dependent on interrupt reasons being listed in header file |
-// in order. |
-const InterruptReasonAssociation current_reasons[] = { |
-#define INTERRUPT_REASON(a, b) { #a, b }, |
-#include "content/public/browser/download_interrupt_reason_values.h" |
-#undef INTERRUPT_REASON |
-}; |
- |
-// This represents a list of all reasons we've previously used; |
-// Do Not Remove Any Entries From This List. |
-const InterruptReasonAssociation historical_reasons[] = { |
- {"FILE_FAILED", 1}, |
- {"FILE_ACCESS_DENIED", 2}, |
- {"FILE_NO_SPACE", 3}, |
- {"FILE_NAME_TOO_LONG", 5}, |
- {"FILE_TOO_LARGE", 6}, |
- {"FILE_VIRUS_INFECTED", 7}, |
- {"FILE_TRANSIENT_ERROR", 10}, |
- {"FILE_BLOCKED", 11}, |
- {"FILE_SECURITY_CHECK_FAILED", 12}, |
- {"FILE_TOO_SHORT", 13}, |
- {"NETWORK_FAILED", 20}, |
- {"NETWORK_TIMEOUT", 21}, |
- {"NETWORK_DISCONNECTED", 22}, |
- {"NETWORK_SERVER_DOWN", 23}, |
- {"NETWORK_INVALID_REQUEST", 24}, |
- {"SERVER_FAILED", 30}, |
- {"SERVER_NO_RANGE", 31}, |
- {"SERVER_PRECONDITION", 32}, |
- {"SERVER_BAD_CONTENT", 33}, |
- {"SERVER_UNAUTHORIZED", 34}, |
- {"SERVER_CERT_PROBLEM", 35}, |
- {"USER_CANCELED", 40}, |
- {"USER_SHUTDOWN", 41}, |
- {"CRASH", 50}, |
-}; |
- |
-// Make sure no one has changed a DownloadInterruptReason we've previously |
-// persisted. |
-TEST_F(HistoryBackendDBTest, |
- ConfirmDownloadInterruptReasonBackwardsCompatible) { |
- // Are there any cases in which a historical number has been repurposed |
- // for an error other than it's original? |
- for (size_t i = 0; i < arraysize(current_reasons); i++) { |
- const InterruptReasonAssociation& cur_reason(current_reasons[i]); |
- bool found = false; |
- |
- for (size_t j = 0; j < arraysize(historical_reasons); ++j) { |
- const InterruptReasonAssociation& hist_reason(historical_reasons[j]); |
- |
- if (hist_reason.value == cur_reason.value) { |
- EXPECT_EQ(cur_reason.name, hist_reason.name) |
- << "Same integer value used for old error \"" |
- << hist_reason.name |
- << "\" as for new error \"" |
- << cur_reason.name |
- << "\"." << std::endl |
- << "**This will cause database conflicts with persisted values**" |
- << std::endl |
- << "Please assign a new, non-conflicting value for the new error."; |
- } |
- |
- if (hist_reason.name == cur_reason.name) { |
- EXPECT_EQ(cur_reason.value, hist_reason.value) |
- << "Same name (\"" << hist_reason.name |
- << "\") maps to a different value historically (" |
- << hist_reason.value << ") and currently (" |
- << cur_reason.value << ")" << std::endl |
- << "This may cause database conflicts with persisted values" |
- << std::endl |
- << "If this error is the same as the old one, you should" |
- << std::endl |
- << "use the old value, and if it is different, you should" |
- << std::endl |
- << "use a new name."; |
- |
- found = true; |
- } |
- } |
- |
- EXPECT_TRUE(found) |
- << "Error \"" << cur_reason.name << "\" not found in historical list." |
- << std::endl |
- << "Please add it."; |
- } |
-} |
- |
-class HistoryTest : public testing::Test { |
- public: |
- HistoryTest() : query_url_success_(false) { |
- } |
- |
- ~HistoryTest() override {} |
- |
- void OnMostVisitedURLsAvailable(const MostVisitedURLList* url_list) { |
- most_visited_urls_ = *url_list; |
- base::MessageLoop::current()->Quit(); |
- } |
- |
- protected: |
- friend class BackendDelegate; |
- |
- // testing::Test |
- void SetUp() override { |
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
- history_dir_ = temp_dir_.path().AppendASCII("HistoryTest"); |
- ASSERT_TRUE(base::CreateDirectory(history_dir_)); |
- history_service_.reset(new history::HistoryService); |
- if (!history_service_->Init(std::string(), |
- HistoryDatabaseParamsForPath(history_dir_))) { |
- history_service_.reset(); |
- ADD_FAILURE(); |
- } |
- } |
- |
- void TearDown() override { |
- if (history_service_) |
- CleanupHistoryService(); |
- |
- // Make sure we don't have any event pending that could disrupt the next |
- // test. |
- base::MessageLoop::current()->PostTask(FROM_HERE, |
- base::MessageLoop::QuitClosure()); |
- base::MessageLoop::current()->Run(); |
- } |
- |
- void CleanupHistoryService() { |
- DCHECK(history_service_); |
- |
- history_service_->ClearCachedDataForContextID(0); |
- history_service_->SetOnBackendDestroyTask(base::MessageLoop::QuitClosure()); |
- history_service_->Cleanup(); |
- history_service_.reset(); |
- |
- // Wait for the backend class to terminate before deleting the files and |
- // moving to the next test. Note: if this never terminates, somebody is |
- // probably leaking a reference to the history backend, so it never calls |
- // our destroy task. |
- base::MessageLoop::current()->Run(); |
- } |
- |
- // Fills the query_url_row_ and query_url_visits_ structures with the |
- // information about the given URL and returns true. If the URL was not |
- // found, this will return false and those structures will not be changed. |
- bool QueryURL(history::HistoryService* history, const GURL& url) { |
- history_service_->QueryURL( |
- url, |
- true, |
- base::Bind(&HistoryTest::SaveURLAndQuit, base::Unretained(this)), |
- &tracker_); |
- base::MessageLoop::current()->Run(); // Will be exited in SaveURLAndQuit. |
- return query_url_success_; |
- } |
- |
- // Callback for HistoryService::QueryURL. |
- void SaveURLAndQuit(bool success, |
- const URLRow& url_row, |
- const VisitVector& visits) { |
- query_url_success_ = success; |
- if (query_url_success_) { |
- query_url_row_ = url_row; |
- query_url_visits_ = visits; |
- } else { |
- query_url_row_ = URLRow(); |
- query_url_visits_.clear(); |
- } |
- base::MessageLoop::current()->Quit(); |
- } |
- |
- // Fills in saved_redirects_ with the redirect information for the given URL, |
- // returning true on success. False means the URL was not found. |
- void QueryRedirectsFrom(history::HistoryService* history, const GURL& url) { |
- history_service_->QueryRedirectsFrom( |
- url, |
- base::Bind(&HistoryTest::OnRedirectQueryComplete, |
- base::Unretained(this)), |
- &tracker_); |
- base::MessageLoop::current()->Run(); // Will be exited in *QueryComplete. |
- } |
- |
- // Callback for QueryRedirects. |
- void OnRedirectQueryComplete(const history::RedirectList* redirects) { |
- saved_redirects_.clear(); |
- if (!redirects->empty()) { |
- saved_redirects_.insert( |
- saved_redirects_.end(), redirects->begin(), redirects->end()); |
- } |
- base::MessageLoop::current()->Quit(); |
- } |
- |
- base::ScopedTempDir temp_dir_; |
- |
- base::MessageLoopForUI message_loop_; |
- |
- MostVisitedURLList most_visited_urls_; |
- |
- // When non-NULL, this will be deleted on tear down and we will block until |
- // the backend thread has completed. This allows tests for the history |
- // service to use this feature, but other tests to ignore this. |
- scoped_ptr<history::HistoryService> history_service_; |
- |
- // names of the database files |
- base::FilePath history_dir_; |
- |
- // Set by the redirect callback when we get data. You should be sure to |
- // clear this before issuing a redirect request. |
- history::RedirectList saved_redirects_; |
- |
- // For history requests. |
- base::CancelableTaskTracker tracker_; |
- |
- // For saving URL info after a call to QueryURL |
- bool query_url_success_; |
- URLRow query_url_row_; |
- VisitVector query_url_visits_; |
-}; |
- |
-TEST_F(HistoryTest, AddPage) { |
- ASSERT_TRUE(history_service_.get()); |
- // Add the page once from a child frame. |
- const GURL test_url("http://www.google.com/"); |
- history_service_->AddPage(test_url, base::Time::Now(), NULL, 0, GURL(), |
- history::RedirectList(), |
- ui::PAGE_TRANSITION_MANUAL_SUBFRAME, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- EXPECT_EQ(0, query_url_row_.typed_count()); |
- EXPECT_TRUE(query_url_row_.hidden()); // Hidden because of child frame. |
- |
- // Add the page once from the main frame (should unhide it). |
- history_service_->AddPage(test_url, base::Time::Now(), NULL, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- EXPECT_EQ(2, query_url_row_.visit_count()); // Added twice. |
- EXPECT_EQ(0, query_url_row_.typed_count()); // Never typed. |
- EXPECT_FALSE(query_url_row_.hidden()); // Because loaded in main frame. |
-} |
- |
-TEST_F(HistoryTest, AddRedirect) { |
- ASSERT_TRUE(history_service_.get()); |
- const char* first_sequence[] = { |
- "http://first.page.com/", |
- "http://second.page.com/"}; |
- int first_count = arraysize(first_sequence); |
- history::RedirectList first_redirects; |
- for (int i = 0; i < first_count; i++) |
- first_redirects.push_back(GURL(first_sequence[i])); |
- |
- // Add the sequence of pages as a server with no referrer. Note that we need |
- // to have a non-NULL page ID scope. |
- history_service_->AddPage( |
- first_redirects.back(), base::Time::Now(), |
- reinterpret_cast<ContextID>(1), 0, GURL(), first_redirects, |
- ui::PAGE_TRANSITION_LINK, history::SOURCE_BROWSED, true); |
- |
- // The first page should be added once with a link visit type (because we set |
- // LINK when we added the original URL, and a referrer of nowhere (0). |
- EXPECT_TRUE(QueryURL(history_service_.get(), first_redirects[0])); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- ASSERT_EQ(1U, query_url_visits_.size()); |
- int64 first_visit = query_url_visits_[0].visit_id; |
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK | |
- ui::PAGE_TRANSITION_CHAIN_START, |
- query_url_visits_[0].transition); |
- EXPECT_EQ(0, query_url_visits_[0].referring_visit); // No referrer. |
- |
- // The second page should be a server redirect type with a referrer of the |
- // first page. |
- EXPECT_TRUE(QueryURL(history_service_.get(), first_redirects[1])); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- ASSERT_EQ(1U, query_url_visits_.size()); |
- int64 second_visit = query_url_visits_[0].visit_id; |
- EXPECT_EQ(ui::PAGE_TRANSITION_SERVER_REDIRECT | |
- ui::PAGE_TRANSITION_CHAIN_END, |
- query_url_visits_[0].transition); |
- EXPECT_EQ(first_visit, query_url_visits_[0].referring_visit); |
- |
- // Check that the redirect finding function successfully reports it. |
- saved_redirects_.clear(); |
- QueryRedirectsFrom(history_service_.get(), first_redirects[0]); |
- ASSERT_EQ(1U, saved_redirects_.size()); |
- EXPECT_EQ(first_redirects[1], saved_redirects_[0]); |
- |
- // Now add a client redirect from that second visit to a third, client |
- // redirects are tracked by the RenderView prior to updating history, |
- // so we pass in a CLIENT_REDIRECT qualifier to mock that behavior. |
- history::RedirectList second_redirects; |
- second_redirects.push_back(first_redirects[1]); |
- second_redirects.push_back(GURL("http://last.page.com/")); |
- history_service_->AddPage(second_redirects[1], base::Time::Now(), |
- reinterpret_cast<ContextID>(1), 1, |
- second_redirects[0], second_redirects, |
- ui::PageTransitionFromInt( |
- ui::PAGE_TRANSITION_LINK | |
- ui::PAGE_TRANSITION_CLIENT_REDIRECT), |
- history::SOURCE_BROWSED, true); |
- |
- // The last page (source of the client redirect) should NOT have an |
- // additional visit added, because it was a client redirect (normally it |
- // would). We should only have 1 left over from the first sequence. |
- EXPECT_TRUE(QueryURL(history_service_.get(), second_redirects[0])); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- |
- // The final page should be set as a client redirect from the previous visit. |
- EXPECT_TRUE(QueryURL(history_service_.get(), second_redirects[1])); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- ASSERT_EQ(1U, query_url_visits_.size()); |
- EXPECT_EQ(ui::PAGE_TRANSITION_CLIENT_REDIRECT | |
- ui::PAGE_TRANSITION_CHAIN_END, |
- query_url_visits_[0].transition); |
- EXPECT_EQ(second_visit, query_url_visits_[0].referring_visit); |
-} |
- |
-TEST_F(HistoryTest, MakeIntranetURLsTyped) { |
- ASSERT_TRUE(history_service_.get()); |
- |
- // Add a non-typed visit to an intranet URL on an unvisited host. This should |
- // get promoted to a typed visit. |
- const GURL test_url("http://intranet_host/path"); |
- history_service_->AddPage( |
- test_url, base::Time::Now(), NULL, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- EXPECT_EQ(1, query_url_row_.typed_count()); |
- ASSERT_EQ(1U, query_url_visits_.size()); |
- EXPECT_EQ(ui::PAGE_TRANSITION_TYPED, |
- ui::PageTransitionStripQualifier(query_url_visits_[0].transition)); |
- |
- // Add more visits on the same host. None of these should be promoted since |
- // there is already a typed visit. |
- |
- // Different path. |
- const GURL test_url2("http://intranet_host/different_path"); |
- history_service_->AddPage( |
- test_url2, base::Time::Now(), NULL, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url2)); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- EXPECT_EQ(0, query_url_row_.typed_count()); |
- ASSERT_EQ(1U, query_url_visits_.size()); |
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, |
- ui::PageTransitionStripQualifier(query_url_visits_[0].transition)); |
- |
- // No path. |
- const GURL test_url3("http://intranet_host/"); |
- history_service_->AddPage( |
- test_url3, base::Time::Now(), NULL, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url3)); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- EXPECT_EQ(0, query_url_row_.typed_count()); |
- ASSERT_EQ(1U, query_url_visits_.size()); |
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, |
- ui::PageTransitionStripQualifier(query_url_visits_[0].transition)); |
- |
- // Different scheme. |
- const GURL test_url4("https://intranet_host/"); |
- history_service_->AddPage( |
- test_url4, base::Time::Now(), NULL, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url4)); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- EXPECT_EQ(0, query_url_row_.typed_count()); |
- ASSERT_EQ(1U, query_url_visits_.size()); |
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, |
- ui::PageTransitionStripQualifier(query_url_visits_[0].transition)); |
- |
- // Different transition. |
- const GURL test_url5("http://intranet_host/another_path"); |
- history_service_->AddPage( |
- test_url5, base::Time::Now(), NULL, 0, GURL(), |
- history::RedirectList(), |
- ui::PAGE_TRANSITION_AUTO_BOOKMARK, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url5)); |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- EXPECT_EQ(0, query_url_row_.typed_count()); |
- ASSERT_EQ(1U, query_url_visits_.size()); |
- EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_BOOKMARK, |
- ui::PageTransitionStripQualifier(query_url_visits_[0].transition)); |
- |
- // Original URL. |
- history_service_->AddPage( |
- test_url, base::Time::Now(), NULL, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- EXPECT_EQ(2, query_url_row_.visit_count()); |
- EXPECT_EQ(1, query_url_row_.typed_count()); |
- ASSERT_EQ(2U, query_url_visits_.size()); |
- EXPECT_EQ(ui::PAGE_TRANSITION_LINK, |
- ui::PageTransitionStripQualifier(query_url_visits_[1].transition)); |
-} |
- |
-TEST_F(HistoryTest, Typed) { |
- const ContextID context_id = reinterpret_cast<ContextID>(1); |
- |
- ASSERT_TRUE(history_service_.get()); |
- |
- // Add the page once as typed. |
- const GURL test_url("http://www.google.com/"); |
- history_service_->AddPage( |
- test_url, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_TYPED, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- |
- // We should have the same typed & visit count. |
- EXPECT_EQ(1, query_url_row_.visit_count()); |
- EXPECT_EQ(1, query_url_row_.typed_count()); |
- |
- // Add the page again not typed. |
- history_service_->AddPage( |
- test_url, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- |
- // The second time should not have updated the typed count. |
- EXPECT_EQ(2, query_url_row_.visit_count()); |
- EXPECT_EQ(1, query_url_row_.typed_count()); |
- |
- // Add the page again as a generated URL. |
- history_service_->AddPage( |
- test_url, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_GENERATED, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- |
- // This should have worked like a link click. |
- EXPECT_EQ(3, query_url_row_.visit_count()); |
- EXPECT_EQ(1, query_url_row_.typed_count()); |
- |
- // Add the page again as a reload. |
- history_service_->AddPage( |
- test_url, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_RELOAD, |
- history::SOURCE_BROWSED, false); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- |
- // This should not have incremented any visit counts. |
- EXPECT_EQ(3, query_url_row_.visit_count()); |
- EXPECT_EQ(1, query_url_row_.typed_count()); |
-} |
- |
-TEST_F(HistoryTest, SetTitle) { |
- ASSERT_TRUE(history_service_.get()); |
- |
- // Add a URL. |
- const GURL existing_url("http://www.google.com/"); |
- history_service_->AddPage( |
- existing_url, base::Time::Now(), history::SOURCE_BROWSED); |
- |
- // Set some title. |
- const base::string16 existing_title = base::UTF8ToUTF16("Google"); |
- history_service_->SetPageTitle(existing_url, existing_title); |
- |
- // Make sure the title got set. |
- EXPECT_TRUE(QueryURL(history_service_.get(), existing_url)); |
- EXPECT_EQ(existing_title, query_url_row_.title()); |
- |
- // set a title on a nonexistent page |
- const GURL nonexistent_url("http://news.google.com/"); |
- const base::string16 nonexistent_title = base::UTF8ToUTF16("Google News"); |
- history_service_->SetPageTitle(nonexistent_url, nonexistent_title); |
- |
- // Make sure nothing got written. |
- EXPECT_FALSE(QueryURL(history_service_.get(), nonexistent_url)); |
- EXPECT_EQ(base::string16(), query_url_row_.title()); |
- |
- // TODO(brettw) this should also test redirects, which get the title of the |
- // destination page. |
-} |
- |
-TEST_F(HistoryTest, MostVisitedURLs) { |
- ASSERT_TRUE(history_service_.get()); |
- |
- const GURL url0("http://www.google.com/url0/"); |
- const GURL url1("http://www.google.com/url1/"); |
- const GURL url2("http://www.google.com/url2/"); |
- const GURL url3("http://www.google.com/url3/"); |
- const GURL url4("http://www.google.com/url4/"); |
- |
- const ContextID context_id = reinterpret_cast<ContextID>(1); |
- |
- // Add two pages. |
- history_service_->AddPage( |
- url0, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_TYPED, |
- history::SOURCE_BROWSED, false); |
- history_service_->AddPage( |
- url1, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_TYPED, |
- history::SOURCE_BROWSED, false); |
- history_service_->QueryMostVisitedURLs( |
- 20, |
- 90, |
- base::Bind(&HistoryTest::OnMostVisitedURLsAvailable, |
- base::Unretained(this)), |
- &tracker_); |
- base::MessageLoop::current()->Run(); |
- |
- EXPECT_EQ(2U, most_visited_urls_.size()); |
- EXPECT_EQ(url0, most_visited_urls_[0].url); |
- EXPECT_EQ(url1, most_visited_urls_[1].url); |
- |
- // Add another page. |
- history_service_->AddPage( |
- url2, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_TYPED, |
- history::SOURCE_BROWSED, false); |
- history_service_->QueryMostVisitedURLs( |
- 20, |
- 90, |
- base::Bind(&HistoryTest::OnMostVisitedURLsAvailable, |
- base::Unretained(this)), |
- &tracker_); |
- base::MessageLoop::current()->Run(); |
- |
- EXPECT_EQ(3U, most_visited_urls_.size()); |
- EXPECT_EQ(url0, most_visited_urls_[0].url); |
- EXPECT_EQ(url1, most_visited_urls_[1].url); |
- EXPECT_EQ(url2, most_visited_urls_[2].url); |
- |
- // Revisit url2, making it the top URL. |
- history_service_->AddPage( |
- url2, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_TYPED, |
- history::SOURCE_BROWSED, false); |
- history_service_->QueryMostVisitedURLs( |
- 20, |
- 90, |
- base::Bind(&HistoryTest::OnMostVisitedURLsAvailable, |
- base::Unretained(this)), |
- &tracker_); |
- base::MessageLoop::current()->Run(); |
- |
- EXPECT_EQ(3U, most_visited_urls_.size()); |
- EXPECT_EQ(url2, most_visited_urls_[0].url); |
- EXPECT_EQ(url0, most_visited_urls_[1].url); |
- EXPECT_EQ(url1, most_visited_urls_[2].url); |
- |
- // Revisit url1, making it the top URL. |
- history_service_->AddPage( |
- url1, base::Time::Now(), context_id, 0, GURL(), |
- history::RedirectList(), ui::PAGE_TRANSITION_TYPED, |
- history::SOURCE_BROWSED, false); |
- history_service_->QueryMostVisitedURLs( |
- 20, |
- 90, |
- base::Bind(&HistoryTest::OnMostVisitedURLsAvailable, |
- base::Unretained(this)), |
- &tracker_); |
- base::MessageLoop::current()->Run(); |
- |
- EXPECT_EQ(3U, most_visited_urls_.size()); |
- EXPECT_EQ(url1, most_visited_urls_[0].url); |
- EXPECT_EQ(url2, most_visited_urls_[1].url); |
- EXPECT_EQ(url0, most_visited_urls_[2].url); |
- |
- // Redirects |
- history::RedirectList redirects; |
- redirects.push_back(url3); |
- redirects.push_back(url4); |
- |
- // Visit url4 using redirects. |
- history_service_->AddPage( |
- url4, base::Time::Now(), context_id, 0, GURL(), |
- redirects, ui::PAGE_TRANSITION_TYPED, |
- history::SOURCE_BROWSED, false); |
- history_service_->QueryMostVisitedURLs( |
- 20, |
- 90, |
- base::Bind(&HistoryTest::OnMostVisitedURLsAvailable, |
- base::Unretained(this)), |
- &tracker_); |
- base::MessageLoop::current()->Run(); |
- |
- EXPECT_EQ(4U, most_visited_urls_.size()); |
- EXPECT_EQ(url1, most_visited_urls_[0].url); |
- EXPECT_EQ(url2, most_visited_urls_[1].url); |
- EXPECT_EQ(url0, most_visited_urls_[2].url); |
- EXPECT_EQ(url3, most_visited_urls_[3].url); |
- EXPECT_EQ(2U, most_visited_urls_[3].redirects.size()); |
-} |
- |
-namespace { |
- |
-// A HistoryDBTask implementation. Each time RunOnDBThread is invoked |
-// invoke_count is increment. When invoked kWantInvokeCount times, true is |
-// returned from RunOnDBThread which should stop RunOnDBThread from being |
-// invoked again. When DoneRunOnMainThread is invoked, done_invoked is set to |
-// true. |
-class HistoryDBTaskImpl : public HistoryDBTask { |
- public: |
- static const int kWantInvokeCount; |
- |
- HistoryDBTaskImpl(int* invoke_count, bool* done_invoked) |
- : invoke_count_(invoke_count), done_invoked_(done_invoked) {} |
- |
- bool RunOnDBThread(HistoryBackend* backend, HistoryDatabase* db) override { |
- return (++*invoke_count_ == kWantInvokeCount); |
- } |
- |
- void DoneRunOnMainThread() override { |
- *done_invoked_ = true; |
- base::MessageLoop::current()->Quit(); |
- } |
- |
- int* invoke_count_; |
- bool* done_invoked_; |
- |
- private: |
- ~HistoryDBTaskImpl() override {} |
- |
- DISALLOW_COPY_AND_ASSIGN(HistoryDBTaskImpl); |
-}; |
- |
-// static |
-const int HistoryDBTaskImpl::kWantInvokeCount = 2; |
- |
-} // namespace |
- |
-TEST_F(HistoryTest, HistoryDBTask) { |
- ASSERT_TRUE(history_service_.get()); |
- base::CancelableTaskTracker task_tracker; |
- int invoke_count = 0; |
- bool done_invoked = false; |
- history_service_->ScheduleDBTask( |
- scoped_ptr<history::HistoryDBTask>( |
- new HistoryDBTaskImpl(&invoke_count, &done_invoked)), |
- &task_tracker); |
- // Run the message loop. When HistoryDBTaskImpl::DoneRunOnMainThread runs, |
- // it will stop the message loop. If the test hangs here, it means |
- // DoneRunOnMainThread isn't being invoked correctly. |
- base::MessageLoop::current()->Run(); |
- CleanupHistoryService(); |
- // WARNING: history has now been deleted. |
- history_service_.reset(); |
- ASSERT_EQ(HistoryDBTaskImpl::kWantInvokeCount, invoke_count); |
- ASSERT_TRUE(done_invoked); |
-} |
- |
-TEST_F(HistoryTest, HistoryDBTaskCanceled) { |
- ASSERT_TRUE(history_service_.get()); |
- base::CancelableTaskTracker task_tracker; |
- int invoke_count = 0; |
- bool done_invoked = false; |
- history_service_->ScheduleDBTask( |
- scoped_ptr<history::HistoryDBTask>( |
- new HistoryDBTaskImpl(&invoke_count, &done_invoked)), |
- &task_tracker); |
- task_tracker.TryCancelAll(); |
- CleanupHistoryService(); |
- // WARNING: history has now been deleted. |
- history_service_.reset(); |
- ASSERT_FALSE(done_invoked); |
-} |
- |
-// Create a local delete directive and process it while sync is |
-// online, and then when offline. The delete directive should be sent to sync, |
-// no error should be returned for the first time, and an error should be |
-// returned for the second time. |
-TEST_F(HistoryTest, ProcessLocalDeleteDirectiveSyncOnline) { |
- ASSERT_TRUE(history_service_.get()); |
- |
- const GURL test_url("http://www.google.com/"); |
- for (int64 i = 1; i <= 10; ++i) { |
- base::Time t = |
- base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(i); |
- history_service_->AddPage(test_url, t, NULL, 0, GURL(), |
- history::RedirectList(), |
- ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- } |
- |
- sync_pb::HistoryDeleteDirectiveSpecifics delete_directive; |
- sync_pb::GlobalIdDirective* global_id_directive = |
- delete_directive.mutable_global_id_directive(); |
- global_id_directive->add_global_id( |
- (base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(1)) |
- .ToInternalValue()); |
- |
- syncer::FakeSyncChangeProcessor change_processor; |
- |
- EXPECT_FALSE( |
- history_service_->MergeDataAndStartSyncing( |
- syncer::HISTORY_DELETE_DIRECTIVES, |
- syncer::SyncDataList(), |
- scoped_ptr<syncer::SyncChangeProcessor>( |
- new syncer::SyncChangeProcessorWrapperForTest( |
- &change_processor)), |
- scoped_ptr<syncer::SyncErrorFactory>()) |
- .error() |
- .IsSet()); |
- |
- syncer::SyncError err = |
- history_service_->ProcessLocalDeleteDirective(delete_directive); |
- EXPECT_FALSE(err.IsSet()); |
- EXPECT_EQ(1u, change_processor.changes().size()); |
- |
- history_service_->StopSyncing(syncer::HISTORY_DELETE_DIRECTIVES); |
- err = history_service_->ProcessLocalDeleteDirective(delete_directive); |
- EXPECT_TRUE(err.IsSet()); |
- EXPECT_EQ(1u, change_processor.changes().size()); |
-} |
- |
-// Closure function that runs periodically to check result of delete directive |
-// processing. Stop when timeout or processing ends indicated by the creation |
-// of sync changes. |
-void CheckDirectiveProcessingResult( |
- Time timeout, |
- const syncer::FakeSyncChangeProcessor* change_processor, |
- uint32 num_changes) { |
- if (base::Time::Now() > timeout || |
- change_processor->changes().size() >= num_changes) { |
- return; |
- } |
- |
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100)); |
- base::MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&CheckDirectiveProcessingResult, timeout, |
- change_processor, num_changes)); |
-} |
- |
-// Create a delete directive for a few specific history entries, |
-// including ones that don't exist. The expected entries should be |
-// deleted. |
-TEST_F(HistoryTest, ProcessGlobalIdDeleteDirective) { |
- ASSERT_TRUE(history_service_.get()); |
- const GURL test_url("http://www.google.com/"); |
- for (int64 i = 1; i <= 20; i++) { |
- base::Time t = |
- base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(i); |
- history_service_->AddPage(test_url, t, NULL, 0, GURL(), |
- history::RedirectList(), |
- ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- } |
- |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- EXPECT_EQ(20, query_url_row_.visit_count()); |
- |
- syncer::SyncDataList directives; |
- // 1st directive. |
- sync_pb::EntitySpecifics entity_specs; |
- sync_pb::GlobalIdDirective* global_id_directive = |
- entity_specs.mutable_history_delete_directive() |
- ->mutable_global_id_directive(); |
- global_id_directive->add_global_id( |
- (base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(6)) |
- .ToInternalValue()); |
- global_id_directive->set_start_time_usec(3); |
- global_id_directive->set_end_time_usec(10); |
- directives.push_back(syncer::SyncData::CreateRemoteData( |
- 1, |
- entity_specs, |
- base::Time(), |
- syncer::AttachmentIdList(), |
- syncer::AttachmentServiceProxyForTest::Create())); |
- |
- // 2nd directive. |
- global_id_directive->Clear(); |
- global_id_directive->add_global_id( |
- (base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(17)) |
- .ToInternalValue()); |
- global_id_directive->set_start_time_usec(13); |
- global_id_directive->set_end_time_usec(19); |
- directives.push_back(syncer::SyncData::CreateRemoteData( |
- 2, |
- entity_specs, |
- base::Time(), |
- syncer::AttachmentIdList(), |
- syncer::AttachmentServiceProxyForTest::Create())); |
- |
- syncer::FakeSyncChangeProcessor change_processor; |
- EXPECT_FALSE( |
- history_service_->MergeDataAndStartSyncing( |
- syncer::HISTORY_DELETE_DIRECTIVES, |
- directives, |
- scoped_ptr<syncer::SyncChangeProcessor>( |
- new syncer::SyncChangeProcessorWrapperForTest( |
- &change_processor)), |
- scoped_ptr<syncer::SyncErrorFactory>()) |
- .error() |
- .IsSet()); |
- |
- // Inject a task to check status and keep message loop filled before directive |
- // processing finishes. |
- base::MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&CheckDirectiveProcessingResult, |
- base::Time::Now() + base::TimeDelta::FromSeconds(10), |
- &change_processor, 2)); |
- base::MessageLoop::current()->RunUntilIdle(); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- ASSERT_EQ(5, query_url_row_.visit_count()); |
- EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(1), |
- query_url_visits_[0].visit_time); |
- EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(2), |
- query_url_visits_[1].visit_time); |
- EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(11), |
- query_url_visits_[2].visit_time); |
- EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(12), |
- query_url_visits_[3].visit_time); |
- EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(20), |
- query_url_visits_[4].visit_time); |
- |
- // Expect two sync changes for deleting processed directives. |
- const syncer::SyncChangeList& sync_changes = change_processor.changes(); |
- ASSERT_EQ(2u, sync_changes.size()); |
- EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, sync_changes[0].change_type()); |
- EXPECT_EQ(1, syncer::SyncDataRemote(sync_changes[0].sync_data()).GetId()); |
- EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, sync_changes[1].change_type()); |
- EXPECT_EQ(2, syncer::SyncDataRemote(sync_changes[1].sync_data()).GetId()); |
-} |
- |
-// Create delete directives for time ranges. The expected entries should be |
-// deleted. |
-TEST_F(HistoryTest, ProcessTimeRangeDeleteDirective) { |
- ASSERT_TRUE(history_service_.get()); |
- const GURL test_url("http://www.google.com/"); |
- for (int64 i = 1; i <= 10; ++i) { |
- base::Time t = |
- base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(i); |
- history_service_->AddPage(test_url, t, NULL, 0, GURL(), |
- history::RedirectList(), |
- ui::PAGE_TRANSITION_LINK, |
- history::SOURCE_BROWSED, false); |
- } |
- |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- EXPECT_EQ(10, query_url_row_.visit_count()); |
- |
- syncer::SyncDataList directives; |
- // 1st directive. |
- sync_pb::EntitySpecifics entity_specs; |
- sync_pb::TimeRangeDirective* time_range_directive = |
- entity_specs.mutable_history_delete_directive() |
- ->mutable_time_range_directive(); |
- time_range_directive->set_start_time_usec(2); |
- time_range_directive->set_end_time_usec(5); |
- directives.push_back(syncer::SyncData::CreateRemoteData( |
- 1, |
- entity_specs, |
- base::Time(), |
- syncer::AttachmentIdList(), |
- syncer::AttachmentServiceProxyForTest::Create())); |
- |
- // 2nd directive. |
- time_range_directive->Clear(); |
- time_range_directive->set_start_time_usec(8); |
- time_range_directive->set_end_time_usec(10); |
- directives.push_back(syncer::SyncData::CreateRemoteData( |
- 2, |
- entity_specs, |
- base::Time(), |
- syncer::AttachmentIdList(), |
- syncer::AttachmentServiceProxyForTest::Create())); |
- |
- syncer::FakeSyncChangeProcessor change_processor; |
- EXPECT_FALSE( |
- history_service_->MergeDataAndStartSyncing( |
- syncer::HISTORY_DELETE_DIRECTIVES, |
- directives, |
- scoped_ptr<syncer::SyncChangeProcessor>( |
- new syncer::SyncChangeProcessorWrapperForTest( |
- &change_processor)), |
- scoped_ptr<syncer::SyncErrorFactory>()) |
- .error() |
- .IsSet()); |
- |
- // Inject a task to check status and keep message loop filled before |
- // directive processing finishes. |
- base::MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&CheckDirectiveProcessingResult, |
- base::Time::Now() + base::TimeDelta::FromSeconds(10), |
- &change_processor, 2)); |
- base::MessageLoop::current()->RunUntilIdle(); |
- EXPECT_TRUE(QueryURL(history_service_.get(), test_url)); |
- ASSERT_EQ(3, query_url_row_.visit_count()); |
- EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(1), |
- query_url_visits_[0].visit_time); |
- EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(6), |
- query_url_visits_[1].visit_time); |
- EXPECT_EQ(base::Time::UnixEpoch() + base::TimeDelta::FromMicroseconds(7), |
- query_url_visits_[2].visit_time); |
- |
- // Expect two sync changes for deleting processed directives. |
- const syncer::SyncChangeList& sync_changes = change_processor.changes(); |
- ASSERT_EQ(2u, sync_changes.size()); |
- EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, sync_changes[0].change_type()); |
- EXPECT_EQ(1, syncer::SyncDataRemote(sync_changes[0].sync_data()).GetId()); |
- EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, sync_changes[1].change_type()); |
- EXPECT_EQ(2, syncer::SyncDataRemote(sync_changes[1].sync_data()).GetId()); |
-} |
- |
-TEST_F(HistoryBackendDBTest, MigratePresentations) { |
- // Create the db we want. Use 22 since segments didn't change in that time |
- // frame. |
- ASSERT_NO_FATAL_FAILURE(CreateDBVersion(22)); |
- |
- const SegmentID segment_id = 2; |
- const URLID url_id = 3; |
- const GURL url("http://www.foo.com"); |
- const std::string url_name(VisitSegmentDatabase::ComputeSegmentName(url)); |
- const base::string16 title(base::ASCIIToUTF16("Title1")); |
- const Time segment_time(Time::Now()); |
- |
- { |
- // Re-open the db for manual manipulation. |
- sql::Connection db; |
- ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); |
- |
- // Add an entry to urls. |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO urls " |
- "(id, url, title, last_visit_time) VALUES " |
- "(?, ?, ?, ?)")); |
- s.BindInt64(0, url_id); |
- s.BindString(1, url.spec()); |
- s.BindString16(2, title); |
- s.BindInt64(3, segment_time.ToInternalValue()); |
- ASSERT_TRUE(s.Run()); |
- } |
- |
- // Add an entry to segments. |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO segments " |
- "(id, name, url_id, pres_index) VALUES " |
- "(?, ?, ?, ?)")); |
- s.BindInt64(0, segment_id); |
- s.BindString(1, url_name); |
- s.BindInt64(2, url_id); |
- s.BindInt(3, 4); // pres_index |
- ASSERT_TRUE(s.Run()); |
- } |
- |
- // And one to segment_usage. |
- { |
- sql::Statement s(db.GetUniqueStatement( |
- "INSERT INTO segment_usage " |
- "(id, segment_id, time_slot, visit_count) VALUES " |
- "(?, ?, ?, ?)")); |
- s.BindInt64(0, 4); // id. |
- s.BindInt64(1, segment_id); |
- s.BindInt64(2, segment_time.ToInternalValue()); |
- s.BindInt(3, 5); // visit count. |
- ASSERT_TRUE(s.Run()); |
- } |
- } |
- |
- // Re-open the db, triggering migration. |
- CreateBackendAndDatabase(); |
- |
- std::vector<PageUsageData*> results; |
- db_->QuerySegmentUsage(segment_time, 10, &results); |
- ASSERT_EQ(1u, results.size()); |
- EXPECT_EQ(url, results[0]->GetURL()); |
- EXPECT_EQ(segment_id, results[0]->GetID()); |
- EXPECT_EQ(title, results[0]->GetTitle()); |
- STLDeleteElements(&results); |
-} |
- |
-} // namespace history |