| Index: sql/connection_unittest.cc
|
| diff --git a/sql/connection_unittest.cc b/sql/connection_unittest.cc
|
| index 2aaeb27b33371d8249a70c85dd31d6a6e885266e..c9b5b615d2ce42961ad0cffc570b765a25db4bb2 100644
|
| --- a/sql/connection_unittest.cc
|
| +++ b/sql/connection_unittest.cc
|
| @@ -280,6 +280,84 @@ TEST_F(SQLConnectionTest, RazeLocked) {
|
| ASSERT_TRUE(db().Raze());
|
| }
|
|
|
| +// Most corruptions seen in the wild seem to happen when two pages in
|
| +// the database were not written transactionally (the transaction
|
| +// changed both, but one wasn't successfully written for some reason).
|
| +// A special case of that is when the header indicates that the
|
| +// database contains more pages than are in the file. This breaks
|
| +// things at a very basic level, verify that Raze() can handle it.
|
| +TEST_F(SQLConnectionTest, RazeShortDB) {
|
| + const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
|
| + ASSERT_TRUE(db().Execute(kCreateSql));
|
| +
|
| + db().Close();
|
| + {
|
| + file_util::ScopedFILE file(file_util::OpenFile(db_path(), "r+"));
|
| + ASSERT_TRUE(file.get() != NULL);
|
| + ASSERT_EQ(0, fseek(file.get(), 1024, SEEK_END));
|
| + ASSERT_TRUE(file_util::TruncateFile(file.get()));
|
| + }
|
| + ASSERT_TRUE(db().Open(db_path()));
|
| + ASSERT_TRUE(db().Raze());
|
| +}
|
| +
|
| +// Verify that Raze() can handle a completely empty database file.
|
| +TEST_F(SQLConnectionTest, RazeEmptyDB) {
|
| + const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
|
| + ASSERT_TRUE(db().Execute(kCreateSql));
|
| +
|
| + db().Close();
|
| + {
|
| + file_util::ScopedFILE file(file_util::OpenFile(db_path(), "r+"));
|
| + ASSERT_TRUE(file.get() != NULL);
|
| + ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
|
| + ASSERT_TRUE(file_util::TruncateFile(file.get()));
|
| + }
|
| + ASSERT_TRUE(db().Open(db_path()));
|
| + ASSERT_TRUE(db().Raze());
|
| +}
|
| +
|
| +// Verify that Raze() can handle garbage.
|
| +TEST_F(SQLConnectionTest, RazeNOTADB) {
|
| + db().Close();
|
| +
|
| + {
|
| + file_util::ScopedFILE file(file_util::OpenFile(db_path(), "w"));
|
| + ASSERT_TRUE(file.get() != NULL);
|
| +
|
| + const char* kJunk = "This is the hour of our discontent.";
|
| + fputs(kJunk, file.get());
|
| + }
|
| +
|
| + sql::ScopedErrorIgnorer ignore_errors;
|
| + ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ);
|
| + EXPECT_TRUE(db().Open(db_path()));
|
| + EXPECT_TRUE(db().Raze());
|
| + ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
|
| +}
|
| +
|
| +// Verify that Raze() can handle garbage.
|
| +TEST_F(SQLConnectionTest, RazeNOTADB2) {
|
| + const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
|
| + ASSERT_TRUE(db().Execute(kCreateSql));
|
| +
|
| + db().Close();
|
| + {
|
| + file_util::ScopedFILE file(file_util::OpenFile(db_path(), "r+"));
|
| + ASSERT_TRUE(file.get() != NULL);
|
| + ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
|
| +
|
| + const char* kJunk = "This is the hour of our discontent.";
|
| + fputs(kJunk, file.get());
|
| + }
|
| +
|
| + sql::ScopedErrorIgnorer ignore_errors;
|
| + ignore_errors.IgnoreError(SQLITE_NOTADB);
|
| + EXPECT_TRUE(db().Open(db_path()));
|
| + EXPECT_TRUE(db().Raze());
|
| + ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
|
| +}
|
| +
|
| // Basic test of RazeAndClose() operation.
|
| TEST_F(SQLConnectionTest, RazeAndClose) {
|
| const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
|
|
|