// Copyright 2014 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_manager.h"

#include <string>
#include <utility>
#include <vector>

#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/testing_pref_service.h"
#include "components/metrics/metrics_log.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/test_metrics_service_client.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace metrics {

namespace {

// Dummy serializer that just stores logs in memory.
class TestLogPrefService : public TestingPrefServiceSimple {
 public:
  TestLogPrefService() {
    registry()->RegisterListPref(prefs::kMetricsInitialLogs);
    registry()->RegisterListPref(prefs::kMetricsOngoingLogs);
  }

  // Returns the number of logs of the given type.
  size_t TypeCount(MetricsLog::LogType log_type) {
    int list_length = 0;
    if (log_type == MetricsLog::INITIAL_STABILITY_LOG)
      list_length = GetList(prefs::kMetricsInitialLogs)->GetSize();
    else
      list_length = GetList(prefs::kMetricsOngoingLogs)->GetSize();
    return list_length / 2;
  }
};

}  // namespace

TEST(MetricsLogManagerTest, StandardFlow) {
  TestMetricsServiceClient client;
  TestLogPrefService pref_service;
  MetricsLogManager log_manager(&pref_service, 0);

  // Make sure a new manager has a clean slate.
  EXPECT_EQ(NULL, log_manager.current_log());
  EXPECT_FALSE(log_manager.has_staged_log());
  EXPECT_FALSE(log_manager.has_unsent_logs());

  // Check that the normal flow works.
  MetricsLog* initial_log = new MetricsLog(
      "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service);
  log_manager.BeginLoggingWithLog(make_scoped_ptr(initial_log));
  EXPECT_EQ(initial_log, log_manager.current_log());
  EXPECT_FALSE(log_manager.has_staged_log());

  log_manager.FinishCurrentLog();
  EXPECT_EQ(NULL, log_manager.current_log());
  EXPECT_TRUE(log_manager.has_unsent_logs());
  EXPECT_FALSE(log_manager.has_staged_log());

  MetricsLog* second_log =
      new MetricsLog("id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service);
  log_manager.BeginLoggingWithLog(make_scoped_ptr(second_log));
  EXPECT_EQ(second_log, log_manager.current_log());

  log_manager.StageNextLogForUpload();
  EXPECT_TRUE(log_manager.has_staged_log());
  EXPECT_FALSE(log_manager.staged_log().empty());

  log_manager.DiscardStagedLog();
  EXPECT_EQ(second_log, log_manager.current_log());
  EXPECT_FALSE(log_manager.has_staged_log());
  EXPECT_FALSE(log_manager.has_unsent_logs());

  EXPECT_FALSE(log_manager.has_unsent_logs());
}

TEST(MetricsLogManagerTest, AbandonedLog) {
  TestMetricsServiceClient client;
  TestLogPrefService pref_service;
  MetricsLogManager log_manager(&pref_service, 0);

  MetricsLog* dummy_log = new MetricsLog(
      "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service);
  log_manager.BeginLoggingWithLog(make_scoped_ptr(dummy_log));
  EXPECT_EQ(dummy_log, log_manager.current_log());

  log_manager.DiscardCurrentLog();
  EXPECT_EQ(NULL, log_manager.current_log());
  EXPECT_FALSE(log_manager.has_staged_log());
}

TEST(MetricsLogManagerTest, InterjectedLog) {
  TestMetricsServiceClient client;
  TestLogPrefService pref_service;
  MetricsLogManager log_manager(&pref_service, 0);

  MetricsLog* ongoing_log =
      new MetricsLog("id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service);
  MetricsLog* temp_log = new MetricsLog(
      "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service);

  log_manager.BeginLoggingWithLog(make_scoped_ptr(ongoing_log));
  EXPECT_EQ(ongoing_log, log_manager.current_log());

  log_manager.PauseCurrentLog();
  EXPECT_EQ(NULL, log_manager.current_log());

  log_manager.BeginLoggingWithLog(make_scoped_ptr(temp_log));
  EXPECT_EQ(temp_log, log_manager.current_log());
  log_manager.FinishCurrentLog();
  EXPECT_EQ(NULL, log_manager.current_log());

  log_manager.ResumePausedLog();
  EXPECT_EQ(ongoing_log, log_manager.current_log());

  EXPECT_FALSE(log_manager.has_staged_log());
  log_manager.StageNextLogForUpload();
  log_manager.DiscardStagedLog();
  EXPECT_FALSE(log_manager.has_unsent_logs());
}

TEST(MetricsLogManagerTest, InterjectedLogPreservesType) {
  TestMetricsServiceClient client;
  TestLogPrefService pref_service;
  MetricsLogManager log_manager(&pref_service, 0);
  log_manager.LoadPersistedUnsentLogs();

  log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
      "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
  log_manager.PauseCurrentLog();
  log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
      "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
  log_manager.FinishCurrentLog();
  log_manager.ResumePausedLog();
  log_manager.StageNextLogForUpload();
  log_manager.DiscardStagedLog();

  // Verify that the remaining log (which is the original ongoing log) still
  // has the right type.
  log_manager.FinishCurrentLog();
  log_manager.PersistUnsentLogs();
  EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
  EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
}

TEST(MetricsLogManagerTest, StoreAndLoad) {
  TestMetricsServiceClient client;
  TestLogPrefService pref_service;
  // Set up some in-progress logging in a scoped log manager simulating the
  // leadup to quitting, then persist as would be done on quit.
  {
    MetricsLogManager log_manager(&pref_service, 0);
    log_manager.LoadPersistedUnsentLogs();

    // Simulate a log having already been unsent from a previous session.
    {
      std::string log("proto");
      PersistedLogs ongoing_logs(&pref_service, prefs::kMetricsOngoingLogs, 1,
                                 1, 0);
      ongoing_logs.StoreLog(log);
      ongoing_logs.SerializeLogs();
    }
    EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    EXPECT_FALSE(log_manager.has_unsent_logs());
    log_manager.LoadPersistedUnsentLogs();
    EXPECT_TRUE(log_manager.has_unsent_logs());

    log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
        "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
    log_manager.FinishCurrentLog();
    log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
        "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    log_manager.StageNextLogForUpload();
    log_manager.FinishCurrentLog();

    // Nothing should be written out until PersistUnsentLogs is called.
    EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    log_manager.PersistUnsentLogs();
    EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
  }

  // Now simulate the relaunch, ensure that the log manager restores
  // everything correctly, and verify that once the are handled they are not
  // re-persisted.
  {
    MetricsLogManager log_manager(&pref_service, 0);
    log_manager.LoadPersistedUnsentLogs();
    EXPECT_TRUE(log_manager.has_unsent_logs());

    log_manager.StageNextLogForUpload();
    log_manager.DiscardStagedLog();
    // The initial log should be sent first; update the persisted storage to
    // verify.
    log_manager.PersistUnsentLogs();
    EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));

    // Handle the first ongoing log.
    log_manager.StageNextLogForUpload();
    log_manager.DiscardStagedLog();
    EXPECT_TRUE(log_manager.has_unsent_logs());

    // Handle the last log.
    log_manager.StageNextLogForUpload();
    log_manager.DiscardStagedLog();
    EXPECT_FALSE(log_manager.has_unsent_logs());

    // Nothing should have changed "on disk" since PersistUnsentLogs hasn't been
    // called again.
    EXPECT_EQ(2U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
    // Persist, and make sure nothing is left.
    log_manager.PersistUnsentLogs();
    EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
  }
}

TEST(MetricsLogManagerTest, StoreStagedLogTypes) {
  TestMetricsServiceClient client;

  // Ensure that types are preserved when storing staged logs.
  {
    TestLogPrefService pref_service;
    MetricsLogManager log_manager(&pref_service, 0);
    log_manager.LoadPersistedUnsentLogs();

    log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
        "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    log_manager.FinishCurrentLog();
    log_manager.StageNextLogForUpload();
    log_manager.PersistUnsentLogs();

    EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
  }

  {
    TestLogPrefService pref_service;
    MetricsLogManager log_manager(&pref_service, 0);
    log_manager.LoadPersistedUnsentLogs();

    log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
        "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
    log_manager.FinishCurrentLog();
    log_manager.StageNextLogForUpload();
    log_manager.PersistUnsentLogs();

    EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
  }
}

TEST(MetricsLogManagerTest, LargeLogDiscarding) {
  TestMetricsServiceClient client;
  TestLogPrefService pref_service;
  // Set the size threshold very low, to verify that it's honored.
  MetricsLogManager log_manager(&pref_service, 1);
  log_manager.LoadPersistedUnsentLogs();

  log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
      "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
  log_manager.FinishCurrentLog();
  log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
      "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
  log_manager.FinishCurrentLog();

  // Only the ongoing log should be written out, due to the threshold.
  log_manager.PersistUnsentLogs();
  EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
  EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
}

TEST(MetricsLogManagerTest, DiscardOrder) {
  // Ensure that the correct log is discarded if new logs are pushed while
  // a log is staged.
  TestMetricsServiceClient client;
  {
    TestLogPrefService pref_service;
    MetricsLogManager log_manager(&pref_service, 0);
    log_manager.LoadPersistedUnsentLogs();

    log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
        "id", 0, MetricsLog::INITIAL_STABILITY_LOG, &client, &pref_service)));
    log_manager.FinishCurrentLog();
    log_manager.BeginLoggingWithLog(make_scoped_ptr(new MetricsLog(
        "id", 0, MetricsLog::ONGOING_LOG, &client, &pref_service)));
    log_manager.StageNextLogForUpload();
    log_manager.FinishCurrentLog();
    log_manager.DiscardStagedLog();

    log_manager.PersistUnsentLogs();
    EXPECT_EQ(0U, pref_service.TypeCount(MetricsLog::INITIAL_STABILITY_LOG));
    EXPECT_EQ(1U, pref_service.TypeCount(MetricsLog::ONGOING_LOG));
  }
}

}  // namespace metrics
