blob: 4d359de34e1303faed7300c14b966e451820461b [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 "components/subresource_filter/core/common/test_ruleset_creator.h"
#include <memory>
#include <string>
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "components/subresource_filter/core/common/indexed_ruleset.h"
#include "components/subresource_filter/core/common/test_ruleset_utils.h"
#include "components/subresource_filter/core/common/unindexed_ruleset.h"
#include "components/url_pattern_index/proto/rules.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
namespace subresource_filter {
namespace proto = url_pattern_index::proto;
namespace {
// The methods below assume that char and uint8_t are interchangeable.
static_assert(CHAR_BIT == 8, "Assumed char was 8 bits.");
void WriteRulesetContents(const std::vector<uint8_t>& contents,
base::FilePath path) {
base::ScopedAllowBlockingForTesting allow_blocking;
int ruleset_size_as_int = base::checked_cast<int>(contents.size());
int num_bytes_written =
base::WriteFile(path, reinterpret_cast<const char*>(contents.data()),
ruleset_size_as_int);
ASSERT_EQ(ruleset_size_as_int, num_bytes_written);
}
std::vector<uint8_t> SerializeUnindexedRulesetWithMultipleRules(
const std::vector<proto::UrlRule>& rules) {
std::string ruleset_contents;
google::protobuf::io::StringOutputStream output(&ruleset_contents);
UnindexedRulesetWriter ruleset_writer(&output);
for (const auto& rule : rules)
ruleset_writer.AddUrlRule(rule);
ruleset_writer.Finish();
auto* data = reinterpret_cast<const uint8_t*>(ruleset_contents.data());
return std::vector<uint8_t>(data, data + ruleset_contents.size());
}
std::vector<uint8_t> SerializeIndexedRulesetWithMultipleRules(
const std::vector<proto::UrlRule>& rules) {
RulesetIndexer indexer;
for (const auto& rule : rules)
EXPECT_TRUE(indexer.AddUrlRule(rule));
indexer.Finish();
return std::vector<uint8_t>(indexer.data(), indexer.data() + indexer.size());
}
} // namespace
namespace testing {
// TestRuleset -----------------------------------------------------------------
TestRuleset::TestRuleset() = default;
TestRuleset::~TestRuleset() = default;
// static
base::File TestRuleset::Open(const TestRuleset& ruleset) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::File file;
file.Initialize(ruleset.path, base::File::FLAG_OPEN | base::File::FLAG_READ |
base::File::FLAG_SHARE_DELETE);
return file;
}
// static
void TestRuleset::CorruptByTruncating(const TestRuleset& ruleset,
size_t tail_size) {
ASSERT_GT(tail_size, 0u);
ASSERT_FALSE(ruleset.contents.empty());
std::vector<uint8_t> new_contents = ruleset.contents;
const size_t new_size =
tail_size < new_contents.size() ? new_contents.size() - tail_size : 0;
new_contents.resize(new_size);
WriteRulesetContents(new_contents, ruleset.path);
}
// static
void TestRuleset::CorruptByFilling(const TestRuleset& ruleset,
size_t from,
size_t to,
uint8_t fill_with) {
ASSERT_LT(from, to);
ASSERT_LE(to, ruleset.contents.size());
std::vector<uint8_t> new_contents = ruleset.contents;
for (size_t i = from; i < to; ++i)
new_contents[i] = fill_with;
WriteRulesetContents(new_contents, ruleset.path);
}
// TestRulesetPair -------------------------------------------------------------
TestRulesetPair::TestRulesetPair() = default;
TestRulesetPair::~TestRulesetPair() = default;
// TestRulesetCreator ----------------------------------------------------------
TestRulesetCreator::TestRulesetCreator()
: scoped_temp_dir_(std::make_unique<base::ScopedTempDir>()) {}
TestRulesetCreator::~TestRulesetCreator() {
base::ScopedAllowBlockingForTesting allow_blocking;
scoped_temp_dir_.reset();
}
void TestRulesetCreator::CreateRulesetToDisallowURLsWithPathSuffix(
base::StringPiece suffix,
TestRulesetPair* test_ruleset_pair) {
DCHECK(test_ruleset_pair);
proto::UrlRule suffix_rule = CreateSuffixRule(suffix);
CreateRulesetWithRules({suffix_rule}, test_ruleset_pair);
}
void TestRulesetCreator::CreateUnindexedRulesetToDisallowURLsWithPathSuffix(
base::StringPiece suffix,
TestRuleset* test_unindexed_ruleset) {
DCHECK(test_unindexed_ruleset);
proto::UrlRule suffix_rule = CreateSuffixRule(suffix);
ASSERT_NO_FATAL_FAILURE(
CreateUnindexedRulesetWithRules({suffix_rule}, test_unindexed_ruleset));
}
void TestRulesetCreator::CreateRulesetToDisallowURLsWithManySuffixes(
base::StringPiece suffix,
int num_of_suffixes,
TestRulesetPair* test_ruleset_pair) {
DCHECK(test_ruleset_pair);
std::vector<proto::UrlRule> rules;
for (int i = 0; i < num_of_suffixes; ++i) {
std::string current_suffix =
suffix.as_string() + '_' + base::NumberToString(i);
rules.push_back(CreateSuffixRule(current_suffix));
}
CreateRulesetWithRules(rules, test_ruleset_pair);
}
void TestRulesetCreator::CreateRulesetWithRules(
const std::vector<proto::UrlRule>& rules,
TestRulesetPair* test_ruleset_pair) {
ASSERT_NO_FATAL_FAILURE(CreateTestRulesetFromContents(
SerializeUnindexedRulesetWithMultipleRules(rules),
&test_ruleset_pair->unindexed));
ASSERT_NO_FATAL_FAILURE(CreateTestRulesetFromContents(
SerializeIndexedRulesetWithMultipleRules(rules),
&test_ruleset_pair->indexed));
}
void TestRulesetCreator::CreateUnindexedRulesetWithRules(
const std::vector<proto::UrlRule>& rules,
TestRuleset* test_unindexed_ruleset) {
ASSERT_NO_FATAL_FAILURE(CreateTestRulesetFromContents(
SerializeUnindexedRulesetWithMultipleRules(rules),
test_unindexed_ruleset));
}
void TestRulesetCreator::GetUniqueTemporaryPath(base::FilePath* path) {
DCHECK(path);
base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(scoped_temp_dir_->IsValid() ||
scoped_temp_dir_->CreateUniqueTempDir());
*path = scoped_temp_dir_->GetPath().AppendASCII(
base::NumberToString(next_unique_file_suffix++));
}
void TestRulesetCreator::CreateTestRulesetFromContents(
std::vector<uint8_t> ruleset_contents,
TestRuleset* ruleset) {
DCHECK(ruleset);
ruleset->contents = std::move(ruleset_contents);
ASSERT_NO_FATAL_FAILURE(GetUniqueTemporaryPath(&ruleset->path));
WriteRulesetContents(ruleset->contents, ruleset->path);
}
} // namespace testing
} // namespace subresource_filter