blob: 728454359a4b71bc883afb2fe66d1559d12e3162 [file] [log] [blame]
// 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 "components/reporting/client/report_queue_configuration.h"
#include <cstddef>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/test/task_environment.h"
#include "components/reporting/proto/synced/record_constants.pb.h"
#include "components/reporting/util/rate_limiter_interface.h"
#include "components/reporting/util/status.h"
#include "components/reporting/util/status_macros.h"
#include "components/reporting/util/statusor.h"
#include "components/reporting/util/test_support_callbacks.h"
#include "components/reporting/util/wrapped_rate_limiter.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::Eq;
using ::testing::Return;
using ::testing::StrEq;
using ::testing::WithArgs;
namespace reporting {
namespace {
constexpr char kDmToken[] = "dm_token";
class MockRateLimiter : public RateLimiterInterface {
public:
MOCK_METHOD(bool, Acquire, (size_t event_size), (override));
};
class ReportQueueConfigurationTest : public ::testing::Test {
protected:
using PolicyCheckCallback = ReportQueueConfiguration::PolicyCheckCallback;
const Destination kInvalidDestination = Destination::UNDEFINED_DESTINATION;
const Destination kValidDestination = Destination::UPLOAD_EVENTS;
const PolicyCheckCallback kValidCallback = GetSuccessfulCallback();
const PolicyCheckCallback kInvalidCallback = GetInvalidCallback();
static PolicyCheckCallback GetSuccessfulCallback() {
return base::BindRepeating([]() { return Status::StatusOK(); });
}
static PolicyCheckCallback GetInvalidCallback() {
return base::RepeatingCallback<Status(void)>();
}
base::test::TaskEnvironment task_environment_;
};
// Tests to ensure that only valid parameters are used to generate a
// ReportQueueConfiguration.
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithInvalidDestination) {
StatusOr<std::unique_ptr<ReportQueueConfiguration>> config_result =
ReportQueueConfiguration::Builder({.destination = kInvalidDestination})
.SetDMToken(kDmToken)
.SetPolicyCheckCallback(kValidCallback)
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithInvalidDestinationInvalidCallback) {
auto config_result =
ReportQueueConfiguration::Create({.destination = kInvalidDestination})
.SetPolicyCheckCallback(kInvalidCallback)
.SetDMToken(kDmToken)
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest, ValidateConfigurationWithValidParams) {
auto config_result =
ReportQueueConfiguration::Create({.destination = kValidDestination})
.SetDMToken(kDmToken)
.SetPolicyCheckCallback(kValidCallback)
.Build();
EXPECT_OK(config_result) << config_result.error();
}
TEST_F(ReportQueueConfigurationTest, ValidateConfigurationWithNoDMToken) {
auto config_result =
ReportQueueConfiguration::Create({.destination = kValidDestination})
.SetPolicyCheckCallback(kValidCallback)
.Build();
EXPECT_OK(config_result) << config_result.error();
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithNoDMTokenInvalidDestination) {
auto config_result =
ReportQueueConfiguration::Create({.destination = kInvalidDestination})
.SetPolicyCheckCallback(kValidCallback)
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithNoDMTokenInvalidCallback) {
auto config_result =
ReportQueueConfiguration::Create({.destination = kValidDestination})
.SetPolicyCheckCallback(kInvalidCallback)
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithNoDMTokenInvalidDestinationInvalidCallback) {
auto config_result =
ReportQueueConfiguration::Create({.destination = kInvalidDestination})
.SetPolicyCheckCallback(kInvalidCallback)
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest, ValidateConfigurationWithDeviceEventType) {
auto config_result =
ReportQueueConfiguration::Create(
{.event_type = EventType::kDevice, .destination = kValidDestination})
.SetPolicyCheckCallback(kValidCallback)
.Build();
EXPECT_OK(config_result) << config_result.error();
}
TEST_F(ReportQueueConfigurationTest, ValidateConfigurationWithUserEventType) {
auto config_result =
ReportQueueConfiguration::Create(
{.event_type = EventType::kUser, .destination = kValidDestination})
.SetPolicyCheckCallback(kValidCallback)
.Build();
EXPECT_OK(config_result) << config_result.error();
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithEventTypeInvalidDestination) {
auto config_result =
ReportQueueConfiguration::Create({.event_type = EventType::kDevice,
.destination = kInvalidDestination})
.SetPolicyCheckCallback(kValidCallback)
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithEventTypeInvalidCallback) {
auto config_result =
ReportQueueConfiguration::Create(
{.event_type = EventType::kDevice, .destination = kValidDestination})
.SetPolicyCheckCallback(kInvalidCallback)
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithEventTypeInvalidReservedSpace) {
auto config_result =
ReportQueueConfiguration::Create({.event_type = EventType::kDevice,
.destination = kValidDestination,
.reserved_space = -1L})
.SetPolicyCheckCallback(kValidCallback)
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest, UsesProvidedPolicyCheckCallback) {
const Destination destination = Destination::UPLOAD_EVENTS;
testing::MockFunction<Status(void)> mock_handler;
EXPECT_CALL(mock_handler, Call()).WillOnce(Return(Status::StatusOK()));
auto config_result =
ReportQueueConfiguration::Create({.destination = destination})
.SetDMToken(kDmToken)
.SetPolicyCheckCallback(
base::BindRepeating(&::testing::MockFunction<Status(void)>::Call,
base::Unretained(&mock_handler)))
.Build();
ASSERT_OK(config_result) << config_result.error();
const auto config = std::move(config_result.value());
EXPECT_OK(config->CheckPolicy());
EXPECT_THAT(config->reserved_space(), Eq(0L));
}
TEST_F(ReportQueueConfigurationTest, ValidateConfigurationWithRateLimiter) {
auto rate_limiter = std::make_unique<MockRateLimiter>();
auto* const mock_rate_limiter = rate_limiter.get();
auto config_result =
ReportQueueConfiguration::Create(
{.event_type = EventType::kDevice, .destination = kValidDestination})
.SetPolicyCheckCallback(kValidCallback)
.SetRateLimiter(std::move(rate_limiter))
.Build();
ASSERT_TRUE(config_result.has_value()) << config_result.error();
const auto config = std::move(config_result.value());
const auto is_event_allowed_cb = config->is_event_allowed_cb();
ASSERT_TRUE(is_event_allowed_cb);
EXPECT_CALL(*mock_rate_limiter, Acquire(_)).WillOnce(Return(false));
test::TestEvent<bool> rejected_event;
is_event_allowed_cb.Run(/*event_size=*/1000, rejected_event.cb());
EXPECT_FALSE(rejected_event.result());
EXPECT_CALL(*mock_rate_limiter, Acquire(_)).WillOnce(Return(true));
test::TestEvent<bool> acquired_event;
is_event_allowed_cb.Run(/*event_size=*/1, acquired_event.cb());
EXPECT_TRUE(acquired_event.result());
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithRateLimiterAfterRemoval) {
auto rate_limiter = std::make_unique<MockRateLimiter>();
auto config_result =
ReportQueueConfiguration::Create(
{.event_type = EventType::kDevice, .destination = kValidDestination})
.SetPolicyCheckCallback(kValidCallback)
.SetRateLimiter(std::move(rate_limiter))
.Build();
ASSERT_TRUE(config_result.has_value()) << config_result.error();
auto config = std::move(config_result.value());
const auto is_event_allowed_cb = config->is_event_allowed_cb();
ASSERT_TRUE(is_event_allowed_cb);
config.reset();
test::TestEvent<bool> rejected_event;
is_event_allowed_cb.Run(/*event_size=*/1000, rejected_event.cb());
EXPECT_FALSE(rejected_event.result());
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithReservedSpaceSetting) {
static constexpr int64_t kReservedSpace = 12345L;
auto config_result =
ReportQueueConfiguration::Create({.event_type = EventType::kDevice,
.destination = kValidDestination,
.reserved_space = kReservedSpace})
.SetPolicyCheckCallback(kValidCallback)
.Build();
ASSERT_TRUE(config_result.has_value()) << config_result.error();
const auto config = std::move(config_result.value());
EXPECT_THAT(config->reserved_space(), Eq(kReservedSpace));
}
TEST_F(ReportQueueConfigurationTest, ValidateConfigurationWithSource) {
SourceInfo source_info;
source_info.set_source(SourceInfo::ASH);
auto config_result =
ReportQueueConfiguration::Create(
{.event_type = EventType::kUser, .destination = kValidDestination})
.SetPolicyCheckCallback(kValidCallback)
.SetSourceInfo(source_info)
.Build();
ASSERT_TRUE(config_result.has_value()) << config_result.error();
const auto config = std::move(config_result.value());
ASSERT_TRUE(config->source_info().has_value());
EXPECT_THAT(config->source_info().value().source(), Eq(source_info.source()));
}
TEST_F(ReportQueueConfigurationTest, ValidateConfigurationWithUnsetSource) {
SourceInfo source_info;
auto config_result =
ReportQueueConfiguration::Create(
{.event_type = EventType::kUser, .destination = kValidDestination})
.SetPolicyCheckCallback(kValidCallback)
.SetSourceInfo(std::move(source_info))
.Build();
EXPECT_FALSE(config_result.has_value());
}
TEST_F(ReportQueueConfigurationTest, ValidateConfigurationWithSourceVersion) {
SourceInfo source_info;
source_info.set_source(SourceInfo::ASH);
source_info.set_source_version("1.0.0");
auto config_result =
ReportQueueConfiguration::Create(
{.event_type = EventType::kUser, .destination = kValidDestination})
.SetPolicyCheckCallback(kValidCallback)
.SetSourceInfo(source_info)
.Build();
ASSERT_TRUE(config_result.has_value()) << config_result.error();
const auto config = std::move(config_result.value());
ASSERT_TRUE(config->source_info().has_value());
const auto config_source_info = config->source_info().value();
EXPECT_THAT(config_source_info.source(), Eq(source_info.source()));
EXPECT_THAT(config_source_info.source_version(),
StrEq(source_info.source_version()));
}
TEST_F(ReportQueueConfigurationTest,
ValidateConfigurationWithSourceVersionAndInvalidSource) {
SourceInfo source_info;
source_info.set_source(SourceInfo::SOURCE_UNSPECIFIED);
source_info.set_source_version("1.0.0");
auto config_result =
ReportQueueConfiguration::Create({
.event_type = EventType::kUser,
.destination = kValidDestination,
})
.SetPolicyCheckCallback(kValidCallback)
.SetSourceInfo(std::move(source_info))
.Build();
EXPECT_FALSE(config_result.has_value());
}
} // namespace
} // namespace reporting