| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_TEST_UTILS_H_ |
| #define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_TEST_UTILS_H_ |
| |
| #include <stdint.h> |
| |
| #include <iosfwd> |
| #include <limits> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/flat_set.h" |
| #include "base/guid.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/observer_list.h" |
| #include "base/run_loop.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "base/thread_annotations.h" |
| #include "base/time/time.h" |
| #include "components/attribution_reporting/aggregatable_values.h" |
| #include "components/attribution_reporting/aggregation_keys.h" |
| #include "components/attribution_reporting/bounded_list.h" |
| #include "components/attribution_reporting/constants.h" |
| #include "components/attribution_reporting/event_trigger_data.h" |
| #include "components/attribution_reporting/filters.h" |
| #include "components/attribution_reporting/source_registration_error.mojom-forward.h" |
| #include "components/attribution_reporting/suitable_origin.h" |
| #include "components/attribution_reporting/test_utils.h" |
| #include "content/browser/attribution_reporting/aggregatable_histogram_contribution.h" |
| #include "content/browser/attribution_reporting/attribution_data_host_manager.h" |
| #include "content/browser/attribution_reporting/attribution_host.h" |
| #include "content/browser/attribution_reporting/attribution_info.h" |
| #include "content/browser/attribution_reporting/attribution_input_event.h" |
| #include "content/browser/attribution_reporting/attribution_manager.h" |
| #include "content/browser/attribution_reporting/attribution_observer.h" |
| #include "content/browser/attribution_reporting/attribution_observer_types.h" |
| #include "content/browser/attribution_reporting/attribution_report.h" |
| #include "content/browser/attribution_reporting/attribution_source_type.h" |
| #include "content/browser/attribution_reporting/attribution_storage.h" |
| #include "content/browser/attribution_reporting/attribution_storage_delegate.h" |
| #include "content/browser/attribution_reporting/attribution_trigger.h" |
| #include "content/browser/attribution_reporting/common_source_info.h" |
| #include "content/browser/attribution_reporting/send_result.h" |
| #include "content/browser/attribution_reporting/storable_source.h" |
| #include "content/browser/attribution_reporting/stored_source.h" |
| #include "content/public/browser/attribution_config.h" |
| #include "content/public/browser/navigation_handle.h" |
| #include "content/public/test/test_navigation_observer.h" |
| #include "content/test/test_content_browser_client.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| #include "third_party/blink/public/common/navigation/impression.h" |
| #include "third_party/blink/public/mojom/conversions/attribution_data_host.mojom.h" |
| #include "url/origin.h" |
| |
| namespace attribution_reporting { |
| class AggregatableTriggerData; |
| struct TriggerRegistration; |
| } // namespace attribution_reporting |
| |
| namespace mojo { |
| |
| template <typename Interface> |
| class PendingReceiver; |
| |
| } // namespace mojo |
| |
| namespace content { |
| |
| class AttributionObserver; |
| class AttributionTrigger; |
| |
| enum class RateLimitResult : int; |
| |
| const AttributionSourceType kSourceTypes[] = { |
| AttributionSourceType::kNavigation, |
| AttributionSourceType::kEvent, |
| }; |
| |
| class MockAttributionReportingContentBrowserClient |
| : public TestContentBrowserClient { |
| public: |
| MockAttributionReportingContentBrowserClient(); |
| ~MockAttributionReportingContentBrowserClient() override; |
| |
| // ContentBrowserClient: |
| MOCK_METHOD(bool, |
| IsAttributionReportingOperationAllowed, |
| (content::BrowserContext * browser_context, |
| AttributionReportingOperation operation, |
| const url::Origin* source_origin, |
| const url::Origin* destination_origin, |
| const url::Origin* reporting_origin), |
| (override)); |
| }; |
| |
| class MockAttributionHost : public AttributionHost { |
| public: |
| static MockAttributionHost* Override(WebContents* web_contents); |
| |
| ~MockAttributionHost() override; |
| |
| MOCK_METHOD( |
| void, |
| RegisterDataHost, |
| (mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host), |
| (override)); |
| |
| MOCK_METHOD( |
| void, |
| RegisterNavigationDataHost, |
| (mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host, |
| const blink::AttributionSrcToken& attribution_src_token, |
| blink::mojom::AttributionNavigationType), |
| (override)); |
| |
| private: |
| explicit MockAttributionHost(WebContents* web_contents); |
| }; |
| |
| class MockDataHost : public blink::mojom::AttributionDataHost { |
| public: |
| explicit MockDataHost( |
| mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host); |
| ~MockDataHost() override; |
| |
| void WaitForSourceData(size_t num_source_data); |
| void WaitForTriggerData(size_t num_trigger_data); |
| |
| const std::vector<blink::mojom::AttributionSourceDataPtr>& source_data() |
| const { |
| return source_data_; |
| } |
| |
| const std::vector<blink::mojom::AttributionTriggerDataPtr>& trigger_data() |
| const { |
| return trigger_data_; |
| } |
| |
| mojo::Receiver<blink::mojom::AttributionDataHost>& receiver() { |
| return receiver_; |
| } |
| |
| private: |
| // blink::mojom::AttributionDataHost: |
| void SourceDataAvailable( |
| blink::mojom::AttributionSourceDataPtr data) override; |
| void TriggerDataAvailable( |
| blink::mojom::AttributionTriggerDataPtr data) override; |
| |
| size_t min_source_data_count_ = 0; |
| std::vector<blink::mojom::AttributionSourceDataPtr> source_data_; |
| |
| size_t min_trigger_data_count_ = 0; |
| std::vector<blink::mojom::AttributionTriggerDataPtr> trigger_data_; |
| |
| base::RunLoop wait_loop_; |
| mojo::Receiver<blink::mojom::AttributionDataHost> receiver_{this}; |
| }; |
| |
| class MockDataHostManager : public AttributionDataHostManager { |
| public: |
| MockDataHostManager(); |
| ~MockDataHostManager() override; |
| |
| MOCK_METHOD( |
| void, |
| RegisterDataHost, |
| (mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host, |
| attribution_reporting::SuitableOrigin context_origin, |
| bool is_within_fenced_frame), |
| (override)); |
| |
| MOCK_METHOD( |
| bool, |
| RegisterNavigationDataHost, |
| (mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host, |
| const blink::AttributionSrcToken& attribution_src_token, |
| AttributionInputEvent input_event, |
| blink::mojom::AttributionNavigationType), |
| (override)); |
| |
| MOCK_METHOD(void, |
| NotifyNavigationRedirectRegistration, |
| (const blink::AttributionSrcToken& attribution_src_token, |
| std::string header_value, |
| attribution_reporting::SuitableOrigin reporting_origin, |
| const attribution_reporting::SuitableOrigin& source_origin, |
| AttributionInputEvent input_event, |
| blink::mojom::AttributionNavigationType), |
| (override)); |
| |
| MOCK_METHOD(void, |
| NotifyNavigationForDataHost, |
| (const blink::AttributionSrcToken& attribution_src_token, |
| const attribution_reporting::SuitableOrigin& source_origin, |
| blink::mojom::AttributionNavigationType), |
| (override)); |
| |
| MOCK_METHOD(void, |
| NotifyNavigationFailure, |
| (const blink::AttributionSrcToken& attribution_src_token), |
| (override)); |
| }; |
| |
| base::GUID DefaultExternalReportID(); |
| |
| std::vector<base::GUID> DefaultExternalReportIDs(size_t size); |
| |
| class ConfigurableStorageDelegate : public AttributionStorageDelegate { |
| public: |
| ConfigurableStorageDelegate(); |
| ~ConfigurableStorageDelegate() override; |
| |
| // AttributionStorageDelegate |
| base::Time GetEventLevelReportTime(const CommonSourceInfo& source, |
| base::Time trigger_time) const override; |
| base::Time GetAggregatableReportTime(base::Time trigger_time) const override; |
| base::TimeDelta GetDeleteExpiredSourcesFrequency() const override; |
| base::TimeDelta GetDeleteExpiredRateLimitsFrequency() const override; |
| base::GUID NewReportID() const override; |
| absl::optional<OfflineReportDelayConfig> GetOfflineReportDelayConfig() |
| const override; |
| void ShuffleReports(std::vector<AttributionReport>& reports) override; |
| RandomizedResponse GetRandomizedResponse( |
| const CommonSourceInfo& source) override; |
| |
| void set_max_attributions_per_source(int max); |
| |
| void set_max_sources_per_origin(int max); |
| |
| void set_max_reports_per_destination(AttributionReport::Type report_type, |
| int max); |
| |
| void set_max_destinations_per_source_site_reporting_origin(int max); |
| |
| void set_aggregatable_budget_per_source(int64_t max); |
| |
| void set_rate_limits(AttributionConfig::RateLimitConfig c); |
| |
| void set_delete_expired_sources_frequency(base::TimeDelta frequency); |
| |
| void set_delete_expired_rate_limits_frequency(base::TimeDelta frequency); |
| |
| void set_report_delay(base::TimeDelta report_delay); |
| |
| void set_offline_report_delay_config( |
| absl::optional<OfflineReportDelayConfig> config); |
| |
| void set_reverse_reports_on_shuffle(bool reverse); |
| |
| // Note that these rates are *not* used to produce a randomized response; that |
| // is controlled deterministically by `set_randomized_response()`. |
| void set_randomized_response_rates(double navigation, double event); |
| |
| void set_randomized_response(RandomizedResponse randomized_response); |
| |
| void set_trigger_data_cardinality(uint64_t navigation, uint64_t event); |
| |
| void set_source_event_id_cardinality(uint64_t cardinality); |
| |
| // Detaches the delegate from its current sequence in preparation for being |
| // moved to storage, which runs on its own sequence. |
| void DetachFromSequence(); |
| |
| private: |
| base::TimeDelta delete_expired_sources_frequency_ |
| GUARDED_BY_CONTEXT(sequence_checker_); |
| base::TimeDelta delete_expired_rate_limits_frequency_ |
| GUARDED_BY_CONTEXT(sequence_checker_); |
| |
| base::TimeDelta report_delay_ GUARDED_BY_CONTEXT(sequence_checker_); |
| |
| absl::optional<OfflineReportDelayConfig> offline_report_delay_config_ |
| GUARDED_BY_CONTEXT(sequence_checker_); |
| |
| // If true, `ShuffleReports()` reverses the reports to allow testing the |
| // proper call from `AttributionStorage::GetAttributionReports()`. |
| bool reverse_reports_on_shuffle_ GUARDED_BY_CONTEXT(sequence_checker_) = |
| false; |
| |
| RandomizedResponse randomized_response_ |
| GUARDED_BY_CONTEXT(sequence_checker_) = absl::nullopt; |
| }; |
| |
| class MockAttributionManager : public AttributionManager { |
| public: |
| MockAttributionManager(); |
| ~MockAttributionManager() override; |
| |
| // AttributionManager: |
| MOCK_METHOD(void, HandleSource, (StorableSource source), (override)); |
| |
| MOCK_METHOD(void, HandleTrigger, (AttributionTrigger trigger), (override)); |
| |
| MOCK_METHOD(void, |
| GetActiveSourcesForWebUI, |
| (base::OnceCallback<void(std::vector<StoredSource>)> callback), |
| (override)); |
| |
| MOCK_METHOD( |
| void, |
| GetPendingReportsForInternalUse, |
| (AttributionReport::Types report_types, |
| int limit, |
| base::OnceCallback<void(std::vector<AttributionReport>)> callback), |
| (override)); |
| |
| MOCK_METHOD(void, |
| SendReportsForWebUI, |
| (const std::vector<AttributionReport::Id>& ids, |
| base::OnceClosure done), |
| (override)); |
| |
| MOCK_METHOD(void, |
| ClearData, |
| (base::Time delete_begin, |
| base::Time delete_end, |
| StoragePartition::StorageKeyMatcherFunction filter, |
| BrowsingDataFilterBuilder* filter_builder, |
| bool delete_rate_limit_data, |
| base::OnceClosure done), |
| (override)); |
| |
| MOCK_METHOD(void, |
| NotifyFailedSourceRegistration, |
| (const std::string& header_value, |
| const attribution_reporting::SuitableOrigin& reporting_origin, |
| attribution_reporting::mojom::SourceRegistrationError), |
| (override)); |
| |
| void AddObserver(AttributionObserver* observer) override; |
| void RemoveObserver(AttributionObserver* observer) override; |
| AttributionDataHostManager* GetDataHostManager() override; |
| |
| void NotifySourcesChanged(); |
| void NotifyReportsChanged(AttributionReport::Type report_type); |
| void NotifySourceHandled( |
| const StorableSource& source, |
| StorableSource::Result result, |
| absl::optional<uint64_t> cleared_debug_key = absl::nullopt); |
| void NotifyReportSent(const AttributionReport& report, |
| bool is_debug_report, |
| const SendResult& info); |
| void NotifyTriggerHandled( |
| const AttributionTrigger& trigger, |
| const CreateReportResult& result, |
| absl::optional<uint64_t> cleared_debug_key = absl::nullopt); |
| void NotifySourceRegistrationFailure( |
| const std::string& header_value, |
| const attribution_reporting::SuitableOrigin& reporting_origin, |
| attribution_reporting::mojom::SourceRegistrationError); |
| void NotifyDebugReportSent(const AttributionDebugReport&, |
| int status, |
| base::Time time); |
| |
| void SetDataHostManager(std::unique_ptr<AttributionDataHostManager> manager); |
| |
| private: |
| std::unique_ptr<AttributionDataHostManager> data_host_manager_; |
| base::ObserverList<AttributionObserver, /*check_empty=*/true> observers_; |
| }; |
| |
| class MockAttributionObserver : public AttributionObserver { |
| public: |
| MockAttributionObserver(); |
| ~MockAttributionObserver() override; |
| |
| MockAttributionObserver(const MockAttributionObserver&) = delete; |
| MockAttributionObserver(MockAttributionObserver&&) = delete; |
| |
| MockAttributionObserver& operator=(const MockAttributionObserver&) = delete; |
| MockAttributionObserver& operator=(MockAttributionObserver&&) = delete; |
| |
| MOCK_METHOD(void, OnSourcesChanged, (), (override)); |
| |
| MOCK_METHOD(void, OnReportsChanged, (AttributionReport::Type), (override)); |
| |
| MOCK_METHOD(void, |
| OnSourceHandled, |
| (const StorableSource& source, |
| absl::optional<uint64_t> cleared_debug_key, |
| StorableSource::Result result), |
| (override)); |
| |
| MOCK_METHOD(void, |
| OnReportSent, |
| (const AttributionReport& report, |
| bool is_debug_report, |
| const SendResult& info), |
| (override)); |
| |
| MOCK_METHOD(void, |
| OnDebugReportSent, |
| (const AttributionDebugReport& report, |
| int status, |
| base::Time time), |
| (override)); |
| |
| MOCK_METHOD(void, |
| OnTriggerHandled, |
| (const AttributionTrigger& trigger, |
| absl::optional<uint64_t> cleared_debug_key, |
| const CreateReportResult& result), |
| (override)); |
| }; |
| |
| // WebContentsObserver that waits until a source is available on a |
| // navigation handle for a finished navigation. |
| class SourceObserver : public TestNavigationObserver { |
| public: |
| explicit SourceObserver(WebContents* contents, size_t num_impressions = 1u); |
| ~SourceObserver() override; |
| |
| // WebContentsObserver: |
| void OnDidFinishNavigation(NavigationHandle* navigation_handle) override; |
| |
| const blink::Impression& last_impression() const { return *last_impression_; } |
| |
| // Waits for |expected_num_impressions_| navigations with impressions, and |
| // returns the last impression. |
| const blink::Impression& Wait(); |
| |
| bool WaitForNavigationWithNoImpression(); |
| |
| private: |
| size_t num_impressions_ = 0u; |
| const size_t expected_num_impressions_ = 0u; |
| absl::optional<blink::Impression> last_impression_; |
| bool waiting_for_null_impression_ = false; |
| base::RunLoop impression_loop_; |
| }; |
| |
| // Helper class to construct a StorableSource for tests using default data. |
| // StorableSource members are not mutable after construction requiring a |
| // builder pattern. |
| class SourceBuilder { |
| public: |
| explicit SourceBuilder(base::Time time = base::Time::Now()); |
| ~SourceBuilder(); |
| |
| SourceBuilder(const SourceBuilder&); |
| SourceBuilder(SourceBuilder&&); |
| |
| SourceBuilder& operator=(const SourceBuilder&); |
| SourceBuilder& operator=(SourceBuilder&&); |
| |
| SourceBuilder& SetExpiry(base::TimeDelta delta); |
| |
| SourceBuilder& SetEventReportWindow(base::TimeDelta delta); |
| |
| SourceBuilder& SetAggregatableReportWindow(base::TimeDelta delta); |
| |
| SourceBuilder& SetSourceEventId(uint64_t source_event_id); |
| |
| // TODO(crbug.com/1383580): Remove this method. |
| SourceBuilder& SetSourceOrigin(url::Origin origin); |
| |
| SourceBuilder& SetSourceOrigin(attribution_reporting::SuitableOrigin); |
| |
| // TODO(crbug.com/1383580): Remove this method. |
| SourceBuilder& SetDestinationOrigin(url::Origin origin); |
| |
| SourceBuilder& SetDestinationOrigin(attribution_reporting::SuitableOrigin); |
| |
| SourceBuilder& SetDestinationOrigins( |
| base::flat_set<attribution_reporting::SuitableOrigin>); |
| |
| // TODO(crbug.com/1383580): Remove this method. |
| SourceBuilder& SetReportingOrigin(url::Origin origin); |
| |
| SourceBuilder& SetReportingOrigin(attribution_reporting::SuitableOrigin); |
| |
| SourceBuilder& SetSourceType(AttributionSourceType source_type); |
| |
| SourceBuilder& SetPriority(int64_t priority); |
| |
| SourceBuilder& SetAttributionLogic( |
| StoredSource::AttributionLogic attribution_logic); |
| |
| SourceBuilder& SetFilterData(attribution_reporting::FilterData filter_data); |
| |
| SourceBuilder& SetActiveState(StoredSource::ActiveState active_state); |
| |
| SourceBuilder& SetDebugKey(absl::optional<uint64_t> debug_key); |
| |
| SourceBuilder& SetSourceId(StoredSource::Id source_id); |
| |
| SourceBuilder& SetDedupKeys(std::vector<uint64_t> dedup_keys); |
| |
| SourceBuilder& SetAggregationKeys( |
| attribution_reporting::AggregationKeys aggregation_keys); |
| |
| SourceBuilder& SetAggregatableBudgetConsumed( |
| int64_t aggregatable_budget_consumed); |
| |
| SourceBuilder& SetAggregatableDedupKeys( |
| std::vector<uint64_t> aggregatable_dedup_keys); |
| |
| SourceBuilder& SetIsWithinFencedFrame(bool is_within_fenced_frame); |
| |
| SourceBuilder& SetDebugReporting(bool debug_reporting); |
| |
| StorableSource Build() const; |
| |
| StoredSource BuildStored() const; |
| |
| CommonSourceInfo BuildCommonInfo() const; |
| |
| private: |
| uint64_t source_event_id_ = 123; |
| base::Time source_time_; |
| base::TimeDelta expiry_; |
| absl::optional<base::TimeDelta> event_report_window_; |
| absl::optional<base::TimeDelta> aggregatable_report_window_; |
| attribution_reporting::SuitableOrigin source_origin_; |
| base::flat_set<attribution_reporting::SuitableOrigin> destination_origins_; |
| attribution_reporting::SuitableOrigin reporting_origin_; |
| AttributionSourceType source_type_ = AttributionSourceType::kNavigation; |
| int64_t priority_ = 0; |
| StoredSource::AttributionLogic attribution_logic_ = |
| StoredSource::AttributionLogic::kTruthfully; |
| attribution_reporting::FilterData filter_data_; |
| StoredSource::ActiveState active_state_ = StoredSource::ActiveState::kActive; |
| absl::optional<uint64_t> debug_key_; |
| // `base::StrongAlias` does not automatically initialize the value here. |
| // Ensure that we don't use uninitialized memory. |
| StoredSource::Id source_id_{0}; |
| std::vector<uint64_t> dedup_keys_; |
| attribution_reporting::AggregationKeys aggregation_keys_; |
| int64_t aggregatable_budget_consumed_ = 0; |
| std::vector<uint64_t> aggregatable_dedup_keys_; |
| bool is_within_fenced_frame_ = false; |
| bool debug_reporting_ = false; |
| }; |
| |
| // Returns a AttributionTrigger with default data which matches the default |
| // impressions created by SourceBuilder. |
| AttributionTrigger DefaultTrigger(); |
| |
| // Helper class to construct a AttributionTrigger for tests using default data. |
| // AttributionTrigger members are not mutable after construction requiring a |
| // builder pattern. |
| class TriggerBuilder { |
| public: |
| TriggerBuilder(); |
| ~TriggerBuilder(); |
| |
| TriggerBuilder(const TriggerBuilder&); |
| TriggerBuilder(TriggerBuilder&&); |
| |
| TriggerBuilder& operator=(const TriggerBuilder&); |
| TriggerBuilder& operator=(TriggerBuilder&&); |
| |
| TriggerBuilder& SetTriggerData(uint64_t trigger_data); |
| |
| TriggerBuilder& SetEventSourceTriggerData(uint64_t event_source_trigger_data); |
| |
| // TODO(crbug.com/1383580): Remove this method. |
| TriggerBuilder& SetDestinationOrigin(url::Origin destination_origin); |
| |
| TriggerBuilder& SetDestinationOrigin(attribution_reporting::SuitableOrigin); |
| |
| // TODO(crbug.com/1383580): Remove this method. |
| TriggerBuilder& SetReportingOrigin(url::Origin reporting_origin); |
| |
| TriggerBuilder& SetReportingOrigin(attribution_reporting::SuitableOrigin); |
| |
| TriggerBuilder& SetPriority(int64_t priority); |
| |
| TriggerBuilder& SetDedupKey(absl::optional<uint64_t> dedup_key); |
| |
| TriggerBuilder& SetDebugKey(absl::optional<uint64_t> debug_key); |
| |
| TriggerBuilder& SetAggregatableTriggerData( |
| std::vector<attribution_reporting::AggregatableTriggerData>); |
| |
| TriggerBuilder& SetAggregatableValues( |
| attribution_reporting::AggregatableValues); |
| |
| TriggerBuilder& SetAggregatableDedupKey( |
| absl::optional<uint64_t> aggregatable_dedup_key); |
| |
| TriggerBuilder& SetIsWithinFencedFrame(bool is_within_fenced_frame); |
| |
| TriggerBuilder& SetDebugReporting(bool debug_reporting); |
| |
| AttributionTrigger Build(bool generate_event_trigger_data = true) const; |
| |
| private: |
| uint64_t trigger_data_ = 111; |
| uint64_t event_source_trigger_data_ = 0; |
| attribution_reporting::SuitableOrigin destination_origin_; |
| attribution_reporting::SuitableOrigin reporting_origin_; |
| int64_t priority_ = 0; |
| absl::optional<uint64_t> dedup_key_; |
| absl::optional<uint64_t> debug_key_; |
| std::vector<attribution_reporting::AggregatableTriggerData> |
| aggregatable_trigger_data_; |
| attribution_reporting::AggregatableValues aggregatable_values_; |
| absl::optional<uint64_t> aggregatable_dedup_key_; |
| bool is_within_fenced_frame_ = false; |
| bool debug_reporting_ = false; |
| }; |
| |
| // Helper class to construct an `AttributionInfo` for tests using default data. |
| class AttributionInfoBuilder { |
| public: |
| explicit AttributionInfoBuilder(StoredSource source); |
| ~AttributionInfoBuilder(); |
| |
| AttributionInfoBuilder& SetTime(base::Time time); |
| |
| AttributionInfoBuilder& SetDebugKey(absl::optional<uint64_t> debug_key); |
| |
| AttributionInfo Build() const; |
| |
| private: |
| StoredSource source_; |
| base::Time time_; |
| absl::optional<uint64_t> debug_key_; |
| }; |
| |
| // Helper class to construct an `AttributionReport` for tests using default |
| // data. |
| class ReportBuilder { |
| public: |
| explicit ReportBuilder(AttributionInfo attribution_info); |
| ~ReportBuilder(); |
| |
| ReportBuilder& SetTriggerData(uint64_t trigger_data); |
| |
| ReportBuilder& SetReportTime(base::Time time); |
| |
| ReportBuilder& SetPriority(int64_t priority); |
| |
| ReportBuilder& SetExternalReportId(base::GUID external_report_id); |
| |
| ReportBuilder& SetRandomizedTriggerRate(double rate); |
| |
| ReportBuilder& SetReportId(AttributionReport::EventLevelData::Id id); |
| |
| ReportBuilder& SetReportId( |
| AttributionReport::AggregatableAttributionData::Id id); |
| |
| ReportBuilder& SetAggregatableHistogramContributions( |
| std::vector<AggregatableHistogramContribution> contributions); |
| |
| AttributionReport Build() const; |
| |
| AttributionReport BuildAggregatableAttribution() const; |
| |
| private: |
| AttributionInfo attribution_info_; |
| uint64_t trigger_data_ = 0; |
| base::Time report_time_; |
| int64_t priority_ = 0; |
| base::GUID external_report_id_; |
| double randomized_trigger_rate_ = 0; |
| AttributionReport::EventLevelData::Id report_id_{0}; |
| AttributionReport::AggregatableAttributionData::Id |
| aggregatable_attribution_report_id_{0}; |
| std::vector<AggregatableHistogramContribution> contributions_; |
| }; |
| |
| bool operator==(const AttributionTrigger& a, const AttributionTrigger& b); |
| |
| bool operator==(const CommonSourceInfo& a, const CommonSourceInfo& b); |
| |
| bool operator==(const AttributionInfo& a, const AttributionInfo& b); |
| |
| bool operator==(const AttributionStorageDelegate::FakeReport& a, |
| const AttributionStorageDelegate::FakeReport& b); |
| |
| bool operator<(const AttributionStorageDelegate::FakeReport& a, |
| const AttributionStorageDelegate::FakeReport& b); |
| |
| bool operator==(const StorableSource& a, const StorableSource& b); |
| |
| bool operator==(const StoredSource& a, const StoredSource& b); |
| |
| bool operator==(const AggregatableHistogramContribution& a, |
| const AggregatableHistogramContribution& b); |
| |
| bool operator==(const AttributionReport::EventLevelData& a, |
| const AttributionReport::EventLevelData& b); |
| |
| bool operator==(const AttributionReport::AggregatableAttributionData& a, |
| const AttributionReport::AggregatableAttributionData& b); |
| |
| bool operator==(const AttributionReport& a, const AttributionReport& b); |
| |
| bool operator==(const SendResult& a, const SendResult& b); |
| |
| std::ostream& operator<<(std::ostream& out, |
| AttributionTrigger::EventLevelResult status); |
| |
| std::ostream& operator<<(std::ostream& out, |
| AttributionTrigger::AggregatableResult status); |
| |
| std::ostream& operator<<(std::ostream& out, RateLimitResult result); |
| |
| std::ostream& operator<<(std::ostream& out, |
| const AttributionTrigger& conversion); |
| |
| std::ostream& operator<<(std::ostream& out, const CommonSourceInfo& source); |
| |
| std::ostream& operator<<(std::ostream& out, |
| const AttributionInfo& attribution_info); |
| |
| std::ostream& operator<<(std::ostream& out, |
| const AttributionStorageDelegate::FakeReport&); |
| |
| std::ostream& operator<<(std::ostream& out, const StorableSource& source); |
| |
| std::ostream& operator<<(std::ostream& out, const StoredSource& source); |
| |
| std::ostream& operator<<(std::ostream& out, |
| const AggregatableHistogramContribution& contribution); |
| |
| std::ostream& operator<<(std::ostream& out, |
| const AttributionReport::EventLevelData& data); |
| |
| std::ostream& operator<<( |
| std::ostream& out, |
| const AttributionReport::AggregatableAttributionData& data); |
| |
| std::ostream& operator<<(std::ostream& out, const AttributionReport& report); |
| |
| std::ostream& operator<<(std::ostream& out, |
| AttributionReport::Type report_type); |
| |
| std::ostream& operator<<(std::ostream& out, SendResult::Status status); |
| |
| std::ostream& operator<<(std::ostream& out, const SendResult& info); |
| |
| std::ostream& operator<<(std::ostream& out, |
| StoredSource::AttributionLogic attribution_logic); |
| |
| std::ostream& operator<<(std::ostream& out, |
| StoredSource::ActiveState active_state); |
| |
| std::ostream& operator<<(std::ostream& out, StorableSource::Result status); |
| |
| std::vector<AttributionReport> GetAttributionReportsForTesting( |
| AttributionManager* manager); |
| |
| std::unique_ptr<MockDataHost> GetRegisteredDataHost( |
| mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host); |
| |
| // Source matchers |
| |
| MATCHER_P(CommonSourceInfoIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info(), result_listener); |
| } |
| |
| MATCHER_P(SourceEventIdIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info().source_event_id(), |
| result_listener); |
| } |
| |
| MATCHER_P(ImpressionOriginIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info().source_origin(), |
| result_listener); |
| } |
| |
| MATCHER_P(DestinationOriginIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info().destination_origin(), |
| result_listener); |
| } |
| |
| MATCHER_P(SourceTypeIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info().source_type(), |
| result_listener); |
| } |
| |
| MATCHER_P(SourcePriorityIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info().priority(), |
| result_listener); |
| } |
| |
| MATCHER_P(SourceDebugKeyIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info().debug_key(), |
| result_listener); |
| } |
| |
| MATCHER_P(SourceFilterDataIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info().filter_data(), |
| result_listener); |
| } |
| |
| MATCHER_P(DedupKeysAre, matcher, "") { |
| return ExplainMatchResult(matcher, arg.dedup_keys(), result_listener); |
| } |
| |
| MATCHER_P(AggregatableDedupKeysAre, matcher, "") { |
| return ExplainMatchResult(matcher, arg.aggregatable_dedup_keys(), |
| result_listener); |
| } |
| |
| MATCHER_P(AggregationKeysAre, matcher, "") { |
| return ExplainMatchResult(matcher, arg.common_info().aggregation_keys(), |
| result_listener); |
| } |
| |
| MATCHER_P(AggregatableBudgetConsumedIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.aggregatable_budget_consumed(), |
| result_listener); |
| } |
| |
| MATCHER_P(SourceActiveStateIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.active_state(), result_listener); |
| } |
| |
| // Trigger matchers. |
| |
| MATCHER_P(TriggerDestinationOriginIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.destination_origin(), result_listener); |
| } |
| |
| // Report matchers |
| |
| MATCHER_P(ReportSourceIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.attribution_info().source, |
| result_listener); |
| } |
| |
| MATCHER_P(ReportTimeIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.report_time(), result_listener); |
| } |
| |
| MATCHER_P(FailedSendAttemptsIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.failed_send_attempts(), |
| result_listener); |
| } |
| |
| MATCHER_P(TriggerDebugKeyIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.attribution_info().debug_key, |
| result_listener); |
| } |
| |
| MATCHER_P(EventLevelDataIs, matcher, "") { |
| return ExplainMatchResult( |
| ::testing::VariantWith<AttributionReport::EventLevelData>(matcher), |
| arg.data(), result_listener); |
| } |
| |
| MATCHER_P(TriggerDataIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.trigger_data, result_listener); |
| } |
| |
| MATCHER_P(TriggerPriorityIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.priority, result_listener); |
| } |
| |
| MATCHER_P(RandomizedTriggerRateIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.randomized_trigger_rate, |
| result_listener); |
| } |
| |
| MATCHER_P(ReportURLIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.ReportURL(), result_listener); |
| } |
| |
| MATCHER_P(ReportTypeIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.GetReportType(), result_listener); |
| } |
| |
| MATCHER_P(AggregatableAttributionDataIs, matcher, "") { |
| return ExplainMatchResult( |
| ::testing::VariantWith<AttributionReport::AggregatableAttributionData>( |
| matcher), |
| arg.data(), result_listener); |
| } |
| |
| MATCHER_P(AggregatableHistogramContributionsAre, matcher, "") { |
| return ExplainMatchResult(matcher, arg.contributions, result_listener); |
| } |
| |
| MATCHER_P(InitialReportTimeIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.initial_report_time, result_listener); |
| } |
| |
| // `CreateReportResult` matchers |
| |
| MATCHER_P(CreateReportEventLevelStatusIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.event_level_status(), result_listener); |
| } |
| |
| MATCHER_P(CreateReportAggregatableStatusIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.aggregatable_status(), |
| result_listener); |
| } |
| |
| MATCHER_P(ReplacedEventLevelReportIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.replaced_event_level_report(), |
| result_listener); |
| } |
| |
| MATCHER_P(DeactivatedSourceIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.GetDeactivatedSource(), |
| result_listener); |
| } |
| |
| MATCHER_P(NewEventLevelReportIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.new_event_level_report(), |
| result_listener); |
| } |
| |
| MATCHER_P(NewAggregatableReportIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.new_aggregatable_report(), |
| result_listener); |
| } |
| |
| MATCHER_P(DroppedEventLevelReportIs, matcher, "") { |
| return ExplainMatchResult(matcher, arg.dropped_event_level_report(), |
| result_listener); |
| } |
| |
| struct EventTriggerDataMatcherConfig { |
| ::testing::Matcher<uint64_t> data; |
| ::testing::Matcher<int64_t> priority; |
| ::testing::Matcher<absl::optional<uint64_t>> dedup_key; |
| ::testing::Matcher<const attribution_reporting::Filters&> filters; |
| ::testing::Matcher<const attribution_reporting::Filters&> not_filters; |
| |
| EventTriggerDataMatcherConfig() = delete; |
| explicit EventTriggerDataMatcherConfig( |
| ::testing::Matcher<uint64_t> data = ::testing::_, |
| ::testing::Matcher<int64_t> priority = ::testing::_, |
| ::testing::Matcher<absl::optional<uint64_t>> dedup_key = ::testing::_, |
| ::testing::Matcher<const attribution_reporting::Filters&> filters = |
| ::testing::_, |
| ::testing::Matcher<const attribution_reporting::Filters&> not_filters = |
| ::testing::_); |
| ~EventTriggerDataMatcherConfig(); |
| }; |
| |
| ::testing::Matcher<const attribution_reporting::EventTriggerData&> |
| EventTriggerDataMatches(const EventTriggerDataMatcherConfig&); |
| |
| template <typename T> |
| struct BoundedListMatcherConfig { |
| ::testing::Matcher<const std::vector<T>&> vec = ::testing::_; |
| |
| BoundedListMatcherConfig() = delete; |
| explicit BoundedListMatcherConfig( |
| ::testing::Matcher<const std::vector<T>&> vec = ::testing::_) |
| : vec(std::move(vec)) {} |
| |
| ~BoundedListMatcherConfig() = default; |
| }; |
| |
| template <typename T, size_t kMaxSize> |
| ::testing::Matcher<const attribution_reporting::BoundedList<T, kMaxSize>&> |
| BoundedListMatches(const BoundedListMatcherConfig<T>& cfg) { |
| return Property("vec", &attribution_reporting::BoundedList<T, kMaxSize>::vec, |
| cfg.vec); |
| } |
| |
| using EventTriggerDataListMatcherConfig = |
| BoundedListMatcherConfig<attribution_reporting::EventTriggerData>; |
| |
| constexpr auto EventTriggerDataListMatches = |
| BoundedListMatches<attribution_reporting::EventTriggerData, |
| attribution_reporting::kMaxEventTriggerData>; |
| |
| struct TriggerRegistrationMatcherConfig { |
| ::testing::Matcher<const attribution_reporting::SuitableOrigin&> |
| reporting_origin = ::testing::_; |
| ::testing::Matcher<const attribution_reporting::Filters&> filters = |
| ::testing::_; |
| ::testing::Matcher<absl::optional<uint64_t>> debug_key = ::testing::_; |
| ::testing::Matcher<const attribution_reporting::EventTriggerDataList&> |
| event_triggers = ::testing::_; |
| ::testing::Matcher<absl::optional<uint64_t>> aggregatable_dedup_key = |
| ::testing::_; |
| ::testing::Matcher<bool> debug_reporting = ::testing::_; |
| |
| TriggerRegistrationMatcherConfig() = delete; |
| explicit TriggerRegistrationMatcherConfig( |
| ::testing::Matcher<const attribution_reporting::SuitableOrigin&> |
| reporting_origin = ::testing::_, |
| ::testing::Matcher<const attribution_reporting::Filters&> filters = |
| ::testing::_, |
| ::testing::Matcher<absl::optional<uint64_t>> debug_key = ::testing::_, |
| ::testing::Matcher<const attribution_reporting::EventTriggerDataList&> |
| event_triggers = ::testing::_, |
| ::testing::Matcher<absl::optional<uint64_t>> aggregatable_dedup_key = |
| ::testing::_, |
| ::testing::Matcher<bool> debug_reporting = ::testing::_); |
| ~TriggerRegistrationMatcherConfig(); |
| }; |
| |
| ::testing::Matcher<const attribution_reporting::TriggerRegistration&> |
| TriggerRegistrationMatches(const TriggerRegistrationMatcherConfig&); |
| |
| struct AttributionTriggerMatcherConfig { |
| ::testing::Matcher<const attribution_reporting::TriggerRegistration&> |
| registration = ::testing::_; |
| ::testing::Matcher<const attribution_reporting::SuitableOrigin&> |
| destination_origin = ::testing::_; |
| |
| ::testing::Matcher<bool> is_within_fenced_frame = ::testing::_; |
| |
| AttributionTriggerMatcherConfig() = delete; |
| explicit AttributionTriggerMatcherConfig( |
| ::testing::Matcher<const attribution_reporting::TriggerRegistration&> |
| registration = ::testing::_, |
| ::testing::Matcher<const attribution_reporting::SuitableOrigin&> |
| destination_origin = ::testing::_, |
| ::testing::Matcher<bool> is_within_fenced_frame = ::testing::_); |
| ~AttributionTriggerMatcherConfig(); |
| }; |
| |
| ::testing::Matcher<AttributionTrigger> AttributionTriggerMatches( |
| const AttributionTriggerMatcherConfig&); |
| |
| class TestAggregatableSourceProvider { |
| public: |
| explicit TestAggregatableSourceProvider(size_t size = 1); |
| ~TestAggregatableSourceProvider(); |
| |
| SourceBuilder GetBuilder(base::Time source_time = base::Time::Now()) const; |
| |
| private: |
| attribution_reporting::AggregationKeys source_; |
| }; |
| |
| TriggerBuilder DefaultAggregatableTriggerBuilder( |
| const std::vector<uint32_t>& histogram_values = {1}); |
| |
| std::vector<AggregatableHistogramContribution> |
| DefaultAggregatableHistogramContributions( |
| const std::vector<uint32_t>& histogram_values = {1}); |
| |
| // Returns filters that match only the given source type. |
| attribution_reporting::Filters AttributionFiltersForSourceType( |
| AttributionSourceType); |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_TEST_UTILS_H_ |