// Copyright (c) 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/browser_watcher/watcher_metrics_provider_win.h"

#include <cstdlib>

#include "base/process/process_handle.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/test/histogram_tester.h"
#include "base/test/test_reg_util_win.h"
#include "base/win/registry.h"
#include "components/browser_watcher/exit_funnel_win.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace browser_watcher {

namespace {

const wchar_t kRegistryPath[] = L"Software\\WatcherMetricsProviderWinTest";

class WatcherMetricsProviderWinTest : public testing::Test {
 public:
  typedef testing::Test Super;

  virtual void SetUp() override {
    Super::SetUp();

    override_manager_.OverrideRegistry(HKEY_CURRENT_USER);
  }

  void AddProcessExitCode(bool use_own_pid, int exit_code) {
    int pid = 0;
    if (use_own_pid) {
      pid = base::GetCurrentProcId();
    } else {
      // Make sure not to accidentally collide with own pid.
      do {
        pid = rand();
      } while (pid == static_cast<int>(base::GetCurrentProcId()));
    }

    base::win::RegKey key(HKEY_CURRENT_USER, kRegistryPath, KEY_WRITE);

    // Make up a unique key, starting with the given pid.
    base::string16 key_name(base::StringPrintf(L"%d-%d", pid, rand()));

    // Write the exit code to registry.
    ULONG result = key.WriteValue(key_name.c_str(), exit_code);
    ASSERT_EQ(result, ERROR_SUCCESS);
  }

  size_t ExitCodeRegistryPathValueCount() {
    base::win::RegKey key(HKEY_CURRENT_USER, kRegistryPath, KEY_READ);
    return key.GetValueCount();
  }

  void AddExitFunnelEvent(int pid, const base::char16* name, int64 value) {
    base::string16 key_name =
        base::StringPrintf(L"%ls\\%d-%d", kRegistryPath, pid, pid);

    base::win::RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_WRITE);
    ASSERT_EQ(key.WriteValue(name, &value, sizeof(value), REG_QWORD),
              ERROR_SUCCESS);
  }

 protected:
  registry_util::RegistryOverrideManager override_manager_;
  base::HistogramTester histogram_tester_;
};

}  // namespace

TEST_F(WatcherMetricsProviderWinTest, RecordsStabilityHistogram) {
  // Record multiple success exits.
  for (size_t i = 0; i < 11; ++i)
    AddProcessExitCode(false, 0);

  // Record a single failure.
  AddProcessExitCode(false, 100);

  WatcherMetricsProviderWin provider(kRegistryPath);

  provider.ProvideStabilityMetrics(NULL);
  histogram_tester_.ExpectBucketCount(
        WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 0, 11);
  histogram_tester_.ExpectBucketCount(
        WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 100, 1);
  histogram_tester_.ExpectTotalCount(
        WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 12);

  // Verify that the reported values are gone.
  EXPECT_EQ(ExitCodeRegistryPathValueCount(), 0);
}

TEST_F(WatcherMetricsProviderWinTest, DoesNotReportOwnProcessId) {
  // Record multiple success exits.
  for (size_t i = 0; i < 11; ++i)
    AddProcessExitCode(i, 0);

  // Record own process as STILL_ACTIVE.
  AddProcessExitCode(true, STILL_ACTIVE);

  WatcherMetricsProviderWin provider(kRegistryPath);

  provider.ProvideStabilityMetrics(NULL);
  histogram_tester_.ExpectUniqueSample(
        WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 0, 11);

  // Verify that the reported values are gone.
  EXPECT_EQ(ExitCodeRegistryPathValueCount(), 1);
}

TEST_F(WatcherMetricsProviderWinTest, RecordsOrderedExitFunnelEvents) {
  // Record an exit funnel with a given set of timings and check that the
  // ordering is correct on the reported histograms.
  // Note the recorded times are in microseconds, but the reporting is in
  // milliseconds, hence the times 1000.
  AddExitFunnelEvent(100, L"One", 1000 * 1000);
  AddExitFunnelEvent(100, L"Two", 1010 * 1000);
  AddExitFunnelEvent(100, L"Three", 990 * 1000);

  WatcherMetricsProviderWin provider(kRegistryPath);

  provider.ProvideStabilityMetrics(NULL);
  histogram_tester_.ExpectUniqueSample("Stability.ExitFunnel.Three", 0, 1);
  histogram_tester_.ExpectUniqueSample("Stability.ExitFunnel.One", 10, 1);
  histogram_tester_.ExpectUniqueSample("Stability.ExitFunnel.Two", 20, 1);

  // Make sure the subkey is deleted on reporting.
  base::win::RegistryKeyIterator it(HKEY_CURRENT_USER, kRegistryPath);
  ASSERT_EQ(it.SubkeyCount(), 0);
}

TEST_F(WatcherMetricsProviderWinTest, ReadsExitFunnelWrites) {
  // Test that the metrics provider picks up the writes from
  ExitFunnel funnel;

  // Events against our own process should not get reported.
  ASSERT_TRUE(funnel.Init(kRegistryPath, base::GetCurrentProcessHandle()));
  ASSERT_TRUE(funnel.RecordEvent(L"Forgetaboutit"));

  // Reset the funnel to a pseudo process. The PID 4 is the system process,
  // which tests can hopefully never open.
  ASSERT_TRUE(funnel.InitImpl(kRegistryPath, 4, base::Time::Now()));

  // Each named event can only exist in a single copy.
  ASSERT_TRUE(funnel.RecordEvent(L"One"));
  ASSERT_TRUE(funnel.RecordEvent(L"One"));
  ASSERT_TRUE(funnel.RecordEvent(L"One"));
  ASSERT_TRUE(funnel.RecordEvent(L"Two"));
  ASSERT_TRUE(funnel.RecordEvent(L"Three"));

  WatcherMetricsProviderWin provider(kRegistryPath);

  provider.ProvideStabilityMetrics(NULL);
  histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.One", 1);
  histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.Two", 1);
  histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.Three", 1);

  // Make sure the subkey for the pseudo process has been deleted on reporting.
  base::win::RegistryKeyIterator it(HKEY_CURRENT_USER, kRegistryPath);
  ASSERT_EQ(it.SubkeyCount(), 1);
}

}  // namespace browser_watcher
