// Copyright 2018 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 <memory>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_task_environment.h"
#include "media/capabilities/in_memory_video_decode_stats_db_impl.h"
#include "media/capabilities/video_decode_stats_db_impl.h"
#include "media/capabilities/video_decode_stats_db_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::_;
using testing::Eq;
using testing::Pointee;
using testing::IsNull;

namespace media {

static VideoDecodeStatsDB::VideoDescKey kTestKey() {
  return VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey(
      VP9PROFILE_PROFILE3, gfx::Size(1024, 768), 60, "com.widevine.alpha",
      false);
}

static VideoDecodeStatsDB::DecodeStatsEntry kEmtpyEntry() {
  return VideoDecodeStatsDB::DecodeStatsEntry(0, 0, 0);
}

class MockSeedDB : public VideoDecodeStatsDB {
 public:
  MockSeedDB() = default;
  ~MockSeedDB() override = default;

  MOCK_METHOD1(Initialize, void(InitializeCB init_cb));
  MOCK_METHOD3(AppendDecodeStats,
               void(const VideoDescKey& key,
                    const DecodeStatsEntry& entry,
                    AppendDecodeStatsCB append_done_cb));
  MOCK_METHOD2(GetDecodeStats,
               void(const VideoDescKey& key, GetDecodeStatsCB get_stats_cb));
  MOCK_METHOD1(ClearStats, void(base::OnceClosure destroy_done_cb));
};

class MockDBProvider : public VideoDecodeStatsDBProvider {
 public:
  MockDBProvider() = default;
  ~MockDBProvider() override = default;

  MOCK_METHOD1(GetVideoDecodeStatsDB, void(GetCB get_db_b));
};

template <bool WithSeedDB>
class InMemoryDBTestBase : public testing::Test {
 public:
  InMemoryDBTestBase()
      : seed_db_(WithSeedDB ? new MockSeedDB() : nullptr),
        db_provider_(WithSeedDB ? new MockDBProvider() : nullptr),
        in_memory_db_(new InMemoryVideoDecodeStatsDBImpl(db_provider_.get())) {
    // Setup MockDBProvider to provide the seed DB. No need to initialize the
    // DB here since it too is a Mock.
    if (db_provider_) {
      using GetCB = VideoDecodeStatsDBProvider::GetCB;
      ON_CALL(*db_provider_, GetVideoDecodeStatsDB(_))
          .WillByDefault([&](GetCB cb) { std::move(cb).Run(seed_db_.get()); });
    }

    // The InMemoryDB should NEVER modify the seed DB.
    if (seed_db_) {
      EXPECT_CALL(*seed_db_, AppendDecodeStats(_, _, _)).Times(0);
      EXPECT_CALL(*seed_db_, ClearStats(_)).Times(0);
    }
  }

  void InitializeEmptyDB() {
    if (seed_db_)
      EXPECT_CALL(*db_provider_, GetVideoDecodeStatsDB(_));

    EXPECT_CALL(*this, InitializeCB(true));

    in_memory_db_->Initialize(base::BindOnce(&InMemoryDBTestBase::InitializeCB,
                                             base::Unretained(this)));
    scoped_task_environment_.RunUntilIdle();
  }

  MOCK_METHOD1(InitializeCB, void(bool success));
  MOCK_METHOD1(AppendDecodeStatsCB, void(bool success));
  MOCK_METHOD2(
      GetDecodeStatsCB,
      void(bool success,
           std::unique_ptr<VideoDecodeStatsDB::DecodeStatsEntry> entry));
  MOCK_METHOD0(ClearStatsCB, void());

 protected:
  using VideoDescKey = media::VideoDecodeStatsDB::VideoDescKey;
  using DecodeStatsEntry = media::VideoDecodeStatsDB::DecodeStatsEntry;

  base::test::ScopedTaskEnvironment scoped_task_environment_;
  std::unique_ptr<MockSeedDB> seed_db_;
  std::unique_ptr<MockDBProvider> db_provider_;
  std::unique_ptr<InMemoryVideoDecodeStatsDBImpl> in_memory_db_;
};

// Specialization for tests that have/lack a seed DB. Some tests only make sense
// with seed DB, so we separate them.
class SeededInMemoryDBTest : public InMemoryDBTestBase<true> {};
class SeedlessInMemoryDBTest : public InMemoryDBTestBase<false> {};

TEST_F(SeedlessInMemoryDBTest, ReadExpectingEmpty) {
  InitializeEmptyDB();

  // Database is empty, seed DB is empty => expect empty stats entry.
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(kEmtpyEntry()))));

  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
}

