chromium/content/browser/attribution_reporting/attribution_resolver_unittest.cc

// 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.

#include "content/browser/attribution_reporting/attribution_resolver.h"

#include <stdint.h>

#include <cmath>
#include <functional>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

#include "base/containers/enum_set.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/attribution_reporting/aggregatable_debug_reporting_config.h"
#include "components/attribution_reporting/aggregatable_dedup_key.h"
#include "components/attribution_reporting/aggregatable_filtering_id_max_bytes.h"
#include "components/attribution_reporting/aggregatable_trigger_config.h"
#include "components/attribution_reporting/aggregatable_trigger_data.h"
#include "components/attribution_reporting/aggregatable_values.h"
#include "components/attribution_reporting/aggregation_keys.h"
#include "components/attribution_reporting/attribution_scopes_data.h"
#include "components/attribution_reporting/attribution_scopes_set.h"
#include "components/attribution_reporting/constants.h"
#include "components/attribution_reporting/event_report_windows.h"
#include "components/attribution_reporting/event_trigger_data.h"
#include "components/attribution_reporting/features.h"
#include "components/attribution_reporting/filters.h"
#include "components/attribution_reporting/max_event_level_reports.h"
#include "components/attribution_reporting/privacy_math.h"
#include "components/attribution_reporting/source_registration_time_config.mojom.h"
#include "components/attribution_reporting/source_type.mojom.h"
#include "components/attribution_reporting/suitable_origin.h"
#include "components/attribution_reporting/test_utils.h"
#include "components/attribution_reporting/trigger_config.h"
#include "components/attribution_reporting/trigger_data_matching.mojom.h"
#include "components/attribution_reporting/trigger_registration.h"
#include "content/browser/attribution_reporting/aggregatable_debug_report.h"
#include "content/browser/attribution_reporting/attribution_features.h"
#include "content/browser/attribution_reporting/attribution_report.h"
#include "content/browser/attribution_reporting/attribution_resolver_impl.h"
#include "content/browser/attribution_reporting/attribution_storage_sql.h"
#include "content/browser/attribution_reporting/attribution_test_utils.h"
#include "content/browser/attribution_reporting/attribution_trigger.h"
#include "content/browser/attribution_reporting/common_source_info.h"
#include "content/browser/attribution_reporting/create_report_result.h"
#include "content/browser/attribution_reporting/process_aggregatable_debug_report_result.mojom.h"
#include "content/browser/attribution_reporting/rate_limit_result.h"
#include "content/browser/attribution_reporting/storable_source.h"
#include "content/browser/attribution_reporting/store_source_result.h"
#include "content/browser/attribution_reporting/stored_source.h"
#include "content/browser/attribution_reporting/test/configurable_storage_delegate.h"
#include "content/public/browser/attribution_data_model.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/schemeful_site.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/numeric/int128.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/aggregation_service/aggregatable_report.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace content {

namespace {

_;
AllOf;
ElementsAre;
Eq;
Field;
Ge;
IsEmpty;
IsNull;
IsTrue;
Le;
Optional;
Pointee;
Property;
SizeIs;
UnorderedElementsAre;
VariantWith;

AggregatableValues;
AggregatableValuesValue;
FilterConfig;
FilterData;
FilterPair;
kDefaultFilteringId;
MaxEventLevelReports;
SuitableOrigin;
TriggerSpec;
TriggerSpecs;
SourceType;
TriggerDataMatching;
AggregatableReportHistogramContribution;

ProcessAggregatableDebugReportStatus;

// Default max number of conversions for a single impression for testing.
const int kMaxConversions =;

// Default delay for when a report should be sent for testing.
constexpr base::TimeDelta kReportDelay =;

StoragePartition::StorageKeyMatcherFunction GetMatcher(
    const url::Origin& to_delete) {}

AggregatableDebugReport CreateAggregatableDebugReport(
    std::vector<AggregatableReportHistogramContribution> contributions,
    std::string_view reporting_origin = "https://r.test") {}

MATCHER_P(CreateReportSourceIs, matcher, "") {}

MATCHER_P(CreateReportMaxEventLevelReportsLimitIs, matcher, "") {}

MATCHER_P(CreateReportMaxAggregatableReportsLimitIs, matcher, "") {}

}  // namespace

// Unit test suite for the AttributionResolver interface. All
// AttributionResolver implementations (including fakes) should be able to
// re-use this test suite.
class AttributionResolverTest : public testing::Test {};

