1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/metrics/events_metrics_manager.h"
10 #include "base/bind.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "cc/metrics/event_metrics.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/events/types/event_type.h"
16 #include "ui/events/types/scroll_input_type.h"
21 MATCHER(UniquePtrMatches, negation ? "do not match" : "match") {
22 return std::get<0>(arg).get() == std::get<1>(arg);
25 EventsMetricsManager::ScopedMonitor::DoneCallback CreateSimpleDoneCallback(
26 std::unique_ptr<EventMetrics> metrics) {
27 return base::BindOnce(
28 [](std::unique_ptr<EventMetrics> metrics, bool handled) {
29 std::unique_ptr<EventMetrics> result =
30 handled ? std::move(metrics) : nullptr;
38 #define EXPECT_SCOPED(statements) \
44 using ::testing::IsEmpty;
45 using ::testing::Message;
46 using ::testing::UnorderedPointwise;
48 class EventsMetricsManagerTest : public testing::Test {
50 EventsMetricsManagerTest() = default;
51 ~EventsMetricsManagerTest() override = default;
54 std::unique_ptr<EventMetrics> CreateEventMetrics(ui::EventType type) {
55 test_tick_clock_.Advance(base::Microseconds(10));
56 base::TimeTicks event_time = test_tick_clock_.NowTicks();
57 test_tick_clock_.Advance(base::Microseconds(10));
58 return EventMetrics::CreateForTesting(type, event_time, &test_tick_clock_);
61 EventsMetricsManager manager_;
62 base::SimpleTestTickClock test_tick_clock_;
65 // Tests that EventMetrics are saved only if they have an event type we are
66 // interested in, and SaveActiveEventMetrics() is called inside their
67 // corresponding monitor's scope.
68 TEST_F(EventsMetricsManagerTest, EventsMetricsSaved) {
75 std::pair<std::unique_ptr<EventMetrics>, Behavior> events[] = {
76 // An interesting event type for which SaveActiveEventMetrics() is not
78 {CreateEventMetrics(ui::ET_MOUSE_PRESSED), Behavior::kDoNotSave},
80 // An interesting event type for which SaveActiveEventMetrics() is called
81 // inside its monitor scope.
82 {CreateEventMetrics(ui::ET_MOUSE_PRESSED), Behavior::kSaveInsideScope},
84 // An interesting event type for which SaveActiveEventMetrics() is called
85 // after its monitor scope is finished.
86 {CreateEventMetrics(ui::ET_MOUSE_PRESSED), Behavior::kSaveOutsideScope},
88 // A non-interesting event type for which SaveActiveEventMetrics() is
89 // called inside its monitor scope.
90 {CreateEventMetrics(ui::ET_MOUSE_MOVED), Behavior::kSaveInsideScope},
92 EXPECT_NE(events[0].first, nullptr);
93 EXPECT_NE(events[1].first, nullptr);
94 EXPECT_NE(events[2].first, nullptr);
95 EXPECT_EQ(events[3].first, nullptr);
97 // Out of the above events, only those with an interesting event type, for
98 // which SaveActiveEventMetrics() is called inside its monitor scope, are
99 // expected to be saved.
100 const EventMetrics* expected_saved_events[] = {
101 events[1].first.get(),
104 for (auto& event : events) {
106 auto monitor = manager_.GetScopedMonitor(
107 CreateSimpleDoneCallback(std::move(event.first)));
108 if (event.second == Behavior::kSaveInsideScope)
109 manager_.SaveActiveEventMetrics();
110 // Ending the scope destroys the |monitor|.
112 if (event.second == Behavior::kSaveOutsideScope)
113 manager_.SaveActiveEventMetrics();
116 // Check saved event metrics are as expected.
117 EXPECT_THAT(manager_.TakeSavedEventsMetrics(),
118 UnorderedPointwise(UniquePtrMatches(), expected_saved_events));
120 // The first call to TakeSavedEventsMetrics() should remove events metrics
121 // from the manager, so the second call should return empty list.
122 EXPECT_THAT(manager_.TakeSavedEventsMetrics(), IsEmpty());
125 // Tests that metrics for nested event loops are handled properly in a few
126 // different configurations.
127 TEST_F(EventsMetricsManagerTest, NestedEventsMetrics) {
129 // Type of event to use for the outer scope. `ui::EventType::ET_UNKNOWN` if
130 // no event should be used.
131 ui::EventType outer_event_type;
133 // Whether to save the outer scope metrics before starting the inner scope.
134 bool save_outer_metrics_before_inner;
136 // Type of event to use for the inner scope. `ui::EventType::ET_UNKNOWN` if
137 // no event should be used.
138 ui::EventType inner_event_type;
140 // Whether to save the inner scope metrics.
141 bool save_inner_metrics;
143 // Whether to save the outer scope metrics after the inner scope ended.
144 bool save_outer_metrics_after_inner;
148 /*outer_event_type=*/ui::EventType::ET_MOUSE_PRESSED,
149 /*save_outer_metrics_before_inner=*/true,
150 /*inner_event_type=*/ui::EventType::ET_MOUSE_RELEASED,
151 /*save_inner_metrics=*/true,
152 /*save_outer_metrics_after_inner=*/false,
157 /*outer_event_type=*/ui::EventType::ET_MOUSE_PRESSED,
158 /*save_outer_metrics_before_inner=*/false,
159 /*inner_event_type=*/ui::EventType::ET_MOUSE_RELEASED,
160 /*save_inner_metrics=*/true,
161 /*save_outer_metrics_after_inner=*/true,
166 /*outer_event_type=*/ui::EventType::ET_MOUSE_PRESSED,
167 /*save_outer_metrics_before_inner=*/true,
168 /*inner_event_type=*/ui::EventType::ET_MOUSE_RELEASED,
169 /*save_inner_metrics=*/true,
170 /*save_outer_metrics_after_inner=*/true,
175 /*outer_event_type=*/ui::EventType::ET_MOUSE_PRESSED,
176 /*save_outer_metrics_before_inner=*/false,
177 /*inner_event_type=*/ui::EventType::ET_UNKNOWN,
178 /*save_inner_metrics=*/false,
179 /*save_outer_metrics_after_inner=*/true,
184 /*outer_event_type=*/ui::EventType::ET_UNKNOWN,
185 /*save_outer_metrics_before_inner=*/false,
186 /*inner_event_type=*/ui::EventType::ET_MOUSE_PRESSED,
187 /*save_inner_metrics=*/true,
188 /*save_outer_metrics_after_inner=*/false,
192 for (size_t i = 0; i < std::size(configs); i++) {
193 auto& config = configs[i];
194 std::vector<const EventMetrics*> expected_saved_metrics;
196 { // Start outer scope.
197 std::unique_ptr<EventMetrics> outer_metrics;
198 if (config.outer_event_type != ui::EventType::ET_UNKNOWN) {
199 outer_metrics = CreateEventMetrics(config.outer_event_type);
200 DCHECK_NE(outer_metrics, nullptr);
201 expected_saved_metrics.push_back(outer_metrics.get());
203 auto outer_monitor = manager_.GetScopedMonitor(
204 CreateSimpleDoneCallback(std::move(outer_metrics)));
205 if (config.save_outer_metrics_before_inner)
206 manager_.SaveActiveEventMetrics();
208 { // Start inner scope.
209 std::unique_ptr<EventMetrics> inner_metrics;
210 if (config.inner_event_type != ui::EventType::ET_UNKNOWN) {
211 inner_metrics = CreateEventMetrics(config.inner_event_type);
212 DCHECK_NE(inner_metrics, nullptr);
213 expected_saved_metrics.push_back(inner_metrics.get());
215 auto inner_monitor = manager_.GetScopedMonitor(
216 CreateSimpleDoneCallback(std::move(inner_metrics)));
217 if (config.save_inner_metrics)
218 manager_.SaveActiveEventMetrics();
221 if (config.save_outer_metrics_after_inner)
222 manager_.SaveActiveEventMetrics();
223 } // End outer scope.
225 SCOPED_TRACE(Message() << "Config #" << i);
226 EXPECT_THAT(manager_.TakeSavedEventsMetrics(),
227 UnorderedPointwise(UniquePtrMatches(), expected_saved_metrics));