OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "sql/recovery.h" | 5 #include "sql/recovery.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <string> | 10 #include <string> |
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 ASSERT_TRUE(expecter.SawExpectedErrors()); | 827 ASSERT_TRUE(expecter.SawExpectedErrors()); |
828 } | 828 } |
829 | 829 |
830 // Recovery poisoned the handle, must re-open. | 830 // Recovery poisoned the handle, must re-open. |
831 db().Close(); | 831 db().Close(); |
832 ASSERT_TRUE(Reopen()); | 832 ASSERT_TRUE(Reopen()); |
833 | 833 |
834 EXPECT_EQ("", GetSchema(&db())); | 834 EXPECT_EQ("", GetSchema(&db())); |
835 } | 835 } |
836 | 836 |
| 837 // Allow callers to validate the database between recovery and commit. |
| 838 TEST_F(SQLRecoveryTest, BeginRecoverDatabase) { |
| 839 // Create a table with a broken index. |
| 840 ASSERT_TRUE(db().Execute("CREATE TABLE t (id INTEGER PRIMARY KEY, c TEXT)")); |
| 841 ASSERT_TRUE(db().Execute("CREATE UNIQUE INDEX t_id ON t (id)")); |
| 842 ASSERT_TRUE(db().Execute("INSERT INTO t VALUES (1, 'hello world')")); |
| 843 ASSERT_TRUE(db().Execute("INSERT INTO t VALUES (2, 'testing')")); |
| 844 ASSERT_TRUE(db().Execute("INSERT INTO t VALUES (3, 'nope')")); |
| 845 |
| 846 // Inject corruption into the index. |
| 847 db().Close(); |
| 848 const char kDeleteSql[] = "DELETE FROM t WHERE id = 3"; |
| 849 ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path(), "t_id", kDeleteSql)); |
| 850 ASSERT_TRUE(Reopen()); |
| 851 |
| 852 // id as read from index. |
| 853 const char kSelectIndexIdSql[] = "SELECT id FROM t INDEXED BY t_id"; |
| 854 EXPECT_EQ("1,2,3", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ",")); |
| 855 |
| 856 // id as read from table. |
| 857 const char kSelectTableIdSql[] = "SELECT id FROM t NOT INDEXED"; |
| 858 EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ",")); |
| 859 |
| 860 // Run recovery code, then rollback. Database remains the same. |
| 861 { |
| 862 std::unique_ptr<sql::Recovery> recovery = |
| 863 sql::Recovery::BeginRecoverDatabase(&db(), db_path()); |
| 864 ASSERT_TRUE(recovery); |
| 865 sql::Recovery::Rollback(std::move(recovery)); |
| 866 } |
| 867 db().Close(); |
| 868 ASSERT_TRUE(Reopen()); |
| 869 EXPECT_EQ("1,2,3", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ",")); |
| 870 EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ",")); |
| 871 |
| 872 // Run recovery code, then commit. The failing row is dropped. |
| 873 { |
| 874 std::unique_ptr<sql::Recovery> recovery = |
| 875 sql::Recovery::BeginRecoverDatabase(&db(), db_path()); |
| 876 ASSERT_TRUE(recovery); |
| 877 ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); |
| 878 } |
| 879 db().Close(); |
| 880 ASSERT_TRUE(Reopen()); |
| 881 EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ",")); |
| 882 EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ",")); |
| 883 } |
| 884 |
837 // Test histograms recorded when the invalid database cannot be attached. | 885 // Test histograms recorded when the invalid database cannot be attached. |
838 TEST_F(SQLRecoveryTest, AttachFailure) { | 886 TEST_F(SQLRecoveryTest, AttachFailure) { |
839 // Create a valid database, then write junk over the header. This should lead | 887 // Create a valid database, then write junk over the header. This should lead |
840 // to SQLITE_NOTADB, which will cause ATTACH to fail. | 888 // to SQLITE_NOTADB, which will cause ATTACH to fail. |
841 ASSERT_TRUE(db().Execute("CREATE TABLE x (t TEXT)")); | 889 ASSERT_TRUE(db().Execute("CREATE TABLE x (t TEXT)")); |
842 ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test')")); | 890 ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test')")); |
843 db().Close(); | 891 db().Close(); |
844 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE); | 892 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE); |
845 | 893 |
846 const char kEventHistogramName[] = "Sqlite.RecoveryEvents"; | 894 const char kEventHistogramName[] = "Sqlite.RecoveryEvents"; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
933 EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 1024, "1024", 1024, "1024")); | 981 EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 1024, "1024", 1024, "1024")); |
934 | 982 |
935 // Databases with no page size specified should recover with the new default | 983 // Databases with no page size specified should recover with the new default |
936 // page size. 2k has never been the default page size. | 984 // page size. 2k has never been the default page size. |
937 ASSERT_NE("2048", default_page_size); | 985 ASSERT_NE("2048", default_page_size); |
938 EXPECT_NO_FATAL_FAILURE( | 986 EXPECT_NO_FATAL_FAILURE( |
939 TestPageSize(db_path(), 2048, "2048", 0, default_page_size)); | 987 TestPageSize(db_path(), 2048, "2048", 0, default_page_size)); |
940 } | 988 } |
941 | 989 |
942 } // namespace | 990 } // namespace |
OLD | NEW |