TEST_F(AttributionResolverTest, ImpressionStoredAndRetrieved_ValuesIdentical) {}

TEST_F(AttributionResolverTest, UniqueReportWindowsStored_ValuesIdentical) {}

TEST_F(AttributionResolverTest,
       GetWithNoMatchingImpressions_NoImpressionsReturned) {}

TEST_F(AttributionResolverTest, GetWithMatchingImpression_ImpressionReturned) {}

TEST_F(AttributionResolverTest, MultipleImpressionsForConversion_OneConverts) {}

TEST_F(AttributionResolverTest,
       CrossOriginSameDomainConversion_ImpressionConverted) {}

TEST_F(AttributionResolverTest,
       ImpressionWithMultipleDestinations_ImpressionConverted) {}

TEST_F(AttributionResolverTest, EventSourceImpressionsForConversion_Converts) {}

TEST_F(AttributionResolverTest, ImpressionExpired_NoConversionsStored) {}

TEST_F(AttributionResolverTest,
       AggregatableReportWindowPassed_NoReportGenerated) {}

TEST_F(AttributionResolverTest, ImpressionExpired_ConversionsStoredPrior) {}

TEST_F(AttributionResolverTest,
       ImpressionWithSetMaxConversions_ConversionReportStored) {}

TEST_F(AttributionResolverTest,
       ImpressionWithMaxConversionsSetToZero_NoReportGenerated) {}

TEST_F(AttributionResolverTest,
       ImpressionReportWindowNotStarted_NoReportGenerated) {}

TEST_F(AttributionResolverTest,
       ImpressionReportWindowsPassed_NoReportGenerated) {}

TEST_F(AttributionResolverTest, OneConversion_OneReportScheduled) {}

TEST_F(AttributionResolverTest,
       ConversionWithDifferentReportingOrigin_NoReportScheduled) {}

TEST_F(AttributionResolverTest,
       ConversionWithDifferentConversionOrigin_NoReportScheduled) {}

TEST_F(AttributionResolverTest, ConversionReportDeleted_RemovedFromStorage) {}

TEST_F(AttributionResolverTest,
       ManyImpressionsWithManyConversions_OneImpressionAttributed) {}

TEST_F(AttributionResolverTest,
       MultipleImpressionsForConversion_UnattributedImpressionsInactive) {}

// This test makes sure that when a new click is received for a given
// <reporting_origin, destination_origin> pair, all existing impressions for
// that origin that have converted are marked ineligible for new conversions per
// the multi-touch model.
TEST_F(AttributionResolverTest,
       NewImpressionForConvertedImpression_MarkedInactive) {}

TEST_F(AttributionResolverTest,
       NonMatchingImpressionForConvertedImpression_FirstRemainsActive) {}

TEST_F(AttributionResolverTest, ImpressionWithDeletedReport_RemainsActive) {}

TEST_F(
    AttributionResolverTest,
    MultipleImpressionsForConversionAtDifferentTimes_OneImpressionAttributed) {}

TEST_F(AttributionResolverTest,
       ImpressionsAtDifferentTimes_AttributedImpressionHasCorrectReportTime) {}

TEST_F(AttributionResolverTest, GetAttributionReportsMultipleTimes_SameResult) {}

TEST_F(AttributionResolverTest, ExceedsChannelCapacity_SupersedesRateLimits) {}

TEST_F(AttributionResolverTest, MaxImpressionsPerOrigin_PerOriginNotSite) {}

// Regression test for https://crbug.com/1510433 in which expired sources
// were erroneously counted during calculation of the sources-per-source-origin
// limit check.
TEST_F(AttributionResolverTest, MaxImpressionsPerOrigin_ExpiredSourcesIgnored) {}

TEST_F(AttributionResolverTest, MaxEventLevelReportsPerDestination) {}

TEST_F(AttributionResolverTest,
       MaxEventLevelReportsPerDestination_MultipleDestinations) {}

TEST_F(AttributionResolverTest, MaxAggregatableReportsPerDestination) {}

TEST_F(AttributionResolverTest,
       MaxAggregatableReportsPerDestination_MultipleDestinations) {}

TEST_F(AttributionResolverTest, ClearDataWithNoMatch_NoDelete) {}

TEST_F(AttributionResolverTest,
       ClearData_SourceAndDestinationOriginsIrrelevant) {}

TEST_F(AttributionResolverTest, ClearDataOutsideRange_NoDelete) {}

