/*
 * 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/dom/local_storage_database.h"

#include <vector>

#include "base/file_path.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "base/time.h"
#include "cobalt/base/cobalt_paths.h"
#include "cobalt/storage/savegame_fake.h"
#include "cobalt/storage/storage_manager.h"

#include "sql/connection.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace dom {

namespace {

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 Reader : public CallbackWaiter {
 public:
  Reader() {}
  ~Reader() {}

  void OnReadAll(scoped_ptr<StorageArea::StorageMap> data) {
    data_ = *data;
    Signal();
  }
  StorageArea::StorageMap data_;

 private:
  DISALLOW_COPY_AND_ASSIGN(Reader);
};

std::string GetSavePath() {
  FilePath test_path;
  CHECK(PathService::Get(paths::DIR_COBALT_TEST_OUT, &test_path));
  return test_path.Append("local_storage_database_test.bin").value();
}

class DummyUpgradeHandler : public storage::StorageManager::UpgradeHandler {
  void OnUpgrade(storage::StorageManager* /*storage*/, const char* /*data*/,
                 int /*size*/) OVERRIDE {}
};

class LocalStorageDatabaseTest : public ::testing::Test {
 protected:
  LocalStorageDatabaseTest()
      : message_loop_(MessageLoop::TYPE_DEFAULT),
        host_("https://www.example.com") {
    scoped_ptr<storage::StorageManager::UpgradeHandler> upgrade_handler(
        new DummyUpgradeHandler());
    storage::StorageManager::Options options;
    options.savegame_options.path_override = GetSavePath();
    options.savegame_options.delete_on_destruction = true;
    options.savegame_options.factory = &storage::SavegameFake::Create;

    storage_manager_.reset(
        new storage::StorageManager(upgrade_handler.Pass(), options));
    db_.reset(new LocalStorageDatabase(storage_manager_.get()));
  }

  ~LocalStorageDatabaseTest() {
    db_.reset();
    storage_manager_.reset();
  }

  MessageLoop message_loop_;
  std::string host_;
  scoped_ptr<storage::StorageManager> storage_manager_;
  scoped_ptr<LocalStorageDatabase> db_;
};
}  // namespace

TEST_F(LocalStorageDatabaseTest, EmptyRead) {
  StorageArea::StorageMap empty;
  Reader reader;
  db_->ReadAll(host_,
               base::Bind(&Reader::OnReadAll, base::Unretained(&reader)));
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(reader.TimedWait());
  EXPECT_EQ(empty, reader.data_);
}

TEST_F(LocalStorageDatabaseTest, WritePersists) {
  StorageArea::StorageMap test_vals;
  test_vals["key0"] = "value0";
  test_vals["key1"] = "value1";

  for (StorageArea::StorageMap::const_iterator it = test_vals.begin();
       it != test_vals.end(); ++it) {
    db_->Write(host_, it->first, it->second);
  }

  FlushWaiter waiter;
  db_->Flush(base::Bind(&FlushWaiter::OnFlushDone, base::Unretained(&waiter)));
  EXPECT_EQ(true, waiter.TimedWait());

  // Ensure a Flush persists the data.
  db_.reset(new LocalStorageDatabase(storage_manager_.get()));
  Reader reader;
  db_->ReadAll(host_,
               base::Bind(&Reader::OnReadAll, base::Unretained(&reader)));
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(reader.TimedWait());
  EXPECT_EQ(test_vals, reader.data_);
}

TEST_F(LocalStorageDatabaseTest, Delete) {
  StorageArea::StorageMap test_vals;
  test_vals["key0"] = "value0";
  test_vals["key1"] = "value1";

  for (StorageArea::StorageMap::const_iterator it = test_vals.begin();
       it != test_vals.end(); ++it) {
    db_->Write(host_, it->first, it->second);
  }

  db_->Delete(host_, "key0");
  StorageArea::StorageMap expected_vals;
  expected_vals["key1"] = "value1";
  Reader reader;
  db_->ReadAll(host_,
               base::Bind(&Reader::OnReadAll, base::Unretained(&reader)));
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(reader.TimedWait());
  EXPECT_EQ(expected_vals, reader.data_);
}

TEST_F(LocalStorageDatabaseTest, Clear) {
  StorageArea::StorageMap test_vals;
  test_vals["key0"] = "value0";
  test_vals["key1"] = "value1";

  for (StorageArea::StorageMap::const_iterator it = test_vals.begin();
       it != test_vals.end(); ++it) {
    db_->Write(host_, it->first, it->second);
  }
  db_->Clear(host_);
  StorageArea::StorageMap expected_vals;
  Reader reader;
  db_->ReadAll(host_,
               base::Bind(&Reader::OnReadAll, base::Unretained(&reader)));
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(reader.TimedWait());
  EXPECT_EQ(expected_vals, reader.data_);
}
}  // namespace dom
}  // namespace cobalt
