| // Copyright 2017 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/metrics/metrics_log_store.h" |
| |
| #include "components/metrics/metrics_pref_names.h" |
| #include "components/metrics/test_metrics_service_client.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace metrics { |
| |
| namespace { |
| |
| class MetricsLogStoreTest : public testing::Test { |
| public: |
| MetricsLogStoreTest() { |
| MetricsLogStore::RegisterPrefs(pref_service_.registry()); |
| } |
| ~MetricsLogStoreTest() override {} |
| |
| MetricsLog* CreateLog(MetricsLog::LogType log_type) { |
| return new MetricsLog("id", 0, log_type, &client_); |
| } |
| |
| // Returns the stored number of logs of the given type. |
| size_t TypeCount(MetricsLog::LogType log_type) { |
| const char* pref = log_type == MetricsLog::INITIAL_STABILITY_LOG |
| ? prefs::kMetricsInitialLogs |
| : prefs::kMetricsOngoingLogs; |
| return pref_service_.GetList(pref)->GetSize(); |
| } |
| |
| TestMetricsServiceClient client_; |
| TestingPrefServiceSimple pref_service_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MetricsLogStoreTest); |
| }; |
| |
| } // namespace |
| |
| TEST_F(MetricsLogStoreTest, StandardFlow) { |
| MetricsLogStore log_store(&pref_service_, 0); |
| log_store.LoadPersistedUnsentLogs(); |
| |
| // Make sure a new manager has a clean slate. |
| EXPECT_FALSE(log_store.has_staged_log()); |
| EXPECT_FALSE(log_store.has_unsent_logs()); |
| |
| log_store.StoreLog("a", MetricsLog::ONGOING_LOG); |
| EXPECT_TRUE(log_store.has_unsent_logs()); |
| EXPECT_FALSE(log_store.has_staged_log()); |
| |
| log_store.StageNextLog(); |
| EXPECT_TRUE(log_store.has_staged_log()); |
| EXPECT_FALSE(log_store.staged_log().empty()); |
| |
| log_store.DiscardStagedLog(); |
| EXPECT_FALSE(log_store.has_staged_log()); |
| EXPECT_FALSE(log_store.has_unsent_logs()); |
| } |
| |
| TEST_F(MetricsLogStoreTest, StoreAndLoad) { |
| // Set up some in-progress logging in a scoped log manager simulating the |
| // leadup to quitting, then persist as would be done on quit. |
| { |
| MetricsLogStore log_store(&pref_service_, 0); |
| log_store.LoadPersistedUnsentLogs(); |
| EXPECT_FALSE(log_store.has_unsent_logs()); |
| log_store.StoreLog("a", MetricsLog::ONGOING_LOG); |
| log_store.PersistUnsentLogs(); |
| EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG)); |
| } |
| |
| // Relaunch load and store more logs. |
| { |
| MetricsLogStore log_store(&pref_service_, 0); |
| log_store.LoadPersistedUnsentLogs(); |
| EXPECT_TRUE(log_store.has_unsent_logs()); |
| EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG)); |
| log_store.StoreLog("x", MetricsLog::INITIAL_STABILITY_LOG); |
| log_store.StageNextLog(); |
| log_store.StoreLog("b", MetricsLog::ONGOING_LOG); |
| |
| EXPECT_TRUE(log_store.has_unsent_logs()); |
| EXPECT_TRUE(log_store.has_staged_log()); |
| EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG)); |
| |
| log_store.PersistUnsentLogs(); |
| EXPECT_EQ(1U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(2U, TypeCount(MetricsLog::ONGOING_LOG)); |
| } |
| |
| // Relaunch and verify that once logs are handled they are not re-persisted. |
| { |
| MetricsLogStore log_store(&pref_service_, 0); |
| log_store.LoadPersistedUnsentLogs(); |
| EXPECT_TRUE(log_store.has_unsent_logs()); |
| |
| log_store.StageNextLog(); |
| log_store.DiscardStagedLog(); |
| // The initial log should be sent first; update the persisted storage to |
| // verify. |
| log_store.PersistUnsentLogs(); |
| EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(2U, TypeCount(MetricsLog::ONGOING_LOG)); |
| |
| // Handle the first ongoing log. |
| log_store.StageNextLog(); |
| log_store.DiscardStagedLog(); |
| EXPECT_TRUE(log_store.has_unsent_logs()); |
| |
| // Handle the last log. |
| log_store.StageNextLog(); |
| log_store.DiscardStagedLog(); |
| EXPECT_FALSE(log_store.has_unsent_logs()); |
| |
| // Nothing should have changed "on disk" since PersistUnsentLogs hasn't been |
| // called again. |
| EXPECT_EQ(2U, TypeCount(MetricsLog::ONGOING_LOG)); |
| // Persist, and make sure nothing is left. |
| log_store.PersistUnsentLogs(); |
| EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(0U, TypeCount(MetricsLog::ONGOING_LOG)); |
| } |
| } |
| |
| TEST_F(MetricsLogStoreTest, StoreStagedOngoingLog) { |
| // Ensure that types are preserved when storing staged logs. |
| MetricsLogStore log_store(&pref_service_, 0); |
| log_store.LoadPersistedUnsentLogs(); |
| log_store.StoreLog("a", MetricsLog::ONGOING_LOG); |
| log_store.StageNextLog(); |
| log_store.PersistUnsentLogs(); |
| |
| EXPECT_EQ(0U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(1U, TypeCount(MetricsLog::ONGOING_LOG)); |
| } |
| |
| TEST_F(MetricsLogStoreTest, StoreStagedInitialLog) { |
| // Ensure that types are preserved when storing staged logs. |
| MetricsLogStore log_store(&pref_service_, 0); |
| log_store.LoadPersistedUnsentLogs(); |
| log_store.StoreLog("b", MetricsLog::INITIAL_STABILITY_LOG); |
| log_store.StageNextLog(); |
| log_store.PersistUnsentLogs(); |
| |
| EXPECT_EQ(1U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(0U, TypeCount(MetricsLog::ONGOING_LOG)); |
| } |
| |
| TEST_F(MetricsLogStoreTest, LargeLogDiscarding) { |
| // Set the size threshold very low, to verify that it's honored. |
| MetricsLogStore log_store(&pref_service_, 1); |
| log_store.LoadPersistedUnsentLogs(); |
| |
| log_store.StoreLog("persisted", MetricsLog::INITIAL_STABILITY_LOG); |
| log_store.StoreLog("not_persisted", MetricsLog::ONGOING_LOG); |
| |
| // Only the stability log should be written out, due to the threshold. |
| log_store.PersistUnsentLogs(); |
| EXPECT_EQ(1U, TypeCount(MetricsLog::INITIAL_STABILITY_LOG)); |
| EXPECT_EQ(0U, TypeCount(MetricsLog::ONGOING_LOG)); |
| } |
| |
| TEST_F(MetricsLogStoreTest, DiscardOrder) { |
| // Ensure that the correct log is discarded if new logs are pushed while |
| // a log is staged. |
| MetricsLogStore log_store(&pref_service_, 0); |
| log_store.LoadPersistedUnsentLogs(); |
| |
| log_store.StoreLog("a", MetricsLog::ONGOING_LOG); |
| log_store.StoreLog("b", MetricsLog::ONGOING_LOG); |
| log_store.StageNextLog(); |
| log_store.StoreLog("c", MetricsLog::INITIAL_STABILITY_LOG); |
| EXPECT_EQ(2U, log_store.ongoing_log_count()); |
| EXPECT_EQ(1U, log_store.initial_log_count()); |
| // Should discard the ongoing log staged earlier. |
| log_store.DiscardStagedLog(); |
| EXPECT_EQ(1U, log_store.ongoing_log_count()); |
| EXPECT_EQ(1U, log_store.initial_log_count()); |
| // Initial log should be staged next. |
| log_store.StageNextLog(); |
| log_store.DiscardStagedLog(); |
| EXPECT_EQ(1U, log_store.ongoing_log_count()); |
| EXPECT_EQ(0U, log_store.initial_log_count()); |
| } |
| |
| } // namespace metrics |