1 // Copyright 2017 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.
4
5 #include "components/metrics/metrics_log_store.h"
6
7 #include "components/metrics/metrics_logs_event_manager.h"
8 #include "components/metrics/metrics_pref_names.h"
9 #include "components/metrics/test/test_metrics_service_client.h"
10 #include "components/metrics/unsent_log_store_metrics_impl.h"
11 #include "components/prefs/pref_registry_simple.h"
12 #include "components/prefs/testing_pref_service.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace metrics {
16 namespace {
17
18 const char kTestPrefName[] = "TestPref";
19
20 class TestUnsentLogStore : public UnsentLogStore {
21 public:
TestUnsentLogStore(PrefService * service)22 explicit TestUnsentLogStore(PrefService* service)
23 : UnsentLogStore(std::make_unique<UnsentLogStoreMetricsImpl>(),
24 service,
25 kTestPrefName,
26 nullptr,
27 // Set to 3 so logs are not dropped in the test.
28 UnsentLogStore::UnsentLogStoreLimits{
29 .min_log_count = 3,
30 },
31 /*signing_key=*/std::string(),
32 /*logs_event_manager=*/nullptr) {}
33 ~TestUnsentLogStore() override = default;
34
35 TestUnsentLogStore(const TestUnsentLogStore&) = delete;
36 TestUnsentLogStore& operator=(const TestUnsentLogStore&) = delete;
37
RegisterPrefs(PrefRegistrySimple * registry)38 static void RegisterPrefs(PrefRegistrySimple* registry) {
39 registry->RegisterListPref(kTestPrefName);
40 }
41 };
42
43 class MetricsLogStoreTest : public testing::Test {
44 public:
MetricsLogStoreTest()45 MetricsLogStoreTest() {
46 MetricsLogStore::RegisterPrefs(pref_service_.registry());
47 TestUnsentLogStore::RegisterPrefs(pref_service_.registry());
48 }
49
50 MetricsLogStoreTest(const MetricsLogStoreTest&) = delete;
51 MetricsLogStoreTest& operator=(const MetricsLogStoreTest&) = delete;
52
~MetricsLogStoreTest()53 ~MetricsLogStoreTest() override {}
54
CreateLog(MetricsLog::LogType log_type)55 MetricsLog* CreateLog(MetricsLog::LogType log_type) {
56 return new MetricsLog("0a94430b-18e5-43c8-a657-580f7e855ce1", 0, log_type,
57 &client_);
58 }
59
60 // Returns the stored number of logs of the given type.
TypeCount(MetricsLog::LogType log_type)61 size_t TypeCount(MetricsLog::LogType log_type) {
62 const char* pref = log_type == MetricsLog::INITIAL_STABILITY_LOG
63 ? prefs::kMetricsInitialLogs
64 : prefs::kMetricsOngoingLogs;
65 return pref_service_.GetList(pref).size();
66 }
67
68 TestMetricsServiceClient client_;
69 TestingPrefServiceSimple pref_service_;
70 };
71
72 } // namespace
73
TEST_F(MetricsLogStoreTest,StandardFlow)74 TEST_F(MetricsLogStoreTest, StandardFlow) {
75 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
76 /*signing_key=*/std::string(),
77 /*logs_event_manager=*/nullptr);
78 log_store.LoadPersistedUnsentLogs();
79
80 // Make sure a new manager has a clean slate.
81 EXPECT_FALSE(log_store.has_staged_log());
82 EXPECT_FALSE(log_store.has_unsent_logs());
83
84 log_store.StoreLog("a", MetricsLog::ONGOING_LOG, LogMetadata(),
85 MetricsLogsEventManager::CreateReason::kUnknown);
86 EXPECT_TRUE(log_store.has_unsent_logs());
87 EXPECT_FALSE(log_store.has_staged_log());
88
89 log_store.StageNextLog();
90 EXPECT_TRUE(log_store.has_staged_log());
91 EXPECT_FALSE(log_store.staged_log().empty());
92
93 log_store.DiscardStagedLog();
94 EXPECT_FALSE(log_store.has_staged_log());
95 EXPECT_FALSE(log_store.has_unsent_logs());
96 }
97
TEST_F(MetricsLogStoreTest,StoreAndLoad)98 TEST_F(MetricsLogStoreTest, StoreAndLoad) {
99 // Set up some in-progress logging in a scoped log manager simulating the
100 // leadup to quitting, then persist as would be done on quit.
101 {
102 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
103 /*signing_key=*/std::string(),
104 /*logs_event_manager=*/nullptr);
105 log_store.LoadPersistedUnsentLogs();
106 EXPECT_FALSE(log_store.has_unsent_logs());
107 log_store.StoreLog("a", MetricsLog::ONGOING_LOG, LogMetadata(),
108 MetricsLogsEventManager::CreateReason::kUnknown);
109 log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
110 EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
111 EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG));
112 }
113
114 // Relaunch load and store more logs.
115 {
116 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
117 /*signing_key=*/std::string(),
118 /*logs_event_manager=*/nullptr);
119 log_store.LoadPersistedUnsentLogs();
120 EXPECT_TRUE(log_store.has_unsent_logs());
121 EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
122 EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG));
123 log_store.StoreLog("x", MetricsLog::INITIAL_STABILITY_LOG, LogMetadata(),
124 MetricsLogsEventManager::CreateReason::kUnknown);
125 log_store.StageNextLog();
126 log_store.StoreLog("b", MetricsLog::ONGOING_LOG, LogMetadata(),
127 MetricsLogsEventManager::CreateReason::kUnknown);
128
129 EXPECT_TRUE(log_store.has_unsent_logs());
130 EXPECT_TRUE(log_store.has_staged_log());
131 EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
132 EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG));
133
134 log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
135 EXPECT_EQ(1U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
136 EXPECT_EQ(2U, TypeCount(MetricsLog::ONGOING_LOG));
137 }
138
139 // Relaunch and verify that once logs are handled they are not re-persisted.
140 {
141 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
142 /*signing_key=*/std::string(),
143 /*logs_event_manager=*/nullptr);
144 log_store.LoadPersistedUnsentLogs();
145 EXPECT_TRUE(log_store.has_unsent_logs());
146
147 log_store.StageNextLog();
148 log_store.DiscardStagedLog();
149 // The initial log should be sent first; update the persisted storage to
150 // verify.
151 log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
152 EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
153 EXPECT_EQ(2U, TypeCount(MetricsLog::ONGOING_LOG));
154
155 // Handle the first ongoing log.
156 log_store.StageNextLog();
157 log_store.DiscardStagedLog();
158 EXPECT_TRUE(log_store.has_unsent_logs());
159
160 // Handle the last log.
161 log_store.StageNextLog();
162 log_store.DiscardStagedLog();
163 EXPECT_FALSE(log_store.has_unsent_logs());
164
165 // Nothing should have changed "on disk" since TrimAndPersistUnsentLogs
166 // hasn't been called again.
167 EXPECT_EQ(2U, TypeCount(MetricsLog::ONGOING_LOG));
168 // Persist, and make sure nothing is left.
169 log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
170 EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
171 EXPECT_EQ(0U, TypeCount(MetricsLog::ONGOING_LOG));
172 }
173 }
174
TEST_F(MetricsLogStoreTest,StoreStagedOngoingLog)175 TEST_F(MetricsLogStoreTest, StoreStagedOngoingLog) {
176 // Ensure that types are preserved when storing staged logs.
177 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
178 /*signing_key=*/std::string(),
179 /*logs_event_manager=*/nullptr);
180 log_store.LoadPersistedUnsentLogs();
181 log_store.StoreLog("a", MetricsLog::ONGOING_LOG, LogMetadata(),
182 MetricsLogsEventManager::CreateReason::kUnknown);
183 log_store.StageNextLog();
184 log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
185
186 EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
187 EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG));
188 }
189
TEST_F(MetricsLogStoreTest,StoreStagedInitialLog)190 TEST_F(MetricsLogStoreTest, StoreStagedInitialLog) {
191 // Ensure that types are preserved when storing staged logs.
192 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
193 /*signing_key=*/std::string(),
194 /*logs_event_manager=*/nullptr);
195 log_store.LoadPersistedUnsentLogs();
196 log_store.StoreLog("b", MetricsLog::INITIAL_STABILITY_LOG, LogMetadata(),
197 MetricsLogsEventManager::CreateReason::kUnknown);
198 log_store.StageNextLog();
199 log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
200
201 EXPECT_EQ(1U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
202 EXPECT_EQ(0U, TypeCount(MetricsLog::ONGOING_LOG));
203 }
204
TEST_F(MetricsLogStoreTest,LargeLogDiscarding)205 TEST_F(MetricsLogStoreTest, LargeLogDiscarding) {
206 // Set the size threshold very low, to verify that it's honored.
207 client_.set_max_ongoing_log_size_bytes(1);
208 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
209 /*signing_key=*/std::string(),
210 /*logs_event_manager=*/nullptr);
211 log_store.LoadPersistedUnsentLogs();
212
213 log_store.StoreLog("persisted", MetricsLog::INITIAL_STABILITY_LOG,
214 LogMetadata(),
215 MetricsLogsEventManager::CreateReason::kUnknown);
216 log_store.StoreLog("not_persisted", MetricsLog::ONGOING_LOG, LogMetadata(),
217 MetricsLogsEventManager::CreateReason::kUnknown);
218
219 // Only the stability log should be written out, due to the threshold.
220 log_store.TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
221 EXPECT_EQ(1U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
222 EXPECT_EQ(0U, TypeCount(MetricsLog::ONGOING_LOG));
223 }
224
TEST_F(MetricsLogStoreTest,DiscardOrder)225 TEST_F(MetricsLogStoreTest, DiscardOrder) {
226 // Ensure that the correct log is discarded if new logs are pushed while
227 // a log is staged.
228 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
229 /*signing_key=*/std::string(),
230 /*logs_event_manager=*/nullptr);
231 log_store.LoadPersistedUnsentLogs();
232
233 log_store.StoreLog("a", MetricsLog::ONGOING_LOG, LogMetadata(),
234 MetricsLogsEventManager::CreateReason::kUnknown);
235 log_store.StoreLog("b", MetricsLog::ONGOING_LOG, LogMetadata(),
236 MetricsLogsEventManager::CreateReason::kUnknown);
237 log_store.StageNextLog();
238 log_store.StoreLog("c", MetricsLog::INITIAL_STABILITY_LOG, LogMetadata(),
239 MetricsLogsEventManager::CreateReason::kUnknown);
240 EXPECT_EQ(2U, log_store.ongoing_log_count());
241 EXPECT_EQ(1U, log_store.initial_log_count());
242 // Should discard the ongoing log staged earlier.
243 log_store.DiscardStagedLog();
244 EXPECT_EQ(1U, log_store.ongoing_log_count());
245 EXPECT_EQ(1U, log_store.initial_log_count());
246 // Initial log should be staged next.
247 log_store.StageNextLog();
248 log_store.DiscardStagedLog();
249 EXPECT_EQ(1U, log_store.ongoing_log_count());
250 EXPECT_EQ(0U, log_store.initial_log_count());
251 }
252
TEST_F(MetricsLogStoreTest,WritesToAlternateOngoingLogStore)253 TEST_F(MetricsLogStoreTest, WritesToAlternateOngoingLogStore) {
254 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
255 /*signing_key=*/std::string(),
256 /*logs_event_manager=*/nullptr);
257 std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
258 std::make_unique<TestUnsentLogStore>(&pref_service_);
259 TestUnsentLogStore* alternate_ongoing_log_store_ptr =
260 alternate_ongoing_log_store.get();
261
262 // Needs to be called before writing logs to alternate ongoing store since
263 // SetAlternateOngoingLogStore loads persisted unsent logs and assumes that
264 // the native initial and ongoing unsent logs have already been loaded.
265 log_store.LoadPersistedUnsentLogs();
266
267 log_store.StoreLog("a", MetricsLog::ONGOING_LOG, LogMetadata(),
268 MetricsLogsEventManager::CreateReason::kUnknown);
269 log_store.SetAlternateOngoingLogStore(std::move(alternate_ongoing_log_store));
270 log_store.StoreLog("b", MetricsLog::ONGOING_LOG, LogMetadata(),
271 MetricsLogsEventManager::CreateReason::kUnknown);
272 log_store.StoreLog("c", MetricsLog::ONGOING_LOG, LogMetadata(),
273 MetricsLogsEventManager::CreateReason::kUnknown);
274
275 EXPECT_EQ(1U, log_store.ongoing_log_count());
276 EXPECT_EQ(2U, alternate_ongoing_log_store_ptr->size());
277 }
278
TEST_F(MetricsLogStoreTest,AlternateOngoingLogStoreGetsEventsLogsManager)279 TEST_F(MetricsLogStoreTest, AlternateOngoingLogStoreGetsEventsLogsManager) {
280 // Create a MetricsLogStore with a MetricsLogsEventManager.
281 MetricsLogsEventManager logs_event_manager;
282 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
283 /*signing_key=*/std::string(), &logs_event_manager);
284
285 // Create an UnsentLogStore that will be used as an alternate ongoing log
286 // store.
287 std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
288 std::make_unique<TestUnsentLogStore>(&pref_service_);
289 TestUnsentLogStore* alternate_ongoing_log_store_ptr =
290 alternate_ongoing_log_store.get();
291
292 // Verify that |alternate_ongoing_log_store| has no logs event manager.
293 EXPECT_FALSE(
294 alternate_ongoing_log_store_ptr->GetLogsEventManagerForTesting());
295
296 // Needs to be called before we can set |log_store|'s alternate ongoing log
297 // store.
298 log_store.LoadPersistedUnsentLogs();
299
300 // Verify that after setting |log_store|'s alternate ongoing log store to
301 // |alternate_ongoing_log_store|, the latter should have the former's logs
302 // event manager.
303 log_store.SetAlternateOngoingLogStore(std::move(alternate_ongoing_log_store));
304 EXPECT_EQ(alternate_ongoing_log_store_ptr->GetLogsEventManagerForTesting(),
305 &logs_event_manager);
306 }
307
TEST_F(MetricsLogStoreTest,StagesInitialOverBothOngoing)308 TEST_F(MetricsLogStoreTest, StagesInitialOverBothOngoing) {
309 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
310 /*signing_key=*/std::string(),
311 /*logs_event_manager=*/nullptr);
312 std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
313 std::make_unique<TestUnsentLogStore>(&pref_service_);
314 TestUnsentLogStore* alternate_ongoing_log_store_ptr =
315 alternate_ongoing_log_store.get();
316
317 // Needs to be called before writing logs to alternate ongoing store since
318 // SetAlternateOngoingLogStore loads persisted unsent logs and assumes that
319 // the native initial and ongoing unsent logs have already been loaded.
320 log_store.LoadPersistedUnsentLogs();
321
322 log_store.StoreLog("a", MetricsLog::INITIAL_STABILITY_LOG, LogMetadata(),
323 MetricsLogsEventManager::CreateReason::kUnknown);
324 log_store.StoreLog("b", MetricsLog::ONGOING_LOG, LogMetadata(),
325 MetricsLogsEventManager::CreateReason::kUnknown);
326 log_store.SetAlternateOngoingLogStore(std::move(alternate_ongoing_log_store));
327 log_store.StoreLog("c", MetricsLog::ONGOING_LOG, LogMetadata(),
328 MetricsLogsEventManager::CreateReason::kUnknown);
329 log_store.StageNextLog();
330 log_store.DiscardStagedLog();
331
332 // Discarded log should be from initial_log_store.
333 EXPECT_EQ(0U, log_store.initial_log_count());
334 EXPECT_EQ(1U, log_store.ongoing_log_count());
335 EXPECT_EQ(1U, alternate_ongoing_log_store_ptr->size());
336 }
337
TEST_F(MetricsLogStoreTest,StagesAlternateOverOngoing)338 TEST_F(MetricsLogStoreTest, StagesAlternateOverOngoing) {
339 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
340 /*signing_key=*/std::string(),
341 /*logs_event_manager=*/nullptr);
342 std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
343 std::make_unique<TestUnsentLogStore>(&pref_service_);
344 TestUnsentLogStore* alternate_ongoing_log_store_ptr =
345 alternate_ongoing_log_store.get();
346
347 // Needs to be called before writing logs to alternate ongoing store since
348 // SetAlternateOngoingLogStore loads persisted unsent logs and assumes that
349 // the native initial and ongoing unsent logs have already been loaded.
350 log_store.LoadPersistedUnsentLogs();
351
352 log_store.StoreLog("a", MetricsLog::ONGOING_LOG, LogMetadata(),
353 MetricsLogsEventManager::CreateReason::kUnknown);
354 log_store.SetAlternateOngoingLogStore(std::move(alternate_ongoing_log_store));
355 log_store.StoreLog("b", MetricsLog::ONGOING_LOG, LogMetadata(),
356 MetricsLogsEventManager::CreateReason::kUnknown);
357 log_store.StageNextLog();
358 log_store.DiscardStagedLog();
359
360 // Discarded log should be from alternate_ongoing_log_store.
361 EXPECT_EQ(1U, log_store.ongoing_log_count());
362 EXPECT_EQ(0U, alternate_ongoing_log_store_ptr->size());
363 }
364
TEST_F(MetricsLogStoreTest,UnboundAlternateOngoingLogStoreWritesToNativeOngoing)365 TEST_F(MetricsLogStoreTest,
366 UnboundAlternateOngoingLogStoreWritesToNativeOngoing) {
367 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
368 /*signing_key=*/std::string(),
369 /*logs_event_manager=*/nullptr);
370 std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
371 std::make_unique<TestUnsentLogStore>(&pref_service_);
372
373 // Needs to be called before writing logs to alternate ongoing store since
374 // SetAlternateOngoingLogStore loads persisted unsent logs and assumes that
375 // the native initial and ongoing unsent logs have already been loaded.
376 log_store.LoadPersistedUnsentLogs();
377
378 log_store.SetAlternateOngoingLogStore(std::move(alternate_ongoing_log_store));
379 // Should be written to alternate ongoing log store.
380 log_store.StoreLog("a", MetricsLog::ONGOING_LOG, LogMetadata(),
381 MetricsLogsEventManager::CreateReason::kUnknown);
382
383 log_store.UnsetAlternateOngoingLogStore();
384
385 // Should be in native ongoing log store.
386 log_store.StoreLog("b", MetricsLog::ONGOING_LOG, LogMetadata(),
387 MetricsLogsEventManager::CreateReason::kUnknown);
388 log_store.StoreLog("c", MetricsLog::ONGOING_LOG, LogMetadata(),
389 MetricsLogsEventManager::CreateReason::kUnknown);
390
391 EXPECT_EQ(2U, log_store.ongoing_log_count());
392 }
393
TEST_F(MetricsLogStoreTest,StageOngoingLogWhenAlternateOngoingLogStoreIsEmpty)394 TEST_F(MetricsLogStoreTest,
395 StageOngoingLogWhenAlternateOngoingLogStoreIsEmpty) {
396 MetricsLogStore log_store(&pref_service_, client_.GetStorageLimits(),
397 /*signing_key=*/std::string(),
398 /*logs_event_manager=*/nullptr);
399 std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
400 std::make_unique<TestUnsentLogStore>(&pref_service_);
401
402 // Needs to be called before writing logs to alternate ongoing store since
403 // SetAlternateOngoingLogStore loads persisted unsent logs and assumes that
404 // the native initial and ongoing unsent logs have already been loaded.
405 log_store.LoadPersistedUnsentLogs();
406
407 // Should be written to ongoing log store.
408 log_store.StoreLog("a", MetricsLog::ONGOING_LOG, LogMetadata(),
409 MetricsLogsEventManager::CreateReason::kUnknown);
410
411 // Ensure that the log was stored in ongoing log.
412 EXPECT_EQ(1U, log_store.ongoing_log_count());
413
414 log_store.SetAlternateOngoingLogStore(std::move(alternate_ongoing_log_store));
415
416 log_store.StageNextLog();
417 log_store.DiscardStagedLog();
418
419 // Discarded log should be from ongoing.
420 EXPECT_EQ(0U, log_store.ongoing_log_count());
421 }
422
423 } // namespace metrics
424