blob: c7764d9e8a4d243bf4d199c180e681b55f58940e [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/components/local_search_service/search_metrics_reporter.h"
#include <memory>
#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "chromeos/components/local_search_service/pref_names.h"
#include "chromeos/components/local_search_service/shared_structs.h"
#include "components/metrics/daily_event.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace local_search_service {
class SearchMetricsReporterTest : public testing::Test {
public:
SearchMetricsReporterTest() = default;
~SearchMetricsReporterTest() override = default;
void SetUp() override {
SearchMetricsReporter::RegisterLocalStatePrefs(pref_service_.registry());
}
void TearDown() override { reporter_.reset(); }
protected:
void SetReporter() {
reporter_ = std::make_unique<SearchMetricsReporter>(&pref_service_);
}
// Notifies |reporter_| that a search is performed.
void SendOnSearchPerformedAndCheck(IndexId index_id) {
bool callback_done = false;
reporter_->OnSearchPerformed(
index_id,
base::BindOnce([](bool* callback_done) { *callback_done = true; },
&callback_done));
task_environment_.RunUntilIdle();
ASSERT_TRUE(callback_done);
}
// Instructs |reporter_| to report daily metrics for reason |type|.
void TriggerDailyEvent(metrics::DailyEvent::IntervalType type) {
reporter_->ReportDailyMetricsForTesting(type);
}
// Instructs |reporter_| to report daily metrics due to the passage of a day
// and verifies that it reports one sample with each of the passed values.
void TriggerDailyEventAndVerifyHistograms(const std::string& histogram_name,
int expected_count) {
base::HistogramTester histogram_tester;
TriggerDailyEvent(metrics::DailyEvent::IntervalType::DAY_ELAPSED);
histogram_tester.ExpectUniqueSample(histogram_name, expected_count, 1);
}
base::test::TaskEnvironment task_environment_;
TestingPrefServiceSimple pref_service_;
std::unique_ptr<SearchMetricsReporter> reporter_;
};
TEST_F(SearchMetricsReporterTest, CountAndReportEvents) {
SetReporter();
base::HistogramTester tester;
SendOnSearchPerformedAndCheck(IndexId::kCrosSettings);
SendOnSearchPerformedAndCheck(IndexId::kCrosSettings);
SendOnSearchPerformedAndCheck(IndexId::kCrosSettings);
TriggerDailyEvent(metrics::DailyEvent::IntervalType::DAY_ELAPSED);
tester.ExpectUniqueSample(SearchMetricsReporter::kHelpAppName, 0, 1);
tester.ExpectUniqueSample(SearchMetricsReporter::kCrosSettingsName, 3, 1);
// The next day, another two searches.
SendOnSearchPerformedAndCheck(IndexId::kCrosSettings);
SendOnSearchPerformedAndCheck(IndexId::kCrosSettings);
SendOnSearchPerformedAndCheck(IndexId::kHelpApp);
TriggerDailyEvent(metrics::DailyEvent::IntervalType::DAY_ELAPSED);
tester.ExpectBucketCount(SearchMetricsReporter::kHelpAppName, 1, 1);
tester.ExpectBucketCount(SearchMetricsReporter::kCrosSettingsName, 2, 1);
// Next day, CLOCK_CHANGED event happens, nothing more is logged.
SendOnSearchPerformedAndCheck(IndexId::kHelpApp);
SendOnSearchPerformedAndCheck(IndexId::kCrosSettings);
SendOnSearchPerformedAndCheck(IndexId::kHelpApp);
SendOnSearchPerformedAndCheck(IndexId::kCrosSettings);
SendOnSearchPerformedAndCheck(IndexId::kHelpApp);
TriggerDailyEvent(metrics::DailyEvent::IntervalType::CLOCK_CHANGED);
tester.ExpectTotalCount(SearchMetricsReporter::kHelpAppName, 2);
tester.ExpectTotalCount(SearchMetricsReporter::kCrosSettingsName, 2);
}
TEST_F(SearchMetricsReporterTest, LoadInitialCountsFromPrefs) {
// Create a new reporter and check that it loads its initial event counts from
// prefs.
pref_service_.SetInteger(prefs::kLocalSearchServiceMetricsCrosSettingsCount,
2);
SetReporter();
TriggerDailyEventAndVerifyHistograms(SearchMetricsReporter::kCrosSettingsName,
2);
// The previous report should've cleared the prefs, so a new reporter should
// start out at zero.
TriggerDailyEventAndVerifyHistograms(SearchMetricsReporter::kCrosSettingsName,
0);
}
TEST_F(SearchMetricsReporterTest, IgnoreDailyEventFirstRun) {
SetReporter();
// metrics::DailyEvent notifies observers immediately on first run. Histograms
// shouldn't be sent in this case.
base::HistogramTester tester;
TriggerDailyEvent(metrics::DailyEvent::IntervalType::FIRST_RUN);
tester.ExpectTotalCount(SearchMetricsReporter::kCrosSettingsName, 0);
}
TEST_F(SearchMetricsReporterTest, IgnoreDailyEventClockChanged) {
SetReporter();
SendOnSearchPerformedAndCheck(IndexId::kCrosSettings);
// metrics::DailyEvent notifies observers if it sees that the system clock has
// jumped back. Histograms shouldn't be sent in this case.
base::HistogramTester tester;
TriggerDailyEvent(metrics::DailyEvent::IntervalType::CLOCK_CHANGED);
tester.ExpectTotalCount(SearchMetricsReporter::kCrosSettingsName, 0);
// The existing stats should be cleared when the clock change notification is
// received, so the next report should only contain zeros.
TriggerDailyEventAndVerifyHistograms(SearchMetricsReporter::kCrosSettingsName,
0);
}
} // namespace local_search_service
} // namespace chromeos