TEST_F(SeededInMemoryDBTest, ReadExpectingEmpty) {
  InitializeEmptyDB();

  // Make seed DB return null (empty) for this request.
  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _))
      .WillOnce([](const auto& key, auto get_cb) {
        std::move(get_cb).Run(true, nullptr);
      });

  // Database is empty, seed DB is empty => expect empty stats entry.
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(kEmtpyEntry()))));

  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
}

TEST_F(SeededInMemoryDBTest, ReadExpectingSeedData) {
  InitializeEmptyDB();

  // Setup seed DB to return an entry for the test key.
  DecodeStatsEntry seed_entry(1000, 2, 10);

  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _))
      .WillOnce([&](const auto& key, auto get_cb) {
        std::move(get_cb).Run(true,
                              std::make_unique<DecodeStatsEntry>(seed_entry));
      });

  // Seed DB has a an entry for the test key. Expect it!
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(seed_entry))));

  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // Verify a second GetDecodeStats() call with the same key does not trigger a
  // second call to the seed DB (we cache it).
  EXPECT_CALL(*seed_db_, GetDecodeStats(_, _)).Times(0);
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(seed_entry))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
}

TEST_F(SeededInMemoryDBTest, AppendReadAndClear) {
  const DecodeStatsEntry seed_entry(1000, 2, 10);
  const DecodeStatsEntry double_seed_entry(2000, 4, 20);
  const DecodeStatsEntry triple_seed_entry(3000, 6, 30);

  InitializeEmptyDB();

  // Setup seed DB to always return an entry for the test key.
  ON_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _))
      .WillByDefault([&](const auto& key, auto get_cb) {
        std::move(get_cb).Run(true,
                              std::make_unique<DecodeStatsEntry>(seed_entry));
      });

  // First append should trigger a request for the same key from the seed DB.
  // Simulate a successful read providing seed_entry for that key.
  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _));

  // Append the same seed entry, doubling the stats for this key.
  EXPECT_CALL(*this, AppendDecodeStatsCB(true));
  in_memory_db_->AppendDecodeStats(
      kTestKey(), seed_entry,
      base::BindOnce(&InMemoryDBTestBase::AppendDecodeStatsCB,
                     base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // Seed DB should not be queried again for this key.
  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _)).Times(0);

  // Now verify that the stats were doubled by the append above.
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(double_seed_entry))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // Append the same seed entry again to triple the stats. Additional appends
  // should not trigger queries the seed DB for this key.
  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _)).Times(0);
  in_memory_db_->AppendDecodeStats(
      kTestKey(), seed_entry,
      base::BindOnce(&InMemoryDBTestBase::AppendDecodeStatsCB,
                     base::Unretained(this)));

  // Verify we have 3x the stats.
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(triple_seed_entry))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  // Now destroy the in-memory stats...
  EXPECT_CALL(*this, ClearStatsCB());
  in_memory_db_->ClearStats(base::BindOnce(&InMemoryDBTestBase::ClearStatsCB,
                                           base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // With in-memory stats now gone, GetDecodeStats(kTestKey()) should again
  // trigger a call to the seed DB and return the un-doubled seed stats.
  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _));
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(seed_entry))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
}

