blob: 9680686c191ec34ccf10e7ce3f935086b97c591f [file] [log] [blame]
// Copyright 2020 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 "content/browser/attribution_reporting/attribution_test_utils.h"
#include <limits.h>
#include <algorithm>
#include <tuple>
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/task_runner_util.h"
#include "base/test/bind.h"
#include "content/browser/attribution_reporting/rate_limit_result.h"
#include "url/gurl.h"
namespace content {
namespace {
using DeactivatedSource = ::content::AttributionStorage::DeactivatedSource;
const char kDefaultImpressionOrigin[] = "https://impression.test/";
const char kDefaultTriggerOrigin[] = "https://sub.conversion.test/";
const char kDefaultTriggerDestination[] = "https://conversion.test/";
const char kDefaultReportOrigin[] = "https://report.test/";
// Default expiry time for impressions for testing.
const int64_t kExpiryTime = 30;
} // namespace
MockAttributionReportingContentBrowserClient::
MockAttributionReportingContentBrowserClient() = default;
MockAttributionReportingContentBrowserClient::
~MockAttributionReportingContentBrowserClient() = default;
MockAttributionHost::MockAttributionHost(WebContents* web_contents)
: AttributionHost(web_contents) {
SetReceiverImplForTesting(this);
}
MockAttributionHost::~MockAttributionHost() {
SetReceiverImplForTesting(nullptr);
}
MockDataHost::MockDataHost(
mojo::PendingReceiver<blink::mojom::AttributionDataHost> data_host) {
receiver_.Bind(std::move(data_host));
}
MockDataHost::~MockDataHost() = default;
void MockDataHost::WaitForSourceData(size_t num_source_data) {
min_source_data_count_ = num_source_data;
if (source_data_.size() >= min_source_data_count_) {
return;
}
wait_loop_.Run();
}
void MockDataHost::SourceDataAvailable(
blink::mojom::AttributionSourceDataPtr data) {
source_data_.push_back(std::move(data));
if (source_data_.size() < min_source_data_count_) {
return;
}
wait_loop_.Quit();
}
MockDataHostManager::MockDataHostManager() = default;
MockDataHostManager::~MockDataHostManager() = default;
base::GUID DefaultExternalReportID() {
return base::GUID::ParseLowercase("21abd97f-73e8-4b88-9389-a9fee6abda5e");
}
ConfigurableStorageDelegate::ConfigurableStorageDelegate() = default;
ConfigurableStorageDelegate::~ConfigurableStorageDelegate() = default;
base::Time ConfigurableStorageDelegate::GetReportTime(
const CommonSourceInfo& source,
base::Time trigger_time) const {
return source.impression_time() + report_delay_;
}
int ConfigurableStorageDelegate::GetMaxAttributionsPerSource(
CommonSourceInfo::SourceType source_type) const {
return max_attributions_per_source_;
}
int ConfigurableStorageDelegate::GetMaxSourcesPerOrigin() const {
return max_sources_per_origin_;
}
int ConfigurableStorageDelegate::GetMaxAttributionsPerOrigin() const {
return max_attributions_per_origin_;
}
int ConfigurableStorageDelegate::
GetMaxDestinationsPerSourceSiteReportingOrigin() const {
return max_destinations_per_source_site_reporting_origin_;
}
AttributionStorageDelegate::RateLimitConfig
ConfigurableStorageDelegate::GetRateLimits() const {
return rate_limits_;
}
base::TimeDelta ConfigurableStorageDelegate::GetDeleteExpiredSourcesFrequency()
const {
return delete_expired_sources_frequency_;
}
base::TimeDelta
ConfigurableStorageDelegate::GetDeleteExpiredRateLimitsFrequency() const {
return delete_expired_rate_limits_frequency_;
}
base::GUID ConfigurableStorageDelegate::NewReportID() const {
return DefaultExternalReportID();
}
absl::optional<AttributionStorageDelegate::OfflineReportDelayConfig>
ConfigurableStorageDelegate::GetOfflineReportDelayConfig() const {
return offline_report_delay_config_;
}
void ConfigurableStorageDelegate::ShuffleReports(
std::vector<AttributionReport>& reports) const {
if (reverse_reports_on_shuffle_)
base::ranges::reverse(reports);
}
double ConfigurableStorageDelegate::GetRandomizedResponseRate(
CommonSourceInfo::SourceType source_type) const {
switch (source_type) {
case CommonSourceInfo::SourceType::kNavigation:
return randomized_response_rates_.navigation;
case CommonSourceInfo::SourceType::kEvent:
return randomized_response_rates_.event;
}
}
AttributionStorageDelegate::RandomizedResponse
ConfigurableStorageDelegate::GetRandomizedResponse(
const CommonSourceInfo& source) const {
return randomized_response_;
}
int64_t ConfigurableStorageDelegate::GetAggregatableBudgetPerSource() const {
return aggregatable_budget_per_source_;
}
AttributionManager* TestManagerProvider::GetManager(
WebContents* web_contents) const {
return manager_;
}
MockAttributionManager::MockAttributionManager() = default;
MockAttributionManager::~MockAttributionManager() = default;
void MockAttributionManager::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void MockAttributionManager::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
AttributionDataHostManager* MockAttributionManager::GetDataHostManager() {
return data_host_manager_.get();
}
void MockAttributionManager::NotifySourcesChanged() {
for (Observer& observer : observers_)
observer.OnSourcesChanged();
}
void MockAttributionManager::NotifyReportsChanged() {
for (Observer& observer : observers_)
observer.OnReportsChanged();
}
void MockAttributionManager::NotifySourceDeactivated(
const DeactivatedSource& source) {
for (Observer& observer : observers_)
observer.OnSourceDeactivated(source);
}
void MockAttributionManager::NotifySourceHandled(
const StorableSource& source,
StorableSource::Result result) {
for (Observer& observer : observers_)
observer.OnSourceHandled(source, result);
}
void MockAttributionManager::NotifyReportSent(const AttributionReport& report,
const SendResult& info) {
for (Observer& observer : observers_)
observer.OnReportSent(report, info);
}
void MockAttributionManager::NotifyTriggerHandled(
const AttributionStorage::CreateReportResult& result) {
for (Observer& observer : observers_)
observer.OnTriggerHandled(result);
}
void MockAttributionManager::SetDataHostManager(
std::unique_ptr<AttributionDataHostManager> manager) {
data_host_manager_ = std::move(manager);
}
// Builds an impression with default values. This is done as a builder because
// all values needed to be provided at construction time.
SourceBuilder::SourceBuilder(base::Time time)
: impression_time_(time),
expiry_(base::Milliseconds(kExpiryTime)),
impression_origin_(url::Origin::Create(GURL(kDefaultImpressionOrigin))),
conversion_origin_(url::Origin::Create(GURL(kDefaultTriggerOrigin))),
reporting_origin_(url::Origin::Create(GURL(kDefaultReportOrigin))) {}
SourceBuilder::~SourceBuilder() = default;
SourceBuilder::SourceBuilder(const SourceBuilder&) = default;
SourceBuilder::SourceBuilder(SourceBuilder&&) = default;
SourceBuilder& SourceBuilder::operator=(const SourceBuilder&) = default;
SourceBuilder& SourceBuilder::operator=(SourceBuilder&&) = default;
SourceBuilder& SourceBuilder::SetExpiry(base::TimeDelta delta) {
expiry_ = delta;
return *this;
}
SourceBuilder& SourceBuilder::SetSourceEventId(uint64_t source_event_id) {
source_event_id_ = source_event_id;
return *this;
}
SourceBuilder& SourceBuilder::SetImpressionOrigin(url::Origin origin) {
impression_origin_ = std::move(origin);
return *this;
}
SourceBuilder& SourceBuilder::SetConversionOrigin(url::Origin origin) {
conversion_origin_ = std::move(origin);
return *this;
}
SourceBuilder& SourceBuilder::SetReportingOrigin(url::Origin origin) {
reporting_origin_ = std::move(origin);
return *this;
}
SourceBuilder& SourceBuilder::SetSourceType(
CommonSourceInfo::SourceType source_type) {
source_type_ = source_type;
return *this;
}
SourceBuilder& SourceBuilder::SetPriority(int64_t priority) {
priority_ = priority;
return *this;
}
SourceBuilder& SourceBuilder::SetDebugKey(absl::optional<uint64_t> debug_key) {
debug_key_ = debug_key;
return *this;
}
SourceBuilder& SourceBuilder::SetAttributionLogic(
StoredSource::AttributionLogic attribution_logic) {
attribution_logic_ = attribution_logic;
return *this;
}
SourceBuilder& SourceBuilder::SetSourceId(StoredSource::Id source_id) {
source_id_ = source_id;
return *this;
}
SourceBuilder& SourceBuilder::SetDedupKeys(std::vector<uint64_t> dedup_keys) {
dedup_keys_ = std::move(dedup_keys);
return *this;
}
CommonSourceInfo SourceBuilder::BuildCommonInfo() const {
return CommonSourceInfo(source_event_id_, impression_origin_,
conversion_origin_, reporting_origin_,
impression_time_,
/*expiry_time=*/impression_time_ + expiry_,
source_type_, priority_, debug_key_);
}
StorableSource SourceBuilder::Build() const {
return StorableSource(BuildCommonInfo());
}
StoredSource SourceBuilder::BuildStored() const {
StoredSource source(BuildCommonInfo(), attribution_logic_, source_id_);
source.SetDedupKeys(dedup_keys_);
return source;
}
AttributionTrigger DefaultTrigger() {
return TriggerBuilder().Build();
}
TriggerBuilder::TriggerBuilder()
: conversion_destination_(
net::SchemefulSite(GURL(kDefaultTriggerDestination))),
reporting_origin_(url::Origin::Create(GURL(kDefaultReportOrigin))) {}
TriggerBuilder::~TriggerBuilder() = default;
TriggerBuilder& TriggerBuilder::SetTriggerData(uint64_t trigger_data) {
trigger_data_ = trigger_data;
return *this;
}
TriggerBuilder& TriggerBuilder::SetEventSourceTriggerData(
uint64_t event_source_trigger_data) {
event_source_trigger_data_ = event_source_trigger_data;
return *this;
}
TriggerBuilder& TriggerBuilder::SetConversionDestination(
net::SchemefulSite conversion_destination) {
conversion_destination_ = std::move(conversion_destination);
return *this;
}
TriggerBuilder& TriggerBuilder::SetReportingOrigin(
url::Origin reporting_origin) {
reporting_origin_ = std::move(reporting_origin);
return *this;
}
TriggerBuilder& TriggerBuilder::SetPriority(int64_t priority) {
priority_ = priority;
return *this;
}
TriggerBuilder& TriggerBuilder::SetDedupKey(
absl::optional<uint64_t> dedup_key) {
dedup_key_ = dedup_key;
return *this;
}
TriggerBuilder& TriggerBuilder::SetDebugKey(
absl::optional<uint64_t> debug_key) {
debug_key_ = debug_key;
return *this;
}
AttributionTrigger TriggerBuilder::Build() const {
return AttributionTrigger(trigger_data_, conversion_destination_,
reporting_origin_, event_source_trigger_data_,
priority_, dedup_key_, debug_key_);
}
AttributionInfoBuilder::AttributionInfoBuilder(StoredSource source)
: source_(std::move(source)) {}
AttributionInfoBuilder::~AttributionInfoBuilder() = default;
AttributionInfoBuilder& AttributionInfoBuilder::SetTime(base::Time time) {
time_ = time;
return *this;
}
AttributionInfoBuilder& AttributionInfoBuilder::SetDebugKey(
absl::optional<uint64_t> debug_key) {
debug_key_ = debug_key;
return *this;
}
AttributionInfo AttributionInfoBuilder::Build() const {
return AttributionInfo(source_, time_, debug_key_);
}
ReportBuilder::ReportBuilder(AttributionInfo attribution_info)
: attribution_info_(std::move(attribution_info)),
external_report_id_(DefaultExternalReportID()) {}
ReportBuilder::~ReportBuilder() = default;
ReportBuilder& ReportBuilder::SetTriggerData(uint64_t trigger_data) {
trigger_data_ = trigger_data;
return *this;
}
ReportBuilder& ReportBuilder::SetReportTime(base::Time time) {
report_time_ = time;
return *this;
}
ReportBuilder& ReportBuilder::SetPriority(int64_t priority) {
priority_ = priority;
return *this;
}
ReportBuilder& ReportBuilder::SetExternalReportId(
base::GUID external_report_id) {
external_report_id_ = std::move(external_report_id);
return *this;
}
ReportBuilder& ReportBuilder::SetRandomizedTriggerRate(double rate) {
randomized_trigger_rate_ = rate;
return *this;
}
ReportBuilder& ReportBuilder::SetReportId(
absl::optional<AttributionReport::EventLevelData::Id> id) {
report_id_ = id;
return *this;
}
AttributionReport ReportBuilder::Build() const {
return AttributionReport(
attribution_info_, report_time_, external_report_id_,
AttributionReport::EventLevelData(trigger_data_, priority_,
randomized_trigger_rate_, report_id_));
}
bool operator==(const AttributionTrigger& a, const AttributionTrigger& b) {
const auto tie = [](const AttributionTrigger& t) {
return std::make_tuple(t.trigger_data(), t.conversion_destination(),
t.reporting_origin(), t.event_source_trigger_data(),
t.priority(), t.dedup_key());
};
return tie(a) == tie(b);
}
bool operator==(const CommonSourceInfo& a, const CommonSourceInfo& b) {
const auto tie = [](const CommonSourceInfo& source) {
return std::make_tuple(source.source_event_id(), source.impression_origin(),
source.conversion_origin(),
source.reporting_origin(), source.impression_time(),
source.expiry_time(), source.source_type(),
source.priority(), source.debug_key());
};
return tie(a) == tie(b);
}
bool operator==(const AttributionInfo& a, const AttributionInfo& b) {
const auto tie = [](const AttributionInfo& attribution_info) {
return std::make_tuple(attribution_info.source, attribution_info.time,
attribution_info.debug_key);
};
return tie(a) == tie(b);
}
bool operator==(const AttributionStorageDelegate::FakeReport& a,
const AttributionStorageDelegate::FakeReport& b) {
const auto tie = [](const AttributionStorageDelegate::FakeReport& r) {
return std::make_tuple(r.trigger_data, r.report_time);
};
return tie(a) == tie(b);
}
bool operator<(const AttributionStorageDelegate::FakeReport& a,
const AttributionStorageDelegate::FakeReport& b) {
const auto tie = [](const AttributionStorageDelegate::FakeReport& r) {
return std::make_tuple(r.trigger_data, r.report_time);
};
return tie(a) < tie(b);
}
bool operator==(const StorableSource& a, const StorableSource& b) {
const auto tie = [](const StorableSource& source) {
return std::make_tuple(source.common_info());
};
return tie(a) == tie(b);
}
// Does not compare source IDs, as they are set by the underlying sqlite DB and
// should not be tested.
bool operator==(const StoredSource& a, const StoredSource& b) {
const auto tie = [](const StoredSource& source) {
return std::make_tuple(source.common_info(), source.attribution_logic(),
source.dedup_keys());
};
return tie(a) == tie(b);
}
bool operator==(const AggregatableHistogramContribution& a,
const AggregatableHistogramContribution& b) {
const auto tie = [](const AggregatableHistogramContribution& contribution) {
return std::make_tuple(contribution.bucket(), contribution.value());
};
return tie(a) == tie(b);
}
bool operator==(const AggregatableAttribution& a, AggregatableAttribution& b) {
const auto tie = [](const AggregatableAttribution& aggregatable_attribution) {
return std::make_tuple(aggregatable_attribution.source_id,
aggregatable_attribution.trigger_time,
aggregatable_attribution.report_time,
aggregatable_attribution.contributions);
};
return tie(a) == tie(b);
}
// Does not compare ID as it is set by the underlying sqlite db and
// should not be tested.
bool operator==(const AttributionReport::EventLevelData& a,
const AttributionReport::EventLevelData& b) {
const auto tie = [](const AttributionReport::EventLevelData& data) {
return std::make_tuple(data.trigger_data, data.priority,
data.randomized_trigger_rate);
};
return tie(a) == tie(b);
}
// Does not compare ID as it is set by the underlying sqlite db and
// should not be tested.
bool operator==(const AttributionReport::AggregatableContributionData& a,
const AttributionReport::AggregatableContributionData& b) {
return a.contribution == b.contribution;
}
// Does not compare source or report IDs, as they are set by the underlying
// sqlite DB and should not be tested.
bool operator==(const AttributionReport& a, const AttributionReport& b) {
const auto tie = [](const AttributionReport& report) {
return std::make_tuple(report.attribution_info(), report.report_time(),
report.external_report_id(),
report.failed_send_attempts(), report.data());
};
return tie(a) == tie(b);
}
bool operator==(const SendResult& a, const SendResult& b) {
const auto tie = [](const SendResult& info) {
return std::make_tuple(info.status, info.http_response_code);
};
return tie(a) == tie(b);
}
bool operator==(const DeactivatedSource& a, const DeactivatedSource& b) {
const auto tie = [](const DeactivatedSource& deactivated_source) {
return std::make_tuple(deactivated_source.source,
deactivated_source.reason);
};
return tie(a) == tie(b);
}
std::ostream& operator<<(std::ostream& out, AttributionTrigger::Result status) {
switch (status) {
case AttributionTrigger::Result::kSuccess:
out << "success";
break;
case AttributionTrigger::Result::kSuccessDroppedLowerPriority:
out << "successDroppedLowerPriority";
break;
case AttributionTrigger::Result::kInternalError:
out << "internalError";
break;
case AttributionTrigger::Result::kNoCapacityForConversionDestination:
out << "insufficientDestinationCapacity";
break;
case AttributionTrigger::Result::kNoMatchingImpressions:
out << "noMatchingSources";
break;
case AttributionTrigger::Result::kDeduplicated:
out << "deduplicated";
break;
case AttributionTrigger::Result::kExcessiveAttributions:
out << "excessiveAttributions";
break;
case AttributionTrigger::Result::kPriorityTooLow:
out << "priorityTooLow";
break;
case AttributionTrigger::Result::kDroppedForNoise:
out << "noised";
break;
case AttributionTrigger::Result::kExcessiveReportingOrigins:
out << "excessiveReportingOrigins";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out, DeactivatedSource::Reason reason) {
switch (reason) {
case DeactivatedSource::Reason::kReplacedByNewerSource:
out << "kReplacedByNewerSource";
break;
case DeactivatedSource::Reason::kReachedAttributionLimit:
out << "kReachedAttributionLimit";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out, RateLimitResult result) {
switch (result) {
case RateLimitResult::kAllowed:
out << "kAllowed";
break;
case RateLimitResult::kNotAllowed:
out << "kNotAllowed";
break;
case RateLimitResult::kError:
out << "kError";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out,
CommonSourceInfo::SourceType source_type) {
switch (source_type) {
case CommonSourceInfo::SourceType::kNavigation:
out << "kNavigation";
break;
case CommonSourceInfo::SourceType::kEvent:
out << "kEvent";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out,
StoredSource::AttributionLogic attribution_logic) {
switch (attribution_logic) {
case StoredSource::AttributionLogic::kNever:
out << "kNever";
break;
case StoredSource::AttributionLogic::kTruthfully:
out << "kTruthfully";
break;
case StoredSource::AttributionLogic::kFalsely:
out << "kFalsely";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out,
const AttributionTrigger& conversion) {
return out << "{trigger_data=" << conversion.trigger_data()
<< ",conversion_destination="
<< conversion.conversion_destination().Serialize()
<< ",reporting_origin=" << conversion.reporting_origin()
<< ",event_source_trigger_data="
<< conversion.event_source_trigger_data()
<< ",priority=" << conversion.priority() << ",dedup_key="
<< (conversion.dedup_key()
? base::NumberToString(*conversion.dedup_key())
: "null")
<< ",debug_key="
<< (conversion.debug_key()
? base::NumberToString(*conversion.debug_key())
: "null")
<< "}";
}
std::ostream& operator<<(std::ostream& out, const CommonSourceInfo& source) {
return out << "{source_event_id=" << source.source_event_id()
<< ",impression_origin=" << source.impression_origin()
<< ",conversion_origin=" << source.conversion_origin()
<< ",reporting_origin=" << source.reporting_origin()
<< ",impression_time=" << source.impression_time()
<< ",expiry_time=" << source.expiry_time()
<< ",source_type=" << source.source_type()
<< ",priority=" << source.priority() << ",debug_key="
<< (source.debug_key() ? base::NumberToString(*source.debug_key())
: "null")
<< "}";
}
std::ostream& operator<<(std::ostream& out,
const AttributionInfo& attribution_info) {
return out << "{source=" << attribution_info.source
<< ",time=" << attribution_info.time << ",debug_key="
<< (attribution_info.debug_key
? base::NumberToString(*attribution_info.debug_key)
: "null")
<< "}";
}
std::ostream& operator<<(std::ostream& out,
const AttributionStorageDelegate::FakeReport& r) {
return out << "{trigger_data=" << r.trigger_data
<< ",report_time=" << r.report_time << "}";
}
std::ostream& operator<<(std::ostream& out, const StorableSource& source) {
return out << "{common_info=" << source.common_info() << "}";
}
std::ostream& operator<<(std::ostream& out, const StoredSource& source) {
out << "{common_info=" << source.common_info()
<< ",attribution_logic=" << source.attribution_logic()
<< ",source_id=" << *source.source_id() << ",dedup_keys=[";
const char* separator = "";
for (int64_t dedup_key : source.dedup_keys()) {
out << separator << dedup_key;
separator = ", ";
}
return out << "]}";
}
std::ostream& operator<<(
std::ostream& out,
const AggregatableHistogramContribution& contribution) {
return out << "{bucket=" << contribution.bucket()
<< ",value=" << contribution.value() << "}";
}
std::ostream& operator<<(
std::ostream& out,
const AggregatableAttribution& aggregatable_attribution) {
out << "{source_id=" << aggregatable_attribution.source_id
<< ",trigger_time=" << aggregatable_attribution.trigger_time
<< ",report_time=" << aggregatable_attribution.report_time
<< ",contributions=[";
const char* separator = "";
for (const AggregatableHistogramContribution& contribution :
aggregatable_attribution.contributions) {
out << separator << contribution;
separator = ", ";
}
return out << "]}";
}
std::ostream& operator<<(std::ostream& out,
const AttributionReport::EventLevelData& data) {
return out << "{trigger_data=" << data.trigger_data
<< ",priority=" << data.priority
<< ",randomized_trigger_rate=" << data.randomized_trigger_rate
<< ",id=" << (data.id ? base::NumberToString(**data.id) : "null")
<< "}";
}
std::ostream& operator<<(
std::ostream& out,
const AttributionReport::AggregatableContributionData& data) {
return out << "{contribution=" << data.contribution
<< ",id=" << (data.id ? base::NumberToString(**data.id) : "null")
<< "}";
}
namespace {
std::ostream& operator<<(
std::ostream& out,
const absl::variant<AttributionReport::EventLevelData,
AttributionReport::AggregatableContributionData>&
data) {
absl::visit([&out](const auto& v) { out << v; }, data);
return out;
}
} // namespace
std::ostream& operator<<(std::ostream& out, const AttributionReport& report) {
out << "{attribution_info=" << report.attribution_info()
<< ",report_time=" << report.report_time()
<< ",external_report_id=" << report.external_report_id()
<< ",failed_send_attempts=" << report.failed_send_attempts()
<< ",data=" << report.data() << "}";
return out;
}
std::ostream& operator<<(std::ostream& out, SendResult::Status status) {
switch (status) {
case SendResult::Status::kSent:
out << "kSent";
break;
case SendResult::Status::kTransientFailure:
out << "kTransientFailure";
break;
case SendResult::Status::kFailure:
out << "kFailure";
break;
case SendResult::Status::kDropped:
out << "kDropped";
break;
}
return out;
}
std::ostream& operator<<(std::ostream& out, const SendResult& info) {
return out << "{status=" << info.status
<< ",http_response_code=" << info.http_response_code << "}";
}
std::ostream& operator<<(std::ostream& out,
const DeactivatedSource& deactivated_source) {
return out << "{source=" << deactivated_source.source
<< ",reason=" << deactivated_source.reason << "}";
}
std::ostream& operator<<(std::ostream& out, StorableSource::Result status) {
switch (status) {
case StorableSource::Result::kSuccess:
return out << "success";
case StorableSource::Result::kInternalError:
return out << "internalError";
case StorableSource::Result::kInsufficientSourceCapacity:
return out << "insufficientSourceCapacity";
case StorableSource::Result::kInsufficientUniqueDestinationCapacity:
return out << "insufficientUniqueDestinationCapacity";
case StorableSource::Result::kExcessiveReportingOrigins:
return out << "excessiveReportingOrigins";
}
}
std::vector<AttributionReport> GetAttributionsToReportForTesting(
AttributionManagerImpl* manager,
base::Time max_report_time) {
base::RunLoop run_loop;
std::vector<AttributionReport> attribution_reports;
manager->attribution_storage_
.AsyncCall(&AttributionStorage::GetAttributionsToReport)
.WithArgs(max_report_time, /*limit=*/-1)
.Then(base::BindOnce(base::BindLambdaForTesting(
[&](std::vector<AttributionReport> reports) {
attribution_reports = std::move(reports);
run_loop.Quit();
})));
run_loop.Run();
return attribution_reports;
}
} // namespace content