[go: nahoru, domu]

blob: 21468ef54a7cecade2545f729099de08cb59bfe7 [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/browsing_topics/browsing_topics_calculator.h"
#include <memory>
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "components/browsing_topics/test_util.h"
#include "components/browsing_topics/util.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/history/core/browser/history_database_params.h"
#include "components/history/core/browser/history_service.h"
#include "components/history/core/test/test_history_database.h"
#include "components/optimization_guide/core/test_model_info_builder.h"
#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
#include "components/privacy_sandbox/privacy_sandbox_settings_impl.h"
#include "components/privacy_sandbox/privacy_sandbox_test_util.h"
#include "components/privacy_sandbox/tracking_protection_settings.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/browsing_topics_test_util.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/common/features.h"
namespace browsing_topics {
namespace {
constexpr int kTaxonomyVersion = 2;
constexpr char kHost1[] = "www.foo1.com";
constexpr char kHost2[] = "www.foo2.com";
constexpr char kHost3[] = "www.foo3.com";
constexpr char kHost4[] = "www.foo4.com";
constexpr char kHost5[] = "www.foo5.com";
constexpr char kHost6[] = "www.foo6.com";
Topic ExpectedRandomTopic(size_t index) {
Topic kExpectedRandomTopicsForTaxonomyV1[5] = {
Topic(101), Topic(102), Topic(103), Topic(104), Topic(105)};
Topic kExpectedRandomTopicsForTaxonomyV2[5] = {
Topic(176), Topic(177), Topic(180), Topic(183), Topic(184)};
if (blink::features::kBrowsingTopicsTaxonomyVersion.Get() == 1) {
return kExpectedRandomTopicsForTaxonomyV1[index];
}
if (blink::features::kBrowsingTopicsTaxonomyVersion.Get() == 2) {
return kExpectedRandomTopicsForTaxonomyV2[index];
}
NOTREACHED_NORETURN();
}
} // namespace
class BrowsingTopicsCalculatorTest : public testing::Test {
public:
BrowsingTopicsCalculatorTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
content_settings::CookieSettings::RegisterProfilePrefs(prefs_.registry());
HostContentSettingsMap::RegisterProfilePrefs(prefs_.registry());
privacy_sandbox::RegisterProfilePrefs(prefs_.registry());
host_content_settings_map_ = base::MakeRefCounted<HostContentSettingsMap>(
&prefs_, /*is_off_the_record=*/false, /*store_last_modified=*/false,
/*restore_session=*/false, /*should_record_metrics=*/false);
tracking_protection_settings_ =
std::make_unique<privacy_sandbox::TrackingProtectionSettings>(
&prefs_,
/*onboarding_service=*/nullptr, /*is_incognito=*/false);
cookie_settings_ = base::MakeRefCounted<content_settings::CookieSettings>(
host_content_settings_map_.get(), &prefs_,
tracking_protection_settings_.get(), false, "chrome-extension");
auto privacy_sandbox_delegate = std::make_unique<
privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>();
privacy_sandbox_delegate->SetUpIsPrivacySandboxRestrictedResponse(
/*restricted=*/false);
privacy_sandbox_delegate->SetUpIsIncognitoProfileResponse(
/*incognito=*/false);
privacy_sandbox_settings_ =
std::make_unique<privacy_sandbox::PrivacySandboxSettingsImpl>(
std::move(privacy_sandbox_delegate),
host_content_settings_map_.get(), cookie_settings_,
tracking_protection_settings_.get(), &prefs_);
privacy_sandbox_settings_->SetAllPrivacySandboxAllowedForTesting();
topics_site_data_manager_ =
std::make_unique<content::TesterBrowsingTopicsSiteDataManager>(
temp_dir_.GetPath());
history_service_ = std::make_unique<history::HistoryService>();
history_service_->Init(
history::TestHistoryDatabaseParamsForPath(temp_dir_.GetPath()));
task_environment_.RunUntilIdle();
}
~BrowsingTopicsCalculatorTest() override {
cookie_settings_->ShutdownOnUIThread();
host_content_settings_map_->ShutdownOnUIThread();
tracking_protection_settings_->Shutdown();
}
EpochTopics CalculateTopics(base::circular_deque<EpochTopics> epochs = {}) {
EpochTopics result = EpochTopics(base::Time());
base::RunLoop run_loop;
TesterBrowsingTopicsCalculator topics_calculator =
TesterBrowsingTopicsCalculator(
privacy_sandbox_settings_.get(), history_service_.get(),
topics_site_data_manager_.get(), &test_annotator_, epochs,
base::BindLambdaForTesting([&](EpochTopics epoch_topics) {
result = std::move(epoch_topics);
run_loop.Quit();
}),
/*rand_uint64_queue=*/
base::queue<uint64_t>{{100, 101, 102, 103, 104}});
run_loop.Run();
return result;
}
void AddHistoryEntries(const std::vector<std::string>& hosts,
base::Time time) {
history::HistoryAddPageArgs add_page_args;
add_page_args.time = time;
add_page_args.context_id = 1;
for (const std::string& host : hosts) {
static int nav_entry_id = 0;
++nav_entry_id;
add_page_args.url = GURL(base::StrCat({"https://", host}));
add_page_args.nav_entry_id = nav_entry_id;
history_service_->AddPage(add_page_args);
history_service_->SetBrowsingTopicsAllowed(
add_page_args.context_id, nav_entry_id, add_page_args.url);
}
task_environment_.RunUntilIdle();
}
void AddApiUsageContextEntries(
const std::vector<std::pair<std::string, std::set<HashedDomain>>>&
main_frame_hosts_with_context_domains) {
for (auto& [main_frame_host, context_domains] :
main_frame_hosts_with_context_domains) {
for (const HashedDomain& context_domain : context_domains) {
topics_site_data_manager_->OnBrowsingTopicsApiUsed(
HashMainFrameHostForStorage(main_frame_host), context_domain,
base::NumberToString(context_domain.value()), base::Time::Now());
}
}
task_environment_.RunUntilIdle();
}
void ExpectResultTopicsEqual(
const std::vector<TopicAndDomains>& result,
std::vector<std::pair<Topic, std::set<HashedDomain>>> expected) {
DCHECK_EQ(expected.size(), 5u);
EXPECT_EQ(result.size(), 5u);
for (int i = 0; i < 5; ++i) {
EXPECT_EQ(result[i].topic(), expected[i].first);
EXPECT_EQ(result[i].hashed_domains(), expected[i].second);
}
}
protected:
content::BrowserTaskEnvironment task_environment_;
sync_preferences::TestingPrefServiceSyncable prefs_;
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
scoped_refptr<content_settings::CookieSettings> cookie_settings_;
std::unique_ptr<privacy_sandbox::TrackingProtectionSettings>
tracking_protection_settings_;
std::unique_ptr<privacy_sandbox::PrivacySandboxSettings>
privacy_sandbox_settings_;
TestAnnotator test_annotator_;
std::unique_ptr<content::TesterBrowsingTopicsSiteDataManager>
topics_site_data_manager_;
std::unique_ptr<history::HistoryService> history_service_;
base::ScopedTempDir temp_dir_;
};
TEST_F(BrowsingTopicsCalculatorTest, PermissionDenied) {
base::HistogramTester histograms;
privacy_sandbox_settings_->SetTopicsBlockedForTesting();
EpochTopics result = CalculateTopics();
EXPECT_TRUE(result.empty());
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
/*kFailurePermissionDenied*/ 1,
/*expected_bucket_count=*/1);
}
TEST_F(BrowsingTopicsCalculatorTest, ApiUsageContextQueryError) {
base::HistogramTester histograms;
topics_site_data_manager_->SetQueryFailureOverride();
EpochTopics result = CalculateTopics();
EXPECT_TRUE(result.empty());
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
/*kFailureApiUsageContextQueryError*/ 2,
/*expected_bucket_count=*/1);
}
TEST_F(BrowsingTopicsCalculatorTest, AnnotationExecutionError) {
base::HistogramTester histograms;
EpochTopics result = CalculateTopics();
EXPECT_TRUE(result.empty());
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
/*kFailureAnnotationExecutionError*/ 3,
/*expected_bucket_count=*/1);
}
class BrowsingTopicsCalculatorUnsupporedTaxonomyVersionTest
: public BrowsingTopicsCalculatorTest {
public:
BrowsingTopicsCalculatorUnsupporedTaxonomyVersionTest() {
feature_list_.InitAndEnableFeatureWithParameters(
blink::features::kBrowsingTopicsParameters,
{{"taxonomy_version", "999"}});
}
private:
base::test::ScopedFeatureList feature_list_;
};
TEST_F(BrowsingTopicsCalculatorUnsupporedTaxonomyVersionTest,
TaxonomyVersionNotSupportedInBinary) {
base::HistogramTester histograms;
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
EpochTopics result = CalculateTopics();
EXPECT_TRUE(result.empty());
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
/*kFailureTaxonomyVersionNotSupportedInBinary*/ 4,
/*expected_bucket_count=*/1);
}
TEST_F(BrowsingTopicsCalculatorTest, TopicsMetadata) {
base::HistogramTester histograms;
base::Time begin_time = base::Time::Now();
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
EpochTopics result1 = CalculateTopics();
EXPECT_FALSE(result1.empty());
EXPECT_EQ(result1.taxonomy_version(), kTaxonomyVersion);
EXPECT_EQ(result1.model_version(), 1);
EXPECT_EQ(result1.calculation_time(), begin_time);
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
/*kSuccess*/ 0,
/*expected_bucket_count=*/1);
task_environment_.AdvanceClock(base::Seconds(2));
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(50).Build());
EpochTopics result2 = CalculateTopics();
EXPECT_FALSE(result2.empty());
EXPECT_EQ(result2.taxonomy_version(), kTaxonomyVersion);
EXPECT_EQ(result2.model_version(), 50);
EXPECT_EQ(result2.calculation_time(), begin_time + base::Seconds(2));
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.CalculatorResultStatus",
/*kSuccess*/ 0,
/*expected_bucket_count=*/2);
}
// Regression test for crbug/1495959.
TEST_F(BrowsingTopicsCalculatorTest, ModelAvailableAfterDelay) {
test_annotator_.SetModelAvailable(false);
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
task_environment_.AdvanceClock(base::Seconds(1));
// This PostTask will run when the |CalculateTopics| run loop starts and will
// signal to the calculator that the model is ready, triggering it to start.
task_environment_.GetMainThreadTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(
[](TestAnnotator* annotator) {
annotator->UseModelInfo(*optimization_guide::TestModelInfoBuilder()
.SetVersion(1)
.Build());
annotator->UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
annotator->SetModelAvailable(true);
},
&test_annotator_));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{Topic(6), {}},
{Topic(5), {}},
{Topic(4), {}},
{Topic(3), {}},
{Topic(2), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
}
TEST_F(BrowsingTopicsCalculatorTest, TopTopicsRankedByFrequency) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{Topic(6), {}},
{Topic(5), {}},
{Topic(4), {}},
{Topic(3), {}},
{Topic(2), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
}
TEST_F(BrowsingTopicsCalculatorTest, ModelHasNoTopicsForHost) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{ExpectedRandomTopic(0), {}},
{ExpectedRandomTopic(1), {}},
{ExpectedRandomTopic(2), {}},
{ExpectedRandomTopic(3), {}},
{ExpectedRandomTopic(4), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 0u);
}
TEST_F(BrowsingTopicsCalculatorTest,
TopTopicsRankedByFrequency_AlsoAffectedByHostsCount) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost1, kHost1, kHost1, kHost1, kHost1, kHost2,
kHost3, kHost4, kHost5, kHost6},
begin_time);
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{Topic(2), {}},
{Topic(1), {}},
{Topic(6), {}},
{Topic(5), {}},
{Topic(4), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
}
TEST_F(BrowsingTopicsCalculatorTest, AllTopTopicsRandomlyPadded) {
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{ExpectedRandomTopic(0), {}},
{ExpectedRandomTopic(1), {}},
{ExpectedRandomTopic(2), {}},
{ExpectedRandomTopic(3), {}},
{ExpectedRandomTopic(4), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 0u);
}
TEST_F(BrowsingTopicsCalculatorTest, TopTopicsPartiallyPadded) {
base::HistogramTester histograms;
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost4, kHost5, kHost6}, begin_time);
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{Topic(6), {}},
{Topic(5), {}},
{Topic(4), {}},
{ExpectedRandomTopic(0), {}},
{ExpectedRandomTopic(1), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 3u);
}
TEST_F(BrowsingTopicsCalculatorTest, CalculationResultUkm_FailedCalculation) {
ukm::TestAutoSetUkmRecorder ukm_recorder;
privacy_sandbox_settings_->SetTopicsBlockedForTesting();
CalculateTopics();
auto entries = ukm_recorder.GetEntriesByName(
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::kEntryName);
EXPECT_EQ(1u, entries.size());
EXPECT_FALSE(ukm_recorder.GetEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kTopTopic0Name));
}
TEST_F(BrowsingTopicsCalculatorTest, CalculationResultUkm) {
ukm::TestAutoSetUkmRecorder ukm_recorder;
base::HistogramTester histograms;
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost4, kHost5, kHost6}, begin_time);
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
CalculateTopics();
auto entries = ukm_recorder.GetEntriesByName(
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::kEntryName);
EXPECT_EQ(1u, entries.size());
ukm_recorder.ExpectEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kTopTopic0Name,
6);
ukm_recorder.ExpectEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kTopTopic1Name,
5);
ukm_recorder.ExpectEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kTopTopic2Name,
4);
ukm_recorder.ExpectEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kTopTopic3Name,
ExpectedRandomTopic(0).value());
ukm_recorder.ExpectEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kTopTopic4Name,
ExpectedRandomTopic(1).value());
ukm_recorder.ExpectEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kTaxonomyVersionName,
kTaxonomyVersion);
ukm_recorder.ExpectEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kModelVersionName,
1);
ukm_recorder.ExpectEntryMetric(
entries.back(),
ukm::builders::BrowsingTopics_EpochTopicsCalculationResult::
kPaddedTopicsStartIndexName,
3);
}
TEST_F(BrowsingTopicsCalculatorTest, TopTopicsAndObservingDomains) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{Topic(6), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(5), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(4), {HashedDomain(2), HashedDomain(3)}},
{Topic(3), {HashedDomain(2)}},
{Topic(2), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
}
TEST_F(
BrowsingTopicsCalculatorTest,
HistoryHostsBefore21DaysAgo_IgnoredForTopTopicsDecision_IgnoredForObservingDomainsDecision) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time - base::Days(21));
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 103, 4, 5, 6}},
{kHost2, {2, 103, 4, 5, 6}},
{kHost3, {103, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{ExpectedRandomTopic(0), {}},
{ExpectedRandomTopic(1), {}},
{ExpectedRandomTopic(2), {}},
{ExpectedRandomTopic(3), {}},
{ExpectedRandomTopic(4), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 0u);
}
TEST_F(
BrowsingTopicsCalculatorTest,
HistoryHostsBetween7And21Days_IgnoredForTopTopicsDecision_ConsideredForObservingDomainsDecision) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time - base::Days(20));
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, ExpectedRandomTopic(2).value(), 4, 5, 6}},
{kHost2, {2, ExpectedRandomTopic(2).value(), 4, 5, 6}},
{kHost3, {ExpectedRandomTopic(2).value(), 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{ExpectedRandomTopic(0), {}},
{ExpectedRandomTopic(1), {}},
{ExpectedRandomTopic(2), {HashedDomain(2)}},
{ExpectedRandomTopic(3), {}},
{ExpectedRandomTopic(4), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 0u);
}
TEST_F(BrowsingTopicsCalculatorTest,
DataQueryBoundedByTopicsDataAccessibleSince) {
base::Time begin_time = base::Time::Now();
prefs_.SetTime(prefs::kPrivacySandboxTopicsDataAccessibleSince,
begin_time + base::Days(6));
AddHistoryEntries({kHost1, kHost2}, begin_time);
AddApiUsageContextEntries({{kHost1, {}}, {kHost2, {}}});
task_environment_.AdvanceClock(base::Days(6));
AddHistoryEntries({kHost3, kHost4, kHost5, kHost6},
begin_time + base::Days(6));
AddApiUsageContextEntries(
{{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{Topic(6), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(5), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(4), {HashedDomain(2), HashedDomain(3)}},
{Topic(3), {HashedDomain(2)}},
{ExpectedRandomTopic(0), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 4u);
}
TEST_F(BrowsingTopicsCalculatorTest,
HistoryDataBoundedByLastEpochCalculationTime) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3}, begin_time);
AddApiUsageContextEntries({{kHost3, {HashedDomain(5)}}});
task_environment_.AdvanceClock(base::Days(4));
AddHistoryEntries({kHost2, kHost3}, begin_time + base::Days(4));
AddApiUsageContextEntries({{kHost3, {HashedDomain(2)}}});
task_environment_.AdvanceClock(base::Days(2));
AddHistoryEntries({kHost3, kHost4, kHost5, kHost6},
begin_time + base::Days(6));
AddApiUsageContextEntries(
{{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
base::circular_deque<EpochTopics> epochs;
epochs.push_back(EpochTopics(begin_time + base::Days(6)));
EpochTopics result = CalculateTopics(std::move(epochs));
// The topics are only from hosts since `begin_time + base::Days(6)`. The
// observing domains are from data since `begin_time`.
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{Topic(6),
{HashedDomain(1), HashedDomain(2), HashedDomain(3), HashedDomain(5)}},
{Topic(5),
{HashedDomain(1), HashedDomain(2), HashedDomain(3), HashedDomain(5)}},
{Topic(4), {HashedDomain(2), HashedDomain(3), HashedDomain(5)}},
{Topic(3), {HashedDomain(2), HashedDomain(5)}},
{ExpectedRandomTopic(0), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 4u);
}
TEST_F(BrowsingTopicsCalculatorTest,
HistoryDataAndApiUsageContextDataBoundedByPriorEpochsCalculationTime) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3}, begin_time);
AddApiUsageContextEntries({{kHost3, {HashedDomain(5)}}});
task_environment_.AdvanceClock(base::Days(4));
AddHistoryEntries({kHost2, kHost3}, begin_time + base::Days(4));
AddApiUsageContextEntries({{kHost3, {HashedDomain(2)}}});
task_environment_.AdvanceClock(base::Days(2));
AddHistoryEntries({kHost3, kHost4, kHost5, kHost6},
begin_time + base::Days(6));
AddApiUsageContextEntries(
{{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
base::circular_deque<EpochTopics> epochs;
epochs.push_back(EpochTopics(begin_time + base::Days(4)));
epochs.push_back(EpochTopics(begin_time + base::Days(5)));
epochs.push_back(EpochTopics(begin_time + base::Days(6)));
EpochTopics result = CalculateTopics(std::move(epochs));
// The topics are only from hosts since `begin_time + base::Days(6)`. The
// observing domains are from data since `begin_time + base::Days(4)`.
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{Topic(6), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(5), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(4), {HashedDomain(2), HashedDomain(3)}},
{Topic(3), {HashedDomain(2)}},
{ExpectedRandomTopic(0), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 4u);
}
TEST_F(BrowsingTopicsCalculatorTest,
TopTopicsAndObservingDomains_DomainsSizeExceedsLimit) {
base::Time begin_time = base::Time::Now();
std::set<HashedDomain> large_size_domains;
for (int i = 1; i <= 1001; ++i) {
large_size_domains.insert(HashedDomain(i));
}
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
AddApiUsageContextEntries({{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, large_size_domains}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
std::set<HashedDomain> expected_domains_after_capping = large_size_domains;
expected_domains_after_capping.erase(HashedDomain(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
{{Topic(6), expected_domains_after_capping},
{Topic(5), expected_domains_after_capping},
{Topic(4), {HashedDomain(2), HashedDomain(3)}},
{Topic(3), {HashedDomain(2)}},
{Topic(2), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
}
TEST_F(BrowsingTopicsCalculatorTest, TopicBlocked) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
privacy_sandbox_settings_->SetTopicAllowed(
privacy_sandbox::CanonicalTopic(Topic(6), kTaxonomyVersion),
/*allowed=*/false);
privacy_sandbox_settings_->SetTopicAllowed(
privacy_sandbox::CanonicalTopic(Topic(4), kTaxonomyVersion),
/*allowed=*/false);
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{Topic(0), {}},
{Topic(5), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(0), {}},
{Topic(3), {HashedDomain(2)}},
{Topic(2), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
}
TEST_F(BrowsingTopicsCalculatorTest, TopicBlockedByFinch) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeatureWithParameters(
blink::features::kBrowsingTopicsParameters,
{{"disabled_topics_list", "6,4"}});
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{Topic(0), {}},
{Topic(5), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(0), {}},
{Topic(3), {HashedDomain(2)}},
{Topic(2), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
}
TEST_F(BrowsingTopicsCalculatorTest, TopicsPrioritizedByFinch) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {74, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeatureWithParameters(
blink::features::kBrowsingTopicsParameters,
{{"prioritized_topics_list", "4,57"}}); // 74 is descended from 57.
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{Topic(4), {HashedDomain(2), HashedDomain(3)}},
{Topic(74), {}},
{Topic(6), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(5), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(3), {HashedDomain(2)}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
EXPECT_EQ(result.config_version(), 2);
}
TEST_F(BrowsingTopicsCalculatorTest, PaddedTopicsDoNotDuplicate) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost4, kHost5, kHost6}, begin_time);
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, ExpectedRandomTopic(1).value()}},
{kHost2, {2, 3, 4, 5, ExpectedRandomTopic(1).value()}},
{kHost3, {3, 4, 5, ExpectedRandomTopic(1).value()}},
{kHost4, {4, 5, ExpectedRandomTopic(1).value()}},
{kHost5, {5, ExpectedRandomTopic(1).value()}},
{kHost6, {ExpectedRandomTopic(1).value()}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
// Note that ExpectedRandomTopic(1) (i.e. Topic(177)) is a descendant of
// ExpectedRandomTopic(0) (i.e. Topic(176)). Thus, `ExpectedRandomTopic(0)` is
// considered to have observed all three domains as well.
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{ExpectedRandomTopic(1),
{HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(5), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(4), {HashedDomain(3)}},
{ExpectedRandomTopic(0),
{HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{ExpectedRandomTopic(2), {}}});
}
TEST_F(BrowsingTopicsCalculatorTest, Metrics_LessThan5HistoryTopics) {
base::HistogramTester histograms;
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost4, kHost5, kHost6}, begin_time);
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
ExpectResultTopicsEqual(
result.top_topics_and_observing_domains(),
{{Topic(6), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(5), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(4), {HashedDomain(3)}},
{ExpectedRandomTopic(0), {}},
{ExpectedRandomTopic(1), {}}});
EXPECT_EQ(result.padded_top_topics_start_index(), 3u);
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.EligibleDistinctHistoryHostsCount",
/*sample=*/3,
/*expected_bucket_count=*/1);
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.HistoryTopicsCount",
/*sample=*/3,
/*expected_bucket_count=*/1);
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.TopTopicsCountBeforePadding",
/*sample=*/3,
/*expected_bucket_count=*/1);
histograms.ExpectTotalCount(
"BrowsingTopics.EpochTopicsCalculation."
"ObservationContextDomainsCountPerTopTopic",
/*count=*/5);
histograms.ExpectBucketCount(
"BrowsingTopics.EpochTopicsCalculation."
"ObservationContextDomainsCountPerTopTopic",
/*sample=*/0,
/*expected_count=*/2);
histograms.ExpectBucketCount(
"BrowsingTopics.EpochTopicsCalculation."
"ObservationContextDomainsCountPerTopTopic",
/*sample=*/1,
/*expected_count=*/1);
histograms.ExpectBucketCount(
"BrowsingTopics.EpochTopicsCalculation."
"ObservationContextDomainsCountPerTopTopic",
/*sample=*/3,
/*expected_count=*/2);
}
TEST_F(BrowsingTopicsCalculatorTest, Metrics_MoreThan5HistoryTopics) {
base::HistogramTester histograms;
base::Time begin_time = base::Time::Now();
AddHistoryEntries({kHost1, kHost2, kHost3, kHost4, kHost5, kHost6},
begin_time);
AddApiUsageContextEntries(
{{kHost1, {}},
{kHost2, {}},
{kHost3, {HashedDomain(2)}},
{kHost4, {HashedDomain(3)}},
{kHost5, {HashedDomain(1), HashedDomain(2), HashedDomain(3)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5, 6}},
{kHost2, {2, 3, 4, 5, 6}},
{kHost3, {3, 4, 5, 6}},
{kHost4, {4, 5, 6}},
{kHost5, {5, 6}},
{kHost6, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
EXPECT_EQ(result.padded_top_topics_start_index(), 5u);
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.HistoryTopicsCount",
/*sample=*/6,
/*expected_bucket_count=*/1);
histograms.ExpectUniqueSample(
"BrowsingTopics.EpochTopicsCalculation.TopTopicsCountBeforePadding",
/*sample=*/5,
/*expected_bucket_count=*/1);
}
TEST_F(BrowsingTopicsCalculatorTest, NoDescendantTopics) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries(
{
kHost1,
kHost2,
kHost3,
kHost4,
kHost5,
},
begin_time);
AddApiUsageContextEntries({{kHost1, {HashedDomain(1)}},
{kHost2, {HashedDomain(2)}},
{kHost3, {HashedDomain(3)}},
{kHost4, {HashedDomain(4)}},
{kHost5, {HashedDomain(5)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
test_annotator_.UseAnnotations({
{kHost1, {2, 3, 4, 5, 6}},
{kHost2, {3, 4, 5, 6}},
{kHost3, {4, 5, 6}},
{kHost4, {5, 6}},
{kHost5, {6}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
std::vector<std::pair<Topic, std::set<HashedDomain>>>
expected_top_topics_and_observing_domains = {
{Topic(6),
{HashedDomain(1), HashedDomain(2), HashedDomain(3), HashedDomain(4),
HashedDomain(5)}},
{Topic(5),
{HashedDomain(1), HashedDomain(2), HashedDomain(3),
HashedDomain(4)}},
{Topic(4), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(3), {HashedDomain(1), HashedDomain(2)}},
{Topic(2), {HashedDomain(1)}}};
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
expected_top_topics_and_observing_domains);
}
TEST_F(BrowsingTopicsCalculatorTest, DescendantTopicIsBlocked) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries(
{
kHost1,
kHost2,
kHost3,
kHost4,
kHost5,
},
begin_time);
AddApiUsageContextEntries({{kHost1, {HashedDomain(1)}},
{kHost2, {HashedDomain(2)}},
{kHost3, {HashedDomain(3)}},
{kHost4, {HashedDomain(4)}},
{kHost5, {HashedDomain(5)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
// 1 is the parent topic of 2-5.
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 5}},
{kHost2, {2, 3, 4, 5}},
{kHost3, {3, 4, 5}},
{kHost4, {4, 5}},
{kHost5, {5}},
});
privacy_sandbox_settings_->SetTopicAllowed(
privacy_sandbox::CanonicalTopic(Topic(5), kTaxonomyVersion),
/*allowed=*/false);
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
// topic 5 is cleared but topic 1 can still see its observing domains
std::vector<std::pair<Topic, std::set<HashedDomain>>>
expected_top_topics_and_observing_domains = {
{Topic(), {}},
{Topic(4),
{HashedDomain(1), HashedDomain(2), HashedDomain(3),
HashedDomain(4)}},
{Topic(3), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(2), {HashedDomain(1), HashedDomain(2)}},
{Topic(1),
{HashedDomain(1), HashedDomain(2), HashedDomain(3), HashedDomain(4),
HashedDomain(5)}}};
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
expected_top_topics_and_observing_domains);
}
TEST_F(BrowsingTopicsCalculatorTest, TopicHasDistantDescendant) {
base::Time begin_time = base::Time::Now();
AddHistoryEntries(
{
kHost1,
kHost2,
kHost3,
kHost4,
kHost5,
},
begin_time);
AddApiUsageContextEntries({{kHost1, {HashedDomain(1)}},
{kHost2, {HashedDomain(2)}},
{kHost3, {HashedDomain(3)}},
{kHost4, {HashedDomain(4)}},
{kHost5, {HashedDomain(5)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
// 1 is the parent topic of 2-4, and grandparent of 21.
test_annotator_.UseAnnotations({
{kHost1, {1, 2, 3, 4, 21}},
{kHost2, {2, 3, 4, 21}},
{kHost3, {3, 4, 21}},
{kHost4, {4, 21}},
{kHost5, {21}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
std::vector<std::pair<Topic, std::set<HashedDomain>>>
expected_top_topics_and_observing_domains = {
{Topic(21),
{HashedDomain(1), HashedDomain(2), HashedDomain(3), HashedDomain(4),
HashedDomain(5)}},
{Topic(4),
{HashedDomain(1), HashedDomain(2), HashedDomain(3),
HashedDomain(4)}},
{Topic(3), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(2), {HashedDomain(1), HashedDomain(2)}},
{Topic(1),
{HashedDomain(1), HashedDomain(2), HashedDomain(3), HashedDomain(4),
HashedDomain(5)}}};
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
expected_top_topics_and_observing_domains);
}
TEST_F(BrowsingTopicsCalculatorTest, MultipleTopTopicsHaveDescendants) {
// This test assumes no top topics prioritization.
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeatureWithParameters(
blink::features::kBrowsingTopicsParameters,
{{"prioritized_topics_list", ""}});
base::Time begin_time = base::Time::Now();
AddHistoryEntries(
{
kHost1,
kHost2,
kHost3,
kHost4,
kHost5,
},
begin_time);
AddApiUsageContextEntries({{kHost1, {HashedDomain(1)}},
{kHost2, {HashedDomain(2)}},
{kHost3, {HashedDomain(3)}},
{kHost4, {HashedDomain(4)}},
{kHost5, {HashedDomain(5)}}});
test_annotator_.UseModelInfo(
*optimization_guide::TestModelInfoBuilder().SetVersion(1).Build());
// 1 is the ancestor of 21, 57 is the ancestor of 63 and 64.
test_annotator_.UseAnnotations({
{kHost1, {1, 57, 63, 64, 21}},
{kHost2, {57, 63, 64, 21}},
{kHost3, {63, 64, 21}},
{kHost4, {64, 21}},
{kHost5, {21}},
});
task_environment_.AdvanceClock(base::Seconds(1));
EpochTopics result = CalculateTopics();
std::vector<std::pair<Topic, std::set<HashedDomain>>>
expected_top_topics_and_observing_domains = {
{Topic(21),
{HashedDomain(1), HashedDomain(2), HashedDomain(3), HashedDomain(4),
HashedDomain(5)}},
{Topic(64),
{HashedDomain(1), HashedDomain(2), HashedDomain(3),
HashedDomain(4)}},
{Topic(63), {HashedDomain(1), HashedDomain(2), HashedDomain(3)}},
{Topic(57),
{HashedDomain(1), HashedDomain(2), HashedDomain(3),
HashedDomain(4)}},
{Topic(1),
{HashedDomain(1), HashedDomain(2), HashedDomain(3), HashedDomain(4),
HashedDomain(5)}}};
ExpectResultTopicsEqual(result.top_topics_and_observing_domains(),
expected_top_topics_and_observing_domains);
}
} // namespace browsing_topics