Replace FINAL and OVERRIDE with their C++11 counterparts in content/renderer
[chromium-blink-merge.git] / content / renderer / dom_storage / dom_storage_cached_area_unittest.cc
blob39b1eb76a2f6feab1b7ebc75087eb736413e1ef4
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/dom_storage/dom_storage_cached_area.h"
7 #include <list>
9 #include "base/bind.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/renderer/dom_storage/dom_storage_proxy.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 namespace content {
16 namespace {
17 // A mock implementation of the DOMStorageProxy interface.
18 class MockProxy : public DOMStorageProxy {
19 public:
20 MockProxy() {
21 ResetObservations();
24 // DOMStorageProxy interface for use by DOMStorageCachedArea.
26 virtual void LoadArea(int connection_id,
27 DOMStorageValuesMap* values,
28 bool* send_log_get_messages,
29 const CompletionCallback& callback) override {
30 pending_callbacks_.push_back(callback);
31 observed_load_area_ = true;
32 observed_connection_id_ = connection_id;
33 *values = load_area_return_values_;
34 *send_log_get_messages = false;
37 virtual void SetItem(int connection_id,
38 const base::string16& key,
39 const base::string16& value,
40 const GURL& page_url,
41 const CompletionCallback& callback) override {
42 pending_callbacks_.push_back(callback);
43 observed_set_item_ = true;
44 observed_connection_id_ = connection_id;
45 observed_key_ = key;
46 observed_value_ = value;
47 observed_page_url_ = page_url;
50 virtual void LogGetItem(int connection_id,
51 const base::string16& key,
52 const base::NullableString16& value) override {
55 virtual void RemoveItem(int connection_id,
56 const base::string16& key,
57 const GURL& page_url,
58 const CompletionCallback& callback) override {
59 pending_callbacks_.push_back(callback);
60 observed_remove_item_ = true;
61 observed_connection_id_ = connection_id;
62 observed_key_ = key;
63 observed_page_url_ = page_url;
66 virtual void ClearArea(int connection_id,
67 const GURL& page_url,
68 const CompletionCallback& callback) override {
69 pending_callbacks_.push_back(callback);
70 observed_clear_area_ = true;
71 observed_connection_id_ = connection_id;
72 observed_page_url_ = page_url;
75 // Methods and members for use by test fixtures.
77 void ResetObservations() {
78 observed_load_area_ = false;
79 observed_set_item_ = false;
80 observed_remove_item_ = false;
81 observed_clear_area_ = false;
82 observed_connection_id_ = 0;
83 observed_key_.clear();
84 observed_value_.clear();
85 observed_page_url_ = GURL();
88 void CompleteAllPendingCallbacks() {
89 while (!pending_callbacks_.empty())
90 CompleteOnePendingCallback(true);
93 void CompleteOnePendingCallback(bool success) {
94 ASSERT_TRUE(!pending_callbacks_.empty());
95 pending_callbacks_.front().Run(success);
96 pending_callbacks_.pop_front();
99 typedef std::list<CompletionCallback> CallbackList;
101 DOMStorageValuesMap load_area_return_values_;
102 CallbackList pending_callbacks_;
103 bool observed_load_area_;
104 bool observed_set_item_;
105 bool observed_remove_item_;
106 bool observed_clear_area_;
107 int observed_connection_id_;
108 base::string16 observed_key_;
109 base::string16 observed_value_;
110 GURL observed_page_url_;
112 private:
113 virtual ~MockProxy() {}
116 } // namespace
118 class DOMStorageCachedAreaTest : public testing::Test {
119 public:
120 DOMStorageCachedAreaTest()
121 : kNamespaceId(10),
122 kOrigin("http://dom_storage/"),
123 kKey(base::ASCIIToUTF16("key")),
124 kValue(base::ASCIIToUTF16("value")),
125 kPageUrl("http://dom_storage/page") {
128 const int64 kNamespaceId;
129 const GURL kOrigin;
130 const base::string16 kKey;
131 const base::string16 kValue;
132 const GURL kPageUrl;
134 virtual void SetUp() {
135 mock_proxy_ = new MockProxy();
138 bool IsPrimed(DOMStorageCachedArea* cached_area) {
139 return cached_area->map_.get();
142 bool IsIgnoringAllMutations(DOMStorageCachedArea* cached_area) {
143 return cached_area->ignore_all_mutations_;
146 bool IsIgnoringKeyMutations(DOMStorageCachedArea* cached_area,
147 const base::string16& key) {
148 return cached_area->should_ignore_key_mutation(key);
151 void ResetAll(DOMStorageCachedArea* cached_area) {
152 cached_area->Reset();
153 mock_proxy_->ResetObservations();
154 mock_proxy_->pending_callbacks_.clear();
157 void ResetCacheOnly(DOMStorageCachedArea* cached_area) {
158 cached_area->Reset();
161 protected:
162 scoped_refptr<MockProxy> mock_proxy_;
165 TEST_F(DOMStorageCachedAreaTest, Basics) {
166 EXPECT_TRUE(mock_proxy_->HasOneRef());
167 scoped_refptr<DOMStorageCachedArea> cached_area =
168 new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get());
169 EXPECT_EQ(kNamespaceId, cached_area->namespace_id());
170 EXPECT_EQ(kOrigin, cached_area->origin());
171 EXPECT_FALSE(mock_proxy_->HasOneRef());
172 cached_area->ApplyMutation(base::NullableString16(kKey, false),
173 base::NullableString16(kValue, false));
174 EXPECT_FALSE(IsPrimed(cached_area.get()));
176 ResetAll(cached_area.get());
177 EXPECT_EQ(kNamespaceId, cached_area->namespace_id());
178 EXPECT_EQ(kOrigin, cached_area->origin());
180 const int kConnectionId = 1;
181 EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
182 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
183 EXPECT_EQ(1u, cached_area->GetLength(kConnectionId));
184 EXPECT_EQ(kKey, cached_area->GetKey(kConnectionId, 0).string());
185 EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
186 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
187 EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
190 TEST_F(DOMStorageCachedAreaTest, Getters) {
191 const int kConnectionId = 7;
192 scoped_refptr<DOMStorageCachedArea> cached_area =
193 new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get());
195 // GetLength, we expect to see one call to load in the proxy.
196 EXPECT_FALSE(IsPrimed(cached_area.get()));
197 EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
198 EXPECT_TRUE(IsPrimed(cached_area.get()));
199 EXPECT_TRUE(mock_proxy_->observed_load_area_);
200 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
201 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
202 EXPECT_TRUE(IsIgnoringAllMutations(cached_area.get()));
203 mock_proxy_->CompleteAllPendingCallbacks();
204 EXPECT_FALSE(IsIgnoringAllMutations(cached_area.get()));
206 // GetKey, expect the one call to load.
207 ResetAll(cached_area.get());
208 EXPECT_FALSE(IsPrimed(cached_area.get()));
209 EXPECT_TRUE(cached_area->GetKey(kConnectionId, 2).is_null());
210 EXPECT_TRUE(IsPrimed(cached_area.get()));
211 EXPECT_TRUE(mock_proxy_->observed_load_area_);
212 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
213 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
215 // GetItem, ditto.
216 ResetAll(cached_area.get());
217 EXPECT_FALSE(IsPrimed(cached_area.get()));
218 EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
219 EXPECT_TRUE(IsPrimed(cached_area.get()));
220 EXPECT_TRUE(mock_proxy_->observed_load_area_);
221 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
222 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
225 TEST_F(DOMStorageCachedAreaTest, Setters) {
226 const int kConnectionId = 7;
227 scoped_refptr<DOMStorageCachedArea> cached_area =
228 new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get());
230 // SetItem, we expect a call to load followed by a call to set item
231 // in the proxy.
232 EXPECT_FALSE(IsPrimed(cached_area.get()));
233 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
234 EXPECT_TRUE(IsPrimed(cached_area.get()));
235 EXPECT_TRUE(mock_proxy_->observed_load_area_);
236 EXPECT_TRUE(mock_proxy_->observed_set_item_);
237 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
238 EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
239 EXPECT_EQ(kKey, mock_proxy_->observed_key_);
240 EXPECT_EQ(kValue, mock_proxy_->observed_value_);
241 EXPECT_EQ(2u, mock_proxy_->pending_callbacks_.size());
243 // Clear, we expect a just the one call to clear in the proxy since
244 // there's no need to load the data prior to deleting it.
245 ResetAll(cached_area.get());
246 EXPECT_FALSE(IsPrimed(cached_area.get()));
247 cached_area->Clear(kConnectionId, kPageUrl);
248 EXPECT_TRUE(IsPrimed(cached_area.get()));
249 EXPECT_TRUE(mock_proxy_->observed_clear_area_);
250 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
251 EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
252 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
254 // RemoveItem with nothing to remove, expect just one call to load.
255 ResetAll(cached_area.get());
256 EXPECT_FALSE(IsPrimed(cached_area.get()));
257 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
258 EXPECT_TRUE(IsPrimed(cached_area.get()));
259 EXPECT_TRUE(mock_proxy_->observed_load_area_);
260 EXPECT_FALSE(mock_proxy_->observed_remove_item_);
261 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
262 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
264 // RemoveItem with something to remove, expect a call to load followed
265 // by a call to remove.
266 ResetAll(cached_area.get());
267 mock_proxy_->load_area_return_values_[kKey] =
268 base::NullableString16(kValue, false);
269 EXPECT_FALSE(IsPrimed(cached_area.get()));
270 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
271 EXPECT_TRUE(IsPrimed(cached_area.get()));
272 EXPECT_TRUE(mock_proxy_->observed_load_area_);
273 EXPECT_TRUE(mock_proxy_->observed_remove_item_);
274 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
275 EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
276 EXPECT_EQ(kKey, mock_proxy_->observed_key_);
277 EXPECT_EQ(2u, mock_proxy_->pending_callbacks_.size());
280 TEST_F(DOMStorageCachedAreaTest, MutationsAreIgnoredUntilLoadCompletion) {
281 const int kConnectionId = 7;
282 scoped_refptr<DOMStorageCachedArea> cached_area =
283 new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get());
284 EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
285 EXPECT_TRUE(IsPrimed(cached_area.get()));
286 EXPECT_TRUE(IsIgnoringAllMutations(cached_area.get()));
288 // Before load completion, the mutation should be ignored.
289 cached_area->ApplyMutation(base::NullableString16(kKey, false),
290 base::NullableString16(kValue, false));
291 EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
293 // Call the load completion callback.
294 mock_proxy_->CompleteOnePendingCallback(true);
295 EXPECT_FALSE(IsIgnoringAllMutations(cached_area.get()));
297 // Verify that mutations are now applied.
298 cached_area->ApplyMutation(base::NullableString16(kKey, false),
299 base::NullableString16(kValue, false));
300 EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
303 TEST_F(DOMStorageCachedAreaTest, MutationsAreIgnoredUntilClearCompletion) {
304 const int kConnectionId = 4;
305 scoped_refptr<DOMStorageCachedArea> cached_area =
306 new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get());
307 cached_area->Clear(kConnectionId, kPageUrl);
308 EXPECT_TRUE(IsIgnoringAllMutations(cached_area.get()));
309 mock_proxy_->CompleteOnePendingCallback(true);
310 EXPECT_FALSE(IsIgnoringAllMutations(cached_area.get()));
312 // Verify that calling Clear twice works as expected, the first
313 // completion callback should have been cancelled.
314 ResetCacheOnly(cached_area.get());
315 cached_area->Clear(kConnectionId, kPageUrl);
316 EXPECT_TRUE(IsIgnoringAllMutations(cached_area.get()));
317 cached_area->Clear(kConnectionId, kPageUrl);
318 EXPECT_TRUE(IsIgnoringAllMutations(cached_area.get()));
319 mock_proxy_->CompleteOnePendingCallback(true);
320 EXPECT_TRUE(IsIgnoringAllMutations(cached_area.get()));
321 mock_proxy_->CompleteOnePendingCallback(true);
322 EXPECT_FALSE(IsIgnoringAllMutations(cached_area.get()));
325 TEST_F(DOMStorageCachedAreaTest, KeyMutationsAreIgnoredUntilCompletion) {
326 const int kConnectionId = 8;
327 scoped_refptr<DOMStorageCachedArea> cached_area =
328 new DOMStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_.get());
330 // SetItem
331 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
332 mock_proxy_->CompleteOnePendingCallback(true); // load completion
333 EXPECT_FALSE(IsIgnoringAllMutations(cached_area.get()));
334 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area.get(), kKey));
335 cached_area->ApplyMutation(base::NullableString16(kKey, false),
336 base::NullableString16());
337 EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
338 mock_proxy_->CompleteOnePendingCallback(true); // set completion
339 EXPECT_FALSE(IsIgnoringKeyMutations(cached_area.get(), kKey));
341 // RemoveItem
342 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
343 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area.get(), kKey));
344 mock_proxy_->CompleteOnePendingCallback(true); // remove completion
345 EXPECT_FALSE(IsIgnoringKeyMutations(cached_area.get(), kKey));
347 // Multiple mutations to the same key.
348 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
349 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
350 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area.get(), kKey));
351 mock_proxy_->CompleteOnePendingCallback(true); // set completion
352 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area.get(), kKey));
353 mock_proxy_->CompleteOnePendingCallback(true); // remove completion
354 EXPECT_FALSE(IsIgnoringKeyMutations(cached_area.get(), kKey));
356 // A failed set item operation should Reset the cache.
357 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
358 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area.get(), kKey));
359 mock_proxy_->CompleteOnePendingCallback(false);
360 EXPECT_FALSE(IsPrimed(cached_area.get()));
363 } // namespace content