OLD | NEW |
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/files/scoped_temp_dir.h" | 7 #include "base/files/scoped_temp_dir.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "sql/connection.h" | 9 #include "sql/connection.h" |
10 #include "sql/meta_table.h" | 10 #include "sql/meta_table.h" |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 EXPECT_TRUE(db().Raze()); | 484 EXPECT_TRUE(db().Raze()); |
485 db().Close(); | 485 db().Close(); |
486 | 486 |
487 // Now empty, the open should succeed with an empty database. | 487 // Now empty, the open should succeed with an empty database. |
488 EXPECT_TRUE(db().Open(db_path())); | 488 EXPECT_TRUE(db().Open(db_path())); |
489 EXPECT_EQ(0, SqliteMasterCount(&db())); | 489 EXPECT_EQ(0, SqliteMasterCount(&db())); |
490 } | 490 } |
491 | 491 |
492 // Test that a callback from Open() can raze the database. This is | 492 // Test that a callback from Open() can raze the database. This is |
493 // essential for cases where the Open() can fail entirely, so the | 493 // essential for cases where the Open() can fail entirely, so the |
494 // Raze() cannot happen later. | 494 // Raze() cannot happen later. Additionally test that when the |
| 495 // callback does this during Open(), the open is retried and succeeds. |
495 // | 496 // |
496 // Most corruptions seen in the wild seem to happen when two pages in | 497 // Most corruptions seen in the wild seem to happen when two pages in |
497 // the database were not written transactionally (the transaction | 498 // the database were not written transactionally (the transaction |
498 // changed both, but one wasn't successfully written for some reason). | 499 // changed both, but one wasn't successfully written for some reason). |
499 // A special case of that is when the header indicates that the | 500 // A special case of that is when the header indicates that the |
500 // database contains more pages than are in the file. This breaks | 501 // database contains more pages than are in the file. This breaks |
501 // things at a very basic level, verify that Raze() can handle it. | 502 // things at a very basic level, verify that Raze() can handle it. |
502 TEST_F(SQLConnectionTest, RazeOpenCallback) { | 503 TEST_F(SQLConnectionTest, RazeCallbackReopen) { |
503 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | 504 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; |
504 ASSERT_TRUE(db().Execute(kCreateSql)); | 505 ASSERT_TRUE(db().Execute(kCreateSql)); |
505 ASSERT_EQ(1, SqliteMasterCount(&db())); | 506 ASSERT_EQ(1, SqliteMasterCount(&db())); |
506 int page_size = 0; | 507 int page_size = 0; |
507 { | 508 { |
508 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); | 509 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); |
509 ASSERT_TRUE(s.Step()); | 510 ASSERT_TRUE(s.Step()); |
510 page_size = s.ColumnInt(0); | 511 page_size = s.ColumnInt(0); |
511 } | 512 } |
512 db().Close(); | 513 db().Close(); |
513 | 514 |
514 // Trim a single page from the end of the file. | 515 // Trim a single page from the end of the file. |
515 { | 516 { |
516 file_util::ScopedFILE file(file_util::OpenFile(db_path(), "r+")); | 517 file_util::ScopedFILE file(file_util::OpenFile(db_path(), "r+")); |
517 ASSERT_TRUE(file.get() != NULL); | 518 ASSERT_TRUE(file.get() != NULL); |
518 ASSERT_EQ(0, fseek(file.get(), -page_size, SEEK_END)); | 519 ASSERT_EQ(0, fseek(file.get(), -page_size, SEEK_END)); |
519 ASSERT_TRUE(file_util::TruncateFile(file.get())); | 520 ASSERT_TRUE(file_util::TruncateFile(file.get())); |
520 } | 521 } |
521 | 522 |
| 523 // Open() will succeed, even though the PRAGMA calls within will |
| 524 // fail with SQLITE_CORRUPT, as will this PRAGMA. |
| 525 { |
| 526 sql::ScopedErrorIgnorer ignore_errors; |
| 527 ignore_errors.IgnoreError(SQLITE_CORRUPT); |
| 528 ASSERT_TRUE(db().Open(db_path())); |
| 529 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum")); |
| 530 db().Close(); |
| 531 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); |
| 532 } |
| 533 |
522 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback, | 534 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback, |
523 base::Unretained(this), | 535 base::Unretained(this), |
524 SQLITE_CORRUPT)); | 536 SQLITE_CORRUPT)); |
525 | 537 |
526 // Open() will see SQLITE_CORRUPT due to size mismatch when | 538 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error |
527 // attempting to run a pragma, and the callback will RazeAndClose(). | 539 // callback will call RazeAndClose(). Open() will then fail and be |
528 // Later statements will fail, including the final secure_delete, | 540 // retried. The second Open() on the empty database will succeed |
529 // which will fail the Open() itself. | 541 // cleanly. |
530 ASSERT_FALSE(db().Open(db_path())); | 542 ASSERT_TRUE(db().Open(db_path())); |
531 db().Close(); | 543 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum")); |
532 | |
533 // Now empty, the open should succeed with an empty database. | |
534 EXPECT_TRUE(db().Open(db_path())); | |
535 EXPECT_EQ(0, SqliteMasterCount(&db())); | 544 EXPECT_EQ(0, SqliteMasterCount(&db())); |
536 } | 545 } |
537 | 546 |
538 // Basic test of RazeAndClose() operation. | 547 // Basic test of RazeAndClose() operation. |
539 TEST_F(SQLConnectionTest, RazeAndClose) { | 548 TEST_F(SQLConnectionTest, RazeAndClose) { |
540 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | 549 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; |
541 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)"; | 550 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)"; |
542 | 551 |
543 // Test that RazeAndClose() closes the database, and that the | 552 // Test that RazeAndClose() closes the database, and that the |
544 // database is empty when re-opened. | 553 // database is empty when re-opened. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); | 665 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); |
657 ASSERT_TRUE(base::PathExists(db_path())); | 666 ASSERT_TRUE(base::PathExists(db_path())); |
658 ASSERT_TRUE(base::PathExists(journal)); | 667 ASSERT_TRUE(base::PathExists(journal)); |
659 | 668 |
660 sql::Connection::Delete(db_path()); | 669 sql::Connection::Delete(db_path()); |
661 EXPECT_FALSE(base::PathExists(db_path())); | 670 EXPECT_FALSE(base::PathExists(db_path())); |
662 EXPECT_FALSE(base::PathExists(journal)); | 671 EXPECT_FALSE(base::PathExists(journal)); |
663 } | 672 } |
664 | 673 |
665 } // namespace | 674 } // namespace |
OLD | NEW |