blob: 15afcfd2cd2ca2a164bf31aa6469fd19be0eb5ca [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/user_education/recent_session_policy.h"
#include <sstream>
#include <vector>
#include "base/containers/map_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/user_education/browser_user_education_storage_service.h"
#include "chrome/browser/user_education/user_education_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
// Arbitrary date not too far from the current date.
// Use a time that will not be exactly midnight in any locale.
constexpr base::Time kNow = base::Time::FromDeltaSinceWindowsEpoch(
base::Days(150000) + base::Minutes(23));
// Calculates a set of start times in terms of time before kNow.
// The most recent time will always be kNow; the other times are
// added after and should be in increasing order of time interval.
RecentSessionData CreateSessionData(
const std::initializer_list<base::TimeDelta>& before_now,
const std::optional<base::TimeDelta>& since_enabled = base::Days(30)) {
RecentSessionData data;
data.recent_session_start_times.push_back(kNow);
for (const auto& delta : before_now) {
data.recent_session_start_times.push_back(kNow - delta);
}
if (since_enabled) {
data.enabled_time = kNow - *since_enabled;
}
return data;
}
using Constraint = RecentSessionPolicyImpl::Constraint;
using ConstraintInfo = RecentSessionPolicyImpl::ConstraintInfo;
using ConstraintInfos = RecentSessionPolicyImpl::ConstraintInfos;
constexpr char kTestHistogramName[] = "Test.Histogram";
constexpr char kTestHistogramName2[] = "Test.Histogram2";
class MockConstraint : public Constraint {
public:
MOCK_METHOD(std::optional<int>,
GetCount,
(const RecentSessionData&),
(const, override));
};
using StrictMockConstraint = testing::StrictMock<MockConstraint>;
using StrictMockConstraintPtr = raw_ptr<StrictMockConstraint>;
// Creates a constraint info with a StrictMockConstraint, which is output via
// `constraint`. Callers will need to set any expectations on the mock.
ConstraintInfo CreateMockConstraintInfo(StrictMockConstraintPtr& constraint,
std::string histogram_name,
std::optional<int> histogram_max,
std::optional<int> low_usage) {
auto constraint_ptr = std::make_unique<StrictMockConstraint>();
constraint = constraint_ptr.get();
return ConstraintInfo(std::move(constraint_ptr), std::move(histogram_name),
histogram_max, low_usage);
}
} // namespace
class RecentSessionPolicyTest : public testing::Test {
public:
RecentSessionPolicyTest() = default;
~RecentSessionPolicyTest() override = default;
void SetUp() override {
// Default setup is to initialize right away, but this can be skipped in
// other tests by overriding and replacing this behavior.
Init();
}
void TearDown() override { policy_.reset(); }
void Init(const base::FieldTrialParams& params = {}) {
feature_list_.InitAndEnableFeatureWithParameters(
kAllowRecentSessionTracking, params);
policy_ = std::make_unique<RecentSessionPolicyImpl>();
}
void EnsureBucketCounts(const std::string& name,
std::map<int, int> counts) const {
const auto buckets = histograms_.GetAllSamples(name);
for (const auto& bucket : buckets) {
if (bucket.count == 0) {
continue;
}
int* const expected = base::FindOrNull(counts, bucket.min);
if (!expected) {
ADD_FAILURE() << "Got unexpected bucket in " << name << ": "
<< bucket.min << " = " << bucket.count;
continue;
}
EXPECT_EQ(*expected, bucket.count) << "Got bucket with wrong count in "
<< name << " for entry " << bucket.min;
counts.erase(bucket.min);
}
for (const auto& count : counts) {
if (count.second != 0) {
ADD_FAILURE() << "Did not get expected entry in " << name << ": "
<< count.first;
}
}
}
protected:
base::HistogramTester histograms_;
std::unique_ptr<RecentSessionPolicyImpl> policy_;
private:
base::test::ScopedFeatureList feature_list_;
};
TEST_F(RecentSessionPolicyTest,
ShouldEnableLowUsagePromoMode_SingleConstraint) {
RecentSessionData data;
ConstraintInfos constraints;
StrictMockConstraintPtr mock_constraint;
constraints.emplace_back(
CreateMockConstraintInfo(mock_constraint, "", std::nullopt, 2));
policy_->set_constraints_for_testing(std::move(constraints));
// Returns below the threshold.
EXPECT_CALL(*mock_constraint, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(1));
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Returns equal to the threshold.
EXPECT_CALL(*mock_constraint, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(2));
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Returns above the threshold.
EXPECT_CALL(*mock_constraint, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(3));
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
}
TEST_F(RecentSessionPolicyTest,
ShouldEnableLowUsagePromoMode_MultipleConstraints) {
RecentSessionData data;
ConstraintInfos constraints;
StrictMockConstraintPtr mock_constraint1;
StrictMockConstraintPtr mock_constraint2;
constraints.emplace_back(
CreateMockConstraintInfo(mock_constraint1, "", std::nullopt, 2));
constraints.emplace_back(
CreateMockConstraintInfo(mock_constraint2, "", std::nullopt, 2));
policy_->set_constraints_for_testing(std::move(constraints));
// Both constraints below the threshold.
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(1));
EXPECT_CALL(*mock_constraint2, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(1));
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// One constraint above the threshold.
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(3));
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
// The other constraint above the threshold.
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(1));
EXPECT_CALL(*mock_constraint2, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(3));
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
// Both constraints above the threshold.
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(3));
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
}
TEST_F(RecentSessionPolicyTest,
ShouldEnableLowUsagePromoMode_HistogramOnlyConstraint) {
RecentSessionData data;
ConstraintInfos constraints;
StrictMockConstraintPtr mock_constraint1;
StrictMockConstraintPtr mock_constraint2;
constraints.emplace_back(
CreateMockConstraintInfo(mock_constraint1, "", std::nullopt, 2));
constraints.emplace_back(CreateMockConstraintInfo(
mock_constraint2, kTestHistogramName, 7, std::nullopt));
policy_->set_constraints_for_testing(std::move(constraints));
// Active constraint below the threshold.
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(1));
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Active constraint above the threshold.
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(3));
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
}
TEST_F(RecentSessionPolicyTest, RecordRecentUsageMetrics_SingleHistogram) {
RecentSessionData data;
ConstraintInfos constraints;
StrictMockConstraintPtr mock_constraint;
constraints.emplace_back(CreateMockConstraintInfo(
mock_constraint, kTestHistogramName, 4, std::nullopt));
policy_->set_constraints_for_testing(std::move(constraints));
EXPECT_CALL(*mock_constraint, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(1));
policy_->RecordRecentUsageMetrics(data);
EXPECT_CALL(*mock_constraint, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(std::nullopt));
policy_->RecordRecentUsageMetrics(data);
EXPECT_CALL(*mock_constraint, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(2));
policy_->RecordRecentUsageMetrics(data);
EXPECT_CALL(*mock_constraint, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(2));
policy_->RecordRecentUsageMetrics(data);
EXPECT_CALL(*mock_constraint, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(7));
policy_->RecordRecentUsageMetrics(data);
histograms_.ExpectTotalCount(kTestHistogramName, 4);
histograms_.ExpectBucketCount(kTestHistogramName, 1, 1);
histograms_.ExpectBucketCount(kTestHistogramName, 2, 2);
histograms_.ExpectBucketCount(kTestHistogramName, 4, 1);
}
TEST_F(RecentSessionPolicyTest, RecordRecentUsageMetrics_TwoHistograms) {
RecentSessionData data;
ConstraintInfos constraints;
StrictMockConstraintPtr mock_constraint1;
StrictMockConstraintPtr mock_constraint2;
constraints.emplace_back(CreateMockConstraintInfo(
mock_constraint1, kTestHistogramName, 4, std::nullopt));
constraints.emplace_back(CreateMockConstraintInfo(
mock_constraint2, kTestHistogramName2, 4, std::nullopt));
policy_->set_constraints_for_testing(std::move(constraints));
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(1));
EXPECT_CALL(*mock_constraint2, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(std::nullopt));
policy_->RecordRecentUsageMetrics(data);
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(1));
EXPECT_CALL(*mock_constraint2, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(2));
policy_->RecordRecentUsageMetrics(data);
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(2));
EXPECT_CALL(*mock_constraint2, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(3));
policy_->RecordRecentUsageMetrics(data);
EXPECT_CALL(*mock_constraint1, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(4));
EXPECT_CALL(*mock_constraint2, GetCount(testing::Ref(data)))
.WillOnce(testing::Return(7));
policy_->RecordRecentUsageMetrics(data);
histograms_.ExpectTotalCount(kTestHistogramName, 4);
histograms_.ExpectBucketCount(kTestHistogramName, 1, 2);
histograms_.ExpectBucketCount(kTestHistogramName, 2, 1);
histograms_.ExpectBucketCount(kTestHistogramName, 4, 1);
histograms_.ExpectTotalCount(kTestHistogramName2, 3);
histograms_.ExpectBucketCount(kTestHistogramName2, 2, 1);
histograms_.ExpectBucketCount(kTestHistogramName2, 3, 1);
histograms_.ExpectBucketCount(kTestHistogramName2, 4, 1);
}
TEST_F(RecentSessionPolicyTest, SessionCountConstraint) {
RecentSessionPolicyImpl::SessionCountConstraint constraint(7);
// Too short a time to render a count:
EXPECT_EQ(std::nullopt, constraint.GetCount(CreateSessionData(
{base::Days(3)}, base::Days(5))));
EXPECT_EQ(std::nullopt,
constraint.GetCount(CreateSessionData(
{base::Days(3)}, base::Days(7) - base::Seconds(1))));
// Just long enough to render a count:
EXPECT_EQ(2, constraint.GetCount(
CreateSessionData({base::Days(3)}, base::Days(7))));
// Time outside window - only current session is counted:
EXPECT_EQ(1, constraint.GetCount(CreateSessionData(
{base::Days(7) + base::Seconds(1)}, base::Days(7))));
// Many times:
EXPECT_EQ(4,
constraint.GetCount(CreateSessionData(
{base::Days(10), base::Days(6), base::Days(4), base::Days(2)},
base::Days(7))));
}
TEST_F(RecentSessionPolicyTest, ActiveDaysConstraint) {
RecentSessionPolicyImpl::ActiveDaysConstraint constraint(7);
// Too short a time to render a count:
EXPECT_EQ(std::nullopt, constraint.GetCount(CreateSessionData(
{base::Days(3)}, base::Days(5))));
// Since days are counted back from the following midnight, exactly 7 days is
// enough to enable counting.
EXPECT_EQ(2, constraint.GetCount(
CreateSessionData({base::Days(3)}, base::Days(7))));
// Multiple active days with more than one session on a day.
EXPECT_EQ(3, constraint.GetCount(CreateSessionData(
{// In same day as most recent session.
base::Minutes(5),
// In previous day.
base::Days(1), base::Days(1) + base::Minutes(5),
// Several days ago.
base::Days(3)},
base::Days(10))));
// Multiple active days with more than one session on a day, and sessions
// outside the period.
EXPECT_EQ(4, constraint.GetCount(CreateSessionData(
{base::Days(1), base::Days(3), base::Days(6), base::Days(8),
base::Days(12)},
base::Days(15))));
}
TEST_F(RecentSessionPolicyTest, ActiveWeeksConstraint) {
RecentSessionPolicyImpl::ActiveWeeksConstraint constraint(4, 1);
// Too short a time to render a count:
EXPECT_EQ(std::nullopt, constraint.GetCount(CreateSessionData(
{base::Days(3)}, base::Days(27))));
// Since days are counted back from the following midnight, exactly 28 days is
// enough to enable counting.
EXPECT_EQ(2, constraint.GetCount(
CreateSessionData({base::Days(10)}, base::Days(28))));
// Multiple active weeks with more than one session in a week.
EXPECT_EQ(3, constraint.GetCount(CreateSessionData(
{// In same week as most recent session.
base::Days(2), base::Days(4),
// Exactly seven days will shunt into a different week,
// because of counting from next midnight.
base::Days(7), base::Days(9),
// Three weeks ago.
base::Days(25)})));
// Multiple active weeks with more than one session in a week, and sessions
// outside the period.
EXPECT_EQ(2, constraint.GetCount(CreateSessionData(
{base::Days(1), base::Days(3), base::Days(6), base::Days(8),
base::Days(12), base::Days(29)})));
}
TEST_F(RecentSessionPolicyTest, ActiveWeeksConstraintWithThreshold) {
RecentSessionPolicyImpl::ActiveWeeksConstraint constraint(4, 2);
// Too short a time to render a count:
EXPECT_EQ(std::nullopt, constraint.GetCount(CreateSessionData(
{base::Days(3)}, base::Days(27))));
// Since days are counted back from the following midnight, exactly 28 days is
// enough to enable counting.
EXPECT_EQ(0, constraint.GetCount(
CreateSessionData({base::Days(10)}, base::Days(28))));
// Multiple active weeks with more than one session in a week.
EXPECT_EQ(2, constraint.GetCount(CreateSessionData(
{// In same week as most recent session.
base::Days(2), base::Days(4),
// Exactly seven days will shunt into a different week,
// because of counting from next midnight.
base::Days(7), base::Days(9),
// Three weeks ago.
base::Days(25)})));
// Multiple active weeks with more than one session in a week, and sessions
// outside the period.
EXPECT_EQ(3, constraint.GetCount(CreateSessionData(
{base::Days(1), base::Days(3), base::Days(6), base::Days(8),
base::Days(12), base::Days(19), base::Days(20),
base::Days(29)})));
}
TEST_F(RecentSessionPolicyTest,
ShouldEnableLowUsagePromoMode_OffWhenNotEnabledForLongEnough) {
// Only one session, but not enabled long enough for the long threshold.
auto data = CreateSessionData({}, base::Days(19));
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
// Not enough in any threshold, not enabled long enough for any threshold.
data = CreateSessionData({base::Days(2), base::Days(15)}, base::Days(25));
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
// Not enough in any threshold, enabled at the longer threshold.
data = CreateSessionData({base::Days(10)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
}
TEST_F(RecentSessionPolicyTest,
ShouldEnableLowUsagePromoMode_OffMoreThanTwoActiveDays) {
// Two days, same week.
auto data = CreateSessionData({base::Days(1)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Two days, different weeks.
data = CreateSessionData({base::Days(8)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Three days one week.
data = CreateSessionData({base::Days(1), base::Days(3)});
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
// Three days multiple weeks.
data = CreateSessionData({base::Days(2), base::Days(22)});
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
}
TEST_F(RecentSessionPolicyTest, RecordRecentUsageMetrics_LessThanOneWeek) {
policy_->RecordRecentUsageMetrics(
CreateSessionData({base::Days(1), base::Days(2)}, base::Days(4)));
EnsureBucketCounts("UserEducation.Session.ShortTermCount", {});
EnsureBucketCounts("UserEducation.Session.LongTermCount", {});
EnsureBucketCounts("UserEducation.Session.MonthlyActiveDays", {});
EnsureBucketCounts("UserEducation.Session.RecentActiveDays", {});
EnsureBucketCounts("UserEducation.Session.RecentActiveWeeks", {});
EnsureBucketCounts("UserEducation.Session.RecentSuperActiveWeeks", {});
}
TEST_F(RecentSessionPolicyTest, RecordRecentUsageMetrics_MoreThanOneWeek) {
policy_->RecordRecentUsageMetrics(
CreateSessionData({base::Days(1), base::Days(1) + base::Minutes(5),
base::Days(2), base::Days(6)},
base::Days(8)));
EnsureBucketCounts("UserEducation.Session.ShortTermCount", {{5, 1}});
EnsureBucketCounts("UserEducation.Session.LongTermCount", {});
EnsureBucketCounts("UserEducation.Session.MonthlyActiveDays", {});
EnsureBucketCounts("UserEducation.Session.RecentActiveDays", {{4, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveWeeks", {});
EnsureBucketCounts("UserEducation.Session.RecentSuperActiveWeeks", {});
}
TEST_F(RecentSessionPolicyTest, RecordRecentUsageMetrics_FullPeriod) {
policy_->RecordRecentUsageMetrics(CreateSessionData(
{base::Days(1), base::Days(1) + base::Minutes(5), base::Days(2),
base::Days(6), base::Days(15), base::Days(20)}));
EnsureBucketCounts("UserEducation.Session.ShortTermCount", {{5, 1}});
EnsureBucketCounts("UserEducation.Session.LongTermCount", {{7, 1}});
EnsureBucketCounts("UserEducation.Session.MonthlyActiveDays", {{6, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveDays", {{4, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveWeeks", {{2, 1}});
EnsureBucketCounts("UserEducation.Session.RecentSuperActiveWeeks", {{1, 1}});
}
TEST_F(RecentSessionPolicyTest,
RecordRecentUsageMetrics_SuperActiveCountsDaysNotSessions) {
policy_->RecordRecentUsageMetrics(CreateSessionData(
{// Initial week with four active days (counting day zero) and no
// additional sessions.
base::Days(1), base::Days(2), base::Days(6),
// Second week with three active days but four sessions.
base::Days(15), base::Days(15) + base::Minutes(5),
base::Days(15) + base::Minutes(10),
base::Days(15) + base::Minutes(15)}));
EnsureBucketCounts("UserEducation.Session.ShortTermCount", {{4, 1}});
EnsureBucketCounts("UserEducation.Session.LongTermCount", {{8, 1}});
EnsureBucketCounts("UserEducation.Session.MonthlyActiveDays", {{5, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveDays", {{4, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveWeeks", {{2, 1}});
EnsureBucketCounts("UserEducation.Session.RecentSuperActiveWeeks", {{1, 1}});
}
TEST_F(RecentSessionPolicyTest, RecordRecentUsageMetrics_DailyLimit) {
auto data = CreateSessionData(
{base::Days(1), base::Days(1) + base::Minutes(5), base::Days(2),
base::Days(6), base::Days(15), base::Days(20)});
policy_->RecordRecentUsageMetrics(data);
EnsureBucketCounts("UserEducation.Session.ShortTermCount", {{5, 1}});
EnsureBucketCounts("UserEducation.Session.LongTermCount", {{7, 1}});
EnsureBucketCounts("UserEducation.Session.MonthlyActiveDays", {{6, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveDays", {{4, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveWeeks", {{2, 1}});
EnsureBucketCounts("UserEducation.Session.RecentSuperActiveWeeks", {{1, 1}});
// Start another session almost right away, so it's in the same day.
data.recent_session_start_times.insert(
data.recent_session_start_times.begin(),
data.recent_session_start_times.front() + base::Seconds(5));
policy_->RecordRecentUsageMetrics(data);
// Session-based metrics should still be recorded.
EnsureBucketCounts("UserEducation.Session.ShortTermCount", {{5, 1}, {6, 1}});
EnsureBucketCounts("UserEducation.Session.LongTermCount", {{7, 1}, {8, 1}});
// Daily and weekly metrics, however, should not.
EnsureBucketCounts("UserEducation.Session.MonthlyActiveDays", {{6, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveDays", {{4, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveWeeks", {{2, 1}});
EnsureBucketCounts("UserEducation.Session.RecentSuperActiveWeeks", {{1, 1}});
// Start another session on the next calendar day.
data.recent_session_start_times.insert(
data.recent_session_start_times.begin(),
data.recent_session_start_times.front() + base::Days(1));
policy_->RecordRecentUsageMetrics(data);
// All metrics should now be recorded. Some days will have shifted to the next
// week.
EnsureBucketCounts("UserEducation.Session.ShortTermCount", {{5, 1}, {6, 2}});
EnsureBucketCounts("UserEducation.Session.LongTermCount",
{{7, 1}, {8, 1}, {9, 1}});
EnsureBucketCounts("UserEducation.Session.MonthlyActiveDays",
{{6, 1}, {7, 1}});
EnsureBucketCounts("UserEducation.Session.RecentActiveDays", {{4, 2}});
EnsureBucketCounts("UserEducation.Session.RecentActiveWeeks",
{{2, 1}, {4, 1}});
EnsureBucketCounts("UserEducation.Session.RecentSuperActiveWeeks", {{1, 2}});
}
class RecentSessionPolicyFinchTest : public RecentSessionPolicyTest {
public:
RecentSessionPolicyFinchTest() = default;
~RecentSessionPolicyFinchTest() override = default;
// Don't initialize during setup.
void SetUp() override {}
};
TEST_F(RecentSessionPolicyFinchTest, ChangeExistingThresholds) {
Init({{"max_active_weeks", "1"}, {"max_active_days", "2"}});
// Two days, one week.
auto data = CreateSessionData({base::Days(2)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Two days, one week, but more entries.
data = CreateSessionData({base::Days(2), base::Days(2) + base::Minutes(5)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Three days, one week.
data = CreateSessionData({base::Days(2), base::Days(4)});
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
// Two days, two weeks.
data = CreateSessionData({base::Days(2), base::Days(8)});
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
}
TEST_F(RecentSessionPolicyFinchTest, SwitchToNewThresholds) {
Init({{"max_active_weeks", "0"},
{"max_active_days", "0"},
{"max_monthly_active_days", "0"},
{"max_weekly_sessions", "2"},
{"max_monthly_sessions", "5"}});
// Two sessions.
auto data = CreateSessionData({base::Days(2)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Three sessions, two days.
data = CreateSessionData({base::Days(2), base::Days(2) + base::Minutes(5)});
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
// Three sessions spread over three active weeks.
data = CreateSessionData({base::Days(8), base::Days(16)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Six sessions in two active weeks.
data = CreateSessionData({base::Days(2), base::Days(8), base::Days(9),
base::Days(10), base::Days(11)});
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
}
TEST_F(RecentSessionPolicyFinchTest, EnableSuperActiveThreshold) {
Init({{"max_active_days", "0"},
{"max_active_weeks", "0"},
{"max_monthly_active_days", "0"},
{"super_active_days", "3"},
{"max_super_active_weeks", "1"}});
// Two sessions.
auto data = CreateSessionData({base::Days(2)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Three sessions, two weeks.
data = CreateSessionData({base::Days(2), base::Days(12)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Three weeks, one super active week.
data = CreateSessionData({base::Days(8), base::Days(9), base::Days(10),
base::Days(11), base::Days(16)});
EXPECT_TRUE(policy_->ShouldEnableLowUsagePromoMode(data));
// Two super active weeks by minimum definition.
data = CreateSessionData({base::Days(8), base::Days(9), base::Days(10),
base::Days(15), base::Days(16), base::Days(17)});
EXPECT_FALSE(policy_->ShouldEnableLowUsagePromoMode(data));
}