Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / webkit / dom_storage / dom_storage_cached_area_unittest.cc
blobd55d73f7168e61fad7a1214ce5ffbd161057377b
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 <list>
7 #include "base/bind.h"
8 #include "base/utf_string_conversions.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "webkit/dom_storage/dom_storage_cached_area.h"
11 #include "webkit/dom_storage/dom_storage_proxy.h"
13 namespace dom_storage {
15 namespace {
16 // A mock implementation of the DomStorageProxy interface.
17 class MockProxy : public DomStorageProxy {
18 public:
19 MockProxy() {
20 ResetObservations();
23 // DomStorageProxy interface for use by DomStorageCachedArea.
25 virtual void LoadArea(int connection_id, ValuesMap* values,
26 const CompletionCallback& callback) OVERRIDE {
27 pending_callbacks_.push_back(callback);
28 observed_load_area_ = true;
29 observed_connection_id_ = connection_id;
30 *values = load_area_return_values_;
33 virtual void SetItem(int connection_id, const base::string16& key,
34 const base::string16& value, const GURL& page_url,
35 const CompletionCallback& callback) OVERRIDE {
36 pending_callbacks_.push_back(callback);
37 observed_set_item_ = true;
38 observed_connection_id_ = connection_id;
39 observed_key_ = key;
40 observed_value_ = value;
41 observed_page_url_ = page_url;
44 virtual void RemoveItem(int connection_id, const base::string16& key,
45 const GURL& page_url,
46 const CompletionCallback& callback) OVERRIDE {
47 pending_callbacks_.push_back(callback);
48 observed_remove_item_ = true;
49 observed_connection_id_ = connection_id;
50 observed_key_ = key;
51 observed_page_url_ = page_url;
54 virtual void ClearArea(int connection_id,
55 const GURL& page_url,
56 const CompletionCallback& callback) OVERRIDE {
57 pending_callbacks_.push_back(callback);
58 observed_clear_area_ = true;
59 observed_connection_id_ = connection_id;
60 observed_page_url_ = page_url;
63 // Methods and members for use by test fixtures.
65 void ResetObservations() {
66 observed_load_area_ = false;
67 observed_set_item_ = false;
68 observed_remove_item_ = false;
69 observed_clear_area_ = false;
70 observed_connection_id_ = 0;
71 observed_key_.clear();
72 observed_value_.clear();
73 observed_page_url_ = GURL();
76 void CompleteAllPendingCallbacks() {
77 while (!pending_callbacks_.empty())
78 CompleteOnePendingCallback(true);
81 void CompleteOnePendingCallback(bool success) {
82 ASSERT_TRUE(!pending_callbacks_.empty());
83 pending_callbacks_.front().Run(success);
84 pending_callbacks_.pop_front();
87 typedef std::list<CompletionCallback> CallbackList;
89 ValuesMap load_area_return_values_;
90 CallbackList pending_callbacks_;
91 bool observed_load_area_;
92 bool observed_set_item_;
93 bool observed_remove_item_;
94 bool observed_clear_area_;
95 int observed_connection_id_;
96 base::string16 observed_key_;
97 base::string16 observed_value_;
98 GURL observed_page_url_;
100 private:
101 virtual ~MockProxy() {}
103 } // namespace
105 class DomStorageCachedAreaTest : public testing::Test {
106 public:
107 DomStorageCachedAreaTest()
108 : kNamespaceId(10),
109 kOrigin("http://dom_storage/"),
110 kKey(ASCIIToUTF16("key")),
111 kValue(ASCIIToUTF16("value")),
112 kPageUrl("http://dom_storage/page") {
115 const int64 kNamespaceId;
116 const GURL kOrigin;
117 const base::string16 kKey;
118 const base::string16 kValue;
119 const GURL kPageUrl;
121 virtual void SetUp() {
122 mock_proxy_ = new MockProxy();
125 bool IsPrimed(DomStorageCachedArea* cached_area) {
126 return cached_area->map_.get();
129 bool IsIgnoringAllMutations(DomStorageCachedArea* cached_area) {
130 return cached_area->ignore_all_mutations_;
133 bool IsIgnoringKeyMutations(DomStorageCachedArea* cached_area,
134 const base::string16& key) {
135 return cached_area->should_ignore_key_mutation(key);
138 void ResetAll(DomStorageCachedArea* cached_area) {
139 cached_area->Reset();
140 mock_proxy_->ResetObservations();
141 mock_proxy_->pending_callbacks_.clear();
144 void ResetCacheOnly(DomStorageCachedArea* cached_area) {
145 cached_area->Reset();
148 protected:
149 scoped_refptr<MockProxy> mock_proxy_;
152 TEST_F(DomStorageCachedAreaTest, Basics) {
153 EXPECT_TRUE(mock_proxy_->HasOneRef());
154 scoped_refptr<DomStorageCachedArea> cached_area =
155 new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
156 EXPECT_EQ(kNamespaceId, cached_area->namespace_id());
157 EXPECT_EQ(kOrigin, cached_area->origin());
158 EXPECT_FALSE(mock_proxy_->HasOneRef());
159 cached_area->ApplyMutation(NullableString16(kKey, false),
160 NullableString16(kValue, false));
161 EXPECT_FALSE(IsPrimed(cached_area));
163 ResetAll(cached_area);
164 EXPECT_EQ(kNamespaceId, cached_area->namespace_id());
165 EXPECT_EQ(kOrigin, cached_area->origin());
167 const int kConnectionId = 1;
168 EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
169 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
170 EXPECT_EQ(1u, cached_area->GetLength(kConnectionId));
171 EXPECT_EQ(kKey, cached_area->GetKey(kConnectionId, 0).string());
172 EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
173 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
174 EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
177 TEST_F(DomStorageCachedAreaTest, Getters) {
178 const int kConnectionId = 7;
179 scoped_refptr<DomStorageCachedArea> cached_area =
180 new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
182 // GetLength, we expect to see one call to load in the proxy.
183 EXPECT_FALSE(IsPrimed(cached_area));
184 EXPECT_EQ(0u, cached_area->GetLength(kConnectionId));
185 EXPECT_TRUE(IsPrimed(cached_area));
186 EXPECT_TRUE(mock_proxy_->observed_load_area_);
187 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
188 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
189 EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
190 mock_proxy_->CompleteAllPendingCallbacks();
191 EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
193 // GetKey, expect the one call to load.
194 ResetAll(cached_area);
195 EXPECT_FALSE(IsPrimed(cached_area));
196 EXPECT_TRUE(cached_area->GetKey(kConnectionId, 2).is_null());
197 EXPECT_TRUE(IsPrimed(cached_area));
198 EXPECT_TRUE(mock_proxy_->observed_load_area_);
199 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
200 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
202 // GetItem, ditto.
203 ResetAll(cached_area);
204 EXPECT_FALSE(IsPrimed(cached_area));
205 EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
206 EXPECT_TRUE(IsPrimed(cached_area));
207 EXPECT_TRUE(mock_proxy_->observed_load_area_);
208 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
209 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
212 TEST_F(DomStorageCachedAreaTest, Setters) {
213 const int kConnectionId = 7;
214 scoped_refptr<DomStorageCachedArea> cached_area =
215 new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
217 // SetItem, we expect a call to load followed by a call to set item
218 // in the proxy.
219 EXPECT_FALSE(IsPrimed(cached_area));
220 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
221 EXPECT_TRUE(IsPrimed(cached_area));
222 EXPECT_TRUE(mock_proxy_->observed_load_area_);
223 EXPECT_TRUE(mock_proxy_->observed_set_item_);
224 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
225 EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
226 EXPECT_EQ(kKey, mock_proxy_->observed_key_);
227 EXPECT_EQ(kValue, mock_proxy_->observed_value_);
228 EXPECT_EQ(2u, mock_proxy_->pending_callbacks_.size());
230 // Clear, we expect a just the one call to clear in the proxy since
231 // there's no need to load the data prior to deleting it.
232 ResetAll(cached_area);
233 EXPECT_FALSE(IsPrimed(cached_area));
234 cached_area->Clear(kConnectionId, kPageUrl);
235 EXPECT_TRUE(IsPrimed(cached_area));
236 EXPECT_TRUE(mock_proxy_->observed_clear_area_);
237 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
238 EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
239 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
241 // RemoveItem with nothing to remove, expect just one call to load.
242 ResetAll(cached_area);
243 EXPECT_FALSE(IsPrimed(cached_area));
244 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
245 EXPECT_TRUE(IsPrimed(cached_area));
246 EXPECT_TRUE(mock_proxy_->observed_load_area_);
247 EXPECT_FALSE(mock_proxy_->observed_remove_item_);
248 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
249 EXPECT_EQ(1u, mock_proxy_->pending_callbacks_.size());
251 // RemoveItem with something to remove, expect a call to load followed
252 // by a call to remove.
253 ResetAll(cached_area);
254 mock_proxy_->load_area_return_values_[kKey] = NullableString16(kValue, false);
255 EXPECT_FALSE(IsPrimed(cached_area));
256 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
257 EXPECT_TRUE(IsPrimed(cached_area));
258 EXPECT_TRUE(mock_proxy_->observed_load_area_);
259 EXPECT_TRUE(mock_proxy_->observed_remove_item_);
260 EXPECT_EQ(kConnectionId, mock_proxy_->observed_connection_id_);
261 EXPECT_EQ(kPageUrl, mock_proxy_->observed_page_url_);
262 EXPECT_EQ(kKey, mock_proxy_->observed_key_);
263 EXPECT_EQ(2u, mock_proxy_->pending_callbacks_.size());
266 TEST_F(DomStorageCachedAreaTest, MutationsAreIgnoredUntilLoadCompletion) {
267 const int kConnectionId = 7;
268 scoped_refptr<DomStorageCachedArea> cached_area =
269 new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
270 EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
271 EXPECT_TRUE(IsPrimed(cached_area));
272 EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
274 // Before load completion, the mutation should be ignored.
275 cached_area->ApplyMutation(NullableString16(kKey, false),
276 NullableString16(kValue, false));
277 EXPECT_TRUE(cached_area->GetItem(kConnectionId, kKey).is_null());
279 // Call the load completion callback.
280 mock_proxy_->CompleteOnePendingCallback(true);
281 EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
283 // Verify that mutations are now applied.
284 cached_area->ApplyMutation(NullableString16(kKey, false),
285 NullableString16(kValue, false));
286 EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
289 TEST_F(DomStorageCachedAreaTest, MutationsAreIgnoredUntilClearCompletion) {
290 const int kConnectionId = 4;
291 scoped_refptr<DomStorageCachedArea> cached_area =
292 new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
293 cached_area->Clear(kConnectionId, kPageUrl);
294 EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
295 mock_proxy_->CompleteOnePendingCallback(true);
296 EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
298 // Verify that calling Clear twice works as expected, the first
299 // completion callback should have been cancelled.
300 ResetCacheOnly(cached_area);
301 cached_area->Clear(kConnectionId, kPageUrl);
302 EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
303 cached_area->Clear(kConnectionId, kPageUrl);
304 EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
305 mock_proxy_->CompleteOnePendingCallback(true);
306 EXPECT_TRUE(IsIgnoringAllMutations(cached_area));
307 mock_proxy_->CompleteOnePendingCallback(true);
308 EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
311 TEST_F(DomStorageCachedAreaTest, KeyMutationsAreIgnoredUntilCompletion) {
312 const int kConnectionId = 8;
313 scoped_refptr<DomStorageCachedArea> cached_area =
314 new DomStorageCachedArea(kNamespaceId, kOrigin, mock_proxy_);
316 // SetItem
317 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
318 mock_proxy_->CompleteOnePendingCallback(true); // load completion
319 EXPECT_FALSE(IsIgnoringAllMutations(cached_area));
320 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
321 cached_area->ApplyMutation(NullableString16(kKey, false),
322 NullableString16(true));
323 EXPECT_EQ(kValue, cached_area->GetItem(kConnectionId, kKey).string());
324 mock_proxy_->CompleteOnePendingCallback(true); // set completion
325 EXPECT_FALSE(IsIgnoringKeyMutations(cached_area, kKey));
327 // RemoveItem
328 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
329 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
330 mock_proxy_->CompleteOnePendingCallback(true); // remove completion
331 EXPECT_FALSE(IsIgnoringKeyMutations(cached_area, kKey));
333 // Multiple mutations to the same key.
334 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
335 cached_area->RemoveItem(kConnectionId, kKey, kPageUrl);
336 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
337 mock_proxy_->CompleteOnePendingCallback(true); // set completion
338 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
339 mock_proxy_->CompleteOnePendingCallback(true); // remove completion
340 EXPECT_FALSE(IsIgnoringKeyMutations(cached_area, kKey));
342 // A failed set item operation should Reset the cache.
343 EXPECT_TRUE(cached_area->SetItem(kConnectionId, kKey, kValue, kPageUrl));
344 EXPECT_TRUE(IsIgnoringKeyMutations(cached_area, kKey));
345 mock_proxy_->CompleteOnePendingCallback(false);
346 EXPECT_FALSE(IsPrimed(cached_area));
349 } // namespace dom_storage