Index: components/omnibox/browser/shortcuts_database_unittest.cc |
diff --git a/components/omnibox/browser/shortcuts_database_unittest.cc b/components/omnibox/browser/shortcuts_database_unittest.cc |
index 6648d8272bb0d66f65cf652a6a456c74ad500e70..c98bdeb673397abc62695ec61d567572da25601c 100644 |
--- a/components/omnibox/browser/shortcuts_database_unittest.cc |
+++ b/components/omnibox/browser/shortcuts_database_unittest.cc |
@@ -17,6 +17,7 @@ |
#include "components/omnibox/browser/autocomplete_match_type.h" |
#include "components/omnibox/browser/shortcuts_constants.h" |
#include "sql/statement.h" |
+#include "sql/test/scoped_error_expecter.h" |
#include "sql/test/test_helpers.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "ui/base/page_transition_types.h" |
@@ -233,7 +234,7 @@ TEST(ShortcutsDatabaseMigrationTest, MigrateTableAddFillIntoEdit) { |
#endif |
base::ScopedTempDir temp_dir; |
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
- base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts1.db")); |
+ base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts.db")); |
ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, sql_path)); |
CheckV2ColumnExistence(db_path, false); |
@@ -277,7 +278,7 @@ TEST(ShortcutsDatabaseMigrationTest, MigrateV0ToV1) { |
base::FilePath sql_path = GetTestDataDir().AppendASCII("Shortcuts.v0.sql"); |
base::ScopedTempDir temp_dir; |
ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
- base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts2.db")); |
+ base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts.db")); |
ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, sql_path)); |
// Create a ShortcutsDatabase from the test database, which will migrate the |
@@ -300,3 +301,72 @@ TEST(ShortcutsDatabaseMigrationTest, MigrateV0ToV1) { |
EXPECT_TRUE(temp_dir.Delete()); |
#endif |
} |
+ |
+TEST(ShortcutsDatabaseMigrationTest, Recovery1) { |
+#if defined(OS_ANDROID) |
+ char kBasename[] = "Shortcuts.v1.sql"; |
+#else |
+ char kBasename[] = "Shortcuts.no_fill_into_edit.sql"; |
+#endif |
+ // Use the pre-v0 test file to create a test database in a temp dir. |
+ base::FilePath sql_path = GetTestDataDir().AppendASCII(kBasename); |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ base::FilePath db_path(temp_dir.path().AppendASCII("TestShortcuts.db")); |
+ ASSERT_TRUE(sql::test::CreateDatabaseFromSQL(db_path, sql_path)); |
+ |
+ // Capture the row count from the golden file before corrupting the database. |
+ const char kCountSql[] = "SELECT COUNT(*) FROM omni_box_shortcuts"; |
+ int row_count; |
+ { |
+ sql::Connection connection; |
+ ASSERT_TRUE(connection.Open(db_path)); |
+ sql::Statement statement(connection.GetUniqueStatement(kCountSql)); |
+ ASSERT_TRUE(statement.is_valid()); |
+ ASSERT_TRUE(statement.Step()); |
+ row_count = statement.ColumnInt(0); |
+ } |
+ |
+ // Break the database. |
+ ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path)); |
+ |
+ // Verify that the database is broken. The corruption will prevent reading |
+ // the schema, causing the prepared statement to not compile. |
+ { |
+ sql::test::ScopedErrorExpecter expecter; |
+ expecter.ExpectError(SQLITE_CORRUPT); |
+ |
+ sql::Connection connection; |
+ ASSERT_TRUE(connection.Open(db_path)); |
+ sql::Statement statement(connection.GetUniqueStatement(kCountSql)); |
+ ASSERT_FALSE(statement.is_valid()); |
+ |
+ ASSERT_TRUE(expecter.SawExpectedErrors()); |
+ } |
+ |
+ // The sql::Connection::Open() called by ShortcutsDatabase::Init() will hit |
+ // the corruption, the error callback will recover and poison the database, |
+ // then Open() will retry successfully, allowing Init() to succeed. |
+ { |
+ sql::test::ScopedErrorExpecter expecter; |
+ expecter.ExpectError(SQLITE_CORRUPT); |
+ |
+ scoped_refptr<ShortcutsDatabase> db(new ShortcutsDatabase(db_path)); |
+ ASSERT_TRUE(db->Init()); |
+ |
+ ASSERT_TRUE(expecter.SawExpectedErrors()); |
+ } |
+ |
+ CheckV2ColumnExistence(db_path, true); |
+ |
+ // The previously-broken statement works and all of the data should have been |
+ // recovered. |
+ { |
+ sql::Connection connection; |
+ ASSERT_TRUE(connection.Open(db_path)); |
+ sql::Statement statement(connection.GetUniqueStatement(kCountSql)); |
+ ASSERT_TRUE(statement.is_valid()); |
+ ASSERT_TRUE(statement.Step()); |
+ EXPECT_EQ(row_count, statement.ColumnInt(0)); |
+ } |
+} |