// Copyright 2016 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/cache_storage/cache_storage_operation.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
#include "base/test/test_mock_time_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

namespace {

const char kSlowOperation[] =
    "ServiceWorkerCache.CacheStorage.Scheduler.IsOperationSlow";

class TestTask {
 public:
  TestTask() = default;
  ~TestTask() = default;
  void Run() { callback_count_++; }

  int callback_count() const { return callback_count_; }

 protected:
  int callback_count_ = 0;
};

}  // namespace

class CacheStorageOperationTest : public testing::Test {
 protected:
  CacheStorageOperationTest()
      : mock_task_runner_(new base::TestMockTimeTaskRunner()) {
    operation_ = base::MakeUnique<CacheStorageOperation>(
        base::BindOnce(&TestTask::Run, base::Unretained(&task_)),
        CacheStorageSchedulerClient::CLIENT_STORAGE, mock_task_runner_);
  }

  base::HistogramTester histogram_tester_;
  TestTask task_;
  scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
  std::unique_ptr<CacheStorageOperation> operation_;
};

TEST_F(CacheStorageOperationTest, OperationFast) {
  operation_->Run();
  mock_task_runner_->RunUntilIdle();
  EXPECT_EQ(1, task_.callback_count());
  histogram_tester_.ExpectTotalCount(kSlowOperation, 0);

  // Finish the operation.
  operation_.reset();

  mock_task_runner_->RunUntilIdle();
  EXPECT_EQ(1, task_.callback_count());
  histogram_tester_.ExpectTotalCount(kSlowOperation, 1);
  histogram_tester_.ExpectBucketCount(kSlowOperation, false, 1);
}

TEST_F(CacheStorageOperationTest, OperationSlow) {
  operation_->Run();
  mock_task_runner_->RunUntilIdle();
  EXPECT_EQ(1, task_.callback_count());
  histogram_tester_.ExpectTotalCount(kSlowOperation, 0);

  // The operation takes 10 seconds.
  mock_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(10));
  mock_task_runner_->RunUntilIdle();
  histogram_tester_.ExpectTotalCount(kSlowOperation, 1);
  histogram_tester_.ExpectBucketCount(kSlowOperation, true, 1);

  // Finish the operation.
  operation_.reset();
  mock_task_runner_->RunUntilIdle();
  EXPECT_EQ(1, task_.callback_count());
  histogram_tester_.ExpectTotalCount(kSlowOperation, 1);
  histogram_tester_.ExpectBucketCount(kSlowOperation, true, 1);
}

}  // namespace content
