Commit 00370898 authored by Shubham Aggarwal's avatar Shubham Aggarwal Committed by Commit Bot

Add test coverage for WAL mode in database_unittest

This change makes it so that all tests in database_unittest.cc now run
both with WAL mode on and off. Better test coverage will help us
transition to using WAL mode by default in the future.

Bug: 78507
Change-Id: I116a8151c1ab4919a78657e46df98b26eddb7f11
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2490664
Commit-Queue: Shubham Aggarwal <shuagga@microsoft.com>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821790}
parent 1bfcd597
This diff is collapsed.
......@@ -9,6 +9,7 @@ namespace sql {
namespace test {
struct ColumnInfo;
bool CorruptSizeInHeader(const base::FilePath&);
} // namespace test
// Restricts access to APIs internal to the //sql package.
......@@ -23,6 +24,7 @@ class InternalApiToken {
friend class DatabaseTestPeer;
friend class Recovery;
friend struct test::ColumnInfo;
friend bool test::CorruptSizeInHeader(const base::FilePath&);
};
} // namespace sql
......
......@@ -10,12 +10,12 @@
#include <memory>
#include <string>
#include "base/check.h"
#include "base/check_op.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/threading/thread_restrictions.h"
#include "sql/database.h"
#include "sql/sql_features.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/sqlite/sqlite3.h"
......@@ -71,21 +71,49 @@ void WriteBigEndian(unsigned val, unsigned char* buf, size_t bytes) {
}
}
bool IsWalDatabase(const base::FilePath& db_path) {
// The SQLite header is documented at:
// https://www.sqlite.org/fileformat.html#the_database_header
//
// Read the entire header.
constexpr int kHeaderSize = 100;
uint8_t header[kHeaderSize];
base::ReadFile(db_path, reinterpret_cast<char*>(header), sizeof(header));
constexpr int kWriteVersionHeaderOffset = 18;
constexpr int kReadVersionHeaderOffset = 19;
// If the read version is unsupported, we can't rely on our ability to
// interpret anything else in the header.
DCHECK_LE(header[kReadVersionHeaderOffset], 2)
<< "Unsupported SQLite file format";
return header[kWriteVersionHeaderOffset] == 2;
}
} // namespace
namespace sql {
namespace test {
bool CorruptSizeInHeader(const base::FilePath& db_path) {
// Checkpoint the WAL file in Truncate mode before corrupting to ensure that
// any future transaction always touches the DB file and not just the WAL
// file.
if (base::FeatureList::IsEnabled(sql::features::kEnableWALModeByDefault)) {
if (IsWalDatabase(db_path)) {
// Checkpoint the WAL file in Truncate mode before corrupting to ensure that
// any future transaction always touches the DB file and not just the WAL
// file.
base::ScopedAllowBlockingForTesting allow_blocking;
sql::Database db;
// TODO: This function doesn't reliably work if connections to the DB are
// still open. Change any uses to ensure that we close all database
// connections before calling this function.
sql::Database db({.exclusive_locking = false, .wal_mode = true});
if (!db.Open(db_path))
return false;
if (!db.Execute("PRAGMA wal_checkpoint(TRUNCATE)"))
int wal_log_size = 0;
int checkpointed_frame_count = 0;
int truncate_result = sqlite3_wal_checkpoint_v2(
db.db(InternalApiToken()), /*zDb=*/nullptr, SQLITE_CHECKPOINT_TRUNCATE,
&wal_log_size, &checkpointed_frame_count);
// A successful checkpoint in truncate mode sets these to zero.
DCHECK(wal_log_size == 0);
DCHECK(checkpointed_frame_count == 0);
if (truncate_result != SQLITE_OK)
return false;
db.Close();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment