Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: webkit/dom_storage/dom_storage_area_unittest.cc

Issue 9718029: DomStorage commit task sequencing. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/dom_storage/dom_storage_area.cc ('k') | webkit/dom_storage/dom_storage_context.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/bind.h" 5 #include "base/bind.h"
6 #include "base/file_util.h" 6 #include "base/file_util.h"
7 #include "base/message_loop.h" 7 #include "base/message_loop.h"
8 #include "base/message_loop_proxy.h" 8 #include "base/message_loop_proxy.h"
9 #include "base/scoped_temp_dir.h" 9 #include "base/scoped_temp_dir.h"
10 #include "base/threading/sequenced_worker_pool.h" 10 #include "base/threading/sequenced_worker_pool.h"
11 #include "base/time.h" 11 #include "base/time.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webkit/dom_storage/dom_storage_area.h" 14 #include "webkit/dom_storage/dom_storage_area.h"
15 #include "webkit/dom_storage/dom_storage_task_runner.h" 15 #include "webkit/dom_storage/dom_storage_task_runner.h"
16 #include "webkit/dom_storage/dom_storage_types.h" 16 #include "webkit/dom_storage/dom_storage_types.h"
17 17
18 namespace dom_storage { 18 namespace dom_storage {
19 19
20 TEST(DomStorageAreaTest, DomStorageAreaBasics) {
21 const GURL kOrigin("http://dom_storage/");
22 const string16 kKey(ASCIIToUTF16("key"));
23 const string16 kValue(ASCIIToUTF16("value"));
24 const string16 kKey2(ASCIIToUTF16("key2"));
25 const string16 kValue2(ASCIIToUTF16("value2"));
26 20
21 class DomStorageAreaTest : public testing::Test {
22 public:
23 DomStorageAreaTest()
24 : kOrigin(GURL("http://dom_storage/")),
25 kKey(ASCIIToUTF16("key")),
26 kValue(ASCIIToUTF16("value")),
27 kKey2(ASCIIToUTF16("key2")),
28 kValue2(ASCIIToUTF16("value2")) {
29 }
30
31 const GURL kOrigin;
32 const string16 kKey;
33 const string16 kValue;
34 const string16 kKey2;
35 const string16 kValue2;
36
37 // Method used in the CommitTasks test case.
38 void InjectedCommitSequencingTask(DomStorageArea* area) {
39 // At this point the OnCommitTimer has run.
40 // Verify that it put a commit in flight.
41 EXPECT_TRUE(area->in_flight_commit_batch_.get());
42 EXPECT_FALSE(area->commit_batch_.get());
43 // Make additional change and verify that a new commit batch
44 // is created for that change.
45 NullableString16 old_value;
46 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value));
47 EXPECT_TRUE(area->commit_batch_.get());
48 EXPECT_TRUE(area->in_flight_commit_batch_.get());
49 }
50
51 // Class used in the CommitChangesAtShutdown test case.
52 class VerifyChangesCommittedDatabase : public DomStorageDatabase {
53 public:
54 VerifyChangesCommittedDatabase() {}
55 virtual ~VerifyChangesCommittedDatabase() {
56 const string16 kKey(ASCIIToUTF16("key"));
57 const string16 kValue(ASCIIToUTF16("value"));
58 ValuesMap values;
59 ReadAllValues(&values);
60 EXPECT_EQ(1u, values.size());
61 EXPECT_EQ(kValue, values[kKey].string());
62 }
63 };
64 };
65
66 TEST_F(DomStorageAreaTest, DomStorageAreaBasics) {
27 scoped_refptr<DomStorageArea> area( 67 scoped_refptr<DomStorageArea> area(
28 new DomStorageArea(1, kOrigin, FilePath(), NULL)); 68 new DomStorageArea(1, kOrigin, FilePath(), NULL));
29 string16 old_value; 69 string16 old_value;
30 NullableString16 old_nullable_value; 70 NullableString16 old_nullable_value;
31 scoped_refptr<DomStorageArea> copy; 71 scoped_refptr<DomStorageArea> copy;
32 72
33 // We don't focus on the underlying DomStorageMap functionality 73 // We don't focus on the underlying DomStorageMap functionality
34 // since that's covered by seperate unit tests. 74 // since that's covered by seperate unit tests.
35 EXPECT_EQ(kOrigin, area->origin()); 75 EXPECT_EQ(kOrigin, area->origin());
36 EXPECT_EQ(1, area->namespace_id()); 76 EXPECT_EQ(1, area->namespace_id());
37 EXPECT_EQ(0u, area->Length()); 77 EXPECT_EQ(0u, area->Length());
38 area->SetItem(kKey, kValue, &old_nullable_value); 78 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value));
39 area->SetItem(kKey2, kValue2, &old_nullable_value); 79 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_nullable_value));
40 80
41 // Verify that a copy shares the same map. 81 // Verify that a copy shares the same map.
42 copy = area->ShallowCopy(2); 82 copy = area->ShallowCopy(2);
43 EXPECT_EQ(kOrigin, copy->origin()); 83 EXPECT_EQ(kOrigin, copy->origin());
44 EXPECT_EQ(2, copy->namespace_id()); 84 EXPECT_EQ(2, copy->namespace_id());
45 EXPECT_EQ(area->Length(), copy->Length()); 85 EXPECT_EQ(area->Length(), copy->Length());
46 EXPECT_EQ(area->GetItem(kKey).string(), copy->GetItem(kKey).string()); 86 EXPECT_EQ(area->GetItem(kKey).string(), copy->GetItem(kKey).string());
47 EXPECT_EQ(area->Key(0).string(), copy->Key(0).string()); 87 EXPECT_EQ(area->Key(0).string(), copy->Key(0).string());
48 EXPECT_EQ(copy->map_.get(), area->map_.get()); 88 EXPECT_EQ(copy->map_.get(), area->map_.get());
49 89
50 // But will deep copy-on-write as needed. 90 // But will deep copy-on-write as needed.
51 EXPECT_TRUE(area->RemoveItem(kKey, &old_value)); 91 EXPECT_TRUE(area->RemoveItem(kKey, &old_value));
52 EXPECT_NE(copy->map_.get(), area->map_.get()); 92 EXPECT_NE(copy->map_.get(), area->map_.get());
53 copy = area->ShallowCopy(2); 93 copy = area->ShallowCopy(2);
54 EXPECT_EQ(copy->map_.get(), area->map_.get()); 94 EXPECT_EQ(copy->map_.get(), area->map_.get());
55 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value)); 95 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value));
56 EXPECT_NE(copy->map_.get(), area->map_.get()); 96 EXPECT_NE(copy->map_.get(), area->map_.get());
57 copy = area->ShallowCopy(2); 97 copy = area->ShallowCopy(2);
58 EXPECT_EQ(copy->map_.get(), area->map_.get()); 98 EXPECT_EQ(copy->map_.get(), area->map_.get());
59 EXPECT_NE(0u, area->Length()); 99 EXPECT_NE(0u, area->Length());
60 EXPECT_TRUE(area->Clear()); 100 EXPECT_TRUE(area->Clear());
61 EXPECT_EQ(0u, area->Length()); 101 EXPECT_EQ(0u, area->Length());
62 EXPECT_NE(copy->map_.get(), area->map_.get()); 102 EXPECT_NE(copy->map_.get(), area->map_.get());
103
104 // Verify that once Shutdown(), behaves that way.
105 area->Shutdown();
106 EXPECT_TRUE(area->is_shutdown_);
107 EXPECT_FALSE(area->map_.get());
108 EXPECT_EQ(0u, area->Length());
109 EXPECT_TRUE(area->Key(0).is_null());
110 EXPECT_TRUE(area->GetItem(kKey).is_null());
111 EXPECT_FALSE(area->SetItem(kKey, kValue, &old_nullable_value));
112 EXPECT_FALSE(area->RemoveItem(kKey, &old_value));
113 EXPECT_FALSE(area->Clear());
63 } 114 }
64 115
65 TEST(DomStorageAreaTest, BackingDatabaseOpened) { 116 TEST_F(DomStorageAreaTest, BackingDatabaseOpened) {
66 const int64 kSessionStorageNamespaceId = kLocalStorageNamespaceId + 1; 117 const int64 kSessionStorageNamespaceId = kLocalStorageNamespaceId + 1;
67 const GURL kOrigin("http://www.google.com");
68
69 const string16 kKey = ASCIIToUTF16("test");
70 const string16 kKey2 = ASCIIToUTF16("test2");
71 const string16 kValue = ASCIIToUTF16("value");
72 ScopedTempDir temp_dir; 118 ScopedTempDir temp_dir;
73 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 119 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
74
75 const FilePath kExpectedOriginFilePath = temp_dir.path().Append( 120 const FilePath kExpectedOriginFilePath = temp_dir.path().Append(
76 DomStorageArea::DatabaseFileNameFromOrigin(kOrigin)); 121 DomStorageArea::DatabaseFileNameFromOrigin(kOrigin));
77 122
78 // No directory, backing should be null. 123 // No directory, backing should be null.
79 { 124 {
80 scoped_refptr<DomStorageArea> area( 125 scoped_refptr<DomStorageArea> area(
81 new DomStorageArea(kLocalStorageNamespaceId, kOrigin, FilePath(), 126 new DomStorageArea(kLocalStorageNamespaceId, kOrigin, FilePath(),
82 NULL)); 127 NULL));
83 EXPECT_EQ(NULL, area->backing_.get()); 128 EXPECT_EQ(NULL, area->backing_.get());
84 EXPECT_TRUE(area->initial_import_done_); 129 EXPECT_TRUE(area->is_initial_import_done_);
85 EXPECT_FALSE(file_util::PathExists(kExpectedOriginFilePath)); 130 EXPECT_FALSE(file_util::PathExists(kExpectedOriginFilePath));
86 } 131 }
87 132
88 // Valid directory and origin but non-local namespace id. Backing should 133 // Valid directory and origin but non-local namespace id. Backing should
89 // be null. 134 // be null.
90 { 135 {
91 scoped_refptr<DomStorageArea> area( 136 scoped_refptr<DomStorageArea> area(
92 new DomStorageArea(kSessionStorageNamespaceId, kOrigin, 137 new DomStorageArea(kSessionStorageNamespaceId, kOrigin,
93 temp_dir.path(), NULL)); 138 temp_dir.path(), NULL));
94 EXPECT_EQ(NULL, area->backing_.get()); 139 EXPECT_EQ(NULL, area->backing_.get());
95 EXPECT_TRUE(area->initial_import_done_); 140 EXPECT_TRUE(area->is_initial_import_done_);
96 141
97 NullableString16 old_value; 142 NullableString16 old_value;
98 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value)); 143 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
99 ASSERT_TRUE(old_value.is_null()); 144 ASSERT_TRUE(old_value.is_null());
100 145
101 // Check that saving a value has still left us without a backing database. 146 // Check that saving a value has still left us without a backing database.
102 EXPECT_EQ(NULL, area->backing_.get()); 147 EXPECT_EQ(NULL, area->backing_.get());
103 EXPECT_FALSE(file_util::PathExists(kExpectedOriginFilePath)); 148 EXPECT_FALSE(file_util::PathExists(kExpectedOriginFilePath));
104 } 149 }
105 150
106 // This should set up a DomStorageArea that is correctly backed to disk. 151 // This should set up a DomStorageArea that is correctly backed to disk.
107 { 152 {
108 scoped_refptr<DomStorageArea> area( 153 scoped_refptr<DomStorageArea> area(
109 new DomStorageArea(kLocalStorageNamespaceId, kOrigin, 154 new DomStorageArea(kLocalStorageNamespaceId, kOrigin,
110 temp_dir.path(), 155 temp_dir.path(),
111 new MockDomStorageTaskRunner(base::MessageLoopProxy::current()))); 156 new MockDomStorageTaskRunner(base::MessageLoopProxy::current())));
112 157
113 EXPECT_TRUE(area->backing_.get()); 158 EXPECT_TRUE(area->backing_.get());
114 EXPECT_FALSE(area->backing_->IsOpen()); 159 EXPECT_FALSE(area->backing_->IsOpen());
115 EXPECT_FALSE(area->initial_import_done_); 160 EXPECT_FALSE(area->is_initial_import_done_);
116 161
117 // Switch out the file-backed db with an in-memory db to speed up the test. 162 // Inject an in-memory db to speed up the test.
118 // We will verify that something is written into the database but not 163 // We will verify that something is written into the database but not
119 // that a file is written to disk - DOMStorageDatabase unit tests cover 164 // that a file is written to disk - DOMStorageDatabase unit tests cover
120 // that. 165 // that.
121 area->backing_.reset(new DomStorageDatabase()); 166 area->backing_.reset(new DomStorageDatabase());
122 167
123 // Need to write something to ensure that the database is created. 168 // Need to write something to ensure that the database is created.
124 NullableString16 old_value; 169 NullableString16 old_value;
125 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value)); 170 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
126 ASSERT_TRUE(old_value.is_null()); 171 ASSERT_TRUE(old_value.is_null());
127 EXPECT_TRUE(area->SetItem(kKey2, kValue, &old_value)); 172 EXPECT_TRUE(area->is_initial_import_done_);
128 ASSERT_TRUE(old_value.is_null()); 173 EXPECT_TRUE(area->commit_batch_.get());
129 EXPECT_TRUE(area->initial_import_done_); 174 EXPECT_FALSE(area->in_flight_commit_batch_.get());
130 EXPECT_TRUE(area->commit_in_flight_);
131 175
132 MessageLoop::current()->RunAllPending(); 176 MessageLoop::current()->RunAllPending();
133 177
134 EXPECT_FALSE(area->commit_in_flight_); 178 EXPECT_FALSE(area->commit_batch_.get());
179 EXPECT_FALSE(area->in_flight_commit_batch_.get());
135 EXPECT_TRUE(area->backing_->IsOpen()); 180 EXPECT_TRUE(area->backing_->IsOpen());
136 EXPECT_EQ(2u, area->Length()); 181 EXPECT_EQ(1u, area->Length());
137 EXPECT_EQ(kValue, area->GetItem(kKey).string()); 182 EXPECT_EQ(kValue, area->GetItem(kKey).string());
138 183
139 // Verify the content made it to the in memory database. 184 // Verify the content made it to the in memory database.
140 ValuesMap values; 185 ValuesMap values;
141 area->backing_->ReadAllValues(&values); 186 area->backing_->ReadAllValues(&values);
142 EXPECT_EQ(2u, values.size()); 187 EXPECT_EQ(1u, values.size());
143 EXPECT_EQ(kValue, values[kKey].string()); 188 EXPECT_EQ(kValue, values[kKey].string());
144 } 189 }
145 } 190 }
146 191
147 TEST(DomStorageAreaTest, TestDatabaseFilePath) { 192 TEST_F(DomStorageAreaTest, CommitTasks) {
193 ScopedTempDir temp_dir;
194 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
195
196 scoped_refptr<DomStorageArea> area(
197 new DomStorageArea(kLocalStorageNamespaceId, kOrigin,
198 temp_dir.path(),
199 new MockDomStorageTaskRunner(base::MessageLoopProxy::current())));
200 // Inject an in-memory db to speed up the test.
201 area->backing_.reset(new DomStorageDatabase());
202
203 // Unrelated to commits, but while we're here, see that querying Length()
204 // causes the backing database to be opened and presumably read from.
205 EXPECT_FALSE(area->is_initial_import_done_);
206 EXPECT_EQ(0u, area->Length());
207 EXPECT_TRUE(area->is_initial_import_done_);
208
209 ValuesMap values;
210 NullableString16 old_value;
211
212 // See that changes are batched up.
213 EXPECT_FALSE(area->commit_batch_.get());
214 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
215 EXPECT_TRUE(area->commit_batch_.get());
216 EXPECT_FALSE(area->commit_batch_->clear_all_first);
217 EXPECT_EQ(1u, area->commit_batch_->changed_values.size());
218 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value));
219 EXPECT_TRUE(area->commit_batch_.get());
220 EXPECT_FALSE(area->commit_batch_->clear_all_first);
221 EXPECT_EQ(2u, area->commit_batch_->changed_values.size());
222 MessageLoop::current()->RunAllPending();
223 EXPECT_FALSE(area->commit_batch_.get());
224 EXPECT_FALSE(area->in_flight_commit_batch_.get());
225 // Verify the changes made it to the database.
226 values.clear();
227 area->backing_->ReadAllValues(&values);
228 EXPECT_EQ(2u, values.size());
229 EXPECT_EQ(kValue, values[kKey].string());
230 EXPECT_EQ(kValue2, values[kKey2].string());
231
232 // See that clear is handled properly.
233 EXPECT_TRUE(area->Clear());
234 EXPECT_TRUE(area->commit_batch_.get());
235 EXPECT_TRUE(area->commit_batch_->clear_all_first);
236 EXPECT_TRUE(area->commit_batch_->changed_values.empty());
237 MessageLoop::current()->RunAllPending();
238 EXPECT_FALSE(area->commit_batch_.get());
239 EXPECT_FALSE(area->in_flight_commit_batch_.get());
240 // Verify the changes made it to the database.
241 values.clear();
242 area->backing_->ReadAllValues(&values);
243 EXPECT_TRUE(values.empty());
244
245 // See that if changes accrue while a commit is "in flight"
246 // those will also get committed.
247 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
248 EXPECT_TRUE(area->commit_batch_.get());
249 // At this point the OnCommitTimer task has been posted. We inject
250 // another task in the queue that will execute after the timer task,
251 // but before the CommitChanges task. From within our injected task,
252 // we'll make an additional SetItem() call.
253 MessageLoop::current()->PostTask(
254 FROM_HERE,
255 base::Bind(&DomStorageAreaTest::InjectedCommitSequencingTask,
256 base::Unretained(this), area));
257 MessageLoop::current()->RunAllPending();
258 EXPECT_TRUE(area->HasOneRef());
259 EXPECT_FALSE(area->commit_batch_.get());
260 EXPECT_FALSE(area->in_flight_commit_batch_.get());
261 // Verify the changes made it to the database.
262 values.clear();
263 area->backing_->ReadAllValues(&values);
264 EXPECT_EQ(2u, values.size());
265 EXPECT_EQ(kValue, values[kKey].string());
266 EXPECT_EQ(kValue2, values[kKey2].string());
267 }
268
269 TEST_F(DomStorageAreaTest, CommitChangesAtShutdown) {
270 ScopedTempDir temp_dir;
271 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
272 scoped_refptr<DomStorageArea> area(
273 new DomStorageArea(kLocalStorageNamespaceId, kOrigin,
274 temp_dir.path(),
275 new MockDomStorageTaskRunner(base::MessageLoopProxy::current())));
276
277 // Inject an in-memory db to speed up the test and also to verify
278 // the final changes are commited in it's dtor.
279 area->backing_.reset(new VerifyChangesCommittedDatabase());
280
281 ValuesMap values;
282 NullableString16 old_value;
283 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
284 EXPECT_TRUE(area->commit_batch_.get());
285 area->backing_->ReadAllValues(&values);
286 EXPECT_TRUE(values.empty()); // not committed yet
287 area->Shutdown();
288 MessageLoop::current()->RunAllPending();
289 EXPECT_TRUE(area->HasOneRef());
290 EXPECT_FALSE(area->backing_.get());
291 // The VerifyChangesCommittedDatabase destructor verifies values
292 // were committed.
293 }
294
295 TEST_F(DomStorageAreaTest, TestDatabaseFilePath) {
148 EXPECT_EQ(FilePath().AppendASCII("file_path_to_0.localstorage"), 296 EXPECT_EQ(FilePath().AppendASCII("file_path_to_0.localstorage"),
149 DomStorageArea::DatabaseFileNameFromOrigin( 297 DomStorageArea::DatabaseFileNameFromOrigin(
150 GURL("file://path_to/index.html"))); 298 GURL("file://path_to/index.html")));
151 299
152 EXPECT_EQ(FilePath().AppendASCII("https_www.google.com_0.localstorage"), 300 EXPECT_EQ(FilePath().AppendASCII("https_www.google.com_0.localstorage"),
153 DomStorageArea::DatabaseFileNameFromOrigin( 301 DomStorageArea::DatabaseFileNameFromOrigin(
154 GURL("https://www.google.com/"))); 302 GURL("https://www.google.com/")));
155 303
156 EXPECT_EQ(FilePath().AppendASCII("https_www.google.com_8080.localstorage"), 304 EXPECT_EQ(FilePath().AppendASCII("https_www.google.com_8080.localstorage"),
157 DomStorageArea::DatabaseFileNameFromOrigin( 305 DomStorageArea::DatabaseFileNameFromOrigin(
158 GURL("https://www.google.com:8080"))); 306 GURL("https://www.google.com:8080")));
159 } 307 }
160 308
161 } // namespace dom_storage 309 } // namespace dom_storage
OLDNEW
« no previous file with comments | « webkit/dom_storage/dom_storage_area.cc ('k') | webkit/dom_storage/dom_storage_context.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698