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()); |