blob: e43705c9d970763465c399ce2ddc739ff62cdaa5 [file] [log] [blame]
// Copyright 2021 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/metrics/metric_report_queue.h"
#include <memory>
#include <string>
#include <string_view>
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/reporting/client/mock_report_queue.h"
#include "components/reporting/metrics/fakes/fake_reporting_settings.h"
#include "components/reporting/proto/synced/metric_data.pb.h"
#include "components/reporting/proto/synced/record_constants.pb.h"
#include "components/reporting/util/status.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::Eq;
using ::testing::Return;
namespace reporting {
namespace {
constexpr char kRateSettingPath[] = "rate_path";
constexpr int kRateMs = 10000;
constexpr base::TimeDelta kDefaultRate = base::Milliseconds(100);
class MetricReportQueueTest : public ::testing::Test {
protected:
void SetUp() override {
priority_ = Priority::SLOW_BATCH;
settings_ = std::make_unique<test::FakeReportingSettings>();
}
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
std::unique_ptr<test::FakeReportingSettings> settings_;
Priority priority_;
};
TEST_F(MetricReportQueueTest, ManualUpload) {
auto mock_queue = std::unique_ptr<MockReportQueue, base::OnTaskRunnerDeleter>(
new MockReportQueue(),
base::OnTaskRunnerDeleter(
base::ThreadPool::CreateSequencedTaskRunner({})));
auto* mock_queue_ptr = mock_queue.get();
MetricData record;
record.set_timestamp_ms(123456);
MetricReportQueue metric_report_queue(std::move(mock_queue), priority_);
EXPECT_CALL(*mock_queue_ptr, AddRecord(_, _, _))
.WillOnce([&record, this](std::string_view record_string,
Priority actual_priority,
ReportQueue::EnqueueCallback cb) {
std::move(cb).Run(Status());
MetricData actual_record;
EXPECT_TRUE(actual_record.ParseFromArray(record_string.data(),
record_string.size()));
EXPECT_EQ(actual_record.timestamp_ms(), record.timestamp_ms());
EXPECT_EQ(actual_priority, priority_);
});
bool callback_called = false;
metric_report_queue.Enqueue(
record, base::BindLambdaForTesting(
[&callback_called](Status) { callback_called = true; }));
EXPECT_TRUE(callback_called);
EXPECT_CALL(*mock_queue_ptr, Flush(priority_, _)).Times(1);
metric_report_queue.Upload();
}
TEST_F(MetricReportQueueTest, ManualUploadWithTimer) {
settings_->SetInteger(kRateSettingPath, kRateMs);
int upload_count = 0;
auto mock_queue = std::unique_ptr<MockReportQueue, base::OnTaskRunnerDeleter>(
new MockReportQueue(),
base::OnTaskRunnerDeleter(
base::ThreadPool::CreateSequencedTaskRunner({})));
auto* mock_queue_ptr = mock_queue.get();
MetricData record;
record.set_timestamp_ms(123456);
MetricReportQueue metric_report_queue(std::move(mock_queue), priority_,
settings_.get(), kRateSettingPath,
kDefaultRate);
EXPECT_CALL(*mock_queue_ptr, AddRecord(_, _, _))
.WillOnce([&record, this](std::string record_string,
Priority actual_priority,
ReportQueue::EnqueueCallback cb) {
std::move(cb).Run(Status());
MetricData actual_record;
EXPECT_TRUE(actual_record.ParseFromArray(record_string.data(),
record_string.size()));
EXPECT_EQ(actual_record.timestamp_ms(), record.timestamp_ms());
EXPECT_EQ(actual_priority, priority_);
});
bool callback_called = false;
metric_report_queue.Enqueue(
record, base::BindLambdaForTesting(
[&callback_called](Status) { callback_called = true; }));
EXPECT_TRUE(callback_called);
ON_CALL(*mock_queue_ptr, Flush(priority_, _)).WillByDefault([&]() {
++upload_count;
});
task_environment_.FastForwardBy(base::Milliseconds(kRateMs / 2));
metric_report_queue.Upload();
ASSERT_EQ(upload_count, 1);
// Manual upload should have reset the timer so no upload should be expected
// after the time is elapsed.
task_environment_.FastForwardBy(base::Milliseconds(kRateMs / 2));
ASSERT_EQ(upload_count, 1);
// Full time elapsed after manual upload, new upload should be initiated.
task_environment_.FastForwardBy(base::Milliseconds(kRateMs / 2));
ASSERT_EQ(upload_count, 2);
}
TEST_F(MetricReportQueueTest, RateControlledFlush_TimeNotElapsed) {
settings_->SetInteger(kRateSettingPath, kRateMs);
auto mock_queue = std::unique_ptr<MockReportQueue, base::OnTaskRunnerDeleter>(
new MockReportQueue(),
base::OnTaskRunnerDeleter(
base::ThreadPool::CreateSequencedTaskRunner({})));
auto* mock_queue_ptr = mock_queue.get();
MetricData record;
record.set_timestamp_ms(123456);
MetricReportQueue metric_report_queue(std::move(mock_queue), priority_,
settings_.get(), kRateSettingPath,
kDefaultRate);
EXPECT_CALL(*mock_queue_ptr, AddRecord(_, _, _))
.WillOnce([&record, this](std::string record_string,
Priority actual_priority,
ReportQueue::EnqueueCallback cb) {
std::move(cb).Run(Status());
MetricData actual_record;
EXPECT_TRUE(actual_record.ParseFromArray(record_string.data(),
record_string.size()));
EXPECT_EQ(actual_record.timestamp_ms(), record.timestamp_ms());
EXPECT_EQ(actual_priority, priority_);
});
bool callback_called = false;
metric_report_queue.Enqueue(
record, base::BindLambdaForTesting(
[&callback_called](Status) { callback_called = true; }));
EXPECT_TRUE(callback_called);
EXPECT_CALL(*mock_queue_ptr, Flush).Times(0);
task_environment_.FastForwardBy(base::Milliseconds(kRateMs - 1));
}
TEST_F(MetricReportQueueTest, RateControlledFlush_TimeElapsed) {
settings_->SetInteger(kRateSettingPath, kRateMs);
auto mock_queue = std::unique_ptr<MockReportQueue, base::OnTaskRunnerDeleter>(
new MockReportQueue(),
base::OnTaskRunnerDeleter(
base::ThreadPool::CreateSequencedTaskRunner({})));
auto* mock_queue_ptr = mock_queue.get();
MetricData record;
record.set_timestamp_ms(123456);
MetricReportQueue metric_report_queue(std::move(mock_queue), priority_,
settings_.get(), kRateSettingPath,
kDefaultRate);
EXPECT_CALL(*mock_queue_ptr, AddRecord(_, _, _))
.WillOnce([&record, this](std::string record_string,
Priority actual_priority,
ReportQueue::EnqueueCallback cb) {
std::move(cb).Run(Status());
MetricData actual_record;
EXPECT_TRUE(actual_record.ParseFromArray(record_string.data(),
record_string.size()));
EXPECT_EQ(actual_record.timestamp_ms(), record.timestamp_ms());
EXPECT_EQ(actual_priority, priority_);
});
bool callback_called = false;
metric_report_queue.Enqueue(
record, base::BindLambdaForTesting(
[&callback_called](Status) { callback_called = true; }));
EXPECT_TRUE(callback_called);
EXPECT_CALL(*mock_queue_ptr, Flush(priority_, _)).Times(1);
task_environment_.FastForwardBy(base::Milliseconds(kRateMs));
}
TEST_F(MetricReportQueueTest, GetDestination) {
auto mock_queue = std::unique_ptr<MockReportQueue, base::OnTaskRunnerDeleter>(
new MockReportQueue(),
base::OnTaskRunnerDeleter(
base::ThreadPool::CreateSequencedTaskRunner({})));
const auto* const mock_queue_ptr = mock_queue.get();
MetricReportQueue metric_report_queue(std::move(mock_queue), priority_);
// Stub mock report queue to verify retrieved destination.
const Destination destination = Destination::TELEMETRY_METRIC;
EXPECT_CALL(*mock_queue_ptr, GetDestination()).WillOnce(Return(destination));
EXPECT_THAT(metric_report_queue.GetDestination(), Eq(destination));
}
} // namespace
} // namespace reporting