| Index: components/subresource_filter/core/browser/ruleset_service_unittest.cc
|
| diff --git a/components/subresource_filter/core/browser/ruleset_service_unittest.cc b/components/subresource_filter/core/browser/ruleset_service_unittest.cc
|
| index 2165d7b1194c24a6bdd1470ca36da484800e2d98..2a604c734760644cf86ab584776dfe276d2bd057 100644
|
| --- a/components/subresource_filter/core/browser/ruleset_service_unittest.cc
|
| +++ b/components/subresource_filter/core/browser/ruleset_service_unittest.cc
|
| @@ -7,7 +7,6 @@
|
| #include <stddef.h>
|
| #include <stdint.h>
|
|
|
| -#include <iterator>
|
| #include <memory>
|
| #include <string>
|
| #include <tuple>
|
| @@ -23,6 +22,7 @@
|
| #include "base/threading/thread_task_runner_handle.h"
|
| #include "components/prefs/testing_pref_service.h"
|
| #include "components/subresource_filter/core/browser/ruleset_distributor.h"
|
| +#include "components/subresource_filter/core/common/test_ruleset_creator.h"
|
| #include "testing/gmock/include/gmock/gmock.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| @@ -33,8 +33,8 @@ namespace {
|
| const char kTestContentVersion1[] = "1.2.3.4";
|
| const char kTestContentVersion2[] = "1.2.3.5";
|
|
|
| -const uint8_t kDummyRuleset1[] = {11, 0, 12, 13, 14};
|
| -const uint8_t kDummyRuleset2[] = {21, 0, 22, 23};
|
| +const char kTestDisallowedSuffix1[] = "foo";
|
| +const char kTestDisallowedSuffix2[] = "bar";
|
|
|
| class MockRulesetDistributor : public RulesetDistributor {
|
| public:
|
| @@ -62,13 +62,11 @@ std::vector<uint8_t> ReadFileContents(base::File* file) {
|
| return contents;
|
| }
|
|
|
| -template <typename T, int N>
|
| -std::vector<T> AsVector(const T (&array)[N]) {
|
| - return std::vector<T>(std::begin(array), std::end(array));
|
| -}
|
| -
|
| } // namespace
|
|
|
| +using testing::TestRulesetPair;
|
| +using testing::TestRulesetCreator;
|
| +
|
| class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
|
| public:
|
| SubresourceFilteringRulesetServiceTest()
|
| @@ -78,11 +76,18 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
|
|
|
| protected:
|
| void SetUp() override {
|
| - RulesetVersion::RegisterPrefs(pref_service_.registry());
|
| + IndexedRulesetVersion::RegisterPrefs(pref_service_.registry());
|
|
|
| ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
|
| ResetService(CreateRulesetService());
|
| RunUntilIdle();
|
| +
|
| + ASSERT_NO_FATAL_FAILURE(
|
| + ruleset_creator_.CreateRulesetToDisallowURLsWithPathSuffix(
|
| + kTestDisallowedSuffix1, &test_ruleset_1_));
|
| + ASSERT_NO_FATAL_FAILURE(
|
| + ruleset_creator_.CreateRulesetToDisallowURLsWithPathSuffix(
|
| + kTestDisallowedSuffix2, &test_ruleset_2_));
|
| }
|
|
|
| std::unique_ptr<RulesetService> CreateRulesetService() {
|
| @@ -100,14 +105,18 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
|
| }
|
| }
|
|
|
| - void StoreAndPublishUpdatedRuleset(const std::vector<uint8_t>& ruleset_data,
|
| - const std::string& new_content_version) {
|
| - service()->StoreAndPublishUpdatedRuleset(ruleset_data, new_content_version);
|
| + void IndexAndStoreAndPublishUpdatedRuleset(
|
| + const TestRulesetPair& test_ruleset_pair,
|
| + const std::string& new_content_version) {
|
| + service()->IndexAndStoreAndPublishRulesetVersionIfNeeded(
|
| + test_ruleset_pair.unindexed.path, new_content_version);
|
| }
|
|
|
| - void WritePreexistingRuleset(const RulesetVersion& version,
|
| - const std::vector<uint8_t>& data) {
|
| - RulesetService::WriteRuleset(base_dir(), version, data);
|
| + void WritePreexistingRuleset(const TestRulesetPair& test_ruleset_pair,
|
| + const IndexedRulesetVersion& indexed_version) {
|
| + RulesetService::WriteRuleset(base_dir(), indexed_version,
|
| + test_ruleset_pair.indexed.contents.data(),
|
| + test_ruleset_pair.indexed.contents.size());
|
| }
|
|
|
| void RunUntilIdle() { task_runner_->RunUntilIdle(); }
|
| @@ -130,11 +139,16 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
|
| ASSERT_EQ(-1, file->Write(0, kTest, sizeof(kTest)));
|
| }
|
|
|
| + void AssertNoPendingTasks() { ASSERT_FALSE(task_runner_->HasPendingTask()); }
|
| +
|
| PrefService* prefs() { return &pref_service_; }
|
| RulesetService* service() { return service_.get(); }
|
| MockRulesetDistributor* mock_distributor() { return mock_distributor_; }
|
| +
|
| + const TestRulesetPair& test_ruleset_1() const { return test_ruleset_1_; }
|
| + const TestRulesetPair& test_ruleset_2() const { return test_ruleset_2_; }
|
| base::FilePath base_dir() const {
|
| - return scoped_temp_dir_.path().AppendASCII("Ruleset Base Dir");
|
| + return scoped_temp_dir_.path().AppendASCII("Rules").AppendASCII("Indexed");
|
| }
|
|
|
| private:
|
| @@ -142,6 +156,10 @@ class SubresourceFilteringRulesetServiceTest : public ::testing::Test {
|
| base::ThreadTaskRunnerHandle task_runner_handle_;
|
| TestingPrefServiceSimple pref_service_;
|
|
|
| + TestRulesetCreator ruleset_creator_;
|
| + TestRulesetPair test_ruleset_1_;
|
| + TestRulesetPair test_ruleset_2_;
|
| +
|
| base::ScopedTempDir scoped_temp_dir_;
|
| std::unique_ptr<RulesetService> service_;
|
| MockRulesetDistributor* mock_distributor_; // Weak, owned by |service_|.
|
| @@ -158,9 +176,9 @@ TEST_F(SubresourceFilteringRulesetServiceTest, Startup_NoRulesetNotPublished) {
|
| // but ensure some sane behavior just in case.
|
| TEST_F(SubresourceFilteringRulesetServiceTest,
|
| Startup_MissingRulesetNotPublished) {
|
| - RulesetVersion current_version(kTestContentVersion1,
|
| - RulesetVersion::CurrentFormatVersion());
|
| - // `Forget` to write ruleset data.
|
| + IndexedRulesetVersion current_version(
|
| + kTestContentVersion1, IndexedRulesetVersion::CurrentFormatVersion());
|
| + // "Forget" to write ruleset data.
|
| current_version.SaveToPrefs(prefs());
|
|
|
| ResetService(CreateRulesetService());
|
| @@ -170,11 +188,12 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest,
|
| Startup_LegacyFormatRulesetNotPublished) {
|
| - int legacy_format_version = RulesetVersion::CurrentFormatVersion() - 1;
|
| - RulesetVersion legacy_version(kTestContentVersion1, legacy_format_version);
|
| + int legacy_format_version = IndexedRulesetVersion::CurrentFormatVersion() - 1;
|
| + IndexedRulesetVersion legacy_version(kTestContentVersion1,
|
| + legacy_format_version);
|
| ASSERT_TRUE(legacy_version.IsValid());
|
| legacy_version.SaveToPrefs(prefs());
|
| - WritePreexistingRuleset(legacy_version, AsVector(kDummyRuleset1));
|
| + WritePreexistingRuleset(test_ruleset_1(), legacy_version);
|
|
|
| ResetService(CreateRulesetService());
|
| RunUntilIdle();
|
| @@ -183,45 +202,56 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest,
|
| Startup_ExistingRulesetPublished) {
|
| - const std::vector<uint8_t> dummy_ruleset(AsVector(kDummyRuleset1));
|
| - RulesetVersion current_version(kTestContentVersion1,
|
| - RulesetVersion::CurrentFormatVersion());
|
| + IndexedRulesetVersion current_version(
|
| + kTestContentVersion1, IndexedRulesetVersion::CurrentFormatVersion());
|
| current_version.SaveToPrefs(prefs());
|
| - WritePreexistingRuleset(current_version, AsVector(kDummyRuleset1));
|
| + WritePreexistingRuleset(test_ruleset_1(), current_version);
|
|
|
| ResetService(CreateRulesetService());
|
| RunUntilIdle();
|
|
|
| ASSERT_EQ(1u, mock_distributor()->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &mock_distributor()->published_rulesets()[0], dummy_ruleset));
|
| + &mock_distributor()->published_rulesets()[0],
|
| + test_ruleset_1().indexed.contents));
|
| }
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_Published) {
|
| - const std::vector<uint8_t> dummy_ruleset(AsVector(kDummyRuleset1));
|
| - service()->StoreAndPublishUpdatedRuleset(dummy_ruleset, kTestContentVersion1);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
|
| RunUntilIdle();
|
|
|
| ASSERT_EQ(1u, mock_distributor()->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &mock_distributor()->published_rulesets()[0], dummy_ruleset));
|
| + &mock_distributor()->published_rulesets()[0],
|
| + test_ruleset_1().indexed.contents));
|
|
|
| MockRulesetDistributor* new_distributor = new MockRulesetDistributor;
|
| service()->RegisterDistributor(base::WrapUnique(new_distributor));
|
| ASSERT_EQ(1u, new_distributor->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &new_distributor->published_rulesets()[0], dummy_ruleset));
|
| + &new_distributor->published_rulesets()[0],
|
| + test_ruleset_1().indexed.contents));
|
| +}
|
| +
|
| +TEST_F(SubresourceFilteringRulesetServiceTest,
|
| + NewRulesetWithEmptyVersion_NotPublished) {
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), std::string());
|
| + RunUntilIdle();
|
| +
|
| + ASSERT_EQ(0u, mock_distributor()->published_rulesets().size());
|
| + MockRulesetDistributor* new_distributor = new MockRulesetDistributor;
|
| + service()->RegisterDistributor(base::WrapUnique(new_distributor));
|
| + ASSERT_EQ(0u, new_distributor->published_rulesets().size());
|
| }
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_Persisted) {
|
| - const std::vector<uint8_t> dummy_ruleset(AsVector(kDummyRuleset1));
|
| - service()->StoreAndPublishUpdatedRuleset(dummy_ruleset, kTestContentVersion1);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
|
| RunUntilIdle();
|
|
|
| - RulesetVersion stored_version;
|
| + IndexedRulesetVersion stored_version;
|
| stored_version.ReadFromPrefs(prefs());
|
| EXPECT_EQ(kTestContentVersion1, stored_version.content_version);
|
| - EXPECT_EQ(RulesetVersion::CurrentFormatVersion(),
|
| + EXPECT_EQ(IndexedRulesetVersion::CurrentFormatVersion(),
|
| stored_version.format_version);
|
|
|
| ResetService(CreateRulesetService());
|
| @@ -229,68 +259,100 @@ TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_Persisted) {
|
|
|
| ASSERT_EQ(1u, mock_distributor()->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &mock_distributor()->published_rulesets()[0], dummy_ruleset));
|
| + &mock_distributor()->published_rulesets()[0],
|
| + test_ruleset_1().indexed.contents));
|
| }
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest,
|
| NewRulesetTwice_SecondRulesetPrevails) {
|
| - const std::vector<uint8_t> dummy_ruleset_1(AsVector(kDummyRuleset1));
|
| - const std::vector<uint8_t> dummy_ruleset_2(AsVector(kDummyRuleset2));
|
| -
|
| - StoreAndPublishUpdatedRuleset(dummy_ruleset_1, kTestContentVersion1);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
|
| RunUntilIdle();
|
|
|
| - StoreAndPublishUpdatedRuleset(dummy_ruleset_2, kTestContentVersion2);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(), kTestContentVersion2);
|
| RunUntilIdle();
|
|
|
| // This verifies that the contents from the first version of the ruleset file
|
| // can still be read after it has been deprecated.
|
| ASSERT_EQ(2u, mock_distributor()->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &mock_distributor()->published_rulesets()[0], dummy_ruleset_1));
|
| + &mock_distributor()->published_rulesets()[0],
|
| + test_ruleset_1().indexed.contents));
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &mock_distributor()->published_rulesets()[1], dummy_ruleset_2));
|
| + &mock_distributor()->published_rulesets()[1],
|
| + test_ruleset_2().indexed.contents));
|
|
|
| MockRulesetDistributor* new_distributor = new MockRulesetDistributor;
|
| service()->RegisterDistributor(base::WrapUnique(new_distributor));
|
| ASSERT_EQ(1u, new_distributor->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &new_distributor->published_rulesets()[0], dummy_ruleset_2));
|
| + &new_distributor->published_rulesets()[0],
|
| + test_ruleset_2().indexed.contents));
|
|
|
| - RulesetVersion stored_version;
|
| + IndexedRulesetVersion stored_version;
|
| stored_version.ReadFromPrefs(prefs());
|
| EXPECT_EQ(kTestContentVersion2, stored_version.content_version);
|
| }
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest,
|
| + NewRulesetTwiceWithTheSameVersion_SecondIsIgnored) {
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
|
| + RunUntilIdle();
|
| +
|
| + // For good measure, also violate the requirement that versions should
|
| + // uniquely identify the contents.
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(), kTestContentVersion1);
|
| + ASSERT_NO_FATAL_FAILURE(AssertNoPendingTasks());
|
| +
|
| + ASSERT_EQ(1u, mock_distributor()->published_rulesets().size());
|
| + ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| + &mock_distributor()->published_rulesets()[0],
|
| + test_ruleset_1().indexed.contents));
|
| +
|
| + MockRulesetDistributor* new_distributor = new MockRulesetDistributor;
|
| + service()->RegisterDistributor(base::WrapUnique(new_distributor));
|
| + ASSERT_EQ(1u, new_distributor->published_rulesets().size());
|
| + ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| + &new_distributor->published_rulesets()[0],
|
| + test_ruleset_1().indexed.contents));
|
| +
|
| + IndexedRulesetVersion stored_version;
|
| + stored_version.ReadFromPrefs(prefs());
|
| + EXPECT_EQ(kTestContentVersion1, stored_version.content_version);
|
| +}
|
| +
|
| +TEST_F(SubresourceFilteringRulesetServiceTest,
|
| NewRulesetSetShortlyBeforeDestruction_NoCrashes) {
|
| - const std::vector<uint8_t> dummy_ruleset(AsVector(kDummyRuleset1));
|
| for (size_t num_tasks_inbetween = 0; num_tasks_inbetween < 5u;
|
| ++num_tasks_inbetween) {
|
| SCOPED_TRACE(::testing::Message() << "#Tasks: " << num_tasks_inbetween);
|
|
|
| - StoreAndPublishUpdatedRuleset(dummy_ruleset, kTestContentVersion1);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
|
| + kTestContentVersion1);
|
| RunPendingTasksNTimes(num_tasks_inbetween);
|
| ResetService();
|
| RunUntilIdle();
|
|
|
| - base::DeleteFile(base_dir(), false);
|
| + EXPECT_TRUE(base::DeleteFile(base_dir(), true));
|
| ResetService(CreateRulesetService());
|
| }
|
| +
|
| + // Must pump out PostTaskWithReply tasks that are referencing the very same
|
| + // task runner to avoid circular dependencies and leaks on shutdown.
|
| + RunUntilIdle();
|
| }
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest,
|
| NewRulesetTwiceInQuickSuccession_SecondRulesetPrevails) {
|
| - const std::vector<uint8_t> dummy_ruleset_1(AsVector(kDummyRuleset1));
|
| - const std::vector<uint8_t> dummy_ruleset_2(AsVector(kDummyRuleset2));
|
| for (size_t num_tasks_inbetween = 0; num_tasks_inbetween < 5u;
|
| ++num_tasks_inbetween) {
|
| SCOPED_TRACE(::testing::Message() << "#Tasks: " << num_tasks_inbetween);
|
|
|
| - StoreAndPublishUpdatedRuleset(dummy_ruleset_1, kTestContentVersion1);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(),
|
| + kTestContentVersion1);
|
| RunPendingTasksNTimes(num_tasks_inbetween);
|
|
|
| - StoreAndPublishUpdatedRuleset(dummy_ruleset_2, kTestContentVersion2);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_2(),
|
| + kTestContentVersion2);
|
| RunUntilIdle();
|
|
|
| // Optionally permit a "hazardous" publication of either the old or new
|
| @@ -300,53 +362,62 @@ TEST_F(SubresourceFilteringRulesetServiceTest,
|
| if (mock_distributor()->published_rulesets().size() == 2) {
|
| base::File* file = &mock_distributor()->published_rulesets()[0];
|
| ASSERT_TRUE(file->IsValid());
|
| - EXPECT_THAT(ReadFileContents(file),
|
| - testing::AnyOf(testing::Eq(dummy_ruleset_1),
|
| - testing::Eq(dummy_ruleset_2)));
|
| + EXPECT_THAT(
|
| + ReadFileContents(file),
|
| + ::testing::AnyOf(::testing::Eq(test_ruleset_1().indexed.contents),
|
| + ::testing::Eq(test_ruleset_2().indexed.contents)));
|
| }
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &mock_distributor()->published_rulesets().back(), dummy_ruleset_2));
|
| + &mock_distributor()->published_rulesets().back(),
|
| + test_ruleset_2().indexed.contents));
|
|
|
| MockRulesetDistributor* new_distributor = new MockRulesetDistributor;
|
| service()->RegisterDistributor(base::WrapUnique(new_distributor));
|
| ASSERT_EQ(1u, new_distributor->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &new_distributor->published_rulesets()[0], dummy_ruleset_2));
|
| + &new_distributor->published_rulesets()[0],
|
| + test_ruleset_2().indexed.contents));
|
|
|
| - RulesetVersion stored_version;
|
| + IndexedRulesetVersion stored_version;
|
| stored_version.ReadFromPrefs(prefs());
|
| EXPECT_EQ(kTestContentVersion2, stored_version.content_version);
|
| +
|
| + ResetService();
|
| + RunUntilIdle();
|
| +
|
| + EXPECT_TRUE(base::DeleteFile(base_dir(), true));
|
| + IndexedRulesetVersion().SaveToPrefs(prefs());
|
| + ResetService(CreateRulesetService());
|
| }
|
| }
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest,
|
| NewRulesetTwiceForTheSameVersion_SuccessAtLeastOnce) {
|
| - const std::vector<uint8_t> dummy_ruleset(AsVector(kDummyRuleset1));
|
| -
|
| - StoreAndPublishUpdatedRuleset(dummy_ruleset, kTestContentVersion1);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
|
| RunUntilIdle();
|
|
|
| - StoreAndPublishUpdatedRuleset(dummy_ruleset, kTestContentVersion1);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
|
| RunUntilIdle();
|
|
|
| ASSERT_LE(1u, mock_distributor()->published_rulesets().size());
|
| ASSERT_GE(2u, mock_distributor()->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &mock_distributor()->published_rulesets().front(), dummy_ruleset));
|
| + &mock_distributor()->published_rulesets().front(),
|
| + test_ruleset_1().indexed.contents));
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &mock_distributor()->published_rulesets().back(), dummy_ruleset));
|
| + &mock_distributor()->published_rulesets().back(),
|
| + test_ruleset_1().indexed.contents));
|
|
|
| MockRulesetDistributor* new_distributor = new MockRulesetDistributor;
|
| service()->RegisterDistributor(base::WrapUnique(new_distributor));
|
| ASSERT_EQ(1u, new_distributor->published_rulesets().size());
|
| ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
|
| - &new_distributor->published_rulesets()[0], dummy_ruleset));
|
| + &new_distributor->published_rulesets()[0],
|
| + test_ruleset_1().indexed.contents));
|
| }
|
|
|
| TEST_F(SubresourceFilteringRulesetServiceTest, RulesetIsReadonly) {
|
| - const std::vector<uint8_t> dummy_ruleset(AsVector(kDummyRuleset1));
|
| -
|
| - service()->StoreAndPublishUpdatedRuleset(dummy_ruleset, kTestContentVersion1);
|
| + IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
|
| RunUntilIdle();
|
|
|
| ASSERT_EQ(1u, mock_distributor()->published_rulesets().size());
|
|
|