[Sync] Componentize UIModelWorker.
[chromium-blink-merge.git] / sql / connection_unittest.cc
blob10a15a868908965d893ce4952388bd09688e4e19
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/bind.h"
6 #include "base/files/file_util.h"
7 #include "base/files/scoped_file.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/logging.h"
10 #include "base/metrics/statistics_recorder.h"
11 #include "base/test/histogram_tester.h"
12 #include "sql/connection.h"
13 #include "sql/correct_sql_test_base.h"
14 #include "sql/meta_table.h"
15 #include "sql/statement.h"
16 #include "sql/test/error_callback_support.h"
17 #include "sql/test/scoped_error_ignorer.h"
18 #include "sql/test/test_helpers.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/sqlite/sqlite3.h"
22 namespace sql {
23 namespace test {
25 // Replaces the database time source with an object that steps forward 1ms on
26 // each check, and which can be jumped forward an arbitrary amount of time
27 // programmatically.
28 class ScopedMockTimeSource {
29 public:
30 ScopedMockTimeSource(Connection& db)
31 : db_(db),
32 delta_(base::TimeDelta::FromMilliseconds(1)) {
33 // Save the current source and replace it.
34 save_.swap(db_.clock_);
35 db_.clock_.reset(new MockTimeSource(*this));
37 ~ScopedMockTimeSource() {
38 // Put original source back.
39 db_.clock_.swap(save_);
42 void adjust(const base::TimeDelta& delta) {
43 current_time_ += delta;
46 private:
47 class MockTimeSource : public TimeSource {
48 public:
49 MockTimeSource(ScopedMockTimeSource& owner)
50 : owner_(owner) {
52 ~MockTimeSource() override {}
54 base::TimeTicks Now() override {
55 base::TimeTicks ret(owner_.current_time_);
56 owner_.current_time_ += owner_.delta_;
57 return ret;
60 private:
61 ScopedMockTimeSource& owner_;
62 DISALLOW_COPY_AND_ASSIGN(MockTimeSource);
65 Connection& db_;
67 // Saves original source from |db_|.
68 scoped_ptr<TimeSource> save_;
70 // Current time returned by mock.
71 base::TimeTicks current_time_;
73 // How far to jump on each Now() call.
74 base::TimeDelta delta_;
76 DISALLOW_COPY_AND_ASSIGN(ScopedMockTimeSource);
79 // Allow a test to add a SQLite function in a scoped context.
80 class ScopedScalarFunction {
81 public:
82 ScopedScalarFunction(
83 sql::Connection& db,
84 const char* function_name,
85 int args,
86 base::Callback<void(sqlite3_context*,int,sqlite3_value**)> cb)
87 : db_(db.db_), function_name_(function_name), cb_(cb) {
88 sqlite3_create_function_v2(db_, function_name, args, SQLITE_UTF8,
89 this, &Run, NULL, NULL, NULL);
91 ~ScopedScalarFunction() {
92 sqlite3_create_function_v2(db_, function_name_, 0, SQLITE_UTF8,
93 NULL, NULL, NULL, NULL, NULL);
96 private:
97 static void Run(sqlite3_context* context, int argc, sqlite3_value** argv) {
98 ScopedScalarFunction* t = static_cast<ScopedScalarFunction*>(
99 sqlite3_user_data(context));
100 t->cb_.Run(context, argc, argv);
103 sqlite3* db_;
104 const char* function_name_;
105 base::Callback<void(sqlite3_context*,int,sqlite3_value**)> cb_;
107 DISALLOW_COPY_AND_ASSIGN(ScopedScalarFunction);
110 // Allow a test to add a SQLite commit hook in a scoped context.
111 class ScopedCommitHook {
112 public:
113 ScopedCommitHook(sql::Connection& db,
114 base::Callback<int(void)> cb)
115 : db_(db.db_),
116 cb_(cb) {
117 sqlite3_commit_hook(db_, &Run, this);
119 ~ScopedCommitHook() {
120 sqlite3_commit_hook(db_, NULL, NULL);
123 private:
124 static int Run(void* p) {
125 ScopedCommitHook* t = static_cast<ScopedCommitHook*>(p);
126 return t->cb_.Run();
129 sqlite3* db_;
130 base::Callback<int(void)> cb_;
132 DISALLOW_COPY_AND_ASSIGN(ScopedCommitHook);
135 } // namespace test
136 } // namespace sql
138 namespace {
140 // Helper to return the count of items in sqlite_master. Return -1 in
141 // case of error.
142 int SqliteMasterCount(sql::Connection* db) {
143 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master";
144 sql::Statement s(db->GetUniqueStatement(kMasterCount));
145 return s.Step() ? s.ColumnInt(0) : -1;
148 // Track the number of valid references which share the same pointer.
149 // This is used to allow testing an implicitly use-after-free case by
150 // explicitly having the ref count live longer than the object.
151 class RefCounter {
152 public:
153 RefCounter(size_t* counter)
154 : counter_(counter) {
155 (*counter_)++;
157 RefCounter(const RefCounter& other)
158 : counter_(other.counter_) {
159 (*counter_)++;
161 ~RefCounter() {
162 (*counter_)--;
165 private:
166 size_t* counter_;
168 DISALLOW_ASSIGN(RefCounter);
171 // Empty callback for implementation of ErrorCallbackSetHelper().
172 void IgnoreErrorCallback(int error, sql::Statement* stmt) {
175 void ErrorCallbackSetHelper(sql::Connection* db,
176 size_t* counter,
177 const RefCounter& r,
178 int error, sql::Statement* stmt) {
179 // The ref count should not go to zero when changing the callback.
180 EXPECT_GT(*counter, 0u);
181 db->set_error_callback(base::Bind(&IgnoreErrorCallback));
182 EXPECT_GT(*counter, 0u);
185 void ErrorCallbackResetHelper(sql::Connection* db,
186 size_t* counter,
187 const RefCounter& r,
188 int error, sql::Statement* stmt) {
189 // The ref count should not go to zero when clearing the callback.
190 EXPECT_GT(*counter, 0u);
191 db->reset_error_callback();
192 EXPECT_GT(*counter, 0u);
195 #if defined(OS_POSIX)
196 // Set a umask and restore the old mask on destruction. Cribbed from
197 // shared_memory_unittest.cc. Used by POSIX-only UserPermission test.
198 class ScopedUmaskSetter {
199 public:
200 explicit ScopedUmaskSetter(mode_t target_mask) {
201 old_umask_ = umask(target_mask);
203 ~ScopedUmaskSetter() { umask(old_umask_); }
204 private:
205 mode_t old_umask_;
206 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
208 #endif
210 class SQLConnectionTest : public sql::SQLTestBase {
211 public:
212 void SetUp() override {
213 // Any macro histograms which fire before the recorder is initialized cannot
214 // be tested. So this needs to be ahead of Open().
215 base::StatisticsRecorder::Initialize();
217 SQLTestBase::SetUp();
220 // Handle errors by blowing away the database.
221 void RazeErrorCallback(int expected_error, int error, sql::Statement* stmt) {
222 EXPECT_EQ(expected_error, error);
223 db().RazeAndClose();
227 TEST_F(SQLConnectionTest, Execute) {
228 // Valid statement should return true.
229 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
230 EXPECT_EQ(SQLITE_OK, db().GetErrorCode());
232 // Invalid statement should fail.
233 ASSERT_EQ(SQLITE_ERROR,
234 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b"));
235 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode());
238 TEST_F(SQLConnectionTest, ExecuteWithErrorCode) {
239 ASSERT_EQ(SQLITE_OK,
240 db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)"));
241 ASSERT_EQ(SQLITE_ERROR,
242 db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE"));
243 ASSERT_EQ(SQLITE_ERROR,
244 db().ExecuteAndReturnErrorCode(
245 "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)"));
248 TEST_F(SQLConnectionTest, CachedStatement) {
249 sql::StatementID id1("foo", 12);
251 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
252 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
254 // Create a new cached statement.
256 sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo"));
257 ASSERT_TRUE(s.is_valid());
259 ASSERT_TRUE(s.Step());
260 EXPECT_EQ(12, s.ColumnInt(0));
263 // The statement should be cached still.
264 EXPECT_TRUE(db().HasCachedStatement(id1));
267 // Get the same statement using different SQL. This should ignore our
268 // SQL and use the cached one (so it will be valid).
269 sql::Statement s(db().GetCachedStatement(id1, "something invalid("));
270 ASSERT_TRUE(s.is_valid());
272 ASSERT_TRUE(s.Step());
273 EXPECT_EQ(12, s.ColumnInt(0));
276 // Make sure other statements aren't marked as cached.
277 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE));
280 TEST_F(SQLConnectionTest, IsSQLValidTest) {
281 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
282 ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo"));
283 ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo"));
286 TEST_F(SQLConnectionTest, DoesStuffExist) {
287 // Test DoesTableExist.
288 EXPECT_FALSE(db().DoesTableExist("foo"));
289 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
290 ASSERT_TRUE(db().Execute("CREATE INDEX foo_a ON foo (a)"));
291 EXPECT_TRUE(db().DoesTableExist("foo"));
292 EXPECT_TRUE(db().DoesIndexExist("foo_a"));
294 // Test DoesColumnExist.
295 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
296 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
298 // Testing for a column on a nonexistent table.
299 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
301 // Names are not case sensitive.
302 EXPECT_TRUE(db().DoesTableExist("FOO"));
303 EXPECT_TRUE(db().DoesColumnExist("FOO", "A"));
306 TEST_F(SQLConnectionTest, GetLastInsertRowId) {
307 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
309 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
311 // Last insert row ID should be valid.
312 int64_t row = db().GetLastInsertRowId();
313 EXPECT_LT(0, row);
315 // It should be the primary key of the row we just inserted.
316 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
317 s.BindInt64(0, row);
318 ASSERT_TRUE(s.Step());
319 EXPECT_EQ(12, s.ColumnInt(0));
322 TEST_F(SQLConnectionTest, Rollback) {
323 ASSERT_TRUE(db().BeginTransaction());
324 ASSERT_TRUE(db().BeginTransaction());
325 EXPECT_EQ(2, db().transaction_nesting());
326 db().RollbackTransaction();
327 EXPECT_FALSE(db().CommitTransaction());
328 EXPECT_TRUE(db().BeginTransaction());
331 // Test the scoped error ignorer by attempting to insert a duplicate
332 // value into an index.
333 TEST_F(SQLConnectionTest, ScopedIgnoreError) {
334 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
335 ASSERT_TRUE(db().Execute(kCreateSql));
336 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
339 sql::ScopedErrorIgnorer ignore_errors;
340 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
341 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
342 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
346 // Test that clients of GetUntrackedStatement() can test corruption-handling
347 // with ScopedErrorIgnorer.
348 TEST_F(SQLConnectionTest, ScopedIgnoreUntracked) {
349 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
350 ASSERT_TRUE(db().Execute(kCreateSql));
351 ASSERT_FALSE(db().DoesTableExist("bar"));
352 ASSERT_TRUE(db().DoesTableExist("foo"));
353 ASSERT_TRUE(db().DoesColumnExist("foo", "id"));
354 db().Close();
356 // Corrupt the database so that nothing works, including PRAGMAs.
357 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
360 sql::ScopedErrorIgnorer ignore_errors;
361 ignore_errors.IgnoreError(SQLITE_CORRUPT);
362 ASSERT_TRUE(db().Open(db_path()));
363 ASSERT_FALSE(db().DoesTableExist("bar"));
364 ASSERT_FALSE(db().DoesTableExist("foo"));
365 ASSERT_FALSE(db().DoesColumnExist("foo", "id"));
366 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
370 TEST_F(SQLConnectionTest, ErrorCallback) {
371 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
372 ASSERT_TRUE(db().Execute(kCreateSql));
373 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
375 int error = SQLITE_OK;
377 sql::ScopedErrorCallback sec(
378 &db(), base::Bind(&sql::CaptureErrorCallback, &error));
379 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
381 // Later versions of SQLite throw SQLITE_CONSTRAINT_UNIQUE. The specific
382 // sub-error isn't really important.
383 EXPECT_EQ(SQLITE_CONSTRAINT, (error&0xff));
386 // Callback is no longer in force due to reset.
388 error = SQLITE_OK;
389 sql::ScopedErrorIgnorer ignore_errors;
390 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
391 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
392 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
393 EXPECT_EQ(SQLITE_OK, error);
396 // base::Bind() can curry arguments to be passed by const reference
397 // to the callback function. If the callback function calls
398 // re/set_error_callback(), the storage for those arguments can be
399 // deleted while the callback function is still executing.
401 // RefCounter() counts how many objects are live using an external
402 // count. The same counter is passed to the callback, so that it
403 // can check directly even if the RefCounter object is no longer
404 // live.
406 size_t count = 0;
407 sql::ScopedErrorCallback sec(
408 &db(), base::Bind(&ErrorCallbackSetHelper,
409 &db(), &count, RefCounter(&count)));
411 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
414 // Same test, but reset_error_callback() case.
416 size_t count = 0;
417 sql::ScopedErrorCallback sec(
418 &db(), base::Bind(&ErrorCallbackResetHelper,
419 &db(), &count, RefCounter(&count)));
421 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
425 // Test that sql::Connection::Raze() results in a database without the
426 // tables from the original database.
427 TEST_F(SQLConnectionTest, Raze) {
428 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
429 ASSERT_TRUE(db().Execute(kCreateSql));
430 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
432 int pragma_auto_vacuum = 0;
434 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
435 ASSERT_TRUE(s.Step());
436 pragma_auto_vacuum = s.ColumnInt(0);
437 ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1);
440 // If auto_vacuum is set, there's an extra page to maintain a freelist.
441 const int kExpectedPageCount = 2 + pragma_auto_vacuum;
444 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
445 ASSERT_TRUE(s.Step());
446 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0));
450 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master"));
451 ASSERT_TRUE(s.Step());
452 EXPECT_EQ("table", s.ColumnString(0));
453 EXPECT_EQ("foo", s.ColumnString(1));
454 EXPECT_EQ("foo", s.ColumnString(2));
455 // Table "foo" is stored in the last page of the file.
456 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3));
457 EXPECT_EQ(kCreateSql, s.ColumnString(4));
460 ASSERT_TRUE(db().Raze());
463 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
464 ASSERT_TRUE(s.Step());
465 EXPECT_EQ(1, s.ColumnInt(0));
468 ASSERT_EQ(0, SqliteMasterCount(&db()));
471 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
472 ASSERT_TRUE(s.Step());
473 // The new database has the same auto_vacuum as a fresh database.
474 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0));
478 // Test that Raze() maintains page_size.
479 TEST_F(SQLConnectionTest, RazePageSize) {
480 // Fetch the default page size and double it for use in this test.
481 // Scoped to release statement before Close().
482 int default_page_size = 0;
484 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
485 ASSERT_TRUE(s.Step());
486 default_page_size = s.ColumnInt(0);
488 ASSERT_GT(default_page_size, 0);
489 const int kPageSize = 2 * default_page_size;
491 // Re-open the database to allow setting the page size.
492 db().Close();
493 db().set_page_size(kPageSize);
494 ASSERT_TRUE(db().Open(db_path()));
496 // page_size should match the indicated value.
497 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
498 ASSERT_TRUE(s.Step());
499 ASSERT_EQ(kPageSize, s.ColumnInt(0));
501 // After raze, page_size should still match the indicated value.
502 ASSERT_TRUE(db().Raze());
503 s.Reset(true);
504 ASSERT_TRUE(s.Step());
505 ASSERT_EQ(kPageSize, s.ColumnInt(0));
508 // Test that Raze() results are seen in other connections.
509 TEST_F(SQLConnectionTest, RazeMultiple) {
510 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
511 ASSERT_TRUE(db().Execute(kCreateSql));
513 sql::Connection other_db;
514 ASSERT_TRUE(other_db.Open(db_path()));
516 // Check that the second connection sees the table.
517 ASSERT_EQ(1, SqliteMasterCount(&other_db));
519 ASSERT_TRUE(db().Raze());
521 // The second connection sees the updated database.
522 ASSERT_EQ(0, SqliteMasterCount(&other_db));
525 // TODO(erg): Enable this in the next patch once I add locking.
526 #if !defined(MOJO_APPTEST_IMPL)
527 TEST_F(SQLConnectionTest, RazeLocked) {
528 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
529 ASSERT_TRUE(db().Execute(kCreateSql));
531 // Open a transaction and write some data in a second connection.
532 // This will acquire a PENDING or EXCLUSIVE transaction, which will
533 // cause the raze to fail.
534 sql::Connection other_db;
535 ASSERT_TRUE(other_db.Open(db_path()));
536 ASSERT_TRUE(other_db.BeginTransaction());
537 const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')";
538 ASSERT_TRUE(other_db.Execute(kInsertSql));
540 ASSERT_FALSE(db().Raze());
542 // Works after COMMIT.
543 ASSERT_TRUE(other_db.CommitTransaction());
544 ASSERT_TRUE(db().Raze());
546 // Re-create the database.
547 ASSERT_TRUE(db().Execute(kCreateSql));
548 ASSERT_TRUE(db().Execute(kInsertSql));
550 // An unfinished read transaction in the other connection also
551 // blocks raze.
552 const char *kQuery = "SELECT COUNT(*) FROM foo";
553 sql::Statement s(other_db.GetUniqueStatement(kQuery));
554 ASSERT_TRUE(s.Step());
555 ASSERT_FALSE(db().Raze());
557 // Complete the statement unlocks the database.
558 ASSERT_FALSE(s.Step());
559 ASSERT_TRUE(db().Raze());
561 #endif
563 // Verify that Raze() can handle an empty file. SQLite should treat
564 // this as an empty database.
565 TEST_F(SQLConnectionTest, RazeEmptyDB) {
566 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
567 ASSERT_TRUE(db().Execute(kCreateSql));
568 db().Close();
570 TruncateDatabase();
572 ASSERT_TRUE(db().Open(db_path()));
573 ASSERT_TRUE(db().Raze());
574 EXPECT_EQ(0, SqliteMasterCount(&db()));
577 // Verify that Raze() can handle a file of junk.
578 TEST_F(SQLConnectionTest, RazeNOTADB) {
579 db().Close();
580 sql::Connection::Delete(db_path());
581 ASSERT_FALSE(GetPathExists(db_path()));
583 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE_AND_TRUNCATE);
584 ASSERT_TRUE(GetPathExists(db_path()));
586 // SQLite will successfully open the handle, but fail when running PRAGMA
587 // statements that access the database.
589 sql::ScopedErrorIgnorer ignore_errors;
591 // Earlier versions of Chromium compiled against SQLite 3.6.7.3, which
592 // returned SQLITE_IOERR_SHORT_READ in this case. Some platforms may still
593 // compile against an earlier SQLite via USE_SYSTEM_SQLITE.
594 if (ignore_errors.SQLiteLibVersionNumber() < 3008005) {
595 ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ);
596 } else {
597 ignore_errors.IgnoreError(SQLITE_NOTADB);
600 EXPECT_TRUE(db().Open(db_path()));
601 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
603 EXPECT_TRUE(db().Raze());
604 db().Close();
606 // Now empty, the open should open an empty database.
607 EXPECT_TRUE(db().Open(db_path()));
608 EXPECT_EQ(0, SqliteMasterCount(&db()));
611 // Verify that Raze() can handle a database overwritten with garbage.
612 TEST_F(SQLConnectionTest, RazeNOTADB2) {
613 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
614 ASSERT_TRUE(db().Execute(kCreateSql));
615 ASSERT_EQ(1, SqliteMasterCount(&db()));
616 db().Close();
618 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE);
620 // SQLite will successfully open the handle, but will fail with
621 // SQLITE_NOTADB on pragma statemenets which attempt to read the
622 // corrupted header.
624 sql::ScopedErrorIgnorer ignore_errors;
625 ignore_errors.IgnoreError(SQLITE_NOTADB);
626 EXPECT_TRUE(db().Open(db_path()));
627 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
629 EXPECT_TRUE(db().Raze());
630 db().Close();
632 // Now empty, the open should succeed with an empty database.
633 EXPECT_TRUE(db().Open(db_path()));
634 EXPECT_EQ(0, SqliteMasterCount(&db()));
637 // Test that a callback from Open() can raze the database. This is
638 // essential for cases where the Open() can fail entirely, so the
639 // Raze() cannot happen later. Additionally test that when the
640 // callback does this during Open(), the open is retried and succeeds.
641 TEST_F(SQLConnectionTest, RazeCallbackReopen) {
642 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
643 ASSERT_TRUE(db().Execute(kCreateSql));
644 ASSERT_EQ(1, SqliteMasterCount(&db()));
645 db().Close();
647 // Corrupt the database so that nothing works, including PRAGMAs.
648 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
650 // Open() will succeed, even though the PRAGMA calls within will
651 // fail with SQLITE_CORRUPT, as will this PRAGMA.
653 sql::ScopedErrorIgnorer ignore_errors;
654 ignore_errors.IgnoreError(SQLITE_CORRUPT);
655 ASSERT_TRUE(db().Open(db_path()));
656 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum"));
657 db().Close();
658 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
661 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback,
662 base::Unretained(this),
663 SQLITE_CORRUPT));
665 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error
666 // callback will call RazeAndClose(). Open() will then fail and be
667 // retried. The second Open() on the empty database will succeed
668 // cleanly.
669 ASSERT_TRUE(db().Open(db_path()));
670 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum"));
671 EXPECT_EQ(0, SqliteMasterCount(&db()));
674 // Basic test of RazeAndClose() operation.
675 TEST_F(SQLConnectionTest, RazeAndClose) {
676 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
677 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
679 // Test that RazeAndClose() closes the database, and that the
680 // database is empty when re-opened.
681 ASSERT_TRUE(db().Execute(kCreateSql));
682 ASSERT_TRUE(db().Execute(kPopulateSql));
683 ASSERT_TRUE(db().RazeAndClose());
684 ASSERT_FALSE(db().is_open());
685 db().Close();
686 ASSERT_TRUE(db().Open(db_path()));
687 ASSERT_EQ(0, SqliteMasterCount(&db()));
689 // Test that RazeAndClose() can break transactions.
690 ASSERT_TRUE(db().Execute(kCreateSql));
691 ASSERT_TRUE(db().Execute(kPopulateSql));
692 ASSERT_TRUE(db().BeginTransaction());
693 ASSERT_TRUE(db().RazeAndClose());
694 ASSERT_FALSE(db().is_open());
695 ASSERT_FALSE(db().CommitTransaction());
696 db().Close();
697 ASSERT_TRUE(db().Open(db_path()));
698 ASSERT_EQ(0, SqliteMasterCount(&db()));
701 // Test that various operations fail without crashing after
702 // RazeAndClose().
703 TEST_F(SQLConnectionTest, RazeAndCloseDiagnostics) {
704 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
705 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
706 const char* kSimpleSql = "SELECT 1";
708 ASSERT_TRUE(db().Execute(kCreateSql));
709 ASSERT_TRUE(db().Execute(kPopulateSql));
711 // Test baseline expectations.
712 db().Preload();
713 ASSERT_TRUE(db().DoesTableExist("foo"));
714 ASSERT_TRUE(db().IsSQLValid(kSimpleSql));
715 ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql));
716 ASSERT_TRUE(db().Execute(kSimpleSql));
717 ASSERT_TRUE(db().is_open());
719 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
720 ASSERT_TRUE(s.Step());
723 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
724 ASSERT_TRUE(s.Step());
726 ASSERT_TRUE(db().BeginTransaction());
727 ASSERT_TRUE(db().CommitTransaction());
728 ASSERT_TRUE(db().BeginTransaction());
729 db().RollbackTransaction();
731 ASSERT_TRUE(db().RazeAndClose());
733 // At this point, they should all fail, but not crash.
734 db().Preload();
735 ASSERT_FALSE(db().DoesTableExist("foo"));
736 ASSERT_FALSE(db().IsSQLValid(kSimpleSql));
737 ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql));
738 ASSERT_FALSE(db().Execute(kSimpleSql));
739 ASSERT_FALSE(db().is_open());
741 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
742 ASSERT_FALSE(s.Step());
745 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
746 ASSERT_FALSE(s.Step());
748 ASSERT_FALSE(db().BeginTransaction());
749 ASSERT_FALSE(db().CommitTransaction());
750 ASSERT_FALSE(db().BeginTransaction());
751 db().RollbackTransaction();
753 // Close normally to reset the poisoned flag.
754 db().Close();
756 // DEATH tests not supported on Android or iOS.
757 #if !defined(OS_ANDROID) && !defined(OS_IOS)
758 // Once the real Close() has been called, various calls enforce API
759 // usage by becoming fatal in debug mode. Since DEATH tests are
760 // expensive, just test one of them.
761 if (DLOG_IS_ON(FATAL)) {
762 ASSERT_DEATH({
763 db().IsSQLValid(kSimpleSql);
764 }, "Illegal use of connection without a db");
766 #endif
769 // TODO(shess): Spin up a background thread to hold other_db, to more
770 // closely match real life. That would also allow testing
771 // RazeWithTimeout().
773 #if defined(OS_ANDROID)
774 TEST_F(SQLConnectionTest, SetTempDirForSQL) {
776 sql::MetaTable meta_table;
777 // Below call needs a temporary directory in sqlite3
778 // On Android, it can pass only when the temporary directory is set.
779 // Otherwise, sqlite3 doesn't find the correct directory to store
780 // temporary files and will report the error 'unable to open
781 // database file'.
782 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
784 #endif
786 TEST_F(SQLConnectionTest, Delete) {
787 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
788 db().Close();
790 // Should have both a main database file and a journal file because
791 // of journal_mode TRUNCATE.
792 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
793 ASSERT_TRUE(GetPathExists(db_path()));
794 ASSERT_TRUE(GetPathExists(journal));
796 sql::Connection::Delete(db_path());
797 EXPECT_FALSE(GetPathExists(db_path()));
798 EXPECT_FALSE(GetPathExists(journal));
801 // This test manually sets on disk permissions; this doesn't apply to the mojo
802 // fork.
803 #if defined(OS_POSIX) && !defined(MOJO_APPTEST_IMPL)
804 // Test that set_restrict_to_user() trims database permissions so that
805 // only the owner (and root) can read.
806 TEST_F(SQLConnectionTest, UserPermission) {
807 // If the bots all had a restrictive umask setting such that
808 // databases are always created with only the owner able to read
809 // them, then the code could break without breaking the tests.
810 // Temporarily provide a more permissive umask.
811 db().Close();
812 sql::Connection::Delete(db_path());
813 ASSERT_FALSE(GetPathExists(db_path()));
814 ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH);
815 ASSERT_TRUE(db().Open(db_path()));
817 // Cause the journal file to be created. If the default
818 // journal_mode is changed back to DELETE, then parts of this test
819 // will need to be updated.
820 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
822 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
823 int mode;
825 // Given a permissive umask, the database is created with permissive
826 // read access for the database and journal.
827 ASSERT_TRUE(GetPathExists(db_path()));
828 ASSERT_TRUE(GetPathExists(journal));
829 mode = base::FILE_PERMISSION_MASK;
830 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
831 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
832 mode = base::FILE_PERMISSION_MASK;
833 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
834 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
836 // Re-open with restricted permissions and verify that the modes
837 // changed for both the main database and the journal.
838 db().Close();
839 db().set_restrict_to_user();
840 ASSERT_TRUE(db().Open(db_path()));
841 ASSERT_TRUE(GetPathExists(db_path()));
842 ASSERT_TRUE(GetPathExists(journal));
843 mode = base::FILE_PERMISSION_MASK;
844 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
845 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
846 mode = base::FILE_PERMISSION_MASK;
847 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
848 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
850 // Delete and re-create the database, the restriction should still apply.
851 db().Close();
852 sql::Connection::Delete(db_path());
853 ASSERT_TRUE(db().Open(db_path()));
854 ASSERT_TRUE(GetPathExists(db_path()));
855 ASSERT_FALSE(GetPathExists(journal));
856 mode = base::FILE_PERMISSION_MASK;
857 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
858 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
860 // Verify that journal creation inherits the restriction.
861 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
862 ASSERT_TRUE(GetPathExists(journal));
863 mode = base::FILE_PERMISSION_MASK;
864 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
865 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
867 #endif // defined(OS_POSIX)
869 // Test that errors start happening once Poison() is called.
870 TEST_F(SQLConnectionTest, Poison) {
871 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
873 // Before the Poison() call, things generally work.
874 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
875 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
877 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
878 ASSERT_TRUE(s.is_valid());
879 ASSERT_TRUE(s.Step());
882 // Get a statement which is valid before and will exist across Poison().
883 sql::Statement valid_statement(
884 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master"));
885 ASSERT_TRUE(valid_statement.is_valid());
886 ASSERT_TRUE(valid_statement.Step());
887 valid_statement.Reset(true);
889 db().Poison();
891 // After the Poison() call, things fail.
892 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
893 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')"));
895 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
896 ASSERT_FALSE(s.is_valid());
897 ASSERT_FALSE(s.Step());
900 // The existing statement has become invalid.
901 ASSERT_FALSE(valid_statement.is_valid());
902 ASSERT_FALSE(valid_statement.Step());
905 // Test attaching and detaching databases from the connection.
906 TEST_F(SQLConnectionTest, Attach) {
907 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
909 // Create a database to attach to.
910 base::FilePath attach_path =
911 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
912 const char kAttachmentPoint[] = "other";
914 sql::Connection other_db;
915 ASSERT_TRUE(other_db.Open(attach_path));
916 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
917 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
920 // Cannot see the attached database, yet.
921 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
923 // Attach fails in a transaction.
924 EXPECT_TRUE(db().BeginTransaction());
926 sql::ScopedErrorIgnorer ignore_errors;
927 ignore_errors.IgnoreError(SQLITE_ERROR);
928 EXPECT_FALSE(db().AttachDatabase(attach_path, kAttachmentPoint));
929 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
932 // Attach succeeds when the transaction is closed.
933 db().RollbackTransaction();
934 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
935 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
937 // Queries can touch both databases.
938 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
940 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
941 ASSERT_TRUE(s.Step());
942 EXPECT_EQ(1, s.ColumnInt(0));
945 // Detach also fails in a transaction.
946 EXPECT_TRUE(db().BeginTransaction());
948 sql::ScopedErrorIgnorer ignore_errors;
949 ignore_errors.IgnoreError(SQLITE_ERROR);
950 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint));
951 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
952 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
955 // Detach succeeds outside of a transaction.
956 db().RollbackTransaction();
957 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
959 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
962 TEST_F(SQLConnectionTest, Basic_QuickIntegrityCheck) {
963 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
964 ASSERT_TRUE(db().Execute(kCreateSql));
965 EXPECT_TRUE(db().QuickIntegrityCheck());
966 db().Close();
968 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
971 sql::ScopedErrorIgnorer ignore_errors;
972 ignore_errors.IgnoreError(SQLITE_CORRUPT);
973 ASSERT_TRUE(db().Open(db_path()));
974 EXPECT_FALSE(db().QuickIntegrityCheck());
975 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
979 TEST_F(SQLConnectionTest, Basic_FullIntegrityCheck) {
980 const std::string kOk("ok");
981 std::vector<std::string> messages;
983 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
984 ASSERT_TRUE(db().Execute(kCreateSql));
985 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
986 EXPECT_EQ(1u, messages.size());
987 EXPECT_EQ(kOk, messages[0]);
988 db().Close();
990 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
993 sql::ScopedErrorIgnorer ignore_errors;
994 ignore_errors.IgnoreError(SQLITE_CORRUPT);
995 ASSERT_TRUE(db().Open(db_path()));
996 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
997 EXPECT_LT(1u, messages.size());
998 EXPECT_NE(kOk, messages[0]);
999 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
1002 // TODO(shess): CorruptTableOrIndex could be used to produce a
1003 // file that would pass the quick check and fail the full check.
1006 // Test Sqlite.Stats histogram for execute-oriented calls.
1007 TEST_F(SQLConnectionTest, EventsExecute) {
1008 // Re-open with histogram tag.
1009 db().Close();
1010 db().set_histogram_tag("Test");
1011 ASSERT_TRUE(db().Open(db_path()));
1013 // Open() uses Execute() extensively, don't track those calls.
1014 base::HistogramTester tester;
1016 const char kHistogramName[] = "Sqlite.Stats.Test";
1017 const char kGlobalHistogramName[] = "Sqlite.Stats";
1019 ASSERT_TRUE(db().BeginTransaction());
1020 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1021 EXPECT_TRUE(db().Execute(kCreateSql));
1022 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1023 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1024 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1025 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (13, 'text')"));
1026 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (14, 'text')"));
1027 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (15, 'text');"
1028 "INSERT INTO foo VALUES (16, 'text');"
1029 "INSERT INTO foo VALUES (17, 'text');"
1030 "INSERT INTO foo VALUES (18, 'text');"
1031 "INSERT INTO foo VALUES (19, 'text')"));
1032 ASSERT_TRUE(db().CommitTransaction());
1033 ASSERT_TRUE(db().BeginTransaction());
1034 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1035 db().RollbackTransaction();
1036 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1037 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (21, 'text')"));
1039 // The create, 5 inserts, multi-statement insert, rolled-back insert, 2
1040 // inserts outside transaction.
1041 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_EXECUTE, 10);
1042 tester.ExpectBucketCount(kGlobalHistogramName,
1043 sql::Connection::EVENT_EXECUTE, 10);
1045 // All of the executes, with the multi-statement inserts broken out, plus one
1046 // for each begin, commit, and rollback.
1047 tester.ExpectBucketCount(kHistogramName,
1048 sql::Connection::EVENT_STATEMENT_RUN, 18);
1049 tester.ExpectBucketCount(kGlobalHistogramName,
1050 sql::Connection::EVENT_STATEMENT_RUN, 18);
1052 tester.ExpectBucketCount(kHistogramName,
1053 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1054 tester.ExpectBucketCount(kGlobalHistogramName,
1055 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1056 tester.ExpectBucketCount(kHistogramName,
1057 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1058 tester.ExpectBucketCount(kGlobalHistogramName,
1059 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1061 // The 2 inserts outside the transaction.
1062 tester.ExpectBucketCount(kHistogramName,
1063 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1064 tester.ExpectBucketCount(kGlobalHistogramName,
1065 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1067 // 11 inserts inside transactions.
1068 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_CHANGES, 11);
1069 tester.ExpectBucketCount(kGlobalHistogramName,
1070 sql::Connection::EVENT_CHANGES, 11);
1072 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_BEGIN, 2);
1073 tester.ExpectBucketCount(kGlobalHistogramName,
1074 sql::Connection::EVENT_BEGIN, 2);
1075 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_COMMIT, 1);
1076 tester.ExpectBucketCount(kGlobalHistogramName,
1077 sql::Connection::EVENT_COMMIT, 1);
1078 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_ROLLBACK, 1);
1079 tester.ExpectBucketCount(kGlobalHistogramName,
1080 sql::Connection::EVENT_ROLLBACK, 1);
1083 // Test Sqlite.Stats histogram for prepared statements.
1084 TEST_F(SQLConnectionTest, EventsStatement) {
1085 // Re-open with histogram tag.
1086 db().Close();
1087 db().set_histogram_tag("Test");
1088 ASSERT_TRUE(db().Open(db_path()));
1090 const char kHistogramName[] = "Sqlite.Stats.Test";
1091 const char kGlobalHistogramName[] = "Sqlite.Stats";
1093 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1094 EXPECT_TRUE(db().Execute(kCreateSql));
1095 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1096 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1097 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1100 base::HistogramTester tester;
1103 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo"));
1104 while (s.Step()) {
1108 tester.ExpectBucketCount(kHistogramName,
1109 sql::Connection::EVENT_STATEMENT_RUN, 1);
1110 tester.ExpectBucketCount(kGlobalHistogramName,
1111 sql::Connection::EVENT_STATEMENT_RUN, 1);
1112 tester.ExpectBucketCount(kHistogramName,
1113 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1114 tester.ExpectBucketCount(kGlobalHistogramName,
1115 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1116 tester.ExpectBucketCount(kHistogramName,
1117 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1118 tester.ExpectBucketCount(kGlobalHistogramName,
1119 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1123 base::HistogramTester tester;
1126 sql::Statement s(db().GetUniqueStatement(
1127 "SELECT value FROM foo WHERE id > 10"));
1128 while (s.Step()) {
1132 tester.ExpectBucketCount(kHistogramName,
1133 sql::Connection::EVENT_STATEMENT_RUN, 1);
1134 tester.ExpectBucketCount(kGlobalHistogramName,
1135 sql::Connection::EVENT_STATEMENT_RUN, 1);
1136 tester.ExpectBucketCount(kHistogramName,
1137 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1138 tester.ExpectBucketCount(kGlobalHistogramName,
1139 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1140 tester.ExpectBucketCount(kHistogramName,
1141 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1142 tester.ExpectBucketCount(kGlobalHistogramName,
1143 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1147 // SQLite function to adjust mock time by |argv[0]| milliseconds.
1148 void sqlite_adjust_millis(sql::test::ScopedMockTimeSource* time_mock,
1149 sqlite3_context* context,
1150 int argc, sqlite3_value** argv) {
1151 int64 milliseconds = argc > 0 ? sqlite3_value_int64(argv[0]) : 1000;
1152 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
1153 sqlite3_result_int64(context, milliseconds);
1156 // Adjust mock time by |milliseconds| on commit.
1157 int adjust_commit_hook(sql::test::ScopedMockTimeSource* time_mock,
1158 int64 milliseconds) {
1159 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
1160 return SQLITE_OK;
1163 const char kCommitTime[] = "Sqlite.CommitTime.Test";
1164 const char kAutoCommitTime[] = "Sqlite.AutoCommitTime.Test";
1165 const char kUpdateTime[] = "Sqlite.UpdateTime.Test";
1166 const char kQueryTime[] = "Sqlite.QueryTime.Test";
1168 // Read-only query allocates time to QueryTime, but not others.
1169 TEST_F(SQLConnectionTest, TimeQuery) {
1170 // Re-open with histogram tag. Use an in-memory database to minimize variance
1171 // due to filesystem.
1172 db().Close();
1173 db().set_histogram_tag("Test");
1174 ASSERT_TRUE(db().OpenInMemory());
1176 sql::test::ScopedMockTimeSource time_mock(db());
1178 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1179 EXPECT_TRUE(db().Execute(kCreateSql));
1181 // Function to inject pauses into statements.
1182 sql::test::ScopedScalarFunction scoper(
1183 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1185 base::HistogramTester tester;
1187 EXPECT_TRUE(db().Execute("SELECT milliadjust(10)"));
1189 scoped_ptr<base::HistogramSamples> samples(
1190 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1191 ASSERT_TRUE(samples);
1192 // 10 for the adjust, 1 for the measurement.
1193 EXPECT_EQ(11, samples->sum());
1195 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1196 EXPECT_EQ(0, samples->sum());
1198 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1199 EXPECT_EQ(0, samples->sum());
1201 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1202 EXPECT_EQ(0, samples->sum());
1205 // Autocommit update allocates time to QueryTime, UpdateTime, and
1206 // AutoCommitTime.
1207 TEST_F(SQLConnectionTest, TimeUpdateAutocommit) {
1208 // Re-open with histogram tag. Use an in-memory database to minimize variance
1209 // due to filesystem.
1210 db().Close();
1211 db().set_histogram_tag("Test");
1212 ASSERT_TRUE(db().OpenInMemory());
1214 sql::test::ScopedMockTimeSource time_mock(db());
1216 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1217 EXPECT_TRUE(db().Execute(kCreateSql));
1219 // Function to inject pauses into statements.
1220 sql::test::ScopedScalarFunction scoper(
1221 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1223 base::HistogramTester tester;
1225 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, milliadjust(10))"));
1227 scoped_ptr<base::HistogramSamples> samples(
1228 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1229 ASSERT_TRUE(samples);
1230 // 10 for the adjust, 1 for the measurement.
1231 EXPECT_EQ(11, samples->sum());
1233 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1234 ASSERT_TRUE(samples);
1235 // 10 for the adjust, 1 for the measurement.
1236 EXPECT_EQ(11, samples->sum());
1238 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1239 EXPECT_EQ(0, samples->sum());
1241 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1242 ASSERT_TRUE(samples);
1243 // 10 for the adjust, 1 for the measurement.
1244 EXPECT_EQ(11, samples->sum());
1247 // Update with explicit transaction allocates time to QueryTime, UpdateTime, and
1248 // CommitTime.
1249 TEST_F(SQLConnectionTest, TimeUpdateTransaction) {
1250 // Re-open with histogram tag. Use an in-memory database to minimize variance
1251 // due to filesystem.
1252 db().Close();
1253 db().set_histogram_tag("Test");
1254 ASSERT_TRUE(db().OpenInMemory());
1256 sql::test::ScopedMockTimeSource time_mock(db());
1258 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1259 EXPECT_TRUE(db().Execute(kCreateSql));
1261 // Function to inject pauses into statements.
1262 sql::test::ScopedScalarFunction scoper(
1263 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1265 base::HistogramTester tester;
1268 // Make the commit slow.
1269 sql::test::ScopedCommitHook scoped_hook(
1270 db(), base::Bind(adjust_commit_hook, &time_mock, 100));
1271 ASSERT_TRUE(db().BeginTransaction());
1272 EXPECT_TRUE(db().Execute(
1273 "INSERT INTO foo VALUES (11, milliadjust(10))"));
1274 EXPECT_TRUE(db().Execute(
1275 "UPDATE foo SET value = milliadjust(10) WHERE id = 11"));
1276 EXPECT_TRUE(db().CommitTransaction());
1279 scoped_ptr<base::HistogramSamples> samples(
1280 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1281 ASSERT_TRUE(samples);
1282 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1283 // measuring each of BEGIN, INSERT, UPDATE, and COMMIT.
1284 EXPECT_EQ(124, samples->sum());
1286 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1287 ASSERT_TRUE(samples);
1288 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1289 // measuring each of INSERT, UPDATE, and COMMIT.
1290 EXPECT_EQ(123, samples->sum());
1292 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1293 ASSERT_TRUE(samples);
1294 // 100 for commit adjust, 1 for measuring COMMIT.
1295 EXPECT_EQ(101, samples->sum());
1297 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1298 EXPECT_EQ(0, samples->sum());
1301 } // namespace