TEST_F(AttributionResolverTest, ClearDataImpression) {}

TEST_F(AttributionResolverTest, ClearDataImpressionConversion) {}

// The null filter should match all origins.
TEST_F(AttributionResolverTest, ClearDataNullFilter) {}

TEST_F(AttributionResolverTest, ClearDataWithImpressionOutsideRange) {}

// Deletions with time range between the impression and conversion should not
// delete anything, unless the time range intersects one of the events.
TEST_F(AttributionResolverTest, ClearDataRangeBetweenEvents) {}

// Test that only a subset of impressions / conversions are deleted with
// multiple impressions per conversion, if only a subset of impressions match.
TEST_F(AttributionResolverTest, ClearDataWithMultiTouch) {}

// The max time range with a null filter should delete everything.
TEST_F(AttributionResolverTest, DeleteAll) {}

// Same as the above test, but uses base::Time() instead of base::Time::Min()
// for delete_begin, which should yield the same behavior.
TEST_F(AttributionResolverTest, DeleteAllNullDeleteBegin) {}

TEST_F(AttributionResolverTest, MaxAttributionsBetweenSites) {}

TEST_F(AttributionResolverTest,
       MaxAttributionReportsBetweenSites_IgnoresSourceType) {}

TEST_F(AttributionResolverTest,
       NeverAttributeImpression_EventLevelReportNotStored) {}

TEST_F(AttributionResolverTest,
       AttributeFalseImpression_OtherSourceDeactivated) {}

TEST_F(AttributionResolverTest, NeverAttributeImpression_RateLimitsChanged) {}

TEST_F(AttributionResolverTest,
       NeverAndTruthfullyAttributeImpressions_EventLevelReportNotStored) {}

TEST_F(AttributionResolverTest,
       MaxDestinationsPerSource_ScopedToSourceSiteAndReportingSite) {}

TEST_F(AttributionResolverTest, DestinationLimit_ApplyLimit) {}

TEST_F(AttributionResolverTest,
       MaxAttributionDestinationsPerSource_AppliesToNavigationSources) {}

TEST_F(AttributionResolverTest,
       MaxAttributionDestinationsPerSource_CountsAllSourceTypes) {}

TEST_F(AttributionResolverTest,
       MaxAttributionDestinationsPerSource_CountsUnexpiredSources) {}

TEST_F(AttributionResolverTest,
       MaxAttributionDestinationsPerSource_SourceWithTooManyDestinations) {}

TEST_F(AttributionResolverTest,
       HandleSource_DestinationThrottleReportingLimitReached) {}

TEST_F(AttributionResolverTest,
       HandleSource_DestinationThrottleGlobalLimitReached) {}

TEST_F(AttributionResolverTest,
       HandleSource_DestinationThrottleBothLimitsReached) {}

TEST_F(AttributionResolverTest,
       MultipleImpressionsPerConversion_MostRecentAttributesForSamePriority) {}

TEST_F(AttributionResolverTest,
       MultipleImpressionsPerConversion_HighestPriorityAttributes) {}

TEST_F(AttributionResolverTest, MultipleImpressions_CorrectDeactivation) {}

TEST_F(AttributionResolverTest, FalselyAttributeImpression_ReportStored) {}

TEST_F(AttributionResolverTest, StoreSource_ReturnsMinFakeReportTime) {}

TEST_F(AttributionResolverTest, TriggerPriority) {}

// Regression test for erroneous use of report_time instead of
// initial_report_time in event-level prioritization (http://crbug.com/1500598).
TEST_F(AttributionResolverTest, TriggerPriority_UsesOriginalReportTime) {}

TEST_F(AttributionResolverTest, TriggerPriority_Simple) {}

TEST_F(AttributionResolverTest, TriggerPriority_SamePriorityDeletesMostRecent) {}

TEST_F(AttributionResolverTest, TriggerPriority_DeactivatesImpression) {}

TEST_F(AttributionResolverTest, TriggerPriority_AttributionRateLimitAdjusted) {}

TEST_F(AttributionResolverTest,
       TriggerPriority_ReplacementSkipAttributionRateLimitCheck) {}

TEST_F(AttributionResolverTest, DedupKey_Dedups) {}

TEST_F(AttributionResolverTest, DedupKey_DedupsAfterConversionDeletion) {}

TEST_F(AttributionResolverTest, AggregatableDedupKey_Dedups) {}

