blob: c431a9fb9535b21597a8b0204bf7c6221f9f19f6 [file] [log] [blame]
[email protected]43ffdd82013-09-10 23:44:501// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef SQL_TEST_TEST_HELPERS_H_
6#define SQL_TEST_TEST_HELPERS_H_
7
avi0b519202015-12-21 07:25:198#include <stddef.h>
9#include <stdint.h>
10
[email protected]a8848a72013-11-18 04:18:4711#include <string>
12
[email protected]ae4f1622013-12-08 06:49:1213#include "base/files/file_path.h"
[email protected]43ffdd82013-09-10 23:44:5014
15// Collection of test-only convenience functions.
16
17namespace base {
18class FilePath;
19}
20
21namespace sql {
Victor Costancfbfa602018-08-01 23:24:4622class Database;
[email protected]43ffdd82013-09-10 23:44:5023}
24
25namespace sql {
26namespace test {
27
[email protected]a8848a72013-11-18 04:18:4728// SQLite stores the database size in the header, and if the actual
29// OS-derived size is smaller, the database is considered corrupt.
30// [This case is actually a common form of corruption in the wild.]
31// This helper sets the in-header size to one page larger than the
32// actual file size. The resulting file will return SQLITE_CORRUPT
33// for most operations unless PRAGMA writable_schema is turned ON.
34//
shess4640cc22016-10-19 22:47:1335// This function operates on the raw database file, outstanding database
36// connections may not see the change because of the database cache. See
37// CorruptSizeInHeaderWithLock().
38//
[email protected]a8848a72013-11-18 04:18:4739// Returns false if any error occurs accessing the file.
Daniel Cheng1ac0cad2022-01-14 00:19:5340[[nodiscard]] bool CorruptSizeInHeader(const base::FilePath& db_path);
[email protected]a8848a72013-11-18 04:18:4741
shess4640cc22016-10-19 22:47:1342// Call CorruptSizeInHeader() while holding a SQLite-compatible lock
43// on the database. This can be used to corrupt a database which is
44// already open elsewhere. Blocks until a write lock can be acquired.
Daniel Cheng1ac0cad2022-01-14 00:19:5345[[nodiscard]] bool CorruptSizeInHeaderWithLock(const base::FilePath& db_path);
shess4640cc22016-10-19 22:47:1346
[email protected]ae4f1622013-12-08 06:49:1247// Frequently corruption is a result of failure to atomically update
48// pages in different structures. For instance, if an index update
49// takes effect but the corresponding table update does not. This
50// helper restores the prior version of a b-tree root after running an
51// update which changed that b-tree. The named b-tree must exist and
52// must be a leaf node (either index or table). Returns true if the
53// on-disk file is successfully modified, and the restored page
54// differs from the updated page.
55//
56// The resulting database should be possible to open, and many
57// statements should work. SQLITE_CORRUPT will be thrown if a query
58// through the index finds the row missing in the table.
59//
60// TODO(shess): It would be very helpful to allow a parameter to the
61// sql statement. Perhaps a version with a string parameter would be
62// sufficient, given affinity rules?
Daniel Cheng1ac0cad2022-01-14 00:19:5363[[nodiscard]] bool CorruptTableOrIndex(const base::FilePath& db_path,
64 const char* tree_name,
65 const char* update_sql);
[email protected]ae4f1622013-12-08 06:49:1266
John Delaney86dbec62021-08-24 15:05:2167// Return the number of tables in sqlite_schema.
Daniel Cheng1ac0cad2022-01-14 00:19:5368[[nodiscard]] size_t CountSQLTables(sql::Database* db);
[email protected]43ffdd82013-09-10 23:44:5069
John Delaney86dbec62021-08-24 15:05:2170// Return the number of indices in sqlite_schema.
Daniel Cheng1ac0cad2022-01-14 00:19:5371[[nodiscard]] size_t CountSQLIndices(sql::Database* db);
[email protected]43ffdd82013-09-10 23:44:5072
73// Returns the number of columns in the named table. 0 indicates an
74// error (probably no such table).
Daniel Cheng1ac0cad2022-01-14 00:19:5375[[nodiscard]] size_t CountTableColumns(sql::Database* db, const char* table);
[email protected]43ffdd82013-09-10 23:44:5076
[email protected]fe4e3de2013-10-08 02:19:1777// Sets |*count| to the number of rows in |table|. Returns false in
78// case of error, such as the table not existing.
Victor Costancfbfa602018-08-01 23:24:4679bool CountTableRows(sql::Database* db, const char* table, size_t* count);
[email protected]fe4e3de2013-10-08 02:19:1780
[email protected]43ffdd82013-09-10 23:44:5081// Creates a SQLite database at |db_path| from the sqlite .dump output
82// at |sql_path|. Returns false if |db_path| already exists, or if
83// sql_path does not exist or cannot be read, or if there is an error
84// executing the statements.
Daniel Cheng1ac0cad2022-01-14 00:19:5385[[nodiscard]] bool CreateDatabaseFromSQL(const base::FilePath& db_path,
86 const base::FilePath& sql_path);
[email protected]43ffdd82013-09-10 23:44:5087
[email protected]a8848a72013-11-18 04:18:4788// Return the results of running "PRAGMA integrity_check" on |db|.
Victor Costancfbfa602018-08-01 23:24:4689// TODO(shess): sql::Database::IntegrityCheck() is basically the
[email protected]a8848a72013-11-18 04:18:4790// same, but not as convenient for testing. Maybe combine.
Daniel Cheng1ac0cad2022-01-14 00:19:5391[[nodiscard]] std::string IntegrityCheck(sql::Database* db);
[email protected]a8848a72013-11-18 04:18:4792
shess1f955b182016-10-25 22:59:0993// ExecuteWithResult() executes |sql| and returns the first column of the first
94// row as a string. The empty string is returned for no rows. This makes it
95// easier to test simple query results using EXPECT_EQ(). For instance:
96// EXPECT_EQ("1024", ExecuteWithResult(db, "PRAGMA page_size"));
97//
98// ExecuteWithResults() stringifies a larger result set by putting |column_sep|
99// between columns and |row_sep| between rows. For instance:
100// EXPECT_EQ("1,3,5", ExecuteWithResults(
101// db, "SELECT id FROM t ORDER BY id", "|", ","));
102// Note that EXPECT_EQ() can nicely diff when using \n as |row_sep|.
103//
104// To test NULL, use the COALESCE() function:
105// EXPECT_EQ("<NULL>", ExecuteWithResult(
106// db, "SELECT c || '<NULL>' FROM t WHERE id = 1"));
107// To test blobs use the HEX() function.
Victor Costancfbfa602018-08-01 23:24:46108std::string ExecuteWithResult(sql::Database* db, const char* sql);
109std::string ExecuteWithResults(sql::Database* db,
shess1f955b182016-10-25 22:59:09110 const char* sql,
111 const char* column_sep,
112 const char* row_sep);
113
Victor Costan455989b2019-05-13 21:43:15114// Returns the database size, in pages. Crashes on SQLite errors.
115int GetPageCount(sql::Database* db);
116
117// Column information returned by GetColumnInfo.
118//
119// C++ wrapper around the out-params of sqlite3_table_column_metadata().
120struct ColumnInfo {
121 // Retrieves schema information for a column in a table.
122 //
123 // Crashes on SQLite errors.
124 //
125 // |db_name| should be "main" for the connection's main (opened) database, and
126 // "temp" for the connection's temporary (in-memory) database.
127 //
128 // This is a static method rather than a function so it can be listed in the
129 // InternalApiToken access control list.
Daniel Cheng1ac0cad2022-01-14 00:19:53130 [[nodiscard]] static ColumnInfo Create(sql::Database* db,
131 const std::string& db_name,
132 const std::string& table_name,
133 const std::string& column_name);
Victor Costan455989b2019-05-13 21:43:15134
135 // The native data type. Example: "INTEGER".
136 std::string data_type;
137 // Default collation sequence for sorting. Example: "BINARY".
138 std::string collation_sequence;
139 // True if the column has a "NOT NULL" constraint.
140 bool has_non_null_constraint;
141 // True if the column is included in the table's PRIMARY KEY.
142 bool is_in_primary_key;
143 // True if the column is AUTOINCREMENT.
144 bool is_auto_incremented;
145};
146
[email protected]43ffdd82013-09-10 23:44:50147} // namespace test
148} // namespace sql
149
150#endif // SQL_TEST_TEST_HELPERS_H_