| // 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 "net/reporting/reporting_test_util.h" |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/check_op.h" |
| #include "base/json/json_reader.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/notreached.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/test/simple_test_clock.h" |
| #include "base/test/simple_test_tick_clock.h" |
| #include "base/timer/mock_timer.h" |
| #include "net/base/network_isolation_key.h" |
| #include "net/reporting/reporting_cache.h" |
| #include "net/reporting/reporting_context.h" |
| #include "net/reporting/reporting_delegate.h" |
| #include "net/reporting/reporting_delivery_agent.h" |
| #include "net/reporting/reporting_endpoint.h" |
| #include "net/reporting/reporting_garbage_collector.h" |
| #include "net/reporting/reporting_policy.h" |
| #include "net/reporting/reporting_uploader.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| class PendingUploadImpl : public TestReportingUploader::PendingUpload { |
| public: |
| PendingUploadImpl(const url::Origin& report_origin, |
| const GURL& url, |
| const NetworkIsolationKey& network_isolation_key, |
| const std::string& json, |
| ReportingUploader::UploadCallback callback, |
| base::OnceCallback<void(PendingUpload*)> complete_callback) |
| : report_origin_(report_origin), |
| url_(url), |
| network_isolation_key_(network_isolation_key), |
| json_(json), |
| callback_(std::move(callback)), |
| complete_callback_(std::move(complete_callback)) {} |
| |
| ~PendingUploadImpl() override = default; |
| |
| // PendingUpload implementation: |
| const url::Origin& report_origin() const override { return report_origin_; } |
| const GURL& url() const override { return url_; } |
| const std::string& json() const override { return json_; } |
| std::unique_ptr<base::Value> GetValue() const override { |
| return base::JSONReader::ReadDeprecated(json_); |
| } |
| |
| void Complete(ReportingUploader::Outcome outcome) override { |
| std::move(callback_).Run(outcome); |
| // Deletes |this|. |
| std::move(complete_callback_).Run(this); |
| } |
| |
| private: |
| url::Origin report_origin_; |
| GURL url_; |
| NetworkIsolationKey network_isolation_key_; |
| std::string json_; |
| ReportingUploader::UploadCallback callback_; |
| base::OnceCallback<void(PendingUpload*)> complete_callback_; |
| }; |
| |
| void ErasePendingUpload( |
| std::vector<std::unique_ptr<TestReportingUploader::PendingUpload>>* uploads, |
| TestReportingUploader::PendingUpload* upload) { |
| for (auto it = uploads->begin(); it != uploads->end(); ++it) { |
| if (it->get() == upload) { |
| uploads->erase(it); |
| return; |
| } |
| } |
| NOTREACHED(); |
| } |
| |
| } // namespace |
| |
| RandIntCallback TestReportingRandIntCallback() { |
| return base::BindRepeating( |
| [](int* rand_counter, int min, int max) { |
| DCHECK_LE(min, max); |
| return min + ((*rand_counter)++ % (max - min + 1)); |
| }, |
| base::Owned(std::make_unique<int>(0))); |
| } |
| |
| TestReportingUploader::PendingUpload::~PendingUpload() = default; |
| TestReportingUploader::PendingUpload::PendingUpload() = default; |
| |
| TestReportingUploader::TestReportingUploader() = default; |
| TestReportingUploader::~TestReportingUploader() = default; |
| |
| void TestReportingUploader::StartUpload( |
| const url::Origin& report_origin, |
| const GURL& url, |
| const NetworkIsolationKey& network_isolation_key, |
| const std::string& json, |
| int max_depth, |
| UploadCallback callback) { |
| pending_uploads_.push_back(std::make_unique<PendingUploadImpl>( |
| report_origin, url, network_isolation_key, json, std::move(callback), |
| base::BindOnce(&ErasePendingUpload, &pending_uploads_))); |
| } |
| |
| void TestReportingUploader::OnShutdown() { |
| pending_uploads_.clear(); |
| } |
| |
| int TestReportingUploader::GetPendingUploadCountForTesting() const { |
| return pending_uploads_.size(); |
| } |
| |
| TestReportingDelegate::TestReportingDelegate() = default; |
| |
| TestReportingDelegate::~TestReportingDelegate() = default; |
| |
| bool TestReportingDelegate::CanQueueReport(const url::Origin& origin) const { |
| return true; |
| } |
| |
| void TestReportingDelegate::CanSendReports( |
| std::set<url::Origin> origins, |
| base::OnceCallback<void(std::set<url::Origin>)> result_callback) const { |
| if (pause_permissions_check_) { |
| saved_origins_ = std::move(origins); |
| permissions_check_callback_ = std::move(result_callback); |
| return; |
| } |
| |
| if (disallow_report_uploads_) |
| origins.clear(); |
| std::move(result_callback).Run(std::move(origins)); |
| } |
| |
| bool TestReportingDelegate::PermissionsCheckPaused() const { |
| return !permissions_check_callback_.is_null(); |
| } |
| |
| void TestReportingDelegate::ResumePermissionsCheck() { |
| if (disallow_report_uploads_) |
| saved_origins_.clear(); |
| std::move(permissions_check_callback_).Run(std::move(saved_origins_)); |
| } |
| |
| bool TestReportingDelegate::CanSetClient(const url::Origin& origin, |
| const GURL& endpoint) const { |
| return true; |
| } |
| |
| bool TestReportingDelegate::CanUseClient(const url::Origin& origin, |
| const GURL& endpoint) const { |
| return true; |
| } |
| |
| TestReportingContext::TestReportingContext( |
| base::Clock* clock, |
| const base::TickClock* tick_clock, |
| const ReportingPolicy& policy, |
| ReportingCache::PersistentReportingStore* store) |
| : ReportingContext(policy, |
| clock, |
| tick_clock, |
| TestReportingRandIntCallback(), |
| std::make_unique<TestReportingUploader>(), |
| std::make_unique<TestReportingDelegate>(), |
| store), |
| delivery_timer_(new base::MockOneShotTimer()), |
| garbage_collection_timer_(new base::MockOneShotTimer()) { |
| garbage_collector()->SetTimerForTesting( |
| base::WrapUnique(garbage_collection_timer_)); |
| delivery_agent()->SetTimerForTesting(base::WrapUnique(delivery_timer_)); |
| } |
| |
| TestReportingContext::~TestReportingContext() { |
| delivery_timer_ = nullptr; |
| garbage_collection_timer_ = nullptr; |
| } |
| |
| ReportingTestBase::ReportingTestBase() : store_(nullptr) { |
| // For tests, disable jitter. |
| ReportingPolicy policy; |
| policy.endpoint_backoff_policy.jitter_factor = 0.0; |
| |
| CreateContext(policy, base::Time::Now(), base::TimeTicks::Now()); |
| } |
| |
| ReportingTestBase::~ReportingTestBase() = default; |
| |
| void ReportingTestBase::UsePolicy(const ReportingPolicy& new_policy) { |
| CreateContext(new_policy, clock()->Now(), tick_clock()->NowTicks()); |
| } |
| |
| void ReportingTestBase::UseStore( |
| ReportingCache::PersistentReportingStore* store) { |
| store_ = store; |
| CreateContext(policy(), clock()->Now(), tick_clock()->NowTicks()); |
| } |
| |
| const ReportingEndpoint ReportingTestBase::FindEndpointInCache( |
| const ReportingEndpointGroupKey& group_key, |
| const GURL& url) { |
| return cache()->GetEndpointForTesting(group_key, url); |
| } |
| |
| bool ReportingTestBase::SetEndpointInCache( |
| const ReportingEndpointGroupKey& group_key, |
| const GURL& url, |
| base::Time expires, |
| OriginSubdomains include_subdomains, |
| int priority, |
| int weight) { |
| cache()->SetEndpointForTesting(group_key, url, include_subdomains, expires, |
| priority, weight); |
| const ReportingEndpoint endpoint = FindEndpointInCache(group_key, url); |
| return endpoint.is_valid(); |
| } |
| |
| bool ReportingTestBase::EndpointExistsInCache( |
| const ReportingEndpointGroupKey& group_key, |
| const GURL& url) { |
| ReportingEndpoint endpoint = cache()->GetEndpointForTesting(group_key, url); |
| return endpoint.is_valid(); |
| } |
| |
| ReportingEndpoint::Statistics ReportingTestBase::GetEndpointStatistics( |
| const ReportingEndpointGroupKey& group_key, |
| const GURL& url) { |
| ReportingEndpoint endpoint = cache()->GetEndpointForTesting(group_key, url); |
| if (endpoint) |
| return endpoint.stats; |
| return ReportingEndpoint::Statistics(); |
| } |
| |
| bool ReportingTestBase::EndpointGroupExistsInCache( |
| const ReportingEndpointGroupKey& group_key, |
| OriginSubdomains include_subdomains, |
| base::Time expires) { |
| return cache()->EndpointGroupExistsForTesting(group_key, include_subdomains, |
| expires); |
| } |
| |
| bool ReportingTestBase::ClientExistsInCacheForOrigin( |
| const url::Origin& origin) { |
| std::set<url::Origin> all_origins = cache()->GetAllOrigins(); |
| return all_origins.find(origin) != all_origins.end(); |
| } |
| |
| GURL ReportingTestBase::MakeURL(size_t index) { |
| return GURL(base::StringPrintf("https://example%zd.test", index)); |
| } |
| |
| void ReportingTestBase::SimulateRestart(base::TimeDelta delta, |
| base::TimeDelta delta_ticks) { |
| CreateContext(policy(), clock()->Now() + delta, |
| tick_clock()->NowTicks() + delta_ticks); |
| } |
| |
| void ReportingTestBase::CreateContext(const ReportingPolicy& policy, |
| base::Time now, |
| base::TimeTicks now_ticks) { |
| context_ = std::make_unique<TestReportingContext>(&clock_, &tick_clock_, |
| policy, store_); |
| clock()->SetNow(now); |
| tick_clock()->SetNowTicks(now_ticks); |
| } |
| |
| base::TimeTicks ReportingTestBase::yesterday() { |
| return tick_clock()->NowTicks() - base::TimeDelta::FromDays(1); |
| } |
| |
| base::TimeTicks ReportingTestBase::now() { |
| return tick_clock()->NowTicks(); |
| } |
| |
| base::TimeTicks ReportingTestBase::tomorrow() { |
| return tick_clock()->NowTicks() + base::TimeDelta::FromDays(1); |
| } |
| |
| TestReportingService::Report::Report() = default; |
| |
| TestReportingService::Report::Report(Report&& other) |
| : url(other.url), |
| user_agent(other.user_agent), |
| group(other.group), |
| type(other.type), |
| body(std::move(other.body)), |
| depth(other.depth) {} |
| |
| TestReportingService::Report::Report(const GURL& url, |
| const std::string& user_agent, |
| const std::string& group, |
| const std::string& type, |
| std::unique_ptr<const base::Value> body, |
| int depth) |
| : url(url), |
| user_agent(user_agent), |
| group(group), |
| type(type), |
| body(std::move(body)), |
| depth(depth) {} |
| |
| TestReportingService::Report::~Report() = default; |
| |
| TestReportingService::TestReportingService() = default; |
| |
| TestReportingService::~TestReportingService() = default; |
| |
| void TestReportingService::QueueReport(const GURL& url, |
| const std::string& user_agent, |
| const std::string& group, |
| const std::string& type, |
| std::unique_ptr<const base::Value> body, |
| int depth) { |
| reports_.push_back( |
| Report(url, user_agent, group, type, std::move(body), depth)); |
| } |
| |
| void TestReportingService::ProcessHeader(const GURL& url, |
| const std::string& header_value) { |
| NOTREACHED(); |
| } |
| |
| void TestReportingService::RemoveBrowsingData( |
| uint64_t data_type_mask, |
| const base::RepeatingCallback<bool(const GURL&)>& origin_filter) { |
| NOTREACHED(); |
| } |
| |
| void TestReportingService::RemoveAllBrowsingData(uint64_t data_type_mask) { |
| NOTREACHED(); |
| } |
| |
| void TestReportingService::OnShutdown() {} |
| |
| const ReportingPolicy& TestReportingService::GetPolicy() const { |
| NOTREACHED(); |
| return dummy_policy_; |
| } |
| |
| ReportingContext* TestReportingService::GetContextForTesting() const { |
| NOTREACHED(); |
| return nullptr; |
| } |
| |
| } // namespace net |