TEST_F(AttributionResolverTest,
       AggregatableDedupKey_DedupsAfterConversionDeletion) {}

TEST_F(AttributionResolverTest, DedupKey_AggregatableReportNotDedups) {}

TEST_F(AttributionResolverTest,
       AggregatableDedupKey_EventLevelReportNotDedups) {}

TEST_F(AttributionResolverTest, AggregatableDedupKeysFiltering) {}

TEST_F(AttributionResolverTest, GetAttributionReports_SetsPriority) {}

TEST_F(AttributionResolverTest, NoIDReuse_Impression) {}

TEST_F(AttributionResolverTest, NoIDReuse_Conversion) {}

TEST_F(AttributionResolverTest, UpdateReportForSendFailure) {}

TEST_F(AttributionResolverTest,
       MaybeCreateAndStoreEventLevelReport_ReturnsDeactivatedSources) {}

TEST_F(AttributionResolverTest, ReportID_RoundTrips) {}

TEST_F(AttributionResolverTest, AdjustOfflineReportTimes) {}

TEST_F(AttributionResolverTest, AdjustOfflineReportTimes_Range) {}

TEST_F(AttributionResolverTest,
       AdjustOfflineReportTimes_ReturnsMinReportTimeWithoutDelay) {}

TEST_F(AttributionResolverTest, GetNextEventReportTime) {}

TEST_F(AttributionResolverTest, GetAttributionReports_Shuffles) {}

TEST_F(AttributionResolverTest, GetAttributionReportsExceedLimit_Shuffles) {}

TEST_F(AttributionResolverTest, GetAttributionDataKeysSet) {}

TEST_F(AttributionResolverTest, SourceDebugKey_RoundTrips) {}

TEST_F(AttributionResolverTest, TriggerDebugKey_RoundTrips) {}

TEST_F(AttributionResolverTest, AttributionAggregationKeys_RoundTrips) {}

TEST_F(AttributionResolverTest, MaybeCreateAndStoreReport_ReturnsNewReport) {}

// This is tested more thoroughly by the `RateLimitTable` unit tests. Here just
// ensure that the rate limits are consulted at all.
TEST_F(AttributionResolverTest, MaxReportingOriginsPerSource) {}

// This is tested more thoroughly by the `RateLimitTable` unit tests. Here just
// ensure that the rate limits are consulted at all and the rate limit is shared
// between event-level and aggregatable reports.
TEST_F(AttributionResolverTest, MaxReportingOriginsPerAttribution) {}

TEST_F(AttributionResolverTest, SourceBudgetValueRetrieved) {}

TEST_F(AttributionResolverTest, MaxAggregatableBudgetPerSource) {}

TEST_F(AttributionResolverTest, BudgetConsumedAfterTriggerIsRetrieved) {}

TEST_F(AttributionResolverTest,
       GetAttributionReports_SetsRandomizedTriggerRate) {}

TEST_F(AttributionResolverTest, RandomizedResponseRatePerSourceUsed) {}

// Will return minimum of next event-level report and next aggregatable report
// time if both present.
TEST_F(AttributionResolverTest, GetNextReportTime) {}

TEST_F(AttributionResolverTest, TriggerDataSanitized) {}

TEST_F(AttributionResolverTest, SourceFilterData_RoundTrips) {}

TEST_F(AttributionResolverTest, NoMatchingTriggerData_ReturnsError) {}

TEST_F(AttributionResolverTest, MatchingTriggerData_UsesCorrectData) {}

TEST_F(AttributionResolverTest, TopLevelTriggerFiltering) {}

TEST_F(AttributionResolverTest,
       AggregatableAttributionNoMatchingSources_NoSourcesReturned) {}

TEST_F(AttributionResolverTest,
       AggregatableAttributionNoAggregationKeys_NoContributions) {}

TEST_F(AttributionResolverTest,
       AggregatableAttributionValues_NoMatchingFilters_NoContributions) {}

TEST_F(AttributionResolverTest, AggregatableAttribution_ReportsScheduled) {}

TEST_F(
    AttributionResolverTest,
    MaybeCreateAndStoreAggregatableReport_reachedEventLevelAttributionLimit) {}

TEST_F(AttributionResolverTest,
       AggregatableTriggerDataOrValuesNotSet_Registered) {}

TEST_F(AttributionResolverTest,
       PrioritizationConsidersAttributedAndUnattributedSources) {}

TEST_F(AttributionResolverTest,
       MaybeCreateAndStoreEventLevelReport_DeactivatesUnattributedSources) {}

