blob: cc9f2cfaadd30f276ffe72435097994aadff3f8a [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 "components/subresource_filter/tools/indexing_tool.h"
#include <memory>
#include <string>
#include <vector>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "components/subresource_filter/core/common/indexed_ruleset.h"
#include "components/subresource_filter/core/common/test_ruleset_creator.h"
#include "components/subresource_filter/core/common/test_ruleset_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace subresource_filter {
namespace proto = url_pattern_index::proto;
namespace {
std::vector<uint8_t> ReadFileContents(const base::FilePath& file_path) {
base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
size_t length = base::checked_cast<size_t>(file.GetLength());
std::vector<uint8_t> contents(length);
static_assert(sizeof(uint8_t) == sizeof(char), "Expected char = byte.");
file.Read(0, reinterpret_cast<char*>(contents.data()),
base::checked_cast<int>(length));
return contents;
}
class IndexingToolTest : public ::testing::Test {
public:
IndexingToolTest() {}
protected:
void SetUp() override { ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); }
base::FilePath GetUniquePath() {
base::FilePath path = scoped_temp_dir_.GetPath().AppendASCII(
base::NumberToString(file_count_++));
return path;
}
void CreateSimpleRuleset() {
std::vector<proto::UrlRule> rules;
rules.push_back(testing::CreateSuffixRule("disallowed1.png"));
rules.push_back(testing::CreateSuffixRule("disallowed2.png"));
rules.push_back(testing::CreateSuffixRule("disallowed3.png"));
rules.push_back(
testing::CreateWhitelistSuffixRule("whitelist/disallowed1.png"));
rules.push_back(
testing::CreateWhitelistSuffixRule("whitelist/disallowed2.png"));
ASSERT_NO_FATAL_FAILURE(test_ruleset_creator_.CreateRulesetWithRules(
rules, &test_ruleset_pair_));
}
void WriteUnindexedRulesetToFile(const base::FilePath& path) {
// Write the test unindexed data to a file.
const std::vector<uint8_t>& unindexed_data =
test_ruleset_pair_.unindexed.contents;
base::WriteFile(path, reinterpret_cast<const char*>(unindexed_data.data()),
base::checked_cast<int>(unindexed_data.size()));
}
int file_count_ = 0;
base::ScopedTempDir scoped_temp_dir_;
testing::TestRulesetCreator test_ruleset_creator_;
testing::TestRulesetPair test_ruleset_pair_;
DISALLOW_COPY_AND_ASSIGN(IndexingToolTest);
};
TEST_F(IndexingToolTest, UnindexedFileDoesNotExist) {
// There is no file at the unindexed position, so it should return false.
EXPECT_FALSE(IndexAndWriteRuleset(GetUniquePath(), GetUniquePath()));
}
TEST_F(IndexingToolTest, IndexedDirectoryDoesNotExist) {
// Create a valid unindexed file.
base::FilePath unindexed_path = GetUniquePath();
CreateSimpleRuleset();
WriteUnindexedRulesetToFile(unindexed_path);
// The indexed path is in a non-existant directory.
base::FilePath indexed_path =
scoped_temp_dir_.GetPath().AppendASCII("foo/bar");
// This should fail because the directory for indexed_path doesn't exist.
EXPECT_FALSE(IndexAndWriteRuleset(unindexed_path, indexed_path));
}
TEST_F(IndexingToolTest, VerifyOutput) {
base::FilePath unindexed_path = GetUniquePath();
base::FilePath indexed_path = GetUniquePath();
CreateSimpleRuleset();
WriteUnindexedRulesetToFile(unindexed_path);
// Convert the unindexed data to indexed data, and write the result to
// indexed_path.
EXPECT_TRUE(IndexAndWriteRuleset(unindexed_path, indexed_path));
// Verify that the output equals the test indexed data.
std::vector<uint8_t> indexed_data = ReadFileContents(indexed_path);
EXPECT_EQ(test_ruleset_pair_.indexed.contents, indexed_data);
}
TEST_F(IndexingToolTest, VersionMetadata) {
base::FilePath unindexed_path = GetUniquePath();
base::FilePath indexed_path = GetUniquePath();
base::FilePath version_path = GetUniquePath();
CreateSimpleRuleset();
WriteUnindexedRulesetToFile(unindexed_path);
// Convert the unindexed data to indexed data, and write the result to
// indexed_path.
int checksum = 0;
EXPECT_TRUE(IndexAndWriteRuleset(unindexed_path, indexed_path, &checksum));
EXPECT_NE(0, checksum);
WriteVersionMetadata(version_path, "1.2.3", checksum);
std::string version_json;
EXPECT_TRUE(base::ReadFileToString(version_path, &version_json));
std::unique_ptr<base::DictionaryValue> json = base::DictionaryValue::From(
base::JSONReader::ReadDeprecated(version_json));
std::string actual_content =
json->FindPath({"subresource_filter", "ruleset_version", "content"})
->GetString();
EXPECT_EQ("1.2.3", actual_content);
int actual_format =
json->FindPath({"subresource_filter", "ruleset_version", "format"})
->GetInt();
EXPECT_EQ(RulesetIndexer::kIndexedFormatVersion, actual_format);
int actual_checksum =
json->FindPath({"subresource_filter", "ruleset_version", "checksum"})
->GetInt();
EXPECT_EQ(checksum, actual_checksum);
}
} // namespace
} // namespace subresource_filter