123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- // Copyright 2022 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 "base/callback_helpers.h"
- #include "base/files/file_path.h"
- #include "base/files/scoped_temp_dir.h"
- #include "sql/database.h"
- #include "sql/sqlite_result_code.h"
- #include "sql/statement.h"
- #include "sql/test/scoped_error_expecter.h"
- #include "sql/test/test_helpers.h"
- #include "sql/transaction.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/sqlite/sqlite3.h"
- namespace sql {
- namespace {
- enum class OpenVariant {
- kInMemory = 1,
- kOnDiskExclusiveJournal = 2,
- kOnDiskNonExclusiveJournal = 3,
- kOnDiskExclusiveWal = 4,
- };
- // We use the parameter to run all tests with WAL mode on and off.
- class DatabaseOptionsTest : public testing::TestWithParam<OpenVariant> {
- public:
- DatabaseOptionsTest() = default;
- ~DatabaseOptionsTest() override = default;
- void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- db_path_ = temp_dir_.GetPath().AppendASCII("database_test.sqlite");
- }
- OpenVariant open_variant() const { return GetParam(); }
- // The options below interact with all other options. These tests ensure that
- // all combinations work.
- bool exclusive_locking() const {
- return GetParam() != OpenVariant::kOnDiskNonExclusiveJournal;
- }
- bool wal_mode() const {
- return GetParam() == OpenVariant::kOnDiskExclusiveWal;
- }
- void OpenDatabase(Database& db) {
- switch (open_variant()) {
- case OpenVariant::kOnDiskExclusiveJournal:
- ASSERT_TRUE(db.Open(db_path_));
- break;
- case OpenVariant::kOnDiskNonExclusiveJournal:
- ASSERT_TRUE(db.Open(db_path_));
- break;
- case OpenVariant::kOnDiskExclusiveWal:
- ASSERT_TRUE(db.Open(db_path_));
- break;
- case OpenVariant::kInMemory:
- ASSERT_TRUE(db.OpenInMemory());
- break;
- }
- }
- // Runs a rolled back transaction, followed by a committed transaction.
- void RunTransactions(Database& db) {
- {
- Transaction rolled_back(&db);
- ASSERT_TRUE(rolled_back.Begin());
- ASSERT_TRUE(db.Execute("CREATE TABLE rows(id PRIMARY KEY NOT NULL)"));
- rolled_back.Rollback();
- }
- {
- Transaction committed(&db);
- ASSERT_TRUE(committed.Begin());
- ASSERT_TRUE(db.Execute("CREATE TABLE rows(id PRIMARY KEY NOT NULL)"));
- ASSERT_TRUE(committed.Commit());
- }
- }
- protected:
- base::ScopedTempDir temp_dir_;
- base::FilePath db_path_;
- };
- TEST_P(DatabaseOptionsTest, FlushToDisk_FalseByDefault) {
- DatabaseOptions options = {
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- };
- EXPECT_FALSE(options.flush_to_media) << "Invalid test assumption";
- Database db(options);
- OpenDatabase(db);
- EXPECT_EQ("0", sql::test::ExecuteWithResult(&db, "PRAGMA fullfsync"));
- }
- TEST_P(DatabaseOptionsTest, FlushToDisk_True) {
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .flush_to_media = true,
- });
- OpenDatabase(db);
- EXPECT_EQ("1", sql::test::ExecuteWithResult(&db, "PRAGMA fullfsync"));
- }
- TEST_P(DatabaseOptionsTest, FlushToDisk_False_DoesNotCrash) {
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .flush_to_media = false,
- });
- OpenDatabase(db);
- EXPECT_EQ("0", sql::test::ExecuteWithResult(&db, "PRAGMA fullfsync"))
- << "Invalid test setup";
- RunTransactions(db);
- }
- TEST_P(DatabaseOptionsTest, FlushToDisk_True_DoesNotCrash) {
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .flush_to_media = true,
- });
- OpenDatabase(db);
- EXPECT_EQ("1", sql::test::ExecuteWithResult(&db, "PRAGMA fullfsync"))
- << "Invalid test setup";
- RunTransactions(db);
- }
- TEST_P(DatabaseOptionsTest, PageSize_Default) {
- static_assert(DatabaseOptions::kDefaultPageSize == 4096,
- "The page size numbers in this test file need to change");
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .page_size = 4096,
- });
- OpenDatabase(db);
- EXPECT_EQ("4096", sql::test::ExecuteWithResult(&db, "PRAGMA page_size"));
- RunTransactions(db);
- if (open_variant() != OpenVariant::kInMemory) {
- db.Close();
- EXPECT_EQ(4096, sql::test::ReadDatabasePageSize(db_path_).value_or(-1));
- }
- }
- TEST_P(DatabaseOptionsTest, PageSize_Large) {
- static_assert(DatabaseOptions::kDefaultPageSize < 16384,
- "The page size numbers in this test file need to change");
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .page_size = 16384,
- });
- OpenDatabase(db);
- EXPECT_EQ("16384", sql::test::ExecuteWithResult(&db, "PRAGMA page_size"));
- RunTransactions(db);
- if (open_variant() != OpenVariant::kInMemory) {
- db.Close();
- EXPECT_EQ(16384, sql::test::ReadDatabasePageSize(db_path_).value_or(-1));
- }
- }
- TEST_P(DatabaseOptionsTest, PageSize_Small) {
- static_assert(DatabaseOptions::kDefaultPageSize > 1024,
- "The page size numbers in this test file need to change");
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .page_size = 1024,
- });
- OpenDatabase(db);
- EXPECT_EQ("1024", sql::test::ExecuteWithResult(&db, "PRAGMA page_size"));
- RunTransactions(db);
- if (open_variant() != OpenVariant::kInMemory) {
- db.Close();
- EXPECT_EQ(1024, sql::test::ReadDatabasePageSize(db_path_).value_or(-1));
- }
- }
- TEST_P(DatabaseOptionsTest, CacheSize_Legacy) {
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .cache_size = 0,
- });
- OpenDatabase(db);
- EXPECT_EQ("-2000", sql::test::ExecuteWithResult(&db, "PRAGMA cache_size"));
- }
- TEST_P(DatabaseOptionsTest, CacheSize_Small) {
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .cache_size = 16,
- });
- OpenDatabase(db);
- EXPECT_EQ("16", sql::test::ExecuteWithResult(&db, "PRAGMA cache_size"));
- }
- TEST_P(DatabaseOptionsTest, CacheSize_Large) {
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .cache_size = 1000,
- });
- OpenDatabase(db);
- EXPECT_EQ("1000", sql::test::ExecuteWithResult(&db, "PRAGMA cache_size"));
- }
- TEST_P(DatabaseOptionsTest, EnableViewsDiscouraged_FalseByDefault) {
- DatabaseOptions options = {
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- };
- EXPECT_FALSE(options.enable_views_discouraged) << "Invalid test assumption";
- Database db(options);
- OpenDatabase(db);
- // sqlite3_db_config() currently only disables querying views. Schema
- // operations on views are still allowed.
- ASSERT_TRUE(db.Execute("CREATE VIEW view(id) AS SELECT 1"));
- {
- sql::test::ScopedErrorExpecter expecter;
- expecter.ExpectError(SQLITE_ERROR);
- Statement select_from_view(db.GetUniqueStatement("SELECT id FROM view"));
- EXPECT_FALSE(select_from_view.is_valid());
- EXPECT_TRUE(expecter.SawExpectedErrors());
- }
- // sqlite3_db_config() currently only disables querying views. Schema
- // operations on views are still allowed.
- EXPECT_TRUE(db.Execute("DROP VIEW IF EXISTS view"));
- }
- TEST_P(DatabaseOptionsTest, EnableViewsDiscouraged_True) {
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .enable_views_discouraged = true,
- });
- OpenDatabase(db);
- ASSERT_TRUE(db.Execute("CREATE VIEW view(id) AS SELECT 1"));
- Statement select_from_view(db.GetUniqueStatement("SELECT id FROM view"));
- ASSERT_TRUE(select_from_view.is_valid());
- EXPECT_TRUE(select_from_view.Step());
- EXPECT_EQ(1, select_from_view.ColumnInt64(0));
- EXPECT_TRUE(db.Execute("DROP VIEW IF EXISTS view"));
- }
- TEST_P(DatabaseOptionsTest, EnableVirtualTablesDiscouraged_FalseByDefault) {
- DatabaseOptions options = {
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- };
- EXPECT_FALSE(options.enable_virtual_tables_discouraged)
- << "Invalid test assumption";
- Database db(options);
- OpenDatabase(db);
- // sqlite3_prepare_v3() currently only disables accessing virtual tables.
- // Schema operations on virtual tables are still allowed.
- ASSERT_TRUE(db.Execute(
- "CREATE VIRTUAL TABLE fts_table USING fts3(data_table, content TEXT)"));
- {
- sql::test::ScopedErrorExpecter expecter;
- expecter.ExpectError(SQLITE_ERROR);
- Statement select_from_vtable(db.GetUniqueStatement(
- "SELECT content FROM fts_table WHERE content MATCH 'pattern'"));
- EXPECT_FALSE(select_from_vtable.is_valid());
- EXPECT_TRUE(expecter.SawExpectedErrors());
- }
- // sqlite3_prepare_v3() currently only disables accessing virtual tables.
- // Schema operations on virtual tables are still allowed.
- EXPECT_TRUE(db.Execute("DROP TABLE IF EXISTS fts_table"));
- }
- TEST_P(DatabaseOptionsTest, EnableVirtualTablesDiscouraged_True) {
- Database db(DatabaseOptions{
- .exclusive_locking = exclusive_locking(),
- .wal_mode = wal_mode(),
- .enable_virtual_tables_discouraged = true,
- });
- OpenDatabase(db);
- ASSERT_TRUE(db.Execute(
- "CREATE VIRTUAL TABLE fts_table USING fts3(data_table, content TEXT)"));
- Statement select_from_vtable(db.GetUniqueStatement(
- "SELECT content FROM fts_table WHERE content MATCH 'pattern'"));
- ASSERT_TRUE(select_from_vtable.is_valid());
- EXPECT_FALSE(select_from_vtable.Step());
- EXPECT_TRUE(db.Execute("DROP TABLE IF EXISTS fts_table"));
- }
- INSTANTIATE_TEST_SUITE_P(
- ,
- DatabaseOptionsTest,
- testing::Values(OpenVariant::kInMemory,
- OpenVariant::kOnDiskExclusiveJournal,
- OpenVariant::kOnDiskNonExclusiveJournal,
- OpenVariant::kOnDiskExclusiveWal));
- } // namespace
- } // namespace sql
|