// 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 "content/browser/memory/swap_metrics_driver_impl.h"

#include <memory>

#include "base/memory/ptr_util.h"
#include "base/test/task_environment.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

namespace {

// A SwapMetricsDriver that mocks what a platform-dependent driver does, but
// with control over when it fails so we can test error conditions.
class MockSwapMetricsDriver : public SwapMetricsDriverImpl {
 public:
  MockSwapMetricsDriver(std::unique_ptr<Delegate> delegate,
                        const base::TimeDelta update_interval,
                        const bool fail_on_update)
      : SwapMetricsDriverImpl(std::move(delegate), update_interval),
        fail_on_update_(fail_on_update) {}

  ~MockSwapMetricsDriver() override = default;

 protected:
  SwapMetricsDriver::SwapMetricsUpdateResult UpdateMetricsInternal(
      base::TimeDelta interval) override {
    if (fail_on_update_)
      return SwapMetricsDriver::SwapMetricsUpdateResult::
          kSwapMetricsUpdateFailed;

    if (interval.is_zero())
      return SwapMetricsDriver::SwapMetricsUpdateResult::
          kSwapMetricsUpdateSuccess;

    delegate_->OnSwapInCount(0, interval);
    delegate_->OnSwapOutCount(0, interval);
    delegate_->OnDecompressedPageCount(0, interval);
    delegate_->OnCompressedPageCount(0, interval);

    return SwapMetricsDriver::SwapMetricsUpdateResult::
        kSwapMetricsUpdateSuccess;
  }

 private:
  bool fail_on_update_;
};

// A SwapMetricsDriver::Delegate that counts the number of updates for each
// metric.
class SwapMetricsDelegateCounter : public SwapMetricsDriver::Delegate {
 public:
  SwapMetricsDelegateCounter()
      : num_swap_in_updates_(0),
        num_swap_out_updates_(0),
        num_decompressed_updates_(0),
        num_compressed_updates_(0),
        num_updates_failed_(0) {}

  ~SwapMetricsDelegateCounter() override = default;

  void OnSwapInCount(uint64_t count, base::TimeDelta interval) override {
    ++num_swap_in_updates_;
  }

  void OnSwapOutCount(uint64_t count, base::TimeDelta interval) override {
    ++num_swap_out_updates_;
  }

  void OnDecompressedPageCount(uint64_t count,
                               base::TimeDelta interval) override {
    ++num_decompressed_updates_;
  }

  void OnCompressedPageCount(uint64_t count,
                             base::TimeDelta interval) override {
    ++num_compressed_updates_;
  }

  void OnUpdateMetricsFailed() override { ++num_updates_failed_; }

  size_t num_swap_in_updates() const { return num_swap_in_updates_; }
  size_t num_swap_out_updates() const { return num_swap_out_updates_; }
  size_t num_decompressed_updates() const { return num_decompressed_updates_; }
  size_t num_compressed_updates() const { return num_compressed_updates_; }
  size_t num_updates_failed() const { return num_updates_failed_; }

 private:
  size_t num_swap_in_updates_;
  size_t num_swap_out_updates_;
  size_t num_decompressed_updates_;
  size_t num_compressed_updates_;
  size_t num_updates_failed_;

  DISALLOW_COPY_AND_ASSIGN(SwapMetricsDelegateCounter);
};

// The time delta between updates must non-zero for the delegate callbacks to be
// invoked.
constexpr base::TimeDelta kUpdateDelay = base::TimeDelta::FromMilliseconds(50);

}  // namespace

class TestSwapMetricsDriver : public testing::Test {
 public:
  static std::unique_ptr<SwapMetricsDriver> CreateDriver(
      const base::TimeDelta update_interval,
      bool fail_on_update) {
    SwapMetricsDelegateCounter* delegate = new SwapMetricsDelegateCounter();
    return base::WrapUnique<SwapMetricsDriver>(new MockSwapMetricsDriver(
        base::WrapUnique<SwapMetricsDriver::Delegate>(delegate),
        update_interval, fail_on_update));
  }

 protected:
  base::test::TaskEnvironment task_environment_;
};

TEST_F(TestSwapMetricsDriver, ExpectedMetricCounts) {
  std::unique_ptr<SwapMetricsDriver> driver =
      CreateDriver(base::TimeDelta(), false);

  auto result = driver->InitializeMetrics();
  EXPECT_EQ(
      SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess,
      result);

  base::PlatformThread::Sleep(kUpdateDelay);
  result = driver->UpdateMetrics();
  EXPECT_EQ(
      SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess,
      result);

  base::PlatformThread::Sleep(kUpdateDelay);
  result = driver->UpdateMetrics();
  EXPECT_EQ(
      SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess,
      result);

  auto* delegate = static_cast<SwapMetricsDelegateCounter*>(
      static_cast<SwapMetricsDriverImpl*>(driver.get())->delegate_.get());

  EXPECT_EQ(2UL, delegate->num_swap_in_updates());
  EXPECT_EQ(2UL, delegate->num_swap_out_updates());
  EXPECT_EQ(2UL, delegate->num_decompressed_updates());
  EXPECT_EQ(2UL, delegate->num_compressed_updates());
}

TEST_F(TestSwapMetricsDriver, TimerStartSuccess) {
  std::unique_ptr<SwapMetricsDriver> driver =
      CreateDriver(base::TimeDelta::FromSeconds(60), false);
  auto result = driver->Start();
  EXPECT_EQ(
      SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateSuccess,
      result);
}

TEST_F(TestSwapMetricsDriver, TimerStartFail) {
  std::unique_ptr<SwapMetricsDriver> driver =
      CreateDriver(base::TimeDelta::FromSeconds(60), true);
  auto result = driver->Start();
  EXPECT_EQ(
      SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateFailed,
      result);
}

TEST_F(TestSwapMetricsDriver, UpdateMetricsFail) {
  std::unique_ptr<SwapMetricsDriver> driver =
      CreateDriver(base::TimeDelta::FromSeconds(60), true);
  auto result = driver->InitializeMetrics();
  EXPECT_EQ(
      SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateFailed,
      result);
  result = driver->InitializeMetrics();
  EXPECT_EQ(
      SwapMetricsDriver::SwapMetricsUpdateResult::kSwapMetricsUpdateFailed,
      result);
  auto* delegate = static_cast<SwapMetricsDelegateCounter*>(
      static_cast<SwapMetricsDriverImpl*>(driver.get())->delegate_.get());
  EXPECT_EQ(2UL, delegate->num_updates_failed());
}

}  // namespace content
