| Index: sql/recovery_unittest.cc
|
| diff --git a/sql/recovery_unittest.cc b/sql/recovery_unittest.cc
|
| index 111a610450a169923f2fab7165225f39b9a015f6..752688225d9729105fcf9670a6518e13bf7a19c8 100644
|
| --- a/sql/recovery_unittest.cc
|
| +++ b/sql/recovery_unittest.cc
|
| @@ -834,6 +834,54 @@ TEST_F(SQLRecoveryTest, RecoverDatabaseDelete) {
|
| EXPECT_EQ("", GetSchema(&db()));
|
| }
|
|
|
| +// Allow callers to validate the database between recovery and commit.
|
| +TEST_F(SQLRecoveryTest, BeginRecoverDatabase) {
|
| + // Create a table with a broken index.
|
| + ASSERT_TRUE(db().Execute("CREATE TABLE t (id INTEGER PRIMARY KEY, c TEXT)"));
|
| + ASSERT_TRUE(db().Execute("CREATE UNIQUE INDEX t_id ON t (id)"));
|
| + ASSERT_TRUE(db().Execute("INSERT INTO t VALUES (1, 'hello world')"));
|
| + ASSERT_TRUE(db().Execute("INSERT INTO t VALUES (2, 'testing')"));
|
| + ASSERT_TRUE(db().Execute("INSERT INTO t VALUES (3, 'nope')"));
|
| +
|
| + // Inject corruption into the index.
|
| + db().Close();
|
| + const char kDeleteSql[] = "DELETE FROM t WHERE id = 3";
|
| + ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path(), "t_id", kDeleteSql));
|
| + ASSERT_TRUE(Reopen());
|
| +
|
| + // id as read from index.
|
| + const char kSelectIndexIdSql[] = "SELECT id FROM t INDEXED BY t_id";
|
| + EXPECT_EQ("1,2,3", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ","));
|
| +
|
| + // id as read from table.
|
| + const char kSelectTableIdSql[] = "SELECT id FROM t NOT INDEXED";
|
| + EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ","));
|
| +
|
| + // Run recovery code, then rollback. Database remains the same.
|
| + {
|
| + std::unique_ptr<sql::Recovery> recovery =
|
| + sql::Recovery::BeginRecoverDatabase(&db(), db_path());
|
| + ASSERT_TRUE(recovery);
|
| + sql::Recovery::Rollback(std::move(recovery));
|
| + }
|
| + db().Close();
|
| + ASSERT_TRUE(Reopen());
|
| + EXPECT_EQ("1,2,3", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ","));
|
| + EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ","));
|
| +
|
| + // Run recovery code, then commit. The failing row is dropped.
|
| + {
|
| + std::unique_ptr<sql::Recovery> recovery =
|
| + sql::Recovery::BeginRecoverDatabase(&db(), db_path());
|
| + ASSERT_TRUE(recovery);
|
| + ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery)));
|
| + }
|
| + db().Close();
|
| + ASSERT_TRUE(Reopen());
|
| + EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ","));
|
| + EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ","));
|
| +}
|
| +
|
| // Test histograms recorded when the invalid database cannot be attached.
|
| TEST_F(SQLRecoveryTest, AttachFailure) {
|
| // Create a valid database, then write junk over the header. This should lead
|
|
|