From 49a903ab69d4929d3b1ac84fa8573c6dadedf049 Mon Sep 17 00:00:00 2001 From: Victor Costan Date: Fri, 7 May 2021 22:21:00 +0000 Subject: [PATCH] Reland "sql: Remove SQLTestBase." This is a reland of 525b30ab9b994b6cb8a235984a7bbc3fbab9eb9c This reland removes the call to GetDBOptions() from the DatabaseTest constructor, which was flagged as undefined behavior by the ubsan-vptr bot. sql::Database construction is deferred to the SetUp() method by turning the test's sql::Database member into a std::unique_ptr. Original change's description: > sql: Remove SQLTestBase. > > Change-Id: I87bf9499ef590b006660d3b8ab305b0192ec405c > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2866306 > Auto-Submit: Victor Costan > Commit-Queue: Ayu Ishii > Reviewed-by: Ayu Ishii > Cr-Commit-Position: refs/heads/master@{#879443} Change-Id: Ie83bf28eaebb88883b9eb37a7d8407e8bfc619ad Cq-Do-Not-Cancel-Tryjobs: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2878638 Reviewed-by: Ayu Ishii Commit-Queue: Victor Costan Cr-Commit-Position: refs/heads/master@{#880595} --- sql/BUILD.gn | 2 - sql/database_unittest.cc | 910 ++++++++++++----------- sql/meta_table_unittest.cc | 120 +-- sql/recover_module/module_unittest.cc | 409 +++++----- sql/recovery_unittest.cc | 562 +++++++------- sql/sql_memory_dump_provider_unittest.cc | 32 +- sql/sqlite_features_unittest.cc | 172 ++--- sql/statement_unittest.cc | 53 +- sql/test/sql_test_base.cc | 66 -- sql/test/sql_test_base.h | 77 -- sql/transaction_unittest.cc | 68 +- 11 files changed, 1239 insertions(+), 1232 deletions(-) delete mode 100644 sql/test/sql_test_base.cc delete mode 100644 sql/test/sql_test_base.h diff --git a/sql/BUILD.gn b/sql/BUILD.gn index c7fd00f99505ac..e589f9a0994369 100644 --- a/sql/BUILD.gn +++ b/sql/BUILD.gn @@ -121,8 +121,6 @@ test("sql_unittests") { "test/paths.cc", "test/paths.h", "test/run_all_unittests.cc", - "test/sql_test_base.cc", - "test/sql_test_base.h", "test/sql_test_suite.cc", "test/sql_test_suite.h", "transaction_unittest.cc", diff --git a/sql/database_unittest.cc b/sql/database_unittest.cc index 9ae6a176e67b81..c2d65167d967db 100644 --- a/sql/database_unittest.cc +++ b/sql/database_unittest.cc @@ -2,21 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "sql/database.h" + #include #include #include "base/bind.h" #include "base/files/file_util.h" -#include "base/files/scoped_file.h" #include "base/files/scoped_temp_dir.h" #include "base/logging.h" -#include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/test/gtest_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/trace_event/process_memory_dump.h" #include "build/build_config.h" -#include "sql/database.h" #include "sql/database_memory_dump_provider.h" #include "sql/meta_table.h" #include "sql/sql_features.h" @@ -24,7 +23,6 @@ #include "sql/test/database_test_peer.h" #include "sql/test/error_callback_support.h" #include "sql/test/scoped_error_expecter.h" -#include "sql/test/sql_test_base.h" #include "sql/test/test_helpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/sqlite/sqlite3.h" @@ -37,9 +35,9 @@ using sql::test::ExecuteWithResult; // Helper to return the count of items in sqlite_master. Return -1 in // case of error. -int SqliteMasterCount(sql::Database* db) { +int SqliteMasterCount(Database* db) { const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master"; - sql::Statement s(db->GetUniqueStatement(kMasterCount)); + Statement s(db->GetUniqueStatement(kMasterCount)); return s.Step() ? s.ColumnInt(0) : -1; } @@ -48,7 +46,7 @@ int SqliteMasterCount(sql::Database* db) { // explicitly having the ref count live longer than the object. class RefCounter { public: - RefCounter(size_t* counter) : counter_(counter) { (*counter_)++; } + explicit RefCounter(size_t* counter) : counter_(counter) { (*counter_)++; } RefCounter(const RefCounter& other) : counter_(other.counter_) { (*counter_)++; } @@ -61,24 +59,24 @@ class RefCounter { }; // Empty callback for implementation of ErrorCallbackSetHelper(). -void IgnoreErrorCallback(int error, sql::Statement* stmt) {} +void IgnoreErrorCallback(int error, Statement* stmt) {} -void ErrorCallbackSetHelper(sql::Database* db, +void ErrorCallbackSetHelper(Database* db, size_t* counter, const RefCounter& r, int error, - sql::Statement* stmt) { + Statement* stmt) { // The ref count should not go to zero when changing the callback. EXPECT_GT(*counter, 0u); db->set_error_callback(base::BindRepeating(&IgnoreErrorCallback)); EXPECT_GT(*counter, 0u); } -void ErrorCallbackResetHelper(sql::Database* db, +void ErrorCallbackResetHelper(Database* db, size_t* counter, const RefCounter& r, int error, - sql::Statement* stmt) { + Statement* stmt) { // The ref count should not go to zero when clearing the callback. EXPECT_GT(*counter, 0u); db->reset_error_callback(); @@ -86,10 +84,10 @@ void ErrorCallbackResetHelper(sql::Database* db, } // Handle errors by blowing away the database. -void RazeErrorCallback(sql::Database* db, +void RazeErrorCallback(Database* db, int expected_error, int error, - sql::Statement* stmt) { + Statement* stmt) { // Nothing here needs extended errors at this time. EXPECT_EQ(expected_error, expected_error & 0xff); EXPECT_EQ(expected_error, error & 0xff); @@ -106,23 +104,36 @@ class ScopedUmaskSetter { } ~ScopedUmaskSetter() { umask(old_umask_); } + ScopedUmaskSetter(const ScopedUmaskSetter&) = delete; + ScopedUmaskSetter& operator=(const ScopedUmaskSetter&) = delete; + private: mode_t old_umask_; - DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); }; #endif // defined(OS_POSIX) } // namespace // We use the parameter to run all tests with WAL mode on and off. -class SQLDatabaseTest : public SQLTestBase, +class SQLDatabaseTest : public testing::Test, public testing::WithParamInterface { public: - SQLDatabaseTest() : SQLTestBase(GetDBOptions()) {} - explicit SQLDatabaseTest(DatabaseOptions options) : SQLTestBase(options) {} + enum class OverwriteType { + kTruncate, + kOverwrite, + }; + + ~SQLDatabaseTest() override = default; + + void SetUp() override { + db_ = std::make_unique(GetDBOptions()); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + db_path_ = temp_dir_.GetPath().AppendASCII("database_test.sqlite"); + ASSERT_TRUE(db_->Open(db_path_)); + } - sql::DatabaseOptions GetDBOptions() { - sql::DatabaseOptions options; + DatabaseOptions GetDBOptions() { + DatabaseOptions options; options.wal_mode = IsWALEnabled(); // TODO(crbug.com/1120969): Remove after switching to exclusive mode on by // default. @@ -135,186 +146,211 @@ class SQLDatabaseTest : public SQLTestBase, #endif // defined(OS_FUCHSIA) return options; } + bool IsWALEnabled() { return GetParam(); } + + bool TruncateDatabase() { + base::File file(db_path_, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + return file.SetLength(0); + } + + bool OverwriteDatabaseHeader(OverwriteType type) { + base::File file(db_path_, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + if (type == OverwriteType::kTruncate) { + if (!file.SetLength(0)) + return false; + } + + static constexpr char kText[] = "Now is the winter of our discontent."; + constexpr int kTextBytes = sizeof(kText) - 1; + return file.Write(0, kText, kTextBytes) == kTextBytes; + } + + protected: + base::ScopedTempDir temp_dir_; + base::FilePath db_path_; + std::unique_ptr db_; }; TEST_P(SQLDatabaseTest, Execute) { // Valid statement should return true. - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); - EXPECT_EQ(SQLITE_OK, db().GetErrorCode()); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); + EXPECT_EQ(SQLITE_OK, db_->GetErrorCode()); // Invalid statement should fail. ASSERT_EQ(SQLITE_ERROR, - db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b")); - EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode()); + db_->ExecuteAndReturnErrorCode("CREATE TAB foo (a, b")); + EXPECT_EQ(SQLITE_ERROR, db_->GetErrorCode()); } TEST_P(SQLDatabaseTest, ExecuteWithErrorCode) { ASSERT_EQ(SQLITE_OK, - db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)")); - ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE")); - ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode( + db_->ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)")); + ASSERT_EQ(SQLITE_ERROR, db_->ExecuteAndReturnErrorCode("CREATE TABLE TABLE")); + ASSERT_EQ(SQLITE_ERROR, db_->ExecuteAndReturnErrorCode( "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)")); } TEST_P(SQLDatabaseTest, CachedStatement) { - sql::StatementID id1 = SQL_FROM_HERE; - sql::StatementID id2 = SQL_FROM_HERE; + StatementID id1 = SQL_FROM_HERE; + StatementID id2 = SQL_FROM_HERE; static const char kId1Sql[] = "SELECT a FROM foo"; static const char kId2Sql[] = "SELECT b FROM foo"; - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); - ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)")); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_->Execute("INSERT INTO foo(a, b) VALUES (12, 13)")); sqlite3_stmt* raw_id1_statement; sqlite3_stmt* raw_id2_statement; { - scoped_refptr ref_from_id1 = - db().GetCachedStatement(id1, kId1Sql); + scoped_refptr ref_from_id1 = + db_->GetCachedStatement(id1, kId1Sql); raw_id1_statement = ref_from_id1->stmt(); - sql::Statement from_id1(std::move(ref_from_id1)); + Statement from_id1(std::move(ref_from_id1)); ASSERT_TRUE(from_id1.is_valid()); ASSERT_TRUE(from_id1.Step()); EXPECT_EQ(12, from_id1.ColumnInt(0)); - scoped_refptr ref_from_id2 = - db().GetCachedStatement(id2, kId2Sql); + scoped_refptr ref_from_id2 = + db_->GetCachedStatement(id2, kId2Sql); raw_id2_statement = ref_from_id2->stmt(); EXPECT_NE(raw_id1_statement, raw_id2_statement); - sql::Statement from_id2(std::move(ref_from_id2)); + Statement from_id2(std::move(ref_from_id2)); ASSERT_TRUE(from_id2.is_valid()); ASSERT_TRUE(from_id2.Step()); EXPECT_EQ(13, from_id2.ColumnInt(0)); } { - scoped_refptr ref_from_id1 = - db().GetCachedStatement(id1, kId1Sql); + scoped_refptr ref_from_id1 = + db_->GetCachedStatement(id1, kId1Sql); EXPECT_EQ(raw_id1_statement, ref_from_id1->stmt()) << "statement was not cached"; - sql::Statement from_id1(std::move(ref_from_id1)); + Statement from_id1(std::move(ref_from_id1)); ASSERT_TRUE(from_id1.is_valid()); ASSERT_TRUE(from_id1.Step()) << "cached statement was not reset"; EXPECT_EQ(12, from_id1.ColumnInt(0)); - scoped_refptr ref_from_id2 = - db().GetCachedStatement(id2, kId2Sql); + scoped_refptr ref_from_id2 = + db_->GetCachedStatement(id2, kId2Sql); EXPECT_EQ(raw_id2_statement, ref_from_id2->stmt()) << "statement was not cached"; - sql::Statement from_id2(std::move(ref_from_id2)); + Statement from_id2(std::move(ref_from_id2)); ASSERT_TRUE(from_id2.is_valid()); ASSERT_TRUE(from_id2.Step()) << "cached statement was not reset"; EXPECT_EQ(13, from_id2.ColumnInt(0)); } - EXPECT_DCHECK_DEATH(db().GetCachedStatement(id1, kId2Sql)) + EXPECT_DCHECK_DEATH(db_->GetCachedStatement(id1, kId2Sql)) << "Using a different SQL with the same statement ID should DCHECK"; - EXPECT_DCHECK_DEATH(db().GetCachedStatement(id2, kId1Sql)) + EXPECT_DCHECK_DEATH(db_->GetCachedStatement(id2, kId1Sql)) << "Using a different SQL with the same statement ID should DCHECK"; } TEST_P(SQLDatabaseTest, IsSQLValidTest) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); - ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo")); - ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo")); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_->IsSQLValid("SELECT a FROM foo")); + ASSERT_FALSE(db_->IsSQLValid("SELECT no_exist FROM foo")); } TEST_P(SQLDatabaseTest, DoesTableExist) { - EXPECT_FALSE(db().DoesTableExist("foo")); - EXPECT_FALSE(db().DoesTableExist("foo_index")); + EXPECT_FALSE(db_->DoesTableExist("foo")); + EXPECT_FALSE(db_->DoesTableExist("foo_index")); - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); - ASSERT_TRUE(db().Execute("CREATE INDEX foo_index ON foo (a)")); - EXPECT_TRUE(db().DoesTableExist("foo")); - EXPECT_FALSE(db().DoesTableExist("foo_index")); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_->Execute("CREATE INDEX foo_index ON foo (a)")); + EXPECT_TRUE(db_->DoesTableExist("foo")); + EXPECT_FALSE(db_->DoesTableExist("foo_index")); // DoesTableExist() is case-sensitive. - EXPECT_FALSE(db().DoesTableExist("Foo")); - EXPECT_FALSE(db().DoesTableExist("FOO")); + EXPECT_FALSE(db_->DoesTableExist("Foo")); + EXPECT_FALSE(db_->DoesTableExist("FOO")); } TEST_P(SQLDatabaseTest, DoesIndexExist) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); - EXPECT_FALSE(db().DoesIndexExist("foo")); - EXPECT_FALSE(db().DoesIndexExist("foo_ubdex")); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); + EXPECT_FALSE(db_->DoesIndexExist("foo")); + EXPECT_FALSE(db_->DoesIndexExist("foo_ubdex")); - ASSERT_TRUE(db().Execute("CREATE INDEX foo_index ON foo (a)")); - EXPECT_TRUE(db().DoesIndexExist("foo_index")); - EXPECT_FALSE(db().DoesIndexExist("foo")); + ASSERT_TRUE(db_->Execute("CREATE INDEX foo_index ON foo (a)")); + EXPECT_TRUE(db_->DoesIndexExist("foo_index")); + EXPECT_FALSE(db_->DoesIndexExist("foo")); // DoesIndexExist() is case-sensitive. - EXPECT_FALSE(db().DoesIndexExist("Foo_index")); - EXPECT_FALSE(db().DoesIndexExist("Foo_Index")); - EXPECT_FALSE(db().DoesIndexExist("FOO_INDEX")); + EXPECT_FALSE(db_->DoesIndexExist("Foo_index")); + EXPECT_FALSE(db_->DoesIndexExist("Foo_Index")); + EXPECT_FALSE(db_->DoesIndexExist("FOO_INDEX")); } TEST_P(SQLDatabaseTest, DoesViewExist) { - EXPECT_FALSE(db().DoesViewExist("voo")); - ASSERT_TRUE(db().Execute("CREATE VIEW voo (a) AS SELECT 1")); - EXPECT_FALSE(db().DoesIndexExist("voo")); - EXPECT_FALSE(db().DoesTableExist("voo")); - EXPECT_TRUE(db().DoesViewExist("voo")); + EXPECT_FALSE(db_->DoesViewExist("voo")); + ASSERT_TRUE(db_->Execute("CREATE VIEW voo (a) AS SELECT 1")); + EXPECT_FALSE(db_->DoesIndexExist("voo")); + EXPECT_FALSE(db_->DoesTableExist("voo")); + EXPECT_TRUE(db_->DoesViewExist("voo")); // DoesTableExist() is case-sensitive. - EXPECT_FALSE(db().DoesViewExist("Voo")); - EXPECT_FALSE(db().DoesViewExist("VOO")); + EXPECT_FALSE(db_->DoesViewExist("Voo")); + EXPECT_FALSE(db_->DoesViewExist("VOO")); } TEST_P(SQLDatabaseTest, DoesColumnExist) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); - EXPECT_FALSE(db().DoesColumnExist("foo", "bar")); - EXPECT_TRUE(db().DoesColumnExist("foo", "a")); + EXPECT_FALSE(db_->DoesColumnExist("foo", "bar")); + EXPECT_TRUE(db_->DoesColumnExist("foo", "a")); - ASSERT_FALSE(db().DoesTableExist("bar")); - EXPECT_FALSE(db().DoesColumnExist("bar", "b")); + ASSERT_FALSE(db_->DoesTableExist("bar")); + EXPECT_FALSE(db_->DoesColumnExist("bar", "b")); // SQLite resolves table/column names without case sensitivity. - EXPECT_TRUE(db().DoesColumnExist("FOO", "A")); - EXPECT_TRUE(db().DoesColumnExist("FOO", "a")); - EXPECT_TRUE(db().DoesColumnExist("foo", "A")); + EXPECT_TRUE(db_->DoesColumnExist("FOO", "A")); + EXPECT_TRUE(db_->DoesColumnExist("FOO", "a")); + EXPECT_TRUE(db_->DoesColumnExist("foo", "A")); } TEST_P(SQLDatabaseTest, GetLastInsertRowId) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)")); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)")); - ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); + ASSERT_TRUE(db_->Execute("INSERT INTO foo (value) VALUES (12)")); // Last insert row ID should be valid. - int64_t row = db().GetLastInsertRowId(); + int64_t row = db_->GetLastInsertRowId(); EXPECT_LT(0, row); // It should be the primary key of the row we just inserted. - sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?")); + Statement s(db_->GetUniqueStatement("SELECT value FROM foo WHERE id=?")); s.BindInt64(0, row); ASSERT_TRUE(s.Step()); EXPECT_EQ(12, s.ColumnInt(0)); } TEST_P(SQLDatabaseTest, Rollback) { - ASSERT_TRUE(db().BeginTransaction()); - ASSERT_TRUE(db().BeginTransaction()); - EXPECT_EQ(2, db().transaction_nesting()); - db().RollbackTransaction(); - EXPECT_FALSE(db().CommitTransaction()); - EXPECT_TRUE(db().BeginTransaction()); + ASSERT_TRUE(db_->BeginTransaction()); + ASSERT_TRUE(db_->BeginTransaction()); + EXPECT_EQ(2, db_->transaction_nesting()); + db_->RollbackTransaction(); + EXPECT_FALSE(db_->CommitTransaction()); + EXPECT_TRUE(db_->BeginTransaction()); } // Test the scoped error expecter by attempting to insert a duplicate // value into an index. TEST_P(SQLDatabaseTest, ScopedErrorExpecter) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute("INSERT INTO foo (id) VALUES (12)")); { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CONSTRAINT); - ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); + ASSERT_FALSE(db_->Execute("INSERT INTO foo (id) VALUES (12)")); ASSERT_TRUE(expecter.SawExpectedErrors()); } } @@ -323,36 +359,36 @@ TEST_P(SQLDatabaseTest, ScopedErrorExpecter) { // with ScopedErrorExpecter. TEST_P(SQLDatabaseTest, ScopedIgnoreUntracked) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_FALSE(db().DoesTableExist("bar")); - ASSERT_TRUE(db().DoesTableExist("foo")); - ASSERT_TRUE(db().DoesColumnExist("foo", "id")); - db().Close(); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_FALSE(db_->DoesTableExist("bar")); + ASSERT_TRUE(db_->DoesTableExist("foo")); + ASSERT_TRUE(db_->DoesColumnExist("foo", "id")); + db_->Close(); // Corrupt the database so that nothing works, including PRAGMAs. - ASSERT_TRUE(CorruptSizeInHeaderOfDB()); + ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path_)); { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CORRUPT); - ASSERT_TRUE(db().Open(db_path())); - ASSERT_FALSE(db().DoesTableExist("bar")); - ASSERT_FALSE(db().DoesTableExist("foo")); - ASSERT_FALSE(db().DoesColumnExist("foo", "id")); + ASSERT_TRUE(db_->Open(db_path_)); + ASSERT_FALSE(db_->DoesTableExist("bar")); + ASSERT_FALSE(db_->DoesTableExist("foo")); + ASSERT_FALSE(db_->DoesColumnExist("foo", "id")); ASSERT_TRUE(expecter.SawExpectedErrors()); } } TEST_P(SQLDatabaseTest, ErrorCallback) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute("INSERT INTO foo (id) VALUES (12)")); int error = SQLITE_OK; { - sql::ScopedErrorCallback sec( - &db(), base::BindRepeating(&sql::CaptureErrorCallback, &error)); - EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); + ScopedErrorCallback sec(db_.get(), + base::BindRepeating(&CaptureErrorCallback, &error)); + EXPECT_FALSE(db_->Execute("INSERT INTO foo (id) VALUES (12)")); // Later versions of SQLite throw SQLITE_CONSTRAINT_UNIQUE. The specific // sub-error isn't really important. @@ -364,7 +400,7 @@ TEST_P(SQLDatabaseTest, ErrorCallback) { error = SQLITE_OK; sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CONSTRAINT); - ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); + ASSERT_FALSE(db_->Execute("INSERT INTO foo (id) VALUES (12)")); ASSERT_TRUE(expecter.SawExpectedErrors()); EXPECT_EQ(SQLITE_OK, error); } @@ -380,34 +416,34 @@ TEST_P(SQLDatabaseTest, ErrorCallback) { // live. { size_t count = 0; - sql::ScopedErrorCallback sec( - &db(), base::BindRepeating(&ErrorCallbackSetHelper, &db(), &count, - RefCounter(&count))); + ScopedErrorCallback sec( + db_.get(), base::BindRepeating(&ErrorCallbackSetHelper, db_.get(), + &count, RefCounter(&count))); - EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); + EXPECT_FALSE(db_->Execute("INSERT INTO foo (id) VALUES (12)")); } // Same test, but reset_error_callback() case. { size_t count = 0; - sql::ScopedErrorCallback sec( - &db(), base::BindRepeating(&ErrorCallbackResetHelper, &db(), &count, - RefCounter(&count))); + ScopedErrorCallback sec( + db_.get(), base::BindRepeating(&ErrorCallbackResetHelper, db_.get(), + &count, RefCounter(&count))); - EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); + EXPECT_FALSE(db_->Execute("INSERT INTO foo (id) VALUES (12)")); } } -// Test that sql::Database::Raze() results in a database without the +// Test that Database::Raze() results in a database without the // tables from the original database. TEST_P(SQLDatabaseTest, Raze) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute("INSERT INTO foo (value) VALUES (12)")); int pragma_auto_vacuum = 0; { - sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); + Statement s(db_->GetUniqueStatement("PRAGMA auto_vacuum")); ASSERT_TRUE(s.Step()); pragma_auto_vacuum = s.ColumnInt(0); ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1); @@ -417,13 +453,13 @@ TEST_P(SQLDatabaseTest, Raze) { const int kExpectedPageCount = 2 + pragma_auto_vacuum; { - sql::Statement s(db().GetUniqueStatement("PRAGMA page_count")); + Statement s(db_->GetUniqueStatement("PRAGMA page_count")); ASSERT_TRUE(s.Step()); EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0)); } { - sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master")); + Statement s(db_->GetUniqueStatement("SELECT * FROM sqlite_master")); ASSERT_TRUE(s.Step()); EXPECT_EQ("table", s.ColumnString(0)); EXPECT_EQ("foo", s.ColumnString(1)); @@ -433,18 +469,18 @@ TEST_P(SQLDatabaseTest, Raze) { EXPECT_EQ(kCreateSql, s.ColumnString(4)); } - ASSERT_TRUE(db().Raze()); + ASSERT_TRUE(db_->Raze()); { - sql::Statement s(db().GetUniqueStatement("PRAGMA page_count")); + Statement s(db_->GetUniqueStatement("PRAGMA page_count")); ASSERT_TRUE(s.Step()); EXPECT_EQ(1, s.ColumnInt(0)); } - ASSERT_EQ(0, SqliteMasterCount(&db())); + ASSERT_EQ(0, SqliteMasterCount(db_.get())); { - sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); + Statement s(db_->GetUniqueStatement("PRAGMA auto_vacuum")); ASSERT_TRUE(s.Step()); // The new database has the same auto_vacuum as a fresh database. EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0)); @@ -466,8 +502,8 @@ void TestPageSize(const base::FilePath& db_prefix, const base::FilePath db_path = db_prefix.InsertBeforeExtensionASCII( base::NumberToString(initial_page_size)); - sql::Database::Delete(db_path); - sql::Database db({.page_size = initial_page_size}); + Database::Delete(db_path); + Database db({.page_size = initial_page_size}); ASSERT_TRUE(db.Open(db_path)); ASSERT_TRUE(db.Execute(kCreateSql)); ASSERT_TRUE(db.Execute(kInsertSql1)); @@ -477,7 +513,7 @@ void TestPageSize(const base::FilePath& db_prefix, db.Close(); // Re-open the database while setting a new |options.page_size| in the object. - sql::Database razed_db({.page_size = final_page_size}); + Database razed_db({.page_size = final_page_size}); ASSERT_TRUE(razed_db.Open(db_path)); // Raze will use the page size set in the connection object, which may not // match the file's page size. @@ -495,29 +531,29 @@ void TestPageSize(const base::FilePath& db_prefix, EXPECT_EQ("1", ExecuteWithResult(&razed_db, "PRAGMA page_count")); } -// Verify that sql::Recovery maintains the page size, and the virtual table +// Verify that Recovery maintains the page size, and the virtual table // works with page sizes other than SQLite's default. Also verify the case // where the default page size has changed. TEST_P(SQLDatabaseTest, RazePageSize) { const std::string default_page_size = - ExecuteWithResult(&db(), "PRAGMA page_size"); + ExecuteWithResult(db_.get(), "PRAGMA page_size"); // Sync uses 32k pages. EXPECT_NO_FATAL_FAILURE( - TestPageSize(db_path(), 32768, "32768", 32768, "32768")); + TestPageSize(db_path_, 32768, "32768", 32768, "32768")); // Many clients use 4k pages. This is the SQLite default after 3.12.0. - EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 4096, "4096", 4096, "4096")); + EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path_, 4096, "4096", 4096, "4096")); // 1k is the default page size before 3.12.0. - EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 1024, "1024", 1024, "1024")); + EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path_, 1024, "1024", 1024, "1024")); - EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 2048, "2048", 4096, "4096")); + EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path_, 2048, "2048", 4096, "4096")); // Databases with no page size specified should result in the default // page size. 2k has never been the default page size. ASSERT_NE("2048", default_page_size); - EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 2048, "2048", + EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path_, 2048, "2048", DatabaseOptions::kDefaultPageSize, default_page_size)); } @@ -525,15 +561,15 @@ TEST_P(SQLDatabaseTest, RazePageSize) { // Test that Raze() results are seen in other connections. TEST_P(SQLDatabaseTest, RazeMultiple) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute(kCreateSql)); - sql::Database other_db(GetDBOptions()); - ASSERT_TRUE(other_db.Open(db_path())); + Database other_db(GetDBOptions()); + ASSERT_TRUE(other_db.Open(db_path_)); // Check that the second connection sees the table. ASSERT_EQ(1, SqliteMasterCount(&other_db)); - ASSERT_TRUE(db().Raze()); + ASSERT_TRUE(db_->Raze()); // The second connection sees the updated database. ASSERT_EQ(0, SqliteMasterCount(&other_db)); @@ -541,26 +577,26 @@ TEST_P(SQLDatabaseTest, RazeMultiple) { TEST_P(SQLDatabaseTest, RazeLocked) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute(kCreateSql)); // Open a transaction and write some data in a second connection. // This will acquire a PENDING or EXCLUSIVE transaction, which will // cause the raze to fail. - sql::Database other_db(GetDBOptions()); - ASSERT_TRUE(other_db.Open(db_path())); + Database other_db(GetDBOptions()); + ASSERT_TRUE(other_db.Open(db_path_)); ASSERT_TRUE(other_db.BeginTransaction()); const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')"; ASSERT_TRUE(other_db.Execute(kInsertSql)); - ASSERT_FALSE(db().Raze()); + ASSERT_FALSE(db_->Raze()); // Works after COMMIT. ASSERT_TRUE(other_db.CommitTransaction()); - ASSERT_TRUE(db().Raze()); + ASSERT_TRUE(db_->Raze()); // Re-create the database. - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute(kInsertSql)); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute(kInsertSql)); // An unfinished read transaction in the other connection also // blocks raze. @@ -568,13 +604,13 @@ TEST_P(SQLDatabaseTest, RazeLocked) { // write operations when using a WAL. if (!IsWALEnabled()) { const char* kQuery = "SELECT COUNT(*) FROM foo"; - sql::Statement s(other_db.GetUniqueStatement(kQuery)); + Statement s(other_db.GetUniqueStatement(kQuery)); ASSERT_TRUE(s.Step()); - ASSERT_FALSE(db().Raze()); + ASSERT_FALSE(db_->Raze()); // Completing the statement unlocks the database. ASSERT_FALSE(s.Step()); - ASSERT_TRUE(db().Raze()); + ASSERT_TRUE(db_->Raze()); } } @@ -582,26 +618,26 @@ TEST_P(SQLDatabaseTest, RazeLocked) { // this as an empty database. TEST_P(SQLDatabaseTest, RazeEmptyDB) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - db().Close(); + ASSERT_TRUE(db_->Execute(kCreateSql)); + db_->Close(); - TruncateDatabase(); + ASSERT_TRUE(TruncateDatabase()); - ASSERT_TRUE(db().Open(db_path())); - ASSERT_TRUE(db().Raze()); - EXPECT_EQ(0, SqliteMasterCount(&db())); + ASSERT_TRUE(db_->Open(db_path_)); + ASSERT_TRUE(db_->Raze()); + EXPECT_EQ(0, SqliteMasterCount(db_.get())); } // Verify that Raze() can handle a file of junk. // Need exclusive mode off here as there are some subtleties (by design) around // how the cache is used with it on which causes the test to fail. TEST_P(SQLDatabaseTest, RazeNOTADB) { - db().Close(); - sql::Database::Delete(db_path()); - ASSERT_FALSE(GetPathExists(db_path())); + db_->Close(); + Database::Delete(db_path_); + ASSERT_FALSE(base::PathExists(db_path_)); - WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE_AND_TRUNCATE); - ASSERT_TRUE(GetPathExists(db_path())); + ASSERT_TRUE(OverwriteDatabaseHeader(OverwriteType::kTruncate)); + ASSERT_TRUE(base::PathExists(db_path_)); // SQLite will successfully open the handle, but fail when running PRAGMA // statements that access the database. @@ -609,25 +645,25 @@ TEST_P(SQLDatabaseTest, RazeNOTADB) { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_NOTADB); - EXPECT_TRUE(db().Open(db_path())); + EXPECT_TRUE(db_->Open(db_path_)); ASSERT_TRUE(expecter.SawExpectedErrors()); } - EXPECT_TRUE(db().Raze()); - db().Close(); + EXPECT_TRUE(db_->Raze()); + db_->Close(); // Now empty, the open should open an empty database. - EXPECT_TRUE(db().Open(db_path())); - EXPECT_EQ(0, SqliteMasterCount(&db())); + EXPECT_TRUE(db_->Open(db_path_)); + EXPECT_EQ(0, SqliteMasterCount(db_.get())); } // Verify that Raze() can handle a database overwritten with garbage. TEST_P(SQLDatabaseTest, RazeNOTADB2) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_EQ(1, SqliteMasterCount(&db())); - db().Close(); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_EQ(1, SqliteMasterCount(db_.get())); + db_->Close(); - WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE); + ASSERT_TRUE(OverwriteDatabaseHeader(OverwriteType::kOverwrite)); // SQLite will successfully open the handle, but will fail with // SQLITE_NOTADB on pragma statemenets which attempt to read the @@ -635,15 +671,15 @@ TEST_P(SQLDatabaseTest, RazeNOTADB2) { { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_NOTADB); - EXPECT_TRUE(db().Open(db_path())); + EXPECT_TRUE(db_->Open(db_path_)); ASSERT_TRUE(expecter.SawExpectedErrors()); } - EXPECT_TRUE(db().Raze()); - db().Close(); + EXPECT_TRUE(db_->Raze()); + db_->Close(); // Now empty, the open should succeed with an empty database. - EXPECT_TRUE(db().Open(db_path())); - EXPECT_EQ(0, SqliteMasterCount(&db())); + EXPECT_TRUE(db_->Open(db_path_)); + EXPECT_EQ(0, SqliteMasterCount(db_.get())); } // Test that a callback from Open() can raze the database. This is @@ -652,34 +688,34 @@ TEST_P(SQLDatabaseTest, RazeNOTADB2) { // callback does this during Open(), the open is retried and succeeds. TEST_P(SQLDatabaseTest, RazeCallbackReopen) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_EQ(1, SqliteMasterCount(&db())); - db().Close(); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_EQ(1, SqliteMasterCount(db_.get())); + db_->Close(); // Corrupt the database so that nothing works, including PRAGMAs. - ASSERT_TRUE(CorruptSizeInHeaderOfDB()); + ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path_)); // Open() will succeed, even though the PRAGMA calls within will // fail with SQLITE_CORRUPT, as will this PRAGMA. { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CORRUPT); - ASSERT_TRUE(db().Open(db_path())); - ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum")); - db().Close(); + ASSERT_TRUE(db_->Open(db_path_)); + ASSERT_FALSE(db_->Execute("PRAGMA auto_vacuum")); + db_->Close(); ASSERT_TRUE(expecter.SawExpectedErrors()); } - db().set_error_callback( - base::BindRepeating(&RazeErrorCallback, &db(), SQLITE_CORRUPT)); + db_->set_error_callback( + base::BindRepeating(&RazeErrorCallback, db_.get(), SQLITE_CORRUPT)); // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error // callback will call RazeAndClose(). Open() will then fail and be // retried. The second Open() on the empty database will succeed // cleanly. - ASSERT_TRUE(db().Open(db_path())); - ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum")); - EXPECT_EQ(0, SqliteMasterCount(&db())); + ASSERT_TRUE(db_->Open(db_path_)); + ASSERT_TRUE(db_->Execute("PRAGMA auto_vacuum")); + EXPECT_EQ(0, SqliteMasterCount(db_.get())); } // Basic test of RazeAndClose() operation. @@ -689,24 +725,24 @@ TEST_P(SQLDatabaseTest, RazeAndClose) { // Test that RazeAndClose() closes the database, and that the // database is empty when re-opened. - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute(kPopulateSql)); - ASSERT_TRUE(db().RazeAndClose()); - ASSERT_FALSE(db().is_open()); - db().Close(); - ASSERT_TRUE(db().Open(db_path())); - ASSERT_EQ(0, SqliteMasterCount(&db())); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute(kPopulateSql)); + ASSERT_TRUE(db_->RazeAndClose()); + ASSERT_FALSE(db_->is_open()); + db_->Close(); + ASSERT_TRUE(db_->Open(db_path_)); + ASSERT_EQ(0, SqliteMasterCount(db_.get())); // Test that RazeAndClose() can break transactions. - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute(kPopulateSql)); - ASSERT_TRUE(db().BeginTransaction()); - ASSERT_TRUE(db().RazeAndClose()); - ASSERT_FALSE(db().is_open()); - ASSERT_FALSE(db().CommitTransaction()); - db().Close(); - ASSERT_TRUE(db().Open(db_path())); - ASSERT_EQ(0, SqliteMasterCount(&db())); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute(kPopulateSql)); + ASSERT_TRUE(db_->BeginTransaction()); + ASSERT_TRUE(db_->RazeAndClose()); + ASSERT_FALSE(db_->is_open()); + ASSERT_FALSE(db_->CommitTransaction()); + db_->Close(); + ASSERT_TRUE(db_->Open(db_path_)); + ASSERT_EQ(0, SqliteMasterCount(db_.get())); } // Test that various operations fail without crashing after @@ -716,53 +752,53 @@ TEST_P(SQLDatabaseTest, RazeAndCloseDiagnostics) { const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)"; const char* kSimpleSql = "SELECT 1"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute(kPopulateSql)); + ASSERT_TRUE(db_->Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute(kPopulateSql)); // Test baseline expectations. - db().Preload(); - ASSERT_TRUE(db().DoesTableExist("foo")); - ASSERT_TRUE(db().IsSQLValid(kSimpleSql)); - ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql)); - ASSERT_TRUE(db().Execute(kSimpleSql)); - ASSERT_TRUE(db().is_open()); + db_->Preload(); + ASSERT_TRUE(db_->DoesTableExist("foo")); + ASSERT_TRUE(db_->IsSQLValid(kSimpleSql)); + ASSERT_EQ(SQLITE_OK, db_->ExecuteAndReturnErrorCode(kSimpleSql)); + ASSERT_TRUE(db_->Execute(kSimpleSql)); + ASSERT_TRUE(db_->is_open()); { - sql::Statement s(db().GetUniqueStatement(kSimpleSql)); + Statement s(db_->GetUniqueStatement(kSimpleSql)); ASSERT_TRUE(s.Step()); } { - sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); + Statement s(db_->GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); ASSERT_TRUE(s.Step()); } - ASSERT_TRUE(db().BeginTransaction()); - ASSERT_TRUE(db().CommitTransaction()); - ASSERT_TRUE(db().BeginTransaction()); - db().RollbackTransaction(); + ASSERT_TRUE(db_->BeginTransaction()); + ASSERT_TRUE(db_->CommitTransaction()); + ASSERT_TRUE(db_->BeginTransaction()); + db_->RollbackTransaction(); - ASSERT_TRUE(db().RazeAndClose()); + ASSERT_TRUE(db_->RazeAndClose()); // At this point, they should all fail, but not crash. - db().Preload(); - ASSERT_FALSE(db().DoesTableExist("foo")); - ASSERT_FALSE(db().IsSQLValid(kSimpleSql)); - ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql)); - ASSERT_FALSE(db().Execute(kSimpleSql)); - ASSERT_FALSE(db().is_open()); + db_->Preload(); + ASSERT_FALSE(db_->DoesTableExist("foo")); + ASSERT_FALSE(db_->IsSQLValid(kSimpleSql)); + ASSERT_EQ(SQLITE_ERROR, db_->ExecuteAndReturnErrorCode(kSimpleSql)); + ASSERT_FALSE(db_->Execute(kSimpleSql)); + ASSERT_FALSE(db_->is_open()); { - sql::Statement s(db().GetUniqueStatement(kSimpleSql)); + Statement s(db_->GetUniqueStatement(kSimpleSql)); ASSERT_FALSE(s.Step()); } { - sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); + Statement s(db_->GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); ASSERT_FALSE(s.Step()); } - ASSERT_FALSE(db().BeginTransaction()); - ASSERT_FALSE(db().CommitTransaction()); - ASSERT_FALSE(db().BeginTransaction()); - db().RollbackTransaction(); + ASSERT_FALSE(db_->BeginTransaction()); + ASSERT_FALSE(db_->CommitTransaction()); + ASSERT_FALSE(db_->BeginTransaction()); + db_->RollbackTransaction(); // Close normally to reset the poisoned flag. - db().Close(); + db_->Close(); // DEATH tests not supported on Android, iOS, or Fuchsia. #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA) @@ -770,7 +806,7 @@ TEST_P(SQLDatabaseTest, RazeAndCloseDiagnostics) { // usage by becoming fatal in debug mode. Since DEATH tests are // expensive, just test one of them. if (DLOG_IS_ON(FATAL)) { - ASSERT_DEATH({ db().IsSQLValid(kSimpleSql); }, + ASSERT_DEATH({ db_->IsSQLValid(kSimpleSql); }, "Illegal use of Database without a db"); } #endif // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA) @@ -789,75 +825,75 @@ TEST_P(SQLDatabaseTest, RazeTruncate) { // The empty database has 0 or 1 pages. Raze() should leave it with exactly 1 // page. Not checking directly because auto_vacuum on Android adds a freelist // page. - ASSERT_TRUE(db().Raze()); + ASSERT_TRUE(db_->Raze()); int64_t expected_size; - ASSERT_TRUE(base::GetFileSize(db_path(), &expected_size)); + ASSERT_TRUE(base::GetFileSize(db_path_, &expected_size)); ASSERT_GT(expected_size, 0); // Cause the database to take a few pages. const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); + ASSERT_TRUE(db_->Execute(kCreateSql)); for (size_t i = 0; i < 24; ++i) { ASSERT_TRUE( - db().Execute("INSERT INTO foo (value) VALUES (randomblob(1024))")); + db_->Execute("INSERT INTO foo (value) VALUES (randomblob(1024))")); } // In WAL mode, writes don't reach the database file until a checkpoint // happens. - ASSERT_TRUE(db().CheckpointDatabase()); + ASSERT_TRUE(db_->CheckpointDatabase()); int64_t db_size; - ASSERT_TRUE(base::GetFileSize(db_path(), &db_size)); + ASSERT_TRUE(base::GetFileSize(db_path_, &db_size)); ASSERT_GT(db_size, expected_size); // Make a query covering most of the database file to make sure that the // blocks are actually mapped into memory. Empirically, the truncate problem // doesn't seem to happen if no blocks are mapped. EXPECT_EQ("24576", - ExecuteWithResult(&db(), "SELECT SUM(LENGTH(value)) FROM foo")); + ExecuteWithResult(db_.get(), "SELECT SUM(LENGTH(value)) FROM foo")); - ASSERT_TRUE(db().Raze()); - ASSERT_TRUE(base::GetFileSize(db_path(), &db_size)); + ASSERT_TRUE(db_->Raze()); + ASSERT_TRUE(base::GetFileSize(db_path_, &db_size)); ASSERT_EQ(expected_size, db_size); } #if defined(OS_ANDROID) TEST_P(SQLDatabaseTest, SetTempDirForSQL) { - sql::MetaTable meta_table; + MetaTable meta_table; // Below call needs a temporary directory in sqlite3 // On Android, it can pass only when the temporary directory is set. // Otherwise, sqlite3 doesn't find the correct directory to store // temporary files and will report the error 'unable to open // database file'. - ASSERT_TRUE(meta_table.Init(&db(), 4, 4)); + ASSERT_TRUE(meta_table.Init(db_.get(), 4, 4)); } #endif // defined(OS_ANDROID) TEST_P(SQLDatabaseTest, Delete) { - EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); - db().Close(); + EXPECT_TRUE(db_->Execute("CREATE TABLE x (x)")); + db_->Close(); - base::FilePath journal_path = sql::Database::JournalPath(db_path()); - base::FilePath wal_path = sql::Database::WriteAheadLogPath(db_path()); + base::FilePath journal_path = Database::JournalPath(db_path_); + base::FilePath wal_path = Database::WriteAheadLogPath(db_path_); // Should have both a main database file and a journal file if // journal_mode is TRUNCATE. There is no WAL file as it is deleted on Close. - ASSERT_TRUE(GetPathExists(db_path())); + ASSERT_TRUE(base::PathExists(db_path_)); if (!IsWALEnabled()) { // TRUNCATE mode - ASSERT_TRUE(GetPathExists(journal_path)); + ASSERT_TRUE(base::PathExists(journal_path)); } - sql::Database::Delete(db_path()); - EXPECT_FALSE(GetPathExists(db_path())); - EXPECT_FALSE(GetPathExists(journal_path)); - EXPECT_FALSE(GetPathExists(wal_path)); + Database::Delete(db_path_); + EXPECT_FALSE(base::PathExists(db_path_)); + EXPECT_FALSE(base::PathExists(journal_path)); + EXPECT_FALSE(base::PathExists(wal_path)); } #if defined(OS_POSIX) // This test operates on POSIX file permissions. TEST_P(SQLDatabaseTest, PosixFilePermissions) { - db().Close(); - sql::Database::Delete(db_path()); - ASSERT_FALSE(GetPathExists(db_path())); + db_->Close(); + Database::Delete(db_path_); + ASSERT_FALSE(base::PathExists(db_path_)); // If the bots all had a restrictive umask setting such that databases are // always created with only the owner able to read them, then the code could @@ -865,37 +901,37 @@ TEST_P(SQLDatabaseTest, PosixFilePermissions) { // umask. ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH); - ASSERT_TRUE(db().Open(db_path())); + ASSERT_TRUE(db_->Open(db_path_)); // Cause the journal file to be created. If the default journal_mode is // changed back to DELETE, this test will need to be updated. - EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); + EXPECT_TRUE(db_->Execute("CREATE TABLE x (x)")); int mode; - ASSERT_TRUE(GetPathExists(db_path())); - EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode)); + ASSERT_TRUE(base::PathExists(db_path_)); + EXPECT_TRUE(base::GetPosixFilePermissions(db_path_, &mode)); ASSERT_EQ(mode, 0600); if (IsWALEnabled()) { // WAL mode // The WAL file is created lazily on first change. - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); - base::FilePath wal_path = sql::Database::WriteAheadLogPath(db_path()); - ASSERT_TRUE(GetPathExists(wal_path)); + base::FilePath wal_path = Database::WriteAheadLogPath(db_path_); + ASSERT_TRUE(base::PathExists(wal_path)); EXPECT_TRUE(base::GetPosixFilePermissions(wal_path, &mode)); ASSERT_EQ(mode, 0600); // The shm file doesn't exist in exclusive locking mode. - if (ExecuteWithResult(&db(), "PRAGMA locking_mode") == "normal") { - base::FilePath shm_path = sql::Database::SharedMemoryFilePath(db_path()); - ASSERT_TRUE(GetPathExists(shm_path)); + if (ExecuteWithResult(db_.get(), "PRAGMA locking_mode") == "normal") { + base::FilePath shm_path = Database::SharedMemoryFilePath(db_path_); + ASSERT_TRUE(base::PathExists(shm_path)); EXPECT_TRUE(base::GetPosixFilePermissions(shm_path, &mode)); ASSERT_EQ(mode, 0600); } } else { // Truncate mode - base::FilePath journal_path = sql::Database::JournalPath(db_path()); + base::FilePath journal_path = Database::JournalPath(db_path_); DLOG(ERROR) << "journal_path: " << journal_path; - ASSERT_TRUE(GetPathExists(journal_path)); + ASSERT_TRUE(base::PathExists(journal_path)); EXPECT_TRUE(base::GetPosixFilePermissions(journal_path, &mode)); ASSERT_EQ(mode, 0600); } @@ -904,31 +940,31 @@ TEST_P(SQLDatabaseTest, PosixFilePermissions) { // Test that errors start happening once Poison() is called. TEST_P(SQLDatabaseTest, Poison) { - EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); + EXPECT_TRUE(db_->Execute("CREATE TABLE x (x)")); // Before the Poison() call, things generally work. - EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')")); - EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')")); + EXPECT_TRUE(db_->IsSQLValid("INSERT INTO x VALUES ('x')")); + EXPECT_TRUE(db_->Execute("INSERT INTO x VALUES ('x')")); { - sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x")); + Statement s(db_->GetUniqueStatement("SELECT COUNT(*) FROM x")); ASSERT_TRUE(s.is_valid()); ASSERT_TRUE(s.Step()); } // Get a statement which is valid before and will exist across Poison(). - sql::Statement valid_statement( - db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master")); + Statement valid_statement( + db_->GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master")); ASSERT_TRUE(valid_statement.is_valid()); ASSERT_TRUE(valid_statement.Step()); valid_statement.Reset(true); - db().Poison(); + db_->Poison(); // After the Poison() call, things fail. - EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')")); - EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')")); + EXPECT_FALSE(db_->IsSQLValid("INSERT INTO x VALUES ('x')")); + EXPECT_FALSE(db_->Execute("INSERT INTO x VALUES ('x')")); { - sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x")); + Statement s(db_->GetUniqueStatement("SELECT COUNT(*) FROM x")); ASSERT_FALSE(s.is_valid()); ASSERT_FALSE(s.Step()); } @@ -939,77 +975,77 @@ TEST_P(SQLDatabaseTest, Poison) { // Test that poisoning the database during a transaction works (with errors). // RazeErrorCallback() poisons the database, the extra COMMIT causes - // CommitTransaction() to throw an error while commiting. - db().set_error_callback( - base::BindRepeating(&RazeErrorCallback, &db(), SQLITE_ERROR)); - db().Close(); - ASSERT_TRUE(db().Open(db_path())); - EXPECT_TRUE(db().BeginTransaction()); - EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')")); - EXPECT_TRUE(db().Execute("COMMIT")); - EXPECT_FALSE(db().CommitTransaction()); + // CommitTransaction() to throw an error while committing. + db_->set_error_callback( + base::BindRepeating(&RazeErrorCallback, db_.get(), SQLITE_ERROR)); + db_->Close(); + ASSERT_TRUE(db_->Open(db_path_)); + EXPECT_TRUE(db_->BeginTransaction()); + EXPECT_TRUE(db_->Execute("INSERT INTO x VALUES ('x')")); + EXPECT_TRUE(db_->Execute("COMMIT")); + EXPECT_FALSE(db_->CommitTransaction()); } TEST_P(SQLDatabaseTest, AttachDatabase) { - EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + EXPECT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); // Create a database to attach to. base::FilePath attach_path = - db_path().DirName().AppendASCII("SQLDatabaseAttach.db"); + db_path_.DirName().AppendASCII("SQLDatabaseAttach.db"); static const char kAttachmentPoint[] = "other"; { - sql::Database other_db; + Database other_db; ASSERT_TRUE(other_db.Open(attach_path)); EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)")); EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')")); } // Cannot see the attached database, yet. - EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar")); + EXPECT_FALSE(db_->IsSQLValid("SELECT count(*) from other.bar")); - EXPECT_TRUE( - DatabaseTestPeer::AttachDatabase(&db(), attach_path, kAttachmentPoint)); - EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar")); + EXPECT_TRUE(DatabaseTestPeer::AttachDatabase(db_.get(), attach_path, + kAttachmentPoint)); + EXPECT_TRUE(db_->IsSQLValid("SELECT count(*) from other.bar")); // Queries can touch both databases after the ATTACH. - EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar")); + EXPECT_TRUE(db_->Execute("INSERT INTO foo SELECT a, b FROM other.bar")); { - sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo")); + Statement s(db_->GetUniqueStatement("SELECT COUNT(*) FROM foo")); ASSERT_TRUE(s.Step()); EXPECT_EQ(1, s.ColumnInt(0)); } - EXPECT_TRUE(DatabaseTestPeer::DetachDatabase(&db(), kAttachmentPoint)); - EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar")); + EXPECT_TRUE(DatabaseTestPeer::DetachDatabase(db_.get(), kAttachmentPoint)); + EXPECT_FALSE(db_->IsSQLValid("SELECT count(*) from other.bar")); } TEST_P(SQLDatabaseTest, AttachDatabaseWithOpenTransaction) { - EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + EXPECT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); // Create a database to attach to. base::FilePath attach_path = - db_path().DirName().AppendASCII("SQLDatabaseAttach.db"); + db_path_.DirName().AppendASCII("SQLDatabaseAttach.db"); static const char kAttachmentPoint[] = "other"; { - sql::Database other_db; + Database other_db; ASSERT_TRUE(other_db.Open(attach_path)); EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)")); EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')")); } // Cannot see the attached database, yet. - EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar")); + EXPECT_FALSE(db_->IsSQLValid("SELECT count(*) from other.bar")); // Attach succeeds in a transaction. - EXPECT_TRUE(db().BeginTransaction()); - EXPECT_TRUE( - DatabaseTestPeer::AttachDatabase(&db(), attach_path, kAttachmentPoint)); - EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar")); + EXPECT_TRUE(db_->BeginTransaction()); + EXPECT_TRUE(DatabaseTestPeer::AttachDatabase(db_.get(), attach_path, + kAttachmentPoint)); + EXPECT_TRUE(db_->IsSQLValid("SELECT count(*) from other.bar")); // Queries can touch both databases after the ATTACH. - EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar")); + EXPECT_TRUE(db_->Execute("INSERT INTO foo SELECT a, b FROM other.bar")); { - sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo")); + Statement s(db_->GetUniqueStatement("SELECT COUNT(*) FROM foo")); ASSERT_TRUE(s.Step()); EXPECT_EQ(1, s.ColumnInt(0)); } @@ -1018,30 +1054,30 @@ TEST_P(SQLDatabaseTest, AttachDatabaseWithOpenTransaction) { { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_ERROR); - EXPECT_FALSE(DatabaseTestPeer::DetachDatabase(&db(), kAttachmentPoint)); - EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar")); + EXPECT_FALSE(DatabaseTestPeer::DetachDatabase(db_.get(), kAttachmentPoint)); + EXPECT_TRUE(db_->IsSQLValid("SELECT count(*) from other.bar")); ASSERT_TRUE(expecter.SawExpectedErrors()); } // Detach succeeds when the transaction is closed. - db().RollbackTransaction(); - EXPECT_TRUE(DatabaseTestPeer::DetachDatabase(&db(), kAttachmentPoint)); - EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar")); + db_->RollbackTransaction(); + EXPECT_TRUE(DatabaseTestPeer::DetachDatabase(db_.get(), kAttachmentPoint)); + EXPECT_FALSE(db_->IsSQLValid("SELECT count(*) from other.bar")); } TEST_P(SQLDatabaseTest, Basic_QuickIntegrityCheck) { const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - EXPECT_TRUE(db().QuickIntegrityCheck()); - db().Close(); + ASSERT_TRUE(db_->Execute(kCreateSql)); + EXPECT_TRUE(db_->QuickIntegrityCheck()); + db_->Close(); - ASSERT_TRUE(CorruptSizeInHeaderOfDB()); + ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path_)); { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CORRUPT); - ASSERT_TRUE(db().Open(db_path())); - EXPECT_FALSE(db().QuickIntegrityCheck()); + ASSERT_TRUE(db_->Open(db_path_)); + EXPECT_FALSE(db_->QuickIntegrityCheck()); ASSERT_TRUE(expecter.SawExpectedErrors()); } } @@ -1051,19 +1087,19 @@ TEST_P(SQLDatabaseTest, Basic_FullIntegrityCheck) { std::vector messages; const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - EXPECT_TRUE(db().FullIntegrityCheck(&messages)); + ASSERT_TRUE(db_->Execute(kCreateSql)); + EXPECT_TRUE(db_->FullIntegrityCheck(&messages)); EXPECT_EQ(1u, messages.size()); EXPECT_EQ(kOk, messages[0]); - db().Close(); + db_->Close(); - ASSERT_TRUE(CorruptSizeInHeaderOfDB()); + ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path_)); { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CORRUPT); - ASSERT_TRUE(db().Open(db_path())); - EXPECT_TRUE(db().FullIntegrityCheck(&messages)); + ASSERT_TRUE(db_->Open(db_path_)); + EXPECT_TRUE(db_->FullIntegrityCheck(&messages)); EXPECT_LT(1u, messages.size()); EXPECT_NE(kOk, messages[0]); ASSERT_TRUE(expecter.SawExpectedErrors()); @@ -1077,38 +1113,38 @@ TEST_P(SQLDatabaseTest, OnMemoryDump) { base::trace_event::MemoryDumpArgs args = { base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; base::trace_event::ProcessMemoryDump pmd(args); - ASSERT_TRUE(db().memory_dump_provider_->OnMemoryDump(args, &pmd)); + ASSERT_TRUE(db_->memory_dump_provider_->OnMemoryDump(args, &pmd)); EXPECT_GE(pmd.allocator_dumps().size(), 1u); } // Test that the functions to collect diagnostic data run to completion, without // worrying too much about what they generate (since that will change). TEST_P(SQLDatabaseTest, CollectDiagnosticInfo) { - const std::string corruption_info = db().CollectCorruptionInfo(); + const std::string corruption_info = db_->CollectCorruptionInfo(); EXPECT_NE(std::string::npos, corruption_info.find("SQLITE_CORRUPT")); EXPECT_NE(std::string::npos, corruption_info.find("integrity_check")); // A statement to see in the results. const char* kSimpleSql = "SELECT 'mountain'"; - Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); + Statement s(db_->GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); // Error includes the statement. - const std::string readonly_info = db().CollectErrorInfo(SQLITE_READONLY, &s); + const std::string readonly_info = db_->CollectErrorInfo(SQLITE_READONLY, &s); EXPECT_NE(std::string::npos, readonly_info.find(kSimpleSql)); // Some other error doesn't include the statment. // TODO(shess): This is weak. - const std::string full_info = db().CollectErrorInfo(SQLITE_FULL, nullptr); + const std::string full_info = db_->CollectErrorInfo(SQLITE_FULL, nullptr); EXPECT_EQ(std::string::npos, full_info.find(kSimpleSql)); // A table to see in the SQLITE_ERROR results. - EXPECT_TRUE(db().Execute("CREATE TABLE volcano (x)")); + EXPECT_TRUE(db_->Execute("CREATE TABLE volcano (x)")); // Version info to see in the SQLITE_ERROR results. - sql::MetaTable meta_table; - ASSERT_TRUE(meta_table.Init(&db(), 4, 4)); + MetaTable meta_table; + ASSERT_TRUE(meta_table.Init(db_.get(), 4, 4)); - const std::string error_info = db().CollectErrorInfo(SQLITE_ERROR, &s); + const std::string error_info = db_->CollectErrorInfo(SQLITE_ERROR, &s); EXPECT_NE(std::string::npos, error_info.find(kSimpleSql)); EXPECT_NE(std::string::npos, error_info.find("volcano")); EXPECT_NE(std::string::npos, error_info.find("version: 4")); @@ -1118,7 +1154,7 @@ TEST_P(SQLDatabaseTest, CollectDiagnosticInfo) { // enabled by SQLite. TEST_P(SQLDatabaseTest, MmapInitiallyEnabled) { { - sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size")); + Statement s(db_->GetUniqueStatement("PRAGMA mmap_size")); ASSERT_TRUE(s.Step()) << "All supported SQLite versions should have mmap support"; @@ -1127,7 +1163,7 @@ TEST_P(SQLDatabaseTest, MmapInitiallyEnabled) { // returned. If the VFS does not understand SQLITE_FCNTL_MMAP_SIZE (for // instance MojoVFS), -1 is returned. if (s.ColumnInt(0) <= 0) { - ASSERT_TRUE(db().Execute("PRAGMA mmap_size = 1048576")); + ASSERT_TRUE(db_->Execute("PRAGMA mmap_size = 1048576")); s.Reset(true); ASSERT_TRUE(s.Step()); EXPECT_LE(s.ColumnInt(0), 0); @@ -1135,24 +1171,24 @@ TEST_P(SQLDatabaseTest, MmapInitiallyEnabled) { } // Test that explicit disable prevents mmap'ed I/O. - db().Close(); - sql::Database::Delete(db_path()); - db().set_mmap_disabled(); - ASSERT_TRUE(db().Open(db_path())); - EXPECT_EQ("0", ExecuteWithResult(&db(), "PRAGMA mmap_size")); + db_->Close(); + Database::Delete(db_path_); + db_->set_mmap_disabled(); + ASSERT_TRUE(db_->Open(db_path_)); + EXPECT_EQ("0", ExecuteWithResult(db_.get(), "PRAGMA mmap_size")); } // Test whether a fresh database gets mmap enabled when using alternate status // storage. TEST_P(SQLDatabaseTest, MmapInitiallyEnabledAltStatus) { // Re-open fresh database with alt-status flag set. - db().Close(); - sql::Database::Delete(db_path()); - db().set_mmap_alt_status(); - ASSERT_TRUE(db().Open(db_path())); + db_->Close(); + Database::Delete(db_path_); + db_->set_mmap_alt_status(); + ASSERT_TRUE(db_->Open(db_path_)); { - sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size")); + Statement s(db_->GetUniqueStatement("PRAGMA mmap_size")); ASSERT_TRUE(s.Step()) << "All supported SQLite versions should have mmap support"; @@ -1161,7 +1197,7 @@ TEST_P(SQLDatabaseTest, MmapInitiallyEnabledAltStatus) { // returned. If the VFS does not understand SQLITE_FCNTL_MMAP_SIZE (for // instance MojoVFS), -1 is returned. if (s.ColumnInt(0) <= 0) { - ASSERT_TRUE(db().Execute("PRAGMA mmap_size = 1048576")); + ASSERT_TRUE(db_->Execute("PRAGMA mmap_size = 1048576")); s.Reset(true); ASSERT_TRUE(s.Step()); EXPECT_LE(s.ColumnInt(0), 0); @@ -1169,11 +1205,11 @@ TEST_P(SQLDatabaseTest, MmapInitiallyEnabledAltStatus) { } // Test that explicit disable overrides set_mmap_alt_status(). - db().Close(); - sql::Database::Delete(db_path()); - db().set_mmap_disabled(); - ASSERT_TRUE(db().Open(db_path())); - EXPECT_EQ("0", ExecuteWithResult(&db(), "PRAGMA mmap_size")); + db_->Close(); + Database::Delete(db_path_); + db_->set_mmap_disabled(); + ASSERT_TRUE(db_->Open(db_path_)); + EXPECT_EQ("0", ExecuteWithResult(db_.get(), "PRAGMA mmap_size")); } TEST_P(SQLDatabaseTest, GetAppropriateMmapSize) { @@ -1182,40 +1218,40 @@ TEST_P(SQLDatabaseTest, GetAppropriateMmapSize) { // If there is no meta table (as for a fresh database), assume that everything // should be mapped, and the status of the meta table is not affected. - ASSERT_TRUE(!db().DoesTableExist("meta")); - ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot); - ASSERT_TRUE(!db().DoesTableExist("meta")); + ASSERT_TRUE(!db_->DoesTableExist("meta")); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); + ASSERT_TRUE(!db_->DoesTableExist("meta")); // When the meta table is first created, it sets up to map everything. - MetaTable().Init(&db(), 1, 1); - ASSERT_TRUE(db().DoesTableExist("meta")); - ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot); - ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status)); + MetaTable().Init(db_.get(), 1, 1); + ASSERT_TRUE(db_->DoesTableExist("meta")); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); + ASSERT_TRUE(MetaTable::GetMmapStatus(db_.get(), &mmap_status)); ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status); // Preload with partial progress of one page. Should map everything. - ASSERT_TRUE(db().Execute("REPLACE INTO meta VALUES ('mmap_status', 1)")); - ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot); - ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status)); + ASSERT_TRUE(db_->Execute("REPLACE INTO meta VALUES ('mmap_status', 1)")); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); + ASSERT_TRUE(MetaTable::GetMmapStatus(db_.get(), &mmap_status)); ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status); // Failure status maps nothing. - ASSERT_TRUE(db().Execute("REPLACE INTO meta VALUES ('mmap_status', -2)")); - ASSERT_EQ(0UL, db().GetAppropriateMmapSize()); + ASSERT_TRUE(db_->Execute("REPLACE INTO meta VALUES ('mmap_status', -2)")); + ASSERT_EQ(0UL, db_->GetAppropriateMmapSize()); // Re-initializing the meta table does not re-create the key if the table // already exists. - ASSERT_TRUE(db().Execute("DELETE FROM meta WHERE key = 'mmap_status'")); - MetaTable().Init(&db(), 1, 1); + ASSERT_TRUE(db_->Execute("DELETE FROM meta WHERE key = 'mmap_status'")); + MetaTable().Init(db_.get(), 1, 1); ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status); - ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status)); + ASSERT_TRUE(MetaTable::GetMmapStatus(db_.get(), &mmap_status)); ASSERT_EQ(0, mmap_status); // With no key, map everything and create the key. // TODO(shess): This really should be "maps everything after validating it", // but that is more complicated to structure. - ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot); - ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status)); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); + ASSERT_TRUE(MetaTable::GetMmapStatus(db_.get(), &mmap_status)); ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status); } @@ -1223,133 +1259,151 @@ TEST_P(SQLDatabaseTest, GetAppropriateMmapSizeAltStatus) { const size_t kMmapAlot = 25 * 1024 * 1024; // At this point, Database still expects a future [meta] table. - ASSERT_FALSE(db().DoesTableExist("meta")); - ASSERT_FALSE(db().DoesViewExist("MmapStatus")); - ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot); - ASSERT_FALSE(db().DoesTableExist("meta")); - ASSERT_FALSE(db().DoesViewExist("MmapStatus")); + ASSERT_FALSE(db_->DoesTableExist("meta")); + ASSERT_FALSE(db_->DoesViewExist("MmapStatus")); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); + ASSERT_FALSE(db_->DoesTableExist("meta")); + ASSERT_FALSE(db_->DoesViewExist("MmapStatus")); // Using alt status, everything should be mapped, with state in the view. - db().set_mmap_alt_status(); - ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot); - ASSERT_FALSE(db().DoesTableExist("meta")); - ASSERT_TRUE(db().DoesViewExist("MmapStatus")); + db_->set_mmap_alt_status(); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); + ASSERT_FALSE(db_->DoesTableExist("meta")); + ASSERT_TRUE(db_->DoesViewExist("MmapStatus")); EXPECT_EQ(base::NumberToString(MetaTable::kMmapSuccess), - ExecuteWithResult(&db(), "SELECT * FROM MmapStatus")); + ExecuteWithResult(db_.get(), "SELECT * FROM MmapStatus")); // Also maps everything when kMmapSuccess is already in the view. - ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); // Preload with partial progress of one page. Should map everything. - ASSERT_TRUE(db().Execute("DROP VIEW MmapStatus")); - ASSERT_TRUE(db().Execute("CREATE VIEW MmapStatus (value) AS SELECT 1")); - ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot); + ASSERT_TRUE(db_->Execute("DROP VIEW MmapStatus")); + ASSERT_TRUE(db_->Execute("CREATE VIEW MmapStatus (value) AS SELECT 1")); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); EXPECT_EQ(base::NumberToString(MetaTable::kMmapSuccess), - ExecuteWithResult(&db(), "SELECT * FROM MmapStatus")); + ExecuteWithResult(db_.get(), "SELECT * FROM MmapStatus")); // Failure status leads to nothing being mapped. - ASSERT_TRUE(db().Execute("DROP VIEW MmapStatus")); - ASSERT_TRUE(db().Execute("CREATE VIEW MmapStatus (value) AS SELECT -2")); - ASSERT_EQ(0UL, db().GetAppropriateMmapSize()); + ASSERT_TRUE(db_->Execute("DROP VIEW MmapStatus")); + ASSERT_TRUE(db_->Execute("CREATE VIEW MmapStatus (value) AS SELECT -2")); + ASSERT_EQ(0UL, db_->GetAppropriateMmapSize()); EXPECT_EQ(base::NumberToString(MetaTable::kMmapFailure), - ExecuteWithResult(&db(), "SELECT * FROM MmapStatus")); + ExecuteWithResult(db_.get(), "SELECT * FROM MmapStatus")); } TEST_P(SQLDatabaseTest, GetMemoryUsage) { // Databases with mmap enabled may not follow the assumptions below. - db().Close(); - db().set_mmap_disabled(); - ASSERT_TRUE(db().Open(db_path())); + db_->Close(); + db_->set_mmap_disabled(); + ASSERT_TRUE(db_->Open(db_path_)); - int initial_memory = db().GetMemoryUsage(); + int initial_memory = db_->GetMemoryUsage(); EXPECT_GT(initial_memory, 0) << "SQLite should always use some memory for a database"; - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); - ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)")); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_->Execute("INSERT INTO foo(a, b) VALUES (12, 13)")); - int post_query_memory = db().GetMemoryUsage(); + int post_query_memory = db_->GetMemoryUsage(); EXPECT_GT(post_query_memory, initial_memory) << "Page cache usage should go up after executing queries"; - db().TrimMemory(); - int post_trim_memory = db().GetMemoryUsage(); + db_->TrimMemory(); + int post_trim_memory = db_->GetMemoryUsage(); EXPECT_GT(post_query_memory, post_trim_memory) << "Page cache usage should go down after calling TrimMemory()"; } -class SQLDatabaseTestExclusiveMode : public SQLDatabaseTest { +class SQLDatabaseTestExclusiveMode : public testing::Test, + public testing::WithParamInterface { public: - SQLDatabaseTestExclusiveMode() : SQLDatabaseTest(GetDBOptions()) {} + ~SQLDatabaseTestExclusiveMode() override = default; + + void SetUp() override { + db_ = std::make_unique(GetDBOptions()); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + db_path_ = temp_dir_.GetPath().AppendASCII("recovery_test.sqlite"); + ASSERT_TRUE(db_->Open(db_path_)); + } DatabaseOptions GetDBOptions() { - DatabaseOptions options = SQLDatabaseTest::GetDBOptions(); + DatabaseOptions options; + options.wal_mode = IsWALEnabled(); options.exclusive_locking = true; return options; } + + bool IsWALEnabled() { return GetParam(); } + + protected: + base::ScopedTempDir temp_dir_; + base::FilePath db_path_; + std::unique_ptr db_; }; TEST_P(SQLDatabaseTestExclusiveMode, LockingModeExclusive) { - EXPECT_EQ(ExecuteWithResult(&db(), "PRAGMA locking_mode"), "exclusive"); + EXPECT_EQ(ExecuteWithResult(db_.get(), "PRAGMA locking_mode"), "exclusive"); } TEST_P(SQLDatabaseTest, LockingModeNormal) { - EXPECT_EQ(ExecuteWithResult(&db(), "PRAGMA locking_mode"), "normal"); + EXPECT_EQ(ExecuteWithResult(db_.get(), "PRAGMA locking_mode"), "normal"); } TEST_P(SQLDatabaseTest, OpenedInCorrectMode) { std::string expected_mode = IsWALEnabled() ? "wal" : "truncate"; - EXPECT_EQ(ExecuteWithResult(&db(), "PRAGMA journal_mode"), expected_mode); + EXPECT_EQ(ExecuteWithResult(db_.get(), "PRAGMA journal_mode"), expected_mode); } TEST_P(SQLDatabaseTest, CheckpointDatabase) { if (!IsWALEnabled()) return; - base::FilePath wal_path = sql::Database::WriteAheadLogPath(db_path()); + base::FilePath wal_path = Database::WriteAheadLogPath(db_path_); int64_t wal_size = 0; // WAL file initially empty. - EXPECT_TRUE(GetPathExists(wal_path)); + EXPECT_TRUE(base::PathExists(wal_path)); base::GetFileSize(wal_path, &wal_size); EXPECT_EQ(wal_size, 0); ASSERT_TRUE( - db().Execute("CREATE TABLE foo (id INTEGER UNIQUE, value INTEGER)")); - ASSERT_TRUE(db().Execute("INSERT INTO foo VALUES (1, 1)")); - ASSERT_TRUE(db().Execute("INSERT INTO foo VALUES (2, 2)")); + db_->Execute("CREATE TABLE foo (id INTEGER UNIQUE, value INTEGER)")); + ASSERT_TRUE(db_->Execute("INSERT INTO foo VALUES (1, 1)")); + ASSERT_TRUE(db_->Execute("INSERT INTO foo VALUES (2, 2)")); // Writes reach WAL file but not db file. base::GetFileSize(wal_path, &wal_size); EXPECT_GT(wal_size, 0); int64_t db_size = 0; - base::GetFileSize(db_path(), &db_size); - EXPECT_EQ(db_size, db().page_size()); + base::GetFileSize(db_path_, &db_size); + EXPECT_EQ(db_size, db_->page_size()); // Checkpoint database to immediately propagate writes to DB file. - EXPECT_TRUE(db().CheckpointDatabase()); - - base::GetFileSize(db_path(), &db_size); - EXPECT_GT(db_size, db().page_size()); - EXPECT_EQ(ExecuteWithResult(&db(), "SELECT value FROM foo where id=1"), "1"); - EXPECT_EQ(ExecuteWithResult(&db(), "SELECT value FROM foo where id=2"), "2"); + EXPECT_TRUE(db_->CheckpointDatabase()); + + base::GetFileSize(db_path_, &db_size); + EXPECT_GT(db_size, db_->page_size()); + EXPECT_EQ(ExecuteWithResult(db_.get(), "SELECT value FROM foo where id=1"), + "1"); + EXPECT_EQ(ExecuteWithResult(db_.get(), "SELECT value FROM foo where id=2"), + "2"); } TEST_P(SQLDatabaseTest, CorruptSizeInHeaderTest) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (x)")); - ASSERT_TRUE(db().Execute("CREATE TABLE bar (x)")); - db().Close(); + ASSERT_TRUE(db_->Execute("CREATE TABLE foo (x)")); + ASSERT_TRUE(db_->Execute("CREATE TABLE bar (x)")); + db_->Close(); - ASSERT_TRUE(CorruptSizeInHeaderOfDB()); + ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path_)); { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CORRUPT); - ASSERT_TRUE(db().Open(db_path())); - EXPECT_FALSE(db().Execute("INSERT INTO foo values (1)")); - EXPECT_FALSE(db().DoesTableExist("foo")); - EXPECT_FALSE(db().DoesTableExist("bar")); - EXPECT_FALSE(db().Execute("SELECT * FROM foo")); + ASSERT_TRUE(db_->Open(db_path_)); + EXPECT_FALSE(db_->Execute("INSERT INTO foo values (1)")); + EXPECT_FALSE(db_->DoesTableExist("foo")); + EXPECT_FALSE(db_->DoesTableExist("bar")); + EXPECT_FALSE(db_->Execute("SELECT * FROM foo")); EXPECT_TRUE(expecter.SawExpectedErrors()); } } @@ -1361,8 +1415,8 @@ TEST_P(SQLDatabaseTest, CompileError) { // DEATH tests not supported on Android, iOS, or Fuchsia. #if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA) if (DLOG_IS_ON(FATAL)) { - db().set_error_callback(base::BindRepeating(&IgnoreErrorCallback)); - ASSERT_DEATH({ db().GetUniqueStatement("SELECT x"); }, + db_->set_error_callback(base::BindRepeating(&IgnoreErrorCallback)); + ASSERT_DEATH({ db_->GetUniqueStatement("SELECT x"); }, "SQL compile error no such column: x"); } #endif // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA) diff --git a/sql/meta_table_unittest.cc b/sql/meta_table_unittest.cc index 928c0ed02da663..e91380b2279a81 100644 --- a/sql/meta_table_unittest.cc +++ b/sql/meta_table_unittest.cc @@ -10,22 +10,36 @@ #include "base/files/scoped_temp_dir.h" #include "sql/database.h" #include "sql/statement.h" -#include "sql/test/sql_test_base.h" #include "testing/gtest/include/gtest/gtest.h" +namespace sql { + namespace { -using SQLMetaTableTest = sql::SQLTestBase; +class SQLMetaTableTest : public testing::Test { + public: + ~SQLMetaTableTest() override = default; + + void SetUp() override { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + ASSERT_TRUE( + db_.Open(temp_dir_.GetPath().AppendASCII("meta_table_test.sqlite"))); + } + + protected: + base::ScopedTempDir temp_dir_; + Database db_; +}; TEST_F(SQLMetaTableTest, DoesTableExist) { - EXPECT_FALSE(sql::MetaTable::DoesTableExist(&db())); + EXPECT_FALSE(MetaTable::DoesTableExist(&db_)); { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); } - EXPECT_TRUE(sql::MetaTable::DoesTableExist(&db())); + EXPECT_TRUE(MetaTable::DoesTableExist(&db_)); } TEST_F(SQLMetaTableTest, RazeIfDeprecated) { @@ -34,45 +48,45 @@ TEST_F(SQLMetaTableTest, RazeIfDeprecated) { // Setup a current database. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), kVersion, kVersion)); - EXPECT_TRUE(db().Execute("CREATE TABLE t(c)")); - EXPECT_TRUE(db().DoesTableExist("t")); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, kVersion, kVersion)); + EXPECT_TRUE(db_.Execute("CREATE TABLE t(c)")); + EXPECT_TRUE(db_.DoesTableExist("t")); } // Table should should still exist if the database version is new enough. - sql::MetaTable::RazeIfDeprecated(&db(), kDeprecatedVersion); - EXPECT_TRUE(db().DoesTableExist("t")); + MetaTable::RazeIfDeprecated(&db_, kDeprecatedVersion); + EXPECT_TRUE(db_.DoesTableExist("t")); // TODO(shess): It may make sense to Raze() if meta isn't present or // version isn't present. See meta_table.h TODO on RazeIfDeprecated(). // Table should still exist if the version is not available. - EXPECT_TRUE(db().Execute("DELETE FROM meta WHERE key = 'version'")); + EXPECT_TRUE(db_.Execute("DELETE FROM meta WHERE key = 'version'")); { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), kVersion, kVersion)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, kVersion, kVersion)); EXPECT_EQ(0, meta_table.GetVersionNumber()); } - sql::MetaTable::RazeIfDeprecated(&db(), kDeprecatedVersion); - EXPECT_TRUE(db().DoesTableExist("t")); + MetaTable::RazeIfDeprecated(&db_, kDeprecatedVersion); + EXPECT_TRUE(db_.DoesTableExist("t")); // Table should still exist if meta table is missing. - EXPECT_TRUE(db().Execute("DROP TABLE meta")); - sql::MetaTable::RazeIfDeprecated(&db(), kDeprecatedVersion); - EXPECT_TRUE(db().DoesTableExist("t")); + EXPECT_TRUE(db_.Execute("DROP TABLE meta")); + MetaTable::RazeIfDeprecated(&db_, kDeprecatedVersion); + EXPECT_TRUE(db_.DoesTableExist("t")); // Setup meta with deprecated version. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), kDeprecatedVersion, kDeprecatedVersion)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, kDeprecatedVersion, kDeprecatedVersion)); } // Deprecation check should remove the table. - EXPECT_TRUE(db().DoesTableExist("t")); - sql::MetaTable::RazeIfDeprecated(&db(), kDeprecatedVersion); - EXPECT_FALSE(sql::MetaTable::DoesTableExist(&db())); - EXPECT_FALSE(db().DoesTableExist("t")); + EXPECT_TRUE(db_.DoesTableExist("t")); + MetaTable::RazeIfDeprecated(&db_, kDeprecatedVersion); + EXPECT_FALSE(MetaTable::DoesTableExist(&db_)); + EXPECT_FALSE(db_.DoesTableExist("t")); } TEST_F(SQLMetaTableTest, VersionNumber) { @@ -87,16 +101,16 @@ TEST_F(SQLMetaTableTest, VersionNumber) { // First Init() sets the version info as expected. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), kVersionFirst, kCompatVersionFirst)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, kVersionFirst, kCompatVersionFirst)); EXPECT_EQ(kVersionFirst, meta_table.GetVersionNumber()); EXPECT_EQ(kCompatVersionFirst, meta_table.GetCompatibleVersionNumber()); } // Second Init() does not change the version info. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), kVersionSecond, kCompatVersionSecond)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, kVersionSecond, kCompatVersionSecond)); EXPECT_EQ(kVersionFirst, meta_table.GetVersionNumber()); EXPECT_EQ(kCompatVersionFirst, meta_table.GetCompatibleVersionNumber()); @@ -106,8 +120,8 @@ TEST_F(SQLMetaTableTest, VersionNumber) { // Version info from Set*() calls is seen. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), kVersionThird, kCompatVersionThird)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, kVersionThird, kCompatVersionThird)); EXPECT_EQ(kVersionSecond, meta_table.GetVersionNumber()); EXPECT_EQ(kCompatVersionSecond, meta_table.GetCompatibleVersionNumber()); } @@ -120,8 +134,8 @@ TEST_F(SQLMetaTableTest, StringValue) { // Initially, the value isn't there until set. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); std::string value; EXPECT_FALSE(meta_table.GetValue(kKey, &value)); @@ -133,8 +147,8 @@ TEST_F(SQLMetaTableTest, StringValue) { // Value is persistent across different instances. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); std::string value; EXPECT_TRUE(meta_table.GetValue(kKey, &value)); @@ -145,8 +159,8 @@ TEST_F(SQLMetaTableTest, StringValue) { // Existing value was successfully changed. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); std::string value; EXPECT_TRUE(meta_table.GetValue(kKey, &value)); @@ -161,8 +175,8 @@ TEST_F(SQLMetaTableTest, IntValue) { // Initially, the value isn't there until set. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); int value; EXPECT_FALSE(meta_table.GetValue(kKey, &value)); @@ -174,8 +188,8 @@ TEST_F(SQLMetaTableTest, IntValue) { // Value is persistent across different instances. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); int value; EXPECT_TRUE(meta_table.GetValue(kKey, &value)); @@ -186,8 +200,8 @@ TEST_F(SQLMetaTableTest, IntValue) { // Existing value was successfully changed. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); int value; EXPECT_TRUE(meta_table.GetValue(kKey, &value)); @@ -202,8 +216,8 @@ TEST_F(SQLMetaTableTest, Int64Value) { // Initially, the value isn't there until set. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); int64_t value; EXPECT_FALSE(meta_table.GetValue(kKey, &value)); @@ -215,8 +229,8 @@ TEST_F(SQLMetaTableTest, Int64Value) { // Value is persistent across different instances. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); int64_t value; EXPECT_TRUE(meta_table.GetValue(kKey, &value)); @@ -227,8 +241,8 @@ TEST_F(SQLMetaTableTest, Int64Value) { // Existing value was successfully changed. { - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); int64_t value; EXPECT_TRUE(meta_table.GetValue(kKey, &value)); @@ -240,8 +254,8 @@ TEST_F(SQLMetaTableTest, DeleteKey) { static const char kKey[] = "String Key"; const std::string kValue("String Value"); - sql::MetaTable meta_table; - EXPECT_TRUE(meta_table.Init(&db(), 1, 1)); + MetaTable meta_table; + EXPECT_TRUE(meta_table.Init(&db_, 1, 1)); // Value isn't present. std::string value; @@ -258,3 +272,5 @@ TEST_F(SQLMetaTableTest, DeleteKey) { } } // namespace + +} // namespace sql diff --git a/sql/recover_module/module_unittest.cc b/sql/recover_module/module_unittest.cc index a711756fbb7556..2e0db47cf261ad 100644 --- a/sql/recover_module/module_unittest.cc +++ b/sql/recover_module/module_unittest.cc @@ -7,12 +7,12 @@ #include #include +#include "base/files/scoped_temp_dir.h" #include "base/strings/stringprintf.h" #include "sql/database.h" #include "sql/statement.h" #include "sql/test/database_test_peer.h" #include "sql/test/scoped_error_expecter.h" -#include "sql/test/sql_test_base.h" #include "sql/test/test_helpers.h" #include "sql/transaction.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,123 +21,131 @@ namespace sql { namespace recover { -class RecoverModuleTest : public sql::SQLTestBase { +class RecoverModuleTest : public testing::Test { public: + ~RecoverModuleTest() override = default; + void SetUp() override { - SQLTestBase::SetUp(); - ASSERT_TRUE(DatabaseTestPeer::EnableRecoveryExtension(&db())); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + ASSERT_TRUE( + db_.Open(temp_dir_.GetPath().AppendASCII("recovery_test.sqlite"))); + ASSERT_TRUE(DatabaseTestPeer::EnableRecoveryExtension(&db_)); } + + protected: + base::ScopedTempDir temp_dir_; + sql::Database db_; }; TEST_F(RecoverModuleTest, CreateVtable) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); EXPECT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing, t TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing, t TEXT)")); } TEST_F(RecoverModuleTest, CreateVtableWithDatabaseSpecifier) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); EXPECT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(main.backing, t TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(main.backing, t TEXT)")); } TEST_F(RecoverModuleTest, CreateVtableOnSqliteMaster) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); EXPECT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing USING recover(" - "sqlite_master, type TEXT, name TEXT, tbl_name TEXT, " - "rootpage INTEGER, sql TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing USING recover(" + "sqlite_master, type TEXT, name TEXT, tbl_name TEXT, " + "rootpage INTEGER, sql TEXT)")); } TEST_F(RecoverModuleTest, CreateVtableFailsOnNonTempTable) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_MISUSE); - EXPECT_FALSE(db().Execute( + EXPECT_FALSE(db_.Execute( "CREATE VIRTUAL TABLE recover_backing USING recover(backing, t TEXT)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, CreateVtableFailsOnMissingTable) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_CORRUPT); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_missing " - "USING recover(missing, t TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_missing " + "USING recover(missing, t TEXT)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, DISABLED_CreateVtableFailsOnMissingDatabase) { // TODO(pwnall): Enable test after removing incorrect DLOG(FATAL) from // sql::Statement::Execute(). - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_ERROR); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(db.backing, t TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(db.backing, t TEXT)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, CreateVtableFailsOnTableWithInvalidQualifier) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_CORRUPT); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing invalid, t TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing invalid, t TEXT)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, DISABLED_CreateVtableFailsOnMissingTableName) { // TODO(pwnall): Enable test after removing incorrect DLOG(FATAL) from // sql::Statement::Execute(). - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_ERROR); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(main., t TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(main., t TEXT)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, CreateVtableFailsOnMissingSchemaSpec) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_MISUSE); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, CreateVtableFailsOnMissingDbName) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_MISUSE); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(.backing)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(.backing)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, ColumnTypeMappingAny) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); EXPECT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing, t ANY)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing, t ANY)")); sql::test::ColumnInfo column_info = - sql::test::ColumnInfo::Create(&db(), "temp", "recover_backing", "t"); + sql::test::ColumnInfo::Create(&db_, "temp", "recover_backing", "t"); EXPECT_EQ("(nullptr)", column_info.data_type); EXPECT_EQ("BINARY", column_info.collation_sequence); EXPECT_FALSE(column_info.has_non_null_constraint); @@ -145,13 +153,13 @@ TEST_F(RecoverModuleTest, ColumnTypeMappingAny) { EXPECT_FALSE(column_info.is_auto_incremented); } TEST_F(RecoverModuleTest, ColumnTypeMappingAnyNotNull) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); EXPECT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing, t ANY NOT NULL)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing, t ANY NOT NULL)")); sql::test::ColumnInfo column_info = - sql::test::ColumnInfo::Create(&db(), "temp", "recover_backing", "t"); + sql::test::ColumnInfo::Create(&db_, "temp", "recover_backing", "t"); EXPECT_EQ("(nullptr)", column_info.data_type); EXPECT_EQ("BINARY", column_info.collation_sequence); EXPECT_TRUE(column_info.has_non_null_constraint); @@ -159,58 +167,58 @@ TEST_F(RecoverModuleTest, ColumnTypeMappingAnyNotNull) { EXPECT_FALSE(column_info.is_auto_incremented); } TEST_F(RecoverModuleTest, ColumnTypeMappingAnyStrict) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_MISUSE); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing, t ANY STRICT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing, t ANY STRICT)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, ColumnTypeExtraKeyword) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_MISUSE); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing, t INTEGER SOMETHING)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing, t INTEGER SOMETHING)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, ColumnTypeNotNullExtraKeyword) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_MISUSE); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing, t INTEGER NOT NULL SOMETHING)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing, t INTEGER NOT NULL SOMETHING)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, ColumnTypeDoubleTypes) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_MISUSE); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing " - "USING recover(backing, t INTEGER FLOAT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing " + "USING recover(backing, t INTEGER FLOAT)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } TEST_F(RecoverModuleTest, ColumnTypeNotNullDoubleTypes) { - ASSERT_TRUE(db().Execute("CREATE TABLE backing(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE backing(t TEXT)")); { sql::test::ScopedErrorExpecter error_expecter; error_expecter.ExpectError(SQLITE_MISUSE); EXPECT_FALSE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_backing USING recover(" - "backing, t INTEGER NOT NULL TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_backing USING recover(" + "backing, t INTEGER NOT NULL TEXT)")); EXPECT_TRUE(error_expecter.SawExpectedErrors()); } } @@ -220,30 +228,39 @@ class RecoverModuleColumnTypeMappingTest public ::testing::WithParamInterface< std::tuple> { public: + ~RecoverModuleColumnTypeMappingTest() override = default; + void SetUp() override { - RecoverModuleTest::SetUp(); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + ASSERT_TRUE( + db_.Open(temp_dir_.GetPath().AppendASCII("recovery_test.sqlite"))); + ASSERT_TRUE(DatabaseTestPeer::EnableRecoveryExtension(&db_)); + std::string sql = base::StringPrintf("CREATE TABLE backing(data %s)", SchemaType()); - ASSERT_TRUE(db().Execute(sql.c_str())); + ASSERT_TRUE(db_.Execute(sql.c_str())); } - protected: void CreateRecoveryTable(const char* suffix) { std::string sql = base::StringPrintf( "CREATE VIRTUAL TABLE temp.recover_backing " "USING recover(backing, data %s%s)", SchemaType(), suffix); - ASSERT_TRUE(db().Execute(sql.c_str())); + ASSERT_TRUE(db_.Execute(sql.c_str())); } const char* SchemaType() const { return std::get<0>(GetParam()); } const char* ExpectedType() const { return std::get<1>(GetParam()); } bool IsAlwaysNonNull() const { return std::get<2>(GetParam()); } + + protected: + base::ScopedTempDir temp_dir_; + sql::Database db_; }; TEST_P(RecoverModuleColumnTypeMappingTest, Unqualified) { CreateRecoveryTable(""); sql::test::ColumnInfo column_info = - sql::test::ColumnInfo::Create(&db(), "temp", "recover_backing", "data"); + sql::test::ColumnInfo::Create(&db_, "temp", "recover_backing", "data"); EXPECT_EQ(ExpectedType(), column_info.data_type); EXPECT_EQ("BINARY", column_info.collation_sequence); EXPECT_EQ(IsAlwaysNonNull(), column_info.has_non_null_constraint); @@ -253,7 +270,7 @@ TEST_P(RecoverModuleColumnTypeMappingTest, Unqualified) { TEST_P(RecoverModuleColumnTypeMappingTest, NotNull) { CreateRecoveryTable(" NOT NULL"); sql::test::ColumnInfo column_info = - sql::test::ColumnInfo::Create(&db(), "temp", "recover_backing", "data"); + sql::test::ColumnInfo::Create(&db_, "temp", "recover_backing", "data"); EXPECT_EQ(ExpectedType(), column_info.data_type); EXPECT_EQ("BINARY", column_info.collation_sequence); EXPECT_TRUE(column_info.has_non_null_constraint); @@ -263,7 +280,7 @@ TEST_P(RecoverModuleColumnTypeMappingTest, NotNull) { TEST_P(RecoverModuleColumnTypeMappingTest, Strict) { CreateRecoveryTable(" STRICT"); sql::test::ColumnInfo column_info = - sql::test::ColumnInfo::Create(&db(), "temp", "recover_backing", "data"); + sql::test::ColumnInfo::Create(&db_, "temp", "recover_backing", "data"); EXPECT_EQ(ExpectedType(), column_info.data_type); EXPECT_EQ("BINARY", column_info.collation_sequence); EXPECT_EQ(IsAlwaysNonNull(), column_info.has_non_null_constraint); @@ -273,7 +290,7 @@ TEST_P(RecoverModuleColumnTypeMappingTest, Strict) { TEST_P(RecoverModuleColumnTypeMappingTest, StrictNotNull) { CreateRecoveryTable(" STRICT NOT NULL"); sql::test::ColumnInfo column_info = - sql::test::ColumnInfo::Create(&db(), "temp", "recover_backing", "data"); + sql::test::ColumnInfo::Create(&db_, "temp", "recover_backing", "data"); EXPECT_EQ(ExpectedType(), column_info.data_type); EXPECT_EQ("BINARY", column_info.collation_sequence); EXPECT_TRUE(column_info.has_non_null_constraint); @@ -305,12 +322,12 @@ void GenerateAlteredTable(sql::Database* db) { } // namespace TEST_F(RecoverModuleTest, ReadFromAlteredTableNullDefaults) { - GenerateAlteredTable(&db()); + GenerateAlteredTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_altered " - "USING recover(altered, t TEXT, i INTEGER)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_altered " + "USING recover(altered, t TEXT, i INTEGER)")); - sql::Statement statement(db().GetUniqueStatement( + sql::Statement statement(db_.GetUniqueStatement( "SELECT t, i FROM recover_altered ORDER BY rowid")); ASSERT_TRUE(statement.Step()); EXPECT_EQ("a", statement.ColumnString(0)); @@ -329,12 +346,12 @@ TEST_F(RecoverModuleTest, ReadFromAlteredTableNullDefaults) { } TEST_F(RecoverModuleTest, ReadFromAlteredTableSkipsNulls) { - GenerateAlteredTable(&db()); + GenerateAlteredTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_altered " - "USING recover(altered, t TEXT, i INTEGER NOT NULL)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_altered " + "USING recover(altered, t TEXT, i INTEGER NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + sql::Statement statement(db_.GetUniqueStatement( "SELECT t, i FROM recover_altered ORDER BY rowid")); ASSERT_TRUE(statement.Step()); EXPECT_EQ("d", statement.ColumnString(0)); @@ -366,13 +383,13 @@ void GenerateSizedTable(sql::Database* db, } // namespace TEST_F(RecoverModuleTest, LeafNodes) { - GenerateSizedTable(&db(), 10, "Leaf-node-generating line "); + GenerateSizedTable(&db_, 10, "Leaf-node-generating line "); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_sized " - "USING recover(sized, t TEXT, i INTEGER NOT NULL)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_sized " + "USING recover(sized, t TEXT, i INTEGER NOT NULL)")); sql::Statement statement( - db().GetUniqueStatement("SELECT t, i FROM recover_sized ORDER BY rowid")); + db_.GetUniqueStatement("SELECT t, i FROM recover_sized ORDER BY rowid")); for (int i = 0; i < 10; ++i) { ASSERT_TRUE(statement.Step()); EXPECT_EQ(base::StringPrintf("Leaf-node-generating line %d", i), @@ -383,22 +400,22 @@ TEST_F(RecoverModuleTest, LeafNodes) { } TEST_F(RecoverModuleTest, EmptyTable) { - GenerateSizedTable(&db(), 0, ""); + GenerateSizedTable(&db_, 0, ""); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_sized " - "USING recover(sized, t TEXT, i INTEGER NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_sized " + "USING recover(sized, t TEXT, i INTEGER NOT NULL)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, t, i FROM recover_sized ORDER BY rowid")); EXPECT_FALSE(statement.Step()); } TEST_F(RecoverModuleTest, SingleLevelInteriorNodes) { - GenerateSizedTable(&db(), 100, "Interior-node-generating line "); + GenerateSizedTable(&db_, 100, "Interior-node-generating line "); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_sized " - "USING recover(sized, t TEXT, i INTEGER NOT NULL)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_sized " + "USING recover(sized, t TEXT, i INTEGER NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, t, i FROM recover_sized ORDER BY rowid")); for (int i = 0; i < 100; ++i) { ASSERT_TRUE(statement.Step()); @@ -411,12 +428,12 @@ TEST_F(RecoverModuleTest, SingleLevelInteriorNodes) { } TEST_F(RecoverModuleTest, MultiLevelInteriorNodes) { - GenerateSizedTable(&db(), 5000, "Interior-node-generating line "); + GenerateSizedTable(&db_, 5000, "Interior-node-generating line "); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_sized " - "USING recover(sized, t TEXT, i INTEGER NOT NULL)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_sized " + "USING recover(sized, t TEXT, i INTEGER NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, t, i FROM recover_sized ORDER BY rowid")); for (int i = 0; i < 5000; ++i) { ASSERT_TRUE(statement.Step()); @@ -444,11 +461,11 @@ void GenerateTypesTable(sql::Database* db) { } // namespace TEST_F(RecoverModuleTest, Any) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value ANY)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value ANY)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -482,11 +499,11 @@ TEST_F(RecoverModuleTest, Any) { } TEST_F(RecoverModuleTest, Integers) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value INTEGER)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value INTEGER)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -503,11 +520,11 @@ TEST_F(RecoverModuleTest, Integers) { } TEST_F(RecoverModuleTest, NonNullIntegers) { - GenerateTypesTable(&db()); - ASSERT_TRUE(db().Execute( + GenerateTypesTable(&db_); + ASSERT_TRUE(db_.Execute( "CREATE VIRTUAL TABLE temp.recover_types " "USING recover(types, rowtype TEXT, value INTEGER NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -520,11 +537,11 @@ TEST_F(RecoverModuleTest, NonNullIntegers) { } TEST_F(RecoverModuleTest, Floats) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value FLOAT)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value FLOAT)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -546,11 +563,11 @@ TEST_F(RecoverModuleTest, Floats) { } TEST_F(RecoverModuleTest, NonNullFloats) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value FLOAT NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value FLOAT NOT NULL)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -568,11 +585,11 @@ TEST_F(RecoverModuleTest, NonNullFloats) { } TEST_F(RecoverModuleTest, FloatsStrict) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value FLOAT STRICT)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value FLOAT STRICT)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -589,11 +606,11 @@ TEST_F(RecoverModuleTest, FloatsStrict) { } TEST_F(RecoverModuleTest, NonNullFloatsStrict) { - GenerateTypesTable(&db()); - ASSERT_TRUE(db().Execute( + GenerateTypesTable(&db_); + ASSERT_TRUE(db_.Execute( "CREATE VIRTUAL TABLE temp.recover_types " "USING recover(types, rowtype TEXT, value FLOAT STRICT NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -606,11 +623,11 @@ TEST_F(RecoverModuleTest, NonNullFloatsStrict) { } TEST_F(RecoverModuleTest, Texts) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value TEXT)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value TEXT)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -634,11 +651,11 @@ TEST_F(RecoverModuleTest, Texts) { } TEST_F(RecoverModuleTest, NonNullTexts) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value TEXT NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value TEXT NOT NULL)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -658,11 +675,11 @@ TEST_F(RecoverModuleTest, NonNullTexts) { } TEST_F(RecoverModuleTest, TextsStrict) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value TEXT STRICT)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value TEXT STRICT)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -679,11 +696,11 @@ TEST_F(RecoverModuleTest, TextsStrict) { } TEST_F(RecoverModuleTest, NonNullTextsStrict) { - GenerateTypesTable(&db()); - ASSERT_TRUE(db().Execute( + GenerateTypesTable(&db_); + ASSERT_TRUE(db_.Execute( "CREATE VIRTUAL TABLE temp.recover_types " "USING recover(types, rowtype TEXT, value TEXT STRICT NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -696,11 +713,11 @@ TEST_F(RecoverModuleTest, NonNullTextsStrict) { } TEST_F(RecoverModuleTest, Blobs) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value BLOB)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value BLOB)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -719,11 +736,11 @@ TEST_F(RecoverModuleTest, Blobs) { } TEST_F(RecoverModuleTest, NonNullBlobs) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value BLOB NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value BLOB NOT NULL)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -738,11 +755,11 @@ TEST_F(RecoverModuleTest, NonNullBlobs) { } TEST_F(RecoverModuleTest, AnyNonNull) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_types " - "USING recover(types, rowtype TEXT, value ANY NOT NULL)")); - sql::Statement statement(db().GetUniqueStatement( + db_.Execute("CREATE VIRTUAL TABLE temp.recover_types " + "USING recover(types, rowtype TEXT, value ANY NOT NULL)")); + sql::Statement statement(db_.GetUniqueStatement( "SELECT rowid, rowtype, value FROM recover_types")); ASSERT_TRUE(statement.Step()); @@ -772,20 +789,20 @@ TEST_F(RecoverModuleTest, AnyNonNull) { } TEST_F(RecoverModuleTest, RowidAlias) { - GenerateTypesTable(&db()); + GenerateTypesTable(&db_); // The id column is an alias for rowid, and its values get serialized as NULL. - ASSERT_TRUE(db().Execute( + ASSERT_TRUE(db_.Execute( "CREATE TABLE types2(id INTEGER PRIMARY KEY, rowtype TEXT, value)")); ASSERT_TRUE( - db().Execute("INSERT INTO types2(id, rowtype, value) " - "SELECT rowid, rowtype, value FROM types WHERE true")); - ASSERT_TRUE(db().Execute( + db_.Execute("INSERT INTO types2(id, rowtype, value) " + "SELECT rowid, rowtype, value FROM types WHERE true")); + ASSERT_TRUE(db_.Execute( "CREATE VIRTUAL TABLE temp.recover_types2 " "USING recover(types2, id ROWID NOT NULL, rowtype TEXT, value ANY)")); sql::Statement statement( - db().GetUniqueStatement("SELECT id, rowid, rowtype, value FROM types2")); + db_.GetUniqueStatement("SELECT id, rowid, rowtype, value FROM types2")); ASSERT_TRUE(statement.Step()); EXPECT_EQ(1, statement.ColumnInt(0)); @@ -819,7 +836,7 @@ TEST_F(RecoverModuleTest, RowidAlias) { } TEST_F(RecoverModuleTest, IntegerEncodings) { - ASSERT_TRUE(db().Execute("CREATE TABLE integers(value)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE integers(value)")); const std::vector values = { // Encoded directly in type info. @@ -857,7 +874,7 @@ TEST_F(RecoverModuleTest, IntegerEncodings) { -9223372036854775807, }; sql::Statement insert( - db().GetUniqueStatement("INSERT INTO integers VALUES(?)")); + db_.GetUniqueStatement("INSERT INTO integers VALUES(?)")); for (int64_t value : values) { insert.BindInt64(0, value); ASSERT_TRUE(insert.Run()); @@ -865,10 +882,10 @@ TEST_F(RecoverModuleTest, IntegerEncodings) { } ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_integers " - "USING recover(integers, value INTEGER)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_integers " + "USING recover(integers, value INTEGER)")); sql::Statement select( - db().GetUniqueStatement("SELECT rowid, value FROM recover_integers")); + db_.GetUniqueStatement("SELECT rowid, value FROM recover_integers")); for (size_t i = 0; i < values.size(); ++i) { ASSERT_TRUE(select.Step()) << "Was attemping to read " << values[i]; EXPECT_EQ(static_cast(i + 1), select.ColumnInt(0)); @@ -967,30 +984,30 @@ TEST_F(RecoverModuleTest, VarintEncodings) { -0x8000000000000000, }; - ASSERT_TRUE(db().Execute("CREATE TABLE varints(value INTEGER PRIMARY KEY)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE varints(value INTEGER PRIMARY KEY)")); ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_varints " - "USING recover(varints, value ROWID)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_varints " + "USING recover(varints, value ROWID)")); for (int64_t value : values) { sql::Statement insert( - db().GetUniqueStatement("INSERT INTO varints VALUES(?)")); + db_.GetUniqueStatement("INSERT INTO varints VALUES(?)")); insert.BindInt64(0, value); ASSERT_TRUE(insert.Run()); sql::Statement select( - db().GetUniqueStatement("SELECT rowid, value FROM recover_varints")); + db_.GetUniqueStatement("SELECT rowid, value FROM recover_varints")); ASSERT_TRUE(select.Step()) << "Was attemping to read " << value; EXPECT_EQ(value, select.ColumnInt64(0)); EXPECT_EQ(value, select.ColumnInt64(1)); EXPECT_FALSE(select.Step()); - ASSERT_TRUE(db().Execute("DELETE FROM varints")); + ASSERT_TRUE(db_.Execute("DELETE FROM varints")); } } TEST_F(RecoverModuleTest, TextEncodings) { - ASSERT_TRUE(db().Execute("CREATE TABLE encodings(t TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE encodings(t TEXT)")); const std::vector values = { "", "a", u8"ö", u8"Mjollnir", u8"Mjölnir", @@ -998,7 +1015,7 @@ TEST_F(RecoverModuleTest, TextEncodings) { }; sql::Statement insert( - db().GetUniqueStatement("INSERT INTO encodings VALUES(?)")); + db_.GetUniqueStatement("INSERT INTO encodings VALUES(?)")); for (const std::string& value : values) { insert.BindString(0, value); ASSERT_TRUE(insert.Run()); @@ -1006,10 +1023,10 @@ TEST_F(RecoverModuleTest, TextEncodings) { } ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_encodings " - "USING recover(encodings, t TEXT)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_encodings " + "USING recover(encodings, t TEXT)")); sql::Statement select( - db().GetUniqueStatement("SELECT rowid, t FROM recover_encodings")); + db_.GetUniqueStatement("SELECT rowid, t FROM recover_encodings")); for (size_t i = 0; i < values.size(); ++i) { ASSERT_TRUE(select.Step()); EXPECT_EQ(static_cast(i + 1), select.ColumnInt(0)); @@ -1019,7 +1036,7 @@ TEST_F(RecoverModuleTest, TextEncodings) { } TEST_F(RecoverModuleTest, BlobEncodings) { - ASSERT_TRUE(db().Execute("CREATE TABLE blob_encodings(t BLOB)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE blob_encodings(t BLOB)")); const std::vector> values = { {}, {0x00}, {0x01}, @@ -1028,7 +1045,7 @@ TEST_F(RecoverModuleTest, BlobEncodings) { }; sql::Statement insert( - db().GetUniqueStatement("INSERT INTO blob_encodings VALUES(?)")); + db_.GetUniqueStatement("INSERT INTO blob_encodings VALUES(?)")); for (const std::vector& value : values) { // std::vector::data() returns nullptr for empty vectors. Unfortunately, // sqlite3_bind_blob() always interprets null data as a NULL value. In this @@ -1043,10 +1060,10 @@ TEST_F(RecoverModuleTest, BlobEncodings) { } ASSERT_TRUE( - db().Execute("CREATE VIRTUAL TABLE temp.recover_blob_encodings " - "USING recover(blob_encodings, t BLOB)")); + db_.Execute("CREATE VIRTUAL TABLE temp.recover_blob_encodings " + "USING recover(blob_encodings, t BLOB)")); sql::Statement select( - db().GetUniqueStatement("SELECT rowid, t FROM recover_blob_encodings")); + db_.GetUniqueStatement("SELECT rowid, t FROM recover_blob_encodings")); for (size_t i = 0; i < values.size(); ++i) { ASSERT_TRUE(select.Step()); EXPECT_EQ(static_cast(i + 1), select.ColumnInt(0)); @@ -1113,60 +1130,60 @@ constexpr int kOverflowOverhead = 4; } // namespace TEST_F(RecoverModuleTest, ValueWithoutOverflow) { - CheckLargeValueRecovery(&db(), db().page_size() - kRecordOverhead); - int auto_vacuum_pages = HasEnabledAutoVacuum(&db()) ? 1 : 0; - ASSERT_EQ(2 + auto_vacuum_pages, sql::test::GetPageCount(&db())) + CheckLargeValueRecovery(&db_, db_.page_size() - kRecordOverhead); + int auto_vacuum_pages = HasEnabledAutoVacuum(&db_) ? 1 : 0; + ASSERT_EQ(2 + auto_vacuum_pages, sql::test::GetPageCount(&db_)) << "Database should have a root page and a leaf page"; } TEST_F(RecoverModuleTest, ValueWithOneByteOverflow) { - CheckLargeValueRecovery(&db(), db().page_size() - kRecordOverhead + 1); - int auto_vacuum_pages = HasEnabledAutoVacuum(&db()) ? 1 : 0; - ASSERT_EQ(3 + auto_vacuum_pages, sql::test::GetPageCount(&db())) + CheckLargeValueRecovery(&db_, db_.page_size() - kRecordOverhead + 1); + int auto_vacuum_pages = HasEnabledAutoVacuum(&db_) ? 1 : 0; + ASSERT_EQ(3 + auto_vacuum_pages, sql::test::GetPageCount(&db_)) << "Database should have a root page, a leaf page, and 1 overflow page"; } TEST_F(RecoverModuleTest, ValueWithOneOverflowPage) { CheckLargeValueRecovery( - &db(), db().page_size() - kRecordOverhead + db().page_size() / 2); - int auto_vacuum_pages = HasEnabledAutoVacuum(&db()) ? 1 : 0; - ASSERT_EQ(3 + auto_vacuum_pages, sql::test::GetPageCount(&db())) + &db_, db_.page_size() - kRecordOverhead + db_.page_size() / 2); + int auto_vacuum_pages = HasEnabledAutoVacuum(&db_) ? 1 : 0; + ASSERT_EQ(3 + auto_vacuum_pages, sql::test::GetPageCount(&db_)) << "Database should have a root page, a leaf page, and 1 overflow page"; } TEST_F(RecoverModuleTest, ValueWithOneFullOverflowPage) { - CheckLargeValueRecovery(&db(), db().page_size() - kRecordOverhead + - db().page_size() - kOverflowOverhead); - int auto_vacuum_pages = HasEnabledAutoVacuum(&db()) ? 1 : 0; - ASSERT_EQ(3 + auto_vacuum_pages, sql::test::GetPageCount(&db())) + CheckLargeValueRecovery(&db_, db_.page_size() - kRecordOverhead + + db_.page_size() - kOverflowOverhead); + int auto_vacuum_pages = HasEnabledAutoVacuum(&db_) ? 1 : 0; + ASSERT_EQ(3 + auto_vacuum_pages, sql::test::GetPageCount(&db_)) << "Database should have a root page, a leaf page, and 1 overflow page"; } TEST_F(RecoverModuleTest, ValueWithOneByteSecondOverflowPage) { - CheckLargeValueRecovery(&db(), db().page_size() - kRecordOverhead + - db().page_size() - kOverflowOverhead + 1); - int auto_vacuum_pages = HasEnabledAutoVacuum(&db()) ? 1 : 0; - ASSERT_EQ(4 + auto_vacuum_pages, sql::test::GetPageCount(&db())) + CheckLargeValueRecovery(&db_, db_.page_size() - kRecordOverhead + + db_.page_size() - kOverflowOverhead + 1); + int auto_vacuum_pages = HasEnabledAutoVacuum(&db_) ? 1 : 0; + ASSERT_EQ(4 + auto_vacuum_pages, sql::test::GetPageCount(&db_)) << "Database should have a root page, a leaf page, and 2 overflow pages"; } TEST_F(RecoverModuleTest, ValueWithTwoOverflowPages) { - CheckLargeValueRecovery(&db(), db().page_size() - kRecordOverhead + - db().page_size() - kOverflowOverhead + - db().page_size() / 2); - int auto_vacuum_pages = HasEnabledAutoVacuum(&db()) ? 1 : 0; - ASSERT_EQ(4 + auto_vacuum_pages, sql::test::GetPageCount(&db())) + CheckLargeValueRecovery(&db_, db_.page_size() - kRecordOverhead + + db_.page_size() - kOverflowOverhead + + db_.page_size() / 2); + int auto_vacuum_pages = HasEnabledAutoVacuum(&db_) ? 1 : 0; + ASSERT_EQ(4 + auto_vacuum_pages, sql::test::GetPageCount(&db_)) << "Database should have a root page, a leaf page, and 2 overflow pages"; } TEST_F(RecoverModuleTest, ValueWithTwoFullOverflowPages) { // This value is large enough that the varint encoding of its type ID takes up // 3 bytes, instead of 2. - CheckLargeValueRecovery(&db(), - db().page_size() - kRecordOverhead + - (db().page_size() - kOverflowOverhead) * 2 - 1); - int auto_vacuum_pages = HasEnabledAutoVacuum(&db()) ? 1 : 0; - ASSERT_EQ(4 + auto_vacuum_pages, sql::test::GetPageCount(&db())) + CheckLargeValueRecovery(&db_, db_.page_size() - kRecordOverhead + + (db_.page_size() - kOverflowOverhead) * 2 - + 1); + int auto_vacuum_pages = HasEnabledAutoVacuum(&db_) ? 1 : 0; + ASSERT_EQ(4 + auto_vacuum_pages, sql::test::GetPageCount(&db_)) << "Database should have a root page, a leaf page, and 2 overflow pages"; } diff --git a/sql/recovery_unittest.cc b/sql/recovery_unittest.cc index afd386574f3619..f40290757a0e33 100644 --- a/sql/recovery_unittest.cc +++ b/sql/recovery_unittest.cc @@ -22,11 +22,12 @@ #include "sql/statement.h" #include "sql/test/paths.h" #include "sql/test/scoped_error_expecter.h" -#include "sql/test/sql_test_base.h" #include "sql/test/test_helpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/sqlite/sqlite3.h" +namespace sql { + namespace { using sql::test::ExecuteWithResult; @@ -36,81 +37,104 @@ using sql::test::ExecuteWithResults; // schema. For tables or indices, this will contain the sql command // to create the table or index. For certain automatic SQLite // structures with no sql, the name is used. -std::string GetSchema(sql::Database* db) { +std::string GetSchema(Database* db) { static const char kSql[] = "SELECT COALESCE(sql, name) FROM sqlite_master ORDER BY 1"; return ExecuteWithResults(db, kSql, "|", "\n"); } -using SQLRecoveryTest = sql::SQLTestBase; +class SQLRecoveryTest : public testing::Test { + public: + ~SQLRecoveryTest() override = default; + + void SetUp() override { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + db_path_ = temp_dir_.GetPath().AppendASCII("recovery_test.sqlite"); + ASSERT_TRUE(db_.Open(db_path_)); + } + + bool Reopen() { + db_.Close(); + return db_.Open(db_path_); + } -// Baseline sql::Recovery test covering the different ways to dispose of the -// scoped pointer received from sql::Recovery::Begin(). + bool OverwriteDatabaseHeader() { + base::File file(db_path_, + base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); + static constexpr char kText[] = "Now is the winter of our discontent."; + constexpr int kTextBytes = sizeof(kText) - 1; + return file.Write(0, kText, kTextBytes) == kTextBytes; + } + + protected: + base::ScopedTempDir temp_dir_; + base::FilePath db_path_; + Database db_; +}; + +// Baseline Recovery test covering the different ways to dispose of the +// scoped pointer received from Recovery::Begin(). TEST_F(SQLRecoveryTest, RecoverBasic) { static const char kCreateSql[] = "CREATE TABLE x (t TEXT)"; static const char kInsertSql[] = "INSERT INTO x VALUES ('This is a test')"; static const char kAltInsertSql[] = "INSERT INTO x VALUES ('That was a test')"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute(kInsertSql)); - ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db())); + ASSERT_TRUE(db_.Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute(kInsertSql)); + ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db_)); // If the Recovery handle goes out of scope without being // Recovered(), the database is razed. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery.get()); } - EXPECT_FALSE(db().is_open()); + EXPECT_FALSE(db_.is_open()); ASSERT_TRUE(Reopen()); - EXPECT_TRUE(db().is_open()); - ASSERT_EQ("", GetSchema(&db())); + EXPECT_TRUE(db_.is_open()); + ASSERT_EQ("", GetSchema(&db_)); // Recreate the database. - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute(kInsertSql)); - ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db())); + ASSERT_TRUE(db_.Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute(kInsertSql)); + ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db_)); // Unrecoverable() also razes. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery.get()); - sql::Recovery::Unrecoverable(std::move(recovery)); + Recovery::Unrecoverable(std::move(recovery)); - // TODO(shess): Test that calls to recover.db() start failing. + // TODO(shess): Test that calls to recover.db_ start failing. } - EXPECT_FALSE(db().is_open()); + EXPECT_FALSE(db_.is_open()); ASSERT_TRUE(Reopen()); - EXPECT_TRUE(db().is_open()); - ASSERT_EQ("", GetSchema(&db())); + EXPECT_TRUE(db_.is_open()); + ASSERT_EQ("", GetSchema(&db_)); // Attempting to recover a previously-recovered handle fails early. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery.get()); recovery.reset(); - recovery = sql::Recovery::Begin(&db(), db_path()); + recovery = Recovery::Begin(&db_, db_path_); ASSERT_FALSE(recovery.get()); } ASSERT_TRUE(Reopen()); // Recreate the database. - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute(kInsertSql)); - ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db())); + ASSERT_TRUE(db_.Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute(kInsertSql)); + ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db_)); // Unrecovered table to distinguish from recovered database. - ASSERT_TRUE(db().Execute("CREATE TABLE y (c INTEGER)")); - ASSERT_NE("CREATE TABLE x (t TEXT)", GetSchema(&db())); + ASSERT_TRUE(db_.Execute("CREATE TABLE y (c INTEGER)")); + ASSERT_NE("CREATE TABLE x (t TEXT)", GetSchema(&db_)); // Recovered() replaces the original with the "recovered" version. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery.get()); // Create the new version of the table. @@ -120,50 +144,48 @@ TEST_F(SQLRecoveryTest, RecoverBasic) { ASSERT_TRUE(recovery->db()->Execute(kAltInsertSql)); // Successfully recovered. - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } - EXPECT_FALSE(db().is_open()); + EXPECT_FALSE(db_.is_open()); ASSERT_TRUE(Reopen()); - EXPECT_TRUE(db().is_open()); - ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db())); + EXPECT_TRUE(db_.is_open()); + ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db_)); const char* kXSql = "SELECT * FROM x ORDER BY 1"; - ASSERT_EQ("That was a test", ExecuteWithResult(&db(), kXSql)); + ASSERT_EQ("That was a test", ExecuteWithResult(&db_, kXSql)); // Reset the database contents. - ASSERT_TRUE(db().Execute("DELETE FROM x")); - ASSERT_TRUE(db().Execute(kInsertSql)); + ASSERT_TRUE(db_.Execute("DELETE FROM x")); + ASSERT_TRUE(db_.Execute(kInsertSql)); // Rollback() discards recovery progress and leaves the database as it was. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery.get()); ASSERT_TRUE(recovery->db()->Execute(kCreateSql)); ASSERT_TRUE(recovery->db()->Execute(kAltInsertSql)); - sql::Recovery::Rollback(std::move(recovery)); + Recovery::Rollback(std::move(recovery)); } - EXPECT_FALSE(db().is_open()); + EXPECT_FALSE(db_.is_open()); ASSERT_TRUE(Reopen()); - EXPECT_TRUE(db().is_open()); - ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db())); + EXPECT_TRUE(db_.is_open()); + ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db_)); - ASSERT_EQ("This is a test", ExecuteWithResult(&db(), kXSql)); + ASSERT_EQ("This is a test", ExecuteWithResult(&db_, kXSql)); } -// Test operation of the virtual table used by sql::Recovery. +// Test operation of the virtual table used by Recovery. TEST_F(SQLRecoveryTest, VirtualTable) { static const char kCreateSql[] = "CREATE TABLE x (t TEXT)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test')")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('That was a test')")); + ASSERT_TRUE(db_.Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES ('This is a test')")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES ('That was a test')")); // Successfully recover the database. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); // Tables to recover original DB, now at [corrupt]. static const char kRecoveryCreateSql[] = @@ -182,32 +204,32 @@ TEST_F(SQLRecoveryTest, VirtualTable) { ASSERT_TRUE(recovery->db()->Execute(kRecoveryCopySql)); // Successfully recovered. - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } // Since the database was not corrupt, the entire schema and all // data should be recovered. ASSERT_TRUE(Reopen()); - ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db())); + ASSERT_EQ("CREATE TABLE x (t TEXT)", GetSchema(&db_)); static const char* kXSql = "SELECT * FROM x ORDER BY 1"; ASSERT_EQ("That was a test\nThis is a test", - ExecuteWithResults(&db(), kXSql, "|", "\n")); + ExecuteWithResults(&db_, kXSql, "|", "\n")); } -void RecoveryCallback(sql::Database* db, +void RecoveryCallback(Database* db, const base::FilePath& db_path, const char* create_table, const char* create_index, int* record_error, int error, - sql::Statement* stmt) { + Statement* stmt) { *record_error = error; // Clear the error callback to prevent reentrancy. db->reset_error_callback(); - std::unique_ptr recovery = sql::Recovery::Begin(db, db_path); + std::unique_ptr recovery = Recovery::Begin(db, db_path); ASSERT_TRUE(recovery.get()); ASSERT_TRUE(recovery->db()->Execute(create_table)); @@ -216,7 +238,7 @@ void RecoveryCallback(sql::Database* db, size_t rows = 0; ASSERT_TRUE(recovery->AutoRecoverTable("x", &rows)); - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } // Build a database, corrupt it by making an index reference to @@ -224,15 +246,15 @@ void RecoveryCallback(sql::Database* db, TEST_F(SQLRecoveryTest, RecoverCorruptIndex) { static const char kCreateTable[] = "CREATE TABLE x (id INTEGER, v INTEGER)"; static const char kCreateIndex[] = "CREATE UNIQUE INDEX x_id ON x (id)"; - ASSERT_TRUE(db().Execute(kCreateTable)); - ASSERT_TRUE(db().Execute(kCreateIndex)); + ASSERT_TRUE(db_.Execute(kCreateTable)); + ASSERT_TRUE(db_.Execute(kCreateIndex)); // Insert a bit of data. { - ASSERT_TRUE(db().BeginTransaction()); + ASSERT_TRUE(db_.BeginTransaction()); static const char kInsertSql[] = "INSERT INTO x (id, v) VALUES (?, ?)"; - sql::Statement s(db().GetUniqueStatement(kInsertSql)); + Statement s(db_.GetUniqueStatement(kInsertSql)); for (int i = 0; i < 10; ++i) { s.Reset(true); s.BindInt(0, i); @@ -241,42 +263,42 @@ TEST_F(SQLRecoveryTest, RecoverCorruptIndex) { EXPECT_TRUE(s.Succeeded()); } - ASSERT_TRUE(db().CommitTransaction()); + ASSERT_TRUE(db_.CommitTransaction()); } - db().Close(); + db_.Close(); // Delete a row from the table, while leaving the index entry which // references it. static const char kDeleteSql[] = "DELETE FROM x WHERE id = 0"; - ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path(), "x_id", kDeleteSql)); + ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path_, "x_id", kDeleteSql)); ASSERT_TRUE(Reopen()); int error = SQLITE_OK; - db().set_error_callback(base::BindRepeating( - &RecoveryCallback, &db(), db_path(), kCreateTable, kCreateIndex, &error)); + db_.set_error_callback(base::BindRepeating( + &RecoveryCallback, &db_, db_path_, kCreateTable, kCreateIndex, &error)); // This works before the callback is called. static const char kTrivialSql[] = "SELECT COUNT(*) FROM sqlite_master"; - EXPECT_TRUE(db().IsSQLValid(kTrivialSql)); + EXPECT_TRUE(db_.IsSQLValid(kTrivialSql)); // TODO(shess): Could this be delete? Anything which fails should work. static const char kSelectSql[] = "SELECT v FROM x WHERE id = 0"; - ASSERT_FALSE(db().Execute(kSelectSql)); + ASSERT_FALSE(db_.Execute(kSelectSql)); EXPECT_EQ(SQLITE_CORRUPT, error); // Database handle has been poisoned. - EXPECT_FALSE(db().IsSQLValid(kTrivialSql)); + EXPECT_FALSE(db_.IsSQLValid(kTrivialSql)); ASSERT_TRUE(Reopen()); // The recovered table should reflect the deletion. static const char kSelectAllSql[] = "SELECT v FROM x ORDER BY id"; EXPECT_EQ("1,2,3,4,5,6,7,8,9", - ExecuteWithResults(&db(), kSelectAllSql, "|", ",")); + ExecuteWithResults(&db_, kSelectAllSql, "|", ",")); // The failing statement should now succeed, with no results. - EXPECT_EQ("", ExecuteWithResults(&db(), kSelectSql, "|", ",")); + EXPECT_EQ("", ExecuteWithResults(&db_, kSelectSql, "|", ",")); } // Build a database, corrupt it by making a table contain a row not @@ -284,15 +306,15 @@ TEST_F(SQLRecoveryTest, RecoverCorruptIndex) { TEST_F(SQLRecoveryTest, RecoverCorruptTable) { static const char kCreateTable[] = "CREATE TABLE x (id INTEGER, v INTEGER)"; static const char kCreateIndex[] = "CREATE UNIQUE INDEX x_id ON x (id)"; - ASSERT_TRUE(db().Execute(kCreateTable)); - ASSERT_TRUE(db().Execute(kCreateIndex)); + ASSERT_TRUE(db_.Execute(kCreateTable)); + ASSERT_TRUE(db_.Execute(kCreateIndex)); // Insert a bit of data. { - ASSERT_TRUE(db().BeginTransaction()); + ASSERT_TRUE(db_.BeginTransaction()); static const char kInsertSql[] = "INSERT INTO x (id, v) VALUES (?, ?)"; - sql::Statement s(db().GetUniqueStatement(kInsertSql)); + Statement s(db_.GetUniqueStatement(kInsertSql)); for (int i = 0; i < 10; ++i) { s.Reset(true); s.BindInt(0, i); @@ -301,62 +323,62 @@ TEST_F(SQLRecoveryTest, RecoverCorruptTable) { EXPECT_TRUE(s.Succeeded()); } - ASSERT_TRUE(db().CommitTransaction()); + ASSERT_TRUE(db_.CommitTransaction()); } - db().Close(); + db_.Close(); // Delete a row from the index while leaving a table entry. static const char kDeleteSql[] = "DELETE FROM x WHERE id = 0"; - ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path(), "x", kDeleteSql)); + ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path_, "x", kDeleteSql)); ASSERT_TRUE(Reopen()); int error = SQLITE_OK; - db().set_error_callback(base::BindRepeating( - &RecoveryCallback, &db(), db_path(), kCreateTable, kCreateIndex, &error)); + db_.set_error_callback(base::BindRepeating( + &RecoveryCallback, &db_, db_path_, kCreateTable, kCreateIndex, &error)); // Index shows one less than originally inserted. static const char kCountSql[] = "SELECT COUNT (*) FROM x"; - EXPECT_EQ("9", ExecuteWithResult(&db(), kCountSql)); + EXPECT_EQ("9", ExecuteWithResult(&db_, kCountSql)); // A full table scan shows all of the original data. Using column [v] to // force use of the table rather than the index. static const char kDistinctSql[] = "SELECT DISTINCT COUNT (v) FROM x"; - EXPECT_EQ("10", ExecuteWithResult(&db(), kDistinctSql)); + EXPECT_EQ("10", ExecuteWithResult(&db_, kDistinctSql)); // Insert id 0 again. Since it is not in the index, the insert // succeeds, but results in a duplicate value in the table. static const char kInsertSql[] = "INSERT INTO x (id, v) VALUES (0, 100)"; - ASSERT_TRUE(db().Execute(kInsertSql)); + ASSERT_TRUE(db_.Execute(kInsertSql)); // Duplication is visible. - EXPECT_EQ("10", ExecuteWithResult(&db(), kCountSql)); - EXPECT_EQ("11", ExecuteWithResult(&db(), kDistinctSql)); + EXPECT_EQ("10", ExecuteWithResult(&db_, kCountSql)); + EXPECT_EQ("11", ExecuteWithResult(&db_, kDistinctSql)); // This works before the callback is called. static const char kTrivialSql[] = "SELECT COUNT(*) FROM sqlite_master"; - EXPECT_TRUE(db().IsSQLValid(kTrivialSql)); + EXPECT_TRUE(db_.IsSQLValid(kTrivialSql)); // TODO(shess): Figure out a statement which causes SQLite to notice the // corruption. SELECT doesn't see errors because missing index values aren't // visible. UPDATE or DELETE against v=0 don't see errors, even though the // index item is missing. I suspect SQLite only deletes the key in these // cases, but doesn't verify that one or more keys were deleted. - ASSERT_FALSE(db().Execute("INSERT INTO x (id, v) VALUES (0, 101)")); + ASSERT_FALSE(db_.Execute("INSERT INTO x (id, v) VALUES (0, 101)")); EXPECT_EQ(SQLITE_CONSTRAINT_UNIQUE, error); // Database handle has been poisoned. - EXPECT_FALSE(db().IsSQLValid(kTrivialSql)); + EXPECT_FALSE(db_.IsSQLValid(kTrivialSql)); ASSERT_TRUE(Reopen()); // The recovered table has consistency between the index and the table. - EXPECT_EQ("10", ExecuteWithResult(&db(), kCountSql)); - EXPECT_EQ("10", ExecuteWithResult(&db(), kDistinctSql)); + EXPECT_EQ("10", ExecuteWithResult(&db_, kCountSql)); + EXPECT_EQ("10", ExecuteWithResult(&db_, kDistinctSql)); // Only one of the values is retained. static const char kSelectSql[] = "SELECT v FROM x WHERE id = 0"; - const std::string results = ExecuteWithResult(&db(), kSelectSql); + const std::string results = ExecuteWithResult(&db_, kSelectSql); EXPECT_TRUE(results=="100" || results=="0") << "Actual results: " << results; } @@ -365,45 +387,42 @@ TEST_F(SQLRecoveryTest, Meta) { const int kCompatibleVersion = 2; { - sql::MetaTable meta; - EXPECT_TRUE(meta.Init(&db(), kVersion, kCompatibleVersion)); + MetaTable meta; + EXPECT_TRUE(meta.Init(&db_, kVersion, kCompatibleVersion)); EXPECT_EQ(kVersion, meta.GetVersionNumber()); } // Test expected case where everything works. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); EXPECT_TRUE(recovery->SetupMeta()); int version = 0; EXPECT_TRUE(recovery->GetMetaVersionNumber(&version)); EXPECT_EQ(kVersion, version); - sql::Recovery::Rollback(std::move(recovery)); + Recovery::Rollback(std::move(recovery)); } ASSERT_TRUE(Reopen()); // Handle was poisoned. // Test version row missing. - EXPECT_TRUE(db().Execute("DELETE FROM meta WHERE key = 'version'")); + EXPECT_TRUE(db_.Execute("DELETE FROM meta WHERE key = 'version'")); { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); EXPECT_TRUE(recovery->SetupMeta()); int version = 0; EXPECT_FALSE(recovery->GetMetaVersionNumber(&version)); EXPECT_EQ(0, version); - sql::Recovery::Rollback(std::move(recovery)); + Recovery::Rollback(std::move(recovery)); } ASSERT_TRUE(Reopen()); // Handle was poisoned. // Test meta table missing. - EXPECT_TRUE(db().Execute("DROP TABLE meta")); + EXPECT_TRUE(db_.Execute("DROP TABLE meta")); { sql::test::ScopedErrorExpecter expecter; expecter.ExpectError(SQLITE_CORRUPT); // From virtual table. - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); EXPECT_FALSE(recovery->SetupMeta()); ASSERT_TRUE(expecter.SawExpectedErrors()); } @@ -414,23 +433,22 @@ TEST_F(SQLRecoveryTest, AutoRecoverTable) { // BIGINT and VARCHAR to test type affinity. static const char kCreateSql[] = "CREATE TABLE x (id BIGINT, t TEXT, v VARCHAR)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (11, 'This is', 'a test')")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (5, 'That was', 'a test')")); + ASSERT_TRUE(db_.Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (11, 'This is', 'a test')")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (5, 'That was', 'a test')")); // Save aside a copy of the original schema and data. - const std::string orig_schema(GetSchema(&db())); + const std::string orig_schema(GetSchema(&db_)); static const char kXSql[] = "SELECT * FROM x ORDER BY 1"; - const std::string orig_data(ExecuteWithResults(&db(), kXSql, "|", "\n")); + const std::string orig_data(ExecuteWithResults(&db_, kXSql, "|", "\n")); // Create a lame-duck table which will not be propagated by recovery to // detect that the recovery code actually ran. - ASSERT_TRUE(db().Execute("CREATE TABLE y (c TEXT)")); - ASSERT_NE(orig_schema, GetSchema(&db())); + ASSERT_TRUE(db_.Execute("CREATE TABLE y (c TEXT)")); + ASSERT_NE(orig_schema, GetSchema(&db_)); { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery->db()->Execute(kCreateSql)); // Save a copy of the temp db's schema before recovering the table. @@ -447,26 +465,25 @@ TEST_F(SQLRecoveryTest, AutoRecoverTable) { EXPECT_EQ(temp_schema, ExecuteWithResults(recovery->db(), kTempSchemaSql, "|", "\n")); - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } // Since the database was not corrupt, the entire schema and all // data should be recovered. ASSERT_TRUE(Reopen()); - ASSERT_EQ(orig_schema, GetSchema(&db())); - ASSERT_EQ(orig_data, ExecuteWithResults(&db(), kXSql, "|", "\n")); + ASSERT_EQ(orig_schema, GetSchema(&db_)); + ASSERT_EQ(orig_data, ExecuteWithResults(&db_, kXSql, "|", "\n")); // Recovery fails if the target table doesn't exist. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery->db()->Execute(kCreateSql)); // TODO(shess): Should this failure implicitly lead to Raze()? size_t rows = 0; EXPECT_FALSE(recovery->AutoRecoverTable("y", &rows)); - sql::Recovery::Unrecoverable(std::move(recovery)); + Recovery::Unrecoverable(std::move(recovery)); } } @@ -474,30 +491,30 @@ TEST_F(SQLRecoveryTest, AutoRecoverTable) { // virtual table reads directly from the database, so DEFAULT is not // interpretted at that level. TEST_F(SQLRecoveryTest, AutoRecoverTableWithDefault) { - ASSERT_TRUE(db().Execute("CREATE TABLE x (id INTEGER)")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (5)")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (15)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE x (id INTEGER)")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (5)")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (15)")); // ALTER effectively leaves the new columns NULL in the first two // rows. The row with 17 will get the default injected at insert // time, while the row with 42 will get the actual value provided. // Embedded "'" to make sure default-handling continues to be quoted // correctly. - ASSERT_TRUE(db().Execute("ALTER TABLE x ADD COLUMN t TEXT DEFAULT 'a''a'")); - ASSERT_TRUE(db().Execute("ALTER TABLE x ADD COLUMN b BLOB DEFAULT x'AA55'")); - ASSERT_TRUE(db().Execute("ALTER TABLE x ADD COLUMN i INT DEFAULT 93")); - ASSERT_TRUE(db().Execute("INSERT INTO x (id) VALUES (17)")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (42, 'b', x'1234', 12)")); + ASSERT_TRUE(db_.Execute("ALTER TABLE x ADD COLUMN t TEXT DEFAULT 'a''a'")); + ASSERT_TRUE(db_.Execute("ALTER TABLE x ADD COLUMN b BLOB DEFAULT x'AA55'")); + ASSERT_TRUE(db_.Execute("ALTER TABLE x ADD COLUMN i INT DEFAULT 93")); + ASSERT_TRUE(db_.Execute("INSERT INTO x (id) VALUES (17)")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (42, 'b', x'1234', 12)")); // Save aside a copy of the original schema and data. - const std::string orig_schema(GetSchema(&db())); + const std::string orig_schema(GetSchema(&db_)); static const char kXSql[] = "SELECT * FROM x ORDER BY 1"; - const std::string orig_data(ExecuteWithResults(&db(), kXSql, "|", "\n")); + const std::string orig_data(ExecuteWithResults(&db_, kXSql, "|", "\n")); // Create a lame-duck table which will not be propagated by recovery to // detect that the recovery code actually ran. - ASSERT_TRUE(db().Execute("CREATE TABLE y (c TEXT)")); - ASSERT_NE(orig_schema, GetSchema(&db())); + ASSERT_TRUE(db_.Execute("CREATE TABLE y (c TEXT)")); + ASSERT_NE(orig_schema, GetSchema(&db_)); // Mechanically adjust the stored schema and data to allow detecting // where the default value is coming from. The target table is just @@ -516,8 +533,7 @@ TEST_F(SQLRecoveryTest, AutoRecoverTableWithDefault) { } { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); // Different default to detect which table provides the default. ASSERT_TRUE(recovery->db()->Execute(final_schema.c_str())); @@ -525,14 +541,14 @@ TEST_F(SQLRecoveryTest, AutoRecoverTableWithDefault) { EXPECT_TRUE(recovery->AutoRecoverTable("x", &rows)); EXPECT_EQ(4u, rows); - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } // Since the database was not corrupt, the entire schema and all // data should be recovered. ASSERT_TRUE(Reopen()); - ASSERT_EQ(final_schema, GetSchema(&db())); - ASSERT_EQ(final_data, ExecuteWithResults(&db(), kXSql, "|", "\n")); + ASSERT_EQ(final_schema, GetSchema(&db_)); + ASSERT_EQ(final_data, ExecuteWithResults(&db_, kXSql, "|", "\n")); } // Test that rows with NULL in a NOT NULL column are filtered @@ -544,34 +560,33 @@ TEST_F(SQLRecoveryTest, AutoRecoverTableNullFilter) { static const char kFinalSchema[] = "CREATE TABLE x (id INTEGER, t TEXT NOT NULL)"; - ASSERT_TRUE(db().Execute(kOrigSchema)); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (5, NULL)")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (15, 'this is a test')")); + ASSERT_TRUE(db_.Execute(kOrigSchema)); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (5, NULL)")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (15, 'this is a test')")); // Create a lame-duck table which will not be propagated by recovery to // detect that the recovery code actually ran. - ASSERT_EQ(kOrigSchema, GetSchema(&db())); - ASSERT_TRUE(db().Execute("CREATE TABLE y (c TEXT)")); - ASSERT_NE(kOrigSchema, GetSchema(&db())); + ASSERT_EQ(kOrigSchema, GetSchema(&db_)); + ASSERT_TRUE(db_.Execute("CREATE TABLE y (c TEXT)")); + ASSERT_NE(kOrigSchema, GetSchema(&db_)); { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery->db()->Execute(kFinalSchema)); size_t rows = 0; EXPECT_TRUE(recovery->AutoRecoverTable("x", &rows)); EXPECT_EQ(1u, rows); - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } // The schema should be the same, but only one row of data should // have been recovered. ASSERT_TRUE(Reopen()); - ASSERT_EQ(kFinalSchema, GetSchema(&db())); + ASSERT_EQ(kFinalSchema, GetSchema(&db_)); static const char kXSql[] = "SELECT * FROM x ORDER BY 1"; - ASSERT_EQ("15|this is a test", ExecuteWithResults(&db(), kXSql, "|", "\n")); + ASSERT_EQ("15|this is a test", ExecuteWithResults(&db_, kXSql, "|", "\n")); } // Test AutoRecoverTable with a ROWID alias. @@ -580,37 +595,36 @@ TEST_F(SQLRecoveryTest, AutoRecoverTableWithRowid) { // put it later. static const char kCreateSql[] = "CREATE TABLE x (t TEXT, id INTEGER PRIMARY KEY NOT NULL)"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test', NULL)")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('That was a test', NULL)")); + ASSERT_TRUE(db_.Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES ('This is a test', NULL)")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES ('That was a test', NULL)")); // Save aside a copy of the original schema and data. - const std::string orig_schema(GetSchema(&db())); + const std::string orig_schema(GetSchema(&db_)); static const char kXSql[] = "SELECT * FROM x ORDER BY 1"; - const std::string orig_data(ExecuteWithResults(&db(), kXSql, "|", "\n")); + const std::string orig_data(ExecuteWithResults(&db_, kXSql, "|", "\n")); // Create a lame-duck table which will not be propagated by recovery to // detect that the recovery code actually ran. - ASSERT_TRUE(db().Execute("CREATE TABLE y (c TEXT)")); - ASSERT_NE(orig_schema, GetSchema(&db())); + ASSERT_TRUE(db_.Execute("CREATE TABLE y (c TEXT)")); + ASSERT_NE(orig_schema, GetSchema(&db_)); { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery->db()->Execute(kCreateSql)); size_t rows = 0; EXPECT_TRUE(recovery->AutoRecoverTable("x", &rows)); EXPECT_EQ(2u, rows); - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } // Since the database was not corrupt, the entire schema and all // data should be recovered. ASSERT_TRUE(Reopen()); - ASSERT_EQ(orig_schema, GetSchema(&db())); - ASSERT_EQ(orig_data, ExecuteWithResults(&db(), kXSql, "|", "\n")); + ASSERT_EQ(orig_schema, GetSchema(&db_)); + ASSERT_EQ(orig_data, ExecuteWithResults(&db_, kXSql, "|", "\n")); } // Test that a compound primary key doesn't fire the ROWID code. @@ -622,41 +636,40 @@ TEST_F(SQLRecoveryTest, AutoRecoverTableWithCompoundKey) { "t TEXT," "PRIMARY KEY (id, id2)" ")"; - ASSERT_TRUE(db().Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute(kCreateSql)); // NOTE(shess): Do not accidentally use [id] 1, 2, 3, as those will // be the ROWID values. - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (1, 'a', 'This is a test')")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (1, 'b', 'That was a test')")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (2, 'a', 'Another test')")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (1, 'a', 'This is a test')")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (1, 'b', 'That was a test')")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (2, 'a', 'Another test')")); // Save aside a copy of the original schema and data. - const std::string orig_schema(GetSchema(&db())); + const std::string orig_schema(GetSchema(&db_)); static const char kXSql[] = "SELECT * FROM x ORDER BY 1"; - const std::string orig_data(ExecuteWithResults(&db(), kXSql, "|", "\n")); + const std::string orig_data(ExecuteWithResults(&db_, kXSql, "|", "\n")); // Create a lame-duck table which will not be propagated by recovery to // detect that the recovery code actually ran. - ASSERT_TRUE(db().Execute("CREATE TABLE y (c TEXT)")); - ASSERT_NE(orig_schema, GetSchema(&db())); + ASSERT_TRUE(db_.Execute("CREATE TABLE y (c TEXT)")); + ASSERT_NE(orig_schema, GetSchema(&db_)); { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery->db()->Execute(kCreateSql)); size_t rows = 0; EXPECT_TRUE(recovery->AutoRecoverTable("x", &rows)); EXPECT_EQ(3u, rows); - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } // Since the database was not corrupt, the entire schema and all // data should be recovered. ASSERT_TRUE(Reopen()); - ASSERT_EQ(orig_schema, GetSchema(&db())); - ASSERT_EQ(orig_data, ExecuteWithResults(&db(), kXSql, "|", "\n")); + ASSERT_EQ(orig_schema, GetSchema(&db_)); + ASSERT_EQ(orig_data, ExecuteWithResults(&db_, kXSql, "|", "\n")); } // Test recovering from a table with fewer columns than the target. @@ -665,46 +678,45 @@ TEST_F(SQLRecoveryTest, AutoRecoverTableMissingColumns) { "CREATE TABLE x (id INTEGER PRIMARY KEY, t0 TEXT)"; static const char kAlterSql[] = "ALTER TABLE x ADD COLUMN t1 TEXT DEFAULT 't'"; - ASSERT_TRUE(db().Execute(kCreateSql)); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (1, 'This is')")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES (2, 'That was')")); + ASSERT_TRUE(db_.Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (1, 'This is')")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES (2, 'That was')")); // Generate the expected info by faking a table to match what recovery will // create. - const std::string orig_schema(GetSchema(&db())); + const std::string orig_schema(GetSchema(&db_)); static const char kXSql[] = "SELECT * FROM x ORDER BY 1"; std::string expected_schema; std::string expected_data; { - ASSERT_TRUE(db().BeginTransaction()); - ASSERT_TRUE(db().Execute(kAlterSql)); + ASSERT_TRUE(db_.BeginTransaction()); + ASSERT_TRUE(db_.Execute(kAlterSql)); - expected_schema = GetSchema(&db()); - expected_data = ExecuteWithResults(&db(), kXSql, "|", "\n"); + expected_schema = GetSchema(&db_); + expected_data = ExecuteWithResults(&db_, kXSql, "|", "\n"); - db().RollbackTransaction(); + db_.RollbackTransaction(); } // Following tests are pointless if the rollback didn't work. - ASSERT_EQ(orig_schema, GetSchema(&db())); + ASSERT_EQ(orig_schema, GetSchema(&db_)); // Recover the previous version of the table into the altered version. { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery->db()->Execute(kCreateSql)); ASSERT_TRUE(recovery->db()->Execute(kAlterSql)); size_t rows = 0; EXPECT_TRUE(recovery->AutoRecoverTable("x", &rows)); EXPECT_EQ(2u, rows); - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } // Since the database was not corrupt, the entire schema and all // data should be recovered. ASSERT_TRUE(Reopen()); - ASSERT_EQ(expected_schema, GetSchema(&db())); - ASSERT_EQ(expected_data, ExecuteWithResults(&db(), kXSql, "|", "\n")); + ASSERT_EQ(expected_schema, GetSchema(&db_)); + ASSERT_EQ(expected_data, ExecuteWithResults(&db_, kXSql, "|", "\n")); } // Recover a golden file where an interior page has been manually modified so @@ -714,13 +726,12 @@ TEST_F(SQLRecoveryTest, Bug387868) { base::FilePath golden_path; ASSERT_TRUE(base::PathService::Get(sql::test::DIR_TEST_DATA, &golden_path)); golden_path = golden_path.AppendASCII("recovery_387868"); - db().Close(); - ASSERT_TRUE(base::CopyFile(golden_path, db_path())); + db_.Close(); + ASSERT_TRUE(base::CopyFile(golden_path, db_path_)); ASSERT_TRUE(Reopen()); { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery.get()); // Create the new version of the table. @@ -733,96 +744,95 @@ TEST_F(SQLRecoveryTest, Bug387868) { EXPECT_EQ(43u, rows); // Successfully recovered. - EXPECT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + EXPECT_TRUE(Recovery::Recovered(std::move(recovery))); } } // Memory-mapped I/O interacts poorly with I/O errors. Make sure the recovery // database doesn't accidentally enable it. TEST_F(SQLRecoveryTest, NoMmap) { - std::unique_ptr recovery = - sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_TRUE(recovery.get()); // In the current implementation, the PRAGMA successfully runs with no result // rows. Running with a single result of |0| is also acceptable. - sql::Statement s(recovery->db()->GetUniqueStatement("PRAGMA mmap_size")); + Statement s(recovery->db()->GetUniqueStatement("PRAGMA mmap_size")); EXPECT_TRUE(!s.Step() || !s.ColumnInt64(0)); } TEST_F(SQLRecoveryTest, RecoverDatabase) { // As a side effect, AUTOINCREMENT creates the sqlite_sequence table for // RecoverDatabase() to handle. - ASSERT_TRUE(db().Execute( + ASSERT_TRUE(db_.Execute( "CREATE TABLE x (id INTEGER PRIMARY KEY AUTOINCREMENT, v TEXT)")); - EXPECT_TRUE(db().Execute("INSERT INTO x (v) VALUES ('turtle')")); - EXPECT_TRUE(db().Execute("INSERT INTO x (v) VALUES ('truck')")); - EXPECT_TRUE(db().Execute("INSERT INTO x (v) VALUES ('trailer')")); + EXPECT_TRUE(db_.Execute("INSERT INTO x (v) VALUES ('turtle')")); + EXPECT_TRUE(db_.Execute("INSERT INTO x (v) VALUES ('truck')")); + EXPECT_TRUE(db_.Execute("INSERT INTO x (v) VALUES ('trailer')")); // This table needs index and a unique index to work. - ASSERT_TRUE(db().Execute("CREATE TABLE y (name TEXT, v TEXT)")); - ASSERT_TRUE(db().Execute("CREATE UNIQUE INDEX y_name ON y(name)")); - ASSERT_TRUE(db().Execute("CREATE INDEX y_v ON y(v)")); - EXPECT_TRUE(db().Execute("INSERT INTO y VALUES ('jim', 'telephone')")); - EXPECT_TRUE(db().Execute("INSERT INTO y VALUES ('bob', 'truck')")); - EXPECT_TRUE(db().Execute("INSERT INTO y VALUES ('dean', 'trailer')")); + ASSERT_TRUE(db_.Execute("CREATE TABLE y (name TEXT, v TEXT)")); + ASSERT_TRUE(db_.Execute("CREATE UNIQUE INDEX y_name ON y(name)")); + ASSERT_TRUE(db_.Execute("CREATE INDEX y_v ON y(v)")); + EXPECT_TRUE(db_.Execute("INSERT INTO y VALUES ('jim', 'telephone')")); + EXPECT_TRUE(db_.Execute("INSERT INTO y VALUES ('bob', 'truck')")); + EXPECT_TRUE(db_.Execute("INSERT INTO y VALUES ('dean', 'trailer')")); // View which is the intersection of [x.v] and [y.v]. - ASSERT_TRUE(db().Execute( - "CREATE VIEW v AS SELECT x.v FROM x, y WHERE x.v = y.v")); + ASSERT_TRUE( + db_.Execute("CREATE VIEW v AS SELECT x.v FROM x, y WHERE x.v = y.v")); // When an element is deleted from [x], trigger a delete on [y]. Between the // BEGIN and END, [old] stands for the deleted rows from [x]. - ASSERT_TRUE(db().Execute("CREATE TRIGGER t AFTER DELETE ON x " - "BEGIN DELETE FROM y WHERE y.v = old.v; END")); + ASSERT_TRUE( + db_.Execute("CREATE TRIGGER t AFTER DELETE ON x " + "BEGIN DELETE FROM y WHERE y.v = old.v; END")); // Save aside a copy of the original schema, verifying that it has the created // items plus the sqlite_sequence table. - const std::string orig_schema(GetSchema(&db())); + const std::string orig_schema(GetSchema(&db_)); ASSERT_EQ(6, std::count(orig_schema.begin(), orig_schema.end(), '\n')); static const char kXSql[] = "SELECT * FROM x ORDER BY 1"; static const char kYSql[] = "SELECT * FROM y ORDER BY 1"; static const char kVSql[] = "SELECT * FROM v ORDER BY 1"; EXPECT_EQ("1|turtle\n2|truck\n3|trailer", - ExecuteWithResults(&db(), kXSql, "|", "\n")); + ExecuteWithResults(&db_, kXSql, "|", "\n")); EXPECT_EQ("bob|truck\ndean|trailer\njim|telephone", - ExecuteWithResults(&db(), kYSql, "|", "\n")); - EXPECT_EQ("trailer\ntruck", ExecuteWithResults(&db(), kVSql, "|", "\n")); + ExecuteWithResults(&db_, kYSql, "|", "\n")); + EXPECT_EQ("trailer\ntruck", ExecuteWithResults(&db_, kVSql, "|", "\n")); // Database handle is valid before recovery, poisoned after. static const char kTrivialSql[] = "SELECT COUNT(*) FROM sqlite_master"; - EXPECT_TRUE(db().IsSQLValid(kTrivialSql)); - sql::Recovery::RecoverDatabase(&db(), db_path()); - EXPECT_FALSE(db().IsSQLValid(kTrivialSql)); + EXPECT_TRUE(db_.IsSQLValid(kTrivialSql)); + Recovery::RecoverDatabase(&db_, db_path_); + EXPECT_FALSE(db_.IsSQLValid(kTrivialSql)); // Since the database was not corrupt, the entire schema and all // data should be recovered. ASSERT_TRUE(Reopen()); - ASSERT_EQ(orig_schema, GetSchema(&db())); + ASSERT_EQ(orig_schema, GetSchema(&db_)); EXPECT_EQ("1|turtle\n2|truck\n3|trailer", - ExecuteWithResults(&db(), kXSql, "|", "\n")); + ExecuteWithResults(&db_, kXSql, "|", "\n")); EXPECT_EQ("bob|truck\ndean|trailer\njim|telephone", - ExecuteWithResults(&db(), kYSql, "|", "\n")); - EXPECT_EQ("trailer\ntruck", ExecuteWithResults(&db(), kVSql, "|", "\n")); + ExecuteWithResults(&db_, kYSql, "|", "\n")); + EXPECT_EQ("trailer\ntruck", ExecuteWithResults(&db_, kVSql, "|", "\n")); // Test that the trigger works. - ASSERT_TRUE(db().Execute("DELETE FROM x WHERE v = 'truck'")); - EXPECT_EQ("1|turtle\n3|trailer", - ExecuteWithResults(&db(), kXSql, "|", "\n")); + ASSERT_TRUE(db_.Execute("DELETE FROM x WHERE v = 'truck'")); + EXPECT_EQ("1|turtle\n3|trailer", ExecuteWithResults(&db_, kXSql, "|", "\n")); EXPECT_EQ("dean|trailer\njim|telephone", - ExecuteWithResults(&db(), kYSql, "|", "\n")); - EXPECT_EQ("trailer", ExecuteWithResults(&db(), kVSql, "|", "\n")); + ExecuteWithResults(&db_, kYSql, "|", "\n")); + EXPECT_EQ("trailer", ExecuteWithResults(&db_, kVSql, "|", "\n")); } // When RecoverDatabase() encounters SQLITE_NOTADB, the database is deleted. TEST_F(SQLRecoveryTest, RecoverDatabaseDelete) { // Create a valid database, then write junk over the header. This should lead // to SQLITE_NOTADB, which will cause ATTACH to fail. - ASSERT_TRUE(db().Execute("CREATE TABLE x (t TEXT)")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test')")); - db().Close(); - WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE); + ASSERT_TRUE(db_.Execute("CREATE TABLE x (t TEXT)")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES ('This is a test')")); + db_.Close(); + ASSERT_TRUE(OverwriteDatabaseHeader()); { sql::test::ScopedErrorExpecter expecter; @@ -832,74 +842,74 @@ TEST_F(SQLRecoveryTest, RecoverDatabaseDelete) { ASSERT_TRUE(Reopen()); // This should "recover" the database by making it valid, but empty. - sql::Recovery::RecoverDatabase(&db(), db_path()); + Recovery::RecoverDatabase(&db_, db_path_); ASSERT_TRUE(expecter.SawExpectedErrors()); } // Recovery poisoned the handle, must re-open. - db().Close(); + db_.Close(); ASSERT_TRUE(Reopen()); - EXPECT_EQ("", GetSchema(&db())); + 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')")); + 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(); + db_.Close(); static const char kDeleteSql[] = "DELETE FROM t WHERE id = 3"; - ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path(), "t_id", kDeleteSql)); + ASSERT_TRUE(sql::test::CorruptTableOrIndex(db_path_, "t_id", kDeleteSql)); ASSERT_TRUE(Reopen()); // id as read from index. static const char kSelectIndexIdSql[] = "SELECT id FROM t INDEXED BY t_id"; - EXPECT_EQ("1,2,3", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ",")); + EXPECT_EQ("1,2,3", ExecuteWithResults(&db_, kSelectIndexIdSql, "|", ",")); // id as read from table. static const char kSelectTableIdSql[] = "SELECT id FROM t NOT INDEXED"; - EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ",")); + EXPECT_EQ("1,2", ExecuteWithResults(&db_, kSelectTableIdSql, "|", ",")); // Run recovery code, then rollback. Database remains the same. { - std::unique_ptr recovery = - sql::Recovery::BeginRecoverDatabase(&db(), db_path()); + std::unique_ptr recovery = + Recovery::BeginRecoverDatabase(&db_, db_path_); ASSERT_TRUE(recovery); - sql::Recovery::Rollback(std::move(recovery)); + Recovery::Rollback(std::move(recovery)); } - db().Close(); + db_.Close(); ASSERT_TRUE(Reopen()); - EXPECT_EQ("1,2,3", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ",")); - EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ",")); + 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 recovery = - sql::Recovery::BeginRecoverDatabase(&db(), db_path()); + std::unique_ptr recovery = + Recovery::BeginRecoverDatabase(&db_, db_path_); ASSERT_TRUE(recovery); - ASSERT_TRUE(sql::Recovery::Recovered(std::move(recovery))); + ASSERT_TRUE(Recovery::Recovered(std::move(recovery))); } - db().Close(); + db_.Close(); ASSERT_TRUE(Reopen()); - EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectIndexIdSql, "|", ",")); - EXPECT_EQ("1,2", ExecuteWithResults(&db(), kSelectTableIdSql, "|", ",")); + 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 // to SQLITE_NOTADB, which will cause ATTACH to fail. - ASSERT_TRUE(db().Execute("CREATE TABLE x (t TEXT)")); - ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test')")); - db().Close(); - WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE); + ASSERT_TRUE(db_.Execute("CREATE TABLE x (t TEXT)")); + ASSERT_TRUE(db_.Execute("INSERT INTO x VALUES ('This is a test')")); + db_.Close(); + ASSERT_TRUE(OverwriteDatabaseHeader()); static const char kEventHistogramName[] = "Sqlite.RecoveryEvents"; const int kEventEnum = 5; // RECOVERY_FAILED_ATTACH @@ -914,8 +924,7 @@ TEST_F(SQLRecoveryTest, AttachFailure) { ASSERT_TRUE(Reopen()); // Begin() should fail. - std::unique_ptr - recovery = sql::Recovery::Begin(&db(), db_path()); + std::unique_ptr recovery = Recovery::Begin(&db_, db_path_); ASSERT_FALSE(recovery.get()); ASSERT_TRUE(expecter.SawExpectedErrors()); @@ -942,8 +951,8 @@ void TestPageSize(const base::FilePath& db_prefix, const base::FilePath db_path = db_prefix.InsertBeforeExtensionASCII( base::NumberToString(initial_page_size)); - sql::Database::Delete(db_path); - sql::Database db({.page_size = initial_page_size}); + Database::Delete(db_path); + Database db({.page_size = initial_page_size}); ASSERT_TRUE(db.Open(db_path)); ASSERT_TRUE(db.Execute(kCreateSql)); ASSERT_TRUE(db.Execute(kInsertSql1)); @@ -953,18 +962,17 @@ void TestPageSize(const base::FilePath& db_prefix, db.Close(); // Re-open the database while setting a new |options.page_size| in the object. - sql::Database recover_db({.page_size = final_page_size}); + Database recover_db({.page_size = final_page_size}); ASSERT_TRUE(recover_db.Open(db_path)); // Recovery will use the page size set in the database object, which may not // match the file's page size. - sql::Recovery::RecoverDatabase(&recover_db, db_path); + Recovery::RecoverDatabase(&recover_db, db_path); // Recovery poisoned the handle, must re-open. recover_db.Close(); // Make sure the page size is read from the file. - sql::Database recovered_db( - {.page_size = sql::DatabaseOptions::kDefaultPageSize}); + Database recovered_db({.page_size = DatabaseOptions::kDefaultPageSize}); ASSERT_TRUE(recovered_db.Open(db_path)); ASSERT_EQ(expected_final_page_size, ExecuteWithResult(&recovered_db, "PRAGMA page_size")); @@ -972,34 +980,36 @@ void TestPageSize(const base::FilePath& db_prefix, ExecuteWithResults(&recovered_db, kSelectSql, "|", "\n")); } -// Verify that sql::Recovery maintains the page size, and the virtual table +// Verify that Recovery maintains the page size, and the virtual table // works with page sizes other than SQLite's default. Also verify the case // where the default page size has changed. TEST_F(SQLRecoveryTest, PageSize) { const std::string default_page_size = - ExecuteWithResult(&db(), "PRAGMA page_size"); + ExecuteWithResult(&db_, "PRAGMA page_size"); // Check the default page size first. EXPECT_NO_FATAL_FAILURE(TestPageSize( - db_path(), sql::DatabaseOptions::kDefaultPageSize, default_page_size, - sql::DatabaseOptions::kDefaultPageSize, default_page_size)); + db_path_, DatabaseOptions::kDefaultPageSize, default_page_size, + DatabaseOptions::kDefaultPageSize, default_page_size)); // Sync uses 32k pages. EXPECT_NO_FATAL_FAILURE( - TestPageSize(db_path(), 32768, "32768", 32768, "32768")); + TestPageSize(db_path_, 32768, "32768", 32768, "32768")); // Many clients use 4k pages. This is the SQLite default after 3.12.0. - EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 4096, "4096", 4096, "4096")); + EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path_, 4096, "4096", 4096, "4096")); // 1k is the default page size before 3.12.0. - EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 1024, "1024", 1024, "1024")); + EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path_, 1024, "1024", 1024, "1024")); // Databases with no page size specified should recover with the new default // page size. 2k has never been the default page size. ASSERT_NE("2048", default_page_size); - EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 2048, "2048", - sql::DatabaseOptions::kDefaultPageSize, + EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path_, 2048, "2048", + DatabaseOptions::kDefaultPageSize, default_page_size)); } } // namespace + +} // namespace sql diff --git a/sql/sql_memory_dump_provider_unittest.cc b/sql/sql_memory_dump_provider_unittest.cc index c361253b0d12a1..6929639c7e95e2 100644 --- a/sql/sql_memory_dump_provider_unittest.cc +++ b/sql/sql_memory_dump_provider_unittest.cc @@ -4,19 +4,41 @@ #include "sql/sql_memory_dump_provider.h" +#include "base/files/scoped_temp_dir.h" +#include "base/trace_event/memory_dump_request_args.h" #include "base/trace_event/process_memory_dump.h" -#include "sql/test/sql_test_base.h" +#include "sql/database.h" #include "testing/gtest/include/gtest/gtest.h" +namespace sql { + namespace { -using SQLMemoryDumpProviderTest = sql::SQLTestBase; -} + +class SQLMemoryDumpProviderTest : public testing::Test { + public: + ~SQLMemoryDumpProviderTest() override = default; + + void SetUp() override { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + ASSERT_TRUE(db_.Open( + temp_dir_.GetPath().AppendASCII("memory_dump_provider_test.sqlite"))); + + ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a, b)")); + } + + protected: + base::ScopedTempDir temp_dir_; + Database db_; +}; TEST_F(SQLMemoryDumpProviderTest, OnMemoryDump) { base::trace_event::MemoryDumpArgs args = { base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; base::trace_event::ProcessMemoryDump pmd(args); - ASSERT_TRUE( - sql::SqlMemoryDumpProvider::GetInstance()->OnMemoryDump(args, &pmd)); + ASSERT_TRUE(SqlMemoryDumpProvider::GetInstance()->OnMemoryDump(args, &pmd)); ASSERT_TRUE(pmd.GetAllocatorDump("sqlite")); } + +} // namespace + +} // namespace sql diff --git a/sql/sqlite_features_unittest.cc b/sql/sqlite_features_unittest.cc index 877ec675c9a5ae..a84a51bb57d91e 100644 --- a/sql/sqlite_features_unittest.cc +++ b/sql/sqlite_features_unittest.cc @@ -8,13 +8,13 @@ #include #include "base/bind.h" +#include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/memory_mapped_file.h" #include "base/files/scoped_temp_dir.h" #include "build/build_config.h" #include "sql/database.h" #include "sql/statement.h" -#include "sql/test/sql_test_base.h" #include "sql/test/test_helpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/sqlite/sqlite3.h" @@ -40,16 +40,18 @@ void CaptureErrorCallback(int* error_pointer, std::string* sql_text, } // namespace -class SQLiteFeaturesTest : public sql::SQLTestBase { +class SQLiteFeaturesTest : public testing::Test { public: - SQLiteFeaturesTest() : error_(SQLITE_OK) {} + ~SQLiteFeaturesTest() override = default; void SetUp() override { - SQLTestBase::SetUp(); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + db_path_ = temp_dir_.GetPath().AppendASCII("sqlite_features_test.sqlite"); + ASSERT_TRUE(db_.Open(db_path_)); // The error delegate will set |error_| and |sql_text_| when any sqlite // statement operation returns an error code. - db().set_error_callback( + db_.set_error_callback( base::BindRepeating(&CaptureErrorCallback, &error_, &sql_text_)); } @@ -57,15 +59,20 @@ class SQLiteFeaturesTest : public sql::SQLTestBase { // If any error happened the original sql statement can be found in // |sql_text_|. EXPECT_EQ(SQLITE_OK, error_) << sql_text_; + } - SQLTestBase::TearDown(); + bool Reopen() { + db_.Close(); + return db_.Open(db_path_); } - int error() { return error_; } + protected: + base::ScopedTempDir temp_dir_; + base::FilePath db_path_; + Database db_; - private: // The error code of the most recent error. - int error_; + int error_ = SQLITE_OK; // Original statement which has caused the error. std::string sql_text_; }; @@ -73,21 +80,20 @@ class SQLiteFeaturesTest : public sql::SQLTestBase { // Do not include fts1 support, it is not useful, and nobody is // looking at it. TEST_F(SQLiteFeaturesTest, NoFTS1) { - ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode( - "CREATE VIRTUAL TABLE foo USING fts1(x)")); + ASSERT_EQ(SQLITE_ERROR, db_.ExecuteAndReturnErrorCode( + "CREATE VIRTUAL TABLE foo USING fts1(x)")); } // Do not include fts2 support, it is not useful, and nobody is // looking at it. TEST_F(SQLiteFeaturesTest, NoFTS2) { - ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode( - "CREATE VIRTUAL TABLE foo USING fts2(x)")); + ASSERT_EQ(SQLITE_ERROR, db_.ExecuteAndReturnErrorCode( + "CREATE VIRTUAL TABLE foo USING fts2(x)")); } -// fts3 used to be used for history files, and may also be used by WebDatabase -// clients. +// fts3 is exposed in WebSQL. TEST_F(SQLiteFeaturesTest, FTS3) { - ASSERT_TRUE(db().Execute("CREATE VIRTUAL TABLE foo USING fts3(x)")); + ASSERT_TRUE(db_.Execute("CREATE VIRTUAL TABLE foo USING fts3(x)")); } // Originally history used fts2, which Chromium patched to treat "foo*" as a @@ -96,12 +102,12 @@ TEST_F(SQLiteFeaturesTest, FTS3) { TEST_F(SQLiteFeaturesTest, FTS3_Prefix) { static const char kCreateSql[] = "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)"; - ASSERT_TRUE(db().Execute(kCreateSql)); + ASSERT_TRUE(db_.Execute(kCreateSql)); - ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')")); + ASSERT_TRUE(db_.Execute("INSERT INTO foo (x) VALUES ('test')")); EXPECT_EQ("test", - ExecuteWithResult(&db(), "SELECT x FROM foo WHERE x MATCH 'te*'")); + ExecuteWithResult(&db_, "SELECT x FROM foo WHERE x MATCH 'te*'")); } // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With @@ -121,9 +127,9 @@ TEST_F(SQLiteFeaturesTest, UsesUsleep) { // Ensure that our SQLite version has working foreign key support with cascade // delete support. TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { - ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1")); - ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)")); - ASSERT_TRUE(db().Execute( + ASSERT_TRUE(db_.Execute("PRAGMA foreign_keys=1")); + ASSERT_TRUE(db_.Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)")); + ASSERT_TRUE(db_.Execute( "CREATE TABLE children (" " id INTEGER PRIMARY KEY," " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)")); @@ -131,40 +137,40 @@ TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { static const char kSelectChildrenSql[] = "SELECT * FROM children ORDER BY id"; // Inserting without a matching parent should fail with constraint violation. - EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParentsSql)); + EXPECT_EQ("", ExecuteWithResult(&db_, kSelectParentsSql)); const int insert_error = - db().ExecuteAndReturnErrorCode("INSERT INTO children VALUES (10, 1)"); + db_.ExecuteAndReturnErrorCode("INSERT INTO children VALUES (10, 1)"); EXPECT_EQ(SQLITE_CONSTRAINT | SQLITE_CONSTRAINT_FOREIGNKEY, insert_error); - EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildrenSql)); + EXPECT_EQ("", ExecuteWithResult(&db_, kSelectChildrenSql)); // Inserting with a matching parent should work. - ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)")); - EXPECT_EQ("1", ExecuteWithResults(&db(), kSelectParentsSql, "|", "\n")); - EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)")); - EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)")); + ASSERT_TRUE(db_.Execute("INSERT INTO parents VALUES (1)")); + EXPECT_EQ("1", ExecuteWithResults(&db_, kSelectParentsSql, "|", "\n")); + EXPECT_TRUE(db_.Execute("INSERT INTO children VALUES (11, 1)")); + EXPECT_TRUE(db_.Execute("INSERT INTO children VALUES (12, 1)")); EXPECT_EQ("11|1\n12|1", - ExecuteWithResults(&db(), kSelectChildrenSql, "|", "\n")); + ExecuteWithResults(&db_, kSelectChildrenSql, "|", "\n")); // Deleting the parent should cascade, deleting the children as well. - ASSERT_TRUE(db().Execute("DELETE FROM parents")); - EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParentsSql)); - EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildrenSql)); + ASSERT_TRUE(db_.Execute("DELETE FROM parents")); + EXPECT_EQ("", ExecuteWithResult(&db_, kSelectParentsSql)); + EXPECT_EQ("", ExecuteWithResult(&db_, kSelectChildrenSql)); } // Ensure that our SQLite version supports booleans. TEST_F(SQLiteFeaturesTest, BooleanSupport) { ASSERT_TRUE( - db().Execute("CREATE TABLE flags (" - " id INTEGER PRIMARY KEY," - " true_flag BOOL NOT NULL DEFAULT TRUE," - " false_flag BOOL NOT NULL DEFAULT FALSE)")); - ASSERT_TRUE(db().Execute( + db_.Execute("CREATE TABLE flags (" + " id INTEGER PRIMARY KEY," + " true_flag BOOL NOT NULL DEFAULT TRUE," + " false_flag BOOL NOT NULL DEFAULT FALSE)")); + ASSERT_TRUE(db_.Execute( "ALTER TABLE flags ADD COLUMN true_flag2 BOOL NOT NULL DEFAULT TRUE")); - ASSERT_TRUE(db().Execute( + ASSERT_TRUE(db_.Execute( "ALTER TABLE flags ADD COLUMN false_flag2 BOOL NOT NULL DEFAULT FALSE")); - ASSERT_TRUE(db().Execute("INSERT INTO flags (id) VALUES (1)")); + ASSERT_TRUE(db_.Execute("INSERT INTO flags (id) VALUES (1)")); - sql::Statement s(db().GetUniqueStatement( + sql::Statement s(db_.GetUniqueStatement( "SELECT true_flag, false_flag, true_flag2, false_flag2" " FROM flags WHERE id=1;")); ASSERT_TRUE(s.Step()); @@ -177,13 +183,11 @@ TEST_F(SQLiteFeaturesTest, BooleanSupport) { } TEST_F(SQLiteFeaturesTest, IcuEnabled) { - sql::Statement lower_en( - db().GetUniqueStatement("SELECT lower('I', 'en_us')")); + sql::Statement lower_en(db_.GetUniqueStatement("SELECT lower('I', 'en_us')")); ASSERT_TRUE(lower_en.Step()); EXPECT_EQ("i", lower_en.ColumnString(0)); - sql::Statement lower_tr( - db().GetUniqueStatement("SELECT lower('I', 'tr_tr')")); + sql::Statement lower_tr(db_.GetUniqueStatement("SELECT lower('I', 'tr_tr')")); ASSERT_TRUE(lower_tr.Step()); EXPECT_EQ("\u0131", lower_tr.ColumnString(0)); } @@ -196,14 +200,14 @@ TEST_F(SQLiteFeaturesTest, IcuEnabled) { // be disabled on this platform using SQLITE_MAX_MMAP_SIZE=0. TEST_F(SQLiteFeaturesTest, Mmap) { // Try to turn on mmap'ed I/O. - ignore_result(db().Execute("PRAGMA mmap_size = 1048576")); + ignore_result(db_.Execute("PRAGMA mmap_size = 1048576")); { - sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size")); + sql::Statement s(db_.GetUniqueStatement("PRAGMA mmap_size")); ASSERT_TRUE(s.Step()); ASSERT_GT(s.ColumnInt64(0), 0); } - db().Close(); + db_.Close(); const uint32_t kFlags = base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; @@ -211,7 +215,7 @@ TEST_F(SQLiteFeaturesTest, Mmap) { // Create a file with a block of '0', a block of '1', and a block of '2'. { - base::File f(db_path(), kFlags); + base::File f(db_path_, kFlags); ASSERT_TRUE(f.IsValid()); memset(buf, '0', sizeof(buf)); ASSERT_EQ(f.Write(0*sizeof(buf), buf, sizeof(buf)), (int)sizeof(buf)); @@ -226,7 +230,7 @@ TEST_F(SQLiteFeaturesTest, Mmap) { // mmap the file and verify that everything looks right. { base::MemoryMappedFile m; - ASSERT_TRUE(m.Initialize(db_path())); + ASSERT_TRUE(m.Initialize(db_path_)); memset(buf, '0', sizeof(buf)); ASSERT_EQ(0, memcmp(buf, m.data() + 0*sizeof(buf), sizeof(buf))); @@ -240,7 +244,7 @@ TEST_F(SQLiteFeaturesTest, Mmap) { // Scribble some '3' into the first page of the file, and verify that it // looks the same in the memory mapping. { - base::File f(db_path(), kFlags); + base::File f(db_path_, kFlags); ASSERT_TRUE(f.IsValid()); memset(buf, '3', sizeof(buf)); ASSERT_EQ(f.Write(0*sizeof(buf), buf, sizeof(buf)), (int)sizeof(buf)); @@ -251,7 +255,7 @@ TEST_F(SQLiteFeaturesTest, Mmap) { const size_t kOffset = 1*sizeof(buf) + 123; ASSERT_NE('4', m.data()[kOffset]); { - base::File f(db_path(), kFlags); + base::File f(db_path_, kFlags); ASSERT_TRUE(f.IsValid()); buf[0] = '4'; ASSERT_EQ(f.Write(kOffset, buf, 1), 1); @@ -264,14 +268,14 @@ TEST_F(SQLiteFeaturesTest, Mmap) { // compiled regular expression is effectively cached with the prepared // statement, causing errors if the regular expression is rebound. TEST_F(SQLiteFeaturesTest, CachedRegexp) { - ASSERT_TRUE(db().Execute("CREATE TABLE r (id INTEGER UNIQUE, x TEXT)")); - ASSERT_TRUE(db().Execute("INSERT INTO r VALUES (1, 'this is a test')")); - ASSERT_TRUE(db().Execute("INSERT INTO r VALUES (2, 'that was a test')")); - ASSERT_TRUE(db().Execute("INSERT INTO r VALUES (3, 'this is a stickup')")); - ASSERT_TRUE(db().Execute("INSERT INTO r VALUES (4, 'that sucks')")); + ASSERT_TRUE(db_.Execute("CREATE TABLE r (id INTEGER UNIQUE, x TEXT)")); + ASSERT_TRUE(db_.Execute("INSERT INTO r VALUES (1, 'this is a test')")); + ASSERT_TRUE(db_.Execute("INSERT INTO r VALUES (2, 'that was a test')")); + ASSERT_TRUE(db_.Execute("INSERT INTO r VALUES (3, 'this is a stickup')")); + ASSERT_TRUE(db_.Execute("INSERT INTO r VALUES (4, 'that sucks')")); static const char kSimpleSql[] = "SELECT SUM(id) FROM r WHERE x REGEXP ?"; - sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); + sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); s.BindString(0, "this.*"); ASSERT_TRUE(s.Step()); @@ -297,26 +301,26 @@ TEST_F(SQLiteFeaturesTest, CachedRegexp) { // If a database file is marked to be excluded from Time Machine, verify that // journal files are also excluded. TEST_F(SQLiteFeaturesTest, TimeMachine) { - ASSERT_TRUE(db().Execute("CREATE TABLE t (id INTEGER PRIMARY KEY)")); - db().Close(); + ASSERT_TRUE(db_.Execute("CREATE TABLE t (id INTEGER PRIMARY KEY)")); + db_.Close(); - base::FilePath journal_path = sql::Database::JournalPath(db_path()); - ASSERT_TRUE(GetPathExists(db_path())); - ASSERT_TRUE(GetPathExists(journal_path)); + base::FilePath journal_path = sql::Database::JournalPath(db_path_); + ASSERT_TRUE(base::PathExists(db_path_)); + ASSERT_TRUE(base::PathExists(journal_path)); // Not excluded to start. - EXPECT_FALSE(base::mac::GetFileBackupExclusion(db_path())); + EXPECT_FALSE(base::mac::GetFileBackupExclusion(db_path_)); EXPECT_FALSE(base::mac::GetFileBackupExclusion(journal_path)); // Exclude the main database file. - EXPECT_TRUE(base::mac::SetFileBackupExclusion(db_path())); + EXPECT_TRUE(base::mac::SetFileBackupExclusion(db_path_)); - EXPECT_TRUE(base::mac::GetFileBackupExclusion(db_path())); + EXPECT_TRUE(base::mac::GetFileBackupExclusion(db_path_)); EXPECT_FALSE(base::mac::GetFileBackupExclusion(journal_path)); - EXPECT_TRUE(db().Open(db_path())); - ASSERT_TRUE(db().Execute("INSERT INTO t VALUES (1)")); - EXPECT_TRUE(base::mac::GetFileBackupExclusion(db_path())); + EXPECT_TRUE(db_.Open(db_path_)); + ASSERT_TRUE(db_.Execute("INSERT INTO t VALUES (1)")); + EXPECT_TRUE(base::mac::GetFileBackupExclusion(db_path_)); EXPECT_TRUE(base::mac::GetFileBackupExclusion(journal_path)); // TODO(shess): In WAL mode this will touch -wal and -shm files. -shm files @@ -329,30 +333,30 @@ TEST_F(SQLiteFeaturesTest, TimeMachine) { // additional work into Chromium shutdown. Verify that SQLite supports a config // option to not checkpoint on close. TEST_F(SQLiteFeaturesTest, WALNoClose) { - base::FilePath wal_path = sql::Database::WriteAheadLogPath(db_path()); + base::FilePath wal_path = sql::Database::WriteAheadLogPath(db_path_); // Turn on WAL mode, then verify that the mode changed (WAL is supported). - ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL")); - ASSERT_EQ("wal", ExecuteWithResult(&db(), "PRAGMA journal_mode")); + ASSERT_TRUE(db_.Execute("PRAGMA journal_mode = WAL")); + ASSERT_EQ("wal", ExecuteWithResult(&db_, "PRAGMA journal_mode")); // The WAL file is created lazily on first change. - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a, b)")); // By default, the WAL is checkpointed then deleted on close. - ASSERT_TRUE(GetPathExists(wal_path)); - db().Close(); - ASSERT_FALSE(GetPathExists(wal_path)); + ASSERT_TRUE(base::PathExists(wal_path)); + db_.Close(); + ASSERT_FALSE(base::PathExists(wal_path)); // Reopen and configure the database to not checkpoint WAL on close. ASSERT_TRUE(Reopen()); - ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL")); - ASSERT_TRUE(db().Execute("ALTER TABLE foo ADD COLUMN c")); - ASSERT_EQ(SQLITE_OK, - sqlite3_db_config(db().db_, SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, 1, - nullptr)); - ASSERT_TRUE(GetPathExists(wal_path)); - db().Close(); - ASSERT_TRUE(GetPathExists(wal_path)); + ASSERT_TRUE(db_.Execute("PRAGMA journal_mode = WAL")); + ASSERT_TRUE(db_.Execute("ALTER TABLE foo ADD COLUMN c")); + ASSERT_EQ( + SQLITE_OK, + sqlite3_db_config(db_.db_, SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, 1, nullptr)); + ASSERT_TRUE(base::PathExists(wal_path)); + db_.Close(); + ASSERT_TRUE(base::PathExists(wal_path)); } #endif diff --git a/sql/statement_unittest.cc b/sql/statement_unittest.cc index 2033ee367e9057..af85326ea2dedb 100644 --- a/sql/statement_unittest.cc +++ b/sql/statement_unittest.cc @@ -11,29 +11,40 @@ #include "sql/statement.h" #include "sql/test/error_callback_support.h" #include "sql/test/scoped_error_expecter.h" -#include "sql/test/sql_test_base.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/sqlite/sqlite3.h" +namespace sql { namespace { -using SQLStatementTest = sql::SQLTestBase; +class SQLStatementTest : public testing::Test { + public: + ~SQLStatementTest() override = default; -} // namespace + void SetUp() override { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + ASSERT_TRUE( + db_.Open(temp_dir_.GetPath().AppendASCII("statement_test.sqlite"))); + } + + protected: + base::ScopedTempDir temp_dir_; + Database db_; +}; TEST_F(SQLStatementTest, Assign) { - sql::Statement s; + Statement s; EXPECT_FALSE(s.is_valid()); - s.Assign(db().GetUniqueStatement("CREATE TABLE foo (a, b)")); + s.Assign(db_.GetUniqueStatement("CREATE TABLE foo (a, b)")); EXPECT_TRUE(s.is_valid()); } TEST_F(SQLStatementTest, Run) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); - ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (3, 12)")); - sql::Statement s(db().GetUniqueStatement("SELECT b FROM foo WHERE a=?")); + Statement s(db_.GetUniqueStatement("SELECT b FROM foo WHERE a=?")); EXPECT_FALSE(s.Succeeded()); // Stepping it won't work since we haven't bound the value. @@ -44,7 +55,7 @@ TEST_F(SQLStatementTest, Run) { s.Reset(true); s.BindInt(0, 3); EXPECT_FALSE(s.Run()); - EXPECT_EQ(SQLITE_ROW, db().GetErrorCode()); + EXPECT_EQ(SQLITE_ROW, db_.GetErrorCode()); EXPECT_TRUE(s.Succeeded()); // Resetting it should put it back to the previous state (not runnable). @@ -62,16 +73,16 @@ TEST_F(SQLStatementTest, Run) { // Error callback called for error running a statement. TEST_F(SQLStatementTest, ErrorCallback) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)")); int error = SQLITE_OK; - sql::ScopedErrorCallback sec( - &db(), base::BindRepeating(&sql::CaptureErrorCallback, &error)); + ScopedErrorCallback sec(&db_, + base::BindRepeating(&CaptureErrorCallback, &error)); // Insert in the foo table the primary key. It is an error to insert // something other than an number. This error causes the error callback // handler to be called with SQLITE_MISMATCH as error code. - sql::Statement s(db().GetUniqueStatement("INSERT INTO foo (a) VALUES (?)")); + Statement s(db_.GetUniqueStatement("INSERT INTO foo (a) VALUES (?)")); EXPECT_TRUE(s.is_valid()); s.BindCString(0, "bad bad"); EXPECT_FALSE(s.Run()); @@ -80,9 +91,9 @@ TEST_F(SQLStatementTest, ErrorCallback) { // Error expecter works for error running a statement. TEST_F(SQLStatementTest, ScopedIgnoreError) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)")); - sql::Statement s(db().GetUniqueStatement("INSERT INTO foo (a) VALUES (?)")); + Statement s(db_.GetUniqueStatement("INSERT INTO foo (a) VALUES (?)")); EXPECT_TRUE(s.is_valid()); { @@ -95,12 +106,11 @@ TEST_F(SQLStatementTest, ScopedIgnoreError) { } TEST_F(SQLStatementTest, Reset) { - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); - ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)")); - ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (4, 13)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (3, 12)")); + ASSERT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (4, 13)")); - sql::Statement s(db().GetUniqueStatement( - "SELECT b FROM foo WHERE a = ? ")); + Statement s(db_.GetUniqueStatement("SELECT b FROM foo WHERE a = ? ")); s.BindInt(0, 3); ASSERT_TRUE(s.Step()); EXPECT_EQ(12, s.ColumnInt(0)); @@ -115,3 +125,6 @@ TEST_F(SQLStatementTest, Reset) { s.Reset(true); ASSERT_FALSE(s.Step()); } + +} // namespace +} // namespace sql diff --git a/sql/test/sql_test_base.cc b/sql/test/sql_test_base.cc deleted file mode 100644 index ef32741cb0d465..00000000000000 --- a/sql/test/sql_test_base.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sql/test/sql_test_base.h" - -#include "base/files/file_util.h" -#include "sql/test/test_helpers.h" - -namespace sql { - -SQLTestBase::SQLTestBase() = default; - -SQLTestBase::SQLTestBase(sql::DatabaseOptions options) : db_(options) {} - -SQLTestBase::~SQLTestBase() = default; - -base::FilePath SQLTestBase::db_path() { - return temp_dir_.GetPath().AppendASCII("SQLTest.db"); -} - -sql::Database& SQLTestBase::db() { - return db_; -} - -bool SQLTestBase::Reopen() { - db_.Close(); - return db_.Open(db_path()); -} - -bool SQLTestBase::GetPathExists(const base::FilePath& path) { - return base::PathExists(path); -} - -bool SQLTestBase::CorruptSizeInHeaderOfDB() { - return sql::test::CorruptSizeInHeader(db_path()); -} - -void SQLTestBase::WriteJunkToDatabase(WriteJunkType type) { - base::ScopedFILE file(base::OpenFile( - db_path(), - type == TYPE_OVERWRITE_AND_TRUNCATE ? "wb" : "rb+")); - ASSERT_TRUE(file.get()); - ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET)); - - const char* kJunk = "Now is the winter of our discontent."; - fputs(kJunk, file.get()); -} - -void SQLTestBase::TruncateDatabase() { - base::ScopedFILE file(base::OpenFile(db_path(), "rb+")); - ASSERT_TRUE(file); - ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET)); - ASSERT_TRUE(base::TruncateFile(file.get())); -} - -void SQLTestBase::SetUp() { - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - ASSERT_TRUE(db_.Open(db_path())); -} - -void SQLTestBase::TearDown() { - db_.Close(); -} - -} // namespace sql diff --git a/sql/test/sql_test_base.h b/sql/test/sql_test_base.h deleted file mode 100644 index cf35f1e32fd0c5..00000000000000 --- a/sql/test/sql_test_base.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SQL_TEST_SQL_TEST_BASE_H_ -#define SQL_TEST_SQL_TEST_BASE_H_ - -#include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" -#include "base/macros.h" -#include "sql/database.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace sql { - -// Base class for SQL tests. -// -// WARNING: We want to run the same gtest based unit test code both against -// chromium (which uses this implementation here), and the mojo code (which -// uses a different class named SQLTestBase). These two classes need to have -// the same interface because we compile time switch them based on a -// #define. We need to have two different implementations because the mojo -// version derives from mojo::test::ApplicationTestBase instead of -// testing::Test. -class SQLTestBase : public testing::Test { - public: - SQLTestBase(); - explicit SQLTestBase(sql::DatabaseOptions options); - ~SQLTestBase() override; - - enum WriteJunkType { - TYPE_OVERWRITE_AND_TRUNCATE, - TYPE_OVERWRITE - }; - - // Returns the path to the database. - base::FilePath db_path(); - - // Returns a connection to the database at db_path(). - sql::Database& db(); - - // Closes the current connection to the database and reopens it. - bool Reopen(); - - // Proxying method around base::PathExists. - bool GetPathExists(const base::FilePath& path); - - // SQLite stores the database size in the header, and if the actual - // OS-derived size is smaller, the database is considered corrupt. - // [This case is actually a common form of corruption in the wild.] - // This helper sets the in-header size to one page larger than the - // actual file size. The resulting file will return SQLITE_CORRUPT - // for most operations unless PRAGMA writable_schema is turned ON. - // - // Returns false if any error occurs accessing the file. - bool CorruptSizeInHeaderOfDB(); - - // Writes junk to the start of the file. - void WriteJunkToDatabase(WriteJunkType type); - - // Sets the database file size to 0. - void TruncateDatabase(); - - // Overridden from testing::Test: - void SetUp() override; - void TearDown() override; - - private: - base::ScopedTempDir temp_dir_; - sql::Database db_; - - DISALLOW_COPY_AND_ASSIGN(SQLTestBase); -}; - -} // namespace sql - -#endif // SQL_TEST_SQL_TEST_BASE_H_ diff --git a/sql/transaction_unittest.cc b/sql/transaction_unittest.cc index bcc05f5815b9b2..48f75da20b2dc1 100644 --- a/sql/transaction_unittest.cc +++ b/sql/transaction_unittest.cc @@ -3,38 +3,50 @@ // found in the LICENSE file. #include "sql/transaction.h" + #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "sql/database.h" #include "sql/statement.h" -#include "sql/test/sql_test_base.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/sqlite/sqlite3.h" -class SQLTransactionTest : public sql::SQLTestBase { +namespace sql { + +namespace { + +class SQLTransactionTest : public testing::Test { public: + ~SQLTransactionTest() override = default; + void SetUp() override { - SQLTestBase::SetUp(); + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + ASSERT_TRUE( + db_.Open(temp_dir_.GetPath().AppendASCII("transaction_test.sqlite"))); - ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db_.Execute("CREATE TABLE foo (a, b)")); } // Returns the number of rows in table "foo". int CountFoo() { - sql::Statement count(db().GetUniqueStatement("SELECT count(*) FROM foo")); + Statement count(db_.GetUniqueStatement("SELECT count(*) FROM foo")); count.Step(); return count.ColumnInt(0); } + + protected: + base::ScopedTempDir temp_dir_; + Database db_; }; TEST_F(SQLTransactionTest, Commit) { { - sql::Transaction t(&db()); + Transaction t(&db_); EXPECT_FALSE(t.is_open()); EXPECT_TRUE(t.Begin()); EXPECT_TRUE(t.is_open()); - EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + EXPECT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); t.Commit(); EXPECT_FALSE(t.is_open()); @@ -47,23 +59,23 @@ TEST_F(SQLTransactionTest, Rollback) { // Test some basic initialization, and that rollback runs when you exit the // scope. { - sql::Transaction t(&db()); + Transaction t(&db_); EXPECT_FALSE(t.is_open()); EXPECT_TRUE(t.Begin()); EXPECT_TRUE(t.is_open()); - EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + EXPECT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); } // Nothing should have been committed since it was implicitly rolled back. EXPECT_EQ(0, CountFoo()); // Test explicit rollback. - sql::Transaction t2(&db()); + Transaction t2(&db_); EXPECT_FALSE(t2.is_open()); EXPECT_TRUE(t2.Begin()); - EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + EXPECT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); t2.Rollback(); EXPECT_FALSE(t2.is_open()); @@ -73,23 +85,23 @@ TEST_F(SQLTransactionTest, Rollback) { // Rolling back any part of a transaction should roll back all of them. TEST_F(SQLTransactionTest, NestedRollback) { - EXPECT_EQ(0, db().transaction_nesting()); + EXPECT_EQ(0, db_.transaction_nesting()); // Outermost transaction. { - sql::Transaction outer(&db()); + Transaction outer(&db_); EXPECT_TRUE(outer.Begin()); - EXPECT_EQ(1, db().transaction_nesting()); + EXPECT_EQ(1, db_.transaction_nesting()); // The first inner one gets committed. { - sql::Transaction inner1(&db()); + Transaction inner1(&db_); EXPECT_TRUE(inner1.Begin()); - EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); - EXPECT_EQ(2, db().transaction_nesting()); + EXPECT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + EXPECT_EQ(2, db_.transaction_nesting()); inner1.Commit(); - EXPECT_EQ(1, db().transaction_nesting()); + EXPECT_EQ(1, db_.transaction_nesting()); } // One row should have gotten inserted. @@ -97,24 +109,28 @@ TEST_F(SQLTransactionTest, NestedRollback) { // The second inner one gets rolled back. { - sql::Transaction inner2(&db()); + Transaction inner2(&db_); EXPECT_TRUE(inner2.Begin()); - EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); - EXPECT_EQ(2, db().transaction_nesting()); + EXPECT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + EXPECT_EQ(2, db_.transaction_nesting()); inner2.Rollback(); - EXPECT_EQ(1, db().transaction_nesting()); + EXPECT_EQ(1, db_.transaction_nesting()); } // A third inner one will fail in Begin since one has already been rolled // back. - EXPECT_EQ(1, db().transaction_nesting()); + EXPECT_EQ(1, db_.transaction_nesting()); { - sql::Transaction inner3(&db()); + Transaction inner3(&db_); EXPECT_FALSE(inner3.Begin()); - EXPECT_EQ(1, db().transaction_nesting()); + EXPECT_EQ(1, db_.transaction_nesting()); } } - EXPECT_EQ(0, db().transaction_nesting()); + EXPECT_EQ(0, db_.transaction_nesting()); EXPECT_EQ(0, CountFoo()); } + +} // namespace + +} // namespace sql