Index: components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc |
diff --git a/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc b/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4182e1c876e9ff62ffa7a17962fb16f597fa4f83 |
--- /dev/null |
+++ b/components/subresource_filter/content/browser/verified_ruleset_dealer_unittest.cc |
@@ -0,0 +1,339 @@ |
+// Copyright 2017 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/content/browser/verified_ruleset_dealer.h" |
+ |
+#include <memory> |
+#include <vector> |
+ |
+#include "base/bind.h" |
+#include "base/files/file.h" |
+#include "base/test/test_simple_task_runner.h" |
+#include "components/subresource_filter/core/common/memory_mapped_ruleset.h" |
+#include "components/subresource_filter/core/common/test_ruleset_creator.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace subresource_filter { |
+ |
+namespace { |
+ |
+// TODO(pkalinnikov): Consider putting this to a test_support for this test file |
+// and SubresourceFilterRulesetDealerTest. |
+class TestRulesets { |
+ public: |
+ TestRulesets() = default; |
+ |
+ void CreateRulesets(bool many_rules = false) { |
+ if (many_rules) { |
+ ASSERT_NO_FATAL_FAILURE( |
+ test_ruleset_creator_.CreateRulesetToDisallowURLsWithManySuffixes( |
+ kTestRulesetSuffix1, kNumberOfRulesInBigRuleset, |
+ &test_ruleset_pair_1_)); |
+ ASSERT_NO_FATAL_FAILURE( |
+ test_ruleset_creator_.CreateRulesetToDisallowURLsWithManySuffixes( |
+ kTestRulesetSuffix2, kNumberOfRulesInBigRuleset, |
+ &test_ruleset_pair_2_)); |
+ } else { |
+ ASSERT_NO_FATAL_FAILURE( |
+ test_ruleset_creator_.CreateRulesetToDisallowURLsWithPathSuffix( |
+ kTestRulesetSuffix1, &test_ruleset_pair_1_)); |
+ ASSERT_NO_FATAL_FAILURE( |
+ test_ruleset_creator_.CreateRulesetToDisallowURLsWithPathSuffix( |
+ kTestRulesetSuffix2, &test_ruleset_pair_2_)); |
+ } |
+ } |
+ |
+ const testing::TestRuleset& indexed_1() const { |
+ return test_ruleset_pair_1_.indexed; |
+ } |
+ |
+ const testing::TestRuleset& indexed_2() const { |
+ return test_ruleset_pair_2_.indexed; |
+ } |
+ |
+ private: |
+ static constexpr const char kTestRulesetSuffix1[] = "foo"; |
+ static constexpr const char kTestRulesetSuffix2[] = "bar"; |
+ static constexpr int kNumberOfRulesInBigRuleset = 500; |
+ |
+ testing::TestRulesetCreator test_ruleset_creator_; |
+ testing::TestRulesetPair test_ruleset_pair_1_; |
+ testing::TestRulesetPair test_ruleset_pair_2_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestRulesets); |
+}; |
+ |
+constexpr const char TestRulesets::kTestRulesetSuffix1[]; |
+constexpr const char TestRulesets::kTestRulesetSuffix2[]; |
+constexpr int TestRulesets::kNumberOfRulesInBigRuleset; |
+ |
+std::vector<uint8_t> ReadRulesetContents(const MemoryMappedRuleset* ruleset) { |
+ return std::vector<uint8_t>(ruleset->data(), |
+ ruleset->data() + ruleset->length()); |
+} |
+ |
+} // namespace |
+ |
+// Tests for VerifiedRulesetDealer. -------------------------------------------- |
+// |
+// Note that VerifiedRulesetDealer uses RulesetDealer very directly to provide |
+// MemoryMappedRulesets. Many aspects of its work, e.g., lifetime of a |
+// MemoryMappedRuleset, its lazy creation, etc., are covered with tests to |
+// RulesetDealer, therefore these aspects are not tested here. |
+ |
+class SubresourceFilterVerifiedRulesetDealerTest : public ::testing::Test { |
+ public: |
+ SubresourceFilterVerifiedRulesetDealerTest() = default; |
+ |
+ protected: |
+ void SetUp() override { |
+ rulesets_.CreateRulesets(true /* many_rules */); |
+ ruleset_dealer_.reset(new VerifiedRulesetDealer); |
+ } |
+ |
+ const TestRulesets& rulesets() const { return rulesets_; } |
+ VerifiedRulesetDealer* ruleset_dealer() { return ruleset_dealer_.get(); } |
+ |
+ bool has_cached_ruleset() const { |
+ return ruleset_dealer_->has_cached_ruleset(); |
+ } |
+ |
+ private: |
+ TestRulesets rulesets_; |
+ std::unique_ptr<VerifiedRulesetDealer> ruleset_dealer_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SubresourceFilterVerifiedRulesetDealerTest); |
+}; |
+ |
+TEST_F(SubresourceFilterVerifiedRulesetDealerTest, |
+ RulesetIsMemoryMappedAndVerifiedLazily) { |
+ ruleset_dealer()->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_1())); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_FALSE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::NOT_VERIFIED, |
+ ruleset_dealer()->status()); |
+ |
+ scoped_refptr<const MemoryMappedRuleset> ref_to_ruleset = |
+ ruleset_dealer()->GetRuleset(); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_TRUE(ref_to_ruleset); |
+ EXPECT_TRUE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::INTACT, ruleset_dealer()->status()); |
+} |
+ |
+TEST_F(SubresourceFilterVerifiedRulesetDealerTest, |
+ CorruptedRulesetIsNeitherProvidedNorCached) { |
+ testing::TestRuleset::CorruptByTruncating(rulesets().indexed_1(), 123); |
+ |
+ ruleset_dealer()->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_1())); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_FALSE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::NOT_VERIFIED, |
+ ruleset_dealer()->status()); |
+ |
+ scoped_refptr<const MemoryMappedRuleset> ref_to_ruleset = |
+ ruleset_dealer()->GetRuleset(); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_FALSE(ref_to_ruleset); |
+ EXPECT_FALSE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::CORRUPT, ruleset_dealer()->status()); |
+} |
+ |
+TEST_F(SubresourceFilterVerifiedRulesetDealerTest, |
+ TruncatingFileMakesRulesetInvalid) { |
+ testing::TestRuleset::CorruptByTruncating(rulesets().indexed_1(), 4096); |
+ ruleset_dealer()->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_1())); |
+ scoped_refptr<const MemoryMappedRuleset> ref_to_ruleset = |
+ ruleset_dealer()->GetRuleset(); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_FALSE(ref_to_ruleset); |
+ EXPECT_FALSE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::CORRUPT, ruleset_dealer()->status()); |
+} |
+ |
+TEST_F(SubresourceFilterVerifiedRulesetDealerTest, |
+ FillingRangeMakesRulesetInvalid) { |
+ testing::TestRuleset::CorruptByFilling(rulesets().indexed_1(), |
+ 2501 /* from */, 4000 /* to */, |
+ 255 /* fill_with */); |
+ ruleset_dealer()->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_1())); |
+ scoped_refptr<const MemoryMappedRuleset> ref_to_ruleset = |
+ ruleset_dealer()->GetRuleset(); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_FALSE(ref_to_ruleset); |
+ EXPECT_FALSE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::CORRUPT, ruleset_dealer()->status()); |
+} |
+ |
+TEST_F(SubresourceFilterVerifiedRulesetDealerTest, |
+ RulesetIsVerifiedAfterUpdate) { |
+ testing::TestRuleset::CorruptByTruncating(rulesets().indexed_1(), 123); |
+ |
+ ruleset_dealer()->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_1())); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_FALSE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::NOT_VERIFIED, |
+ ruleset_dealer()->status()); |
+ |
+ scoped_refptr<const MemoryMappedRuleset> ref_to_ruleset = |
+ ruleset_dealer()->GetRuleset(); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_FALSE(ref_to_ruleset); |
+ EXPECT_FALSE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::CORRUPT, ruleset_dealer()->status()); |
+ |
+ ruleset_dealer()->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_2())); |
+ EXPECT_EQ(RulesetVerificationStatus::NOT_VERIFIED, |
+ ruleset_dealer()->status()); |
+ ref_to_ruleset = ruleset_dealer()->GetRuleset(); |
+ |
+ EXPECT_TRUE(ruleset_dealer()->IsRulesetFileAvailable()); |
+ EXPECT_TRUE(ref_to_ruleset); |
+ EXPECT_TRUE(has_cached_ruleset()); |
+ EXPECT_EQ(RulesetVerificationStatus::INTACT, ruleset_dealer()->status()); |
+} |
+ |
+// Tests for VerifiedRulesetDealer::Handle. ------------------------------------ |
+ |
+namespace { |
+ |
+class TestVerifiedRulesetDealerClient { |
+ public: |
+ TestVerifiedRulesetDealerClient() = default; |
+ |
+ base::Callback<void(VerifiedRulesetDealer*)> GetCallback() { |
+ return base::Bind(&TestVerifiedRulesetDealerClient::Callback, |
+ base::Unretained(this)); |
+ } |
+ |
+ void ExpectRulesetState(bool expected_availability, |
+ RulesetVerificationStatus expected_status = |
+ RulesetVerificationStatus::NOT_VERIFIED) const { |
+ ASSERT_EQ(1, invocation_counter_); |
+ EXPECT_EQ(expected_availability, is_ruleset_file_available_); |
+ EXPECT_FALSE(has_cached_ruleset_); |
+ EXPECT_EQ(expected_status, status_); |
+ } |
+ |
+ void ExpectRulesetContents( |
+ const std::vector<uint8_t> expected_contents) const { |
+ ExpectRulesetState(true, RulesetVerificationStatus::INTACT); |
+ EXPECT_TRUE(ruleset_is_created_); |
+ EXPECT_EQ(expected_contents, contents_); |
+ } |
+ |
+ private: |
+ void Callback(VerifiedRulesetDealer* dealer) { |
+ ++invocation_counter_; |
+ ASSERT_TRUE(dealer); |
+ |
+ is_ruleset_file_available_ = dealer->IsRulesetFileAvailable(); |
+ has_cached_ruleset_ = dealer->has_cached_ruleset(); |
+ status_ = dealer->status(); |
+ |
+ auto ruleset = dealer->GetRuleset(); |
+ ruleset_is_created_ = !!ruleset; |
+ if (ruleset_is_created_) |
+ contents_ = ReadRulesetContents(ruleset.get()); |
+ } |
+ |
+ bool is_ruleset_file_available_ = false; |
+ bool has_cached_ruleset_ = false; |
+ RulesetVerificationStatus status_ = RulesetVerificationStatus::NOT_VERIFIED; |
+ |
+ bool ruleset_is_created_ = false; |
+ std::vector<uint8_t> contents_; |
+ |
+ int invocation_counter_ = 0; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TestVerifiedRulesetDealerClient); |
+}; |
+ |
+} // namespace |
+ |
+class SubresourceFilterVerifiedRulesetDealerHandleTest |
+ : public ::testing::Test { |
+ public: |
+ SubresourceFilterVerifiedRulesetDealerHandleTest() = default; |
+ |
+ protected: |
+ void SetUp() override { |
+ rulesets_.CreateRulesets(false /* many_rules */); |
+ task_runner_ = new base::TestSimpleTaskRunner; |
+ } |
+ |
+ const TestRulesets& rulesets() const { return rulesets_; } |
+ base::TestSimpleTaskRunner* task_runner() { return task_runner_.get(); } |
+ |
+ private: |
+ TestRulesets rulesets_; |
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SubresourceFilterVerifiedRulesetDealerHandleTest); |
+}; |
+ |
+TEST_F(SubresourceFilterVerifiedRulesetDealerHandleTest, |
+ RulesetIsMappedLazily) { |
+ TestVerifiedRulesetDealerClient before_set_ruleset; |
+ TestVerifiedRulesetDealerClient after_set_ruleset; |
+ TestVerifiedRulesetDealerClient after_warm_up; |
+ |
+ std::unique_ptr<VerifiedRulesetDealer::Handle> dealer_handle( |
+ new VerifiedRulesetDealer::Handle(task_runner())); |
+ dealer_handle->GetDealerAsync(before_set_ruleset.GetCallback()); |
+ dealer_handle->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_1())); |
+ dealer_handle->GetDealerAsync(after_set_ruleset.GetCallback()); |
+ dealer_handle->GetDealerAsync(after_warm_up.GetCallback()); |
+ dealer_handle.reset(nullptr); |
+ task_runner()->RunUntilIdle(); |
+ |
+ before_set_ruleset.ExpectRulesetState(false); |
+ after_set_ruleset.ExpectRulesetState(true); |
+ after_warm_up.ExpectRulesetContents(rulesets().indexed_1().contents); |
+} |
+ |
+TEST_F(SubresourceFilterVerifiedRulesetDealerHandleTest, RulesetFileIsUpdated) { |
+ TestVerifiedRulesetDealerClient after_set_ruleset_1; |
+ TestVerifiedRulesetDealerClient read_ruleset_1; |
+ TestVerifiedRulesetDealerClient after_set_ruleset_2; |
+ TestVerifiedRulesetDealerClient read_ruleset_2; |
+ |
+ std::unique_ptr<VerifiedRulesetDealer::Handle> dealer_handle( |
+ new VerifiedRulesetDealer::Handle(task_runner())); |
+ |
+ dealer_handle->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_1())); |
+ dealer_handle->GetDealerAsync(after_set_ruleset_1.GetCallback()); |
+ dealer_handle->GetDealerAsync(read_ruleset_1.GetCallback()); |
+ |
+ dealer_handle->SetRulesetFile( |
+ testing::TestRuleset::Open(rulesets().indexed_2())); |
+ dealer_handle->GetDealerAsync(after_set_ruleset_2.GetCallback()); |
+ dealer_handle->GetDealerAsync(read_ruleset_2.GetCallback()); |
+ |
+ dealer_handle.reset(nullptr); |
+ task_runner()->RunUntilIdle(); |
+ |
+ after_set_ruleset_1.ExpectRulesetState(true); |
+ read_ruleset_1.ExpectRulesetContents(rulesets().indexed_1().contents); |
+ after_set_ruleset_2.ExpectRulesetState(true); |
+ read_ruleset_2.ExpectRulesetContents(rulesets().indexed_2().contents); |
+} |
+ |
+} // namespace subresource_filter |