blob: c7cd538000dbcacfefdb7e9c945b9874c8102c99 [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 "content/browser/interest_group/noiser_and_bucketer.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
// The function should sometimes return not equal, within the range.
template <typename Function, typename T>
void EqualAndNotEqual(T input,
int expected,
Function function,
int min,
int max) {
bool seen_equal = false, seen_not_equal = false;
while (!seen_equal || !seen_not_equal) {
int actual = function(input);
EXPECT_GE(actual, min);
EXPECT_LE(actual, max);
if (actual == expected) {
seen_equal = true;
} else {
seen_not_equal = true;
}
}
}
TEST(NoiserAndBucketerTest, JoinCount) {
constexpr int kMin = 1, kMax = 16;
// clang-format off
const struct {
int input;
int expected;
} kTestCases[] = {
{-2, 1},
{-1, 1},
{0, 1},
{1, 1},
{2, 2},
{3, 3},
{4, 4},
{5, 5},
{6, 6},
{7, 7},
{8, 8},
{9, 9},
{10, 10},
{11, 11},
{19, 11},
{20, 11},
{21, 12},
{29, 12},
{30, 12},
{31, 13},
{32, 13},
{39, 13},
{40, 13},
{41, 14},
{42, 14},
{49, 14},
{50, 14},
{51, 15},
{52, 15},
{60, 15},
{70, 15},
{80, 15},
{90, 15},
{99, 15},
{100, 15},
{101, 16},
{200, 16},
{1000, 16},
};
// clang-format on
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(test_case.input);
EXPECT_EQ(internals::BucketJoinCount(test_case.input), test_case.expected);
EqualAndNotEqual(/*input=*/test_case.input, /*expected=*/test_case.expected,
/*function=*/NoiseAndBucketJoinCount,
/*min=*/kMin, /*max=*/kMax);
}
}
TEST(NoiserAndBucketerTest, Recency) {
constexpr int kMin = 0, kMax = 31;
// clang-format off
const struct {
base::TimeDelta input;
int expected;
} kTestCases[] = {
{base::Minutes(-2), 0},
{base::Minutes(-1), 0},
{base::Minutes(0), 0},
{base::Minutes(1), 1},
{base::Minutes(2), 2},
{base::Minutes(3), 3},
{base::Minutes(4), 4},
{base::Minutes(5), 5},
{base::Minutes(6), 6},
{base::Minutes(7), 7},
{base::Minutes(8), 8},
{base::Minutes(9), 9},
{base::Minutes(10), 10},
{base::Minutes(11), 10},
{base::Minutes(13), 10},
{base::Minutes(14), 10},
{base::Minutes(15), 11},
{base::Minutes(16), 11},
{base::Minutes(18), 11},
{base::Minutes(19), 11},
{base::Minutes(20), 12},
{base::Minutes(21), 12},
{base::Minutes(28), 12},
{base::Minutes(29), 12},
{base::Minutes(30), 13},
{base::Minutes(31), 13},
{base::Minutes(38), 13},
{base::Minutes(39), 13},
{base::Minutes(40), 14},
{base::Minutes(41), 14},
{base::Minutes(48), 14},
{base::Minutes(49), 14},
{base::Minutes(50), 15},
{base::Minutes(51), 15},
{base::Minutes(58), 15},
{base::Minutes(59), 15},
{base::Minutes(60), 16},
{base::Minutes(61), 16},
{base::Minutes(73), 16},
{base::Minutes(74), 16},
{base::Minutes(75), 17},
{base::Minutes(76), 17},
{base::Minutes(88), 17},
{base::Minutes(89), 17},
{base::Minutes(90), 18},
{base::Minutes(91), 18},
{base::Minutes(103), 18},
{base::Minutes(104), 18},
{base::Minutes(105), 19},
{base::Minutes(106), 19},
{base::Minutes(118), 19},
{base::Minutes(119), 19},
{base::Minutes(120), 20},
{base::Minutes(121), 20},
{base::Minutes(238), 20},
{base::Minutes(239), 20},
{base::Minutes(240), 21},
{base::Minutes(241), 21},
{base::Minutes(718), 21},
{base::Minutes(719), 21},
{base::Minutes(720), 22},
{base::Minutes(721), 22},
{base::Minutes(1438), 22},
{base::Minutes(1439), 22},
{base::Minutes(1440), 23},
{base::Minutes(1441), 23},
{base::Minutes(2158), 23},
{base::Minutes(2159), 23},
{base::Minutes(2160), 24},
{base::Minutes(2161), 24},
{base::Minutes(2878), 24},
{base::Minutes(2879), 24},
{base::Minutes(2880), 25},
{base::Minutes(2881), 25},
{base::Minutes(4318), 25},
{base::Minutes(4319), 25},
{base::Minutes(4320), 26},
{base::Minutes(4321), 26},
{base::Minutes(5758), 26},
{base::Minutes(5759), 26},
{base::Minutes(5760), 27},
{base::Minutes(5761), 27},
{base::Minutes(10078), 27},
{base::Minutes(10079), 27},
{base::Minutes(10080), 28},
{base::Minutes(10081), 28},
{base::Minutes(20158), 28},
{base::Minutes(20159), 28},
{base::Minutes(20160), 29},
{base::Minutes(20161), 29},
{base::Minutes(30238), 29},
{base::Minutes(30239), 29},
{base::Minutes(30240), 30},
{base::Minutes(30241), 30},
{base::Minutes(40318), 30},
{base::Minutes(40319), 30},
{base::Minutes(40320), 31},
{base::Minutes(40321), 31},
{base::Minutes(1000000), 31},
{base::Minutes(1000000000), 31},
};
// clang-format on
for (const auto& test_case : kTestCases) {
SCOPED_TRACE(test_case.input.InMinutes());
EXPECT_EQ(internals::BucketRecency(test_case.input), test_case.expected);
EqualAndNotEqual(/*input=*/test_case.input, /*expected=*/test_case.expected,
/*function=*/NoiseAndBucketRecency,
/*min=*/kMin, /*max=*/kMax);
}
}
TEST(NoiserAndBucketerTest, ModelingSignals) {
constexpr uint16_t kMin = 0, kMax = 0x0FFF;
for (uint16_t i = kMin; i <= kMax; i++) {
SCOPED_TRACE(i);
EqualAndNotEqual(/*input=*/i, /*expected=*/i,
/*function=*/NoiseAndMaskModelingSignals, /*min=*/kMin,
/*max=*/kMax);
}
}
} // namespace
} // namespace content