blob: 31dfe1548585f51d6ba348537a5737f4832dd5e8 [file] [log] [blame]
// Copyright 2016 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.
#include "base/bind.h"
#include "base/debug/leak_annotations.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ptr_util.h"
#include "base/test/test_simple_task_runner.h"
#include "components/safe_browsing_db/v4_database.h"
#include "components/safe_browsing_db/v4_store.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/platform_test.h"
namespace safe_browsing {
class FakeV4Store : public V4Store {
public:
FakeV4Store(const scoped_refptr<base::SequencedTaskRunner>& task_runner,
const base::FilePath& store_path,
const bool reset_succeeds)
: V4Store(
task_runner,
base::FilePath(store_path.value() + FILE_PATH_LITERAL(".fake"))),
reset_succeeds_(reset_succeeds) {}
bool Reset() override { return reset_succeeds_; }
private:
bool reset_succeeds_;
};
// This factory creates a "fake" store. It allows the caller to specify that the
// first store should fail on Reset() i.e. return false. All subsequent stores
// always return true. This is used to test the Reset() method in V4Database.
class FakeV4StoreFactory : public V4StoreFactory {
public:
FakeV4StoreFactory(bool next_store_reset_fails)
: next_store_reset_fails_(next_store_reset_fails) {}
V4Store* CreateV4Store(
const scoped_refptr<base::SequencedTaskRunner>& task_runner,
const base::FilePath& store_path) override {
bool reset_succeeds = !next_store_reset_fails_;
next_store_reset_fails_ = false;
return new FakeV4Store(task_runner, store_path, reset_succeeds);
}
private:
bool next_store_reset_fails_;
};
class SafeBrowsingV4DatabaseTest : public PlatformTest {
public:
SafeBrowsingV4DatabaseTest() : task_runner_(new base::TestSimpleTaskRunner) {}
void SetUp() override {
PlatformTest::SetUp();
// Setup a database in a temporary directory.
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
database_dirname_ =
temp_dir_.path().AppendASCII("SafeBrowsingV4DatabaseTest");
created_but_not_called_back_ = false;
created_and_called_back_ = false;
}
void SetupInfoMapAndExpectedState() {
UpdateListIdentifier update_list_identifier;
update_list_identifier.platform_type = WINDOWS_PLATFORM;
update_list_identifier.threat_entry_type = URL;
update_list_identifier.threat_type = MALWARE_THREAT;
list_info_map_[update_list_identifier] = "win_url_malware";
expected_identifiers_.push_back(update_list_identifier);
expected_store_paths_.push_back(
database_dirname_.AppendASCII("win_url_malware.fake"));
update_list_identifier.platform_type = LINUX_PLATFORM;
update_list_identifier.threat_entry_type = URL;
update_list_identifier.threat_type = MALWARE_THREAT;
list_info_map_[update_list_identifier] = "linux_url_malware";
expected_identifiers_.push_back(update_list_identifier);
expected_store_paths_.push_back(
database_dirname_.AppendASCII("linux_url_malware.fake"));
}
void NewDatabaseReadyWithExpectedStorePathsAndIds(
std::vector<base::FilePath> expected_store_paths,
std::vector<UpdateListIdentifier> expected_identifiers,
bool expected_resets_successfully,
std::unique_ptr<V4Database> v4_database) {
ASSERT_TRUE(v4_database);
ASSERT_TRUE(v4_database->store_map_);
// The following check ensures that the callback was called asynchronously.
EXPECT_TRUE(created_but_not_called_back_);
ASSERT_EQ(expected_store_paths.size(), v4_database->store_map_->size());
ASSERT_EQ(expected_identifiers.size(), v4_database->store_map_->size());
for (size_t i = 0; i < expected_identifiers.size(); i++) {
const auto& expected_identifier = expected_identifiers[i];
const auto& store = (*v4_database->store_map_)[expected_identifier];
ASSERT_TRUE(store);
const auto& expected_store_path = expected_store_paths[i];
EXPECT_EQ(expected_store_path, store->store_path());
}
EXPECT_EQ(expected_resets_successfully, v4_database->ResetDatabase());
EXPECT_FALSE(created_and_called_back_);
created_and_called_back_ = true;
}
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
std::unique_ptr<V4Database> v4_database_;
base::FilePath database_dirname_;
base::ScopedTempDir temp_dir_;
content::TestBrowserThreadBundle thread_bundle_;
bool created_but_not_called_back_;
bool created_and_called_back_;
ListInfoMap list_info_map_;
std::vector<UpdateListIdentifier> expected_identifiers_;
std::vector<base::FilePath> expected_store_paths_;
};
// Test to set up the database with no stores.
TEST_F(SafeBrowsingV4DatabaseTest, TestSetupDatabaseWithNoStores) {
NewDatabaseReadyCallback callback_db_ready = base::Bind(
&SafeBrowsingV4DatabaseTest::NewDatabaseReadyWithExpectedStorePathsAndIds,
base::Unretained(this), expected_store_paths_, expected_identifiers_,
true);
V4Database::Create(task_runner_, database_dirname_, list_info_map_,
callback_db_ready);
created_but_not_called_back_ = true;
task_runner_->RunPendingTasks();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(true, created_and_called_back_);
}
// Test to set up the database with fake stores.
TEST_F(SafeBrowsingV4DatabaseTest, TestSetupDatabaseWithFakeStores) {
SetupInfoMapAndExpectedState();
NewDatabaseReadyCallback callback_db_ready = base::Bind(
&SafeBrowsingV4DatabaseTest::NewDatabaseReadyWithExpectedStorePathsAndIds,
base::Unretained(this), expected_store_paths_, expected_identifiers_,
true);
FakeV4StoreFactory* factory = new FakeV4StoreFactory(false);
ANNOTATE_LEAKING_OBJECT_PTR(factory);
V4Database::RegisterStoreFactoryForTest(factory);
V4Database::Create(task_runner_, database_dirname_, list_info_map_,
callback_db_ready);
created_but_not_called_back_ = true;
task_runner_->RunPendingTasks();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(true, created_and_called_back_);
}
// Test to set up the database with fake stores that fail to reset.
TEST_F(SafeBrowsingV4DatabaseTest, TestSetupDatabaseWithFakeStoresFailsReset) {
SetupInfoMapAndExpectedState();
NewDatabaseReadyCallback callback_db_ready = base::Bind(
&SafeBrowsingV4DatabaseTest::NewDatabaseReadyWithExpectedStorePathsAndIds,
base::Unretained(this), expected_store_paths_, expected_identifiers_,
false);
FakeV4StoreFactory* factory = new FakeV4StoreFactory(true);
ANNOTATE_LEAKING_OBJECT_PTR(factory);
V4Database::RegisterStoreFactoryForTest(factory);
V4Database::Create(task_runner_, database_dirname_, list_info_map_,
callback_db_ready);
created_but_not_called_back_ = true;
task_runner_->RunPendingTasks();
base::MessageLoop::current()->RunUntilIdle();
EXPECT_EQ(true, created_and_called_back_);
}
} // namespace safe_browsing