blob: 14a6ad4ce71f64c08cab93f5c33cc6bb35add643 [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_event_observer_manager.h"
#include <cstddef>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "components/reporting/metrics/collector_base.h"
#include "components/reporting/metrics/fakes/fake_event_driven_telemetry_collector_pool.h"
#include "components/reporting/metrics/fakes/fake_metric_event_observer.h"
#include "components/reporting/metrics/fakes/fake_metric_report_queue.h"
#include "components/reporting/metrics/fakes/fake_reporting_settings.h"
#include "components/reporting/proto/synced/metric_data.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::Eq;
namespace reporting {
namespace {
constexpr char kEventEnableSettingPath[] = "event_enable_path";
constexpr base::TimeDelta init_delay = base::Minutes(1);
class MockCollector : public CollectorBase {
public:
MockCollector() : CollectorBase(/*sampler=*/nullptr) {}
MockCollector(const MockCollector& other) = delete;
MockCollector& operator=(const MockCollector& other) = delete;
~MockCollector() override = default;
MOCK_METHOD(void, Collect, (bool), (override));
protected:
MOCK_METHOD(void,
OnMetricDataCollected,
(bool, std::optional<MetricData>),
(override));
MOCK_METHOD(bool, CanCollect, (), (const override));
};
class MetricEventObserverManagerTest : public ::testing::Test {
public:
void SetUp() override {
settings_ = std::make_unique<test::FakeReportingSettings>();
event_observer_ = std::make_unique<test::FakeMetricEventObserver>();
metric_report_queue_ = std::make_unique<test::FakeMetricReportQueue>();
collector_pool_ =
std::make_unique<test::FakeEventDrivenTelemetryCollectorPool>();
}
protected:
base::test::SingleThreadTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
std::unique_ptr<test::FakeReportingSettings> settings_;
std::unique_ptr<test::FakeMetricEventObserver> event_observer_;
std::unique_ptr<test::FakeMetricReportQueue> metric_report_queue_;
std::unique_ptr<test::FakeEventDrivenTelemetryCollectorPool> collector_pool_;
};
TEST_F(MetricEventObserverManagerTest, InitiallyEnabled) {
settings_->SetReportingEnabled(kEventEnableSettingPath, true);
auto* event_observer_ptr = event_observer_.get();
MetricEventObserverManager event_manager(
std::move(event_observer_), metric_report_queue_.get(), settings_.get(),
kEventEnableSettingPath, /*setting_enabled_default_value=*/false,
/*collector_pool=*/nullptr);
MetricData metric_data;
metric_data.mutable_event_data();
ASSERT_TRUE(event_observer_ptr->GetReportingEnabled());
size_t reporting_count = 2;
for (size_t i = 0; i < reporting_count; ++i) {
event_observer_ptr->RunCallback(metric_data);
MetricData metric_data_reported =
metric_report_queue_->GetMetricDataReported();
EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
EXPECT_TRUE(metric_data_reported.has_event_data());
}
// Setting disabled, no more data should be reported even if the callback is
// called.
settings_->SetReportingEnabled(kEventEnableSettingPath, false);
event_observer_ptr->RunCallback(metric_data);
ASSERT_FALSE(event_observer_ptr->GetReportingEnabled());
EXPECT_TRUE(metric_report_queue_->IsEmpty());
}
TEST_F(MetricEventObserverManagerTest, InitiallyEnabled_Delayed) {
settings_->SetReportingEnabled(kEventEnableSettingPath, true);
auto* event_observer_ptr = event_observer_.get();
MetricEventObserverManager event_manager(
std::move(event_observer_), metric_report_queue_.get(), settings_.get(),
kEventEnableSettingPath, /*setting_enabled_default_value=*/true,
/*sampler_pool=*/nullptr, init_delay);
MetricData metric_data;
metric_data.mutable_event_data();
// `init_delay` not elapsed, reporting enabled value not registered.
ASSERT_FALSE(event_observer_ptr->GetReportingEnabled());
event_observer_ptr->RunCallback(metric_data);
ASSERT_TRUE(metric_report_queue_->IsEmpty());
task_environment_.FastForwardBy(init_delay);
ASSERT_TRUE(event_observer_ptr->GetReportingEnabled());
event_observer_ptr->RunCallback(metric_data);
MetricData metric_data_reported =
metric_report_queue_->GetMetricDataReported();
EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
EXPECT_TRUE(metric_data_reported.has_event_data());
// Setting disabled, no more data should be reported even if the callback is
// called.
settings_->SetReportingEnabled(kEventEnableSettingPath, false);
event_observer_ptr->RunCallback(metric_data);
ASSERT_FALSE(event_observer_ptr->GetReportingEnabled());
EXPECT_TRUE(metric_report_queue_->IsEmpty());
}
TEST_F(MetricEventObserverManagerTest, InitiallyDisabled_Delayed) {
settings_->SetReportingEnabled(kEventEnableSettingPath, false);
auto* event_observer_ptr = event_observer_.get();
MetricEventObserverManager event_manager(
std::move(event_observer_), metric_report_queue_.get(), settings_.get(),
kEventEnableSettingPath, /*setting_enabled_default_value=*/true,
/*sampler_pool=*/nullptr, init_delay);
MetricData metric_data;
metric_data.mutable_event_data();
ASSERT_FALSE(event_observer_ptr->GetReportingEnabled());
event_observer_ptr->RunCallback(metric_data);
ASSERT_TRUE(metric_report_queue_->IsEmpty());
settings_->SetReportingEnabled(kEventEnableSettingPath, true);
task_environment_.FastForwardBy(init_delay / 2);
// `init_delay` still not elapsed, reporting enabled value not registered.
ASSERT_FALSE(event_observer_ptr->GetReportingEnabled());
task_environment_.FastForwardBy(init_delay / 2);
ASSERT_TRUE(event_observer_ptr->GetReportingEnabled());
event_observer_ptr->RunCallback(metric_data);
MetricData metric_data_reported =
metric_report_queue_->GetMetricDataReported();
EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
EXPECT_TRUE(metric_data_reported.has_event_data());
}
TEST_F(MetricEventObserverManagerTest, InitiallyDisabled) {
settings_->SetReportingEnabled(kEventEnableSettingPath, false);
auto* event_observer_ptr = event_observer_.get();
MetricEventObserverManager event_manager(
std::move(event_observer_), metric_report_queue_.get(), settings_.get(),
kEventEnableSettingPath, /*setting_enabled_default_value=*/false,
/*collector_pool=*/nullptr);
MetricData metric_data;
metric_data.mutable_event_data();
event_observer_ptr->RunCallback(metric_data);
ASSERT_FALSE(event_observer_ptr->GetReportingEnabled());
EXPECT_TRUE(metric_report_queue_->IsEmpty());
settings_->SetReportingEnabled(kEventEnableSettingPath, true);
event_observer_ptr->RunCallback(metric_data);
ASSERT_TRUE(event_observer_ptr->GetReportingEnabled());
MetricData metric_data_reported =
metric_report_queue_->GetMetricDataReported();
EXPECT_TRUE(metric_data_reported.has_event_data());
EXPECT_TRUE(metric_report_queue_->IsEmpty());
}
TEST_F(MetricEventObserverManagerTest, DefaultEnabled) {
auto* event_observer_ptr = event_observer_.get();
MetricEventObserverManager event_manager(
std::move(event_observer_), metric_report_queue_.get(), settings_.get(),
"invalid/path", /*setting_enabled_default_value=*/true,
/*collector_pool=*/nullptr);
MetricData metric_data;
metric_data.mutable_event_data();
ASSERT_TRUE(event_observer_ptr->GetReportingEnabled());
event_observer_ptr->RunCallback(metric_data);
MetricData metric_data_reported =
metric_report_queue_->GetMetricDataReported();
EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
EXPECT_TRUE(metric_data_reported.has_event_data());
EXPECT_TRUE(metric_report_queue_->IsEmpty());
}
TEST_F(MetricEventObserverManagerTest, DefaultDisabled) {
auto* event_observer_ptr = event_observer_.get();
MetricEventObserverManager event_manager(
std::move(event_observer_), metric_report_queue_.get(), settings_.get(),
"invalid/path", /*setting_enabled_default_value=*/false,
/*collector_pool=*/nullptr);
MetricData metric_data;
metric_data.mutable_event_data();
event_observer_ptr->RunCallback(metric_data);
ASSERT_FALSE(event_observer_ptr->GetReportingEnabled());
EXPECT_TRUE(metric_report_queue_->IsEmpty());
}
TEST_F(MetricEventObserverManagerTest, EventDrivenTelemetry) {
settings_->SetReportingEnabled(kEventEnableSettingPath, true);
auto* event_observer_ptr = event_observer_.get();
MetricEventType network_event = MetricEventType::WIFI_SIGNAL_STRENGTH_LOW;
MockCollector network_collector1;
MockCollector network_collector2;
MockCollector usb_collector;
collector_pool_->AddEventTelemetryCollector(network_event,
&network_collector1);
collector_pool_->AddEventTelemetryCollector(network_event,
&network_collector2);
collector_pool_->AddEventTelemetryCollector(MetricEventType::USB_ADDED,
&usb_collector);
MetricEventObserverManager event_manager(
std::move(event_observer_), metric_report_queue_.get(), settings_.get(),
kEventEnableSettingPath,
/*setting_enabled_default_value=*/false, collector_pool_.get());
MetricData event_metric_data;
event_metric_data.mutable_event_data()->set_type(network_event);
ASSERT_TRUE(event_observer_ptr->GetReportingEnabled());
EXPECT_CALL(network_collector1, Collect(_))
.WillOnce([](bool is_event_driven) { ASSERT_TRUE(is_event_driven); });
EXPECT_CALL(network_collector2, Collect(_))
.WillOnce([](bool is_event_driven) { ASSERT_TRUE(is_event_driven); });
EXPECT_CALL(usb_collector, Collect(_)).Times(0);
event_observer_ptr->RunCallback(std::move(event_metric_data));
task_environment_.RunUntilIdle();
MetricData metric_data_reported =
metric_report_queue_->GetMetricDataReported();
EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
EXPECT_TRUE(metric_data_reported.has_event_data());
EXPECT_THAT(metric_data_reported.event_data().type(), Eq(network_event));
EXPECT_TRUE(metric_report_queue_->IsEmpty());
}
TEST_F(MetricEventObserverManagerTest, ReportsEnqueuedEventsToUMA) {
settings_->SetReportingEnabled(kEventEnableSettingPath, true);
auto* const event_observer_ptr = event_observer_.get();
MetricEventObserverManager event_manager(
std::move(event_observer_), metric_report_queue_.get(), settings_.get(),
kEventEnableSettingPath, /*setting_enabled_default_value=*/false,
/*collector_pool=*/nullptr);
ASSERT_TRUE(event_observer_ptr->GetReportingEnabled());
static constexpr MetricEventType kEventType = MetricEventType::FATAL_CRASH;
MetricData metric_data;
metric_data.mutable_event_data()->set_type(kEventType);
const base::HistogramTester histogram_tester;
static constexpr size_t kTotalRecordCount = 2;
for (size_t record_count = 1; record_count <= kTotalRecordCount;
++record_count) {
event_observer_ptr->RunCallback(metric_data);
const MetricData metric_data_reported =
metric_report_queue_->GetMetricDataReported();
EXPECT_TRUE(metric_data_reported.has_timestamp_ms());
ASSERT_TRUE(metric_data_reported.has_event_data());
EXPECT_THAT(metric_data_reported.event_data().type(), Eq(kEventType));
histogram_tester.ExpectBucketCount(
MetricEventObserverManager::kEventMetricEnqueuedMetricsName, kEventType,
record_count);
histogram_tester.ExpectTotalCount(
MetricEventObserverManager::kEventMetricEnqueuedMetricsName,
record_count);
}
}
} // namespace
} // namespace reporting