// 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/network/persistent_cookie_store.h"

#include <vector>

#include "base/file_path.h"
#include "base/file_util.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.h"
#include "cobalt/storage/savegame_fake.h"
#include "cobalt/storage/storage_manager.h"
#include "googleurl/src/gurl.h"
#include "net/cookies/canonical_cookie.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace network {

namespace {

scoped_ptr<net::CanonicalCookie> CreateTestCookie() {
  GURL url("http://www.example.com/test");
  base::Time current_time = base::Time::Now();
  base::Time expiration_time = current_time + base::TimeDelta::FromDays(1);
  scoped_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
      url, "A", "2", "www.example.com", "/test", "", "", current_time,
      expiration_time, false, false));
  return cookie.Pass();
}

void DummyOnLoaded(const std::vector<net::CanonicalCookie*>& cookies) {
  UNREFERENCED_PARAMETER(cookies);
}

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 CookieLoader : public CallbackWaiter {
 public:
  CookieLoader() {}
  ~CookieLoader() {
    for (std::vector<net::CanonicalCookie*>::iterator it = cookies.begin();
         it != cookies.end(); ++it) {
      delete *it;
    }
  }

  void OnCookieLoad(const std::vector<net::CanonicalCookie*>& loaded_cookies) {
    cookies = loaded_cookies;
    Signal();
  }
  std::vector<net::CanonicalCookie*> cookies;

 private:
  DISALLOW_COPY_AND_ASSIGN(CookieLoader);
};

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

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

class PersistentCookieStoreTest : public ::testing::Test {
 protected:
  PersistentCookieStoreTest() : message_loop_(MessageLoop::TYPE_DEFAULT) {
    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));
    cookie_store_ = new PersistentCookieStore(storage_manager_.get());
  }

  ~PersistentCookieStoreTest() {
    cookie_store_ = NULL;
    storage_manager_.reset(NULL);
  }

  MessageLoop message_loop_;
  scoped_ptr<storage::StorageManager> storage_manager_;
  scoped_refptr<PersistentCookieStore> cookie_store_;
};
}  // namespace

TEST_F(PersistentCookieStoreTest, LoadGetsAddedCookies) {
  // Put a cookie into the database. Flush, then reload and make sure
  // the Loaded callback contains it.
  scoped_ptr<net::CanonicalCookie> test_cookie(CreateTestCookie());
  cookie_store_->Load(base::Bind(&DummyOnLoaded));
  cookie_store_->AddCookie(*test_cookie);
  FlushWaiter waiter;
  cookie_store_->Flush(
      base::Bind(&FlushWaiter::OnFlushDone, base::Unretained(&waiter)));
  EXPECT_EQ(true, waiter.TimedWait());

  cookie_store_ = new PersistentCookieStore(storage_manager_.get());
  CookieLoader loader;
  cookie_store_->Load(
      base::Bind(&CookieLoader::OnCookieLoad, base::Unretained(&loader)));
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(loader.TimedWait());
  ASSERT_EQ(1, loader.cookies.size());
  EXPECT_TRUE(test_cookie->IsEquivalent(*loader.cookies[0]));
}
}  // namespace network
}  // namespace cobalt
