1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/metrics/metrics_log_manager.h"
11 #include "base/prefs/pref_registry_simple.h"
12 #include "base/prefs/testing_pref_service.h"
13 #include "components/metrics/metrics_log.h"
14 #include "components/metrics/metrics_pref_names.h"
15 #include "components/metrics/test_metrics_service_client.h"
16 #include "testing/gtest/include/gtest/gtest.h"
22 // Dummy serializer that just stores logs in memory.
23 class TestLogPrefService : public TestingPrefServiceSimple {
25 TestLogPrefService() {
26 registry()->RegisterListPref(prefs::kMetricsInitialLogs);
27 registry()->RegisterListPref(prefs::kMetricsInitialLogsOld);
28 registry()->RegisterListPref(prefs::kMetricsOngoingLogs);
29 registry()->RegisterListPref(prefs::kMetricsOngoingLogsOld);
32 // Returns the number of logs of the given type.
33 size_t TypeCount(MetricsLog::LogType log_type) {
35 if (log_type == MetricsLog::INITIAL_STABILITY_LOG)
36 list_length = GetList(prefs::kMetricsInitialLogs)->GetSize();
38 list_length = GetList(prefs::kMetricsOngoingLogs)->GetSize();
39 return list_length / 2;
45 TEST(MetricsLogManagerTest, StandardFlow) {
46 TestMetricsServiceClient client;
47 TestLogPrefService pref_service;
48 MetricsLogManager log_manager(&pref_service, 0);
50 // Make sure a new manager has a clean slate.
51 EXPECT_EQ(NULL, log_manager.current_log());
52 EXPECT_FALSE(log_manager.has_staged_log());
53 EXPECT_FALSE(log_manager.has_unsent_logs());
55 // Check that the normal flow works.
56 MetricsLog* initial_log = new MetricsLog(
57 "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service);
58 log_manager.BeginLoggingWithLog(make_scoped_ptr(initial_log));
59 EXPECT_EQ(initial_log, log_manager.current_log());
60 EXPECT_FALSE(log_manager.has_staged_log());
62 log_manager.FinishCurrentLog();
63 EXPECT_EQ(NULL, log_manager.current_log());
64 EXPECT_TRUE(log_manager.has_unsent_logs());
65 EXPECT_FALSE(log_manager.has_staged_log());
67 MetricsLog* second_log =
68 new MetricsLog("id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service);
69 log_manager.BeginLoggingWithLog(make_scoped_ptr(second_log));
70 EXPECT_EQ(second_log, log_manager.current_log());
72 log_manager.StageNextLogForUpload();
73 EXPECT_TRUE(log_manager.has_staged_log());
74 EXPECT_FALSE(log_manager.staged_log().empty());
76 log_manager.DiscardStagedLog();
77 EXPECT_EQ(second_log, log_manager.current_log());
78 EXPECT_FALSE(log_manager.has_staged_log());
79 EXPECT_FALSE(log_manager.has_unsent_logs());
81 EXPECT_FALSE(log_manager.has_unsent_logs());
84 TEST(MetricsLogManagerTest, AbandonedLog) {
85 TestMetricsServiceClient client;
86 TestLogPrefService pref_service;
87 MetricsLogManager log_manager(&pref_service, 0);
89 MetricsLog* dummy_log = new MetricsLog(
90 "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service);
91 log_manager.BeginLoggingWithLog(make_scoped_ptr(dummy_log));
92 EXPECT_EQ(dummy_log, log_manager.current_log());
94 log_manager.DiscardCurrentLog();
95 EXPECT_EQ(NULL, log_manager.current_log());
96 EXPECT_FALSE(log_manager.has_staged_log());
99 TEST(MetricsLogManagerTest, InterjectedLog) {
100 TestMetricsServiceClient client;
101 TestLogPrefService pref_service;
102 MetricsLogManager log_manager(&pref_service, 0);
104 MetricsLog* ongoing_log =
105 new MetricsLog("id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service);
106 MetricsLog* temp_log = new MetricsLog(
107 "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service);
109 log_manager.BeginLoggingWithLog(make_scoped_ptr(ongoing_log));
110 EXPECT_EQ(ongoing_log, log_manager.current_log());
112 log_manager.PauseCurrentLog();
113 EXPECT_EQ(NULL, log_manager.current_log());
115 log_manager.BeginLoggingWithLog(make_scoped_ptr(temp_log));
116 EXPECT_EQ(temp_log, log_manager.current_log());
117 log_manager.FinishCurrentLog();
118 EXPECT_EQ(NULL, log_manager.current_log());
120 log_manager.ResumePausedLog();
121 EXPECT_EQ(ongoing_log, log_manager.current_log());
123 EXPECT_FALSE(log_manager.has_staged_log());
124 log_manager.StageNextLogForUpload();
125 log_manager.DiscardStagedLog();
126 EXPECT_FALSE(log_manager.has_unsent_logs());
129 TEST(MetricsLogManagerTest, InterjectedLogPreservesType) {
130 TestMetricsServiceClient client;
131 TestLogPrefService pref_service;
132 MetricsLogManager log_manager(&pref_service, 0);
133 log_manager.LoadPersistedUnsentLogs();
135 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
136 "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
137 log_manager.PauseCurrentLog();
138 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
139 "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
140 log_manager.FinishCurrentLog();
141 log_manager.ResumePausedLog();
142 log_manager.StageNextLogForUpload();
143 log_manager.DiscardStagedLog();
145 // Verify that the remaining log (which is the original ongoing log) still
146 // has the right type.
147 log_manager.FinishCurrentLog();
148 log_manager.PersistUnsentLogs();
149 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
150 EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
153 TEST(MetricsLogManagerTest, StoreAndLoad) {
154 TestMetricsServiceClient client;
155 TestLogPrefService pref_service;
156 // Set up some in-progress logging in a scoped log manager simulating the
157 // leadup to quitting, then persist as would be done on quit.
159 MetricsLogManager log_manager(&pref_service, 0);
160 log_manager.LoadPersistedUnsentLogs();
162 // Simulate a log having already been unsent from a previous session.
164 std::string log("proto");
165 PersistedLogs ongoing_logs(&pref_service, prefs::kMetricsOngoingLogs,
166 prefs::kMetricsOngoingLogsOld, 1, 1, 0);
167 ongoing_logs.StoreLog(log);
168 ongoing_logs.SerializeLogs();
170 EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
171 EXPECT_FALSE(log_manager.has_unsent_logs());
172 log_manager.LoadPersistedUnsentLogs();
173 EXPECT_TRUE(log_manager.has_unsent_logs());
175 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
176 "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
177 log_manager.FinishCurrentLog();
178 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
179 "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
180 log_manager.StageNextLogForUpload();
181 log_manager.FinishCurrentLog();
183 // Nothing should be written out until PersistUnsentLogs is called.
184 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
185 EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
186 log_manager.PersistUnsentLogs();
187 EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
188 EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
191 // Now simulate the relaunch, ensure that the log manager restores
192 // everything correctly, and verify that once the are handled they are not
195 MetricsLogManager log_manager(&pref_service, 0);
196 log_manager.LoadPersistedUnsentLogs();
197 EXPECT_TRUE(log_manager.has_unsent_logs());
199 log_manager.StageNextLogForUpload();
200 log_manager.DiscardStagedLog();
201 // The initial log should be sent first; update the persisted storage to
203 log_manager.PersistUnsentLogs();
204 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
205 EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
207 // Handle the first ongoing log.
208 log_manager.StageNextLogForUpload();
209 log_manager.DiscardStagedLog();
210 EXPECT_TRUE(log_manager.has_unsent_logs());
212 // Handle the last log.
213 log_manager.StageNextLogForUpload();
214 log_manager.DiscardStagedLog();
215 EXPECT_FALSE(log_manager.has_unsent_logs());
217 // Nothing should have changed "on disk" since PersistUnsentLogs hasn't been
219 EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
220 // Persist, and make sure nothing is left.
221 log_manager.PersistUnsentLogs();
222 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
223 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
227 TEST(MetricsLogManagerTest, StoreStagedLogTypes) {
228 TestMetricsServiceClient client;
230 // Ensure that types are preserved when storing staged logs.
232 TestLogPrefService pref_service;
233 MetricsLogManager log_manager(&pref_service, 0);
234 log_manager.LoadPersistedUnsentLogs();
236 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
237 "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
238 log_manager.FinishCurrentLog();
239 log_manager.StageNextLogForUpload();
240 log_manager.PersistUnsentLogs();
242 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
243 EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
247 TestLogPrefService pref_service;
248 MetricsLogManager log_manager(&pref_service, 0);
249 log_manager.LoadPersistedUnsentLogs();
251 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
252 "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
253 log_manager.FinishCurrentLog();
254 log_manager.StageNextLogForUpload();
255 log_manager.PersistUnsentLogs();
257 EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
258 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
262 TEST(MetricsLogManagerTest, LargeLogDiscarding) {
263 TestMetricsServiceClient client;
264 TestLogPrefService pref_service;
265 // Set the size threshold very low, to verify that it's honored.
266 MetricsLogManager log_manager(&pref_service, 1);
267 log_manager.LoadPersistedUnsentLogs();
269 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
270 "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
271 log_manager.FinishCurrentLog();
272 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
273 "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
274 log_manager.FinishCurrentLog();
276 // Only the ongoing log should be written out, due to the threshold.
277 log_manager.PersistUnsentLogs();
278 EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
279 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
282 TEST(MetricsLogManagerTest, DiscardOrder) {
283 // Ensure that the correct log is discarded if new logs are pushed while
285 TestMetricsServiceClient client;
287 TestLogPrefService pref_service;
288 MetricsLogManager log_manager(&pref_service, 0);
289 log_manager.LoadPersistedUnsentLogs();
291 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
292 "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
293 log_manager.FinishCurrentLog();
294 log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
295 "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
296 log_manager.StageNextLogForUpload();
297 log_manager.FinishCurrentLog();
298 log_manager.DiscardStagedLog();
300 log_manager.PersistUnsentLogs();
301 EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
302 EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
306 } // namespace metrics