blob: 697f6250b1d41465b418ed7d948f08c67f1d7097 [file] [log] [blame]
Ben Murdochbb1529c2013-08-08 10:24:53 +01001// Copyright 2013 The Chromium Authors. All rights reserved.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/bind.h"
6#include "base/file_util.h"
7#include "base/files/scoped_temp_dir.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +01008#include "base/message_loop/message_loop.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01009#include "base/message_loop/message_loop_proxy.h"
10#include "base/strings/utf_string_conversions.h"
11#include "base/threading/sequenced_worker_pool.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010012#include "base/time/time.h"
Ben Murdochbb1529c2013-08-08 10:24:53 +010013#include "content/browser/dom_storage/dom_storage_area.h"
14#include "content/browser/dom_storage/dom_storage_database.h"
15#include "content/browser/dom_storage/dom_storage_database_adapter.h"
16#include "content/browser/dom_storage/dom_storage_task_runner.h"
17#include "content/browser/dom_storage/local_storage_database_adapter.h"
18#include "content/common/dom_storage/dom_storage_types.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010019#include "testing/gtest/include/gtest/gtest.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010020
Ben Murdochbb1529c2013-08-08 10:24:53 +010021namespace content {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010022
23
Ben Murdochbb1529c2013-08-08 10:24:53 +010024class DOMStorageAreaTest : public testing::Test {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010025 public:
Ben Murdochbb1529c2013-08-08 10:24:53 +010026 DOMStorageAreaTest()
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010027 : kOrigin(GURL("http://dom_storage/")),
28 kKey(ASCIIToUTF16("key")),
29 kValue(ASCIIToUTF16("value")),
30 kKey2(ASCIIToUTF16("key2")),
31 kValue2(ASCIIToUTF16("value2")) {
32 }
33
34 const GURL kOrigin;
35 const base::string16 kKey;
36 const base::string16 kValue;
37 const base::string16 kKey2;
38 const base::string16 kValue2;
39
40 // Method used in the CommitTasks test case.
Ben Murdochbb1529c2013-08-08 10:24:53 +010041 void InjectedCommitSequencingTask(DOMStorageArea* area) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010042 // At this point the OnCommitTimer has run.
43 // Verify that it put a commit in flight.
44 EXPECT_EQ(1, area->commit_batches_in_flight_);
45 EXPECT_FALSE(area->commit_batch_.get());
46 EXPECT_TRUE(area->HasUncommittedChanges());
47 // Make additional change and verify that a new commit batch
48 // is created for that change.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010049 base::NullableString16 old_value;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010050 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value));
51 EXPECT_TRUE(area->commit_batch_.get());
52 EXPECT_EQ(1, area->commit_batches_in_flight_);
53 EXPECT_TRUE(area->HasUncommittedChanges());
54 }
55
56 // Class used in the CommitChangesAtShutdown test case.
Ben Murdochbb1529c2013-08-08 10:24:53 +010057 class VerifyChangesCommittedDatabase : public DOMStorageDatabase {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010058 public:
59 VerifyChangesCommittedDatabase() {}
60 virtual ~VerifyChangesCommittedDatabase() {
61 const base::string16 kKey(ASCIIToUTF16("key"));
62 const base::string16 kValue(ASCIIToUTF16("value"));
Ben Murdochbb1529c2013-08-08 10:24:53 +010063 DOMStorageValuesMap values;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010064 ReadAllValues(&values);
65 EXPECT_EQ(1u, values.size());
66 EXPECT_EQ(kValue, values[kKey].string());
67 }
68 };
69
70 private:
71 base::MessageLoop message_loop_;
72};
73
Ben Murdochbb1529c2013-08-08 10:24:53 +010074TEST_F(DOMStorageAreaTest, DOMStorageAreaBasics) {
75 scoped_refptr<DOMStorageArea> area(
76 new DOMStorageArea(1, std::string(), kOrigin, NULL, NULL));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010077 base::string16 old_value;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010078 base::NullableString16 old_nullable_value;
Ben Murdochbb1529c2013-08-08 10:24:53 +010079 scoped_refptr<DOMStorageArea> copy;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010080
Ben Murdochbb1529c2013-08-08 10:24:53 +010081 // We don't focus on the underlying DOMStorageMap functionality
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010082 // since that's covered by seperate unit tests.
83 EXPECT_EQ(kOrigin, area->origin());
84 EXPECT_EQ(1, area->namespace_id());
85 EXPECT_EQ(0u, area->Length());
86 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value));
87 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_nullable_value));
88 EXPECT_FALSE(area->HasUncommittedChanges());
89
90 // Verify that a copy shares the same map.
91 copy = area->ShallowCopy(2, std::string());
92 EXPECT_EQ(kOrigin, copy->origin());
93 EXPECT_EQ(2, copy->namespace_id());
94 EXPECT_EQ(area->Length(), copy->Length());
95 EXPECT_EQ(area->GetItem(kKey).string(), copy->GetItem(kKey).string());
96 EXPECT_EQ(area->Key(0).string(), copy->Key(0).string());
97 EXPECT_EQ(copy->map_.get(), area->map_.get());
98
99 // But will deep copy-on-write as needed.
100 EXPECT_TRUE(area->RemoveItem(kKey, &old_value));
101 EXPECT_NE(copy->map_.get(), area->map_.get());
102 copy = area->ShallowCopy(2, std::string());
103 EXPECT_EQ(copy->map_.get(), area->map_.get());
104 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value));
105 EXPECT_NE(copy->map_.get(), area->map_.get());
106 copy = area->ShallowCopy(2, std::string());
107 EXPECT_EQ(copy->map_.get(), area->map_.get());
108 EXPECT_NE(0u, area->Length());
109 EXPECT_TRUE(area->Clear());
110 EXPECT_EQ(0u, area->Length());
111 EXPECT_NE(copy->map_.get(), area->map_.get());
112
113 // Verify that once Shutdown(), behaves that way.
114 area->Shutdown();
115 EXPECT_TRUE(area->is_shutdown_);
116 EXPECT_FALSE(area->map_.get());
117 EXPECT_EQ(0u, area->Length());
118 EXPECT_TRUE(area->Key(0).is_null());
119 EXPECT_TRUE(area->GetItem(kKey).is_null());
120 EXPECT_FALSE(area->SetItem(kKey, kValue, &old_nullable_value));
121 EXPECT_FALSE(area->RemoveItem(kKey, &old_value));
122 EXPECT_FALSE(area->Clear());
123}
124
Ben Murdochbb1529c2013-08-08 10:24:53 +0100125TEST_F(DOMStorageAreaTest, BackingDatabaseOpened) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100126 const int64 kSessionStorageNamespaceId = kLocalStorageNamespaceId + 1;
127 base::ScopedTempDir temp_dir;
128 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
129 const base::FilePath kExpectedOriginFilePath = temp_dir.path().Append(
Ben Murdochbb1529c2013-08-08 10:24:53 +0100130 DOMStorageArea::DatabaseFileNameFromOrigin(kOrigin));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100131
132 // No directory, backing should be null.
133 {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100134 scoped_refptr<DOMStorageArea> area(
135 new DOMStorageArea(kOrigin, base::FilePath(), NULL));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100136 EXPECT_EQ(NULL, area->backing_.get());
137 EXPECT_TRUE(area->is_initial_import_done_);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100138 EXPECT_FALSE(base::PathExists(kExpectedOriginFilePath));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100139 }
140
141 // Valid directory and origin but no session storage backing. Backing should
142 // be null.
143 {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100144 scoped_refptr<DOMStorageArea> area(
145 new DOMStorageArea(kSessionStorageNamespaceId, std::string(), kOrigin,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100146 NULL, NULL));
147 EXPECT_EQ(NULL, area->backing_.get());
148 EXPECT_TRUE(area->is_initial_import_done_);
149
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100150 base::NullableString16 old_value;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100151 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
152 ASSERT_TRUE(old_value.is_null());
153
154 // Check that saving a value has still left us without a backing database.
155 EXPECT_EQ(NULL, area->backing_.get());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100156 EXPECT_FALSE(base::PathExists(kExpectedOriginFilePath));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100157 }
158
Ben Murdochbb1529c2013-08-08 10:24:53 +0100159 // This should set up a DOMStorageArea that is correctly backed to disk.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100160 {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100161 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100162 kOrigin,
163 temp_dir.path(),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100164 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100165
166 EXPECT_TRUE(area->backing_.get());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100167 DOMStorageDatabase* database = static_cast<LocalStorageDatabaseAdapter*>(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100168 area->backing_.get())->db_.get();
169 EXPECT_FALSE(database->IsOpen());
170 EXPECT_FALSE(area->is_initial_import_done_);
171
172 // Inject an in-memory db to speed up the test.
173 // We will verify that something is written into the database but not
174 // that a file is written to disk - DOMStorageDatabase unit tests cover
175 // that.
176 area->backing_.reset(new LocalStorageDatabaseAdapter());
177
178 // Need to write something to ensure that the database is created.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100179 base::NullableString16 old_value;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100180 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
181 ASSERT_TRUE(old_value.is_null());
182 EXPECT_TRUE(area->is_initial_import_done_);
183 EXPECT_TRUE(area->commit_batch_.get());
184 EXPECT_EQ(0, area->commit_batches_in_flight_);
185
186 base::MessageLoop::current()->RunUntilIdle();
187
188 EXPECT_FALSE(area->commit_batch_.get());
189 EXPECT_EQ(0, area->commit_batches_in_flight_);
190 database = static_cast<LocalStorageDatabaseAdapter*>(
191 area->backing_.get())->db_.get();
192 EXPECT_TRUE(database->IsOpen());
193 EXPECT_EQ(1u, area->Length());
194 EXPECT_EQ(kValue, area->GetItem(kKey).string());
195
196 // Verify the content made it to the in memory database.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100197 DOMStorageValuesMap values;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100198 area->backing_->ReadAllValues(&values);
199 EXPECT_EQ(1u, values.size());
200 EXPECT_EQ(kValue, values[kKey].string());
201 }
202}
203
Ben Murdochbb1529c2013-08-08 10:24:53 +0100204TEST_F(DOMStorageAreaTest, CommitTasks) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100205 base::ScopedTempDir temp_dir;
206 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
207
Ben Murdochbb1529c2013-08-08 10:24:53 +0100208 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100209 kOrigin,
210 temp_dir.path(),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100211 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100212 // Inject an in-memory db to speed up the test.
213 area->backing_.reset(new LocalStorageDatabaseAdapter());
214
215 // Unrelated to commits, but while we're here, see that querying Length()
216 // causes the backing database to be opened and presumably read from.
217 EXPECT_FALSE(area->is_initial_import_done_);
218 EXPECT_EQ(0u, area->Length());
219 EXPECT_TRUE(area->is_initial_import_done_);
220
Ben Murdochbb1529c2013-08-08 10:24:53 +0100221 DOMStorageValuesMap values;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100222 base::NullableString16 old_value;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100223
224 // See that changes are batched up.
225 EXPECT_FALSE(area->commit_batch_.get());
226 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
227 EXPECT_TRUE(area->HasUncommittedChanges());
228 EXPECT_TRUE(area->commit_batch_.get());
229 EXPECT_FALSE(area->commit_batch_->clear_all_first);
230 EXPECT_EQ(1u, area->commit_batch_->changed_values.size());
231 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value));
232 EXPECT_TRUE(area->commit_batch_.get());
233 EXPECT_FALSE(area->commit_batch_->clear_all_first);
234 EXPECT_EQ(2u, area->commit_batch_->changed_values.size());
235 base::MessageLoop::current()->RunUntilIdle();
236 EXPECT_FALSE(area->HasUncommittedChanges());
237 EXPECT_FALSE(area->commit_batch_.get());
238 EXPECT_EQ(0, area->commit_batches_in_flight_);
239 // Verify the changes made it to the database.
240 values.clear();
241 area->backing_->ReadAllValues(&values);
242 EXPECT_EQ(2u, values.size());
243 EXPECT_EQ(kValue, values[kKey].string());
244 EXPECT_EQ(kValue2, values[kKey2].string());
245
246 // See that clear is handled properly.
247 EXPECT_TRUE(area->Clear());
248 EXPECT_TRUE(area->commit_batch_.get());
249 EXPECT_TRUE(area->commit_batch_->clear_all_first);
250 EXPECT_TRUE(area->commit_batch_->changed_values.empty());
251 base::MessageLoop::current()->RunUntilIdle();
252 EXPECT_FALSE(area->commit_batch_.get());
253 EXPECT_EQ(0, area->commit_batches_in_flight_);
254 // Verify the changes made it to the database.
255 values.clear();
256 area->backing_->ReadAllValues(&values);
257 EXPECT_TRUE(values.empty());
258
259 // See that if changes accrue while a commit is "in flight"
260 // those will also get committed.
261 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
262 EXPECT_TRUE(area->HasUncommittedChanges());
263 // At this point the OnCommitTimer task has been posted. We inject
264 // another task in the queue that will execute after the timer task,
265 // but before the CommitChanges task. From within our injected task,
266 // we'll make an additional SetItem() call.
267 base::MessageLoop::current()->PostTask(
268 FROM_HERE,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100269 base::Bind(&DOMStorageAreaTest::InjectedCommitSequencingTask,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100270 base::Unretained(this),
271 area));
272 base::MessageLoop::current()->RunUntilIdle();
273 EXPECT_TRUE(area->HasOneRef());
274 EXPECT_FALSE(area->HasUncommittedChanges());
275 // Verify the changes made it to the database.
276 values.clear();
277 area->backing_->ReadAllValues(&values);
278 EXPECT_EQ(2u, values.size());
279 EXPECT_EQ(kValue, values[kKey].string());
280 EXPECT_EQ(kValue2, values[kKey2].string());
281}
282
Ben Murdochbb1529c2013-08-08 10:24:53 +0100283TEST_F(DOMStorageAreaTest, CommitChangesAtShutdown) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100284 base::ScopedTempDir temp_dir;
285 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100286 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100287 kOrigin,
288 temp_dir.path(),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100289 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100290
291 // Inject an in-memory db to speed up the test and also to verify
292 // the final changes are commited in it's dtor.
293 static_cast<LocalStorageDatabaseAdapter*>(area->backing_.get())->db_.reset(
294 new VerifyChangesCommittedDatabase());
295
Ben Murdochbb1529c2013-08-08 10:24:53 +0100296 DOMStorageValuesMap values;
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100297 base::NullableString16 old_value;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100298 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
299 EXPECT_TRUE(area->HasUncommittedChanges());
300 area->backing_->ReadAllValues(&values);
301 EXPECT_TRUE(values.empty()); // not committed yet
302 area->Shutdown();
303 base::MessageLoop::current()->RunUntilIdle();
304 EXPECT_TRUE(area->HasOneRef());
305 EXPECT_FALSE(area->backing_.get());
306 // The VerifyChangesCommittedDatabase destructor verifies values
307 // were committed.
308}
309
Ben Murdochbb1529c2013-08-08 10:24:53 +0100310TEST_F(DOMStorageAreaTest, DeleteOrigin) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100311 base::ScopedTempDir temp_dir;
312 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100313 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100314 kOrigin,
315 temp_dir.path(),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100316 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100317
318 // This test puts files on disk.
319 base::FilePath db_file_path = static_cast<LocalStorageDatabaseAdapter*>(
320 area->backing_.get())->db_->file_path();
321 base::FilePath db_journal_file_path =
Ben Murdochbb1529c2013-08-08 10:24:53 +0100322 DOMStorageDatabase::GetJournalFilePath(db_file_path);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100323
324 // Nothing bad should happen when invoked w/o any files on disk.
325 area->DeleteOrigin();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100326 EXPECT_FALSE(base::PathExists(db_file_path));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100327
328 // Commit something in the database and then delete.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100329 base::NullableString16 old_value;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100330 area->SetItem(kKey, kValue, &old_value);
331 base::MessageLoop::current()->RunUntilIdle();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100332 EXPECT_TRUE(base::PathExists(db_file_path));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100333 area->DeleteOrigin();
334 EXPECT_EQ(0u, area->Length());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100335 EXPECT_FALSE(base::PathExists(db_file_path));
336 EXPECT_FALSE(base::PathExists(db_journal_file_path));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100337
338 // Put some uncommitted changes to a non-existing database in
339 // and then delete. No file ever gets created in this case.
340 area->SetItem(kKey, kValue, &old_value);
341 EXPECT_TRUE(area->HasUncommittedChanges());
342 EXPECT_EQ(1u, area->Length());
343 area->DeleteOrigin();
344 EXPECT_TRUE(area->HasUncommittedChanges());
345 EXPECT_EQ(0u, area->Length());
346 base::MessageLoop::current()->RunUntilIdle();
347 EXPECT_FALSE(area->HasUncommittedChanges());
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100348 EXPECT_FALSE(base::PathExists(db_file_path));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100349
350 // Put some uncommitted changes to a an existing database in
351 // and then delete.
352 area->SetItem(kKey, kValue, &old_value);
353 base::MessageLoop::current()->RunUntilIdle();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100354 EXPECT_TRUE(base::PathExists(db_file_path));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100355 area->SetItem(kKey2, kValue2, &old_value);
356 EXPECT_TRUE(area->HasUncommittedChanges());
357 EXPECT_EQ(2u, area->Length());
358 area->DeleteOrigin();
359 EXPECT_TRUE(area->HasUncommittedChanges());
360 EXPECT_EQ(0u, area->Length());
361 base::MessageLoop::current()->RunUntilIdle();
362 EXPECT_FALSE(area->HasUncommittedChanges());
363 // Since the area had uncommitted changes at the time delete
364 // was called, the file will linger until the shutdown time.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100365 EXPECT_TRUE(base::PathExists(db_file_path));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100366 area->Shutdown();
367 base::MessageLoop::current()->RunUntilIdle();
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100368 EXPECT_FALSE(base::PathExists(db_file_path));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100369}
370
Ben Murdochbb1529c2013-08-08 10:24:53 +0100371TEST_F(DOMStorageAreaTest, PurgeMemory) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100372 base::ScopedTempDir temp_dir;
373 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
Ben Murdochbb1529c2013-08-08 10:24:53 +0100374 scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100375 kOrigin,
376 temp_dir.path(),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100377 new MockDOMStorageTaskRunner(base::MessageLoopProxy::current().get())));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100378
379 // Inject an in-memory db to speed up the test.
380 area->backing_.reset(new LocalStorageDatabaseAdapter());
381
382 // Unowned ptrs we use to verify that 'purge' has happened.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100383 DOMStorageDatabase* original_backing =
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100384 static_cast<LocalStorageDatabaseAdapter*>(
385 area->backing_.get())->db_.get();
Ben Murdochbb1529c2013-08-08 10:24:53 +0100386 DOMStorageMap* original_map = area->map_.get();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100387
388 // Should do no harm when called on a newly constructed object.
389 EXPECT_FALSE(area->is_initial_import_done_);
390 area->PurgeMemory();
391 EXPECT_FALSE(area->is_initial_import_done_);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100392 DOMStorageDatabase* new_backing = static_cast<LocalStorageDatabaseAdapter*>(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100393 area->backing_.get())->db_.get();
394 EXPECT_EQ(original_backing, new_backing);
395 EXPECT_EQ(original_map, area->map_.get());
396
397 // Should not do anything when commits are pending.
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100398 base::NullableString16 old_value;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100399 area->SetItem(kKey, kValue, &old_value);
400 EXPECT_TRUE(area->is_initial_import_done_);
401 EXPECT_TRUE(area->HasUncommittedChanges());
402 area->PurgeMemory();
403 EXPECT_TRUE(area->is_initial_import_done_);
404 EXPECT_TRUE(area->HasUncommittedChanges());
405 new_backing = static_cast<LocalStorageDatabaseAdapter*>(
406 area->backing_.get())->db_.get();
407 EXPECT_EQ(original_backing, new_backing);
408 EXPECT_EQ(original_map, area->map_.get());
409
410 // Commit the changes from above,
411 base::MessageLoop::current()->RunUntilIdle();
412 EXPECT_FALSE(area->HasUncommittedChanges());
413 new_backing = static_cast<LocalStorageDatabaseAdapter*>(
414 area->backing_.get())->db_.get();
415 EXPECT_EQ(original_backing, new_backing);
416 EXPECT_EQ(original_map, area->map_.get());
417
418 // Should drop caches and reset database connections
419 // when invoked on an area that's loaded up primed.
420 area->PurgeMemory();
421 EXPECT_FALSE(area->is_initial_import_done_);
422 new_backing = static_cast<LocalStorageDatabaseAdapter*>(
423 area->backing_.get())->db_.get();
424 EXPECT_NE(original_backing, new_backing);
425 EXPECT_NE(original_map, area->map_.get());
426}
427
Ben Murdochbb1529c2013-08-08 10:24:53 +0100428TEST_F(DOMStorageAreaTest, DatabaseFileNames) {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100429 struct {
430 const char* origin;
431 const char* file_name;
432 const char* journal_file_name;
433 } kCases[] = {
434 { "https://www.google.com/",
435 "https_www.google.com_0.localstorage",
436 "https_www.google.com_0.localstorage-journal" },
437 { "http://www.google.com:8080/",
438 "http_www.google.com_8080.localstorage",
439 "http_www.google.com_8080.localstorage-journal" },
440 { "file:///",
441 "file__0.localstorage",
442 "file__0.localstorage-journal" },
443 };
444
445 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kCases); ++i) {
446 GURL origin = GURL(kCases[i].origin).GetOrigin();
Ben Murdochbb1529c2013-08-08 10:24:53 +0100447 base::FilePath file_name =
448 base::FilePath().AppendASCII(kCases[i].file_name);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100449 base::FilePath journal_file_name =
450 base::FilePath().AppendASCII(kCases[i].journal_file_name);
451
452 EXPECT_EQ(file_name,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100453 DOMStorageArea::DatabaseFileNameFromOrigin(origin));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100454 EXPECT_EQ(origin,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100455 DOMStorageArea::OriginFromDatabaseFileName(file_name));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100456 EXPECT_EQ(journal_file_name,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100457 DOMStorageDatabase::GetJournalFilePath(file_name));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100458 }
459
Ben Murdochbb1529c2013-08-08 10:24:53 +0100460 // Also test some DOMStorageDatabase::GetJournalFilePath cases here.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100461 base::FilePath parent = base::FilePath().AppendASCII("a").AppendASCII("b");
462 EXPECT_EQ(
463 parent.AppendASCII("file-journal"),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100464 DOMStorageDatabase::GetJournalFilePath(parent.AppendASCII("file")));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100465 EXPECT_EQ(
466 base::FilePath().AppendASCII("-journal"),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100467 DOMStorageDatabase::GetJournalFilePath(base::FilePath()));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100468 EXPECT_EQ(
469 base::FilePath().AppendASCII(".extensiononly-journal"),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100470 DOMStorageDatabase::GetJournalFilePath(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100471 base::FilePath().AppendASCII(".extensiononly")));
472}
473
Ben Murdochbb1529c2013-08-08 10:24:53 +0100474} // namespace content