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

#include <set>
#include <vector>

#include "cobalt/dom/storage.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using testing::_;
using testing::Return;

namespace cobalt {
namespace dom {

namespace {
class MockStorage : public Storage {
 public:
  MockStorage() : Storage(NULL, kSessionStorage, NULL) {
      ON_CALL(*this, origin()).WillByDefault(
          Return(GURL("https://www.example.com")));
      EXPECT_CALL(*this, origin()).Times(1);
  }
  MOCK_METHOD3(DispatchEvent, bool(const base::optional<std::string>&,
                                   const base::optional<std::string>&,
                                   const base::optional<std::string>&));
  MOCK_CONST_METHOD0(origin, GURL());
};

base::optional<std::string> ToOptStr(const char* str) {
  return base::optional<std::string>(str);
}

}  // namespace

TEST(StorageAreaTest, InitialState) {
  scoped_refptr<MockStorage> mock_storage(new MockStorage());
  EXPECT_EQ(0, mock_storage->length());
  EXPECT_EQ(0, mock_storage->area_->size_bytes());
}

TEST(StorageAreaTest, Identifier) {
  scoped_refptr<MockStorage> mock_storage(new MockStorage());
  EXPECT_EQ(0, mock_storage->length());
  EXPECT_EQ("https_www.example.com_0.sessionstorage",
            mock_storage->area_->identifier());
}

TEST(StorageAreaTest, SetItem) {
  scoped_refptr<MockStorage> mock_storage(new MockStorage());
  EXPECT_CALL(*mock_storage,
              DispatchEvent(base::optional<std::string>("key"),
                            base::optional<std::string>(base::nullopt),
                            base::optional<std::string>("value")));
  mock_storage->SetItem("key", "value");
}

TEST(StorageAreaTest, IndexedKeys) {
  scoped_refptr<MockStorage> mock_storage(new MockStorage());

  std::set<std::string> found_keys;
  std::set<std::string> test_keys;
  test_keys.insert("key0");
  test_keys.insert("key1");
  test_keys.insert("key2");
  EXPECT_CALL(*mock_storage, DispatchEvent(_, _, _)).Times(3);
  for (std::set<std::string>::const_iterator it = test_keys.begin();
       it != test_keys.end(); ++it) {
    mock_storage->SetItem(*it, "value");
  }
  for (size_t i = 0; i < test_keys.size(); ++i) {
    found_keys.insert(mock_storage->Key(static_cast<unsigned int>(i)).value());
  }
  EXPECT_EQ(test_keys, found_keys);
}

TEST(StorageAreaTest, Overwrite) {
  scoped_refptr<MockStorage> mock_storage(new MockStorage());
  EXPECT_EQ(base::nullopt, mock_storage->GetItem("key"));
  EXPECT_CALL(*mock_storage,
              DispatchEvent(ToOptStr("key"), _, ToOptStr("old_value")));
  mock_storage->SetItem("key", "old_value");
  EXPECT_EQ(std::string("old_value"), mock_storage->GetItem("key"));
  EXPECT_CALL(*mock_storage,
              DispatchEvent(ToOptStr("key"), ToOptStr("old_value"),
                            ToOptStr("new_value")));
  mock_storage->SetItem("key", "new_value");
  EXPECT_EQ(std::string("new_value"), mock_storage->GetItem("key"));
}

TEST(StorageAreaTest, KeyOrder) {
  scoped_refptr<MockStorage> mock_storage(new MockStorage());

  std::vector<std::string> found_keys0;
  std::vector<std::string> found_keys1;
  std::vector<std::string> found_keys2;
  std::set<std::string> test_keys;
  test_keys.insert("key0");
  test_keys.insert("key1");
  test_keys.insert("key2");
  EXPECT_CALL(*mock_storage, DispatchEvent(_, _, _)).Times(3);
  for (std::set<std::string>::const_iterator it = test_keys.begin();
       it != test_keys.end(); ++it) {
    mock_storage->SetItem(*it, "value");
  }
  // Verify that the key order is consistent.
  for (size_t i = 0; i < test_keys.size(); ++i) {
    found_keys0.push_back(
        mock_storage->Key(static_cast<unsigned int>(i)).value());
  }
  for (size_t i = 0; i < test_keys.size(); ++i) {
    found_keys1.push_back(
        mock_storage->Key(static_cast<unsigned int>(i)).value());
  }
  EXPECT_EQ(found_keys0, found_keys1);

  // Verify that key order doesn't change even when the value does.
  EXPECT_CALL(*mock_storage, DispatchEvent(_, _, _));
  mock_storage->SetItem("key0", "new_value");
  for (size_t i = 0; i < test_keys.size(); ++i) {
    found_keys2.push_back(
        mock_storage->Key(static_cast<unsigned int>(i)).value());
  }
  EXPECT_EQ(found_keys0, found_keys2);
}

}  // namespace dom
}  // namespace cobalt