TEST_F(SeedlessInMemoryDBTest, AppendReadAndClear) {
  const DecodeStatsEntry entry(50, 1, 5);
  const DecodeStatsEntry double_entry(100, 2, 10);

  InitializeEmptyDB();

  // Expect successful append to the empty seedless DB.
  EXPECT_CALL(*this, AppendDecodeStatsCB(true));
  in_memory_db_->AppendDecodeStats(
      kTestKey(), entry,
      base::BindOnce(&InMemoryDBTestBase::AppendDecodeStatsCB,
                     base::Unretained(this)));

  // Verify stats can be read back.
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(entry))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // Append same stats again to test summation.
  EXPECT_CALL(*this, AppendDecodeStatsCB(true));
  in_memory_db_->AppendDecodeStats(
      kTestKey(), entry,
      base::BindOnce(&InMemoryDBTestBase::AppendDecodeStatsCB,
                     base::Unretained(this)));

  // Verify doubled stats can be read back.
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(double_entry))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // Now destroy the in-memory stats...
  EXPECT_CALL(*this, ClearStatsCB());
  in_memory_db_->ClearStats(base::BindOnce(&InMemoryDBTestBase::ClearStatsCB,
                                           base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // Verify DB now empty for this key.
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(kEmtpyEntry()))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
}

TEST_F(SeededInMemoryDBTest, ProvidedNullSeedDB) {
  // DB provider may provide a null seed DB if it encounters some error.
  EXPECT_CALL(*db_provider_, GetVideoDecodeStatsDB(_))
      .WillOnce([](auto get_db_cb) { std::move(get_db_cb).Run(nullptr); });

  // Failing to obtain the seed DB is not a show stopper. The in-memory DB
  // should simply carry on in a seedless fashion.
  EXPECT_CALL(*this, InitializeCB(true));
  in_memory_db_->Initialize(base::BindOnce(&InMemoryDBTestBase::InitializeCB,
                                           base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // Writes still succeed.
  EXPECT_CALL(*this, AppendDecodeStatsCB(true));
  const DecodeStatsEntry entry(50, 1, 5);
  in_memory_db_->AppendDecodeStats(
      kTestKey(), entry,
      base::BindOnce(&InMemoryDBTestBase::AppendDecodeStatsCB,
                     base::Unretained(this)));

  // Reads should still succeed.
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(entry))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
}

TEST_F(SeededInMemoryDBTest, SeedReadFailureOnGettingStats) {
  // Everything seems fine at initialization...
  InitializeEmptyDB();

  // But seed DB will repeatedly fail to provide stats.
  ON_CALL(*seed_db_, GetDecodeStats(_, _))
      .WillByDefault([](const auto& key, auto get_cb) {
        std::move(get_cb).Run(false, nullptr);
      });

  // Reading the in-memory will still try to read the seed DB, and the read
  // callback will simply report that the DB is empty for this key.
  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _));
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(kEmtpyEntry()))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
}

TEST_F(SeededInMemoryDBTest, SeedReadFailureOnAppendingingStats) {
  // Everything seems fine at initialization...
  InitializeEmptyDB();

  // But seed DB will repeatedly fail to provide stats.
  ON_CALL(*seed_db_, GetDecodeStats(_, _))
      .WillByDefault([](const auto& key, auto get_cb) {
        std::move(get_cb).Run(false, nullptr);
      });

  // Appending to the in-memory will still try to read the seed DB, and the
  // append will proceed successfully as if the seed DB were empty.
  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _));
  EXPECT_CALL(*this, AppendDecodeStatsCB(true));
  const DecodeStatsEntry entry(50, 1, 5);
  in_memory_db_->AppendDecodeStats(
      kTestKey(), entry,
      base::BindOnce(&InMemoryDBTestBase::AppendDecodeStatsCB,
                     base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
  ::testing::Mock::VerifyAndClear(this);

  // Reading the appended data works without issue and does not trigger new
  // queries to the seed DB.
  EXPECT_CALL(*seed_db_, GetDecodeStats(Eq(kTestKey()), _)).Times(0);
  EXPECT_CALL(*this, GetDecodeStatsCB(true, Pointee(Eq(entry))));
  in_memory_db_->GetDecodeStats(
      kTestKey(), base::BindOnce(&InMemoryDBTestBase::GetDecodeStatsCB,
                                 base::Unretained(this)));

  scoped_task_environment_.RunUntilIdle();
}

TEST_F(SeededInMemoryDBTest, SeedDBTearDownRace) {
  ::testing::FLAGS_gtest_death_test_style = "threadsafe";

  // Establish depends-on connection from InMemoryDB to SeedDB.
  InitializeEmptyDB();

  // Clearing the seed-db dependency should trigger a crash.
  EXPECT_CHECK_DEATH(seed_db_.reset());
}

}  // namespace media
