| Index: webkit/dom_storage/dom_storage_cached_area_unittest.cc
|
| ===================================================================
|
| --- webkit/dom_storage/dom_storage_cached_area_unittest.cc (revision 0)
|
| +++ webkit/dom_storage/dom_storage_cached_area_unittest.cc (revision 0)
|
| @@ -0,0 +1,349 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <list>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "webkit/dom_storage/dom_storage_cached_area.h"
|
| +#include "webkit/dom_storage/dom_storage_proxy.h"
|
| +
|
| +namespace dom_storage {
|
| +
|
| +namespace {
|
| +// A mock implementation of the DomStorageProxy interface.
|
| +class MockProxy : public DomStorageProxy {
|
| + public:
|
| + MockProxy() {
|
| + ResetObservations();
|
| + }
|
| +
|
| + // DomStorageProxy interface for use by DomStorageCachedArea.
|
| +
|
| + virtual void LoadArea(int connection_id, ValuesMap* values,
|
| + const CompletionCallback& callback) OVERRIDE {
|
| + pending_callbacks_.push_back(callback);
|
| + observed_load_area_ = true;
|
| + observed_connection_id_ = connection_id;
|
| + *values = load_area_return_values_;
|
| + }
|
| +
|
| + virtual void SetItem(int connection_id, const string16& key,
|
| + const string16& value, const GURL& page_url,
|
| + const CompletionCallback& callback) OVERRIDE {
|
| + pending_callbacks_.push_back(callback);
|
| + observed_set_item_ = true;
|
| + observed_connection_id_ = connection_id;
|
| + observed_key_ = key;
|
| + observed_value_ = value;
|
| + observed_page_url_ = page_url;
|
| + }
|
| +
|
| + virtual void RemoveItem(int connection_id, const string16& key,
|
| + const GURL& page_url,
|
| + const CompletionCallback& callback) OVERRIDE {
|
| + pending_callbacks_.push_back(callback);
|
| + observed_remove_item_ = true;
|
| + observed_connection_id_ = connection_id;
|
| + observed_key_ = key;
|
| + observed_page_url_ = page_url;
|
| + }
|
| +
|
| + virtual void ClearArea(int connection_id,
|
| + const GURL& page_url,
|
| + const CompletionCallback& callback) OVERRIDE {
|
| + pending_callbacks_.push_back(callback);
|
| + observed_clear_area_ = true;
|
| + observed_connection_id_ = connection_id;
|
| + observed_page_url_ = page_url;
|
| + }
|
| +
|
| + // Methods and members for use by test fixtures.
|
| +
|
| + void ResetObservations() {
|
| + observed_load_area_ = false;
|
| + observed_set_item_ = false;
|
| + observed_remove_item_ = false;
|
| + observed_clear_area_ = false;
|
| + observed_connection_id_ = 0;
|
| + observed_key_.clear();
|
| + observed_value_.clear();
|
| + observed_page_url_ = GURL();
|
| + }
|
| +
|
| + void CompleteAllPendingCallbacks() {
|
| + while (!pending_callbacks_.empty())
|
| + CompleteOnePendingCallback(true);
|
| + }
|
| +
|
| + void CompleteOnePendingCallback(bool success) {
|
| + ASSERT_TRUE(!pending_callbacks_.empty());
|
| + pending_callbacks_.front().Run(success);
|
| + pending_callbacks_.pop_front();
|
| + }
|
| +
|
| + typedef std::list<CompletionCallback> CallbackList;
|
| +
|
| + ValuesMap load_area_return_values_;
|
| + CallbackList pending_callbacks_;
|
| + bool observed_load_area_;
|
| + bool observed_set_item_;
|
| + bool observed_remove_item_;
|
| + bool observed_clear_area_;
|
| + int observed_connection_id_;
|
| + string16 observed_key_;
|
| + string16 observed_value_;
|
| + GURL observed_page_url_;
|
| +
|
| + private:
|
| + virtual ~MockProxy() {}
|
| +};
|
| +} // namespace
|
| +
|
| +class DomStorageCachedAreaTest : public testing::Test {
|
| + public:
|
| + DomStorageCachedAreaTest()
|
| + : kNamespaceId(10),
|
| + kOrigin("http://dom_storage/"),
|
| + kKey(ASCIIToUTF16("key")),
|
| + kValue(ASCIIToUTF16("value")),
|
| + kPageUrl("http://dom_storage/page") {
|
| + }
|
| +
|
| + const int64 kNamespaceId;
|
| + const GURL kOrigin;
|
| + const string16 kKey;
|
| + const string16 kValue;
|
| + const GURL kPageUrl;
|
| +
|
| + virtual void SetUp() {
|
| + mock_proxy_ = new MockProxy();
|
| + }
|
| +
|
| + bool IsPrimed(DomStorageCachedArea* cached_area) {
|
| + return cached_area->map_.get();
|
| + }
|
| +
|
| + bool IsIgnoringAllMutations(DomStorageCachedArea* cached_area) {
|
| + return cached_area->ignore_all_mutations_;
|
| + }
|
| +
|
| + bool IsIgnoringKeyMutations(DomStorageCachedArea* cached_area,
|
| + const string16& key) {
|
| + return cached_area->should_ignore_key_mutation(key);
|
| + }
|
| +
|
| + void ResetAll(DomStorageCachedArea* cached_area) {
|
| + cached_area->Reset();
|
| + mock_proxy_->ResetObservations();
|
| + mock_proxy_->pending_callbacks_.clear();
|
| + }
|
| +
|
| + void ResetCacheOnly(DomStorageCachedArea* cached_area) {
|
| + cached_area->Reset();
|
| + }
|
| +
|
| + protected:
|
| + scoped_refptr<MockProxy> mock_proxy_;
|
| +};
|
| +
|
| +TEST_F(DomStorageCachedAreaTest, Basics) {
|
| + EXPECT_TRUE(mock_proxy_->HasOneRef());
|
| + scoped_refptr<DomStorageCachedArea> cached_area =
|
| + new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
|
| + EXPECT_EQ(kNamespaceId, cached_area->namespace_id());
|
| + EXPECT_EQ(kOrigin, cached_area->origin());
|
| + EXPECT_FALSE(mock_proxy_->HasOneRef());
|
| + cached_area->ApplyMutation(NullableString16(kKey, false),
|
| + NullableString16(kValue, false));
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| +
|
| + ResetAll(cached_area);
|
| + EXPECT_EQ(kNamespaceId, cached_area->namespace_id());
|
| + EXPECT_EQ(kOrigin, cached_area->origin());
|
| +
|
| + const int kConnectionId = 1;
|
| + EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
|
| + EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
|
| + EXPECT_EQ(1u, cached_area->GetLength(kConnectionId));
|
| + EXPECT_EQ(kKey, cached_area->GetKey(kConnectionId, 0).string());
|
| + EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
|
| + cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
|
| + EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
|
| +}
|
| +
|
| +TEST_F(DomStorageCachedAreaTest, Getters) {
|
| + const int kConnectionId = 7;
|
| + scoped_refptr<DomStorageCachedArea> cached_area =
|
| + new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
|
| +
|
| + // GetLength, we expect to see one call to load in the proxy.
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| + EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
|
| + EXPECT_TRUE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(mock_proxy_->observed_load_area_);
|
| + EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
|
| + EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
|
| + EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
|
| + mock_proxy_->CompleteAllPendingCallbacks();
|
| + EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
|
| +
|
| + // GetKey, expect the one call to load.
|
| + ResetAll(cached_area);
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(cached_area->GetKey(kConnectionId, 2).is_null());
|
| + EXPECT_TRUE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(mock_proxy_->observed_load_area_);
|
| + EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
|
| + EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
|
| +
|
| + // GetItem, ditto.
|
| + ResetAll(cached_area);
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
|
| + EXPECT_TRUE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(mock_proxy_->observed_load_area_);
|
| + EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
|
| + EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
|
| +}
|
| +
|
| +TEST_F(DomStorageCachedAreaTest, Setters) {
|
| + const int kConnectionId = 7;
|
| + scoped_refptr<DomStorageCachedArea> cached_area =
|
| + new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
|
| +
|
| + // SetItem, we expect a call to load followed by a call to set item
|
| + // in the proxy.
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
|
| + EXPECT_TRUE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(mock_proxy_->observed_load_area_);
|
| + EXPECT_TRUE(mock_proxy_->observed_set_item_);
|
| + EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
|
| + EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
|
| + EXPECT_EQ(kKey, mock_proxy_->observed_key_);
|
| + EXPECT_EQ(kValue, mock_proxy_->observed_value_);
|
| + EXPECT_EQ(2u, mock_proxy_->pending_callbacks_.size());
|
| +
|
| + // Clear, we expect a just the one call to clear in the proxy since
|
| + // there's no need to load the data prior to deleting it.
|
| + ResetAll(cached_area);
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| + cached_area->Clear(kConnectionId, kPageUrl);
|
| + EXPECT_TRUE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(mock_proxy_->observed_clear_area_);
|
| + EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
|
| + EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
|
| + EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
|
| +
|
| + // RemoveItem with nothing to remove, expect just one call to load.
|
| + ResetAll(cached_area);
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| + cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
|
| + EXPECT_TRUE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(mock_proxy_->observed_load_area_);
|
| + EXPECT_FALSE(mock_proxy_->observed_remove_item_);
|
| + EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
|
| + EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
|
| +
|
| + // RemoveItem with something to remove, expect a call to load followed
|
| + // by a call to remove.
|
| + ResetAll(cached_area);
|
| + mock_proxy_->load_area_return_values_[kKey] = NullableString16(kValue, false);
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| + cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
|
| + EXPECT_TRUE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(mock_proxy_->observed_load_area_);
|
| + EXPECT_TRUE(mock_proxy_->observed_remove_item_);
|
| + EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
|
| + EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
|
| + EXPECT_EQ(kKey, mock_proxy_->observed_key_);
|
| + EXPECT_EQ(2u, mock_proxy_->pending_callbacks_.size());
|
| +}
|
| +
|
| +TEST_F(DomStorageCachedAreaTest, MutationsAreIgnoredUntilLoadCompletion) {
|
| + const int kConnectionId = 7;
|
| + scoped_refptr<DomStorageCachedArea> cached_area =
|
| + new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
|
| + EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
|
| + EXPECT_TRUE(IsPrimed(cached_area));
|
| + EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
|
| +
|
| + // Before load completion, the mutation should be ignored.
|
| + cached_area->ApplyMutation(NullableString16(kKey, false),
|
| + NullableString16(kValue, false));
|
| + EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
|
| +
|
| + // Call the load completion callback.
|
| + mock_proxy_->CompleteOnePendingCallback(true);
|
| + EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
|
| +
|
| + // Verify that mutations are now applied.
|
| + cached_area->ApplyMutation(NullableString16(kKey, false),
|
| + NullableString16(kValue, false));
|
| + EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
|
| +}
|
| +
|
| +TEST_F(DomStorageCachedAreaTest, MutationsAreIgnoredUntilClearCompletion) {
|
| + const int kConnectionId = 4;
|
| + scoped_refptr<DomStorageCachedArea> cached_area =
|
| + new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
|
| + cached_area->Clear(kConnectionId, kPageUrl);
|
| + EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
|
| + mock_proxy_->CompleteOnePendingCallback(true);
|
| + EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
|
| +
|
| + // Verify that calling Clear twice works as expected, the first
|
| + // completion callback should have been cancelled.
|
| + ResetCacheOnly(cached_area);
|
| + cached_area->Clear(kConnectionId, kPageUrl);
|
| + EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
|
| + cached_area->Clear(kConnectionId, kPageUrl);
|
| + EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
|
| + mock_proxy_->CompleteOnePendingCallback(true);
|
| + EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
|
| + mock_proxy_->CompleteOnePendingCallback(true);
|
| + EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
|
| +}
|
| +
|
| +TEST_F(DomStorageCachedAreaTest, KeyMutationsAreIgnoredUntilCompletion) {
|
| + const int kConnectionId = 8;
|
| + scoped_refptr<DomStorageCachedArea> cached_area =
|
| + new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
|
| +
|
| + // SetItem
|
| + EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
|
| + mock_proxy_->CompleteOnePendingCallback(true); // load completion
|
| + EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
|
| + EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
|
| + cached_area->ApplyMutation(NullableString16(kKey, false),
|
| + NullableString16(true));
|
| + EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
|
| + mock_proxy_->CompleteOnePendingCallback(true); // set completion
|
| + EXPECT_FALSE(IsIgnoringKeyMutations(cached_area, kKey));
|
| +
|
| + // RemoveItem
|
| + cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
|
| + EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
|
| + mock_proxy_->CompleteOnePendingCallback(true); // remove completion
|
| + EXPECT_FALSE(IsIgnoringKeyMutations(cached_area, kKey));
|
| +
|
| + // Multiple mutations to the same key.
|
| + EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
|
| + cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
|
| + EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
|
| + mock_proxy_->CompleteOnePendingCallback(true); // set completion
|
| + EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
|
| + mock_proxy_->CompleteOnePendingCallback(true); // remove completion
|
| + EXPECT_FALSE(IsIgnoringKeyMutations(cached_area, kKey));
|
| +
|
| + // A failed set item operation should Reset the cache.
|
| + EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
|
| + EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
|
| + mock_proxy_->CompleteOnePendingCallback(false);
|
| + EXPECT_FALSE(IsPrimed(cached_area));
|
| +}
|
| +
|
| +} // namespace dom_storage
|
|
|
| Property changes on: webkit\dom_storage\dom_storage_cached_area_unittest.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|