/*
 * Copyright 2016 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 <cstring>

#include "base/base_paths.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/platform_file.h"
#include "base/time.h"
#include "cobalt/storage/upgrade/upgrade_reader.h"
#include "googleurl/src/gurl.h"
#include "net/cookies/canonical_cookie.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace storage {
namespace upgrade {

namespace {

const int kHeaderSize = 4;
const char kHeader[] = "UPG0";

void ReadFileToString(const char* pathname, std::string* string_out) {
  EXPECT_TRUE(pathname);
  EXPECT_TRUE(string_out);
  FilePath file_path;
  EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
  file_path = file_path.Append(pathname);
  EXPECT_TRUE(file_util::ReadFileToString(file_path, string_out));
  EXPECT_GT(string_out->length(), static_cast<size_t>(kHeaderSize));
  EXPECT_LE(string_out->length(), static_cast<size_t>(10 * 1024 * 1024));
  EXPECT_EQ(string_out->find(kHeader), 0);
}

void ValidateCookie(const net::CanonicalCookie* cookie, const std::string& url,
                    const std::string& name, const std::string& value,
                    const std::string domain, const std::string& path,
                    const base::Time& creation, const base::Time expiration,
                    bool http_only) {
  EXPECT_TRUE(cookie);
  EXPECT_EQ(cookie->Source(),
            net::CanonicalCookie::GetCookieSourceFromURL(GURL(url)));
  EXPECT_EQ(cookie->Name(), name);
  EXPECT_EQ(cookie->Value(), value);
  EXPECT_EQ(cookie->Domain(), domain);
  EXPECT_EQ(cookie->Path(), path);
  EXPECT_EQ((cookie->CreationDate() - creation).InSeconds(), 0);
  EXPECT_EQ((cookie->ExpiryDate() - expiration).InSeconds(), 0);
  EXPECT_EQ((cookie->LastAccessDate() - base::Time::Now()).InSeconds(), 0);
  EXPECT_EQ(cookie->IsSecure(), true);
  EXPECT_EQ(cookie->IsHttpOnly(), http_only);
}

void ValidateCookie(const net::CanonicalCookie* cookie, const std::string& url,
                    const std::string& name, const std::string& value) {
  const std::string host = GURL(url).host();
  const std::string domain = host.empty() ? "" : host.substr(host.find("."));
  const std::string path = "/";
  const base::Time creation = base::Time::Now();
  const base::Time expiration = creation;
  const bool http_only = false;
  ValidateCookie(cookie, url, name, value, domain, path, creation, expiration,
                 http_only);
}

void ValidateLocalStorageEntry(
    const UpgradeReader::LocalStorageEntry* local_storage_entry,
    const std::string& key, const std::string& value) {
  EXPECT_TRUE(local_storage_entry);
  EXPECT_EQ(local_storage_entry->key, key);
  EXPECT_EQ(local_storage_entry->value, value);
}

}  // namespace

TEST(StorageUpgradeTest, UpgradeMinimalCookie) {
  std::string file_contents;
  ReadFileToString("cobalt/storage/upgrade/testdata/minimal_cookie_v1.json",
                   &file_contents);
  UpgradeReader upgrade_reader(
      file_contents.c_str() + kHeaderSize,
      static_cast<int>(file_contents.length()) - kHeaderSize);

  // 1 cookie.
  EXPECT_EQ(upgrade_reader.GetNumCookies(), 1);
  const net::CanonicalCookie* cookie = upgrade_reader.GetCookie(0);
  ValidateCookie(cookie, "https://www.youtube.com/", "cookie_name",
                 "cookie_value");
  EXPECT_FALSE(upgrade_reader.GetCookie(1));

  // 0 local storage entries.
  EXPECT_EQ(upgrade_reader.GetNumLocalStorageEntries(), 0);
  EXPECT_FALSE(upgrade_reader.GetLocalStorageEntry(0));
}

TEST(StorageUpgradeTest, UpgradeMinimalLocalStorageEntry) {
  std::string file_contents;
  ReadFileToString(
      "cobalt/storage/upgrade/testdata/minimal_local_storage_entry_v1.json",
      &file_contents);
  UpgradeReader upgrade_reader(
      file_contents.c_str() + kHeaderSize,
      static_cast<int>(file_contents.length()) - kHeaderSize);

  // 0 cookies.
  EXPECT_EQ(upgrade_reader.GetNumCookies(), 0);
  EXPECT_FALSE(upgrade_reader.GetCookie(0));

  // 1 local storage entry.
  EXPECT_EQ(upgrade_reader.GetNumLocalStorageEntries(), 1);
  const UpgradeReader::LocalStorageEntry* local_storage_entry =
      upgrade_reader.GetLocalStorageEntry(0);
  ValidateLocalStorageEntry(local_storage_entry, "key-1", "value-1");
  EXPECT_FALSE(upgrade_reader.GetLocalStorageEntry(1));
}

TEST(StorageUpgradeTest, UpgradeFullData) {
  std::string file_contents;
  ReadFileToString("cobalt/storage/upgrade/testdata/full_data_v1.json",
                   &file_contents);
  UpgradeReader upgrade_reader(
      file_contents.c_str() + kHeaderSize,
      static_cast<int>(file_contents.length()) - kHeaderSize);

  // 2 cookies.
  EXPECT_EQ(upgrade_reader.GetNumCookies(), 2);
  const net::CanonicalCookie* cookie = upgrade_reader.GetCookie(0);
  base::Time creation = base::Time::FromInternalValue(13119668760000000L);
  base::Time expiration = base::Time::FromInternalValue(13120000000000000L);
  ValidateCookie(cookie, "https://www.youtube.com/", "cookie_name",
                 "cookie_value", "cookie.domain", "cookie/path", creation,
                 expiration, true);
  cookie = upgrade_reader.GetCookie(1);
  creation = base::Time::FromInternalValue(13109668760000000L);
  expiration = base::Time::FromInternalValue(13110000000000000L);
  ValidateCookie(cookie, "https://www.somewhere.com/", "cookie_name_2",
                 "cookie_value_2", "cookie.domain2", "cookie/path/2", creation,
                 expiration, true);
  EXPECT_FALSE(upgrade_reader.GetCookie(2));

  // 2 local storage entries.
  EXPECT_EQ(upgrade_reader.GetNumLocalStorageEntries(), 2);
  const UpgradeReader::LocalStorageEntry* local_storage_entry =
      upgrade_reader.GetLocalStorageEntry(0);
  ValidateLocalStorageEntry(local_storage_entry, "key-1", "value-1");
  local_storage_entry = upgrade_reader.GetLocalStorageEntry(1);
  ValidateLocalStorageEntry(local_storage_entry, "key-2", "value-2");
  EXPECT_FALSE(upgrade_reader.GetLocalStorageEntry(2));
}

TEST(StorageUpgradeTest, UpgradeMissingFields) {
  std::string file_contents;
  ReadFileToString("cobalt/storage/upgrade/testdata/missing_fields_v1.json",
                   &file_contents);
  UpgradeReader upgrade_reader(
      file_contents.c_str() + kHeaderSize,
      static_cast<int>(file_contents.length()) - kHeaderSize);

  // 1 cookie with missing fields, 2 local storage entries with missing fields,
  // 1 valid local storage entry.
  EXPECT_EQ(upgrade_reader.GetNumCookies(), 0);
  EXPECT_FALSE(upgrade_reader.GetCookie(0));
  EXPECT_EQ(upgrade_reader.GetNumLocalStorageEntries(), 1);
  const UpgradeReader::LocalStorageEntry* local_storage_entry =
      upgrade_reader.GetLocalStorageEntry(0);
  ValidateLocalStorageEntry(local_storage_entry, "key-3", "value-3");
  EXPECT_FALSE(upgrade_reader.GetLocalStorageEntry(1));
}

TEST(StorageUpgradeTest, UpgradeMalformed) {
  std::string file_contents;
  ReadFileToString("cobalt/storage/upgrade/testdata/malformed_v1.json",
                   &file_contents);
  UpgradeReader upgrade_reader(
      file_contents.c_str() + kHeaderSize,
      static_cast<int>(file_contents.length()) - kHeaderSize);

  // No cookies or local storage entries available in malformed data.
  EXPECT_EQ(upgrade_reader.GetNumCookies(), 0);
  EXPECT_FALSE(upgrade_reader.GetCookie(0));
  EXPECT_EQ(upgrade_reader.GetNumLocalStorageEntries(), 0);
  EXPECT_FALSE(upgrade_reader.GetLocalStorageEntry(0));
}

TEST(StorageUpgradeTest, UpgradeExtraFields) {
  std::string file_contents;
  ReadFileToString("cobalt/storage/upgrade/testdata/extra_fields_v1.json",
                   &file_contents);
  UpgradeReader upgrade_reader(
      file_contents.c_str() + kHeaderSize,
      static_cast<int>(file_contents.length()) - kHeaderSize);

  // 1 cookie, extra fields should be ignored.
  EXPECT_EQ(upgrade_reader.GetNumCookies(), 1);
  const net::CanonicalCookie* cookie = upgrade_reader.GetCookie(0);
  ValidateCookie(cookie, "https://www.youtube.com/", "cookie_name",
                 "cookie_value");
  EXPECT_FALSE(upgrade_reader.GetCookie(1));

  // 2 local storage entries, extra fields should be ignored.
  EXPECT_EQ(upgrade_reader.GetNumLocalStorageEntries(), 2);
  const UpgradeReader::LocalStorageEntry* local_storage_entry =
      upgrade_reader.GetLocalStorageEntry(0);
  ValidateLocalStorageEntry(local_storage_entry, "key-1", "value-1");
  local_storage_entry = upgrade_reader.GetLocalStorageEntry(1);
  ValidateLocalStorageEntry(local_storage_entry, "key-2", "value-2");
  EXPECT_FALSE(upgrade_reader.GetLocalStorageEntry(2));
}

}  // namespace upgrade
}  // namespace storage
}  // namespace cobalt
