blob: 162693e60e021cca29d0d6ec0c9ff7426468385e [file] [log] [blame]
// Copyright 2018 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 "components/ntp_snippets/contextual/reporting/contextual_suggestions_metrics_reporter.h"
#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_task_environment.h"
#include "components/ntp_snippets/contextual/reporting/contextual_suggestions_ukm_entry.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using ukm::TestUkmRecorder;
using ukm::builders::ContextualSuggestions;
namespace contextual_suggestions {
namespace {
const char kEventsHistogramName[] = "ContextualSuggestions.Events";
const char kTestNavigationUrl[] = "https://foo.com";
const int kUninitialized = 0;
const int kFetchDelayed = 1;
const int kFetchRequested = 2;
const int kFetchError = 3;
const int kFetchServerBusy = 4;
const int kFetchBelowThreshold = 5;
const int kFetchEmpty = 6;
const int kFetchCompleted = 7;
const int kUiPeekReverseScroll = 8;
const int kUiOpened = 9;
const int kUiClosedObsolete = 10;
const int kSuggestionDownloaded = 11;
const int kSuggestionClicked = 12;
const int kUiDismissedWithoutOpen = 13;
const int kUiDismissedAfterOpen = 14;
const int kUiButtonShown = 15;
} // namespace
class ContextualSuggestionsMetricsReporterTest : public ::testing::Test {
protected:
ContextualSuggestionsMetricsReporterTest() = default;
TestUkmRecorder* GetTestUkmRecorder() { return &test_ukm_recorder_; }
ukm::SourceId GetSourceId();
ContextualSuggestionsMetricsReporter& GetReporter() { return reporter_; }
protected:
void ExpectMultipleEventsCountOnce(ContextualSuggestionsEvent event);
private:
// The reporter under test.
ContextualSuggestionsMetricsReporter reporter_;
// Sets up the task scheduling/task-runner environment for each test.
base::test::ScopedTaskEnvironment scoped_task_environment_;
// Sets itself as the global UkmRecorder on construction.
ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsMetricsReporterTest);
};
ukm::SourceId ContextualSuggestionsMetricsReporterTest::GetSourceId() {
ukm::SourceId source_id = ukm::UkmRecorder::GetNewSourceID();
test_ukm_recorder_.UpdateSourceURL(source_id, GURL(kTestNavigationUrl));
return source_id;
}
TEST_F(ContextualSuggestionsMetricsReporterTest, BaseTest) {
base::HistogramTester histogram_tester;
GetReporter().SetupForPage(kTestNavigationUrl, GetSourceId());
GetReporter().RecordEvent(FETCH_REQUESTED);
GetReporter().RecordEvent(FETCH_COMPLETED);
GetReporter().RecordEvent(UI_PEEK_REVERSE_SCROLL);
GetReporter().RecordEvent(UI_OPENED);
GetReporter().RecordEvent(SUGGESTION_DOWNLOADED);
GetReporter().RecordEvent(SUGGESTION_CLICKED);
// Flush data to write to UKM.
GetReporter().Flush();
// Check that we wrote something to UKM. Details of UKM reporting are tested
// in a different test suite.
TestUkmRecorder* test_ukm_recorder = GetTestUkmRecorder();
std::vector<const ukm::mojom::UkmEntry*> entry_vector =
test_ukm_recorder->GetEntriesByName(ContextualSuggestions::kEntryName);
EXPECT_EQ(1U, entry_vector.size());
const ukm::mojom::UkmEntry* first_entry = entry_vector[0];
EXPECT_TRUE(test_ukm_recorder->EntryHasMetric(
first_entry, ContextualSuggestions::kFetchStateName));
EXPECT_EQ(static_cast<int64_t>(FetchState::COMPLETED),
*(test_ukm_recorder->GetEntryMetric(
first_entry, ContextualSuggestions::kFetchStateName)));
// Test that the expected histogram events were written.
histogram_tester.ExpectBucketCount(kEventsHistogramName, kUninitialized, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchDelayed, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchRequested, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchError, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchServerBusy, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchBelowThreshold,
0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchEmpty, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchCompleted, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kUiPeekReverseScroll,
1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kUiOpened, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kUiClosedObsolete,
0);
histogram_tester.ExpectBucketCount(kEventsHistogramName,
kSuggestionDownloaded, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kSuggestionClicked,
1);
histogram_tester.ExpectBucketCount(kEventsHistogramName,
kUiDismissedWithoutOpen, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName,
kUiDismissedAfterOpen, 0);
}
void ContextualSuggestionsMetricsReporterTest::ExpectMultipleEventsCountOnce(
ContextualSuggestionsEvent event) {
std::unique_ptr<base::HistogramTester> histogram_tester =
std::make_unique<base::HistogramTester>();
GetReporter().SetupForPage(kTestNavigationUrl, GetSourceId());
// Always report a single FETCH_DELAYED event so we ensure there's a
// histogram (otherwise the ExpectBucketCount may crash).
GetReporter().RecordEvent(FETCH_DELAYED);
int event_index = static_cast<int>(event);
histogram_tester->ExpectBucketCount(kEventsHistogramName, event_index, 0);
// Peek the UI, which starts the timer, expected by all the other UI or
// suggestion events.
GetReporter().RecordEvent(UI_PEEK_REVERSE_SCROLL);
// Report the event that we want to test multiple times.
GetReporter().RecordEvent(event);
GetReporter().RecordEvent(event);
histogram_tester->ExpectBucketCount(kEventsHistogramName, event_index, 1);
GetReporter().Flush();
}
TEST_F(ContextualSuggestionsMetricsReporterTest, UiPeekReverseScrollTest) {
ExpectMultipleEventsCountOnce(UI_PEEK_REVERSE_SCROLL);
}
TEST_F(ContextualSuggestionsMetricsReporterTest, UiOpenedTest) {
ExpectMultipleEventsCountOnce(UI_OPENED);
}
TEST_F(ContextualSuggestionsMetricsReporterTest, UiDismissedWithoutOpenTest) {
ExpectMultipleEventsCountOnce(UI_DISMISSED_WITHOUT_OPEN);
}
TEST_F(ContextualSuggestionsMetricsReporterTest, UiDismissedAfterOpenTest) {
ExpectMultipleEventsCountOnce(UI_DISMISSED_AFTER_OPEN);
}
TEST_F(ContextualSuggestionsMetricsReporterTest, SuggestionDownloadedTest) {
ExpectMultipleEventsCountOnce(SUGGESTION_DOWNLOADED);
}
TEST_F(ContextualSuggestionsMetricsReporterTest, SuggestionClickedTest) {
ExpectMultipleEventsCountOnce(SUGGESTION_CLICKED);
}
TEST_F(ContextualSuggestionsMetricsReporterTest, MultipleEventsTest) {
std::unique_ptr<base::HistogramTester> histogram_tester =
std::make_unique<base::HistogramTester>();
GetReporter().SetupForPage(kTestNavigationUrl, GetSourceId());
// Test multiple cycles of FETCH_REQUESTED, FETCH_COMPLETED.
GetReporter().RecordEvent(FETCH_REQUESTED);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kFetchRequested, 1);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kFetchCompleted, 0);
GetReporter().RecordEvent(FETCH_COMPLETED);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kFetchRequested, 1);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kFetchCompleted, 1);
GetReporter().RecordEvent(FETCH_REQUESTED);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kFetchRequested, 2);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kFetchCompleted, 1);
GetReporter().RecordEvent(FETCH_COMPLETED);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kFetchRequested, 2);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kFetchCompleted, 2);
GetReporter().Flush();
}
// Test that might catch enum reordering that's not done right.
TEST_F(ContextualSuggestionsMetricsReporterTest, EnumNotReorderedTest) {
std::unique_ptr<base::HistogramTester> histogram_tester =
std::make_unique<base::HistogramTester>();
GetReporter().SetupForPage(kTestNavigationUrl, GetSourceId());
// Peek the UI, which starts the timer, expected by all the other UI or
// suggestion events.
GetReporter().RecordEvent(UI_PEEK_REVERSE_SCROLL);
// The current last legal event.
GetReporter().RecordEvent(SUGGESTION_CLICKED);
histogram_tester->ExpectBucketCount(kEventsHistogramName, kSuggestionClicked,
1);
GetReporter().Flush();
}
TEST_F(ContextualSuggestionsMetricsReporterTest, ButtonTest) {
base::HistogramTester histogram_tester;
GetReporter().SetupForPage(kTestNavigationUrl, GetSourceId());
GetReporter().RecordEvent(FETCH_REQUESTED);
GetReporter().RecordEvent(FETCH_COMPLETED);
GetReporter().RecordEvent(UI_BUTTON_SHOWN);
GetReporter().RecordEvent(UI_OPENED);
GetReporter().RecordEvent(SUGGESTION_DOWNLOADED);
GetReporter().RecordEvent(SUGGESTION_CLICKED);
// Flush data to write to UKM.
GetReporter().Flush();
// Check that we wrote something to UKM. Details of UKM reporting are tested
// in a different test suite.
TestUkmRecorder* test_ukm_recorder = GetTestUkmRecorder();
std::vector<const ukm::mojom::UkmEntry*> entry_vector =
test_ukm_recorder->GetEntriesByName(ContextualSuggestions::kEntryName);
EXPECT_EQ(1U, entry_vector.size());
const ukm::mojom::UkmEntry* first_entry = entry_vector[0];
EXPECT_TRUE(test_ukm_recorder->EntryHasMetric(
first_entry, ContextualSuggestions::kFetchStateName));
EXPECT_EQ(static_cast<int64_t>(FetchState::COMPLETED),
*(test_ukm_recorder->GetEntryMetric(
first_entry, ContextualSuggestions::kFetchStateName)));
// Test that the expected histogram events were written.
histogram_tester.ExpectBucketCount(kEventsHistogramName, kUninitialized, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchDelayed, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchRequested, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchError, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchServerBusy, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchBelowThreshold,
0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchEmpty, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kFetchCompleted, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kUiButtonShown, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kUiOpened, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kUiClosedObsolete,
0);
histogram_tester.ExpectBucketCount(kEventsHistogramName,
kSuggestionDownloaded, 1);
histogram_tester.ExpectBucketCount(kEventsHistogramName, kSuggestionClicked,
1);
histogram_tester.ExpectBucketCount(kEventsHistogramName,
kUiDismissedWithoutOpen, 0);
histogram_tester.ExpectBucketCount(kEventsHistogramName,
kUiDismissedAfterOpen, 0);
}
} // namespace contextual_suggestions