blob: a65d5d453fc0a9aeb8e0ae07c0350bac14f5b3f2 [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"
shess58b8df82015-06-03 00:19:3214#include "base/test/histogram_tester.h"
ssid9f8022f2015-10-12 17:49:0315#include "base/trace_event/process_memory_dump.h"
[email protected]f0a54b22011-07-19 18:40:2116#include "sql/connection.h"
ssid3be5b1ec2016-01-13 14:21:5717#include "sql/connection_memory_dump_provider.h"
erg102ceb412015-06-20 01:38:1318#include "sql/correct_sql_test_base.h"
[email protected]1348765a2012-07-24 08:25:5319#include "sql/meta_table.h"
[email protected]ea1a3f62012-11-16 20:34:2320#include "sql/statement.h"
[email protected]98cf3002013-07-12 01:38:5621#include "sql/test/error_callback_support.h"
shess976814402016-06-21 06:56:2522#include "sql/test/scoped_error_expecter.h"
[email protected]a8848a72013-11-18 04:18:4723#include "sql/test/test_helpers.h"
[email protected]e5ffd0e42009-09-11 21:30:5624#include "testing/gtest/include/gtest/gtest.h"
[email protected]e33cba42010-08-18 23:37:0325#include "third_party/sqlite/sqlite3.h"
[email protected]e5ffd0e42009-09-11 21:30:5626
rohitrao83d6b83a2016-06-21 07:25:5727#if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
28#include "base/ios/ios_util.h"
29#endif
30
shess58b8df82015-06-03 00:19:3231namespace sql {
32namespace test {
33
34// Replaces the database time source with an object that steps forward 1ms on
35// each check, and which can be jumped forward an arbitrary amount of time
36// programmatically.
37class ScopedMockTimeSource {
38 public:
39 ScopedMockTimeSource(Connection& db)
40 : db_(db),
41 delta_(base::TimeDelta::FromMilliseconds(1)) {
42 // Save the current source and replace it.
43 save_.swap(db_.clock_);
44 db_.clock_.reset(new MockTimeSource(*this));
45 }
46 ~ScopedMockTimeSource() {
47 // Put original source back.
48 db_.clock_.swap(save_);
49 }
50
51 void adjust(const base::TimeDelta& delta) {
52 current_time_ += delta;
53 }
54
55 private:
56 class MockTimeSource : public TimeSource {
57 public:
58 MockTimeSource(ScopedMockTimeSource& owner)
59 : owner_(owner) {
60 }
61 ~MockTimeSource() override {}
62
63 base::TimeTicks Now() override {
64 base::TimeTicks ret(owner_.current_time_);
65 owner_.current_time_ += owner_.delta_;
66 return ret;
67 }
68
69 private:
70 ScopedMockTimeSource& owner_;
71 DISALLOW_COPY_AND_ASSIGN(MockTimeSource);
72 };
73
74 Connection& db_;
75
76 // Saves original source from |db_|.
mostynbd82cd9952016-04-11 20:05:3477 std::unique_ptr<TimeSource> save_;
shess58b8df82015-06-03 00:19:3278
79 // Current time returned by mock.
80 base::TimeTicks current_time_;
81
82 // How far to jump on each Now() call.
83 base::TimeDelta delta_;
84
85 DISALLOW_COPY_AND_ASSIGN(ScopedMockTimeSource);
86};
87
88// Allow a test to add a SQLite function in a scoped context.
89class ScopedScalarFunction {
90 public:
91 ScopedScalarFunction(
92 sql::Connection& db,
93 const char* function_name,
94 int args,
95 base::Callback<void(sqlite3_context*,int,sqlite3_value**)> cb)
96 : db_(db.db_), function_name_(function_name), cb_(cb) {
shess6ce9d1f02015-09-02 19:37:4397 sqlite3_create_function_v2(db_, function_name, args, SQLITE_UTF8,
98 this, &Run, NULL, NULL, NULL);
shess58b8df82015-06-03 00:19:3299 }
100 ~ScopedScalarFunction() {
shess6ce9d1f02015-09-02 19:37:43101 sqlite3_create_function_v2(db_, function_name_, 0, SQLITE_UTF8,
102 NULL, NULL, NULL, NULL, NULL);
shess58b8df82015-06-03 00:19:32103 }
104
105 private:
106 static void Run(sqlite3_context* context, int argc, sqlite3_value** argv) {
107 ScopedScalarFunction* t = static_cast<ScopedScalarFunction*>(
108 sqlite3_user_data(context));
109 t->cb_.Run(context, argc, argv);
110 }
111
112 sqlite3* db_;
113 const char* function_name_;
114 base::Callback<void(sqlite3_context*,int,sqlite3_value**)> cb_;
115
116 DISALLOW_COPY_AND_ASSIGN(ScopedScalarFunction);
117};
118
119// Allow a test to add a SQLite commit hook in a scoped context.
120class ScopedCommitHook {
121 public:
122 ScopedCommitHook(sql::Connection& db,
123 base::Callback<int(void)> cb)
124 : db_(db.db_),
125 cb_(cb) {
shess6ce9d1f02015-09-02 19:37:43126 sqlite3_commit_hook(db_, &Run, this);
shess58b8df82015-06-03 00:19:32127 }
128 ~ScopedCommitHook() {
shess6ce9d1f02015-09-02 19:37:43129 sqlite3_commit_hook(db_, NULL, NULL);
shess58b8df82015-06-03 00:19:32130 }
131
132 private:
133 static int Run(void* p) {
134 ScopedCommitHook* t = static_cast<ScopedCommitHook*>(p);
135 return t->cb_.Run();
136 }
137
138 sqlite3* db_;
139 base::Callback<int(void)> cb_;
140
141 DISALLOW_COPY_AND_ASSIGN(ScopedCommitHook);
142};
143
144} // namespace test
shess58b8df82015-06-03 00:19:32145
[email protected]7bae5742013-07-10 20:46:16146namespace {
147
148// Helper to return the count of items in sqlite_master. Return -1 in
149// case of error.
150int SqliteMasterCount(sql::Connection* db) {
151 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master";
152 sql::Statement s(db->GetUniqueStatement(kMasterCount));
153 return s.Step() ? s.ColumnInt(0) : -1;
154}
155
[email protected]98cf3002013-07-12 01:38:56156// Track the number of valid references which share the same pointer.
157// This is used to allow testing an implicitly use-after-free case by
158// explicitly having the ref count live longer than the object.
159class RefCounter {
160 public:
161 RefCounter(size_t* counter)
162 : counter_(counter) {
163 (*counter_)++;
164 }
165 RefCounter(const RefCounter& other)
166 : counter_(other.counter_) {
167 (*counter_)++;
168 }
169 ~RefCounter() {
170 (*counter_)--;
171 }
172
173 private:
174 size_t* counter_;
175
176 DISALLOW_ASSIGN(RefCounter);
177};
178
179// Empty callback for implementation of ErrorCallbackSetHelper().
180void IgnoreErrorCallback(int error, sql::Statement* stmt) {
181}
182
183void ErrorCallbackSetHelper(sql::Connection* db,
184 size_t* counter,
185 const RefCounter& r,
186 int error, sql::Statement* stmt) {
187 // The ref count should not go to zero when changing the callback.
188 EXPECT_GT(*counter, 0u);
189 db->set_error_callback(base::Bind(&IgnoreErrorCallback));
190 EXPECT_GT(*counter, 0u);
191}
192
193void ErrorCallbackResetHelper(sql::Connection* db,
194 size_t* counter,
195 const RefCounter& r,
196 int error, sql::Statement* stmt) {
197 // The ref count should not go to zero when clearing the callback.
198 EXPECT_GT(*counter, 0u);
199 db->reset_error_callback();
200 EXPECT_GT(*counter, 0u);
201}
202
shess1cf87f22016-10-25 22:18:29203// Handle errors by blowing away the database.
204void RazeErrorCallback(sql::Connection* db,
205 int expected_error,
206 int error,
207 sql::Statement* stmt) {
208 // Nothing here needs extended errors at this time.
209 EXPECT_EQ(expected_error, expected_error&0xff);
210 EXPECT_EQ(expected_error, error&0xff);
211 db->RazeAndClose();
212}
213
[email protected]81a2a602013-07-17 19:10:36214#if defined(OS_POSIX)
215// Set a umask and restore the old mask on destruction. Cribbed from
216// shared_memory_unittest.cc. Used by POSIX-only UserPermission test.
217class ScopedUmaskSetter {
218 public:
219 explicit ScopedUmaskSetter(mode_t target_mask) {
220 old_umask_ = umask(target_mask);
221 }
222 ~ScopedUmaskSetter() { umask(old_umask_); }
223 private:
224 mode_t old_umask_;
225 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
226};
227#endif
228
shessc8cd2a162015-10-22 20:30:46229// SQLite function to adjust mock time by |argv[0]| milliseconds.
230void sqlite_adjust_millis(sql::test::ScopedMockTimeSource* time_mock,
231 sqlite3_context* context,
232 int argc, sqlite3_value** argv) {
avi0b519202015-12-21 07:25:19233 int64_t milliseconds = argc > 0 ? sqlite3_value_int64(argv[0]) : 1000;
shessc8cd2a162015-10-22 20:30:46234 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
235 sqlite3_result_int64(context, milliseconds);
236}
237
238// Adjust mock time by |milliseconds| on commit.
239int adjust_commit_hook(sql::test::ScopedMockTimeSource* time_mock,
avi0b519202015-12-21 07:25:19240 int64_t milliseconds) {
shessc8cd2a162015-10-22 20:30:46241 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
242 return SQLITE_OK;
243}
244
245const char kCommitTime[] = "Sqlite.CommitTime.Test";
246const char kAutoCommitTime[] = "Sqlite.AutoCommitTime.Test";
247const char kUpdateTime[] = "Sqlite.UpdateTime.Test";
248const char kQueryTime[] = "Sqlite.QueryTime.Test";
249
250} // namespace
251
shess1cf87f22016-10-25 22:18:29252using SQLConnectionTest = sql::SQLTestBase;
[email protected]e5ffd0e42009-09-11 21:30:56253
254TEST_F(SQLConnectionTest, Execute) {
255 // Valid statement should return true.
256 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
257 EXPECT_EQ(SQLITE_OK, db().GetErrorCode());
258
259 // Invalid statement should fail.
[email protected]eff1fa522011-12-12 23:50:59260 ASSERT_EQ(SQLITE_ERROR,
261 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b"));
[email protected]e5ffd0e42009-09-11 21:30:56262 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode());
263}
264
[email protected]eff1fa522011-12-12 23:50:59265TEST_F(SQLConnectionTest, ExecuteWithErrorCode) {
266 ASSERT_EQ(SQLITE_OK,
267 db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)"));
268 ASSERT_EQ(SQLITE_ERROR,
269 db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE"));
270 ASSERT_EQ(SQLITE_ERROR,
271 db().ExecuteAndReturnErrorCode(
272 "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)"));
273}
274
[email protected]e5ffd0e42009-09-11 21:30:56275TEST_F(SQLConnectionTest, CachedStatement) {
276 sql::StatementID id1("foo", 12);
277
278 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
279 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
280
281 // Create a new cached statement.
282 {
283 sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo"));
[email protected]eff1fa522011-12-12 23:50:59284 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56285
286 ASSERT_TRUE(s.Step());
287 EXPECT_EQ(12, s.ColumnInt(0));
288 }
289
290 // The statement should be cached still.
291 EXPECT_TRUE(db().HasCachedStatement(id1));
292
293 {
294 // Get the same statement using different SQL. This should ignore our
295 // SQL and use the cached one (so it will be valid).
296 sql::Statement s(db().GetCachedStatement(id1, "something invalid("));
[email protected]eff1fa522011-12-12 23:50:59297 ASSERT_TRUE(s.is_valid());
[email protected]e5ffd0e42009-09-11 21:30:56298
299 ASSERT_TRUE(s.Step());
300 EXPECT_EQ(12, s.ColumnInt(0));
301 }
302
303 // Make sure other statements aren't marked as cached.
304 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE));
305}
306
[email protected]eff1fa522011-12-12 23:50:59307TEST_F(SQLConnectionTest, IsSQLValidTest) {
308 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
309 ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo"));
310 ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo"));
311}
312
[email protected]e5ffd0e42009-09-11 21:30:56313TEST_F(SQLConnectionTest, DoesStuffExist) {
314 // Test DoesTableExist.
315 EXPECT_FALSE(db().DoesTableExist("foo"));
316 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
shess92a2ab12015-04-09 01:59:47317 ASSERT_TRUE(db().Execute("CREATE INDEX foo_a ON foo (a)"));
[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"));
[email protected]e5ffd0e42009-09-11 21:30:56320
321 // Test DoesColumnExist.
322 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
323 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
324
[email protected]e7afe2452010-08-22 16:19:13325 // Testing for a column on a nonexistent table.
[email protected]e5ffd0e42009-09-11 21:30:56326 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
shess92a2ab12015-04-09 01:59:47327
328 // Names are not case sensitive.
329 EXPECT_TRUE(db().DoesTableExist("FOO"));
330 EXPECT_TRUE(db().DoesColumnExist("FOO", "A"));
[email protected]e5ffd0e42009-09-11 21:30:56331}
332
333TEST_F(SQLConnectionTest, GetLastInsertRowId) {
334 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
335
336 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
337
338 // Last insert row ID should be valid.
tfarina720d4f32015-05-11 22:31:26339 int64_t row = db().GetLastInsertRowId();
[email protected]e5ffd0e42009-09-11 21:30:56340 EXPECT_LT(0, row);
341
342 // It should be the primary key of the row we just inserted.
343 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
344 s.BindInt64(0, row);
345 ASSERT_TRUE(s.Step());
346 EXPECT_EQ(12, s.ColumnInt(0));
347}
[email protected]44ad7d902012-03-23 00:09:05348
349TEST_F(SQLConnectionTest, Rollback) {
350 ASSERT_TRUE(db().BeginTransaction());
351 ASSERT_TRUE(db().BeginTransaction());
352 EXPECT_EQ(2, db().transaction_nesting());
353 db().RollbackTransaction();
354 EXPECT_FALSE(db().CommitTransaction());
355 EXPECT_TRUE(db().BeginTransaction());
356}
[email protected]8e0c01282012-04-06 19:36:49357
shess976814402016-06-21 06:56:25358// Test the scoped error expecter by attempting to insert a duplicate
[email protected]4350e322013-06-18 22:18:10359// value into an index.
shess976814402016-06-21 06:56:25360TEST_F(SQLConnectionTest, ScopedErrorExpecter) {
[email protected]4350e322013-06-18 22:18:10361 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
362 ASSERT_TRUE(db().Execute(kCreateSql));
363 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
364
shess92a2ab12015-04-09 01:59:47365 {
shess976814402016-06-21 06:56:25366 sql::test::ScopedErrorExpecter expecter;
367 expecter.ExpectError(SQLITE_CONSTRAINT);
shess92a2ab12015-04-09 01:59:47368 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
shess976814402016-06-21 06:56:25369 ASSERT_TRUE(expecter.SawExpectedErrors());
shess92a2ab12015-04-09 01:59:47370 }
371}
372
373// Test that clients of GetUntrackedStatement() can test corruption-handling
shess976814402016-06-21 06:56:25374// with ScopedErrorExpecter.
shess92a2ab12015-04-09 01:59:47375TEST_F(SQLConnectionTest, ScopedIgnoreUntracked) {
376 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
377 ASSERT_TRUE(db().Execute(kCreateSql));
378 ASSERT_FALSE(db().DoesTableExist("bar"));
379 ASSERT_TRUE(db().DoesTableExist("foo"));
380 ASSERT_TRUE(db().DoesColumnExist("foo", "id"));
381 db().Close();
382
383 // Corrupt the database so that nothing works, including PRAGMAs.
erg102ceb412015-06-20 01:38:13384 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
shess92a2ab12015-04-09 01:59:47385
386 {
shess976814402016-06-21 06:56:25387 sql::test::ScopedErrorExpecter expecter;
388 expecter.ExpectError(SQLITE_CORRUPT);
shess92a2ab12015-04-09 01:59:47389 ASSERT_TRUE(db().Open(db_path()));
390 ASSERT_FALSE(db().DoesTableExist("bar"));
391 ASSERT_FALSE(db().DoesTableExist("foo"));
392 ASSERT_FALSE(db().DoesColumnExist("foo", "id"));
shess976814402016-06-21 06:56:25393 ASSERT_TRUE(expecter.SawExpectedErrors());
shess92a2ab12015-04-09 01:59:47394 }
[email protected]4350e322013-06-18 22:18:10395}
396
[email protected]98cf3002013-07-12 01:38:56397TEST_F(SQLConnectionTest, ErrorCallback) {
398 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
399 ASSERT_TRUE(db().Execute(kCreateSql));
400 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
401
402 int error = SQLITE_OK;
403 {
404 sql::ScopedErrorCallback sec(
405 &db(), base::Bind(&sql::CaptureErrorCallback, &error));
[email protected]98cf3002013-07-12 01:38:56406 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
Scott Hessdcf120482015-02-10 21:33:29407
408 // Later versions of SQLite throw SQLITE_CONSTRAINT_UNIQUE. The specific
409 // sub-error isn't really important.
410 EXPECT_EQ(SQLITE_CONSTRAINT, (error&0xff));
[email protected]98cf3002013-07-12 01:38:56411 }
412
413 // Callback is no longer in force due to reset.
414 {
415 error = SQLITE_OK;
shess976814402016-06-21 06:56:25416 sql::test::ScopedErrorExpecter expecter;
417 expecter.ExpectError(SQLITE_CONSTRAINT);
[email protected]98cf3002013-07-12 01:38:56418 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
shess976814402016-06-21 06:56:25419 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]98cf3002013-07-12 01:38:56420 EXPECT_EQ(SQLITE_OK, error);
421 }
422
423 // base::Bind() can curry arguments to be passed by const reference
[email protected]81a2a602013-07-17 19:10:36424 // to the callback function. If the callback function calls
425 // re/set_error_callback(), the storage for those arguments can be
426 // deleted while the callback function is still executing.
[email protected]98cf3002013-07-12 01:38:56427 //
428 // RefCounter() counts how many objects are live using an external
429 // count. The same counter is passed to the callback, so that it
430 // can check directly even if the RefCounter object is no longer
431 // live.
432 {
433 size_t count = 0;
434 sql::ScopedErrorCallback sec(
435 &db(), base::Bind(&ErrorCallbackSetHelper,
436 &db(), &count, RefCounter(&count)));
437
438 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
439 }
440
441 // Same test, but reset_error_callback() case.
442 {
443 size_t count = 0;
444 sql::ScopedErrorCallback sec(
445 &db(), base::Bind(&ErrorCallbackResetHelper,
446 &db(), &count, RefCounter(&count)));
447
448 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
449 }
450}
451
[email protected]8e0c01282012-04-06 19:36:49452// Test that sql::Connection::Raze() results in a database without the
453// tables from the original database.
454TEST_F(SQLConnectionTest, Raze) {
455 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
456 ASSERT_TRUE(db().Execute(kCreateSql));
457 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
458
[email protected]69c58452012-08-06 19:22:42459 int pragma_auto_vacuum = 0;
460 {
461 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
462 ASSERT_TRUE(s.Step());
463 pragma_auto_vacuum = s.ColumnInt(0);
464 ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1);
465 }
466
467 // If auto_vacuum is set, there's an extra page to maintain a freelist.
468 const int kExpectedPageCount = 2 + pragma_auto_vacuum;
469
[email protected]8e0c01282012-04-06 19:36:49470 {
471 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
472 ASSERT_TRUE(s.Step());
[email protected]69c58452012-08-06 19:22:42473 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0));
[email protected]8e0c01282012-04-06 19:36:49474 }
475
476 {
477 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master"));
478 ASSERT_TRUE(s.Step());
479 EXPECT_EQ("table", s.ColumnString(0));
480 EXPECT_EQ("foo", s.ColumnString(1));
481 EXPECT_EQ("foo", s.ColumnString(2));
[email protected]69c58452012-08-06 19:22:42482 // Table "foo" is stored in the last page of the file.
483 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3));
[email protected]8e0c01282012-04-06 19:36:49484 EXPECT_EQ(kCreateSql, s.ColumnString(4));
485 }
486
487 ASSERT_TRUE(db().Raze());
488
489 {
490 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
491 ASSERT_TRUE(s.Step());
492 EXPECT_EQ(1, s.ColumnInt(0));
493 }
494
[email protected]7bae5742013-07-10 20:46:16495 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]69c58452012-08-06 19:22:42496
497 {
498 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
499 ASSERT_TRUE(s.Step());
[email protected]6d42f152012-11-10 00:38:24500 // The new database has the same auto_vacuum as a fresh database.
[email protected]69c58452012-08-06 19:22:42501 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0));
502 }
[email protected]8e0c01282012-04-06 19:36:49503}
504
505// Test that Raze() maintains page_size.
506TEST_F(SQLConnectionTest, RazePageSize) {
[email protected]e73e89222012-07-13 18:55:22507 // Fetch the default page size and double it for use in this test.
[email protected]8e0c01282012-04-06 19:36:49508 // Scoped to release statement before Close().
[email protected]e73e89222012-07-13 18:55:22509 int default_page_size = 0;
[email protected]8e0c01282012-04-06 19:36:49510 {
511 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
512 ASSERT_TRUE(s.Step());
[email protected]e73e89222012-07-13 18:55:22513 default_page_size = s.ColumnInt(0);
[email protected]8e0c01282012-04-06 19:36:49514 }
[email protected]e73e89222012-07-13 18:55:22515 ASSERT_GT(default_page_size, 0);
516 const int kPageSize = 2 * default_page_size;
[email protected]8e0c01282012-04-06 19:36:49517
518 // Re-open the database to allow setting the page size.
519 db().Close();
520 db().set_page_size(kPageSize);
521 ASSERT_TRUE(db().Open(db_path()));
522
523 // page_size should match the indicated value.
524 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
525 ASSERT_TRUE(s.Step());
526 ASSERT_EQ(kPageSize, s.ColumnInt(0));
527
528 // After raze, page_size should still match the indicated value.
529 ASSERT_TRUE(db().Raze());
[email protected]389e0a42012-04-25 21:36:41530 s.Reset(true);
[email protected]8e0c01282012-04-06 19:36:49531 ASSERT_TRUE(s.Step());
532 ASSERT_EQ(kPageSize, s.ColumnInt(0));
533}
534
535// Test that Raze() results are seen in other connections.
536TEST_F(SQLConnectionTest, RazeMultiple) {
537 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
538 ASSERT_TRUE(db().Execute(kCreateSql));
539
540 sql::Connection other_db;
541 ASSERT_TRUE(other_db.Open(db_path()));
542
543 // Check that the second connection sees the table.
[email protected]7bae5742013-07-10 20:46:16544 ASSERT_EQ(1, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49545
546 ASSERT_TRUE(db().Raze());
547
548 // The second connection sees the updated database.
[email protected]7bae5742013-07-10 20:46:16549 ASSERT_EQ(0, SqliteMasterCount(&other_db));
[email protected]8e0c01282012-04-06 19:36:49550}
551
erg102ceb412015-06-20 01:38:13552// TODO(erg): Enable this in the next patch once I add locking.
553#if !defined(MOJO_APPTEST_IMPL)
[email protected]8e0c01282012-04-06 19:36:49554TEST_F(SQLConnectionTest, RazeLocked) {
555 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
556 ASSERT_TRUE(db().Execute(kCreateSql));
557
558 // Open a transaction and write some data in a second connection.
559 // This will acquire a PENDING or EXCLUSIVE transaction, which will
560 // cause the raze to fail.
561 sql::Connection other_db;
562 ASSERT_TRUE(other_db.Open(db_path()));
563 ASSERT_TRUE(other_db.BeginTransaction());
564 const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')";
565 ASSERT_TRUE(other_db.Execute(kInsertSql));
566
567 ASSERT_FALSE(db().Raze());
568
569 // Works after COMMIT.
570 ASSERT_TRUE(other_db.CommitTransaction());
571 ASSERT_TRUE(db().Raze());
572
573 // Re-create the database.
574 ASSERT_TRUE(db().Execute(kCreateSql));
575 ASSERT_TRUE(db().Execute(kInsertSql));
576
577 // An unfinished read transaction in the other connection also
578 // blocks raze.
579 const char *kQuery = "SELECT COUNT(*) FROM foo";
580 sql::Statement s(other_db.GetUniqueStatement(kQuery));
581 ASSERT_TRUE(s.Step());
582 ASSERT_FALSE(db().Raze());
583
584 // Complete the statement unlocks the database.
585 ASSERT_FALSE(s.Step());
586 ASSERT_TRUE(db().Raze());
587}
erg102ceb412015-06-20 01:38:13588#endif
[email protected]8e0c01282012-04-06 19:36:49589
[email protected]7bae5742013-07-10 20:46:16590// Verify that Raze() can handle an empty file. SQLite should treat
591// this as an empty database.
592TEST_F(SQLConnectionTest, RazeEmptyDB) {
593 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
594 ASSERT_TRUE(db().Execute(kCreateSql));
595 db().Close();
596
erg102ceb412015-06-20 01:38:13597 TruncateDatabase();
[email protected]7bae5742013-07-10 20:46:16598
599 ASSERT_TRUE(db().Open(db_path()));
600 ASSERT_TRUE(db().Raze());
601 EXPECT_EQ(0, SqliteMasterCount(&db()));
602}
603
604// Verify that Raze() can handle a file of junk.
605TEST_F(SQLConnectionTest, RazeNOTADB) {
606 db().Close();
607 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13608 ASSERT_FALSE(GetPathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16609
erg102ceb412015-06-20 01:38:13610 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE_AND_TRUNCATE);
611 ASSERT_TRUE(GetPathExists(db_path()));
[email protected]7bae5742013-07-10 20:46:16612
Scott Hessdcf120482015-02-10 21:33:29613 // SQLite will successfully open the handle, but fail when running PRAGMA
614 // statements that access the database.
[email protected]7bae5742013-07-10 20:46:16615 {
shess976814402016-06-21 06:56:25616 sql::test::ScopedErrorExpecter expecter;
Scott Hessdcf120482015-02-10 21:33:29617
618 // Earlier versions of Chromium compiled against SQLite 3.6.7.3, which
619 // returned SQLITE_IOERR_SHORT_READ in this case. Some platforms may still
620 // compile against an earlier SQLite via USE_SYSTEM_SQLITE.
shess976814402016-06-21 06:56:25621 if (expecter.SQLiteLibVersionNumber() < 3008005) {
622 expecter.ExpectError(SQLITE_IOERR_SHORT_READ);
Scott Hessdcf120482015-02-10 21:33:29623 } else {
shess976814402016-06-21 06:56:25624 expecter.ExpectError(SQLITE_NOTADB);
Scott Hessdcf120482015-02-10 21:33:29625 }
626
[email protected]7bae5742013-07-10 20:46:16627 EXPECT_TRUE(db().Open(db_path()));
shess976814402016-06-21 06:56:25628 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]7bae5742013-07-10 20:46:16629 }
630 EXPECT_TRUE(db().Raze());
631 db().Close();
632
633 // Now empty, the open should open an empty database.
634 EXPECT_TRUE(db().Open(db_path()));
635 EXPECT_EQ(0, SqliteMasterCount(&db()));
636}
637
638// Verify that Raze() can handle a database overwritten with garbage.
639TEST_F(SQLConnectionTest, RazeNOTADB2) {
640 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
641 ASSERT_TRUE(db().Execute(kCreateSql));
642 ASSERT_EQ(1, SqliteMasterCount(&db()));
643 db().Close();
644
erg102ceb412015-06-20 01:38:13645 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE);
[email protected]7bae5742013-07-10 20:46:16646
647 // SQLite will successfully open the handle, but will fail with
648 // SQLITE_NOTADB on pragma statemenets which attempt to read the
649 // corrupted header.
650 {
shess976814402016-06-21 06:56:25651 sql::test::ScopedErrorExpecter expecter;
652 expecter.ExpectError(SQLITE_NOTADB);
[email protected]7bae5742013-07-10 20:46:16653 EXPECT_TRUE(db().Open(db_path()));
shess976814402016-06-21 06:56:25654 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]7bae5742013-07-10 20:46:16655 }
656 EXPECT_TRUE(db().Raze());
657 db().Close();
658
659 // Now empty, the open should succeed with an empty database.
660 EXPECT_TRUE(db().Open(db_path()));
661 EXPECT_EQ(0, SqliteMasterCount(&db()));
662}
663
664// Test that a callback from Open() can raze the database. This is
665// essential for cases where the Open() can fail entirely, so the
[email protected]fed734a2013-07-17 04:45:13666// Raze() cannot happen later. Additionally test that when the
667// callback does this during Open(), the open is retried and succeeds.
[email protected]fed734a2013-07-17 04:45:13668TEST_F(SQLConnectionTest, RazeCallbackReopen) {
[email protected]7bae5742013-07-10 20:46:16669 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
670 ASSERT_TRUE(db().Execute(kCreateSql));
671 ASSERT_EQ(1, SqliteMasterCount(&db()));
[email protected]7bae5742013-07-10 20:46:16672 db().Close();
673
[email protected]a8848a72013-11-18 04:18:47674 // Corrupt the database so that nothing works, including PRAGMAs.
erg102ceb412015-06-20 01:38:13675 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]7bae5742013-07-10 20:46:16676
[email protected]fed734a2013-07-17 04:45:13677 // Open() will succeed, even though the PRAGMA calls within will
678 // fail with SQLITE_CORRUPT, as will this PRAGMA.
679 {
shess976814402016-06-21 06:56:25680 sql::test::ScopedErrorExpecter expecter;
681 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]fed734a2013-07-17 04:45:13682 ASSERT_TRUE(db().Open(db_path()));
683 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum"));
684 db().Close();
shess976814402016-06-21 06:56:25685 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]fed734a2013-07-17 04:45:13686 }
687
shess1cf87f22016-10-25 22:18:29688 db().set_error_callback(base::Bind(&RazeErrorCallback,
689 &db(),
[email protected]7bae5742013-07-10 20:46:16690 SQLITE_CORRUPT));
691
[email protected]fed734a2013-07-17 04:45:13692 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error
693 // callback will call RazeAndClose(). Open() will then fail and be
694 // retried. The second Open() on the empty database will succeed
695 // cleanly.
696 ASSERT_TRUE(db().Open(db_path()));
697 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum"));
[email protected]7bae5742013-07-10 20:46:16698 EXPECT_EQ(0, SqliteMasterCount(&db()));
699}
700
[email protected]41a97c812013-02-07 02:35:38701// Basic test of RazeAndClose() operation.
702TEST_F(SQLConnectionTest, RazeAndClose) {
703 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
704 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
705
706 // Test that RazeAndClose() closes the database, and that the
707 // database is empty when re-opened.
708 ASSERT_TRUE(db().Execute(kCreateSql));
709 ASSERT_TRUE(db().Execute(kPopulateSql));
710 ASSERT_TRUE(db().RazeAndClose());
711 ASSERT_FALSE(db().is_open());
712 db().Close();
713 ASSERT_TRUE(db().Open(db_path()));
[email protected]7bae5742013-07-10 20:46:16714 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38715
716 // Test that RazeAndClose() can break transactions.
717 ASSERT_TRUE(db().Execute(kCreateSql));
718 ASSERT_TRUE(db().Execute(kPopulateSql));
719 ASSERT_TRUE(db().BeginTransaction());
720 ASSERT_TRUE(db().RazeAndClose());
721 ASSERT_FALSE(db().is_open());
722 ASSERT_FALSE(db().CommitTransaction());
723 db().Close();
724 ASSERT_TRUE(db().Open(db_path()));
[email protected]7bae5742013-07-10 20:46:16725 ASSERT_EQ(0, SqliteMasterCount(&db()));
[email protected]41a97c812013-02-07 02:35:38726}
727
728// Test that various operations fail without crashing after
729// RazeAndClose().
730TEST_F(SQLConnectionTest, RazeAndCloseDiagnostics) {
731 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
732 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
733 const char* kSimpleSql = "SELECT 1";
734
735 ASSERT_TRUE(db().Execute(kCreateSql));
736 ASSERT_TRUE(db().Execute(kPopulateSql));
737
738 // Test baseline expectations.
739 db().Preload();
740 ASSERT_TRUE(db().DoesTableExist("foo"));
741 ASSERT_TRUE(db().IsSQLValid(kSimpleSql));
742 ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql));
743 ASSERT_TRUE(db().Execute(kSimpleSql));
744 ASSERT_TRUE(db().is_open());
745 {
746 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
747 ASSERT_TRUE(s.Step());
748 }
749 {
750 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
751 ASSERT_TRUE(s.Step());
752 }
753 ASSERT_TRUE(db().BeginTransaction());
754 ASSERT_TRUE(db().CommitTransaction());
755 ASSERT_TRUE(db().BeginTransaction());
756 db().RollbackTransaction();
757
758 ASSERT_TRUE(db().RazeAndClose());
759
760 // At this point, they should all fail, but not crash.
761 db().Preload();
762 ASSERT_FALSE(db().DoesTableExist("foo"));
763 ASSERT_FALSE(db().IsSQLValid(kSimpleSql));
764 ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql));
765 ASSERT_FALSE(db().Execute(kSimpleSql));
766 ASSERT_FALSE(db().is_open());
767 {
768 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
769 ASSERT_FALSE(s.Step());
770 }
771 {
772 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
773 ASSERT_FALSE(s.Step());
774 }
775 ASSERT_FALSE(db().BeginTransaction());
776 ASSERT_FALSE(db().CommitTransaction());
777 ASSERT_FALSE(db().BeginTransaction());
778 db().RollbackTransaction();
779
780 // Close normally to reset the poisoned flag.
781 db().Close();
782
783 // DEATH tests not supported on Android or iOS.
784#if !defined(OS_ANDROID) && !defined(OS_IOS)
785 // Once the real Close() has been called, various calls enforce API
786 // usage by becoming fatal in debug mode. Since DEATH tests are
787 // expensive, just test one of them.
788 if (DLOG_IS_ON(FATAL)) {
789 ASSERT_DEATH({
790 db().IsSQLValid(kSimpleSql);
791 }, "Illegal use of connection without a db");
792 }
793#endif
794}
795
796// TODO(shess): Spin up a background thread to hold other_db, to more
797// closely match real life. That would also allow testing
798// RazeWithTimeout().
799
[email protected]1348765a2012-07-24 08:25:53800#if defined(OS_ANDROID)
801TEST_F(SQLConnectionTest, SetTempDirForSQL) {
802
803 sql::MetaTable meta_table;
804 // Below call needs a temporary directory in sqlite3
805 // On Android, it can pass only when the temporary directory is set.
806 // Otherwise, sqlite3 doesn't find the correct directory to store
807 // temporary files and will report the error 'unable to open
808 // database file'.
809 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
810}
811#endif
[email protected]8d2e39e2013-06-24 05:55:08812
813TEST_F(SQLConnectionTest, Delete) {
814 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
815 db().Close();
816
817 // Should have both a main database file and a journal file because
shess2c21ecf2015-06-02 01:31:09818 // of journal_mode TRUNCATE.
[email protected]8d2e39e2013-06-24 05:55:08819 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
erg102ceb412015-06-20 01:38:13820 ASSERT_TRUE(GetPathExists(db_path()));
821 ASSERT_TRUE(GetPathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08822
823 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13824 EXPECT_FALSE(GetPathExists(db_path()));
825 EXPECT_FALSE(GetPathExists(journal));
[email protected]8d2e39e2013-06-24 05:55:08826}
[email protected]7bae5742013-07-10 20:46:16827
erg102ceb412015-06-20 01:38:13828// This test manually sets on disk permissions; this doesn't apply to the mojo
829// fork.
830#if defined(OS_POSIX) && !defined(MOJO_APPTEST_IMPL)
[email protected]81a2a602013-07-17 19:10:36831// Test that set_restrict_to_user() trims database permissions so that
832// only the owner (and root) can read.
833TEST_F(SQLConnectionTest, UserPermission) {
834 // If the bots all had a restrictive umask setting such that
835 // databases are always created with only the owner able to read
836 // them, then the code could break without breaking the tests.
837 // Temporarily provide a more permissive umask.
838 db().Close();
839 sql::Connection::Delete(db_path());
erg102ceb412015-06-20 01:38:13840 ASSERT_FALSE(GetPathExists(db_path()));
[email protected]81a2a602013-07-17 19:10:36841 ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH);
842 ASSERT_TRUE(db().Open(db_path()));
843
844 // Cause the journal file to be created. If the default
845 // journal_mode is changed back to DELETE, then parts of this test
846 // will need to be updated.
847 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
848
849 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
850 int mode;
851
852 // Given a permissive umask, the database is created with permissive
853 // read access for the database and journal.
erg102ceb412015-06-20 01:38:13854 ASSERT_TRUE(GetPathExists(db_path()));
855 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08856 mode = base::FILE_PERMISSION_MASK;
857 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
858 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
859 mode = base::FILE_PERMISSION_MASK;
860 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
861 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36862
863 // Re-open with restricted permissions and verify that the modes
864 // changed for both the main database and the journal.
865 db().Close();
866 db().set_restrict_to_user();
867 ASSERT_TRUE(db().Open(db_path()));
erg102ceb412015-06-20 01:38:13868 ASSERT_TRUE(GetPathExists(db_path()));
869 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08870 mode = base::FILE_PERMISSION_MASK;
871 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
872 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
873 mode = base::FILE_PERMISSION_MASK;
874 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
875 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36876
877 // Delete and re-create the database, the restriction should still apply.
878 db().Close();
879 sql::Connection::Delete(db_path());
880 ASSERT_TRUE(db().Open(db_path()));
erg102ceb412015-06-20 01:38:13881 ASSERT_TRUE(GetPathExists(db_path()));
882 ASSERT_FALSE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08883 mode = base::FILE_PERMISSION_MASK;
884 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
885 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36886
887 // Verify that journal creation inherits the restriction.
888 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
erg102ceb412015-06-20 01:38:13889 ASSERT_TRUE(GetPathExists(journal));
[email protected]b264eab2013-11-27 23:22:08890 mode = base::FILE_PERMISSION_MASK;
891 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
892 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
[email protected]81a2a602013-07-17 19:10:36893}
894#endif // defined(OS_POSIX)
895
[email protected]8d409412013-07-19 18:25:30896// Test that errors start happening once Poison() is called.
897TEST_F(SQLConnectionTest, Poison) {
898 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
899
900 // Before the Poison() call, things generally work.
901 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
902 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
903 {
904 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
905 ASSERT_TRUE(s.is_valid());
906 ASSERT_TRUE(s.Step());
907 }
908
909 // Get a statement which is valid before and will exist across Poison().
910 sql::Statement valid_statement(
911 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master"));
912 ASSERT_TRUE(valid_statement.is_valid());
913 ASSERT_TRUE(valid_statement.Step());
914 valid_statement.Reset(true);
915
916 db().Poison();
917
918 // After the Poison() call, things fail.
919 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
920 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')"));
921 {
922 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
923 ASSERT_FALSE(s.is_valid());
924 ASSERT_FALSE(s.Step());
925 }
926
927 // The existing statement has become invalid.
928 ASSERT_FALSE(valid_statement.is_valid());
929 ASSERT_FALSE(valid_statement.Step());
shess644fc8a2016-02-26 18:15:58930
931 // Test that poisoning the database during a transaction works (with errors).
932 // RazeErrorCallback() poisons the database, the extra COMMIT causes
933 // CommitTransaction() to throw an error while commiting.
shess1cf87f22016-10-25 22:18:29934 db().set_error_callback(base::Bind(&RazeErrorCallback,
935 &db(),
shess644fc8a2016-02-26 18:15:58936 SQLITE_ERROR));
937 db().Close();
938 ASSERT_TRUE(db().Open(db_path()));
939 EXPECT_TRUE(db().BeginTransaction());
940 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
941 EXPECT_TRUE(db().Execute("COMMIT"));
942 EXPECT_FALSE(db().CommitTransaction());
[email protected]8d409412013-07-19 18:25:30943}
944
945// Test attaching and detaching databases from the connection.
946TEST_F(SQLConnectionTest, Attach) {
947 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
948
949 // Create a database to attach to.
950 base::FilePath attach_path =
951 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
952 const char kAttachmentPoint[] = "other";
953 {
954 sql::Connection other_db;
955 ASSERT_TRUE(other_db.Open(attach_path));
956 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
957 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
958 }
959
960 // Cannot see the attached database, yet.
961 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
962
963 // Attach fails in a transaction.
964 EXPECT_TRUE(db().BeginTransaction());
965 {
shess976814402016-06-21 06:56:25966 sql::test::ScopedErrorExpecter expecter;
967 expecter.ExpectError(SQLITE_ERROR);
[email protected]8d409412013-07-19 18:25:30968 EXPECT_FALSE(db().AttachDatabase(attach_path, kAttachmentPoint));
shess976814402016-06-21 06:56:25969 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]8d409412013-07-19 18:25:30970 }
971
972 // Attach succeeds when the transaction is closed.
973 db().RollbackTransaction();
974 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
975 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
976
977 // Queries can touch both databases.
978 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
979 {
980 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
981 ASSERT_TRUE(s.Step());
982 EXPECT_EQ(1, s.ColumnInt(0));
983 }
984
985 // Detach also fails in a transaction.
986 EXPECT_TRUE(db().BeginTransaction());
987 {
shess976814402016-06-21 06:56:25988 sql::test::ScopedErrorExpecter expecter;
989 expecter.ExpectError(SQLITE_ERROR);
[email protected]8d409412013-07-19 18:25:30990 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint));
991 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
shess976814402016-06-21 06:56:25992 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]8d409412013-07-19 18:25:30993 }
994
995 // Detach succeeds outside of a transaction.
996 db().RollbackTransaction();
997 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
998
999 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
1000}
1001
[email protected]579446c2013-12-16 18:36:521002TEST_F(SQLConnectionTest, Basic_QuickIntegrityCheck) {
1003 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1004 ASSERT_TRUE(db().Execute(kCreateSql));
1005 EXPECT_TRUE(db().QuickIntegrityCheck());
1006 db().Close();
1007
erg102ceb412015-06-20 01:38:131008 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]579446c2013-12-16 18:36:521009
1010 {
shess976814402016-06-21 06:56:251011 sql::test::ScopedErrorExpecter expecter;
1012 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]579446c2013-12-16 18:36:521013 ASSERT_TRUE(db().Open(db_path()));
1014 EXPECT_FALSE(db().QuickIntegrityCheck());
shess976814402016-06-21 06:56:251015 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]579446c2013-12-16 18:36:521016 }
1017}
1018
1019TEST_F(SQLConnectionTest, Basic_FullIntegrityCheck) {
1020 const std::string kOk("ok");
1021 std::vector<std::string> messages;
1022
1023 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1024 ASSERT_TRUE(db().Execute(kCreateSql));
1025 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
1026 EXPECT_EQ(1u, messages.size());
1027 EXPECT_EQ(kOk, messages[0]);
1028 db().Close();
1029
erg102ceb412015-06-20 01:38:131030 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
[email protected]579446c2013-12-16 18:36:521031
1032 {
shess976814402016-06-21 06:56:251033 sql::test::ScopedErrorExpecter expecter;
1034 expecter.ExpectError(SQLITE_CORRUPT);
[email protected]579446c2013-12-16 18:36:521035 ASSERT_TRUE(db().Open(db_path()));
1036 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
1037 EXPECT_LT(1u, messages.size());
1038 EXPECT_NE(kOk, messages[0]);
shess976814402016-06-21 06:56:251039 ASSERT_TRUE(expecter.SawExpectedErrors());
[email protected]579446c2013-12-16 18:36:521040 }
1041
1042 // TODO(shess): CorruptTableOrIndex could be used to produce a
1043 // file that would pass the quick check and fail the full check.
1044}
1045
shess58b8df82015-06-03 00:19:321046// Test Sqlite.Stats histogram for execute-oriented calls.
1047TEST_F(SQLConnectionTest, EventsExecute) {
1048 // Re-open with histogram tag.
1049 db().Close();
1050 db().set_histogram_tag("Test");
1051 ASSERT_TRUE(db().Open(db_path()));
1052
1053 // Open() uses Execute() extensively, don't track those calls.
1054 base::HistogramTester tester;
1055
1056 const char kHistogramName[] = "Sqlite.Stats.Test";
1057 const char kGlobalHistogramName[] = "Sqlite.Stats";
1058
1059 ASSERT_TRUE(db().BeginTransaction());
1060 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1061 EXPECT_TRUE(db().Execute(kCreateSql));
1062 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1063 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1064 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1065 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (13, 'text')"));
1066 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (14, 'text')"));
1067 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (15, 'text');"
1068 "INSERT INTO foo VALUES (16, 'text');"
1069 "INSERT INTO foo VALUES (17, 'text');"
1070 "INSERT INTO foo VALUES (18, 'text');"
1071 "INSERT INTO foo VALUES (19, 'text')"));
1072 ASSERT_TRUE(db().CommitTransaction());
1073 ASSERT_TRUE(db().BeginTransaction());
1074 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1075 db().RollbackTransaction();
1076 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1077 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (21, 'text')"));
1078
1079 // The create, 5 inserts, multi-statement insert, rolled-back insert, 2
1080 // inserts outside transaction.
1081 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_EXECUTE, 10);
1082 tester.ExpectBucketCount(kGlobalHistogramName,
1083 sql::Connection::EVENT_EXECUTE, 10);
1084
1085 // All of the executes, with the multi-statement inserts broken out, plus one
1086 // for each begin, commit, and rollback.
1087 tester.ExpectBucketCount(kHistogramName,
1088 sql::Connection::EVENT_STATEMENT_RUN, 18);
1089 tester.ExpectBucketCount(kGlobalHistogramName,
1090 sql::Connection::EVENT_STATEMENT_RUN, 18);
1091
1092 tester.ExpectBucketCount(kHistogramName,
1093 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1094 tester.ExpectBucketCount(kGlobalHistogramName,
1095 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1096 tester.ExpectBucketCount(kHistogramName,
1097 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1098 tester.ExpectBucketCount(kGlobalHistogramName,
1099 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1100
1101 // The 2 inserts outside the transaction.
1102 tester.ExpectBucketCount(kHistogramName,
1103 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1104 tester.ExpectBucketCount(kGlobalHistogramName,
1105 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1106
1107 // 11 inserts inside transactions.
1108 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_CHANGES, 11);
1109 tester.ExpectBucketCount(kGlobalHistogramName,
1110 sql::Connection::EVENT_CHANGES, 11);
1111
1112 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_BEGIN, 2);
1113 tester.ExpectBucketCount(kGlobalHistogramName,
1114 sql::Connection::EVENT_BEGIN, 2);
1115 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_COMMIT, 1);
1116 tester.ExpectBucketCount(kGlobalHistogramName,
1117 sql::Connection::EVENT_COMMIT, 1);
1118 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_ROLLBACK, 1);
1119 tester.ExpectBucketCount(kGlobalHistogramName,
1120 sql::Connection::EVENT_ROLLBACK, 1);
1121}
1122
1123// Test Sqlite.Stats histogram for prepared statements.
1124TEST_F(SQLConnectionTest, EventsStatement) {
1125 // Re-open with histogram tag.
1126 db().Close();
1127 db().set_histogram_tag("Test");
1128 ASSERT_TRUE(db().Open(db_path()));
1129
1130 const char kHistogramName[] = "Sqlite.Stats.Test";
1131 const char kGlobalHistogramName[] = "Sqlite.Stats";
1132
1133 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1134 EXPECT_TRUE(db().Execute(kCreateSql));
1135 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1136 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1137 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1138
1139 {
1140 base::HistogramTester tester;
1141
1142 {
1143 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo"));
1144 while (s.Step()) {
1145 }
1146 }
1147
1148 tester.ExpectBucketCount(kHistogramName,
1149 sql::Connection::EVENT_STATEMENT_RUN, 1);
1150 tester.ExpectBucketCount(kGlobalHistogramName,
1151 sql::Connection::EVENT_STATEMENT_RUN, 1);
1152 tester.ExpectBucketCount(kHistogramName,
1153 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1154 tester.ExpectBucketCount(kGlobalHistogramName,
1155 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1156 tester.ExpectBucketCount(kHistogramName,
1157 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1158 tester.ExpectBucketCount(kGlobalHistogramName,
1159 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1160 }
1161
1162 {
1163 base::HistogramTester tester;
1164
1165 {
1166 sql::Statement s(db().GetUniqueStatement(
1167 "SELECT value FROM foo WHERE id > 10"));
1168 while (s.Step()) {
1169 }
1170 }
1171
1172 tester.ExpectBucketCount(kHistogramName,
1173 sql::Connection::EVENT_STATEMENT_RUN, 1);
1174 tester.ExpectBucketCount(kGlobalHistogramName,
1175 sql::Connection::EVENT_STATEMENT_RUN, 1);
1176 tester.ExpectBucketCount(kHistogramName,
1177 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1178 tester.ExpectBucketCount(kGlobalHistogramName,
1179 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1180 tester.ExpectBucketCount(kHistogramName,
1181 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1182 tester.ExpectBucketCount(kGlobalHistogramName,
1183 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1184 }
1185}
1186
shess58b8df82015-06-03 00:19:321187// Read-only query allocates time to QueryTime, but not others.
1188TEST_F(SQLConnectionTest, TimeQuery) {
1189 // Re-open with histogram tag. Use an in-memory database to minimize variance
1190 // due to filesystem.
1191 db().Close();
1192 db().set_histogram_tag("Test");
1193 ASSERT_TRUE(db().OpenInMemory());
1194
1195 sql::test::ScopedMockTimeSource time_mock(db());
1196
1197 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1198 EXPECT_TRUE(db().Execute(kCreateSql));
1199
1200 // Function to inject pauses into statements.
1201 sql::test::ScopedScalarFunction scoper(
1202 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1203
1204 base::HistogramTester tester;
1205
1206 EXPECT_TRUE(db().Execute("SELECT milliadjust(10)"));
1207
mostynbd82cd9952016-04-11 20:05:341208 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321209 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1210 ASSERT_TRUE(samples);
1211 // 10 for the adjust, 1 for the measurement.
1212 EXPECT_EQ(11, samples->sum());
1213
1214 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
vabrae960432015-08-03 08:12:541215 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321216
1217 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
vabrae960432015-08-03 08:12:541218 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321219
1220 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
vabrae960432015-08-03 08:12:541221 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321222}
1223
1224// Autocommit update allocates time to QueryTime, UpdateTime, and
1225// AutoCommitTime.
1226TEST_F(SQLConnectionTest, TimeUpdateAutocommit) {
1227 // Re-open with histogram tag. Use an in-memory database to minimize variance
1228 // due to filesystem.
1229 db().Close();
1230 db().set_histogram_tag("Test");
1231 ASSERT_TRUE(db().OpenInMemory());
1232
1233 sql::test::ScopedMockTimeSource time_mock(db());
1234
1235 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1236 EXPECT_TRUE(db().Execute(kCreateSql));
1237
1238 // Function to inject pauses into statements.
1239 sql::test::ScopedScalarFunction scoper(
1240 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1241
1242 base::HistogramTester tester;
1243
1244 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, milliadjust(10))"));
1245
mostynbd82cd9952016-04-11 20:05:341246 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321247 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1248 ASSERT_TRUE(samples);
1249 // 10 for the adjust, 1 for the measurement.
1250 EXPECT_EQ(11, samples->sum());
1251
1252 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1253 ASSERT_TRUE(samples);
1254 // 10 for the adjust, 1 for the measurement.
1255 EXPECT_EQ(11, samples->sum());
1256
1257 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
vabrae960432015-08-03 08:12:541258 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321259
1260 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1261 ASSERT_TRUE(samples);
1262 // 10 for the adjust, 1 for the measurement.
1263 EXPECT_EQ(11, samples->sum());
1264}
1265
1266// Update with explicit transaction allocates time to QueryTime, UpdateTime, and
1267// CommitTime.
1268TEST_F(SQLConnectionTest, TimeUpdateTransaction) {
1269 // Re-open with histogram tag. Use an in-memory database to minimize variance
1270 // due to filesystem.
1271 db().Close();
1272 db().set_histogram_tag("Test");
1273 ASSERT_TRUE(db().OpenInMemory());
1274
1275 sql::test::ScopedMockTimeSource time_mock(db());
1276
1277 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1278 EXPECT_TRUE(db().Execute(kCreateSql));
1279
1280 // Function to inject pauses into statements.
1281 sql::test::ScopedScalarFunction scoper(
1282 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1283
1284 base::HistogramTester tester;
1285
1286 {
1287 // Make the commit slow.
1288 sql::test::ScopedCommitHook scoped_hook(
1289 db(), base::Bind(adjust_commit_hook, &time_mock, 100));
1290 ASSERT_TRUE(db().BeginTransaction());
1291 EXPECT_TRUE(db().Execute(
1292 "INSERT INTO foo VALUES (11, milliadjust(10))"));
1293 EXPECT_TRUE(db().Execute(
1294 "UPDATE foo SET value = milliadjust(10) WHERE id = 11"));
1295 EXPECT_TRUE(db().CommitTransaction());
1296 }
1297
mostynbd82cd9952016-04-11 20:05:341298 std::unique_ptr<base::HistogramSamples> samples(
shess58b8df82015-06-03 00:19:321299 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1300 ASSERT_TRUE(samples);
1301 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1302 // measuring each of BEGIN, INSERT, UPDATE, and COMMIT.
1303 EXPECT_EQ(124, samples->sum());
1304
1305 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1306 ASSERT_TRUE(samples);
1307 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1308 // measuring each of INSERT, UPDATE, and COMMIT.
1309 EXPECT_EQ(123, samples->sum());
1310
1311 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1312 ASSERT_TRUE(samples);
1313 // 100 for commit adjust, 1 for measuring COMMIT.
1314 EXPECT_EQ(101, samples->sum());
1315
1316 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
vabrae960432015-08-03 08:12:541317 EXPECT_EQ(0, samples->sum());
shess58b8df82015-06-03 00:19:321318}
1319
ssid9f8022f2015-10-12 17:49:031320TEST_F(SQLConnectionTest, OnMemoryDump) {
ssid9f8022f2015-10-12 17:49:031321 base::trace_event::MemoryDumpArgs args = {
1322 base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
ssid448e5ed2016-06-04 12:40:511323 base::trace_event::ProcessMemoryDump pmd(nullptr, args);
ssid3be5b1ec2016-01-13 14:21:571324 ASSERT_TRUE(db().memory_dump_provider_->OnMemoryDump(args, &pmd));
ssid9f8022f2015-10-12 17:49:031325 EXPECT_GE(pmd.allocator_dumps().size(), 1u);
1326}
1327
shessc8cd2a162015-10-22 20:30:461328// Test that the functions to collect diagnostic data run to completion, without
1329// worrying too much about what they generate (since that will change).
1330TEST_F(SQLConnectionTest, CollectDiagnosticInfo) {
1331 // NOTE(shess): Mojo doesn't support everything CollectCorruptionInfo() uses,
1332 // but it's not really clear if adding support would be useful.
1333#if !defined(MOJO_APPTEST_IMPL)
1334 const std::string corruption_info = db().CollectCorruptionInfo();
1335 EXPECT_NE(std::string::npos, corruption_info.find("SQLITE_CORRUPT"));
1336 EXPECT_NE(std::string::npos, corruption_info.find("integrity_check"));
1337#endif
1338
1339 // A statement to see in the results.
1340 const char* kSimpleSql = "SELECT 'mountain'";
1341 Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
1342
1343 // Error includes the statement.
1344 const std::string readonly_info = db().CollectErrorInfo(SQLITE_READONLY, &s);
1345 EXPECT_NE(std::string::npos, readonly_info.find(kSimpleSql));
1346
1347 // Some other error doesn't include the statment.
1348 // TODO(shess): This is weak.
1349 const std::string full_info = db().CollectErrorInfo(SQLITE_FULL, NULL);
1350 EXPECT_EQ(std::string::npos, full_info.find(kSimpleSql));
1351
1352 // A table to see in the SQLITE_ERROR results.
1353 EXPECT_TRUE(db().Execute("CREATE TABLE volcano (x)"));
1354
1355 // Version info to see in the SQLITE_ERROR results.
1356 sql::MetaTable meta_table;
1357 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
1358
1359 const std::string error_info = db().CollectErrorInfo(SQLITE_ERROR, &s);
1360 EXPECT_NE(std::string::npos, error_info.find(kSimpleSql));
1361 EXPECT_NE(std::string::npos, error_info.find("volcano"));
1362 EXPECT_NE(std::string::npos, error_info.find("version: 4"));
1363}
1364
1365#if !defined(MOJO_APPTEST_IMPL)
1366TEST_F(SQLConnectionTest, RegisterIntentToUpload) {
1367 base::FilePath breadcrumb_path(
1368 db_path().DirName().Append(FILE_PATH_LITERAL("sqlite-diag")));
1369
1370 // No stale diagnostic store.
1371 ASSERT_TRUE(!base::PathExists(breadcrumb_path));
1372
1373 // The histogram tag is required to enable diagnostic features.
1374 EXPECT_FALSE(db().RegisterIntentToUpload());
1375 EXPECT_TRUE(!base::PathExists(breadcrumb_path));
1376
1377 db().Close();
1378 db().set_histogram_tag("Test");
1379 ASSERT_TRUE(db().Open(db_path()));
1380
1381 // Should signal upload only once.
1382 EXPECT_TRUE(db().RegisterIntentToUpload());
1383 EXPECT_TRUE(base::PathExists(breadcrumb_path));
1384 EXPECT_FALSE(db().RegisterIntentToUpload());
1385
1386 // Changing the histogram tag should allow new upload to succeed.
1387 db().Close();
1388 db().set_histogram_tag("NewTest");
1389 ASSERT_TRUE(db().Open(db_path()));
1390 EXPECT_TRUE(db().RegisterIntentToUpload());
1391 EXPECT_FALSE(db().RegisterIntentToUpload());
1392
1393 // Old tag is still prevented.
1394 db().Close();
1395 db().set_histogram_tag("Test");
1396 ASSERT_TRUE(db().Open(db_path()));
1397 EXPECT_FALSE(db().RegisterIntentToUpload());
1398}
1399#endif // !defined(MOJO_APPTEST_IMPL)
1400
shess9bf2c672015-12-18 01:18:081401// Test that a fresh database has mmap enabled by default, if mmap'ed I/O is
1402// enabled by SQLite.
1403TEST_F(SQLConnectionTest, MmapInitiallyEnabled) {
1404 {
1405 sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size"));
1406
1407 // SQLite doesn't have mmap support (perhaps an early iOS release).
1408 if (!s.Step())
1409 return;
1410
1411 // If mmap I/O is not on, attempt to turn it on. If that succeeds, then
1412 // Open() should have turned it on. If mmap support is disabled, 0 is
1413 // returned. If the VFS does not understand SQLITE_FCNTL_MMAP_SIZE (for
1414 // instance MojoVFS), -1 is returned.
1415 if (s.ColumnInt(0) <= 0) {
1416 ASSERT_TRUE(db().Execute("PRAGMA mmap_size = 1048576"));
1417 s.Reset(true);
1418 ASSERT_TRUE(s.Step());
1419 EXPECT_LE(s.ColumnInt(0), 0);
1420 }
1421 }
1422
1423 // Test that explicit disable prevents mmap'ed I/O.
1424 db().Close();
1425 sql::Connection::Delete(db_path());
1426 db().set_mmap_disabled();
1427 ASSERT_TRUE(db().Open(db_path()));
1428 {
1429 sql::Statement s(db().GetUniqueStatement("PRAGMA mmap_size"));
1430 ASSERT_TRUE(s.Step());
1431 EXPECT_LE(s.ColumnInt(0), 0);
1432 }
1433}
1434
shess9bf2c672015-12-18 01:18:081435TEST_F(SQLConnectionTest, GetAppropriateMmapSize) {
rohitrao83d6b83a2016-06-21 07:25:571436#if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE)
1437 // Mmap is not supported on iOS9.
1438 if (!base::ios::IsRunningOnIOS10OrLater()) {
1439 ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
1440 return;
1441 }
1442#endif
1443
shess9bf2c672015-12-18 01:18:081444 const size_t kMmapAlot = 25 * 1024 * 1024;
shess9e77283d2016-06-13 23:53:201445 int64_t mmap_status = MetaTable::kMmapFailure;
shess9bf2c672015-12-18 01:18:081446
1447 // If there is no meta table (as for a fresh database), assume that everything
shess9e77283d2016-06-13 23:53:201448 // should be mapped, and the status of the meta table is not affected.
shess9bf2c672015-12-18 01:18:081449 ASSERT_TRUE(!db().DoesTableExist("meta"));
1450 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
shess9e77283d2016-06-13 23:53:201451 ASSERT_TRUE(!db().DoesTableExist("meta"));
shess9bf2c672015-12-18 01:18:081452
1453 // When the meta table is first created, it sets up to map everything.
1454 MetaTable().Init(&db(), 1, 1);
1455 ASSERT_TRUE(db().DoesTableExist("meta"));
1456 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1457 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1458 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1459
1460 // Failure status maps nothing.
1461 ASSERT_TRUE(db().Execute("REPLACE INTO meta VALUES ('mmap_status', -2)"));
1462 ASSERT_EQ(0UL, db().GetAppropriateMmapSize());
1463
1464 // Re-initializing the meta table does not re-create the key if the table
1465 // already exists.
1466 ASSERT_TRUE(db().Execute("DELETE FROM meta WHERE key = 'mmap_status'"));
1467 MetaTable().Init(&db(), 1, 1);
1468 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1469 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1470 ASSERT_EQ(0, mmap_status);
1471
1472 // With no key, map everything and create the key.
1473 // TODO(shess): This really should be "maps everything after validating it",
1474 // but that is more complicated to structure.
1475 ASSERT_GT(db().GetAppropriateMmapSize(), kMmapAlot);
1476 ASSERT_TRUE(MetaTable::GetMmapStatus(&db(), &mmap_status));
1477 ASSERT_EQ(MetaTable::kMmapSuccess, mmap_status);
1478}
shess9bf2c672015-12-18 01:18:081479
shess9e77283d2016-06-13 23:53:201480// To prevent invalid SQL from accidentally shipping to production, prepared
1481// statements which fail to compile with SQLITE_ERROR call DLOG(FATAL). This
1482// case cannot be suppressed with an error callback.
1483TEST_F(SQLConnectionTest, CompileError) {
1484 // DEATH tests not supported on Android or iOS.
1485#if !defined(OS_ANDROID) && !defined(OS_IOS)
1486 if (DLOG_IS_ON(FATAL)) {
1487 db().set_error_callback(base::Bind(&IgnoreErrorCallback));
1488 ASSERT_DEATH({
1489 db().GetUniqueStatement("SELECT x");
1490 }, "SQL compile error no such column: x");
1491 }
1492#endif
1493}
1494
shessc8cd2a162015-10-22 20:30:461495} // namespace sql