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

Side by Side Diff: content/browser/indexed_db/indexed_db_browsertest.cc

Issue 197333009: Handling LevelDB errors encountered after open. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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
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/command_line.h" 6 #include "base/command_line.h"
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/files/file_enumerator.h"
8 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
9 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
10 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
11 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
12 #include "base/test/thread_test_helper.h" 13 #include "base/test/thread_test_helper.h"
13 #include "content/browser/browser_main_loop.h" 14 #include "content/browser/browser_main_loop.h"
14 #include "content/browser/indexed_db/indexed_db_context_impl.h" 15 #include "content/browser/indexed_db/indexed_db_context_impl.h"
15 #include "content/browser/web_contents/web_contents_impl.h" 16 #include "content/browser/web_contents/web_contents_impl.h"
16 #include "content/public/browser/browser_context.h" 17 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/render_process_host.h" 19 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/storage_partition.h" 20 #include "content/public/browser/storage_partition.h"
20 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_contents.h"
21 #include "content/public/common/content_switches.h" 22 #include "content/public/common/content_switches.h"
22 #include "content/public/common/url_constants.h" 23 #include "content/public/common/url_constants.h"
23 #include "content/public/test/browser_test_utils.h" 24 #include "content/public/test/browser_test_utils.h"
24 #include "content/shell/browser/shell.h" 25 #include "content/shell/browser/shell.h"
25 #include "content/test/content_browser_test.h" 26 #include "content/test/content_browser_test.h"
26 #include "content/test/content_browser_test_utils.h" 27 #include "content/test/content_browser_test_utils.h"
28 #include "net/base/net_errors.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h"
30 #include "net/test/embedded_test_server/http_request.h"
31 #include "net/test/embedded_test_server/http_response.h"
27 #include "webkit/browser/database/database_util.h" 32 #include "webkit/browser/database/database_util.h"
28 #include "webkit/browser/quota/quota_manager.h" 33 #include "webkit/browser/quota/quota_manager.h"
29 34
30 using base::ASCIIToUTF16; 35 using base::ASCIIToUTF16;
31 using quota::QuotaManager; 36 using quota::QuotaManager;
32 using webkit_database::DatabaseUtil; 37 using webkit_database::DatabaseUtil;
33 38
34 namespace content { 39 namespace content {
35 40
36 // This browser test is aimed towards exercising the IndexedDB bindings and 41 // This browser test is aimed towards exercising the IndexedDB bindings and
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 354
350 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CanDeleteWhenOverQuotaTest) { 355 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CanDeleteWhenOverQuotaTest) {
351 SimpleTest(GetTestUrl("indexeddb", "fill_up_5k.html")); 356 SimpleTest(GetTestUrl("indexeddb", "fill_up_5k.html"));
352 int64 size = RequestDiskUsage(); 357 int64 size = RequestDiskUsage();
353 const int kQuotaKilobytes = 2; 358 const int kQuotaKilobytes = 2;
354 EXPECT_GT(size, kQuotaKilobytes * 1024); 359 EXPECT_GT(size, kQuotaKilobytes * 1024);
355 SetQuota(kQuotaKilobytes); 360 SetQuota(kQuotaKilobytes);
356 SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html")); 361 SimpleTest(GetTestUrl("indexeddb", "delete_over_quota.html"));
357 } 362 }
358 363
364 namespace {
365
366 static void FlushIndexedDBDatabase(scoped_refptr<IndexedDBContextImpl> context,
jsbell 2014/03/26 18:16:58 'Database' or 'BackingStore' ?
cmumford 2014/03/26 21:40:36 Renamed to 'BackingStore'
367 const GURL& origin_url) {
368 IndexedDBFactory* factory = context->GetIDBFactory();
369
370 std::pair<IndexedDBFactory::OriginDBMapIterator,
371 IndexedDBFactory::OriginDBMapIterator> range =
372 factory->GetOpenDatabasesForOrigin(origin_url);
373
374 while (range.first != range.second) {
375 IndexedDBDatabase* db = range.first->second;
376 IndexedDBBackingStore* backing_store = db->backing_store();
377 backing_store->Flush();
jsbell 2014/03/26 18:16:58 All databases in an origin share a backing store,
cmumford 2014/03/26 21:40:36 Done.
378 ++range.first;
379 }
380 }
381
382 static void CorruptIndexedDBDatabase(
jsbell 2014/03/26 18:16:58 Add comment about why it's async?
cmumford 2014/03/26 21:40:36 Actually it's effectively sync, but I didn't see a
jsbell 2014/03/26 22:49:00 Oops, yeah, I shouldn't have said "async". It wasn
383 IndexedDBContextImpl* context,
384 const GURL& origin_url,
385 base::WaitableEvent* signal_when_finished) {
386
387 FlushIndexedDBDatabase(context, origin_url);
388
389 int numFiles = 0;
390 int numErrors = 0;
391 base::FilePath idb_data_path = context->GetFilePath(origin_url);
392 const bool recursive = false;
393 base::FileEnumerator enumerator(
394 idb_data_path, recursive, base::FileEnumerator::FILES);
395 for (base::FilePath idb_file = enumerator.Next(); !idb_file.empty();
396 idb_file = enumerator.Next()) {
397 int64 size(0);
jsbell 2014/03/26 18:16:58 size_t?
cmumford 2014/03/26 21:40:36 Not according to base/file_util.h
jsbell 2014/03/26 22:49:00 Sorry. I swear I saw it as size_t. :(
398 GetFileSize(idb_file, &size);
399
400 if (idb_file.Extension() == ".ldb") {
401 numFiles++;
402 FILE* f = fopen(idb_file.value().c_str(), "w");
jsbell 2014/03/26 18:16:58 Why FILE/fopen/fwrite instead of base::PlatformFil
cmumford 2014/03/26 21:40:36 I think I was unaware way back when I wrote this.
403 if (f) {
404 char zero(0);
405 if (size != (int64)fwrite(&zero, sizeof(zero), size, f))
406 numErrors++;
407 fclose(f);
408 } else {
409 numErrors++;
410 }
411 }
412 }
413
414 VLOG(0) << "There were " << numFiles << " in " << idb_data_path.value()
415 << " with " << numErrors << " errors";
416 signal_when_finished->Signal();
417 }
418
419 const std::string s_corrupt_db_test_prefix = "/corrupt/test/";
420
421 static scoped_ptr<net::test_server::HttpResponse> CorruptDbRequestHandler(
jsbell 2014/03/26 18:16:58 Nit: Capitalize DB
cmumford 2014/03/26 21:40:36 Done.
422 IndexedDBContextImpl* context,
423 const GURL& origin_url,
424 const std::string& path,
425 const net::test_server::HttpRequest& request) {
426
427 std::string request_path;
428 if (path.find(s_corrupt_db_test_prefix) != std::string::npos)
429 request_path = request.relative_url.substr(s_corrupt_db_test_prefix.size());
430 else
431 return scoped_ptr<net::test_server::HttpResponse>();
432
433 // Remove the query string if present.
jsbell 2014/03/26 18:16:58 Can you use a GURL to make this parsing easier?
cmumford 2014/03/26 21:40:36 No, this is only the resource/query part of the UR
434 std::string request_query;
435 size_t query_pos = request_path.find('?');
436 if (query_pos != std::string::npos) {
437 request_query = request_path.substr(query_pos + 1);
438 request_path = request_path.substr(0, query_pos);
439 }
440
441 if (request_path == "corruptdb" && !request_query.empty()) {
442 VLOG(0) << "Requested to currupt IndexedDB: " << request_query;
jsbell 2014/03/26 18:16:58 Typo: corrupt
cmumford 2014/03/26 21:40:36 Done.
443 base::WaitableEvent signal_when_finished(false, false);
444 context->TaskRunner()->PostTask(FROM_HERE,
445 base::Bind(&CorruptIndexedDBDatabase,
446 base::ConstRef(context),
447 origin_url,
448 &signal_when_finished));
449 signal_when_finished.Wait();
450
451 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
452 new net::test_server::BasicHttpResponse);
453 http_response->set_code(net::HTTP_OK);
454 return http_response.PassAs<net::test_server::HttpResponse>();
455 } else {
jsbell 2014/03/26 18:16:58 No need for else block since if() early-exits.
cmumford 2014/03/26 21:40:36 Done.
456 // A request for a test resource
jsbell 2014/03/26 18:16:58 Do we need to handle this? Can't the registered ha
cmumford 2014/03/26 21:40:36 From what I can tell this BasicHttpResponse object
jsbell 2014/03/26 22:49:00 Again, sorry - I thought the RegisterRequestHandle
457 base::FilePath resourcePath =
458 content::GetTestFilePath("indexeddb", request_path.c_str());
459 scoped_ptr<net::test_server::BasicHttpResponse> http_response(
460 new net::test_server::BasicHttpResponse);
461 http_response->set_code(net::HTTP_OK);
462 std::string file_contents;
463 if (!base::ReadFileToString(resourcePath, &file_contents))
464 return scoped_ptr<net::test_server::HttpResponse>();
465 http_response->set_content(file_contents);
466 return http_response.PassAs<net::test_server::HttpResponse>();
467 }
468 }
469
470 } // namespace
471
472 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CorruptedOpenDatabase) {
473 ASSERT_TRUE(embedded_test_server()->Started() ||
474 embedded_test_server()->InitializeAndWaitUntilReady());
475 const GURL& origin_url = embedded_test_server()->base_url();
476 embedded_test_server()->RegisterRequestHandler(
477 base::Bind(&CorruptDbRequestHandler,
478 base::ConstRef(GetContext()),
479 origin_url,
480 s_corrupt_db_test_prefix));
481
482 std::string test_file =
483 s_corrupt_db_test_prefix + "corrupted_open_db_detection.html";
484 SimpleTest(embedded_test_server()->GetURL(test_file));
485
486 test_file = s_corrupt_db_test_prefix + "corrupted_open_db_recovery.html";
487 SimpleTest(embedded_test_server()->GetURL(test_file));
488 }
489
359 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) { 490 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DeleteCompactsBackingStore) {
360 const GURL test_url = GetTestUrl("indexeddb", "delete_compact.html"); 491 const GURL test_url = GetTestUrl("indexeddb", "delete_compact.html");
361 SimpleTest(GURL(test_url.spec() + "#fill")); 492 SimpleTest(GURL(test_url.spec() + "#fill"));
362 int64 after_filling = RequestDiskUsage(); 493 int64 after_filling = RequestDiskUsage();
363 EXPECT_GT(after_filling, 0); 494 EXPECT_GT(after_filling, 0);
364 495
365 SimpleTest(GURL(test_url.spec() + "#purge")); 496 SimpleTest(GURL(test_url.spec() + "#purge"));
366 int64 after_deleting = RequestDiskUsage(); 497 int64 after_deleting = RequestDiskUsage();
367 EXPECT_LT(after_deleting, after_filling); 498 EXPECT_LT(after_deleting, after_filling);
368 499
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 "connection ready"); 573 "connection ready");
443 574
444 GetContext()->TaskRunner()->PostTask( 575 GetContext()->TaskRunner()->PostTask(
445 FROM_HERE, 576 FROM_HERE,
446 base::Bind(&IndexedDBContextImpl::DeleteForOrigin, 577 base::Bind(&IndexedDBContextImpl::DeleteForOrigin,
447 GetContext(), 578 GetContext(),
448 GURL("file:///"))); 579 GURL("file:///")));
449 580
450 base::string16 expected_title16(ASCIIToUTF16("connection closed")); 581 base::string16 expected_title16(ASCIIToUTF16("connection closed"));
451 TitleWatcher title_watcher(shell()->web_contents(), expected_title16); 582 TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
583 title_watcher.AlsoWaitForTitle(ASCIIToUTF16("connection closed with error"));
452 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle()); 584 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
453 } 585 }
454 586
455 class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest { 587 class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest {
456 public: 588 public:
457 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 589 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
458 command_line->AppendSwitch(switches::kSingleProcess); 590 command_line->AppendSwitch(switches::kSingleProcess);
459 } 591 }
460 }; 592 };
461 593
462 // Crashing on Android due to kSingleProcess flag: http://crbug.com/342525 594 // Crashing on Android due to kSingleProcess flag: http://crbug.com/342525
463 #if defined(OS_ANDROID) 595 #if defined(OS_ANDROID)
464 #define MAYBE_RenderThreadShutdownTest DISABLED_RenderThreadShutdownTest 596 #define MAYBE_RenderThreadShutdownTest DISABLED_RenderThreadShutdownTest
465 #else 597 #else
466 #define MAYBE_RenderThreadShutdownTest RenderThreadShutdownTest 598 #define MAYBE_RenderThreadShutdownTest RenderThreadShutdownTest
467 #endif 599 #endif
468 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess, 600 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess,
469 MAYBE_RenderThreadShutdownTest) { 601 MAYBE_RenderThreadShutdownTest) {
470 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html")); 602 SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html"));
471 } 603 }
472 604
473 } // namespace content 605 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698