1 // 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 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <string>
12 
13 #include "base/compiler_specific.h"
14 #include "base/files/file_path.h"
15 
16 // Collection of test-only convenience functions.
17 
18 namespace base {
19 class FilePath;
20 }
21 
22 namespace sql {
23 class Database;
24 }
25 
26 namespace sql {
27 namespace test {
28 
29 // SQLite stores the database size in the header, and if the actual
30 // OS-derived size is smaller, the database is considered corrupt.
31 // [This case is actually a common form of corruption in the wild.]
32 // This helper sets the in-header size to one page larger than the
33 // actual file size.  The resulting file will return SQLITE_CORRUPT
34 // for most operations unless PRAGMA writable_schema is turned ON.
35 //
36 // This function operates on the raw database file, outstanding database
37 // connections may not see the change because of the database cache.  See
38 // CorruptSizeInHeaderWithLock().
39 //
40 // Returns false if any error occurs accessing the file.
41 bool CorruptSizeInHeader(const base::FilePath& db_path) WARN_UNUSED_RESULT;
42 
43 // Common implementation of CorruptSizeInHeader() which operates on loaded
44 // memory. Shared between CorruptSizeInHeader() and the the mojo proxy testing
45 // code.
46 void CorruptSizeInHeaderMemory(unsigned char* header, int64_t db_size);
47 
48 // Call CorruptSizeInHeader() while holding a SQLite-compatible lock
49 // on the database.  This can be used to corrupt a database which is
50 // already open elsewhere.  Blocks until a write lock can be acquired.
51 bool CorruptSizeInHeaderWithLock(
52     const base::FilePath& db_path) WARN_UNUSED_RESULT;
53 
54 // Frequently corruption is a result of failure to atomically update
55 // pages in different structures.  For instance, if an index update
56 // takes effect but the corresponding table update does not.  This
57 // helper restores the prior version of a b-tree root after running an
58 // update which changed that b-tree.  The named b-tree must exist and
59 // must be a leaf node (either index or table).  Returns true if the
60 // on-disk file is successfully modified, and the restored page
61 // differs from the updated page.
62 //
63 // The resulting database should be possible to open, and many
64 // statements should work.  SQLITE_CORRUPT will be thrown if a query
65 // through the index finds the row missing in the table.
66 //
67 // TODO(shess): It would be very helpful to allow a parameter to the
68 // sql statement.  Perhaps a version with a string parameter would be
69 // sufficient, given affinity rules?
70 bool CorruptTableOrIndex(const base::FilePath& db_path,
71                          const char* tree_name,
72                          const char* update_sql) WARN_UNUSED_RESULT;
73 
74 // Return the number of tables in sqlite_master.
75 size_t CountSQLTables(sql::Database* db) WARN_UNUSED_RESULT;
76 
77 // Return the number of indices in sqlite_master.
78 size_t CountSQLIndices(sql::Database* db) WARN_UNUSED_RESULT;
79 
80 // Returns the number of columns in the named table.  0 indicates an
81 // error (probably no such table).
82 size_t CountTableColumns(sql::Database* db,
83                          const char* table) WARN_UNUSED_RESULT;
84 
85 // Sets |*count| to the number of rows in |table|.  Returns false in
86 // case of error, such as the table not existing.
87 bool CountTableRows(sql::Database* db, const char* table, size_t* count);
88 
89 // Creates a SQLite database at |db_path| from the sqlite .dump output
90 // at |sql_path|.  Returns false if |db_path| already exists, or if
91 // sql_path does not exist or cannot be read, or if there is an error
92 // executing the statements.
93 bool CreateDatabaseFromSQL(const base::FilePath& db_path,
94                            const base::FilePath& sql_path) WARN_UNUSED_RESULT;
95 
96 // Return the results of running "PRAGMA integrity_check" on |db|.
97 // TODO(shess): sql::Database::IntegrityCheck() is basically the
98 // same, but not as convenient for testing.  Maybe combine.
99 std::string IntegrityCheck(sql::Database* db) WARN_UNUSED_RESULT;
100 
101 // ExecuteWithResult() executes |sql| and returns the first column of the first
102 // row as a string.  The empty string is returned for no rows.  This makes it
103 // easier to test simple query results using EXPECT_EQ().  For instance:
104 //   EXPECT_EQ("1024", ExecuteWithResult(db, "PRAGMA page_size"));
105 //
106 // ExecuteWithResults() stringifies a larger result set by putting |column_sep|
107 // between columns and |row_sep| between rows.  For instance:
108 //   EXPECT_EQ("1,3,5", ExecuteWithResults(
109 //       db, "SELECT id FROM t ORDER BY id", "|", ","));
110 // Note that EXPECT_EQ() can nicely diff when using \n as |row_sep|.
111 //
112 // To test NULL, use the COALESCE() function:
113 //   EXPECT_EQ("<NULL>", ExecuteWithResult(
114 //       db, "SELECT c || '<NULL>' FROM t WHERE id = 1"));
115 // To test blobs use the HEX() function.
116 std::string ExecuteWithResult(sql::Database* db, const char* sql);
117 std::string ExecuteWithResults(sql::Database* db,
118                                const char* sql,
119                                const char* column_sep,
120                                const char* row_sep);
121 
122 // Returns the database size, in pages. Crashes on SQLite errors.
123 int GetPageCount(sql::Database* db);
124 
125 // Column information returned by GetColumnInfo.
126 //
127 // C++ wrapper around the out-params of sqlite3_table_column_metadata().
128 struct ColumnInfo {
129   // Retrieves schema information for a column in a table.
130   //
131   // Crashes on SQLite errors.
132   //
133   // |db_name| should be "main" for the connection's main (opened) database, and
134   // "temp" for the connection's temporary (in-memory) database.
135   //
136   // This is a static method rather than a function so it can be listed in the
137   // InternalApiToken access control list.
138   static ColumnInfo Create(sql::Database* db,
139                            const std::string& db_name,
140                            const std::string& table_name,
141                            const std::string& column_name) WARN_UNUSED_RESULT;
142 
143   // The native data type. Example: "INTEGER".
144   std::string data_type;
145   // Default collation sequence for sorting. Example: "BINARY".
146   std::string collation_sequence;
147   // True if the column has a "NOT NULL" constraint.
148   bool has_non_null_constraint;
149   // True if the column is included in the table's PRIMARY KEY.
150   bool is_in_primary_key;
151   // True if the column is AUTOINCREMENT.
152   bool is_auto_incremented;
153 };
154 
155 }  // namespace test
156 }  // namespace sql
157 
158 #endif  // SQL_TEST_TEST_HELPERS_H_
159