blob: e9d857e74bc465990222d199b66d7e3016d2dd22 [file] [log] [blame]
// Copyright 2023 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/ssl/daily_navigation_counter.h"
#include "base/test/simple_test_clock.h"
#include "base/values.h"
#include "testing/gtest/include/gtest/gtest.h"
constexpr char kStartTime[] = "2023-10-15T06:00:00Z";
// Navigation counter should be able to load the counts from a dict.
TEST(DailyNavigationCounterTest, ShouldLoadFromDict) {
base::SimpleTestClock clock;
base::Time now;
EXPECT_TRUE(base::Time::FromUTCString(kStartTime, &now));
clock.SetNow(now);
base::Value::Dict dict;
DailyNavigationCounter counter1(&dict, &clock,
/*rolling_window_duration_in_days=*/1u,
/*save_interval=*/1);
EXPECT_EQ(0u, counter1.GetTotal());
EXPECT_EQ(0u, counter1.unsaved_count_for_testing());
EXPECT_TRUE(counter1.Increment());
EXPECT_EQ(1u, counter1.GetTotal());
EXPECT_EQ(0u, counter1.unsaved_count_for_testing());
EXPECT_TRUE(counter1.Increment());
EXPECT_EQ(2u, counter1.GetTotal());
EXPECT_EQ(0u, counter1.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Hours(13));
EXPECT_TRUE(counter1.Increment());
EXPECT_EQ(3u, counter1.GetTotal());
EXPECT_EQ(0u, counter1.unsaved_count_for_testing());
DailyNavigationCounter counter2(&dict, &clock,
/*rolling_window_duration_in_days=*/1u,
/*save_interval=*/1);
EXPECT_EQ(3u, counter1.GetTotal());
EXPECT_EQ(0u, counter1.unsaved_count_for_testing());
EXPECT_TRUE(counter2.Increment());
EXPECT_EQ(4u, counter2.GetTotal());
EXPECT_EQ(0u, counter2.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Hours(14));
EXPECT_TRUE(counter2.Increment());
EXPECT_EQ(5u, counter2.GetTotal());
EXPECT_EQ(0u, counter2.unsaved_count_for_testing());
// Advance the clock a day and record again. This will keep all entries
// because entries added yesterday are within the rolling window.
clock.SetNow(now + base::Hours(25));
EXPECT_TRUE(counter2.Increment());
EXPECT_EQ(6u, counter2.GetTotal());
EXPECT_EQ(0u, counter2.unsaved_count_for_testing());
// Advance the clock further and record again. This will drop 5 old entries
// from the first day.
clock.SetNow(now + base::Hours(49));
EXPECT_TRUE(counter2.Increment());
EXPECT_EQ(2u, counter2.GetTotal());
EXPECT_EQ(0u, counter2.unsaved_count_for_testing());
}
// Navigation counter should properly handle counts using a small rolling
// window and small saving interval.
TEST(DailyNavigationCounterTest, SmallRollingWindowSmallInterval) {
base::SimpleTestClock clock;
base::Time now;
EXPECT_TRUE(base::Time::FromUTCString(kStartTime, &now));
clock.SetNow(now);
base::Value::Dict dict;
DailyNavigationCounter counter(&dict, &clock,
/*rolling_window_duration_in_days=*/1u,
/*save_interval=*/1);
EXPECT_EQ(0u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(1u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(2u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Hours(13));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(3u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will drop old entries and only
// keep the last entry.
clock.SetNow(now + base::Hours(26));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(4u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will drop 3 old entries from the
// first day.
clock.SetNow(now + base::Hours(49));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(2u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
}
// Navigation counter should properly handle counts using a large rolling
// window and small saving interval.
TEST(DailyNavigationCounterTest, LargeRollingWindowSmallInterval) {
base::SimpleTestClock clock;
base::Time now;
EXPECT_TRUE(base::Time::FromUTCString(kStartTime, &now));
clock.SetNow(now);
base::Value::Dict dict;
DailyNavigationCounter counter(&dict, &clock,
/*rolling_window_duration_in_days=*/7u,
/*save_interval=*/1);
EXPECT_EQ(0u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
EXPECT_TRUE(counter.Increment());
clock.SetNow(now + base::Hours(6));
EXPECT_TRUE(counter.Increment());
clock.SetNow(now + base::Hours(12));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(3u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
clock.SetNow(now + base::Days(1));
EXPECT_TRUE(counter.Increment());
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(5u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(2));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(6u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(3));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(7u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(4));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(8u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(5));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(9u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(6));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(10u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries because they
// are still inside the rolling window.
clock.SetNow(now + base::Days(7));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(11u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will drop the 3 entries from the
// second day.
clock.SetNow(now + base::Days(8));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(9u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock very far and record again. This will drop all entries but
// the last one.
clock.SetNow(now + base::Days(30));
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(1u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
}
// Navigation counter should properly handle counts using a small rolling
// window and large saving interval.
TEST(DailyNavigationCounterTest, SmallRollingWindowLargeInterval) {
base::SimpleTestClock clock;
base::Time now;
EXPECT_TRUE(base::Time::FromUTCString(kStartTime, &now));
clock.SetNow(now);
base::Value::Dict dict;
DailyNavigationCounter counter(&dict, &clock,
/*rolling_window_duration_in_days=*/1u,
/*save_interval=*/10);
EXPECT_EQ(0u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Recording 9 times won't save the count in the pref.
for (size_t i = 0; i < 9; i++) {
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(i + 1, counter.GetTotal());
EXPECT_EQ(i + 1, counter.unsaved_count_for_testing());
}
// ... but the 10th time will.
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(10u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Record another 9 times, this also won't save the count in the pref.
for (size_t i = 0; i < 9; i++) {
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(11u + i, counter.GetTotal());
EXPECT_EQ(i + 1, counter.unsaved_count_for_testing());
}
// ... but the 20th time will.
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(20u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Hours(13));
EXPECT_FALSE(counter.Increment());
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(22u, counter.GetTotal());
EXPECT_EQ(2u, counter.unsaved_count_for_testing());
// Advance the clock to next day and record 8 times. This will keep all
// entries as they are still inside the rolling window.
clock.SetNow(now + base::Hours(26));
for (size_t i = 0; i < 7; i++) {
EXPECT_FALSE(counter.Increment());
}
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(30u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock to another day and record 10 times. The first nine
// increments won't discard anything, but the last increment will discard 22
// old entries from the first day and only keep the entries from today and
// yesterday.
clock.SetNow(now + base::Hours(49));
for (size_t i = 0; i < 9; i++) {
EXPECT_FALSE(counter.Increment());
}
EXPECT_EQ(39u, counter.GetTotal());
EXPECT_EQ(9u, counter.unsaved_count_for_testing());
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(18u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
}
// Navigation counter should properly handle counts using a large rolling
// window and large saving interval.
TEST(DailyNavigationCounterTest, LargeRollingWindowLargeInterval) {
base::SimpleTestClock clock;
base::Time now;
EXPECT_TRUE(base::Time::FromUTCString(kStartTime, &now));
clock.SetNow(now);
base::Value::Dict dict;
DailyNavigationCounter counter(&dict, &clock,
/*rolling_window_duration_in_days=*/7u,
/*save_interval=*/10);
EXPECT_EQ(0u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Recording 9 times won't save the count in the pref.
for (size_t i = 0; i < 9; i++) {
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(i + 1, counter.GetTotal());
EXPECT_EQ(i + 1, counter.unsaved_count_for_testing());
}
// ... but the 10th time will.
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(10u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Record another 9 times, this also won't save the count in the pref.
for (size_t i = 0; i < 9; i++) {
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(11u + i, counter.GetTotal());
EXPECT_EQ(i + 1, counter.unsaved_count_for_testing());
}
// ... but the 20th time will.
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(20u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Hours(13));
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(21u, counter.GetTotal());
EXPECT_EQ(1u, counter.unsaved_count_for_testing());
// Advance the clock and record twice. This will keep all entries.
clock.SetNow(now + base::Hours(25));
EXPECT_FALSE(counter.Increment());
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(23u, counter.GetTotal());
EXPECT_EQ(3u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(2));
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(24u, counter.GetTotal());
EXPECT_EQ(4u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(3));
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(25u, counter.GetTotal());
EXPECT_EQ(5u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(4));
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(26u, counter.GetTotal());
EXPECT_EQ(6u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(5));
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(27u, counter.GetTotal());
EXPECT_EQ(7u, counter.unsaved_count_for_testing());
// Advance the clock and record again. This will keep all entries.
clock.SetNow(now + base::Days(6));
EXPECT_FALSE(counter.Increment());
EXPECT_EQ(28u, counter.GetTotal());
EXPECT_EQ(8u, counter.unsaved_count_for_testing());
// Advance the clock and record twice. This will keep all entries as they are
// still inside the rolling window.
clock.SetNow(now + base::Days(7));
EXPECT_FALSE(counter.Increment());
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(30u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record ten times. This will drop the 21 entries from
// the first day.
clock.SetNow(now + base::Days(8));
for (size_t i = 0; i < 9; i++) {
EXPECT_FALSE(counter.Increment());
}
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(19u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock and record ten times. This will drop the 2 entries from
// the second day.
clock.SetNow(now + base::Days(9));
for (size_t i = 0; i < 9; i++) {
EXPECT_FALSE(counter.Increment());
}
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(27u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
// Advance the clock very far and record ten times. This will all entries but
// the last ten.
clock.SetNow(now + base::Days(30));
for (size_t i = 0; i < 9; i++) {
EXPECT_FALSE(counter.Increment());
}
EXPECT_EQ(36u, counter.GetTotal());
EXPECT_EQ(9u, counter.unsaved_count_for_testing());
EXPECT_TRUE(counter.Increment());
EXPECT_EQ(10u, counter.GetTotal());
EXPECT_EQ(0u, counter.unsaved_count_for_testing());
}