Home | History | Annotate | Download | only in metrics
      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.
      4 
      5 #include "components/metrics/metrics_log_manager.h"
      6 
      7 #include <string>
      8 #include <utility>
      9 #include <vector>
     10 
     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"
     17 
     18 namespace metrics {
     19 
     20 namespace {
     21 
     22 // Dummy serializer that just stores logs in memory.
     23 class TestLogPrefService : public TestingPrefServiceSimple {
     24  public:
     25   TestLogPrefService() {
     26     registry()->RegisterListPref(prefs::kMetricsInitialLogs);
     27     registry()->RegisterListPref(prefs::kMetricsInitialLogsOld);
     28     registry()->RegisterListPref(prefs::kMetricsOngoingLogs);
     29     registry()->RegisterListPref(prefs::kMetricsOngoingLogsOld);
     30   }
     31 
     32   // Returns the number of logs of the given type.
     33   size_t TypeCount(MetricsLog::LogType log_type) {
     34     int list_length = 0;
     35     if (log_type == MetricsLog::INITIAL_STABILITY_LOG)
     36       list_length = GetList(prefs::kMetricsInitialLogs)->GetSize();
     37     else
     38       list_length = GetList(prefs::kMetricsOngoingLogs)->GetSize();
     39     return list_length / 2;
     40   }
     41 };
     42 
     43 }  // namespace
     44 
     45 TEST(MetricsLogManagerTest, StandardFlow) {
     46   TestMetricsServiceClient client;
     47   TestLogPrefService pref_service;
     48   MetricsLogManager log_manager(&pref_service, 0);
     49 
     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());
     54 
     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());
     61 
     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());
     66 
     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());
     71 
     72   log_manager.StageNextLogForUpload();
     73   EXPECT_TRUE(log_manager.has_staged_log());
     74   EXPECT_FALSE(log_manager.staged_log().empty());
     75 
     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());
     80 
     81   EXPECT_FALSE(log_manager.has_unsent_logs());
     82 }
     83 
     84 TEST(MetricsLogManagerTest, AbandonedLog) {
     85   TestMetricsServiceClient client;
     86   TestLogPrefService pref_service;
     87   MetricsLogManager log_manager(&pref_service, 0);
     88 
     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());
     93 
     94   log_manager.DiscardCurrentLog();
     95   EXPECT_EQ(NULL, log_manager.current_log());
     96   EXPECT_FALSE(log_manager.has_staged_log());
     97 }
     98 
     99 TEST(MetricsLogManagerTest, InterjectedLog) {
    100   TestMetricsServiceClient client;
    101   TestLogPrefService pref_service;
    102   MetricsLogManager log_manager(&pref_service, 0);
    103 
    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);
    108 
    109   log_manager.BeginLoggingWithLog(make_scoped_ptr(ongoing_log));
    110   EXPECT_EQ(ongoing_log, log_manager.current_log());
    111 
    112   log_manager.PauseCurrentLog();
    113   EXPECT_EQ(NULL, log_manager.current_log());
    114 
    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());
    119 
    120   log_manager.ResumePausedLog();
    121   EXPECT_EQ(ongoing_log, log_manager.current_log());
    122 
    123   EXPECT_FALSE(log_manager.has_staged_log());
    124   log_manager.StageNextLogForUpload();
    125   log_manager.DiscardStagedLog();
    126   EXPECT_FALSE(log_manager.has_unsent_logs());
    127 }
    128 
    129 TEST(MetricsLogManagerTest, InterjectedLogPreservesType) {
    130   TestMetricsServiceClient client;
    131   TestLogPrefService pref_service;
    132   MetricsLogManager log_manager(&pref_service, 0);
    133   log_manager.LoadPersistedUnsentLogs();
    134 
    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();
    144 
    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));
    151 }
    152 
    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.
    158   {
    159     MetricsLogManager log_manager(&pref_service, 0);
    160     log_manager.LoadPersistedUnsentLogs();
    161 
    162     // Simulate a log having already been unsent from a previous session.
    163     {
    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();
    169     }
    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());
    174 
    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.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE);
    182     log_manager.FinishCurrentLog();
    183 
    184     // Nothing should be written out until PersistUnsentLogs is called.
    185     EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    186     EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    187     log_manager.PersistUnsentLogs();
    188     EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    189     EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    190   }
    191 
    192   // Now simulate the relaunch, ensure that the log manager restores
    193   // everything correctly, and verify that once the are handled they are not
    194   // re-persisted.
    195   {
    196     MetricsLogManager log_manager(&pref_service, 0);
    197     log_manager.LoadPersistedUnsentLogs();
    198     EXPECT_TRUE(log_manager.has_unsent_logs());
    199 
    200     log_manager.StageNextLogForUpload();
    201     log_manager.DiscardStagedLog();
    202     // The initial log should be sent first; update the persisted storage to
    203     // verify.
    204     log_manager.PersistUnsentLogs();
    205     EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    206     EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    207 
    208     // Handle the first ongoing log.
    209     log_manager.StageNextLogForUpload();
    210     log_manager.DiscardStagedLog();
    211     EXPECT_TRUE(log_manager.has_unsent_logs());
    212 
    213     // Handle the last log.
    214     log_manager.StageNextLogForUpload();
    215     log_manager.DiscardStagedLog();
    216     EXPECT_FALSE(log_manager.has_unsent_logs());
    217 
    218     // Nothing should have changed "on disk" since PersistUnsentLogs hasn't been
    219     // called again.
    220     EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    221     // Persist, and make sure nothing is left.
    222     log_manager.PersistUnsentLogs();
    223     EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    224     EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    225   }
    226 }
    227 
    228 TEST(MetricsLogManagerTest, StoreStagedLogTypes) {
    229   TestMetricsServiceClient client;
    230 
    231   // Ensure that types are preserved when storing staged logs.
    232   {
    233     TestLogPrefService pref_service;
    234     MetricsLogManager log_manager(&pref_service, 0);
    235     log_manager.LoadPersistedUnsentLogs();
    236 
    237     log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    238         "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    239     log_manager.FinishCurrentLog();
    240     log_manager.StageNextLogForUpload();
    241     log_manager.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE);
    242     log_manager.PersistUnsentLogs();
    243 
    244     EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    245     EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    246   }
    247 
    248   {
    249     TestLogPrefService pref_service;
    250     MetricsLogManager log_manager(&pref_service, 0);
    251     log_manager.LoadPersistedUnsentLogs();
    252 
    253     log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    254         "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
    255     log_manager.FinishCurrentLog();
    256     log_manager.StageNextLogForUpload();
    257     log_manager.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE);
    258     log_manager.PersistUnsentLogs();
    259 
    260     EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    261     EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    262   }
    263 }
    264 
    265 TEST(MetricsLogManagerTest, LargeLogDiscarding) {
    266   TestMetricsServiceClient client;
    267   TestLogPrefService pref_service;
    268   // Set the size threshold very low, to verify that it's honored.
    269   MetricsLogManager log_manager(&pref_service, 1);
    270   log_manager.LoadPersistedUnsentLogs();
    271 
    272   log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    273       "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
    274   log_manager.FinishCurrentLog();
    275   log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    276       "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    277   log_manager.FinishCurrentLog();
    278 
    279   // Only the ongoing log should be written out, due to the threshold.
    280   log_manager.PersistUnsentLogs();
    281   EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    282   EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    283 }
    284 
    285 TEST(MetricsLogManagerTest, ProvisionalStoreStandardFlow) {
    286   TestMetricsServiceClient client;
    287 
    288   // Ensure that provisional store works, and discards the correct log.
    289   {
    290     TestLogPrefService pref_service;
    291     MetricsLogManager log_manager(&pref_service, 0);
    292     log_manager.LoadPersistedUnsentLogs();
    293 
    294     log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    295         "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
    296     log_manager.FinishCurrentLog();
    297     log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    298         "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    299     log_manager.StageNextLogForUpload();
    300     log_manager.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE);
    301     log_manager.FinishCurrentLog();
    302     log_manager.DiscardLastProvisionalStore();
    303 
    304     log_manager.PersistUnsentLogs();
    305     EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    306     EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    307   }
    308 }
    309 
    310 TEST(MetricsLogManagerTest, ProvisionalStoreNoop) {
    311   TestMetricsServiceClient client;
    312 
    313   // Ensure that trying to drop a sent log is a no-op, even if another log has
    314   // since been staged.
    315   {
    316     TestLogPrefService pref_service;
    317     MetricsLogManager log_manager(&pref_service, 0);
    318     log_manager.LoadPersistedUnsentLogs();
    319 
    320     log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    321         "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    322     log_manager.FinishCurrentLog();
    323     log_manager.StageNextLogForUpload();
    324     log_manager.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE);
    325     log_manager.StageNextLogForUpload();
    326     log_manager.DiscardStagedLog();
    327     log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    328         "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    329     log_manager.FinishCurrentLog();
    330     log_manager.StageNextLogForUpload();
    331     log_manager.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE);
    332     log_manager.DiscardLastProvisionalStore();
    333 
    334     log_manager.PersistUnsentLogs();
    335     EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    336   }
    337 
    338   // Ensure that trying to drop more than once is a no-op
    339   {
    340     TestLogPrefService pref_service;
    341     MetricsLogManager log_manager(&pref_service, 0);
    342     log_manager.LoadPersistedUnsentLogs();
    343 
    344     log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    345         "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    346     log_manager.FinishCurrentLog();
    347     log_manager.StageNextLogForUpload();
    348     log_manager.StoreStagedLogAsUnsent(PersistedLogs::NORMAL_STORE);
    349     log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
    350         "id", 0, MetricsLog::ONGOING_LOG,  &client, &pref_service)));
    351     log_manager.FinishCurrentLog();
    352     log_manager.StageNextLogForUpload();
    353     log_manager.StoreStagedLogAsUnsent(PersistedLogs::PROVISIONAL_STORE);
    354     log_manager.DiscardLastProvisionalStore();
    355     log_manager.DiscardLastProvisionalStore();
    356 
    357     log_manager.PersistUnsentLogs();
    358     EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    359   }
    360 }
    361 
    362 }  // namespace metrics
    363