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

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

Issue 9817011: DomStorage data deletion and memory purging. (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"
(...skipping 22 matching lines...) Expand all
33 const string16 kValue; 33 const string16 kValue;
34 const string16 kKey2; 34 const string16 kKey2;
35 const string16 kValue2; 35 const string16 kValue2;
36 36
37 // Method used in the CommitTasks test case. 37 // Method used in the CommitTasks test case.
38 void InjectedCommitSequencingTask(DomStorageArea* area) { 38 void InjectedCommitSequencingTask(DomStorageArea* area) {
39 // At this point the OnCommitTimer has run. 39 // At this point the OnCommitTimer has run.
40 // Verify that it put a commit in flight. 40 // Verify that it put a commit in flight.
41 EXPECT_TRUE(area->in_flight_commit_batch_.get()); 41 EXPECT_TRUE(area->in_flight_commit_batch_.get());
42 EXPECT_FALSE(area->commit_batch_.get()); 42 EXPECT_FALSE(area->commit_batch_.get());
43 EXPECT_TRUE(area->HasUncommittedChanges());
43 // Make additional change and verify that a new commit batch 44 // Make additional change and verify that a new commit batch
44 // is created for that change. 45 // is created for that change.
45 NullableString16 old_value; 46 NullableString16 old_value;
46 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value)); 47 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value));
47 EXPECT_TRUE(area->commit_batch_.get()); 48 EXPECT_TRUE(area->commit_batch_.get());
48 EXPECT_TRUE(area->in_flight_commit_batch_.get()); 49 EXPECT_TRUE(area->in_flight_commit_batch_.get());
50 EXPECT_TRUE(area->HasUncommittedChanges());
49 } 51 }
50 52
51 // Class used in the CommitChangesAtShutdown test case. 53 // Class used in the CommitChangesAtShutdown test case.
52 class VerifyChangesCommittedDatabase : public DomStorageDatabase { 54 class VerifyChangesCommittedDatabase : public DomStorageDatabase {
53 public: 55 public:
54 VerifyChangesCommittedDatabase() {} 56 VerifyChangesCommittedDatabase() {}
55 virtual ~VerifyChangesCommittedDatabase() { 57 virtual ~VerifyChangesCommittedDatabase() {
56 const string16 kKey(ASCIIToUTF16("key")); 58 const string16 kKey(ASCIIToUTF16("key"));
57 const string16 kValue(ASCIIToUTF16("value")); 59 const string16 kValue(ASCIIToUTF16("value"));
58 ValuesMap values; 60 ValuesMap values;
(...skipping 11 matching lines...) Expand all
70 NullableString16 old_nullable_value; 72 NullableString16 old_nullable_value;
71 scoped_refptr<DomStorageArea> copy; 73 scoped_refptr<DomStorageArea> copy;
72 74
73 // We don't focus on the underlying DomStorageMap functionality 75 // We don't focus on the underlying DomStorageMap functionality
74 // since that's covered by seperate unit tests. 76 // since that's covered by seperate unit tests.
75 EXPECT_EQ(kOrigin, area->origin()); 77 EXPECT_EQ(kOrigin, area->origin());
76 EXPECT_EQ(1, area->namespace_id()); 78 EXPECT_EQ(1, area->namespace_id());
77 EXPECT_EQ(0u, area->Length()); 79 EXPECT_EQ(0u, area->Length());
78 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value)); 80 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_nullable_value));
79 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_nullable_value)); 81 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_nullable_value));
82 EXPECT_FALSE(area->HasUncommittedChanges());
80 83
81 // Verify that a copy shares the same map. 84 // Verify that a copy shares the same map.
82 copy = area->ShallowCopy(2); 85 copy = area->ShallowCopy(2);
83 EXPECT_EQ(kOrigin, copy->origin()); 86 EXPECT_EQ(kOrigin, copy->origin());
84 EXPECT_EQ(2, copy->namespace_id()); 87 EXPECT_EQ(2, copy->namespace_id());
85 EXPECT_EQ(area->Length(), copy->Length()); 88 EXPECT_EQ(area->Length(), copy->Length());
86 EXPECT_EQ(area->GetItem(kKey).string(), copy->GetItem(kKey).string()); 89 EXPECT_EQ(area->GetItem(kKey).string(), copy->GetItem(kKey).string());
87 EXPECT_EQ(area->Key(0).string(), copy->Key(0).string()); 90 EXPECT_EQ(area->Key(0).string(), copy->Key(0).string());
88 EXPECT_EQ(copy->map_.get(), area->map_.get()); 91 EXPECT_EQ(copy->map_.get(), area->map_.get());
89 92
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 EXPECT_FALSE(area->is_initial_import_done_); 208 EXPECT_FALSE(area->is_initial_import_done_);
206 EXPECT_EQ(0u, area->Length()); 209 EXPECT_EQ(0u, area->Length());
207 EXPECT_TRUE(area->is_initial_import_done_); 210 EXPECT_TRUE(area->is_initial_import_done_);
208 211
209 ValuesMap values; 212 ValuesMap values;
210 NullableString16 old_value; 213 NullableString16 old_value;
211 214
212 // See that changes are batched up. 215 // See that changes are batched up.
213 EXPECT_FALSE(area->commit_batch_.get()); 216 EXPECT_FALSE(area->commit_batch_.get());
214 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value)); 217 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
218 EXPECT_TRUE(area->HasUncommittedChanges());
215 EXPECT_TRUE(area->commit_batch_.get()); 219 EXPECT_TRUE(area->commit_batch_.get());
216 EXPECT_FALSE(area->commit_batch_->clear_all_first); 220 EXPECT_FALSE(area->commit_batch_->clear_all_first);
217 EXPECT_EQ(1u, area->commit_batch_->changed_values.size()); 221 EXPECT_EQ(1u, area->commit_batch_->changed_values.size());
218 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value)); 222 EXPECT_TRUE(area->SetItem(kKey2, kValue2, &old_value));
219 EXPECT_TRUE(area->commit_batch_.get()); 223 EXPECT_TRUE(area->commit_batch_.get());
220 EXPECT_FALSE(area->commit_batch_->clear_all_first); 224 EXPECT_FALSE(area->commit_batch_->clear_all_first);
221 EXPECT_EQ(2u, area->commit_batch_->changed_values.size()); 225 EXPECT_EQ(2u, area->commit_batch_->changed_values.size());
222 MessageLoop::current()->RunAllPending(); 226 MessageLoop::current()->RunAllPending();
227 EXPECT_FALSE(area->HasUncommittedChanges());
223 EXPECT_FALSE(area->commit_batch_.get()); 228 EXPECT_FALSE(area->commit_batch_.get());
224 EXPECT_FALSE(area->in_flight_commit_batch_.get()); 229 EXPECT_FALSE(area->in_flight_commit_batch_.get());
225 // Verify the changes made it to the database. 230 // Verify the changes made it to the database.
226 values.clear(); 231 values.clear();
227 area->backing_->ReadAllValues(&values); 232 area->backing_->ReadAllValues(&values);
228 EXPECT_EQ(2u, values.size()); 233 EXPECT_EQ(2u, values.size());
229 EXPECT_EQ(kValue, values[kKey].string()); 234 EXPECT_EQ(kValue, values[kKey].string());
230 EXPECT_EQ(kValue2, values[kKey2].string()); 235 EXPECT_EQ(kValue2, values[kKey2].string());
231 236
232 // See that clear is handled properly. 237 // See that clear is handled properly.
233 EXPECT_TRUE(area->Clear()); 238 EXPECT_TRUE(area->Clear());
234 EXPECT_TRUE(area->commit_batch_.get()); 239 EXPECT_TRUE(area->commit_batch_.get());
235 EXPECT_TRUE(area->commit_batch_->clear_all_first); 240 EXPECT_TRUE(area->commit_batch_->clear_all_first);
236 EXPECT_TRUE(area->commit_batch_->changed_values.empty()); 241 EXPECT_TRUE(area->commit_batch_->changed_values.empty());
237 MessageLoop::current()->RunAllPending(); 242 MessageLoop::current()->RunAllPending();
238 EXPECT_FALSE(area->commit_batch_.get()); 243 EXPECT_FALSE(area->commit_batch_.get());
239 EXPECT_FALSE(area->in_flight_commit_batch_.get()); 244 EXPECT_FALSE(area->in_flight_commit_batch_.get());
240 // Verify the changes made it to the database. 245 // Verify the changes made it to the database.
241 values.clear(); 246 values.clear();
242 area->backing_->ReadAllValues(&values); 247 area->backing_->ReadAllValues(&values);
243 EXPECT_TRUE(values.empty()); 248 EXPECT_TRUE(values.empty());
244 249
245 // See that if changes accrue while a commit is "in flight" 250 // See that if changes accrue while a commit is "in flight"
246 // those will also get committed. 251 // those will also get committed.
247 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value)); 252 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
248 EXPECT_TRUE(area->commit_batch_.get()); 253 EXPECT_TRUE(area->HasUncommittedChanges());
249 // At this point the OnCommitTimer task has been posted. We inject 254 // At this point the OnCommitTimer task has been posted. We inject
250 // another task in the queue that will execute after the timer task, 255 // another task in the queue that will execute after the timer task,
251 // but before the CommitChanges task. From within our injected task, 256 // but before the CommitChanges task. From within our injected task,
252 // we'll make an additional SetItem() call. 257 // we'll make an additional SetItem() call.
253 MessageLoop::current()->PostTask( 258 MessageLoop::current()->PostTask(
254 FROM_HERE, 259 FROM_HERE,
255 base::Bind(&DomStorageAreaTest::InjectedCommitSequencingTask, 260 base::Bind(&DomStorageAreaTest::InjectedCommitSequencingTask,
256 base::Unretained(this), area)); 261 base::Unretained(this), area));
257 MessageLoop::current()->RunAllPending(); 262 MessageLoop::current()->RunAllPending();
258 EXPECT_TRUE(area->HasOneRef()); 263 EXPECT_TRUE(area->HasOneRef());
259 EXPECT_FALSE(area->commit_batch_.get()); 264 EXPECT_FALSE(area->HasUncommittedChanges());
260 EXPECT_FALSE(area->in_flight_commit_batch_.get());
261 // Verify the changes made it to the database. 265 // Verify the changes made it to the database.
262 values.clear(); 266 values.clear();
263 area->backing_->ReadAllValues(&values); 267 area->backing_->ReadAllValues(&values);
264 EXPECT_EQ(2u, values.size()); 268 EXPECT_EQ(2u, values.size());
265 EXPECT_EQ(kValue, values[kKey].string()); 269 EXPECT_EQ(kValue, values[kKey].string());
266 EXPECT_EQ(kValue2, values[kKey2].string()); 270 EXPECT_EQ(kValue2, values[kKey2].string());
267 } 271 }
268 272
269 TEST_F(DomStorageAreaTest, CommitChangesAtShutdown) { 273 TEST_F(DomStorageAreaTest, CommitChangesAtShutdown) {
270 ScopedTempDir temp_dir; 274 ScopedTempDir temp_dir;
271 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 275 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
272 scoped_refptr<DomStorageArea> area( 276 scoped_refptr<DomStorageArea> area(
273 new DomStorageArea(kLocalStorageNamespaceId, kOrigin, 277 new DomStorageArea(kLocalStorageNamespaceId, kOrigin,
274 temp_dir.path(), 278 temp_dir.path(),
275 new MockDomStorageTaskRunner(base::MessageLoopProxy::current()))); 279 new MockDomStorageTaskRunner(base::MessageLoopProxy::current())));
276 280
277 // Inject an in-memory db to speed up the test and also to verify 281 // Inject an in-memory db to speed up the test and also to verify
278 // the final changes are commited in it's dtor. 282 // the final changes are commited in it's dtor.
279 area->backing_.reset(new VerifyChangesCommittedDatabase()); 283 area->backing_.reset(new VerifyChangesCommittedDatabase());
280 284
281 ValuesMap values; 285 ValuesMap values;
282 NullableString16 old_value; 286 NullableString16 old_value;
283 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value)); 287 EXPECT_TRUE(area->SetItem(kKey, kValue, &old_value));
284 EXPECT_TRUE(area->commit_batch_.get()); 288 EXPECT_TRUE(area->HasUncommittedChanges());
285 area->backing_->ReadAllValues(&values); 289 area->backing_->ReadAllValues(&values);
286 EXPECT_TRUE(values.empty()); // not committed yet 290 EXPECT_TRUE(values.empty()); // not committed yet
287 area->Shutdown(); 291 area->Shutdown();
288 MessageLoop::current()->RunAllPending(); 292 MessageLoop::current()->RunAllPending();
289 EXPECT_TRUE(area->HasOneRef()); 293 EXPECT_TRUE(area->HasOneRef());
290 EXPECT_FALSE(area->backing_.get()); 294 EXPECT_FALSE(area->backing_.get());
291 // The VerifyChangesCommittedDatabase destructor verifies values 295 // The VerifyChangesCommittedDatabase destructor verifies values
292 // were committed. 296 // were committed.
293 } 297 }
294 298
295 TEST_F(DomStorageAreaTest, TestDatabaseFilePath) { 299 TEST_F(DomStorageAreaTest, DeleteOrigin) {
296 EXPECT_EQ(FilePath().AppendASCII("file_path_to_0.localstorage"), 300 ScopedTempDir temp_dir;
297 DomStorageArea::DatabaseFileNameFromOrigin( 301 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
298 GURL("file://path_to/index.html"))); 302 scoped_refptr<DomStorageArea> area(
303 new DomStorageArea(kLocalStorageNamespaceId, kOrigin,
304 temp_dir.path(),
305 new MockDomStorageTaskRunner(base::MessageLoopProxy::current())));
299 306
300 EXPECT_EQ(FilePath().AppendASCII("https_www.google.com_0.localstorage"), 307 // This test puts files on disk.
301 DomStorageArea::DatabaseFileNameFromOrigin( 308 FilePath db_file_path = area->backing_->file_path();
302 GURL("https://www.google.com/"))); 309 FilePath db_journal_file_path =
310 DomStorageDatabase::GetJournalFilePath(db_file_path);
303 311
304 EXPECT_EQ(FilePath().AppendASCII("https_www.google.com_8080.localstorage"), 312 // Nothing bad should happen when invoked w/o any files on disk.
305 DomStorageArea::DatabaseFileNameFromOrigin( 313 area->DeleteOrigin();
306 GURL("https://www.google.com:8080"))); 314 EXPECT_FALSE(file_util::PathExists(db_file_path));
315
316 // Commit something in the database and then delete.
317 NullableString16 old_value;
318 area->SetItem(kKey, kValue, &old_value);
319 MessageLoop::current()->RunAllPending();
320 EXPECT_TRUE(file_util::PathExists(db_file_path));
321 area->DeleteOrigin();
322 EXPECT_EQ(0u, area->Length());
323 EXPECT_FALSE(file_util::PathExists(db_file_path));
324 EXPECT_FALSE(file_util::PathExists(db_journal_file_path));
325
326 // Put some uncommitted changes to a non-existing database in
327 // and then delete. No file ever gets created in this case.
328 area->SetItem(kKey, kValue, &old_value);
329 EXPECT_TRUE(area->HasUncommittedChanges());
330 EXPECT_EQ(1u, area->Length());
331 area->DeleteOrigin();
332 EXPECT_TRUE(area->HasUncommittedChanges());
333 EXPECT_EQ(0u, area->Length());
334 MessageLoop::current()->RunAllPending();
335 EXPECT_FALSE(area->HasUncommittedChanges());
336 EXPECT_FALSE(file_util::PathExists(db_file_path));
337
338 // Put some uncommitted changes to a an existing database in
339 // and then delete.
340 area->SetItem(kKey, kValue, &old_value);
341 MessageLoop::current()->RunAllPending();
342 EXPECT_TRUE(file_util::PathExists(db_file_path));
343 area->SetItem(kKey2, kValue2, &old_value);
344 EXPECT_TRUE(area->HasUncommittedChanges());
345 EXPECT_EQ(2u, area->Length());
346 area->DeleteOrigin();
347 EXPECT_TRUE(area->HasUncommittedChanges());
348 EXPECT_EQ(0u, area->Length());
349 MessageLoop::current()->RunAllPending();
350 EXPECT_FALSE(area->HasUncommittedChanges());
351 // Since the area had uncommitted changes at the time delete
352 // was called, the file will linger until the shutdown time.
353 EXPECT_TRUE(file_util::PathExists(db_file_path));
354 area->Shutdown();
355 MessageLoop::current()->RunAllPending();
356 EXPECT_FALSE(file_util::PathExists(db_file_path));
357 }
358
359 TEST_F(DomStorageAreaTest, PurgeMemory) {
360 ScopedTempDir temp_dir;
361 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
362 scoped_refptr<DomStorageArea> area(
363 new DomStorageArea(kLocalStorageNamespaceId, kOrigin,
364 temp_dir.path(),
365 new MockDomStorageTaskRunner(base::MessageLoopProxy::current())));
366
367 // Inject an in-memory db to speed up the test.
368 area->backing_.reset(new DomStorageDatabase());
369
370 // Unowned ptrs we use to verify that 'purge' has happened.
371 DomStorageDatabase* original_backing = area->backing_.get();
372 DomStorageMap* original_map = area->map_.get();
373
374 // Should do no harm when called on a newly constructed object.
375 EXPECT_FALSE(area->is_initial_import_done_);
376 area->PurgeMemory();
377 EXPECT_FALSE(area->is_initial_import_done_);
378 EXPECT_EQ(original_backing, area->backing_.get());
379 EXPECT_EQ(original_map, area->map_.get());
380
381 // Should not do anything when commits are pending.
382 NullableString16 old_value;
383 area->SetItem(kKey, kValue, &old_value);
384 EXPECT_TRUE(area->is_initial_import_done_);
385 EXPECT_TRUE(area->HasUncommittedChanges());
386 area->PurgeMemory();
387 EXPECT_TRUE(area->is_initial_import_done_);
388 EXPECT_TRUE(area->HasUncommittedChanges());
389 EXPECT_EQ(original_backing, area->backing_.get());
390 EXPECT_EQ(original_map, area->map_.get());
391
392 // Commit the changes from above,
393 MessageLoop::current()->RunAllPending();
394 EXPECT_FALSE(area->HasUncommittedChanges());
395 EXPECT_EQ(original_backing, area->backing_.get());
396 EXPECT_EQ(original_map, area->map_.get());
397
398 // Should drop caches and reset database connections
399 // invoked on an area that loaded up.
400 area->PurgeMemory();
401 EXPECT_FALSE(area->is_initial_import_done_);
402 EXPECT_NE(original_backing, area->backing_.get());
403 EXPECT_NE(original_map, area->map_.get());
404 }
405
406 TEST_F(DomStorageAreaTest, DatabaseFileNames) {
407 struct {
408 const char* origin;
409 const char* file_name;
410 const char* journal_file_name;
411 } kCases[] = {
412 { "https://www.google.com/",
413 "https_www.google.com_0.localstorage",
414 "https_www.google.com_0.localstorage-journal" },
415 { "http://www.google.com:8080/",
416 "http_www.google.com_8080.localstorage",
417 "http_www.google.com_8080.localstorage-journal" },
418 { "file:///",
419 "file__0.localstorage",
420 "file__0.localstorage-journal" },
421 };
422
423 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kCases); ++i) {
424 GURL origin = GURL(kCases[i].origin).GetOrigin();
425 FilePath file_name = FilePath().AppendASCII(kCases[i].file_name);
426 FilePath journal_file_name =
427 FilePath().AppendASCII(kCases[i].journal_file_name);
428
429 EXPECT_EQ(file_name,
430 DomStorageArea::DatabaseFileNameFromOrigin(origin));
431 EXPECT_EQ(origin,
432 DomStorageArea::OriginFromDatabaseFileName(file_name));
433 EXPECT_EQ(journal_file_name,
434 DomStorageDatabase::GetJournalFilePath(file_name));
435 }
436
437 // Also test some DomStorageDatabase::GetJournalFilePath cases here.
438 FilePath parent = FilePath().AppendASCII("a").AppendASCII("b");
439 EXPECT_EQ(
440 parent.AppendASCII("file-journal"),
441 DomStorageDatabase::GetJournalFilePath(parent.AppendASCII("file")));
442 EXPECT_EQ(
443 FilePath().AppendASCII("-journal"),
444 DomStorageDatabase::GetJournalFilePath(FilePath()));
445 EXPECT_EQ(
446 FilePath().AppendASCII(".extensiononly-journal"),
447 DomStorageDatabase::GetJournalFilePath(
448 FilePath().AppendASCII(".extensiononly")));
307 } 449 }
308 450
309 } // namespace dom_storage 451 } // 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