TEST_F(AttributionResolverTest, AggregationCoordinator_RoundTrip) {}

TEST_F(AttributionResolverTest, MaxAttributions_BoundedBySourceTimeWindow) {}

TEST_F(AttributionResolverTest, NoEventTriggerData_NotRegisteredReturned) {}

TEST_F(AttributionResolverTest, StoreNullAggregatableReport) {}

TEST_F(AttributionResolverTest, NoAggregatableData_NoNullReport) {}

TEST_F(AttributionResolverTest, BothRealAndNullAggregatableReports) {}

TEST_F(AttributionResolverTest, SourceRegistrationTimeConfig_RoundTrip) {}

TEST_F(AttributionResolverTest, MaximumAggregatableReportsPerSource) {}

TEST_F(AttributionResolverTest, MaxSourceReportingOriginsPerSite) {}

TEST_F(AttributionResolverTest, TriggerDataMatching) {}

TEST_F(AttributionResolverTest, EventLevelDedupBeforeWindowCheck) {}

TEST_F(AttributionResolverTest,
       AttributionAggregatableReportWithTriggerContextId_RoundTrip) {}

TEST_F(AttributionResolverTest,
       NullAggregatableReportWithTriggerContextId_RoundTrip) {}

// TODO(crbug.com/40941848): Support multiple trigger specs instead of just 1.
TEST_F(AttributionResolverTest, RejectsMultipleTriggerSpecs) {}

// Regression test for https://crbug.com/331100922.
TEST_F(
    AttributionResolverTest,
    FakeSourceCreateAggregatableReport_EffectiveDestinationAttributionRateLimitRecord) {}

TEST_F(AttributionResolverTest,
       AttributedTriggerIncludeSourceRegistrationTime_NullAggregatableReports) {}

TEST_F(
    AttributionResolverTest,
    UnattributedTriggerIncludeSourceRegistrationTime_NullAggregatableReports) {}

TEST_F(
    AttributionResolverTest,
    AttributedTriggerExcludeSourceRegistrationTime_NoNullAggregatableReport) {}

TEST_F(
    AttributionResolverTest,
    UnattributedTriggerExcludeSourceRegistrationTime_NullAggregatableReport) {}

TEST_F(AttributionResolverTest,
       SourceAggregatableDebugReportingConfig_RoundTrips) {}

TEST_F(AttributionResolverTest,
       ProcessAggregatableDebugReport_NoBudgetAndNoSourceId) {}

TEST_F(AttributionResolverTest,
       ProcessAggregatableDebugReport_BudgetAndNoSourceId) {}

TEST_F(AttributionResolverTest, ProcessAggregatableDebugReport_SourceId) {}

class AttributionResolverSourceDestinationLimitTest
    : public AttributionResolverTest {};

TEST_F(AttributionResolverSourceDestinationLimitTest,
       PerDayLimitReached_SourceDropped) {}

TEST_F(AttributionResolverSourceDestinationLimitTest,
       LimitHit_DestinationDeactivated) {}

TEST_F(AttributionResolverSourceDestinationLimitTest,
       PriorityTooLow_SourceDropped) {}

TEST_F(AttributionResolverSourceDestinationLimitTest,
       LimitHit_EventLevelReportNotDeleted) {}

TEST_F(AttributionResolverSourceDestinationLimitTest,
       LimitHit_AggregatableReportDeleted) {}

TEST_F(AttributionResolverSourceDestinationLimitTest,
       LimitHit_FakeReportDeleted) {}

TEST_F(
    AttributionResolverSourceDestinationLimitTest,
    LimitHitAndDestinationGlobalRateLimitHit_DestinationDeactivatedAndSourceDropped) {}

TEST_F(AttributionResolverSourceDestinationLimitTest,
       DestinationLimitResultMetrics) {}

TEST_F(AttributionResolverTest, SourceAttributionScopesData_RoundTrips) {}

TEST_F(AttributionResolverTest, SourcesWithDifferentAttributionScopeLimits) {}

TEST_F(AttributionResolverTest, IncomingEmptyScopes_RemovesOtherScopes) {}

TEST_F(AttributionResolverTest, SourcesWithDifferentMaxEventStates) {}

TEST_F(AttributionResolverTest, RemoveOutdatedScopes) {}

TEST_F(AttributionResolverTest, TriggerAttributesOnMatchingScope) {}

}  // namespace content