chromium/sql/sqlite_features_unittest.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include <stddef.h>
#include <stdint.h>

#include <cstring>
#include <string>
#include <tuple>
#include <vector>

#include "base/files/file.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 "base/time/time.h"
#include "build/build_config.h"
#include "sql/database.h"
#include "sql/statement.h"
#include "sql/statement_id.h"
#include "sql/test/scoped_error_expecter.h"
#include "sql/test/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/sqlite/sqlite3.h"

#if BUILDFLAG(IS_APPLE)
#include "base/apple/backup_util.h"
#endif

// Test that certain features are/are-not enabled in our SQLite.

namespace sql {
namespace {

ExecuteWithResult;
ExecuteWithResults;

}  // namespace

class SQLiteFeaturesTest : public testing::Test {};

// Do not include fts1 support, it is not useful, and nobody is
// looking at it.
TEST_F(SQLiteFeaturesTest, NoFTS1) {}

// Do not include fts2 support, it is not useful, and nobody is
// looking at it.
TEST_F(SQLiteFeaturesTest, NoFTS2) {}

// fts3 is exposed in WebSQL.
TEST_F(SQLiteFeaturesTest, FTS3) {}

// Originally history used fts2, which Chromium patched to treat "foo*" as a
// prefix search, though the icu tokenizer would return it as two tokens {"foo",
// "*"}.  Test that fts3 works correctly.
TEST_F(SQLiteFeaturesTest, FTS3_Prefix) {}

// Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined.  With
// HAVE_USLEEP, SQLite uses usleep() with millisecond granularity.  Otherwise it
// uses sleep() with second granularity.
TEST_F(SQLiteFeaturesTest, UsesUsleep) {}

// Ensure that our SQLite version has working foreign key support with cascade
// delete support.
TEST_F(SQLiteFeaturesTest, ForeignKeySupport) {}

// Ensure that our SQLite version supports booleans.
TEST_F(SQLiteFeaturesTest, BooleanSupport) {}

TEST_F(SQLiteFeaturesTest, IcuEnabled) {}

// Verify that OS file writes are reflected in the memory mapping of a
// memory-mapped file.  Normally SQLite writes to memory-mapped files using
// memcpy(), which should stay consistent.  Our SQLite is slightly patched to
// mmap read only, then write using OS file writes.  If the memory-mapped
// version doesn't reflect the OS file writes, SQLite's memory-mapped I/O should
// be disabled on this platform using SQLITE_MAX_MMAP_SIZE=0.
TEST_F(SQLiteFeaturesTest, Mmap) {}

// Verify that http://crbug.com/248608 is fixed.  In this bug, the
// compiled regular expression is effectively cached with the prepared
// statement, causing errors if the regular expression is rebound.
TEST_F(SQLiteFeaturesTest, CachedRegexp) {}

TEST_F(SQLiteFeaturesTest, JsonIsDisabled) {}

TEST_F(SQLiteFeaturesTest, WindowFunctionsAreDisabled) {}

// The "No Isolation Between Operations On The Same Database Connection" section
// in https://sqlite.org/isolation.html implies that it's safe to issue multiple
// concurrent SELECTs against the same area.
//
// Chrome code is allowed to rely on this guarantee. So, we test for it here, to
// catch any regressions introduced by SQLite upgrades.
TEST_F(SQLiteFeaturesTest, ConcurrentSelects) {}

// The "No Isolation Between Operations On The Same Database Connection" section
// in https://sqlite.org/isolation.html states that it's safe to DELETE a row
// that was just returned by sqlite_step() executing a SELECT statement.
//
// Chrome code is allowed to rely on this guarantee. So, we test for it here, to
// catch any regressions introduced by SQLite upgrades.
TEST_F(SQLiteFeaturesTest, DeleteCurrentlySelectedRow) {}

// The "No Isolation Between Operations On The Same Database Connection" section
// in https://sqlite.org/isolation.html states that it's safe to DELETE a row
// that was previously by sqlite_step() executing a SELECT statement.
//
// Chrome code is allowed to rely on this guarantee. So, we test for it here, to
// catch any regressions introduced by SQLite upgrades.
TEST_F(SQLiteFeaturesTest, DeletePreviouslySelectedRows) {}

// The "No Isolation Between Operations On The Same Database Connection" section
// in https://sqlite.org/isolation.html states that it's safe to DELETE a row
// while a SELECT statement executes, but the DELETEd row may or may not show up
// in the SELECT results. (See the test above for a case where the DELETEd row
// is guaranteed to now show up in the SELECT results.)
//
// This seems to imply that DELETEing from a table that is not read by the
// concurrent SELECT statement is safe and well-defined, as the DELETEd row(s)
// cannot possibly show up in the SELECT results.
//
// Chrome features are allowed to rely on the implication above, because it
// comes in very handy for DELETEing data across multiple tables. This test
// ensures that our assumption remains valid.
TEST_F(SQLiteFeaturesTest, DeleteWhileSelectingFromDifferentTable) {}

// The "No Isolation Between Operations On The Same Database Connection" section
// in https://sqlite.org/isolation.html states that it's possible to INSERT in
// a table while concurrently executing a SELECT statement reading from it, but
// it's undefined whether the row will show up in the SELECT statement's results
// or not.
//
// Given this ambiguity, Chrome code is not allowed to INSERT in the same table
// as a concurrent SELECT. However, it is allowed to INSERT in a table which is
// not covered by SELECT, because this greatly simplifes migrations. So, we test
// the ability to INSERT in a table while SELECTing from another table, to
// catch any regressions introduced by SQLite upgrades.
TEST_F(SQLiteFeaturesTest, InsertWhileSelectingFromDifferentTable) {}

#if BUILDFLAG(IS_APPLE)
// If a database file is marked to be excluded from backups, verify that journal
// files are also excluded.
TEST_F(SQLiteFeaturesTest, TimeMachine) {
  ASSERT_TRUE(db_.Execute("CREATE TABLE t (id INTEGER PRIMARY KEY)"));
  db_.Close();

  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::apple::GetBackupExclusion(db_path_));
  EXPECT_FALSE(base::apple::GetBackupExclusion(journal_path));

  // Exclude the main database file.
  EXPECT_TRUE(base::apple::SetBackupExclusion(db_path_));

  EXPECT_TRUE(base::apple::GetBackupExclusion(db_path_));
  EXPECT_FALSE(base::apple::GetBackupExclusion(journal_path));

  EXPECT_TRUE(db_.Open(db_path_));
  ASSERT_TRUE(db_.Execute("INSERT INTO t VALUES (1)"));
  EXPECT_TRUE(base::apple::GetBackupExclusion(db_path_));
  EXPECT_TRUE(base::apple::GetBackupExclusion(journal_path));

  // TODO(shess): In WAL mode this will touch -wal and -shm files.  -shm files
  // could be always excluded.
}
#endif

#if !BUILDFLAG(IS_FUCHSIA)
// SQLite WAL mode defaults to checkpointing the WAL on close.  This would push
// additional work into Chromium shutdown.  Verify that SQLite supports a config
// option to not checkpoint on close.
TEST_F(SQLiteFeaturesTest, WALNoClose) {}
#endif

}  // namespace sql