blob: d357bdc90fa52a08708e3483f4ee70ee92bd782b [file] [log] [blame]
[email protected]44ad7d902012-03-23 00:09:051// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]e5ffd0e42009-09-11 21:30:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
avi0b519202015-12-21 07:25:195#include <stddef.h>
6#include <stdint.h>
7
[email protected]7bae5742013-07-10 20:46:168#include "base/bind.h"
thestig22dfc4012014-09-05 08:29:449#include "base/files/file_util.h"
[email protected]b9b4a572014-03-17 23:11:1210#include "base/files/scoped_file.h"
[email protected]ea1a3f62012-11-16 20:34:2311#include "base/files/scoped_temp_dir.h"
[email protected]41a97c812013-02-07 02:35:3812#include "base/logging.h"
avi0b519202015-12-21 07:25:1913#include "base/macros.h"
shess7e2baba2016-10-27 23:46:0514#include "base/strings/string_number_conversions.h"
Devlin Cronin147687f2018-06-05 18:03:5615#include "base/test/metrics/histogram_tester.h"
ssid9f8022f2015-10-12 17:49:0316#include "base/trace_event/process_memory_dump.h"
Scott Graham57ee54822017-09-13 06:37:5617#include "build/build_config.h"
[email protected]f0a54b22011-07-19 18:40:2118#include "sql/connection.h"
ssid3be5b1ec2016-01-13 14:21:5719#include "sql/connection_memory_dump_provider.h"
[email protected]1348765a2012-07-24 08:25:5320#include "sql/meta_table.h"
[email protected]ea1a3f62012-11-16 20:34:2321#include "sql/statement.h"
[email protected]98cf3002013-07-12 01:38:5622#include "sql/test/error_callback_support.h"
shess976814402016-06-21 06:56:2523#include "sql/test/scoped_error_expecter.h"
Scott Graham47ed2c32017-09-15 02:17:0724#include "sql/test/sql_test_base.h"
[email protected]a8848a72013-11-18 04:18:4725#include "sql/test/test_helpers.h"
[email protected]e5ffd0e42009-09-11 21:30:5626#include "testing/gtest/include/gtest/gtest.h"
[email protected]e33cba42010-08-18 23:37:0327#include "third_party/sqlite/sqlite3.h"
[email protected]e5ffd0e42009-09-11 21:30:5628
shess58b8df82015-06-03 00:19:3229namespace sql {
30namespace test {
31
32// Replaces the database time source with an object that steps forward 1ms on
33// each check, and which can be jumped forward an arbitrary amount of time
34// programmatically.
35class ScopedMockTimeSource {
36 public:
37 ScopedMockTimeSource(Connection& db)
38 : db_(db),
39 delta_(base::TimeDelta::FromMilliseconds(1)) {
40 // Save the current source and replace it.
41 save_.swap(db_.clock_);
42 db_.clock_.reset(new MockTimeSource(*this));
43 }
44 ~ScopedMockTimeSource() {
45 // Put original source back.
46 db_.clock_.swap(save_);
47 }
48
49 void adjust(const base::TimeDelta& delta) {
50 current_time_ += delta;
51 }
52
53 private:
54 class MockTimeSource : public TimeSource {
55 public:
56 MockTimeSource(ScopedMockTimeSource& owner)
57 : owner_(owner) {
58 }
Chris Watkinscf6172552017-11-27 03:25:1859 ~MockTimeSource() override = default;
shess58b8df82015-06-03 00:19:3260
61 base::TimeTicks Now() override {
62 base::TimeTicks ret(owner_.current_time_);
63 owner_.current_time_ += owner_.delta_;
64 return ret;
65 }
66
67 private:
68 ScopedMockTimeSource& owner_;
69 DISALLOW_COPY_AND_ASSIGN(MockTimeSource);
70 };
71
72 Connection& db_;
73
74 // Saves original source from |db_|.
mostynbd82cd9952016-04-11 20:05:3475 std::unique_ptr<TimeSource> save_;
shess58b8df82015-06-03 00:19:3276
77 // Current time returned by mock.
78 base::TimeTicks current_time_;
79
80 // How far to jump on each Now() call.
81 base::TimeDelta delta_;
82
83 DISALLOW_COPY_AND_ASSIGN(ScopedMockTimeSource);
84};
85
86// Allow a test to add a SQLite function in a scoped context.
87class ScopedScalarFunction {
88 public:
89 ScopedScalarFunction(
90 sql::Connection& db,
91 const char* function_name,
92 int args,
tzikd16d2192018-03-07 08:58:3693 base::RepeatingCallback<void(sqlite3_context*, int, sqlite3_value**)> cb)
94 : db_(db.db_), function_name_(function_name), cb_(std::move(cb)) {
shess6ce9d1f02015-09-02 19:37:4395 sqlite3_create_function_v2(db_, function_name, args, SQLITE_UTF8,
96 this, &Run, NULL, NULL, NULL);
shess58b8df82015-06-03 00:19:3297 }
98 ~ScopedScalarFunction() {
shess6ce9d1f02015-09-02 19:37:4399 sqlite3_create_function_v2(db_, function_name_, 0, SQLITE_UTF8,
100 NULL, NULL, NULL, NULL, NULL);
shess58b8df82015-06-03 00:19:32101 }
102
103 private:
104 static void Run(sqlite3_context* context, int argc, sqlite3_value** argv) {
105 ScopedScalarFunction* t = static_cast<ScopedScalarFunction*>(
106 sqlite3_user_data(context));
107 t->cb_.Run(context, argc, argv);
108 }
109
110 sqlite3* db_;
111 const char* function_name_;
tzikd16d2192018-03-07 08:58:36112 base::RepeatingCallback<void(sqlite3_context*, int, sqlite3_value**)> cb_;
shess58b8df82015-06-03 00:19:32113
114 DISALLOW_COPY_AND_ASSIGN(ScopedScalarFunction);
115};
116
117// Allow a test to add a SQLite commit hook in a scoped context.
118class ScopedCommitHook {
119 public:
tzikd16d2192018-03-07 08:58:36120 ScopedCommitHook(sql::Connection& db, base::RepeatingCallback<int()> cb)
121 : db_(db.db_), cb_(std::move(cb)) {
shess6ce9d1f02015-09-02 19:37:43122 sqlite3_commit_hook(db_, &Run, this);
shess58b8df82015-06-03 00:19:32123 }
124 ~ScopedCommitHook() {
shess6ce9d1f02015-09-02 19:37:43125 sqlite3_commit_hook(db_, NULL, NULL);
shess58b8df82015-06-03 00:19:32126 }
127
128 private:
129 static int Run(void* p) {
130 ScopedCommitHook* t = static_cast<ScopedCommitHook*>(p);
131 return t->cb_.Run();
132 }
133
134 sqlite3* db_;
tzikd16d2192018-03-07 08:58:36135 base::RepeatingCallback<int(void)> cb_;
shess58b8df82015-06-03 00:19:32136
137 DISALLOW_COPY_AND_ASSIGN(ScopedCommitHook);
138};
139
140} // namespace test
shess58b8df82015-06-03 00:19:32141
[email protected]7bae5742013-07-10 20:46:16142namespace {
143
shess7e2baba2016-10-27 23:46:05144using sql::test::ExecuteWithResults;
145using sql::test::ExecuteWithResult;
146
[email protected]7bae5742013-07-10 20:46:16147// Helper to return the count of items in sqlite_master. Return -1 in
148// case of error.
149int SqliteMasterCount(sql::Connection* db) {
150 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master";
151 sql::Statement s(db->GetUniqueStatement(kMasterCount));
152 return s.Step() ? s.ColumnInt(0) : -1;
153}
154
[email protected]98cf3002013-07-12 01:38:56155// Track the number of valid references which share the same pointer.
156// This is used to allow testing an implicitly use-after-free case by
157// explicitly having the ref count live longer than the object.
158class RefCounter {
159 public:
160 RefCounter(size_t* counter)
161 : counter_(counter) {
162 (*counter_)++;
163 }
164 RefCounter(const RefCounter& other)
165 : counter_(other.counter_) {
166 (*counter_)++;
167 }
168 ~RefCounter() {
169 (*counter_)--;
170 }
171
172 private:
173 size_t* counter_;
174
175 DISALLOW_ASSIGN(RefCounter);
176};
177
178// Empty callback for implementation of ErrorCallbackSetHelper().
179void IgnoreErrorCallback(int error, sql::Statement* stmt) {
180}
181
182void ErrorCallbackSetHelper(sql::Connection* db,
183 size_t* counter,
184 const RefCounter& r,
185 int error, sql::Statement* stmt) {
186 // The ref count should not go to zero when changing the callback.
187 EXPECT_GT(*counter, 0u);
tzikd16d2192018-03-07 08:58:36188 db->set_error_callback(base::BindRepeating(&IgnoreErrorCallback));
[email protected]98cf3002013-07-12 01:38:56189 EXPECT_GT(*counter, 0u);
190}
191
192void ErrorCallbackResetHelper(sql::Connection* db,
193 size_t* counter,
194 const RefCounter& r,
195 int error, sql::Statement* stmt) {
196 // The ref count should not go to zero when clearing the callback.
197 EXPECT_GT(*counter, 0u);
198 db->reset_error_callback();
199 EXPECT_GT(*counter, 0u);
200}
201
shess1cf87f22016-10-25 22:18:29202// Handle errors by blowing away the database.
203void RazeErrorCallback(sql::Connection* db,
204 int expected_error,
205 int error,
206 sql::Statement* stmt) {
207 // Nothing here needs extended errors at this time.
208 EXPECT_EQ(expected_error, expected_error&0xff);
209 EXPECT_EQ(expected_error, error&0xff);
210 db->RazeAndClose();
211}
212
[email protected]81a2a602013-07-17 19:10:36213#if defined(OS_POSIX)
214// Set a umask and restore the old mask on destruction. Cribbed from
215// shared_memory_unittest.cc. Used by POSIX-only UserPermission test.
216class ScopedUmaskSetter {
217 public:
218 explicit ScopedUmaskSetter(mode_t target_mask) {
219 old_umask_ = umask(target_mask);
220 }
221 ~ScopedUmaskSetter() { umask(old_umask_); }
222 private:
223 mode_t old_umask_;
224 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
225};
Victor Costan8a87f7e52017-11-10 01:29:30226#endif // defined(OS_POSIX)
[email protected]81a2a602013-07-17 19:10:36227
shessc8cd2a162015-10-22 20:30:46228// SQLite function to adjust mock time by |argv[0]| milliseconds.
229void sqlite_adjust_millis(sql::test::ScopedMockTimeSource* time_mock,
230 sqlite3_context* context,
231 int argc, sqlite3_value** argv) {
avi0b519202015-12-21 07:25:19232 int64_t milliseconds = argc > 0 ? sqlite3_value_int64(argv[0]) : 1000;
shessc8cd2a162015-10-22 20:30:46233 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
234 sqlite3_result_int64(context, milliseconds);
235}
236
237// Adjust mock time by |milliseconds| on commit.
238int adjust_commit_hook(sql::test::ScopedMockTimeSource* time_mock,
avi0b519202015-12-21 07:25:19239 int64_t milliseconds) {
shessc8cd2a162015-10-22 20:30:46240 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
241 return SQLITE_OK;
242}
243
244const char kCommitTime[] = "Sqlite.CommitTime.Test";
245const char kAutoCommitTime[] = "Sqlite.AutoCommitTime.Test";
246const char kUpdateTime[] = "Sqlite.UpdateTime.Test";
247const char kQueryTime[] = "Sqlite.QueryTime.Test";
248
249} // namespace
250
shess1cf87f22016-10-25 22:18:29251using SQLConnectionTest = sql::SQLTestBase;
[email protected]e5ffd0e42009-09-11 21:30:56252
253TEST_F(SQLConnectionTest, Execute) {
254 // Valid statement should return true.
255 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
256 EXPECT_EQ(SQLITE_OK, db().GetErrorCode());
257
258 // Invalid statement should fail.
[email protected]eff1fa522011-12-12 23:50:59259 ASSERT_EQ(SQLITE_ERROR,
260 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b"));
[email protected]e5ffd0e42009-09-11 21:30:56261 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode());
262}
263
[email protected]eff1fa522011-12-12 23:50:59264TEST_F(SQLConnectionTest, ExecuteWithErrorCode) {
265 ASSERT_EQ(SQLITE_OK,
266 db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)"));
267 ASSERT_EQ(SQLITE_ERROR,
268 db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE"));
269 ASSERT_EQ(SQLITE_ERROR,
270 db().ExecuteAndReturnErrorCode(
271 "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)"));
272}
273
[email protected]e5ffd0e42009-09-11 21:30:56274TEST_F(SQLConnectionTest, CachedStatement) {
275 sql::StatementID id1("foo", 12);
276
277 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
278 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
279
280 // Create a new cached statement.
281 {
282 sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo"));
[email protected]eff1fa522011-12-12 23:50:59283 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56284
285 ASSERT_TRUE(s.Step());
286 EXPECT_EQ(12, s.ColumnInt(0));
287 }
288
289 // The statement should be cached still.
290 EXPECT_TRUE(db().HasCachedStatement(id1));
291
292 {
293 // Get the same statement using different SQL. This should ignore our
294 // SQL and use the cached one (so it will be valid).
295 sql::Statement s(db().GetCachedStatement(id1, "something invalid("));
[email protected]eff1fa522011-12-12 23:50:59296 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56297
298 ASSERT_TRUE(s.Step());
299 EXPECT_EQ(12, s.ColumnInt(0));
300 }
301
302 // Make sure other statements aren't marked as cached.
303 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE));
304}
305
[email protected]eff1fa522011-12-12 23:50:59306TEST_F(SQLConnectionTest, IsSQLValidTest) {
307 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
308 ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo"));
309 ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo"));
310}
311
[email protected]e5ffd0e42009-09-11 21:30:56312TEST_F(SQLConnectionTest, DoesStuffExist) {
shessa62504d2016-11-07 19:26:12313 // Test DoesTableExist and DoesIndexExist.
[email protected]e5ffd0e42009-09-11 21:30:56314 EXPECT_FALSE(db().DoesTableExist("foo"));
315 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
shess92a2ab12015-04-09 01:59:47316 ASSERT_TRUE(db().Execute("CREATE INDEX foo_a ON foo (a)"));
shessa62504d2016-11-07 19:26:12317 EXPECT_FALSE(db().DoesIndexExist("foo"));
[email protected]e5ffd0e42009-09-11 21:30:56318 EXPECT_TRUE(db().DoesTableExist("foo"));
shess92a2ab12015-04-09 01:59:47319 EXPECT_TRUE(db().DoesIndexExist("foo_a"));
shessa62504d2016-11-07 19:26:12320 EXPECT_FALSE(db().DoesTableExist("foo_a"));
321
322 // Test DoesViewExist. The CREATE VIEW is an older form because some iOS
323 // versions use an earlier version of SQLite, and the difference isn't
324 // relevant for this test.
325 EXPECT_FALSE(db().DoesViewExist("voo"));
326 ASSERT_TRUE(db().Execute("CREATE VIEW voo AS SELECT 1"));
327 EXPECT_FALSE(db().DoesIndexExist("voo"));
328 EXPECT_FALSE(db().DoesTableExist("voo"));
329 EXPECT_TRUE(db().DoesViewExist("voo"));
[email protected]e5ffd0e42009-09-11 21:30:56330
331 // Test DoesColumnExist.
332 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
333 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
334
[email protected]e7afe2452010-08-22 16:19:13335 // Testing for a column on a nonexistent table.
[email protected]e5ffd0e42009-09-11 21:30:56336 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
shess92a2ab12015-04-09 01:59:47337
338 // Names are not case sensitive.
339 EXPECT_TRUE(db().DoesTableExist("FOO"));
340 EXPECT_TRUE(db().DoesColumnExist("FOO", "A"));
[email protected]e5ffd0e42009-09-11 21:30:56341}
342
343TEST_F(SQLConnectionTest, GetLastInsertRowId) {
344 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
345
346 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
347
348 // Last insert row ID should be valid.
tfarina720d4f32015-05-11 22:31:26349 int64_t row = db().GetLastInsertRowId();
[email protected]e5ffd0e42009-09-11 21:30:56350 EXPECT_LT(0, row);
351
352 // It should be the primary key of the row we just inserted.
353 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
354 s.BindInt64(0, row);
355 ASSERT_TRUE(s.Step());
356 EXPECT_EQ(12, s.ColumnInt(0));
357}
[email protected]44ad7d902012-03-23 00:09:05358
359TEST_F(SQLConnectionTest, Rollback) {
360 ASSERT_TRUE(db().BeginTransaction());
361 ASSERT_TRUE(db().BeginTransaction());
362 EXPECT_EQ(2, db().transaction_nesting());
363 db().RollbackTransaction();
364 EXPECT_FALSE(db().CommitTransaction());
365 EXPECT_TRUE(db().BeginTransaction());
366}
[email protected]8e0c01282012-04-06 19:36:49367
shess976814402016-06-21 06:56:25368// Test the scoped error expecter by attempting to insert a duplicate
[email protected]4350e322013-06-18 22:18:10369// value into an index.
shess976814402016-06-21 06:56:25370TEST_F(SQLConnectionTest, ScopedErrorExpecter) {
[email protected]4350e322013-06-18 22:18:10371 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
372 ASSERT_TRUE(db().Execute(kCreateSql));
373 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
374
shess92a2ab12015-04-09 01:59:47375 {
shess976814402016-06-21 06:56:25376 sql::test::ScopedErrorExpecter expecter;
377 expecter.ExpectError(SQLITE_CONSTRAINT);
shess92a2ab12015-04-09 01:59:47378 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
shess976814402016-06-21 06:56:25379 ASSERT_TRUE(expecter.SawExpectedErrors());
shess92a2ab12015-04-09 01:59:47380 }
381}
382
383// Test that clients of GetUntrackedStatement() can test corruption-handling
shess976814402016-06-21 06:56:25384// with ScopedErrorExpecter.
shess92a2ab12015-04-09 01:59:47385TEST_F(SQLConnectionTest, ScopedIgnoreUntracked) {
386 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
387 ASSERT_TRUE(db().Execute(kCreateSql));
388 ASSERT_FALSE(db().DoesTableExist("bar"));
389 ASSERT_TRUE(db().DoesTableExist("foo"));
390 ASSERT_TRUE(db().DoesColumnExist("foo", "id"));
391 db().Close();
392
393 // Corrupt the database so that nothing works, including PRAGMAs.
erg102ceb412015-06-20 01:38:13394 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
shess92a2ab12015-04-09 01:59:47395
396 {
shess976814402016-06-21 06:56:25397 sql::test::ScopedErrorExpecter expecter;
398 expecter.ExpectError(SQLITE_CORRUPT);
shess92a2ab12015-04-09 01:59:47399 ASSERT_TRUE(db().Open(db_path()));
400 ASSERT_FALSE(db().DoesTableExist("bar"));
401 ASSERT_FALSE(db().DoesTableExist("foo"));
402 ASSERT_FALSE(db().DoesColumnExist("foo", "id"));
shess976814402016-06-21 06:56:25403 ASSERT_TRUE(expecter.SawExpectedErrors());
shess92a2ab12015-04-09 01:59:47404 }
[email protected]4350e322013-06-18 22:18:10405}
406
[email protected]98cf3002013-07-12 01:38:56407TEST_F(SQLConnectionTest, ErrorCallback) {
408 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
409 ASSERT_TRUE(db().Execute(kCreateSql));
410 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
411
412 int error = SQLITE_OK;
413 {
414 sql::ScopedErrorCallback sec(
tzikd16d2192018-03-07 08:58:36415 &db(), base::BindRepeating(&sql::CaptureErrorCallback, &error));
[email protected]98cf3002013-07-12 01:38:56416 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
Scott Hessdcf120482015-02-10 21:33:29417
418 // Later versions of SQLite throw SQLITE_CONSTRAINT_UNIQUE. The specific
419 // sub-error isn't really important.
420 EXPECT_EQ(SQLITE_CONSTRAINT, (error&0xff));
[email protected]98cf3002013-07-12 01:38:56421 }
422
423 // Callback is no longer in force due to reset.
424 {
425 error = SQLITE_OK;
shess976814402016-06-21 06:56:25426 sql::test::ScopedErrorExpecter expecter;
427 expecter.ExpectError(SQLITE_CONSTRAINT);
[email protected]98cf3002013-07-12 01:38:56428 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
shess976814402016-06-21 06:56:25429 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]98cf3002013-07-12 01:38:56430 EXPECT_EQ(SQLITE_OK, error);
431 }
432
tzikd16d2192018-03-07 08:58:36433 // base::BindRepeating() can curry arguments to be passed by const reference
[email protected]81a2a602013-07-17 19:10:36434 // to the callback function. If the callback function calls
435 // re/set_error_callback(), the storage for those arguments can be
436 // deleted while the callback function is still executing.
[email protected]98cf3002013-07-12 01:38:56437 //
438 // RefCounter() counts how many objects are live using an external
439 // count. The same counter is passed to the callback, so that it
440 // can check directly even if the RefCounter object is no longer
441 // live.
442 {
443 size_t count = 0;
444 sql::ScopedErrorCallback sec(
tzikd16d2192018-03-07 08:58:36445 &db(), base::BindRepeating(&ErrorCallbackSetHelper, &db(), &count,
446 RefCounter(&count)));
[email protected]98cf3002013-07-12 01:38:56447
448 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
449 }
450
451 // Same test, but reset_error_callback() case.
452 {
453 size_t count = 0;
454 sql::ScopedErrorCallback sec(
tzikd16d2192018-03-07 08:58:36455 &db(), base::BindRepeating(&ErrorCallbackResetHelper, &db(), &count,
456 RefCounter(&count)));
[email protected]98cf3002013-07-12 01:38:56457
458 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
459 }
460}
461
[email protected]8e0c01282012-04-06 19:36:49462// Test that sql::Connection::Raze() results in a database without the
463// tables from the original database.
464TEST_F(SQLConnectionTest, Raze) {
465 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
466 ASSERT_TRUE(db().Execute(kCreateSql));
467 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
468
[email protected]69c58452012-08-06 19:22:42469 int pragma_auto_vacuum = 0;
470 {
471 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
472 ASSERT_TRUE(s.Step());
473 pragma_auto_vacuum = s.ColumnInt(0);
474 ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1);
475 }
476
477 // If auto_vacuum is set, there's an extra page to maintain a freelist.
478 const int kExpectedPageCount = 2 + pragma_auto_vacuum;
479
[email protected]8e0c01282012-04-06 19:36:49480 {
481 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
482 ASSERT_TRUE(s.Step());
[email protected]69c58452012-08-06 19:22:42483 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0));
[email protected]8e0c01282012-04-06 19:36:49484 }
485
486 {
487 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master"));
488 ASSERT_TRUE(s.Step());
489 EXPECT_EQ("table", s.ColumnString(0));
490 EXPECT_EQ("foo", s.ColumnString(1));
491 EXPECT_EQ("foo", s.ColumnString(2));
[email protected]69c58452012-08-06 19:22:42492 // Table "foo" is stored in the last page of the file.
493 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3));
[email protected]8e0c01282012-04-06 19:36:49494 EXPECT_EQ(kCreateSql, s.ColumnString(4));
495 }
496
497 ASSERT_TRUE(db().Raze());
498
499 {
500 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
501 ASSERT_TRUE(s.Step());
502 EXPECT_EQ(1, s.ColumnInt(0));
503 }
504
[email protected]7bae5742013-07-10 20:46:16505 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]69c58452012-08-06 19:22:42506
507 {
508 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
509 ASSERT_TRUE(s.Step());
[email protected]6d42f152012-11-10 00:38:24510 // The new database has the same auto_vacuum as a fresh database.
[email protected]69c58452012-08-06 19:22:42511 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0));
512 }
[email protected]8e0c01282012-04-06 19:36:49513}
514
shess7e2baba2016-10-27 23:46:05515// Helper for SQLConnectionTest.RazePageSize. Creates a fresh db based on
516// db_prefix, with the given initial page size, and verifies it against the
517// expected size. Then changes to the final page size and razes, verifying that
518// the fresh database ends up with the expected final page size.
519void TestPageSize(const base::FilePath& db_prefix,
520 int initial_page_size,
521 const std::string& expected_initial_page_size,
522 int final_page_size,
523 const std::string& expected_final_page_size) {
Victor Costan1d868352018-06-26 19:06:48524 static const char kCreateSql[] = "CREATE TABLE x (t TEXT)";
525 static const char kInsertSql1[] = "INSERT INTO x VALUES ('This is a test')";
526 static const char kInsertSql2[] = "INSERT INTO x VALUES ('That was a test')";
shess7e2baba2016-10-27 23:46:05527
528 const base::FilePath db_path = db_prefix.InsertBeforeExtensionASCII(
529 base::IntToString(initial_page_size));
530 sql::Connection::Delete(db_path);
531 sql::Connection db;
532 db.set_page_size(initial_page_size);
533 ASSERT_TRUE(db.Open(db_path));
534 ASSERT_TRUE(db.Execute(kCreateSql));
535 ASSERT_TRUE(db.Execute(kInsertSql1));
536 ASSERT_TRUE(db.Execute(kInsertSql2));
537 ASSERT_EQ(expected_initial_page_size,
538 ExecuteWithResult(&db, "PRAGMA page_size"));
539
540 // Raze will use the page size set in the connection object, which may not
541 // match the file's page size.
542 db.set_page_size(final_page_size);
543 ASSERT_TRUE(db.Raze());
544
545 // SQLite 3.10.2 (at least) has a quirk with the sqlite3_backup() API (used by
546 // Raze()) which causes the destination database to remember the previous
547 // page_size, even if the overwriting database changed the page_size. Access
548 // the actual database to cause the cached value to be updated.
549 EXPECT_EQ("0", ExecuteWithResult(&db, "SELECT COUNT(*) FROM sqlite_master"));
550
551 EXPECT_EQ(expected_final_page_size,
552 ExecuteWithResult(&db, "PRAGMA page_size"));
553 EXPECT_EQ("1", ExecuteWithResult(&db, "PRAGMA page_count"));
554}
555
556// Verify that sql::Recovery maintains the page size, and the virtual table
557// works with page sizes other than SQLite's default. Also verify the case
558// where the default page size has changed.
[email protected]8e0c01282012-04-06 19:36:49559TEST_F(SQLConnectionTest, RazePageSize) {
shess7e2baba2016-10-27 23:46:05560 const std::string default_page_size =
561 ExecuteWithResult(&db(), "PRAGMA page_size");
[email protected]8e0c01282012-04-06 19:36:49562
shess7e2baba2016-10-27 23:46:05563 // The database should have the default page size after raze.
564 EXPECT_NO_FATAL_FAILURE(
565 TestPageSize(db_path(), 0, default_page_size, 0, default_page_size));
[email protected]8e0c01282012-04-06 19:36:49566
shess7e2baba2016-10-27 23:46:05567 // Sync user 32k pages.
568 EXPECT_NO_FATAL_FAILURE(
569 TestPageSize(db_path(), 32768, "32768", 32768, "32768"));
[email protected]8e0c01282012-04-06 19:36:49570
shess7e2baba2016-10-27 23:46:05571 // Many clients use 4k pages. This is the SQLite default after 3.12.0.
572 EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 4096, "4096", 4096, "4096"));
573
574 // 1k is the default page size before 3.12.0.
575 EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 1024, "1024", 1024, "1024"));
576
577 EXPECT_NO_FATAL_FAILURE(
578 TestPageSize(db_path(), 2048, "2048", 4096, "4096"));
579
580 // Databases with no page size specified should result in the new default
581 // page size. 2k has never been the default page size.
582 ASSERT_NE("2048", default_page_size);
583 EXPECT_NO_FATAL_FAILURE(
584 TestPageSize(db_path(), 2048, "2048", 0, default_page_size));
[email protected]8e0c01282012-04-06 19:36:49585}
586
587// Test that Raze() results are seen in other connections.
588TEST_F(SQLConnectionTest, RazeMultiple) {
589 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
590 ASSERT_TRUE(db().Execute(kCreateSql));
591
592 sql::Connection other_db;
593 ASSERT_TRUE(other_db.Open(db_path()));
594
595 // Check that the second connection sees the table.
[email protected]7bae5742013-07-10 20:46:16596 ASSERT_EQ(1, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49597
598 ASSERT_TRUE(db().Raze());
599
600 // The second connection sees the updated database.
[email protected]7bae5742013-07-10 20:46:16601 ASSERT_EQ(0, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49602}
603
604TEST_F(SQLConnectionTest, RazeLocked) {
605 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
606 ASSERT_TRUE(db().Execute(kCreateSql));
607
608 // Open a transaction and write some data in a second connection.
609 // This will acquire a PENDING or EXCLUSIVE transaction, which will
610 // cause the raze to fail.
611 sql::Connection other_db;
612 ASSERT_TRUE(other_db.Open(db_path()));
613 ASSERT_TRUE(other_db.BeginTransaction());
614 const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')";
615 ASSERT_TRUE(other_db.Execute(kInsertSql));
616
617 ASSERT_FALSE(db().Raze());
618
619 // Works after COMMIT.
620 ASSERT_TRUE(other_db.CommitTransaction());
621 ASSERT_TRUE(db().Raze());
622
623 // Re-create the database.
624 ASSERT_TRUE(db().Execute(kCreateSql));
625 ASSERT_TRUE(db().Execute(kInsertSql));
626
627 // An unfinished read transaction in the other connection also
628 // blocks raze.
629 const char *kQuery = "SELECT COUNT(*) FROM foo";
630 sql::Statement s(other_db.GetUniqueStatement(kQuery));
631 ASSERT_TRUE(s.Step());
632 ASSERT_FALSE(db().Raze());
633
634 // Complete the statement unlocks the database.
635 ASSERT_FALSE(s.Step());
636 ASSERT_TRUE(db().Raze());
637}
638
[email protected]7bae5742013-07-10 20:46:16639// Verify that Raze() can handle an empty file. SQLite should treat
640// this as an empty database.
641TEST_F(SQLConnectionTest, RazeEmptyDB) {
642 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
643 ASSERT_TRUE(db().Execute(kCreateSql));
644 db().Close();
645
erg102ceb412015-06-20 01:38:13646 TruncateDatabase();
[email protected]7bae5742013-07-10 20:46:16647
648 ASSERT_TRUE(db().Open(db_path()));
649 ASSERT_TRUE(db().Raze());
650 EXPECT_EQ(0, SqliteMasterCount(&db()));
651}
652
653// Verify that Raze() can handle a file of junk.
654TEST_F(SQLConnectionTest, RazeNOTADB) {
655 db().Close();
656 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13657 ASSERT_FALSE(GetPathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16658
erg102ceb412015-06-20 01:38:13659 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE_AND_TRUNCATE);
660 ASSERT_TRUE(GetPathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16661
Scott Hessdcf120482015-02-10 21:33:29662 // SQLite will successfully open the handle, but fail when running PRAGMA
663 // statements that access the database.
[email protected]7bae5742013-07-10 20:46:16664 {
shess976814402016-06-21 06:56:25665 sql::test::ScopedErrorExpecter expecter;
Scott Hessdcf120482015-02-10 21:33:29666
Victor Costan42988a92018-02-06 02:22:14667 // Old SQLite versions returned a different error code.
668 ASSERT_GE(expecter.SQLiteLibVersionNumber(), 3014000)
669 << "Chrome ships with SQLite 3.22.0+. The system SQLite version is "
670 << "only supported on iOS 10+, which ships with SQLite 3.14.0+";
671 expecter.ExpectError(SQLITE_NOTADB);
Scott Hessdcf120482015-02-10 21:33:29672
[email protected]7bae5742013-07-10 20:46:16673 EXPECT_TRUE(db().Open(db_path()));
shess976814402016-06-21 06:56:25674 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]7bae5742013-07-10 20:46:16675 }
676 EXPECT_TRUE(db().Raze());
677 db().Close();
678
679 // Now empty, the open should open an empty database.
680 EXPECT_TRUE(db().Open(db_path()));
681 EXPECT_EQ(0, SqliteMasterCount(&db()));
682}
683
684// Verify that Raze() can handle a database overwritten with garbage.
685TEST_F(SQLConnectionTest, RazeNOTADB2) {
686 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
687 ASSERT_TRUE(db().Execute(kCreateSql));
688 ASSERT_EQ(1, SqliteMasterCount(&db()));
689 db().Close();
690
erg102ceb412015-06-20 01:38:13691 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE);
[email protected]7bae5742013-07-10 20:46:16692
693 // SQLite will successfully open the handle, but will fail with
694 // SQLITE_NOTADB on pragma statemenets which attempt to read the
695 // corrupted header.
696 {
shess976814402016-06-21 06:56:25697 sql::test::ScopedErrorExpecter expecter;
698 expecter.ExpectError(SQLITE_NOTADB);
[email protected]7bae5742013-07-10 20:46:16699 EXPECT_TRUE(db().Open(db_path()));
shess976814402016-06-21 06:56:25700 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]7bae5742013-07-10 20:46:16701 }
702 EXPECT_TRUE(db().Raze());
703 db().Close();
704
705 // Now empty, the open should succeed with an empty database.
706 EXPECT_TRUE(db().Open(db_path()));
707 EXPECT_EQ(0, SqliteMasterCount(&db()));
708}
709
710// Test that a callback from Open() can raze the database. This is
711// essential for cases where the Open() can fail entirely, so the
[email protected]fed734a2013-07-17 04:45:13712// Raze() cannot happen later. Additionally test that when the
713// callback does this during Open(), the open is retried and succeeds.
[email protected]fed734a2013-07-17 04:45:13714TEST_F(SQLConnectionTest, RazeCallbackReopen) {
[email protected]7bae5742013-07-10 20:46:16715 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
716 ASSERT_TRUE(db().Execute(kCreateSql));
717 ASSERT_EQ(1, SqliteMasterCount(&db()));
[email protected]7bae5742013-07-10 20:46:16718 db().Close();
719
[email protected]a8848a72013-11-18 04:18:47720 // Corrupt the database so that nothing works, including PRAGMAs.
erg102ceb412015-06-20 01:38:13721 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]7bae5742013-07-10 20:46:16722
[email protected]fed734a2013-07-17 04:45:13723 // Open() will succeed, even though the PRAGMA calls within will
724 // fail with SQLITE_CORRUPT, as will this PRAGMA.
725 {
shess976814402016-06-21 06:56:25726 sql::test::ScopedErrorExpecter expecter;
727 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]fed734a2013-07-17 04:45:13728 ASSERT_TRUE(db().Open(db_path()));
729 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum"));
730 db().Close();
shess976814402016-06-21 06:56:25731 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]fed734a2013-07-17 04:45:13732 }
733
tzikd16d2192018-03-07 08:58:36734 db().set_error_callback(
735 base::BindRepeating(&RazeErrorCallback, &db(), SQLITE_CORRUPT));
[email protected]7bae5742013-07-10 20:46:16736
[email protected]fed734a2013-07-17 04:45:13737 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error
738 // callback will call RazeAndClose(). Open() will then fail and be
739 // retried. The second Open() on the empty database will succeed
740 // cleanly.
741 ASSERT_TRUE(db().Open(db_path()));
742 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum"));
[email protected]7bae5742013-07-10 20:46:16743 EXPECT_EQ(0, SqliteMasterCount(&db()));
744}
745
[email protected]41a97c812013-02-07 02:35:38746// Basic test of RazeAndClose() operation.
747TEST_F(SQLConnectionTest, RazeAndClose) {
748 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
749 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
750
751 // Test that RazeAndClose() closes the database, and that the
752 // database is empty when re-opened.
753 ASSERT_TRUE(db().Execute(kCreateSql));
754 ASSERT_TRUE(db().Execute(kPopulateSql));
755 ASSERT_TRUE(db().RazeAndClose());
756 ASSERT_FALSE(db().is_open());
757 db().Close();
758 ASSERT_TRUE(db().Open(db_path()));
[email protected]7bae5742013-07-10 20:46:16759 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38760
761 // Test that RazeAndClose() can break transactions.
762 ASSERT_TRUE(db().Execute(kCreateSql));
763 ASSERT_TRUE(db().Execute(kPopulateSql));
764 ASSERT_TRUE(db().BeginTransaction());
765 ASSERT_TRUE(db().RazeAndClose());
766 ASSERT_FALSE(db().is_open());
767 ASSERT_FALSE(db().CommitTransaction());
768 db().Close();
769 ASSERT_TRUE(db().Open(db_path()));
[email protected]7bae5742013-07-10 20:46:16770 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38771}
772
773// Test that various operations fail without crashing after
774// RazeAndClose().
775TEST_F(SQLConnectionTest, RazeAndCloseDiagnostics) {
776 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
777 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
778 const char* kSimpleSql = "SELECT 1";
779
780 ASSERT_TRUE(db().Execute(kCreateSql));
781 ASSERT_TRUE(db().Execute(kPopulateSql));
782
783 // Test baseline expectations.
784 db().Preload();
785 ASSERT_TRUE(db().DoesTableExist("foo"));
786 ASSERT_TRUE(db().IsSQLValid(kSimpleSql));
787 ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql));
788 ASSERT_TRUE(db().Execute(kSimpleSql));
789 ASSERT_TRUE(db().is_open());
790 {
791 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
792 ASSERT_TRUE(s.Step());
793 }
794 {
795 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
796 ASSERT_TRUE(s.Step());
797 }
798 ASSERT_TRUE(db().BeginTransaction());
799 ASSERT_TRUE(db().CommitTransaction());
800 ASSERT_TRUE(db().BeginTransaction());
801 db().RollbackTransaction();
802
803 ASSERT_TRUE(db().RazeAndClose());
804
805 // At this point, they should all fail, but not crash.
806 db().Preload();
807 ASSERT_FALSE(db().DoesTableExist("foo"));
808 ASSERT_FALSE(db().IsSQLValid(kSimpleSql));
809 ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql));
810 ASSERT_FALSE(db().Execute(kSimpleSql));
811 ASSERT_FALSE(db().is_open());
812 {
813 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
814 ASSERT_FALSE(s.Step());
815 }
816 {
817 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
818 ASSERT_FALSE(s.Step());
819 }
820 ASSERT_FALSE(db().BeginTransaction());
821 ASSERT_FALSE(db().CommitTransaction());
822 ASSERT_FALSE(db().BeginTransaction());
823 db().RollbackTransaction();
824
825 // Close normally to reset the poisoned flag.
826 db().Close();
827
Scott Graham57ee54822017-09-13 06:37:56828 // DEATH tests not supported on Android, iOS, or Fuchsia.
829#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA)
[email protected]41a97c812013-02-07 02:35:38830 // Once the real Close() has been called, various calls enforce API
831 // usage by becoming fatal in debug mode. Since DEATH tests are
832 // expensive, just test one of them.
833 if (DLOG_IS_ON(FATAL)) {
834 ASSERT_DEATH({
835 db().IsSQLValid(kSimpleSql);
836 }, "Illegal use of connection without a db");
837 }
Victor Costan8a87f7e52017-11-10 01:29:30838#endif // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA)
[email protected]41a97c812013-02-07 02:35:38839}
840
841// TODO(shess): Spin up a background thread to hold other_db, to more
842// closely match real life. That would also allow testing
843// RazeWithTimeout().
844
shess92a6fb22017-04-23 04:33:30845// On Windows, truncate silently fails against a memory-mapped file. One goal
846// of Raze() is to truncate the file to remove blocks which generate I/O errors.
847// Test that Raze() turns off memory mapping so that the file is truncated.
848// [This would not cover the case of multiple connections where one of the other
849// connections is memory-mapped. That is infrequent in Chromium.]
850TEST_F(SQLConnectionTest, RazeTruncate) {
851 // The empty database has 0 or 1 pages. Raze() should leave it with exactly 1
852 // page. Not checking directly because auto_vacuum on Android adds a freelist
853 // page.
854 ASSERT_TRUE(db().Raze());
855 int64_t expected_size;
856 ASSERT_TRUE(base::GetFileSize(db_path(), &expected_size));
857 ASSERT_GT(expected_size, 0);
858
859 // Cause the database to take a few pages.
860 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
861 ASSERT_TRUE(db().Execute(kCreateSql));
862 for (size_t i = 0; i < 24; ++i) {
863 ASSERT_TRUE(
864 db().Execute("INSERT INTO foo (value) VALUES (randomblob(1024))"));
865 }
866 int64_t db_size;
867 ASSERT_TRUE(base::GetFileSize(db_path(), &db_size));
868 ASSERT_GT(db_size, expected_size);
869
870 // Make a query covering most of the database file to make sure that the
871 // blocks are actually mapped into memory. Empirically, the truncate problem
872 // doesn't seem to happen if no blocks are mapped.
873 EXPECT_EQ("24576",
874 ExecuteWithResult(&db(), "SELECT SUM(LENGTH(value)) FROM foo"));
875
876 ASSERT_TRUE(db().Raze());
877 ASSERT_TRUE(base::GetFileSize(db_path(), &db_size));
878 ASSERT_EQ(expected_size, db_size);
879}
880
[email protected]1348765a2012-07-24 08:25:53881#if defined(OS_ANDROID)
882TEST_F(SQLConnectionTest, SetTempDirForSQL) {
883
884 sql::MetaTable meta_table;
885 // Below call needs a temporary directory in sqlite3
886 // On Android, it can pass only when the temporary directory is set.
887 // Otherwise, sqlite3 doesn't find the correct directory to store
888 // temporary files and will report the error 'unable to open
889 // database file'.
890 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
891}
Victor Costan8a87f7e52017-11-10 01:29:30892#endif // defined(OS_ANDROID)
[email protected]8d2e39e2013-06-24 05:55:08893
894TEST_F(SQLConnectionTest, Delete) {
895 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
896 db().Close();
897
898 // Should have both a main database file and a journal file because
shess2c21ecf2015-06-02 01:31:09899 // of journal_mode TRUNCATE.
[email protected]8d2e39e2013-06-24 05:55:08900 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
erg102ceb412015-06-20 01:38:13901 ASSERT_TRUE(GetPathExists(db_path()));
902 ASSERT_TRUE(GetPathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08903
904 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13905 EXPECT_FALSE(GetPathExists(db_path()));
906 EXPECT_FALSE(GetPathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08907}
[email protected]7bae5742013-07-10 20:46:16908
Scott Graham47ed2c32017-09-15 02:17:07909// This test manually sets on disk permissions, these don't exist on Fuchsia.
Wez35539132018-07-17 11:26:05910#if defined(OS_POSIX)
[email protected]81a2a602013-07-17 19:10:36911// Test that set_restrict_to_user() trims database permissions so that
912// only the owner (and root) can read.
913TEST_F(SQLConnectionTest, UserPermission) {
914 // If the bots all had a restrictive umask setting such that
915 // databases are always created with only the owner able to read
916 // them, then the code could break without breaking the tests.
917 // Temporarily provide a more permissive umask.
918 db().Close();
919 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13920 ASSERT_FALSE(GetPathExists(db_path()));
[email protected]81a2a602013-07-17 19:10:36921 ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH);
922 ASSERT_TRUE(db().Open(db_path()));
923
924 // Cause the journal file to be created. If the default
925 // journal_mode is changed back to DELETE, then parts of this test
926 // will need to be updated.
927 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
928
929 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
930 int mode;
931
932 // Given a permissive umask, the database is created with permissive
933 // read access for the database and journal.
erg102ceb412015-06-20 01:38:13934 ASSERT_TRUE(GetPathExists(db_path()));
935 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08936 mode = base::FILE_PERMISSION_MASK;
937 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
938 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
939 mode = base::FILE_PERMISSION_MASK;
940 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
941 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36942
943 // Re-open with restricted permissions and verify that the modes
944 // changed for both the main database and the journal.
945 db().Close();
946 db().set_restrict_to_user();
947 ASSERT_TRUE(db().Open(db_path()));
erg102ceb412015-06-20 01:38:13948 ASSERT_TRUE(GetPathExists(db_path()));
949 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08950 mode = base::FILE_PERMISSION_MASK;
951 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
952 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
953 mode = base::FILE_PERMISSION_MASK;
954 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
955 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36956
957 // Delete and re-create the database, the restriction should still apply.
958 db().Close();
959 sql::Connection::Delete(db_path());
960 ASSERT_TRUE(db().Open(db_path()));
erg102ceb412015-06-20 01:38:13961 ASSERT_TRUE(GetPathExists(db_path()));
962 ASSERT_FALSE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08963 mode = base::FILE_PERMISSION_MASK;
964 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
965 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36966
967 // Verify that journal creation inherits the restriction.
968 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
erg102ceb412015-06-20 01:38:13969 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08970 mode = base::FILE_PERMISSION_MASK;
971 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
972 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36973}
Wez35539132018-07-17 11:26:05974#endif // defined(OS_POSIX)
[email protected]81a2a602013-07-17 19:10:36975
[email protected]8d409412013-07-19 18:25:30976// Test that errors start happening once Poison() is called.
977TEST_F(SQLConnectionTest, Poison) {
978 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
979
980 // Before the Poison() call, things generally work.
981 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
982 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
983 {
984 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
985 ASSERT_TRUE(s.is_valid());
986 ASSERT_TRUE(s.Step());
987 }
988
989 // Get a statement which is valid before and will exist across Poison().
990 sql::Statement valid_statement(
991 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master"));
992 ASSERT_TRUE(valid_statement.is_valid());
993 ASSERT_TRUE(valid_statement.Step());
994 valid_statement.Reset(true);
995
996 db().Poison();
997
998 // After the Poison() call, things fail.
999 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
1000 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')"));
1001 {
1002 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
1003 ASSERT_FALSE(s.is_valid());
1004 ASSERT_FALSE(s.Step());
1005 }
1006
1007 // The existing statement has become invalid.
1008 ASSERT_FALSE(valid_statement.is_valid());
1009 ASSERT_FALSE(valid_statement.Step());
shess644fc8a2016-02-26 18:15:581010
1011 // Test that poisoning the database during a transaction works (with errors).
1012 // RazeErrorCallback() poisons the database, the extra COMMIT causes
1013 // CommitTransaction() to throw an error while commiting.
tzikd16d2192018-03-07 08:58:361014 db().set_error_callback(
1015 base::BindRepeating(&RazeErrorCallback, &db(), SQLITE_ERROR));
shess644fc8a2016-02-26 18:15:581016 db().Close();
1017 ASSERT_TRUE(db().Open(db_path()));
1018 EXPECT_TRUE(db().BeginTransaction());
1019 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
1020 EXPECT_TRUE(db().Execute("COMMIT"));
1021 EXPECT_FALSE(db().CommitTransaction());
[email protected]8d409412013-07-19 18:25:301022}
1023
Victor Costan8a87f7e52017-11-10 01:29:301024TEST_F(SQLConnectionTest, AttachDatabase) {
[email protected]8d409412013-07-19 18:25:301025 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
1026
1027 // Create a database to attach to.
1028 base::FilePath attach_path =
1029 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
Victor Costan1d868352018-06-26 19:06:481030 static const char kAttachmentPoint[] = "other";
[email protected]8d409412013-07-19 18:25:301031 {
1032 sql::Connection other_db;
1033 ASSERT_TRUE(other_db.Open(attach_path));
1034 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
1035 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
1036 }
1037
1038 // Cannot see the attached database, yet.
1039 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1040
[email protected]8d409412013-07-19 18:25:301041 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
1042 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
1043
Victor Costan8a87f7e52017-11-10 01:29:301044 // Queries can touch both databases after the ATTACH.
[email protected]8d409412013-07-19 18:25:301045 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
1046 {
1047 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
1048 ASSERT_TRUE(s.Step());
1049 EXPECT_EQ(1, s.ColumnInt(0));
1050 }
1051
Victor Costan8a87f7e52017-11-10 01:29:301052 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
1053 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1054}
1055
1056TEST_F(SQLConnectionTest, AttachDatabaseWithOpenTransaction) {
1057 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
1058
1059 // Create a database to attach to.
1060 base::FilePath attach_path =
1061 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
Victor Costan1d868352018-06-26 19:06:481062 static const char kAttachmentPoint[] = "other";
Victor Costan8a87f7e52017-11-10 01:29:301063 {
1064 sql::Connection other_db;
1065 ASSERT_TRUE(other_db.Open(attach_path));
1066 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
1067 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
1068 }
1069
1070 // Cannot see the attached database, yet.
1071 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1072
Victor Costan8a87f7e52017-11-10 01:29:301073 // Attach succeeds in a transaction.
1074 EXPECT_TRUE(db().BeginTransaction());
1075 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
1076 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
1077
1078 // Queries can touch both databases after the ATTACH.
1079 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
1080 {
1081 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
1082 ASSERT_TRUE(s.Step());
1083 EXPECT_EQ(1, s.ColumnInt(0));
1084 }
1085
1086 // Detaching the same database fails, database is locked in the transaction.
1087 {
1088 sql::test::ScopedErrorExpecter expecter;
1089 expecter.ExpectError(SQLITE_ERROR);
[email protected]8d409412013-07-19 18:25:301090 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint));
1091 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
shess976814402016-06-21 06:56:251092 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]8d409412013-07-19 18:25:301093 }
1094
Victor Costan8a87f7e52017-11-10 01:29:301095 // Detach succeeds when the transaction is closed.
[email protected]8d409412013-07-19 18:25:301096 db().RollbackTransaction();
1097 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
[email protected]8d409412013-07-19 18:25:301098 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1099}
1100
[email protected]579446c2013-12-16 18:36:521101TEST_F(SQLConnectionTest, Basic_QuickIntegrityCheck) {
1102 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1103 ASSERT_TRUE(db().Execute(kCreateSql));
1104 EXPECT_TRUE(db().QuickIntegrityCheck());
1105 db().Close();
1106
erg102ceb412015-06-20 01:38:131107 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]579446c2013-12-16 18:36:521108
1109 {
shess976814402016-06-21 06:56:251110 sql::test::ScopedErrorExpecter expecter;
1111 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]579446c2013-12-16 18:36:521112 ASSERT_TRUE(db().Open(db_path()));
1113 EXPECT_FALSE(db().QuickIntegrityCheck());
shess976814402016-06-21 06:56:251114 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]579446c2013-12-16 18:36:521115 }
1116}
1117
1118TEST_F(SQLConnectionTest, Basic_FullIntegrityCheck) {
1119 const std::string kOk("ok");
1120 std::vector<std::string> messages;
1121
1122 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1123 ASSERT_TRUE(db().Execute(kCreateSql));
1124 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
1125 EXPECT_EQ(1u, messages.size());
1126 EXPECT_EQ(kOk, messages[0]);
1127 db().Close();
1128
erg102ceb412015-06-20 01:38:131129 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]579446c2013-12-16 18:36:521130
1131 {
shess976814402016-06-21 06:56:251132 sql::test::ScopedErrorExpecter expecter;
1133 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]579446c2013-12-16 18:36:521134 ASSERT_TRUE(db().Open(db_path()));
1135 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
1136 EXPECT_LT(1u, messages.size());
1137 EXPECT_NE(kOk, messages[0]);
shess976814402016-06-21 06:56:251138 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]579446c2013-12-16 18:36:521139 }
1140
1141 // TODO(shess): CorruptTableOrIndex could be used to produce a
1142 // file that would pass the quick check and fail the full check.
1143}
1144
shess58b8df82015-06-03 00:19:321145// Test Sqlite.Stats histogram for execute-oriented calls.
1146TEST_F(SQLConnectionTest, EventsExecute) {
1147 // Re-open with histogram tag.
1148 db().Close();
1149 db().set_histogram_tag("Test");
1150 ASSERT_TRUE(db().Open(db_path()));
1151
1152 // Open() uses Execute() extensively, don't track those calls.
1153 base::HistogramTester tester;
1154
Victor Costan1d868352018-06-26 19:06:481155 static const char kHistogramName[] = "Sqlite.Stats.Test";
1156 static const char kGlobalHistogramName[] = "Sqlite.Stats";
shess58b8df82015-06-03 00:19:321157
1158 ASSERT_TRUE(db().BeginTransaction());
1159 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1160 EXPECT_TRUE(db().Execute(kCreateSql));
1161 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1162 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1163 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1164 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (13, 'text')"));
1165 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (14, 'text')"));
1166 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (15, 'text');"
1167 "INSERT INTO foo VALUES (16, 'text');"
1168 "INSERT INTO foo VALUES (17, 'text');"
1169 "INSERT INTO foo VALUES (18, 'text');"
1170 "INSERT INTO foo VALUES (19, 'text')"));
1171 ASSERT_TRUE(db().CommitTransaction());
1172 ASSERT_TRUE(db().BeginTransaction());
1173 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1174 db().RollbackTransaction();
1175 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1176 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (21, 'text')"));
1177
1178 // The create, 5 inserts, multi-statement insert, rolled-back insert, 2
1179 // inserts outside transaction.
1180 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_EXECUTE, 10);
1181 tester.ExpectBucketCount(kGlobalHistogramName,
1182 sql::Connection::EVENT_EXECUTE, 10);
1183
1184 // All of the executes, with the multi-statement inserts broken out, plus one
1185 // for each begin, commit, and rollback.
1186 tester.ExpectBucketCount(kHistogramName,
1187 sql::Connection::EVENT_STATEMENT_RUN, 18);
1188 tester.ExpectBucketCount(kGlobalHistogramName,
1189 sql::Connection::EVENT_STATEMENT_RUN, 18);
1190
1191 tester.ExpectBucketCount(kHistogramName,
1192 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1193 tester.ExpectBucketCount(kGlobalHistogramName,
1194 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1195 tester.ExpectBucketCount(kHistogramName,
1196 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1197 tester.ExpectBucketCount(kGlobalHistogramName,
1198 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1199
1200 // The 2 inserts outside the transaction.
1201 tester.ExpectBucketCount(kHistogramName,
1202 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1203 tester.ExpectBucketCount(kGlobalHistogramName,
1204 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1205
1206 // 11 inserts inside transactions.
1207 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_CHANGES, 11);
1208 tester.ExpectBucketCount(kGlobalHistogramName,
1209 sql::Connection::EVENT_CHANGES, 11);
1210
1211 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_BEGIN, 2);
1212 tester.ExpectBucketCount(kGlobalHistogramName,
1213 sql::Connection::EVENT_BEGIN, 2);
1214 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_COMMIT, 1);
1215 tester.ExpectBucketCount(kGlobalHistogramName,
1216 sql::Connection::EVENT_COMMIT, 1);
1217 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_ROLLBACK, 1);
1218 tester.ExpectBucketCount(kGlobalHistogramName,
1219 sql::Connection::EVENT_ROLLBACK, 1);
1220}
1221
1222// Test Sqlite.Stats histogram for prepared statements.
1223TEST_F(SQLConnectionTest, EventsStatement) {
1224 // Re-open with histogram tag.
1225 db().Close();
1226 db().set_histogram_tag("Test");
1227 ASSERT_TRUE(db().Open(db_path()));
1228
Victor Costan1d868352018-06-26 19:06:481229 static const char kHistogramName[] = "Sqlite.Stats.Test";
1230 static const char kGlobalHistogramName[] = "Sqlite.Stats";
shess58b8df82015-06-03 00:19:321231
Victor Costan1d868352018-06-26 19:06:481232 static const char kCreateSql[] =
1233 "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
shess58b8df82015-06-03 00:19:321234 EXPECT_TRUE(db().Execute(kCreateSql));
1235 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1236 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1237 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1238
1239 {
1240 base::HistogramTester tester;
1241
1242 {
1243 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo"));
1244 while (s.Step()) {
1245 }
1246 }
1247
1248 tester.ExpectBucketCount(kHistogramName,
1249 sql::Connection::EVENT_STATEMENT_RUN, 1);
1250 tester.ExpectBucketCount(kGlobalHistogramName,
1251 sql::Connection::EVENT_STATEMENT_RUN, 1);
1252 tester.ExpectBucketCount(kHistogramName,
1253 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1254 tester.ExpectBucketCount(kGlobalHistogramName,
1255 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1256 tester.ExpectBucketCount(kHistogramName,
1257 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1258 tester.ExpectBucketCount(kGlobalHistogramName,
1259 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1260 }
1261
1262 {
1263 base::HistogramTester tester;
1264
1265 {
1266 sql::Statement s(db().GetUniqueStatement(
1267 "SELECT value FROM foo WHERE id > 10"));
1268 while (s.Step()) {
1269 }
1270 }
1271
1272 tester.ExpectBucketCount(kHistogramName,
1273 sql::Connection::EVENT_STATEMENT_RUN, 1);
1274 tester.ExpectBucketCount(kGlobalHistogramName,
1275 sql::Connection::EVENT_STATEMENT_RUN, 1);
1276 tester.ExpectBucketCount(kHistogramName,
1277 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1278 tester.ExpectBucketCount(kGlobalHistogramName,
1279 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1280 tester.ExpectBucketCount(kHistogramName,
1281 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1282 tester.ExpectBucketCount(kGlobalHistogramName,
1283 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1284 }
1285}
1286
shess58b8df82015-06-03 00:19:321287// Read-only query allocates time to QueryTime, but not others.
1288TEST_F(SQLConnectionTest, TimeQuery) {
1289 // Re-open with histogram tag. Use an in-memory database to minimize variance
1290 // due to filesystem.
1291 db().Close();
1292 db().set_histogram_tag("Test");
1293 ASSERT_TRUE(db().OpenInMemory());
1294
1295 sql::test::ScopedMockTimeSource time_mock(db());
1296
1297 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1298 EXPECT_TRUE(db().Execute(kCreateSql));
1299
1300 // Function to inject pauses into statements.
1301 sql::test::ScopedScalarFunction scoper(
tzikd16d2192018-03-07 08:58:361302 db(), "milliadjust", 1,
1303 base::BindRepeating(&sqlite_adjust_millis, &time_mock));
shess58b8df82015-06-03 00:19:321304
1305 base::HistogramTester tester;
1306
1307 EXPECT_TRUE(db().Execute("SELECT milliadjust(10)"));
1308
mostynbd82cd9952016-04-11 20:05:341309 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321310 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1311 ASSERT_TRUE(samples);
1312 // 10 for the adjust, 1 for the measurement.
1313 EXPECT_EQ(11, samples->sum());
1314
1315 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
vabrae960432015-08-03 08:12:541316 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321317
1318 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
vabrae960432015-08-03 08:12:541319 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321320
1321 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
vabrae960432015-08-03 08:12:541322 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321323}
1324
1325// Autocommit update allocates time to QueryTime, UpdateTime, and
1326// AutoCommitTime.
1327TEST_F(SQLConnectionTest, TimeUpdateAutocommit) {
1328 // Re-open with histogram tag. Use an in-memory database to minimize variance
1329 // due to filesystem.
1330 db().Close();
1331 db().set_histogram_tag("Test");
1332 ASSERT_TRUE(db().OpenInMemory());
1333
1334 sql::test::ScopedMockTimeSource time_mock(db());
1335
1336 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1337 EXPECT_TRUE(db().Execute(kCreateSql));
1338
1339 // Function to inject pauses into statements.
1340 sql::test::ScopedScalarFunction scoper(
tzikd16d2192018-03-07 08:58:361341 db(), "milliadjust", 1,
1342 base::BindRepeating(&sqlite_adjust_millis, &time_mock));
shess58b8df82015-06-03 00:19:321343
1344 base::HistogramTester tester;
1345
1346 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, milliadjust(10))"));
1347
mostynbd82cd9952016-04-11 20:05:341348 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321349 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1350 ASSERT_TRUE(samples);
1351 // 10 for the adjust, 1 for the measurement.
1352 EXPECT_EQ(11, samples->sum());
1353
1354 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1355 ASSERT_TRUE(samples);
1356 // 10 for the adjust, 1 for the measurement.
1357 EXPECT_EQ(11, samples->sum());
1358
1359 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
vabrae960432015-08-03 08:12:541360 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321361
1362 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1363 ASSERT_TRUE(samples);
1364 // 10 for the adjust, 1 for the measurement.
1365 EXPECT_EQ(11, samples->sum());
1366}
1367
1368// Update with explicit transaction allocates time to QueryTime, UpdateTime, and
1369// CommitTime.
1370TEST_F(SQLConnectionTest, TimeUpdateTransaction) {
1371 // Re-open with histogram tag. Use an in-memory database to minimize variance
1372 // due to filesystem.
1373 db().Close();
1374 db().set_histogram_tag("Test");
1375 ASSERT_TRUE(db().OpenInMemory());
1376
1377 sql::test::ScopedMockTimeSource time_mock(db());
1378
1379 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1380 EXPECT_TRUE(db().Execute(kCreateSql));
1381
1382 // Function to inject pauses into statements.
1383 sql::test::ScopedScalarFunction scoper(
tzikd16d2192018-03-07 08:58:361384 db(), "milliadjust", 1,
1385 base::BindRepeating(&sqlite_adjust_millis, &time_mock));
shess58b8df82015-06-03 00:19:321386
1387 base::HistogramTester tester;
1388
1389 {
1390 // Make the commit slow.
1391 sql::test::ScopedCommitHook scoped_hook(
tzikd16d2192018-03-07 08:58:361392 db(), base::BindRepeating(adjust_commit_hook, &time_mock, 100));
shess58b8df82015-06-03 00:19:321393 ASSERT_TRUE(db().BeginTransaction());
1394 EXPECT_TRUE(db().Execute(
1395 "INSERT INTO foo VALUES (11, milliadjust(10))"));
1396 EXPECT_TRUE(db().Execute(
1397 "UPDATE foo SET value = milliadjust(10) WHERE id = 11"));
1398 EXPECT_TRUE(db().CommitTransaction());
1399 }
1400
mostynbd82cd9952016-04-11 20:05:341401 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321402 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1403 ASSERT_TRUE(samples);
1404 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1405 // measuring each of BEGIN, INSERT, UPDATE, and COMMIT.
1406 EXPECT_EQ(124, samples->sum());
1407
1408 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1409 ASSERT_TRUE(samples);
1410 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1411 // measuring each of INSERT, UPDATE, and COMMIT.
1412 EXPECT_EQ(123, samples->sum());
1413
1414 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1415 ASSERT_TRUE(samples);
1416 // 100 for commit adjust, 1 for measuring COMMIT.
1417 EXPECT_EQ(101, samples->sum());
1418
1419 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
vabrae960432015-08-03 08:12:541420 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321421}
1422
ssid9f8022f2015-10-12 17:49:031423TEST_F(SQLConnectionTest, OnMemoryDump) {
ssid9f8022f2015-10-12 17:49:031424 base::trace_event::MemoryDumpArgs args = {
1425 base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
erikchenf62ea042018-05-25 21:30:571426 base::trace_event::ProcessMemoryDump pmd(args);
ssid3be5b1ec2016-01-13 14:21:571427 ASSERT_TRUE(db().memory_dump_provider_->OnMemoryDump(args, &pmd));
ssid9f8022f2015-10-12 17:49:031428 EXPECT_GE(pmd.allocator_dumps().size(), 1u);
1429}
1430
shessc8cd2a162015-10-22 20:30:461431// Test that the functions to collect diagnostic data run to completion, without
1432// worrying too much about what they generate (since that will change).
1433TEST_F(SQLConnectionTest, CollectDiagnosticInfo) {
shessc8cd2a162015-10-22 20:30:461434 const std::string corruption_info = db().CollectCorruptionInfo();
1435 EXPECT_NE(std::string::npos, corruption_info.find("SQLITE_CORRUPT"));
1436 EXPECT_NE(std::string::npos, corruption_info.find("integrity_check"));
shessc8cd2a162015-10-22 20:30:461437
1438 // A statement to see in the results.
1439 const char* kSimpleSql = "SELECT 'mountain'";
1440 Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
1441
1442 // Error includes the statement.
1443 const std::string readonly_info = db().CollectErrorInfo(SQLITE_READONLY, &s);
1444 EXPECT_NE(std::string::npos, readonly_info.find(kSimpleSql));
1445
1446 // Some other error doesn't include the statment.
1447 // TODO(shess): This is weak.
1448 const std::string full_info = db().CollectErrorInfo(SQLITE_FULL, NULL);
1449 EXPECT_EQ(std::string::npos, full_info.find(kSimpleSql));
1450
1451 // A table to see in the SQLITE_ERROR results.
1452 EXPECT_TRUE(db().Execute("CREATE TABLE volcano (x)"));
1453
1454 // Version info to see in the SQLITE_ERROR results.
1455 sql::MetaTable meta_table;
1456 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
1457
1458 const std::string error_info = db().CollectErrorInfo(SQLITE_ERROR, &s);
1459 EXPECT_NE(std::string::npos, error_info.find(kSimpleSql));
1460 EXPECT_NE(std::string::npos, error_info.find("volcano"));
1461 EXPECT_NE(std::string::npos, error_info.find("version: 4"));
1462}
1463
shessc8cd2a162015-10-22 20:30:461464TEST_F(SQLConnectionTest, RegisterIntentToUpload) {
1465 base::FilePath breadcrumb_path(
1466 db_path().DirName().Append(FILE_PATH_LITERAL("sqlite-diag")));
1467
1468 // No stale diagnostic store.
1469 ASSERT_TRUE(!base::PathExists(breadcrumb_path));
1470
1471 // The histogram tag is required to enable diagnostic features.
1472 EXPECT_FALSE(db().RegisterIntentToUpload());
1473 EXPECT_TRUE(!base::PathExists(breadcrumb_path));
1474
1475 db().Close();
1476 db().set_histogram_tag("Test");
1477 ASSERT_TRUE(db().Open(db_path()));
1478
1479 // Should signal upload only once.
1480 EXPECT_TRUE(db().RegisterIntentToUpload());
1481 EXPECT_TRUE(base::PathExists(breadcrumb_path));
1482 EXPECT_FALSE(db().RegisterIntentToUpload());
1483
1484 // Changing the histogram tag should allow new upload to succeed.
1485 db().Close();
1486 db().set_histogram_tag("NewTest");
1487 ASSERT_TRUE(db().Open(db_path()));
1488 EXPECT_TRUE(db().RegisterIntentToUpload());
1489 EXPECT_FALSE(db().RegisterIntentToUpload());
1490
1491 // Old tag is still prevented.
1492 db().Close();
1493 db().set_histogram_tag("Test");
1494 ASSERT_TRUE(db().Open(db_path()));
1495 EXPECT_FALSE(db().RegisterIntentToUpload());
1496}
shessc8cd2a162015-10-22 20:30:461497
shess9bf2c672015-12-18 01:18:081498// Test that a fresh database has mmap enabled by default, if mmap'ed I/O is
1499// enabled by SQLite.
1500TEST_F(SQLConnectionTest, MmapInitiallyEnabled) {
1501 {
1502 sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size"));
Victor Costan42988a92018-02-06 02:22:141503 ASSERT_TRUE(s.Step())
1504 << "All supported SQLite versions should have mmap support";
shess9bf2c672015-12-18 01:18:081505
1506 // If mmap I/O is not on, attempt to turn it on. If that succeeds, then
1507 // Open() should have turned it on. If mmap support is disabled, 0 is
1508 // returned. If the VFS does not understand SQLITE_FCNTL_MMAP_SIZE (for
1509 // instance MojoVFS), -1 is returned.
1510 if (s.ColumnInt(0) <= 0) {
1511 ASSERT_TRUE(db().Execute("PRAGMA mmap_size = 1048576"));
1512 s.Reset(true);
1513 ASSERT_TRUE(s.Step());
1514 EXPECT_LE(s.ColumnInt(0), 0);
1515 }
1516 }
1517
1518 // Test that explicit disable prevents mmap'ed I/O.
1519 db().Close();
1520 sql::Connection::Delete(db_path());
1521 db().set_mmap_disabled();
1522 ASSERT_TRUE(db().Open(db_path()));
shessa62504d2016-11-07 19:26:121523 EXPECT_EQ("0", ExecuteWithResult(&db(), "PRAGMA mmap_size"));
1524}
1525
1526// Test whether a fresh database gets mmap enabled when using alternate status
1527// storage.
1528TEST_F(SQLConnectionTest, MmapInitiallyEnabledAltStatus) {
1529 // Re-open fresh database with alt-status flag set.
1530 db().Close();
1531 sql::Connection::Delete(db_path());
1532 db().set_mmap_alt_status();
1533 ASSERT_TRUE(db().Open(db_path()));
1534
shess9bf2c672015-12-18 01:18:081535 {
1536 sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size"));
Victor Costan42988a92018-02-06 02:22:141537 ASSERT_TRUE(s.Step())
1538 << "All supported SQLite versions should have mmap support";
shessa62504d2016-11-07 19:26:121539
1540 // If mmap I/O is not on, attempt to turn it on. If that succeeds, then
1541 // Open() should have turned it on. If mmap support is disabled, 0 is
1542 // returned. If the VFS does not understand SQLITE_FCNTL_MMAP_SIZE (for
1543 // instance MojoVFS), -1 is returned.
1544 if (s.ColumnInt(0) <= 0) {
1545 ASSERT_TRUE(db().Execute("PRAGMA mmap_size = 1048576"));
1546 s.Reset(true);
1547 ASSERT_TRUE(s.Step());
1548 EXPECT_LE(s.ColumnInt(0), 0);
1549 }
shess9bf2c672015-12-18 01:18:081550 }
shessa62504d2016-11-07 19:26:121551
1552 // Test that explicit disable overrides set_mmap_alt_status().
1553 db().Close();
1554 sql::Connection::Delete(db_path());
1555 db().set_mmap_disabled();
1556 ASSERT_TRUE(db().Open(db_path()));
1557 EXPECT_EQ("0", ExecuteWithResult(&db(), "PRAGMA mmap_size"));
shess9bf2c672015-12-18 01:18:081558}
1559
shess9bf2c672015-12-18 01:18:081560TEST_F(SQLConnectionTest, GetAppropriateMmapSize) {
shess9bf2c672015-12-18 01:18:081561 const size_t kMmapAlot = 25 * 1024 * 1024;
shess9e77283d2016-06-13 23:53:201562 int64_t mmap_status = MetaTable::kMmapFailure;
shess9bf2c672015-12-18 01:18:081563
1564 // If there is no meta table (as for a fresh database), assume that everything
shess9e77283d2016-06-13 23:53:201565 // should be mapped, and the status of the meta table is not affected.
shess9bf2c672015-12-18 01:18:081566 ASSERT_TRUE(!db().DoesTableExist("meta"));
1567 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
shess9e77283d2016-06-13 23:53:201568 ASSERT_TRUE(!db().DoesTableExist("meta"));
shess9bf2c672015-12-18 01:18:081569
1570 // When the meta table is first created, it sets up to map everything.
1571 MetaTable().Init(&db(), 1, 1);
1572 ASSERT_TRUE(db().DoesTableExist("meta"));
1573 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1574 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1575 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1576
shessa7b07acd2017-03-19 23:59:381577 // Preload with partial progress of one page. Should map everything.
1578 ASSERT_TRUE(db().Execute("REPLACE INTO meta VALUES ('mmap_status', 1)"));
1579 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1580 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1581 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1582
shess9bf2c672015-12-18 01:18:081583 // Failure status maps nothing.
1584 ASSERT_TRUE(db().Execute("REPLACE INTO meta VALUES ('mmap_status', -2)"));
1585 ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
1586
1587 // Re-initializing the meta table does not re-create the key if the table
1588 // already exists.
1589 ASSERT_TRUE(db().Execute("DELETE FROM meta WHERE key = 'mmap_status'"));
1590 MetaTable().Init(&db(), 1, 1);
1591 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1592 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1593 ASSERT_EQ(0, mmap_status);
1594
1595 // With no key, map everything and create the key.
1596 // TODO(shess): This really should be "maps everything after validating it",
1597 // but that is more complicated to structure.
1598 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1599 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1600 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1601}
shess9bf2c672015-12-18 01:18:081602
shessa62504d2016-11-07 19:26:121603TEST_F(SQLConnectionTest, GetAppropriateMmapSizeAltStatus) {
shessa62504d2016-11-07 19:26:121604 const size_t kMmapAlot = 25 * 1024 * 1024;
1605
1606 // At this point, Connection still expects a future [meta] table.
1607 ASSERT_FALSE(db().DoesTableExist("meta"));
1608 ASSERT_FALSE(db().DoesViewExist("MmapStatus"));
1609 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1610 ASSERT_FALSE(db().DoesTableExist("meta"));
1611 ASSERT_FALSE(db().DoesViewExist("MmapStatus"));
1612
1613 // Using alt status, everything should be mapped, with state in the view.
1614 db().set_mmap_alt_status();
1615 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1616 ASSERT_FALSE(db().DoesTableExist("meta"));
1617 ASSERT_TRUE(db().DoesViewExist("MmapStatus"));
1618 EXPECT_EQ(base::IntToString(MetaTable::kMmapSuccess),
1619 ExecuteWithResult(&db(), "SELECT * FROM MmapStatus"));
1620
shessa7b07acd2017-03-19 23:59:381621 // Also maps everything when kMmapSuccess is already in the view.
shessa62504d2016-11-07 19:26:121622 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1623
shessa7b07acd2017-03-19 23:59:381624 // Preload with partial progress of one page. Should map everything.
1625 ASSERT_TRUE(db().Execute("DROP VIEW MmapStatus"));
1626 ASSERT_TRUE(db().Execute("CREATE VIEW MmapStatus (value) AS SELECT 1"));
1627 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1628 EXPECT_EQ(base::IntToString(MetaTable::kMmapSuccess),
1629 ExecuteWithResult(&db(), "SELECT * FROM MmapStatus"));
1630
shessa62504d2016-11-07 19:26:121631 // Failure status leads to nothing being mapped.
1632 ASSERT_TRUE(db().Execute("DROP VIEW MmapStatus"));
shessa7b07acd2017-03-19 23:59:381633 ASSERT_TRUE(db().Execute("CREATE VIEW MmapStatus (value) AS SELECT -2"));
shessa62504d2016-11-07 19:26:121634 ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
1635 EXPECT_EQ(base::IntToString(MetaTable::kMmapFailure),
1636 ExecuteWithResult(&db(), "SELECT * FROM MmapStatus"));
1637}
1638
shess9e77283d2016-06-13 23:53:201639// To prevent invalid SQL from accidentally shipping to production, prepared
Sigurdur Asgeirsson8d82bd02017-09-25 21:05:521640// statements which fail to compile with SQLITE_ERROR call DLOG(DCHECK). This
shess9e77283d2016-06-13 23:53:201641// case cannot be suppressed with an error callback.
1642TEST_F(SQLConnectionTest, CompileError) {
Scott Graham57ee54822017-09-13 06:37:561643 // DEATH tests not supported on Android, iOS, or Fuchsia.
1644#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA)
shess9e77283d2016-06-13 23:53:201645 if (DLOG_IS_ON(FATAL)) {
tzikd16d2192018-03-07 08:58:361646 db().set_error_callback(base::BindRepeating(&IgnoreErrorCallback));
shess9e77283d2016-06-13 23:53:201647 ASSERT_DEATH({
1648 db().GetUniqueStatement("SELECT x");
1649 }, "SQL compile error no such column: x");
1650 }
Victor Costan8a87f7e52017-11-10 01:29:301651#endif // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA)
shess9e77283d2016-06-13 23:53:201652}
1653
shessc8cd2a162015-10-22 20:30:461654} // namespace sql