/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cobalt/storage/storage_manager.h"

#include <string>

#include "base/bind.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/synchronization/waitable_event.h"
#include "cobalt/base/cobalt_paths.h"
#include "cobalt/storage/savegame_fake.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::InvokeWithoutArgs;
using ::testing::NotNull;
using ::testing::Eq;

namespace cobalt {
namespace storage {

namespace {

// Used to be able to intercept QueueFlush().
class MockStorageManager : public StorageManager {
 public:
  MockStorageManager(scoped_ptr<StorageManager::UpgradeHandler> upgrade_handler,
                     const Options& options)
      : StorageManager(upgrade_handler.Pass(), options) {}
  MOCK_METHOD1(QueueFlush, void(const base::Closure& callback));
};

class MockUpgradeHandler : public StorageManager::UpgradeHandler {
 public:
  MOCK_METHOD3(OnUpgrade, void(StorageManager*, const char*, int));
};

class CallbackWaiter {
 public:
  CallbackWaiter() : was_called_event_(true, false) {}
  virtual ~CallbackWaiter() {}
  bool TimedWait() {
    return was_called_event_.TimedWait(base::TimeDelta::FromSeconds(5));
  }

 protected:
  void Signal() { was_called_event_.Signal(); }

 private:
  base::WaitableEvent was_called_event_;

  DISALLOW_COPY_AND_ASSIGN(CallbackWaiter);
};

class FlushWaiter : public CallbackWaiter {
 public:
  FlushWaiter() {}
  void OnFlushDone() { Signal(); }

 private:
  DISALLOW_COPY_AND_ASSIGN(FlushWaiter);
};

class SqlWaiter : public CallbackWaiter {
 public:
  SqlWaiter() {}
  void OnSqlConnection(SqlContext* sql_context) {
    UNREFERENCED_PARAMETER(sql_context);
    Signal();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(SqlWaiter);
};

void FlushCallback(SqlContext* sql_context) {
  sql::Connection* conn = sql_context->sql_connection();
  bool ok = conn->Execute("CREATE TABLE FlushTest(test_name TEXT);");
  EXPECT_EQ(true, ok);
}

void QuerySchemaCallback(SqlContext* sql_context) {
  int schema_version;
  EXPECT_EQ(false, sql_context->GetSchemaVersion("Nonexistent table",
                                                 &schema_version));

  sql::Connection* conn = sql_context->sql_connection();
  bool ok = conn->Execute("CREATE TABLE TestTable(test_name TEXT);");
  EXPECT_EQ(true, ok);

  EXPECT_EQ(true, sql_context->GetSchemaVersion("TestTable", &schema_version));
  EXPECT_EQ(static_cast<int>(StorageManager::kSchemaTableIsNew),
            schema_version);

  sql_context->UpdateSchemaVersion("TestTable", 100);
}

void InspectSchemaVersionCallback(SqlContext* sql_context) {
  int schema_version;
  EXPECT_EQ(true, sql_context->GetSchemaVersion("TestTable", &schema_version));
  EXPECT_EQ(100, schema_version);
}

}  // namespace

class StorageManagerTest : public ::testing::Test {
 protected:
  StorageManagerTest() : message_loop_(MessageLoop::TYPE_DEFAULT) {}

  ~StorageManagerTest() { storage_manager_.reset(NULL); }

  template <typename StorageManagerType>
  void Init(bool delete_savegame = true,
            const Savegame::ByteVector* initial_data = NULL) {
    // Destroy the current one first. We can't have two VFSs with the same name
    // concurrently.
    storage_manager_.reset(NULL);

    scoped_ptr<StorageManager::UpgradeHandler> upgrade_handler(
        new MockUpgradeHandler());
    StorageManager::Options options;
    options.savegame_options.delete_on_destruction = delete_savegame;
    options.savegame_options.factory = &SavegameFake::Create;
    if (initial_data) {
      options.savegame_options.test_initial_data = *initial_data;
    }
    storage_manager_.reset(
        new StorageManagerType(upgrade_handler.Pass(), options));
  }

  MessageLoop message_loop_;
  scoped_ptr<StorageManager> storage_manager_;
};

TEST_F(StorageManagerTest, ObtainConnection) {
  // Verify that the SQL connection is non-null.
  Init<StorageManager>();
  SqlWaiter waiter;
  storage_manager_->GetSqlContext(
      base::Bind(&SqlWaiter::OnSqlConnection, base::Unretained(&waiter)));
  message_loop_.RunUntilIdle();
  EXPECT_EQ(true, waiter.TimedWait());
}

TEST_F(StorageManagerTest, FlushNow) {
  // Ensure the Flush callback is called.
  Init<StorageManager>();
  storage_manager_->GetSqlContext(base::Bind(&FlushCallback));
  message_loop_.RunUntilIdle();
  FlushWaiter waiter;
  storage_manager_->FlushNow(
      base::Bind(&FlushWaiter::OnFlushDone, base::Unretained(&waiter)));
  EXPECT_EQ(true, waiter.TimedWait());
}

TEST_F(StorageManagerTest, QuerySchemaVersion) {
  Init<StorageManager>(false /* delete_savegame */);
  storage_manager_->GetSqlContext(base::Bind(&QuerySchemaCallback));
  message_loop_.RunUntilIdle();

  // Force a write to disk and wait until it's done.
  FlushWaiter waiter;
  storage_manager_->FlushNow(
      base::Bind(&FlushWaiter::OnFlushDone, base::Unretained(&waiter)));
  EXPECT_EQ(true, waiter.TimedWait());

  Init<StorageManager>();
  storage_manager_->GetSqlContext(base::Bind(&InspectSchemaVersionCallback));
  message_loop_.RunUntilIdle();
}

TEST_F(StorageManagerTest, Flush) {
  // Test that the Flush callback is called once (and only once, despite us
  // calling Flush() multiple times).
  Init<MockStorageManager>();

  storage_manager_->GetSqlContext(base::Bind(&FlushCallback));
  message_loop_.RunUntilIdle();

  FlushWaiter waiter;
  MockStorageManager& storage_manager =
      *dynamic_cast<MockStorageManager*>(storage_manager_.get());

  // When QueueFlush() is called, have it also call
  // FlushWaiter::OnFlushDone(). We will wait for this in TimedWait().
  ON_CALL(storage_manager, QueueFlush(_))
      .WillByDefault(InvokeWithoutArgs(&waiter, &FlushWaiter::OnFlushDone));
  EXPECT_CALL(storage_manager, QueueFlush(_)).Times(1);

  for (int i = 0; i < 10; ++i) {
    storage_manager_->Flush();
  }
  EXPECT_EQ(true, waiter.TimedWait());
}

TEST_F(StorageManagerTest, Upgrade) {
  Savegame::ByteVector initial_data;
  initial_data.push_back('U');
  initial_data.push_back('P');
  initial_data.push_back('G');
  initial_data.push_back('0');
  Init<StorageManager>(true, &initial_data);

  // We expect a call to the upgrade handler when it reads this data.
  MockUpgradeHandler& upgrade_handler =
      *dynamic_cast<MockUpgradeHandler*>(storage_manager_->upgrade_handler());
  EXPECT_CALL(upgrade_handler,
              OnUpgrade(Eq(storage_manager_.get()), NotNull(), Eq(4)))
      .Times(1);

  FlushWaiter waiter;
  storage_manager_->FlushNow(
      base::Bind(&FlushWaiter::OnFlushDone, base::Unretained(&waiter)));
  EXPECT_EQ(true, waiter.TimedWait());
  message_loop_.RunUntilIdle();
}

}  // namespace storage
}  // namespace cobalt
