blob: 800e775c94aea34e4b0b0150d3608cbc01f4eefb [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"
shess58b8df82015-06-03 00:19:3215#include "base/test/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
rohitrao83d6b83a2016-06-21 07:25:5729#if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
30#include "base/ios/ios_util.h"
Victor Costan8a87f7e52017-11-10 01:29:3031#endif // defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
rohitrao83d6b83a2016-06-21 07:25:5732
shess58b8df82015-06-03 00:19:3233namespace sql {
34namespace test {
35
36// Replaces the database time source with an object that steps forward 1ms on
37// each check, and which can be jumped forward an arbitrary amount of time
38// programmatically.
39class ScopedMockTimeSource {
40 public:
41 ScopedMockTimeSource(Connection& db)
42 : db_(db),
43 delta_(base::TimeDelta::FromMilliseconds(1)) {
44 // Save the current source and replace it.
45 save_.swap(db_.clock_);
46 db_.clock_.reset(new MockTimeSource(*this));
47 }
48 ~ScopedMockTimeSource() {
49 // Put original source back.
50 db_.clock_.swap(save_);
51 }
52
53 void adjust(const base::TimeDelta& delta) {
54 current_time_ += delta;
55 }
56
57 private:
58 class MockTimeSource : public TimeSource {
59 public:
60 MockTimeSource(ScopedMockTimeSource& owner)
61 : owner_(owner) {
62 }
Chris Watkinscf6172552017-11-27 03:25:1863 ~MockTimeSource() override = default;
shess58b8df82015-06-03 00:19:3264
65 base::TimeTicks Now() override {
66 base::TimeTicks ret(owner_.current_time_);
67 owner_.current_time_ += owner_.delta_;
68 return ret;
69 }
70
71 private:
72 ScopedMockTimeSource& owner_;
73 DISALLOW_COPY_AND_ASSIGN(MockTimeSource);
74 };
75
76 Connection& db_;
77
78 // Saves original source from |db_|.
mostynbd82cd9952016-04-11 20:05:3479 std::unique_ptr<TimeSource> save_;
shess58b8df82015-06-03 00:19:3280
81 // Current time returned by mock.
82 base::TimeTicks current_time_;
83
84 // How far to jump on each Now() call.
85 base::TimeDelta delta_;
86
87 DISALLOW_COPY_AND_ASSIGN(ScopedMockTimeSource);
88};
89
90// Allow a test to add a SQLite function in a scoped context.
91class ScopedScalarFunction {
92 public:
93 ScopedScalarFunction(
94 sql::Connection& db,
95 const char* function_name,
96 int args,
97 base::Callback<void(sqlite3_context*,int,sqlite3_value**)> cb)
98 : db_(db.db_), function_name_(function_name), cb_(cb) {
shess6ce9d1f02015-09-02 19:37:4399 sqlite3_create_function_v2(db_, function_name, args, SQLITE_UTF8,
100 this, &Run, NULL, NULL, NULL);
shess58b8df82015-06-03 00:19:32101 }
102 ~ScopedScalarFunction() {
shess6ce9d1f02015-09-02 19:37:43103 sqlite3_create_function_v2(db_, function_name_, 0, SQLITE_UTF8,
104 NULL, NULL, NULL, NULL, NULL);
shess58b8df82015-06-03 00:19:32105 }
106
107 private:
108 static void Run(sqlite3_context* context, int argc, sqlite3_value** argv) {
109 ScopedScalarFunction* t = static_cast<ScopedScalarFunction*>(
110 sqlite3_user_data(context));
111 t->cb_.Run(context, argc, argv);
112 }
113
114 sqlite3* db_;
115 const char* function_name_;
116 base::Callback<void(sqlite3_context*,int,sqlite3_value**)> cb_;
117
118 DISALLOW_COPY_AND_ASSIGN(ScopedScalarFunction);
119};
120
121// Allow a test to add a SQLite commit hook in a scoped context.
122class ScopedCommitHook {
123 public:
124 ScopedCommitHook(sql::Connection& db,
125 base::Callback<int(void)> cb)
126 : db_(db.db_),
127 cb_(cb) {
shess6ce9d1f02015-09-02 19:37:43128 sqlite3_commit_hook(db_, &Run, this);
shess58b8df82015-06-03 00:19:32129 }
130 ~ScopedCommitHook() {
shess6ce9d1f02015-09-02 19:37:43131 sqlite3_commit_hook(db_, NULL, NULL);
shess58b8df82015-06-03 00:19:32132 }
133
134 private:
135 static int Run(void* p) {
136 ScopedCommitHook* t = static_cast<ScopedCommitHook*>(p);
137 return t->cb_.Run();
138 }
139
140 sqlite3* db_;
141 base::Callback<int(void)> cb_;
142
143 DISALLOW_COPY_AND_ASSIGN(ScopedCommitHook);
144};
145
146} // namespace test
shess58b8df82015-06-03 00:19:32147
[email protected]7bae5742013-07-10 20:46:16148namespace {
149
shess7e2baba2016-10-27 23:46:05150using sql::test::ExecuteWithResults;
151using sql::test::ExecuteWithResult;
152
[email protected]7bae5742013-07-10 20:46:16153// Helper to return the count of items in sqlite_master. Return -1 in
154// case of error.
155int SqliteMasterCount(sql::Connection* db) {
156 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master";
157 sql::Statement s(db->GetUniqueStatement(kMasterCount));
158 return s.Step() ? s.ColumnInt(0) : -1;
159}
160
[email protected]98cf3002013-07-12 01:38:56161// Track the number of valid references which share the same pointer.
162// This is used to allow testing an implicitly use-after-free case by
163// explicitly having the ref count live longer than the object.
164class RefCounter {
165 public:
166 RefCounter(size_t* counter)
167 : counter_(counter) {
168 (*counter_)++;
169 }
170 RefCounter(const RefCounter& other)
171 : counter_(other.counter_) {
172 (*counter_)++;
173 }
174 ~RefCounter() {
175 (*counter_)--;
176 }
177
178 private:
179 size_t* counter_;
180
181 DISALLOW_ASSIGN(RefCounter);
182};
183
184// Empty callback for implementation of ErrorCallbackSetHelper().
185void IgnoreErrorCallback(int error, sql::Statement* stmt) {
186}
187
188void ErrorCallbackSetHelper(sql::Connection* db,
189 size_t* counter,
190 const RefCounter& r,
191 int error, sql::Statement* stmt) {
192 // The ref count should not go to zero when changing the callback.
193 EXPECT_GT(*counter, 0u);
194 db->set_error_callback(base::Bind(&IgnoreErrorCallback));
195 EXPECT_GT(*counter, 0u);
196}
197
198void ErrorCallbackResetHelper(sql::Connection* db,
199 size_t* counter,
200 const RefCounter& r,
201 int error, sql::Statement* stmt) {
202 // The ref count should not go to zero when clearing the callback.
203 EXPECT_GT(*counter, 0u);
204 db->reset_error_callback();
205 EXPECT_GT(*counter, 0u);
206}
207
shess1cf87f22016-10-25 22:18:29208// Handle errors by blowing away the database.
209void RazeErrorCallback(sql::Connection* db,
210 int expected_error,
211 int error,
212 sql::Statement* stmt) {
213 // Nothing here needs extended errors at this time.
214 EXPECT_EQ(expected_error, expected_error&0xff);
215 EXPECT_EQ(expected_error, error&0xff);
216 db->RazeAndClose();
217}
218
[email protected]81a2a602013-07-17 19:10:36219#if defined(OS_POSIX)
220// Set a umask and restore the old mask on destruction. Cribbed from
221// shared_memory_unittest.cc. Used by POSIX-only UserPermission test.
222class ScopedUmaskSetter {
223 public:
224 explicit ScopedUmaskSetter(mode_t target_mask) {
225 old_umask_ = umask(target_mask);
226 }
227 ~ScopedUmaskSetter() { umask(old_umask_); }
228 private:
229 mode_t old_umask_;
230 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
231};
Victor Costan8a87f7e52017-11-10 01:29:30232#endif // defined(OS_POSIX)
[email protected]81a2a602013-07-17 19:10:36233
shessc8cd2a162015-10-22 20:30:46234// SQLite function to adjust mock time by |argv[0]| milliseconds.
235void sqlite_adjust_millis(sql::test::ScopedMockTimeSource* time_mock,
236 sqlite3_context* context,
237 int argc, sqlite3_value** argv) {
avi0b519202015-12-21 07:25:19238 int64_t milliseconds = argc > 0 ? sqlite3_value_int64(argv[0]) : 1000;
shessc8cd2a162015-10-22 20:30:46239 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
240 sqlite3_result_int64(context, milliseconds);
241}
242
243// Adjust mock time by |milliseconds| on commit.
244int adjust_commit_hook(sql::test::ScopedMockTimeSource* time_mock,
avi0b519202015-12-21 07:25:19245 int64_t milliseconds) {
shessc8cd2a162015-10-22 20:30:46246 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
247 return SQLITE_OK;
248}
249
250const char kCommitTime[] = "Sqlite.CommitTime.Test";
251const char kAutoCommitTime[] = "Sqlite.AutoCommitTime.Test";
252const char kUpdateTime[] = "Sqlite.UpdateTime.Test";
253const char kQueryTime[] = "Sqlite.QueryTime.Test";
254
255} // namespace
256
shess1cf87f22016-10-25 22:18:29257using SQLConnectionTest = sql::SQLTestBase;
[email protected]e5ffd0e42009-09-11 21:30:56258
259TEST_F(SQLConnectionTest, Execute) {
260 // Valid statement should return true.
261 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
262 EXPECT_EQ(SQLITE_OK, db().GetErrorCode());
263
264 // Invalid statement should fail.
[email protected]eff1fa522011-12-12 23:50:59265 ASSERT_EQ(SQLITE_ERROR,
266 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b"));
[email protected]e5ffd0e42009-09-11 21:30:56267 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode());
268}
269
[email protected]eff1fa522011-12-12 23:50:59270TEST_F(SQLConnectionTest, ExecuteWithErrorCode) {
271 ASSERT_EQ(SQLITE_OK,
272 db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)"));
273 ASSERT_EQ(SQLITE_ERROR,
274 db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE"));
275 ASSERT_EQ(SQLITE_ERROR,
276 db().ExecuteAndReturnErrorCode(
277 "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)"));
278}
279
[email protected]e5ffd0e42009-09-11 21:30:56280TEST_F(SQLConnectionTest, CachedStatement) {
281 sql::StatementID id1("foo", 12);
282
283 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
284 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
285
286 // Create a new cached statement.
287 {
288 sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo"));
[email protected]eff1fa522011-12-12 23:50:59289 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56290
291 ASSERT_TRUE(s.Step());
292 EXPECT_EQ(12, s.ColumnInt(0));
293 }
294
295 // The statement should be cached still.
296 EXPECT_TRUE(db().HasCachedStatement(id1));
297
298 {
299 // Get the same statement using different SQL. This should ignore our
300 // SQL and use the cached one (so it will be valid).
301 sql::Statement s(db().GetCachedStatement(id1, "something invalid("));
[email protected]eff1fa522011-12-12 23:50:59302 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56303
304 ASSERT_TRUE(s.Step());
305 EXPECT_EQ(12, s.ColumnInt(0));
306 }
307
308 // Make sure other statements aren't marked as cached.
309 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE));
310}
311
[email protected]eff1fa522011-12-12 23:50:59312TEST_F(SQLConnectionTest, IsSQLValidTest) {
313 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
314 ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo"));
315 ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo"));
316}
317
[email protected]e5ffd0e42009-09-11 21:30:56318TEST_F(SQLConnectionTest, DoesStuffExist) {
shessa62504d2016-11-07 19:26:12319 // Test DoesTableExist and DoesIndexExist.
[email protected]e5ffd0e42009-09-11 21:30:56320 EXPECT_FALSE(db().DoesTableExist("foo"));
321 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
shess92a2ab12015-04-09 01:59:47322 ASSERT_TRUE(db().Execute("CREATE INDEX foo_a ON foo (a)"));
shessa62504d2016-11-07 19:26:12323 EXPECT_FALSE(db().DoesIndexExist("foo"));
[email protected]e5ffd0e42009-09-11 21:30:56324 EXPECT_TRUE(db().DoesTableExist("foo"));
shess92a2ab12015-04-09 01:59:47325 EXPECT_TRUE(db().DoesIndexExist("foo_a"));
shessa62504d2016-11-07 19:26:12326 EXPECT_FALSE(db().DoesTableExist("foo_a"));
327
328 // Test DoesViewExist. The CREATE VIEW is an older form because some iOS
329 // versions use an earlier version of SQLite, and the difference isn't
330 // relevant for this test.
331 EXPECT_FALSE(db().DoesViewExist("voo"));
332 ASSERT_TRUE(db().Execute("CREATE VIEW voo AS SELECT 1"));
333 EXPECT_FALSE(db().DoesIndexExist("voo"));
334 EXPECT_FALSE(db().DoesTableExist("voo"));
335 EXPECT_TRUE(db().DoesViewExist("voo"));
[email protected]e5ffd0e42009-09-11 21:30:56336
337 // Test DoesColumnExist.
338 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
339 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
340
[email protected]e7afe2452010-08-22 16:19:13341 // Testing for a column on a nonexistent table.
[email protected]e5ffd0e42009-09-11 21:30:56342 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
shess92a2ab12015-04-09 01:59:47343
344 // Names are not case sensitive.
345 EXPECT_TRUE(db().DoesTableExist("FOO"));
346 EXPECT_TRUE(db().DoesColumnExist("FOO", "A"));
[email protected]e5ffd0e42009-09-11 21:30:56347}
348
349TEST_F(SQLConnectionTest, GetLastInsertRowId) {
350 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
351
352 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
353
354 // Last insert row ID should be valid.
tfarina720d4f32015-05-11 22:31:26355 int64_t row = db().GetLastInsertRowId();
[email protected]e5ffd0e42009-09-11 21:30:56356 EXPECT_LT(0, row);
357
358 // It should be the primary key of the row we just inserted.
359 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
360 s.BindInt64(0, row);
361 ASSERT_TRUE(s.Step());
362 EXPECT_EQ(12, s.ColumnInt(0));
363}
[email protected]44ad7d902012-03-23 00:09:05364
365TEST_F(SQLConnectionTest, Rollback) {
366 ASSERT_TRUE(db().BeginTransaction());
367 ASSERT_TRUE(db().BeginTransaction());
368 EXPECT_EQ(2, db().transaction_nesting());
369 db().RollbackTransaction();
370 EXPECT_FALSE(db().CommitTransaction());
371 EXPECT_TRUE(db().BeginTransaction());
372}
[email protected]8e0c01282012-04-06 19:36:49373
shess976814402016-06-21 06:56:25374// Test the scoped error expecter by attempting to insert a duplicate
[email protected]4350e322013-06-18 22:18:10375// value into an index.
shess976814402016-06-21 06:56:25376TEST_F(SQLConnectionTest, ScopedErrorExpecter) {
[email protected]4350e322013-06-18 22:18:10377 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
378 ASSERT_TRUE(db().Execute(kCreateSql));
379 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
380
shess92a2ab12015-04-09 01:59:47381 {
shess976814402016-06-21 06:56:25382 sql::test::ScopedErrorExpecter expecter;
383 expecter.ExpectError(SQLITE_CONSTRAINT);
shess92a2ab12015-04-09 01:59:47384 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
shess976814402016-06-21 06:56:25385 ASSERT_TRUE(expecter.SawExpectedErrors());
shess92a2ab12015-04-09 01:59:47386 }
387}
388
389// Test that clients of GetUntrackedStatement() can test corruption-handling
shess976814402016-06-21 06:56:25390// with ScopedErrorExpecter.
shess92a2ab12015-04-09 01:59:47391TEST_F(SQLConnectionTest, ScopedIgnoreUntracked) {
392 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
393 ASSERT_TRUE(db().Execute(kCreateSql));
394 ASSERT_FALSE(db().DoesTableExist("bar"));
395 ASSERT_TRUE(db().DoesTableExist("foo"));
396 ASSERT_TRUE(db().DoesColumnExist("foo", "id"));
397 db().Close();
398
399 // Corrupt the database so that nothing works, including PRAGMAs.
erg102ceb412015-06-20 01:38:13400 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
shess92a2ab12015-04-09 01:59:47401
402 {
shess976814402016-06-21 06:56:25403 sql::test::ScopedErrorExpecter expecter;
404 expecter.ExpectError(SQLITE_CORRUPT);
shess92a2ab12015-04-09 01:59:47405 ASSERT_TRUE(db().Open(db_path()));
406 ASSERT_FALSE(db().DoesTableExist("bar"));
407 ASSERT_FALSE(db().DoesTableExist("foo"));
408 ASSERT_FALSE(db().DoesColumnExist("foo", "id"));
shess976814402016-06-21 06:56:25409 ASSERT_TRUE(expecter.SawExpectedErrors());
shess92a2ab12015-04-09 01:59:47410 }
[email protected]4350e322013-06-18 22:18:10411}
412
[email protected]98cf3002013-07-12 01:38:56413TEST_F(SQLConnectionTest, ErrorCallback) {
414 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
415 ASSERT_TRUE(db().Execute(kCreateSql));
416 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
417
418 int error = SQLITE_OK;
419 {
420 sql::ScopedErrorCallback sec(
421 &db(), base::Bind(&sql::CaptureErrorCallback, &error));
[email protected]98cf3002013-07-12 01:38:56422 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
Scott Hessdcf120482015-02-10 21:33:29423
424 // Later versions of SQLite throw SQLITE_CONSTRAINT_UNIQUE. The specific
425 // sub-error isn't really important.
426 EXPECT_EQ(SQLITE_CONSTRAINT, (error&0xff));
[email protected]98cf3002013-07-12 01:38:56427 }
428
429 // Callback is no longer in force due to reset.
430 {
431 error = SQLITE_OK;
shess976814402016-06-21 06:56:25432 sql::test::ScopedErrorExpecter expecter;
433 expecter.ExpectError(SQLITE_CONSTRAINT);
[email protected]98cf3002013-07-12 01:38:56434 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
shess976814402016-06-21 06:56:25435 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]98cf3002013-07-12 01:38:56436 EXPECT_EQ(SQLITE_OK, error);
437 }
438
439 // base::Bind() can curry arguments to be passed by const reference
[email protected]81a2a602013-07-17 19:10:36440 // to the callback function. If the callback function calls
441 // re/set_error_callback(), the storage for those arguments can be
442 // deleted while the callback function is still executing.
[email protected]98cf3002013-07-12 01:38:56443 //
444 // RefCounter() counts how many objects are live using an external
445 // count. The same counter is passed to the callback, so that it
446 // can check directly even if the RefCounter object is no longer
447 // live.
448 {
449 size_t count = 0;
450 sql::ScopedErrorCallback sec(
451 &db(), base::Bind(&ErrorCallbackSetHelper,
452 &db(), &count, RefCounter(&count)));
453
454 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
455 }
456
457 // Same test, but reset_error_callback() case.
458 {
459 size_t count = 0;
460 sql::ScopedErrorCallback sec(
461 &db(), base::Bind(&ErrorCallbackResetHelper,
462 &db(), &count, RefCounter(&count)));
463
464 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
465 }
466}
467
[email protected]8e0c01282012-04-06 19:36:49468// Test that sql::Connection::Raze() results in a database without the
469// tables from the original database.
470TEST_F(SQLConnectionTest, Raze) {
471 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
472 ASSERT_TRUE(db().Execute(kCreateSql));
473 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
474
[email protected]69c58452012-08-06 19:22:42475 int pragma_auto_vacuum = 0;
476 {
477 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
478 ASSERT_TRUE(s.Step());
479 pragma_auto_vacuum = s.ColumnInt(0);
480 ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1);
481 }
482
483 // If auto_vacuum is set, there's an extra page to maintain a freelist.
484 const int kExpectedPageCount = 2 + pragma_auto_vacuum;
485
[email protected]8e0c01282012-04-06 19:36:49486 {
487 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
488 ASSERT_TRUE(s.Step());
[email protected]69c58452012-08-06 19:22:42489 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0));
[email protected]8e0c01282012-04-06 19:36:49490 }
491
492 {
493 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master"));
494 ASSERT_TRUE(s.Step());
495 EXPECT_EQ("table", s.ColumnString(0));
496 EXPECT_EQ("foo", s.ColumnString(1));
497 EXPECT_EQ("foo", s.ColumnString(2));
[email protected]69c58452012-08-06 19:22:42498 // Table "foo" is stored in the last page of the file.
499 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3));
[email protected]8e0c01282012-04-06 19:36:49500 EXPECT_EQ(kCreateSql, s.ColumnString(4));
501 }
502
503 ASSERT_TRUE(db().Raze());
504
505 {
506 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
507 ASSERT_TRUE(s.Step());
508 EXPECT_EQ(1, s.ColumnInt(0));
509 }
510
[email protected]7bae5742013-07-10 20:46:16511 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]69c58452012-08-06 19:22:42512
513 {
514 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
515 ASSERT_TRUE(s.Step());
[email protected]6d42f152012-11-10 00:38:24516 // The new database has the same auto_vacuum as a fresh database.
[email protected]69c58452012-08-06 19:22:42517 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0));
518 }
[email protected]8e0c01282012-04-06 19:36:49519}
520
shess7e2baba2016-10-27 23:46:05521// Helper for SQLConnectionTest.RazePageSize. Creates a fresh db based on
522// db_prefix, with the given initial page size, and verifies it against the
523// expected size. Then changes to the final page size and razes, verifying that
524// the fresh database ends up with the expected final page size.
525void TestPageSize(const base::FilePath& db_prefix,
526 int initial_page_size,
527 const std::string& expected_initial_page_size,
528 int final_page_size,
529 const std::string& expected_final_page_size) {
530 const char kCreateSql[] = "CREATE TABLE x (t TEXT)";
531 const char kInsertSql1[] = "INSERT INTO x VALUES ('This is a test')";
532 const char kInsertSql2[] = "INSERT INTO x VALUES ('That was a test')";
533
534 const base::FilePath db_path = db_prefix.InsertBeforeExtensionASCII(
535 base::IntToString(initial_page_size));
536 sql::Connection::Delete(db_path);
537 sql::Connection db;
538 db.set_page_size(initial_page_size);
539 ASSERT_TRUE(db.Open(db_path));
540 ASSERT_TRUE(db.Execute(kCreateSql));
541 ASSERT_TRUE(db.Execute(kInsertSql1));
542 ASSERT_TRUE(db.Execute(kInsertSql2));
543 ASSERT_EQ(expected_initial_page_size,
544 ExecuteWithResult(&db, "PRAGMA page_size"));
545
546 // Raze will use the page size set in the connection object, which may not
547 // match the file's page size.
548 db.set_page_size(final_page_size);
549 ASSERT_TRUE(db.Raze());
550
551 // SQLite 3.10.2 (at least) has a quirk with the sqlite3_backup() API (used by
552 // Raze()) which causes the destination database to remember the previous
553 // page_size, even if the overwriting database changed the page_size. Access
554 // the actual database to cause the cached value to be updated.
555 EXPECT_EQ("0", ExecuteWithResult(&db, "SELECT COUNT(*) FROM sqlite_master"));
556
557 EXPECT_EQ(expected_final_page_size,
558 ExecuteWithResult(&db, "PRAGMA page_size"));
559 EXPECT_EQ("1", ExecuteWithResult(&db, "PRAGMA page_count"));
560}
561
562// Verify that sql::Recovery maintains the page size, and the virtual table
563// works with page sizes other than SQLite's default. Also verify the case
564// where the default page size has changed.
[email protected]8e0c01282012-04-06 19:36:49565TEST_F(SQLConnectionTest, RazePageSize) {
shess7e2baba2016-10-27 23:46:05566 const std::string default_page_size =
567 ExecuteWithResult(&db(), "PRAGMA page_size");
[email protected]8e0c01282012-04-06 19:36:49568
shess7e2baba2016-10-27 23:46:05569 // The database should have the default page size after raze.
570 EXPECT_NO_FATAL_FAILURE(
571 TestPageSize(db_path(), 0, default_page_size, 0, default_page_size));
[email protected]8e0c01282012-04-06 19:36:49572
shess7e2baba2016-10-27 23:46:05573 // Sync user 32k pages.
574 EXPECT_NO_FATAL_FAILURE(
575 TestPageSize(db_path(), 32768, "32768", 32768, "32768"));
[email protected]8e0c01282012-04-06 19:36:49576
shess7e2baba2016-10-27 23:46:05577 // Many clients use 4k pages. This is the SQLite default after 3.12.0.
578 EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 4096, "4096", 4096, "4096"));
579
580 // 1k is the default page size before 3.12.0.
581 EXPECT_NO_FATAL_FAILURE(TestPageSize(db_path(), 1024, "1024", 1024, "1024"));
582
583 EXPECT_NO_FATAL_FAILURE(
584 TestPageSize(db_path(), 2048, "2048", 4096, "4096"));
585
586 // Databases with no page size specified should result in the new default
587 // page size. 2k has never been the default page size.
588 ASSERT_NE("2048", default_page_size);
589 EXPECT_NO_FATAL_FAILURE(
590 TestPageSize(db_path(), 2048, "2048", 0, default_page_size));
[email protected]8e0c01282012-04-06 19:36:49591}
592
593// Test that Raze() results are seen in other connections.
594TEST_F(SQLConnectionTest, RazeMultiple) {
595 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
596 ASSERT_TRUE(db().Execute(kCreateSql));
597
598 sql::Connection other_db;
599 ASSERT_TRUE(other_db.Open(db_path()));
600
601 // Check that the second connection sees the table.
[email protected]7bae5742013-07-10 20:46:16602 ASSERT_EQ(1, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49603
604 ASSERT_TRUE(db().Raze());
605
606 // The second connection sees the updated database.
[email protected]7bae5742013-07-10 20:46:16607 ASSERT_EQ(0, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49608}
609
610TEST_F(SQLConnectionTest, RazeLocked) {
611 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
612 ASSERT_TRUE(db().Execute(kCreateSql));
613
614 // Open a transaction and write some data in a second connection.
615 // This will acquire a PENDING or EXCLUSIVE transaction, which will
616 // cause the raze to fail.
617 sql::Connection other_db;
618 ASSERT_TRUE(other_db.Open(db_path()));
619 ASSERT_TRUE(other_db.BeginTransaction());
620 const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')";
621 ASSERT_TRUE(other_db.Execute(kInsertSql));
622
623 ASSERT_FALSE(db().Raze());
624
625 // Works after COMMIT.
626 ASSERT_TRUE(other_db.CommitTransaction());
627 ASSERT_TRUE(db().Raze());
628
629 // Re-create the database.
630 ASSERT_TRUE(db().Execute(kCreateSql));
631 ASSERT_TRUE(db().Execute(kInsertSql));
632
633 // An unfinished read transaction in the other connection also
634 // blocks raze.
635 const char *kQuery = "SELECT COUNT(*) FROM foo";
636 sql::Statement s(other_db.GetUniqueStatement(kQuery));
637 ASSERT_TRUE(s.Step());
638 ASSERT_FALSE(db().Raze());
639
640 // Complete the statement unlocks the database.
641 ASSERT_FALSE(s.Step());
642 ASSERT_TRUE(db().Raze());
643}
644
[email protected]7bae5742013-07-10 20:46:16645// Verify that Raze() can handle an empty file. SQLite should treat
646// this as an empty database.
647TEST_F(SQLConnectionTest, RazeEmptyDB) {
648 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
649 ASSERT_TRUE(db().Execute(kCreateSql));
650 db().Close();
651
erg102ceb412015-06-20 01:38:13652 TruncateDatabase();
[email protected]7bae5742013-07-10 20:46:16653
654 ASSERT_TRUE(db().Open(db_path()));
655 ASSERT_TRUE(db().Raze());
656 EXPECT_EQ(0, SqliteMasterCount(&db()));
657}
658
659// Verify that Raze() can handle a file of junk.
660TEST_F(SQLConnectionTest, RazeNOTADB) {
661 db().Close();
662 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13663 ASSERT_FALSE(GetPathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16664
erg102ceb412015-06-20 01:38:13665 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE_AND_TRUNCATE);
666 ASSERT_TRUE(GetPathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16667
Scott Hessdcf120482015-02-10 21:33:29668 // SQLite will successfully open the handle, but fail when running PRAGMA
669 // statements that access the database.
[email protected]7bae5742013-07-10 20:46:16670 {
shess976814402016-06-21 06:56:25671 sql::test::ScopedErrorExpecter expecter;
Scott Hessdcf120482015-02-10 21:33:29672
673 // Earlier versions of Chromium compiled against SQLite 3.6.7.3, which
674 // returned SQLITE_IOERR_SHORT_READ in this case. Some platforms may still
675 // compile against an earlier SQLite via USE_SYSTEM_SQLITE.
shess976814402016-06-21 06:56:25676 if (expecter.SQLiteLibVersionNumber() < 3008005) {
677 expecter.ExpectError(SQLITE_IOERR_SHORT_READ);
Scott Hessdcf120482015-02-10 21:33:29678 } else {
shess976814402016-06-21 06:56:25679 expecter.ExpectError(SQLITE_NOTADB);
Scott Hessdcf120482015-02-10 21:33:29680 }
681
[email protected]7bae5742013-07-10 20:46:16682 EXPECT_TRUE(db().Open(db_path()));
shess976814402016-06-21 06:56:25683 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]7bae5742013-07-10 20:46:16684 }
685 EXPECT_TRUE(db().Raze());
686 db().Close();
687
688 // Now empty, the open should open an empty database.
689 EXPECT_TRUE(db().Open(db_path()));
690 EXPECT_EQ(0, SqliteMasterCount(&db()));
691}
692
693// Verify that Raze() can handle a database overwritten with garbage.
694TEST_F(SQLConnectionTest, RazeNOTADB2) {
695 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
696 ASSERT_TRUE(db().Execute(kCreateSql));
697 ASSERT_EQ(1, SqliteMasterCount(&db()));
698 db().Close();
699
erg102ceb412015-06-20 01:38:13700 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE);
[email protected]7bae5742013-07-10 20:46:16701
702 // SQLite will successfully open the handle, but will fail with
703 // SQLITE_NOTADB on pragma statemenets which attempt to read the
704 // corrupted header.
705 {
shess976814402016-06-21 06:56:25706 sql::test::ScopedErrorExpecter expecter;
707 expecter.ExpectError(SQLITE_NOTADB);
[email protected]7bae5742013-07-10 20:46:16708 EXPECT_TRUE(db().Open(db_path()));
shess976814402016-06-21 06:56:25709 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]7bae5742013-07-10 20:46:16710 }
711 EXPECT_TRUE(db().Raze());
712 db().Close();
713
714 // Now empty, the open should succeed with an empty database.
715 EXPECT_TRUE(db().Open(db_path()));
716 EXPECT_EQ(0, SqliteMasterCount(&db()));
717}
718
719// Test that a callback from Open() can raze the database. This is
720// essential for cases where the Open() can fail entirely, so the
[email protected]fed734a2013-07-17 04:45:13721// Raze() cannot happen later. Additionally test that when the
722// callback does this during Open(), the open is retried and succeeds.
[email protected]fed734a2013-07-17 04:45:13723TEST_F(SQLConnectionTest, RazeCallbackReopen) {
[email protected]7bae5742013-07-10 20:46:16724 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
725 ASSERT_TRUE(db().Execute(kCreateSql));
726 ASSERT_EQ(1, SqliteMasterCount(&db()));
[email protected]7bae5742013-07-10 20:46:16727 db().Close();
728
[email protected]a8848a72013-11-18 04:18:47729 // Corrupt the database so that nothing works, including PRAGMAs.
erg102ceb412015-06-20 01:38:13730 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]7bae5742013-07-10 20:46:16731
[email protected]fed734a2013-07-17 04:45:13732 // Open() will succeed, even though the PRAGMA calls within will
733 // fail with SQLITE_CORRUPT, as will this PRAGMA.
734 {
shess976814402016-06-21 06:56:25735 sql::test::ScopedErrorExpecter expecter;
736 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]fed734a2013-07-17 04:45:13737 ASSERT_TRUE(db().Open(db_path()));
738 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum"));
739 db().Close();
shess976814402016-06-21 06:56:25740 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]fed734a2013-07-17 04:45:13741 }
742
shess1cf87f22016-10-25 22:18:29743 db().set_error_callback(base::Bind(&RazeErrorCallback,
744 &db(),
[email protected]7bae5742013-07-10 20:46:16745 SQLITE_CORRUPT));
746
[email protected]fed734a2013-07-17 04:45:13747 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error
748 // callback will call RazeAndClose(). Open() will then fail and be
749 // retried. The second Open() on the empty database will succeed
750 // cleanly.
751 ASSERT_TRUE(db().Open(db_path()));
752 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum"));
[email protected]7bae5742013-07-10 20:46:16753 EXPECT_EQ(0, SqliteMasterCount(&db()));
754}
755
[email protected]41a97c812013-02-07 02:35:38756// Basic test of RazeAndClose() operation.
757TEST_F(SQLConnectionTest, RazeAndClose) {
758 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
759 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
760
761 // Test that RazeAndClose() closes the database, and that the
762 // database is empty when re-opened.
763 ASSERT_TRUE(db().Execute(kCreateSql));
764 ASSERT_TRUE(db().Execute(kPopulateSql));
765 ASSERT_TRUE(db().RazeAndClose());
766 ASSERT_FALSE(db().is_open());
767 db().Close();
768 ASSERT_TRUE(db().Open(db_path()));
[email protected]7bae5742013-07-10 20:46:16769 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38770
771 // Test that RazeAndClose() can break transactions.
772 ASSERT_TRUE(db().Execute(kCreateSql));
773 ASSERT_TRUE(db().Execute(kPopulateSql));
774 ASSERT_TRUE(db().BeginTransaction());
775 ASSERT_TRUE(db().RazeAndClose());
776 ASSERT_FALSE(db().is_open());
777 ASSERT_FALSE(db().CommitTransaction());
778 db().Close();
779 ASSERT_TRUE(db().Open(db_path()));
[email protected]7bae5742013-07-10 20:46:16780 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38781}
782
783// Test that various operations fail without crashing after
784// RazeAndClose().
785TEST_F(SQLConnectionTest, RazeAndCloseDiagnostics) {
786 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
787 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
788 const char* kSimpleSql = "SELECT 1";
789
790 ASSERT_TRUE(db().Execute(kCreateSql));
791 ASSERT_TRUE(db().Execute(kPopulateSql));
792
793 // Test baseline expectations.
794 db().Preload();
795 ASSERT_TRUE(db().DoesTableExist("foo"));
796 ASSERT_TRUE(db().IsSQLValid(kSimpleSql));
797 ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql));
798 ASSERT_TRUE(db().Execute(kSimpleSql));
799 ASSERT_TRUE(db().is_open());
800 {
801 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
802 ASSERT_TRUE(s.Step());
803 }
804 {
805 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
806 ASSERT_TRUE(s.Step());
807 }
808 ASSERT_TRUE(db().BeginTransaction());
809 ASSERT_TRUE(db().CommitTransaction());
810 ASSERT_TRUE(db().BeginTransaction());
811 db().RollbackTransaction();
812
813 ASSERT_TRUE(db().RazeAndClose());
814
815 // At this point, they should all fail, but not crash.
816 db().Preload();
817 ASSERT_FALSE(db().DoesTableExist("foo"));
818 ASSERT_FALSE(db().IsSQLValid(kSimpleSql));
819 ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql));
820 ASSERT_FALSE(db().Execute(kSimpleSql));
821 ASSERT_FALSE(db().is_open());
822 {
823 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
824 ASSERT_FALSE(s.Step());
825 }
826 {
827 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
828 ASSERT_FALSE(s.Step());
829 }
830 ASSERT_FALSE(db().BeginTransaction());
831 ASSERT_FALSE(db().CommitTransaction());
832 ASSERT_FALSE(db().BeginTransaction());
833 db().RollbackTransaction();
834
835 // Close normally to reset the poisoned flag.
836 db().Close();
837
Scott Graham57ee54822017-09-13 06:37:56838 // DEATH tests not supported on Android, iOS, or Fuchsia.
839#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA)
[email protected]41a97c812013-02-07 02:35:38840 // Once the real Close() has been called, various calls enforce API
841 // usage by becoming fatal in debug mode. Since DEATH tests are
842 // expensive, just test one of them.
843 if (DLOG_IS_ON(FATAL)) {
844 ASSERT_DEATH({
845 db().IsSQLValid(kSimpleSql);
846 }, "Illegal use of connection without a db");
847 }
Victor Costan8a87f7e52017-11-10 01:29:30848#endif // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA)
[email protected]41a97c812013-02-07 02:35:38849}
850
851// TODO(shess): Spin up a background thread to hold other_db, to more
852// closely match real life. That would also allow testing
853// RazeWithTimeout().
854
shess92a6fb22017-04-23 04:33:30855// On Windows, truncate silently fails against a memory-mapped file. One goal
856// of Raze() is to truncate the file to remove blocks which generate I/O errors.
857// Test that Raze() turns off memory mapping so that the file is truncated.
858// [This would not cover the case of multiple connections where one of the other
859// connections is memory-mapped. That is infrequent in Chromium.]
860TEST_F(SQLConnectionTest, RazeTruncate) {
861 // The empty database has 0 or 1 pages. Raze() should leave it with exactly 1
862 // page. Not checking directly because auto_vacuum on Android adds a freelist
863 // page.
864 ASSERT_TRUE(db().Raze());
865 int64_t expected_size;
866 ASSERT_TRUE(base::GetFileSize(db_path(), &expected_size));
867 ASSERT_GT(expected_size, 0);
868
869 // Cause the database to take a few pages.
870 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
871 ASSERT_TRUE(db().Execute(kCreateSql));
872 for (size_t i = 0; i < 24; ++i) {
873 ASSERT_TRUE(
874 db().Execute("INSERT INTO foo (value) VALUES (randomblob(1024))"));
875 }
876 int64_t db_size;
877 ASSERT_TRUE(base::GetFileSize(db_path(), &db_size));
878 ASSERT_GT(db_size, expected_size);
879
880 // Make a query covering most of the database file to make sure that the
881 // blocks are actually mapped into memory. Empirically, the truncate problem
882 // doesn't seem to happen if no blocks are mapped.
883 EXPECT_EQ("24576",
884 ExecuteWithResult(&db(), "SELECT SUM(LENGTH(value)) FROM foo"));
885
886 ASSERT_TRUE(db().Raze());
887 ASSERT_TRUE(base::GetFileSize(db_path(), &db_size));
888 ASSERT_EQ(expected_size, db_size);
889}
890
[email protected]1348765a2012-07-24 08:25:53891#if defined(OS_ANDROID)
892TEST_F(SQLConnectionTest, SetTempDirForSQL) {
893
894 sql::MetaTable meta_table;
895 // Below call needs a temporary directory in sqlite3
896 // On Android, it can pass only when the temporary directory is set.
897 // Otherwise, sqlite3 doesn't find the correct directory to store
898 // temporary files and will report the error 'unable to open
899 // database file'.
900 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
901}
Victor Costan8a87f7e52017-11-10 01:29:30902#endif // defined(OS_ANDROID)
[email protected]8d2e39e2013-06-24 05:55:08903
904TEST_F(SQLConnectionTest, Delete) {
905 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
906 db().Close();
907
908 // Should have both a main database file and a journal file because
shess2c21ecf2015-06-02 01:31:09909 // of journal_mode TRUNCATE.
[email protected]8d2e39e2013-06-24 05:55:08910 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
erg102ceb412015-06-20 01:38:13911 ASSERT_TRUE(GetPathExists(db_path()));
912 ASSERT_TRUE(GetPathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08913
914 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13915 EXPECT_FALSE(GetPathExists(db_path()));
916 EXPECT_FALSE(GetPathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08917}
[email protected]7bae5742013-07-10 20:46:16918
Scott Graham47ed2c32017-09-15 02:17:07919// This test manually sets on disk permissions, these don't exist on Fuchsia.
920#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
[email protected]81a2a602013-07-17 19:10:36921// Test that set_restrict_to_user() trims database permissions so that
922// only the owner (and root) can read.
923TEST_F(SQLConnectionTest, UserPermission) {
924 // If the bots all had a restrictive umask setting such that
925 // databases are always created with only the owner able to read
926 // them, then the code could break without breaking the tests.
927 // Temporarily provide a more permissive umask.
928 db().Close();
929 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13930 ASSERT_FALSE(GetPathExists(db_path()));
[email protected]81a2a602013-07-17 19:10:36931 ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH);
932 ASSERT_TRUE(db().Open(db_path()));
933
934 // Cause the journal file to be created. If the default
935 // journal_mode is changed back to DELETE, then parts of this test
936 // will need to be updated.
937 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
938
939 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
940 int mode;
941
942 // Given a permissive umask, the database is created with permissive
943 // read access for the database and journal.
erg102ceb412015-06-20 01:38:13944 ASSERT_TRUE(GetPathExists(db_path()));
945 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08946 mode = base::FILE_PERMISSION_MASK;
947 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
948 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
949 mode = base::FILE_PERMISSION_MASK;
950 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
951 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36952
953 // Re-open with restricted permissions and verify that the modes
954 // changed for both the main database and the journal.
955 db().Close();
956 db().set_restrict_to_user();
957 ASSERT_TRUE(db().Open(db_path()));
erg102ceb412015-06-20 01:38:13958 ASSERT_TRUE(GetPathExists(db_path()));
959 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08960 mode = base::FILE_PERMISSION_MASK;
961 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
962 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
963 mode = base::FILE_PERMISSION_MASK;
964 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
965 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36966
967 // Delete and re-create the database, the restriction should still apply.
968 db().Close();
969 sql::Connection::Delete(db_path());
970 ASSERT_TRUE(db().Open(db_path()));
erg102ceb412015-06-20 01:38:13971 ASSERT_TRUE(GetPathExists(db_path()));
972 ASSERT_FALSE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08973 mode = base::FILE_PERMISSION_MASK;
974 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
975 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36976
977 // Verify that journal creation inherits the restriction.
978 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
erg102ceb412015-06-20 01:38:13979 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08980 mode = base::FILE_PERMISSION_MASK;
981 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
982 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36983}
Scott Graham47ed2c32017-09-15 02:17:07984#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA)
[email protected]81a2a602013-07-17 19:10:36985
[email protected]8d409412013-07-19 18:25:30986// Test that errors start happening once Poison() is called.
987TEST_F(SQLConnectionTest, Poison) {
988 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
989
990 // Before the Poison() call, things generally work.
991 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
992 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
993 {
994 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
995 ASSERT_TRUE(s.is_valid());
996 ASSERT_TRUE(s.Step());
997 }
998
999 // Get a statement which is valid before and will exist across Poison().
1000 sql::Statement valid_statement(
1001 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master"));
1002 ASSERT_TRUE(valid_statement.is_valid());
1003 ASSERT_TRUE(valid_statement.Step());
1004 valid_statement.Reset(true);
1005
1006 db().Poison();
1007
1008 // After the Poison() call, things fail.
1009 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
1010 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')"));
1011 {
1012 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
1013 ASSERT_FALSE(s.is_valid());
1014 ASSERT_FALSE(s.Step());
1015 }
1016
1017 // The existing statement has become invalid.
1018 ASSERT_FALSE(valid_statement.is_valid());
1019 ASSERT_FALSE(valid_statement.Step());
shess644fc8a2016-02-26 18:15:581020
1021 // Test that poisoning the database during a transaction works (with errors).
1022 // RazeErrorCallback() poisons the database, the extra COMMIT causes
1023 // CommitTransaction() to throw an error while commiting.
shess1cf87f22016-10-25 22:18:291024 db().set_error_callback(base::Bind(&RazeErrorCallback,
1025 &db(),
shess644fc8a2016-02-26 18:15:581026 SQLITE_ERROR));
1027 db().Close();
1028 ASSERT_TRUE(db().Open(db_path()));
1029 EXPECT_TRUE(db().BeginTransaction());
1030 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
1031 EXPECT_TRUE(db().Execute("COMMIT"));
1032 EXPECT_FALSE(db().CommitTransaction());
[email protected]8d409412013-07-19 18:25:301033}
1034
Victor Costan8a87f7e52017-11-10 01:29:301035TEST_F(SQLConnectionTest, AttachDatabase) {
[email protected]8d409412013-07-19 18:25:301036 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
1037
1038 // Create a database to attach to.
1039 base::FilePath attach_path =
1040 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
1041 const char kAttachmentPoint[] = "other";
1042 {
1043 sql::Connection other_db;
1044 ASSERT_TRUE(other_db.Open(attach_path));
1045 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
1046 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
1047 }
1048
1049 // Cannot see the attached database, yet.
1050 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1051
[email protected]8d409412013-07-19 18:25:301052 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
1053 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
1054
Victor Costan8a87f7e52017-11-10 01:29:301055 // Queries can touch both databases after the ATTACH.
[email protected]8d409412013-07-19 18:25:301056 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
1057 {
1058 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
1059 ASSERT_TRUE(s.Step());
1060 EXPECT_EQ(1, s.ColumnInt(0));
1061 }
1062
Victor Costan8a87f7e52017-11-10 01:29:301063 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
1064 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1065}
1066
1067TEST_F(SQLConnectionTest, AttachDatabaseWithOpenTransaction) {
1068 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
1069
1070 // Create a database to attach to.
1071 base::FilePath attach_path =
1072 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
1073 const char kAttachmentPoint[] = "other";
1074 {
1075 sql::Connection other_db;
1076 ASSERT_TRUE(other_db.Open(attach_path));
1077 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
1078 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
1079 }
1080
1081 // Cannot see the attached database, yet.
1082 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1083
1084#if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
1085 // SQLite before 3.21 does not support ATTACH and DETACH in transactions.
1086
1087 // Attach fails in a transaction.
[email protected]8d409412013-07-19 18:25:301088 EXPECT_TRUE(db().BeginTransaction());
1089 {
shess976814402016-06-21 06:56:251090 sql::test::ScopedErrorExpecter expecter;
1091 expecter.ExpectError(SQLITE_ERROR);
Victor Costan8a87f7e52017-11-10 01:29:301092 EXPECT_FALSE(db().AttachDatabase(attach_path, kAttachmentPoint));
1093 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1094 ASSERT_TRUE(expecter.SawExpectedErrors());
1095 }
1096
1097 // Detach also fails in a transaction.
1098 {
1099 sql::test::ScopedErrorExpecter expecter;
1100 expecter.ExpectError(SQLITE_ERROR);
1101 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint));
1102 ASSERT_TRUE(expecter.SawExpectedErrors());
1103 }
1104
1105 db().RollbackTransaction();
1106#else // defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
1107 // Chrome's SQLite (3.21+) supports ATTACH and DETACH in transactions.
1108
1109 // Attach succeeds in a transaction.
1110 EXPECT_TRUE(db().BeginTransaction());
1111 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
1112 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
1113
1114 // Queries can touch both databases after the ATTACH.
1115 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
1116 {
1117 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
1118 ASSERT_TRUE(s.Step());
1119 EXPECT_EQ(1, s.ColumnInt(0));
1120 }
1121
1122 // Detaching the same database fails, database is locked in the transaction.
1123 {
1124 sql::test::ScopedErrorExpecter expecter;
1125 expecter.ExpectError(SQLITE_ERROR);
[email protected]8d409412013-07-19 18:25:301126 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint));
1127 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
shess976814402016-06-21 06:56:251128 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]8d409412013-07-19 18:25:301129 }
1130
Victor Costan8a87f7e52017-11-10 01:29:301131 // Detach succeeds when the transaction is closed.
[email protected]8d409412013-07-19 18:25:301132 db().RollbackTransaction();
1133 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
[email protected]8d409412013-07-19 18:25:301134 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
Victor Costan8a87f7e52017-11-10 01:29:301135#endif // defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
[email protected]8d409412013-07-19 18:25:301136}
1137
[email protected]579446c2013-12-16 18:36:521138TEST_F(SQLConnectionTest, Basic_QuickIntegrityCheck) {
1139 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1140 ASSERT_TRUE(db().Execute(kCreateSql));
1141 EXPECT_TRUE(db().QuickIntegrityCheck());
1142 db().Close();
1143
erg102ceb412015-06-20 01:38:131144 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]579446c2013-12-16 18:36:521145
1146 {
shess976814402016-06-21 06:56:251147 sql::test::ScopedErrorExpecter expecter;
1148 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]579446c2013-12-16 18:36:521149 ASSERT_TRUE(db().Open(db_path()));
1150 EXPECT_FALSE(db().QuickIntegrityCheck());
shess976814402016-06-21 06:56:251151 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]579446c2013-12-16 18:36:521152 }
1153}
1154
1155TEST_F(SQLConnectionTest, Basic_FullIntegrityCheck) {
1156 const std::string kOk("ok");
1157 std::vector<std::string> messages;
1158
1159 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1160 ASSERT_TRUE(db().Execute(kCreateSql));
1161 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
1162 EXPECT_EQ(1u, messages.size());
1163 EXPECT_EQ(kOk, messages[0]);
1164 db().Close();
1165
erg102ceb412015-06-20 01:38:131166 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]579446c2013-12-16 18:36:521167
1168 {
shess976814402016-06-21 06:56:251169 sql::test::ScopedErrorExpecter expecter;
1170 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]579446c2013-12-16 18:36:521171 ASSERT_TRUE(db().Open(db_path()));
1172 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
1173 EXPECT_LT(1u, messages.size());
1174 EXPECT_NE(kOk, messages[0]);
shess976814402016-06-21 06:56:251175 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]579446c2013-12-16 18:36:521176 }
1177
1178 // TODO(shess): CorruptTableOrIndex could be used to produce a
1179 // file that would pass the quick check and fail the full check.
1180}
1181
shess58b8df82015-06-03 00:19:321182// Test Sqlite.Stats histogram for execute-oriented calls.
1183TEST_F(SQLConnectionTest, EventsExecute) {
1184 // Re-open with histogram tag.
1185 db().Close();
1186 db().set_histogram_tag("Test");
1187 ASSERT_TRUE(db().Open(db_path()));
1188
1189 // Open() uses Execute() extensively, don't track those calls.
1190 base::HistogramTester tester;
1191
1192 const char kHistogramName[] = "Sqlite.Stats.Test";
1193 const char kGlobalHistogramName[] = "Sqlite.Stats";
1194
1195 ASSERT_TRUE(db().BeginTransaction());
1196 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1197 EXPECT_TRUE(db().Execute(kCreateSql));
1198 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1199 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1200 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1201 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (13, 'text')"));
1202 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (14, 'text')"));
1203 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (15, 'text');"
1204 "INSERT INTO foo VALUES (16, 'text');"
1205 "INSERT INTO foo VALUES (17, 'text');"
1206 "INSERT INTO foo VALUES (18, 'text');"
1207 "INSERT INTO foo VALUES (19, 'text')"));
1208 ASSERT_TRUE(db().CommitTransaction());
1209 ASSERT_TRUE(db().BeginTransaction());
1210 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1211 db().RollbackTransaction();
1212 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1213 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (21, 'text')"));
1214
1215 // The create, 5 inserts, multi-statement insert, rolled-back insert, 2
1216 // inserts outside transaction.
1217 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_EXECUTE, 10);
1218 tester.ExpectBucketCount(kGlobalHistogramName,
1219 sql::Connection::EVENT_EXECUTE, 10);
1220
1221 // All of the executes, with the multi-statement inserts broken out, plus one
1222 // for each begin, commit, and rollback.
1223 tester.ExpectBucketCount(kHistogramName,
1224 sql::Connection::EVENT_STATEMENT_RUN, 18);
1225 tester.ExpectBucketCount(kGlobalHistogramName,
1226 sql::Connection::EVENT_STATEMENT_RUN, 18);
1227
1228 tester.ExpectBucketCount(kHistogramName,
1229 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1230 tester.ExpectBucketCount(kGlobalHistogramName,
1231 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1232 tester.ExpectBucketCount(kHistogramName,
1233 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1234 tester.ExpectBucketCount(kGlobalHistogramName,
1235 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1236
1237 // The 2 inserts outside the transaction.
1238 tester.ExpectBucketCount(kHistogramName,
1239 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1240 tester.ExpectBucketCount(kGlobalHistogramName,
1241 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1242
1243 // 11 inserts inside transactions.
1244 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_CHANGES, 11);
1245 tester.ExpectBucketCount(kGlobalHistogramName,
1246 sql::Connection::EVENT_CHANGES, 11);
1247
1248 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_BEGIN, 2);
1249 tester.ExpectBucketCount(kGlobalHistogramName,
1250 sql::Connection::EVENT_BEGIN, 2);
1251 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_COMMIT, 1);
1252 tester.ExpectBucketCount(kGlobalHistogramName,
1253 sql::Connection::EVENT_COMMIT, 1);
1254 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_ROLLBACK, 1);
1255 tester.ExpectBucketCount(kGlobalHistogramName,
1256 sql::Connection::EVENT_ROLLBACK, 1);
1257}
1258
1259// Test Sqlite.Stats histogram for prepared statements.
1260TEST_F(SQLConnectionTest, EventsStatement) {
1261 // Re-open with histogram tag.
1262 db().Close();
1263 db().set_histogram_tag("Test");
1264 ASSERT_TRUE(db().Open(db_path()));
1265
1266 const char kHistogramName[] = "Sqlite.Stats.Test";
1267 const char kGlobalHistogramName[] = "Sqlite.Stats";
1268
1269 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1270 EXPECT_TRUE(db().Execute(kCreateSql));
1271 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1272 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1273 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1274
1275 {
1276 base::HistogramTester tester;
1277
1278 {
1279 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo"));
1280 while (s.Step()) {
1281 }
1282 }
1283
1284 tester.ExpectBucketCount(kHistogramName,
1285 sql::Connection::EVENT_STATEMENT_RUN, 1);
1286 tester.ExpectBucketCount(kGlobalHistogramName,
1287 sql::Connection::EVENT_STATEMENT_RUN, 1);
1288 tester.ExpectBucketCount(kHistogramName,
1289 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1290 tester.ExpectBucketCount(kGlobalHistogramName,
1291 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1292 tester.ExpectBucketCount(kHistogramName,
1293 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1294 tester.ExpectBucketCount(kGlobalHistogramName,
1295 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1296 }
1297
1298 {
1299 base::HistogramTester tester;
1300
1301 {
1302 sql::Statement s(db().GetUniqueStatement(
1303 "SELECT value FROM foo WHERE id > 10"));
1304 while (s.Step()) {
1305 }
1306 }
1307
1308 tester.ExpectBucketCount(kHistogramName,
1309 sql::Connection::EVENT_STATEMENT_RUN, 1);
1310 tester.ExpectBucketCount(kGlobalHistogramName,
1311 sql::Connection::EVENT_STATEMENT_RUN, 1);
1312 tester.ExpectBucketCount(kHistogramName,
1313 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1314 tester.ExpectBucketCount(kGlobalHistogramName,
1315 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1316 tester.ExpectBucketCount(kHistogramName,
1317 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1318 tester.ExpectBucketCount(kGlobalHistogramName,
1319 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1320 }
1321}
1322
shess58b8df82015-06-03 00:19:321323// Read-only query allocates time to QueryTime, but not others.
1324TEST_F(SQLConnectionTest, TimeQuery) {
1325 // Re-open with histogram tag. Use an in-memory database to minimize variance
1326 // due to filesystem.
1327 db().Close();
1328 db().set_histogram_tag("Test");
1329 ASSERT_TRUE(db().OpenInMemory());
1330
1331 sql::test::ScopedMockTimeSource time_mock(db());
1332
1333 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1334 EXPECT_TRUE(db().Execute(kCreateSql));
1335
1336 // Function to inject pauses into statements.
1337 sql::test::ScopedScalarFunction scoper(
1338 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1339
1340 base::HistogramTester tester;
1341
1342 EXPECT_TRUE(db().Execute("SELECT milliadjust(10)"));
1343
mostynbd82cd9952016-04-11 20:05:341344 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321345 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1346 ASSERT_TRUE(samples);
1347 // 10 for the adjust, 1 for the measurement.
1348 EXPECT_EQ(11, samples->sum());
1349
1350 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
vabrae960432015-08-03 08:12:541351 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321352
1353 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
vabrae960432015-08-03 08:12:541354 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321355
1356 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
vabrae960432015-08-03 08:12:541357 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321358}
1359
1360// Autocommit update allocates time to QueryTime, UpdateTime, and
1361// AutoCommitTime.
1362TEST_F(SQLConnectionTest, TimeUpdateAutocommit) {
1363 // Re-open with histogram tag. Use an in-memory database to minimize variance
1364 // due to filesystem.
1365 db().Close();
1366 db().set_histogram_tag("Test");
1367 ASSERT_TRUE(db().OpenInMemory());
1368
1369 sql::test::ScopedMockTimeSource time_mock(db());
1370
1371 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1372 EXPECT_TRUE(db().Execute(kCreateSql));
1373
1374 // Function to inject pauses into statements.
1375 sql::test::ScopedScalarFunction scoper(
1376 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1377
1378 base::HistogramTester tester;
1379
1380 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, milliadjust(10))"));
1381
mostynbd82cd9952016-04-11 20:05:341382 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321383 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1384 ASSERT_TRUE(samples);
1385 // 10 for the adjust, 1 for the measurement.
1386 EXPECT_EQ(11, samples->sum());
1387
1388 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1389 ASSERT_TRUE(samples);
1390 // 10 for the adjust, 1 for the measurement.
1391 EXPECT_EQ(11, samples->sum());
1392
1393 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
vabrae960432015-08-03 08:12:541394 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321395
1396 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1397 ASSERT_TRUE(samples);
1398 // 10 for the adjust, 1 for the measurement.
1399 EXPECT_EQ(11, samples->sum());
1400}
1401
1402// Update with explicit transaction allocates time to QueryTime, UpdateTime, and
1403// CommitTime.
1404TEST_F(SQLConnectionTest, TimeUpdateTransaction) {
1405 // Re-open with histogram tag. Use an in-memory database to minimize variance
1406 // due to filesystem.
1407 db().Close();
1408 db().set_histogram_tag("Test");
1409 ASSERT_TRUE(db().OpenInMemory());
1410
1411 sql::test::ScopedMockTimeSource time_mock(db());
1412
1413 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1414 EXPECT_TRUE(db().Execute(kCreateSql));
1415
1416 // Function to inject pauses into statements.
1417 sql::test::ScopedScalarFunction scoper(
1418 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1419
1420 base::HistogramTester tester;
1421
1422 {
1423 // Make the commit slow.
1424 sql::test::ScopedCommitHook scoped_hook(
1425 db(), base::Bind(adjust_commit_hook, &time_mock, 100));
1426 ASSERT_TRUE(db().BeginTransaction());
1427 EXPECT_TRUE(db().Execute(
1428 "INSERT INTO foo VALUES (11, milliadjust(10))"));
1429 EXPECT_TRUE(db().Execute(
1430 "UPDATE foo SET value = milliadjust(10) WHERE id = 11"));
1431 EXPECT_TRUE(db().CommitTransaction());
1432 }
1433
mostynbd82cd9952016-04-11 20:05:341434 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321435 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1436 ASSERT_TRUE(samples);
1437 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1438 // measuring each of BEGIN, INSERT, UPDATE, and COMMIT.
1439 EXPECT_EQ(124, samples->sum());
1440
1441 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1442 ASSERT_TRUE(samples);
1443 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1444 // measuring each of INSERT, UPDATE, and COMMIT.
1445 EXPECT_EQ(123, samples->sum());
1446
1447 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1448 ASSERT_TRUE(samples);
1449 // 100 for commit adjust, 1 for measuring COMMIT.
1450 EXPECT_EQ(101, samples->sum());
1451
1452 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
vabrae960432015-08-03 08:12:541453 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321454}
1455
ssid9f8022f2015-10-12 17:49:031456TEST_F(SQLConnectionTest, OnMemoryDump) {
ssid9f8022f2015-10-12 17:49:031457 base::trace_event::MemoryDumpArgs args = {
1458 base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
ssid448e5ed2016-06-04 12:40:511459 base::trace_event::ProcessMemoryDump pmd(nullptr, args);
ssid3be5b1ec2016-01-13 14:21:571460 ASSERT_TRUE(db().memory_dump_provider_->OnMemoryDump(args, &pmd));
ssid9f8022f2015-10-12 17:49:031461 EXPECT_GE(pmd.allocator_dumps().size(), 1u);
1462}
1463
shessc8cd2a162015-10-22 20:30:461464// Test that the functions to collect diagnostic data run to completion, without
1465// worrying too much about what they generate (since that will change).
1466TEST_F(SQLConnectionTest, CollectDiagnosticInfo) {
shessc8cd2a162015-10-22 20:30:461467 const std::string corruption_info = db().CollectCorruptionInfo();
1468 EXPECT_NE(std::string::npos, corruption_info.find("SQLITE_CORRUPT"));
1469 EXPECT_NE(std::string::npos, corruption_info.find("integrity_check"));
shessc8cd2a162015-10-22 20:30:461470
1471 // A statement to see in the results.
1472 const char* kSimpleSql = "SELECT 'mountain'";
1473 Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
1474
1475 // Error includes the statement.
1476 const std::string readonly_info = db().CollectErrorInfo(SQLITE_READONLY, &s);
1477 EXPECT_NE(std::string::npos, readonly_info.find(kSimpleSql));
1478
1479 // Some other error doesn't include the statment.
1480 // TODO(shess): This is weak.
1481 const std::string full_info = db().CollectErrorInfo(SQLITE_FULL, NULL);
1482 EXPECT_EQ(std::string::npos, full_info.find(kSimpleSql));
1483
1484 // A table to see in the SQLITE_ERROR results.
1485 EXPECT_TRUE(db().Execute("CREATE TABLE volcano (x)"));
1486
1487 // Version info to see in the SQLITE_ERROR results.
1488 sql::MetaTable meta_table;
1489 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
1490
1491 const std::string error_info = db().CollectErrorInfo(SQLITE_ERROR, &s);
1492 EXPECT_NE(std::string::npos, error_info.find(kSimpleSql));
1493 EXPECT_NE(std::string::npos, error_info.find("volcano"));
1494 EXPECT_NE(std::string::npos, error_info.find("version: 4"));
1495}
1496
shessc8cd2a162015-10-22 20:30:461497TEST_F(SQLConnectionTest, RegisterIntentToUpload) {
1498 base::FilePath breadcrumb_path(
1499 db_path().DirName().Append(FILE_PATH_LITERAL("sqlite-diag")));
1500
1501 // No stale diagnostic store.
1502 ASSERT_TRUE(!base::PathExists(breadcrumb_path));
1503
1504 // The histogram tag is required to enable diagnostic features.
1505 EXPECT_FALSE(db().RegisterIntentToUpload());
1506 EXPECT_TRUE(!base::PathExists(breadcrumb_path));
1507
1508 db().Close();
1509 db().set_histogram_tag("Test");
1510 ASSERT_TRUE(db().Open(db_path()));
1511
1512 // Should signal upload only once.
1513 EXPECT_TRUE(db().RegisterIntentToUpload());
1514 EXPECT_TRUE(base::PathExists(breadcrumb_path));
1515 EXPECT_FALSE(db().RegisterIntentToUpload());
1516
1517 // Changing the histogram tag should allow new upload to succeed.
1518 db().Close();
1519 db().set_histogram_tag("NewTest");
1520 ASSERT_TRUE(db().Open(db_path()));
1521 EXPECT_TRUE(db().RegisterIntentToUpload());
1522 EXPECT_FALSE(db().RegisterIntentToUpload());
1523
1524 // Old tag is still prevented.
1525 db().Close();
1526 db().set_histogram_tag("Test");
1527 ASSERT_TRUE(db().Open(db_path()));
1528 EXPECT_FALSE(db().RegisterIntentToUpload());
1529}
shessc8cd2a162015-10-22 20:30:461530
shess9bf2c672015-12-18 01:18:081531// Test that a fresh database has mmap enabled by default, if mmap'ed I/O is
1532// enabled by SQLite.
1533TEST_F(SQLConnectionTest, MmapInitiallyEnabled) {
1534 {
1535 sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size"));
1536
1537 // SQLite doesn't have mmap support (perhaps an early iOS release).
1538 if (!s.Step())
1539 return;
1540
1541 // If mmap I/O is not on, attempt to turn it on. If that succeeds, then
1542 // Open() should have turned it on. If mmap support is disabled, 0 is
1543 // returned. If the VFS does not understand SQLITE_FCNTL_MMAP_SIZE (for
1544 // instance MojoVFS), -1 is returned.
1545 if (s.ColumnInt(0) <= 0) {
1546 ASSERT_TRUE(db().Execute("PRAGMA mmap_size = 1048576"));
1547 s.Reset(true);
1548 ASSERT_TRUE(s.Step());
1549 EXPECT_LE(s.ColumnInt(0), 0);
1550 }
1551 }
1552
1553 // Test that explicit disable prevents mmap'ed I/O.
1554 db().Close();
1555 sql::Connection::Delete(db_path());
1556 db().set_mmap_disabled();
1557 ASSERT_TRUE(db().Open(db_path()));
shessa62504d2016-11-07 19:26:121558 EXPECT_EQ("0", ExecuteWithResult(&db(), "PRAGMA mmap_size"));
1559}
1560
1561// Test whether a fresh database gets mmap enabled when using alternate status
1562// storage.
1563TEST_F(SQLConnectionTest, MmapInitiallyEnabledAltStatus) {
1564 // Re-open fresh database with alt-status flag set.
1565 db().Close();
1566 sql::Connection::Delete(db_path());
1567 db().set_mmap_alt_status();
1568 ASSERT_TRUE(db().Open(db_path()));
1569
shess9bf2c672015-12-18 01:18:081570 {
1571 sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size"));
shessa62504d2016-11-07 19:26:121572
1573 // SQLite doesn't have mmap support (perhaps an early iOS release).
1574 if (!s.Step())
1575 return;
1576
1577 // If mmap I/O is not on, attempt to turn it on. If that succeeds, then
1578 // Open() should have turned it on. If mmap support is disabled, 0 is
1579 // returned. If the VFS does not understand SQLITE_FCNTL_MMAP_SIZE (for
1580 // instance MojoVFS), -1 is returned.
1581 if (s.ColumnInt(0) <= 0) {
1582 ASSERT_TRUE(db().Execute("PRAGMA mmap_size = 1048576"));
1583 s.Reset(true);
1584 ASSERT_TRUE(s.Step());
1585 EXPECT_LE(s.ColumnInt(0), 0);
1586 }
shess9bf2c672015-12-18 01:18:081587 }
shessa62504d2016-11-07 19:26:121588
1589 // Test that explicit disable overrides set_mmap_alt_status().
1590 db().Close();
1591 sql::Connection::Delete(db_path());
1592 db().set_mmap_disabled();
1593 ASSERT_TRUE(db().Open(db_path()));
1594 EXPECT_EQ("0", ExecuteWithResult(&db(), "PRAGMA mmap_size"));
shess9bf2c672015-12-18 01:18:081595}
1596
shess9bf2c672015-12-18 01:18:081597TEST_F(SQLConnectionTest, GetAppropriateMmapSize) {
rohitrao83d6b83a2016-06-21 07:25:571598#if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
1599 // Mmap is not supported on iOS9.
1600 if (!base::ios::IsRunningOnIOS10OrLater()) {
1601 ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
1602 return;
1603 }
Victor Costan8a87f7e52017-11-10 01:29:301604#endif // defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
rohitrao83d6b83a2016-06-21 07:25:571605
shess9bf2c672015-12-18 01:18:081606 const size_t kMmapAlot = 25 * 1024 * 1024;
shess9e77283d2016-06-13 23:53:201607 int64_t mmap_status = MetaTable::kMmapFailure;
shess9bf2c672015-12-18 01:18:081608
1609 // If there is no meta table (as for a fresh database), assume that everything
shess9e77283d2016-06-13 23:53:201610 // should be mapped, and the status of the meta table is not affected.
shess9bf2c672015-12-18 01:18:081611 ASSERT_TRUE(!db().DoesTableExist("meta"));
1612 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
shess9e77283d2016-06-13 23:53:201613 ASSERT_TRUE(!db().DoesTableExist("meta"));
shess9bf2c672015-12-18 01:18:081614
1615 // When the meta table is first created, it sets up to map everything.
1616 MetaTable().Init(&db(), 1, 1);
1617 ASSERT_TRUE(db().DoesTableExist("meta"));
1618 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1619 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1620 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1621
shessa7b07acd2017-03-19 23:59:381622 // Preload with partial progress of one page. Should map everything.
1623 ASSERT_TRUE(db().Execute("REPLACE INTO meta VALUES ('mmap_status', 1)"));
1624 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1625 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1626 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1627
shess9bf2c672015-12-18 01:18:081628 // Failure status maps nothing.
1629 ASSERT_TRUE(db().Execute("REPLACE INTO meta VALUES ('mmap_status', -2)"));
1630 ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
1631
1632 // Re-initializing the meta table does not re-create the key if the table
1633 // already exists.
1634 ASSERT_TRUE(db().Execute("DELETE FROM meta WHERE key = 'mmap_status'"));
1635 MetaTable().Init(&db(), 1, 1);
1636 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1637 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1638 ASSERT_EQ(0, mmap_status);
1639
1640 // With no key, map everything and create the key.
1641 // TODO(shess): This really should be "maps everything after validating it",
1642 // but that is more complicated to structure.
1643 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1644 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1645 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1646}
shess9bf2c672015-12-18 01:18:081647
shessa62504d2016-11-07 19:26:121648TEST_F(SQLConnectionTest, GetAppropriateMmapSizeAltStatus) {
1649#if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
1650 // Mmap is not supported on iOS9. Make sure that test takes precedence.
1651 if (!base::ios::IsRunningOnIOS10OrLater()) {
1652 db().set_mmap_alt_status();
1653 ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
1654 return;
1655 }
Victor Costan8a87f7e52017-11-10 01:29:301656#endif // defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
shessa62504d2016-11-07 19:26:121657
1658 const size_t kMmapAlot = 25 * 1024 * 1024;
1659
1660 // At this point, Connection still expects a future [meta] table.
1661 ASSERT_FALSE(db().DoesTableExist("meta"));
1662 ASSERT_FALSE(db().DoesViewExist("MmapStatus"));
1663 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1664 ASSERT_FALSE(db().DoesTableExist("meta"));
1665 ASSERT_FALSE(db().DoesViewExist("MmapStatus"));
1666
1667 // Using alt status, everything should be mapped, with state in the view.
1668 db().set_mmap_alt_status();
1669 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1670 ASSERT_FALSE(db().DoesTableExist("meta"));
1671 ASSERT_TRUE(db().DoesViewExist("MmapStatus"));
1672 EXPECT_EQ(base::IntToString(MetaTable::kMmapSuccess),
1673 ExecuteWithResult(&db(), "SELECT * FROM MmapStatus"));
1674
shessa7b07acd2017-03-19 23:59:381675 // Also maps everything when kMmapSuccess is already in the view.
shessa62504d2016-11-07 19:26:121676 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1677
shessa7b07acd2017-03-19 23:59:381678 // Preload with partial progress of one page. Should map everything.
1679 ASSERT_TRUE(db().Execute("DROP VIEW MmapStatus"));
1680 ASSERT_TRUE(db().Execute("CREATE VIEW MmapStatus (value) AS SELECT 1"));
1681 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1682 EXPECT_EQ(base::IntToString(MetaTable::kMmapSuccess),
1683 ExecuteWithResult(&db(), "SELECT * FROM MmapStatus"));
1684
shessa62504d2016-11-07 19:26:121685 // Failure status leads to nothing being mapped.
1686 ASSERT_TRUE(db().Execute("DROP VIEW MmapStatus"));
shessa7b07acd2017-03-19 23:59:381687 ASSERT_TRUE(db().Execute("CREATE VIEW MmapStatus (value) AS SELECT -2"));
shessa62504d2016-11-07 19:26:121688 ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
1689 EXPECT_EQ(base::IntToString(MetaTable::kMmapFailure),
1690 ExecuteWithResult(&db(), "SELECT * FROM MmapStatus"));
1691}
1692
shess9e77283d2016-06-13 23:53:201693// To prevent invalid SQL from accidentally shipping to production, prepared
Sigurdur Asgeirsson8d82bd02017-09-25 21:05:521694// statements which fail to compile with SQLITE_ERROR call DLOG(DCHECK). This
shess9e77283d2016-06-13 23:53:201695// case cannot be suppressed with an error callback.
1696TEST_F(SQLConnectionTest, CompileError) {
Scott Graham57ee54822017-09-13 06:37:561697 // DEATH tests not supported on Android, iOS, or Fuchsia.
1698#if !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA)
shess9e77283d2016-06-13 23:53:201699 if (DLOG_IS_ON(FATAL)) {
1700 db().set_error_callback(base::Bind(&IgnoreErrorCallback));
1701 ASSERT_DEATH({
1702 db().GetUniqueStatement("SELECT x");
1703 }, "SQL compile error no such column: x");
1704 }
Victor Costan8a87f7e52017-11-10 01:29:301705#endif // !defined(OS_ANDROID) && !defined(OS_IOS) && !defined(OS_FUCHSIA)
shess9e77283d2016-06-13 23:53:201706}
1707
shessc8cd2a162015-10-22 20:30:461708} // namespace sql