blob: fdb4afbfecaac08174c3d467758235a8cf218327 [file] [log] [blame]
// Copyright 2018 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 "chrome/chrome_cleaner/test/test_pup_data.h"
#include "base/logging.h"
#include "chrome/chrome_cleaner/proto/shared_pup_enums.pb.h"
#include "chrome/chrome_cleaner/pup_data/uws_catalog.h"
namespace chrome_cleaner {
namespace {
const PUPData::UwSSignature kEmptyPUP = {PUPData::kInvalidUwSId,
PUPData::FLAGS_NONE,
nullptr,
0,
kNoDisk,
kNoRegistry,
kNoCustomMatcher};
} // namespace
TestPUPData* TestPUPData::current_test_ = nullptr;
TestPUPData* TestPUPData::previous_test_ = nullptr;
SimpleTestPUP::SimpleTestPUP() : PUPData::PUP(&kEmptyPUP) {}
TestPUPData::TestPUPData() : previous_catalogs_(PUPData::GetUwSCatalogs()) {
// Make sure tests don't step on each other.
previous_test_ = current_test_;
current_test_ = this;
// Assume there will be no additional UwSCatalogs used during the test. If
// not, the caller can call Reset again with an explicit list of catalogs.
Reset({});
}
TestPUPData::~TestPUPData() {
// Reset the global PUP data to the non-test version.
PUPData::InitializePUPData(previous_catalogs_);
CHECK_EQ(this, current_test_);
current_test_ = previous_test_;
}
void TestPUPData::Reset(const PUPData::UwSCatalogs& additional_uws_catalogs) {
CHECK_EQ(this, current_test_);
cpp_pup_footprints_.clear();
mirror_pup_footprints_.clear();
PUPData::UwSCatalogs uws_catalogs = additional_uws_catalogs;
uws_catalogs.push_back(this);
PUPData::InitializePUPData(uws_catalogs);
}
void TestPUPData::AddPUP(UwSId pup_id,
PUPData::Flags flags,
const char* name,
size_t max_files_to_remove) {
CHECK_EQ(this, current_test_);
size_t mirror_index = EnsurePUP(pup_id);
mirror_pup_footprints_[mirror_index].flags = flags;
mirror_pup_footprints_[mirror_index].max_files_to_remove =
max_files_to_remove;
// We keep a C++ version of the strings to control lifespan of the pointer
// put in the C array.
if (name) {
cpp_pup_footprints_[pup_id].name = name;
mirror_pup_footprints_[mirror_index].name =
cpp_pup_footprints_[pup_id].name.c_str();
} else {
cpp_pup_footprints_[pup_id].name.clear();
mirror_pup_footprints_[mirror_index].name = nullptr;
}
}
void TestPUPData::AddDiskFootprint(UwSId pup_id,
int csidl,
const wchar_t* path,
PUPData::DiskMatchRule rule) {
CHECK_EQ(this, current_test_);
size_t mirror_index = EnsurePUP(pup_id);
PUPData::StaticDiskFootprint footprint;
footprint.csidl = csidl;
footprint.path = path;
footprint.rule = rule;
// Insert before the null terminating entry.
cpp_pup_footprints_[pup_id].disk_footprints.insert(
cpp_pup_footprints_[pup_id].disk_footprints.end() - 1, footprint);
mirror_pup_footprints_[mirror_index].disk_footprints =
cpp_pup_footprints_[pup_id].disk_footprints.data();
}
void TestPUPData::AddRegistryFootprint(UwSId pup_id,
RegistryRoot registry_root,
const wchar_t* key_path,
const wchar_t* value_name,
const wchar_t* value_substring,
RegistryMatchRule rule) {
CHECK_EQ(this, current_test_);
size_t mirror_index = EnsurePUP(pup_id);
// Sanity checks to avoid making silly mistakes in unittests.
CHECK(key_path);
if (rule == REGISTRY_VALUE_MATCH_KEY) {
CHECK(!value_name);
CHECK(!value_substring);
} else if (rule == REGISTRY_VALUE_MATCH_VALUE_NAME) {
CHECK(value_name);
CHECK(!value_substring);
} else {
CHECK(value_name);
CHECK(value_substring);
}
PUPData::StaticRegistryFootprint footprint;
footprint.registry_root = registry_root;
footprint.key_path = key_path;
footprint.value_name = value_name;
footprint.value_substring = value_substring;
footprint.rule = rule;
// Insert before the null terminating entry.
cpp_pup_footprints_[pup_id].registry_footprints.insert(
cpp_pup_footprints_[pup_id].registry_footprints.end() - 1, footprint);
mirror_pup_footprints_[mirror_index].registry_footprints =
cpp_pup_footprints_[pup_id].registry_footprints.data();
}
TestPUPData::CPPPUP::CPPPUP() = default;
TestPUPData::CPPPUP::~CPPPUP() = default;
void TestPUPData::AddCustomMatcher(UwSId pup_id,
PUPData::CustomMatcher matcher) {
CHECK_EQ(this, current_test_);
size_t mirror_index = EnsurePUP(pup_id);
// Insert before the null terminating entry.
cpp_pup_footprints_[pup_id].custom_matchers.insert(
cpp_pup_footprints_[pup_id].custom_matchers.end() - 1, matcher);
mirror_pup_footprints_[mirror_index].custom_matchers =
cpp_pup_footprints_[pup_id].custom_matchers.data();
}
size_t TestPUPData::EnsurePUP(UwSId pup_id) {
if (mirror_pup_footprints_.empty()) {
// If we are adding the first entry, we need an initial one for the null
// terminating entry.
mirror_pup_footprints_.push_back(kEmptyPUP);
} else {
for (size_t i = 0; i < mirror_pup_footprints_.size(); ++i) {
if (mirror_pup_footprints_[i].id == pup_id)
return i;
}
}
// Make sure the last entry is a null terminating entry.
size_t index = mirror_pup_footprints_.size() - 1;
DCHECK_EQ(PUPData::kInvalidUwSId, mirror_pup_footprints_[index].id);
// Set up the new value to be inserted before the null terminating entry.
PUPData::UwSSignature new_pup;
new_pup.id = pup_id;
new_pup.flags = PUPData::FLAGS_ACTION_REMOVE;
// Initialize all C++ arrays with a null terminating entry, and use their data
// pointers in the C array mirror.
cpp_pup_footprints_[pup_id].disk_footprints.push_back({});
new_pup.disk_footprints = cpp_pup_footprints_[pup_id].disk_footprints.data();
cpp_pup_footprints_[pup_id].registry_footprints.push_back({});
new_pup.registry_footprints =
cpp_pup_footprints_[pup_id].registry_footprints.data();
cpp_pup_footprints_[pup_id].custom_matchers.push_back({});
new_pup.custom_matchers = cpp_pup_footprints_[pup_id].custom_matchers.data();
mirror_pup_footprints_.insert(mirror_pup_footprints_.end() - 1, new_pup);
// Add any newly-created UwS to the cache. Don't touch anything that already
// existed, since this is often called during tests that have pointers to
// that UwS.
PUPData::UpdateCachedUwSForTesting();
return index;
}
std::vector<UwSId> TestPUPData::GetUwSIds() const {
std::vector<UwSId> ids;
ids.reserve(mirror_pup_footprints_.size());
for (const PUPData::UwSSignature& signature : mirror_pup_footprints_) {
if (signature.id != PUPData::kInvalidUwSId)
ids.push_back(signature.id);
}
return ids;
}
bool TestPUPData::IsEnabledForScanning(UwSId id) const {
DCHECK_NE(id, PUPData::kInvalidUwSId);
for (const PUPData::UwSSignature& signature : mirror_pup_footprints_) {
if (signature.id == id)
return true;
}
return false;
}
bool TestPUPData::IsEnabledForCleaning(UwSId id) const {
DCHECK_NE(id, PUPData::kInvalidUwSId);
for (const PUPData::UwSSignature& signature : mirror_pup_footprints_) {
if (signature.id == id && signature.flags & PUPData::FLAGS_ACTION_REMOVE)
return true;
}
return false;
}
std::unique_ptr<PUPData::PUP> TestPUPData::CreatePUPForId(UwSId id) const {
DCHECK_NE(id, PUPData::kInvalidUwSId);
for (const PUPData::UwSSignature& signature : mirror_pup_footprints_) {
if (signature.id == id)
return std::make_unique<PUPData::PUP>(&signature);
}
NOTREACHED() << id << " not in TestPUPData";
return nullptr;
}
} // namespace chrome_cleaner