Roll src/third_party/WebKit 88cc93e:f6ae725 (svn 200125:200141)
[chromium-blink-merge.git] / sql / connection_unittest.cc
blobdf35dd10d08233effde856ce9608d24fed37541f
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/proxy.h"
16 #include "sql/statement.h"
17 #include "sql/test/error_callback_support.h"
18 #include "sql/test/scoped_error_ignorer.h"
19 #include "sql/test/test_helpers.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/sqlite/sqlite3.h"
23 namespace sql {
24 namespace test {
26 // Replaces the database time source with an object that steps forward 1ms on
27 // each check, and which can be jumped forward an arbitrary amount of time
28 // programmatically.
29 class ScopedMockTimeSource {
30 public:
31 ScopedMockTimeSource(Connection& db)
32 : db_(db),
33 delta_(base::TimeDelta::FromMilliseconds(1)) {
34 // Save the current source and replace it.
35 save_.swap(db_.clock_);
36 db_.clock_.reset(new MockTimeSource(*this));
38 ~ScopedMockTimeSource() {
39 // Put original source back.
40 db_.clock_.swap(save_);
43 void adjust(const base::TimeDelta& delta) {
44 current_time_ += delta;
47 private:
48 class MockTimeSource : public TimeSource {
49 public:
50 MockTimeSource(ScopedMockTimeSource& owner)
51 : owner_(owner) {
53 ~MockTimeSource() override {}
55 base::TimeTicks Now() override {
56 base::TimeTicks ret(owner_.current_time_);
57 owner_.current_time_ += owner_.delta_;
58 return ret;
61 private:
62 ScopedMockTimeSource& owner_;
63 DISALLOW_COPY_AND_ASSIGN(MockTimeSource);
66 Connection& db_;
68 // Saves original source from |db_|.
69 scoped_ptr<TimeSource> save_;
71 // Current time returned by mock.
72 base::TimeTicks current_time_;
74 // How far to jump on each Now() call.
75 base::TimeDelta delta_;
77 DISALLOW_COPY_AND_ASSIGN(ScopedMockTimeSource);
80 // Allow a test to add a SQLite function in a scoped context.
81 class ScopedScalarFunction {
82 public:
83 ScopedScalarFunction(
84 sql::Connection& db,
85 const char* function_name,
86 int args,
87 base::Callback<void(sqlite3_context*,int,sqlite3_value**)> cb)
88 : db_(db.db_), function_name_(function_name), cb_(cb) {
89 sql::sqlite3_create_function_v2(db_, function_name, args, SQLITE_UTF8,
90 this, &Run, NULL, NULL, NULL);
92 ~ScopedScalarFunction() {
93 sql::sqlite3_create_function_v2(db_, function_name_, 0, SQLITE_UTF8,
94 NULL, NULL, NULL, NULL, NULL);
97 private:
98 static void Run(sqlite3_context* context, int argc, sqlite3_value** argv) {
99 ScopedScalarFunction* t = static_cast<ScopedScalarFunction*>(
100 sqlite3_user_data(context));
101 t->cb_.Run(context, argc, argv);
104 sqlite3* db_;
105 const char* function_name_;
106 base::Callback<void(sqlite3_context*,int,sqlite3_value**)> cb_;
108 DISALLOW_COPY_AND_ASSIGN(ScopedScalarFunction);
111 // Allow a test to add a SQLite commit hook in a scoped context.
112 class ScopedCommitHook {
113 public:
114 ScopedCommitHook(sql::Connection& db,
115 base::Callback<int(void)> cb)
116 : db_(db.db_),
117 cb_(cb) {
118 sql::sqlite3_commit_hook(db_, &Run, this);
120 ~ScopedCommitHook() {
121 sql::sqlite3_commit_hook(db_, NULL, NULL);
124 private:
125 static int Run(void* p) {
126 ScopedCommitHook* t = static_cast<ScopedCommitHook*>(p);
127 return t->cb_.Run();
130 sqlite3* db_;
131 base::Callback<int(void)> cb_;
133 DISALLOW_COPY_AND_ASSIGN(ScopedCommitHook);
136 } // namespace test
137 } // namespace sql
139 namespace {
141 // Helper to return the count of items in sqlite_master. Return -1 in
142 // case of error.
143 int SqliteMasterCount(sql::Connection* db) {
144 const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master";
145 sql::Statement s(db->GetUniqueStatement(kMasterCount));
146 return s.Step() ? s.ColumnInt(0) : -1;
149 // Track the number of valid references which share the same pointer.
150 // This is used to allow testing an implicitly use-after-free case by
151 // explicitly having the ref count live longer than the object.
152 class RefCounter {
153 public:
154 RefCounter(size_t* counter)
155 : counter_(counter) {
156 (*counter_)++;
158 RefCounter(const RefCounter& other)
159 : counter_(other.counter_) {
160 (*counter_)++;
162 ~RefCounter() {
163 (*counter_)--;
166 private:
167 size_t* counter_;
169 DISALLOW_ASSIGN(RefCounter);
172 // Empty callback for implementation of ErrorCallbackSetHelper().
173 void IgnoreErrorCallback(int error, sql::Statement* stmt) {
176 void ErrorCallbackSetHelper(sql::Connection* db,
177 size_t* counter,
178 const RefCounter& r,
179 int error, sql::Statement* stmt) {
180 // The ref count should not go to zero when changing the callback.
181 EXPECT_GT(*counter, 0u);
182 db->set_error_callback(base::Bind(&IgnoreErrorCallback));
183 EXPECT_GT(*counter, 0u);
186 void ErrorCallbackResetHelper(sql::Connection* db,
187 size_t* counter,
188 const RefCounter& r,
189 int error, sql::Statement* stmt) {
190 // The ref count should not go to zero when clearing the callback.
191 EXPECT_GT(*counter, 0u);
192 db->reset_error_callback();
193 EXPECT_GT(*counter, 0u);
196 #if defined(OS_POSIX)
197 // Set a umask and restore the old mask on destruction. Cribbed from
198 // shared_memory_unittest.cc. Used by POSIX-only UserPermission test.
199 class ScopedUmaskSetter {
200 public:
201 explicit ScopedUmaskSetter(mode_t target_mask) {
202 old_umask_ = umask(target_mask);
204 ~ScopedUmaskSetter() { umask(old_umask_); }
205 private:
206 mode_t old_umask_;
207 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
209 #endif
211 class SQLConnectionTest : public sql::SQLTestBase {
212 public:
213 void SetUp() override {
214 // Any macro histograms which fire before the recorder is initialized cannot
215 // be tested. So this needs to be ahead of Open().
216 base::StatisticsRecorder::Initialize();
218 SQLTestBase::SetUp();
221 // Handle errors by blowing away the database.
222 void RazeErrorCallback(int expected_error, int error, sql::Statement* stmt) {
223 EXPECT_EQ(expected_error, error);
224 db().RazeAndClose();
228 TEST_F(SQLConnectionTest, Execute) {
229 // Valid statement should return true.
230 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
231 EXPECT_EQ(SQLITE_OK, db().GetErrorCode());
233 // Invalid statement should fail.
234 ASSERT_EQ(SQLITE_ERROR,
235 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b"));
236 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode());
239 TEST_F(SQLConnectionTest, ExecuteWithErrorCode) {
240 ASSERT_EQ(SQLITE_OK,
241 db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)"));
242 ASSERT_EQ(SQLITE_ERROR,
243 db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE"));
244 ASSERT_EQ(SQLITE_ERROR,
245 db().ExecuteAndReturnErrorCode(
246 "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)"));
249 TEST_F(SQLConnectionTest, CachedStatement) {
250 sql::StatementID id1("foo", 12);
252 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
253 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
255 // Create a new cached statement.
257 sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo"));
258 ASSERT_TRUE(s.is_valid());
260 ASSERT_TRUE(s.Step());
261 EXPECT_EQ(12, s.ColumnInt(0));
264 // The statement should be cached still.
265 EXPECT_TRUE(db().HasCachedStatement(id1));
268 // Get the same statement using different SQL. This should ignore our
269 // SQL and use the cached one (so it will be valid).
270 sql::Statement s(db().GetCachedStatement(id1, "something invalid("));
271 ASSERT_TRUE(s.is_valid());
273 ASSERT_TRUE(s.Step());
274 EXPECT_EQ(12, s.ColumnInt(0));
277 // Make sure other statements aren't marked as cached.
278 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE));
281 TEST_F(SQLConnectionTest, IsSQLValidTest) {
282 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
283 ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo"));
284 ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo"));
287 TEST_F(SQLConnectionTest, DoesStuffExist) {
288 // Test DoesTableExist.
289 EXPECT_FALSE(db().DoesTableExist("foo"));
290 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
291 ASSERT_TRUE(db().Execute("CREATE INDEX foo_a ON foo (a)"));
292 EXPECT_TRUE(db().DoesTableExist("foo"));
293 EXPECT_TRUE(db().DoesIndexExist("foo_a"));
295 // Test DoesColumnExist.
296 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
297 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
299 // Testing for a column on a nonexistent table.
300 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
302 // Names are not case sensitive.
303 EXPECT_TRUE(db().DoesTableExist("FOO"));
304 EXPECT_TRUE(db().DoesColumnExist("FOO", "A"));
307 TEST_F(SQLConnectionTest, GetLastInsertRowId) {
308 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
310 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
312 // Last insert row ID should be valid.
313 int64_t row = db().GetLastInsertRowId();
314 EXPECT_LT(0, row);
316 // It should be the primary key of the row we just inserted.
317 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
318 s.BindInt64(0, row);
319 ASSERT_TRUE(s.Step());
320 EXPECT_EQ(12, s.ColumnInt(0));
323 TEST_F(SQLConnectionTest, Rollback) {
324 ASSERT_TRUE(db().BeginTransaction());
325 ASSERT_TRUE(db().BeginTransaction());
326 EXPECT_EQ(2, db().transaction_nesting());
327 db().RollbackTransaction();
328 EXPECT_FALSE(db().CommitTransaction());
329 EXPECT_TRUE(db().BeginTransaction());
332 // Test the scoped error ignorer by attempting to insert a duplicate
333 // value into an index.
334 TEST_F(SQLConnectionTest, ScopedIgnoreError) {
335 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
336 ASSERT_TRUE(db().Execute(kCreateSql));
337 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
340 sql::ScopedErrorIgnorer ignore_errors;
341 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
342 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
343 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
347 // Test that clients of GetUntrackedStatement() can test corruption-handling
348 // with ScopedErrorIgnorer.
349 TEST_F(SQLConnectionTest, ScopedIgnoreUntracked) {
350 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
351 ASSERT_TRUE(db().Execute(kCreateSql));
352 ASSERT_FALSE(db().DoesTableExist("bar"));
353 ASSERT_TRUE(db().DoesTableExist("foo"));
354 ASSERT_TRUE(db().DoesColumnExist("foo", "id"));
355 db().Close();
357 // Corrupt the database so that nothing works, including PRAGMAs.
358 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
361 sql::ScopedErrorIgnorer ignore_errors;
362 ignore_errors.IgnoreError(SQLITE_CORRUPT);
363 ASSERT_TRUE(db().Open(db_path()));
364 ASSERT_FALSE(db().DoesTableExist("bar"));
365 ASSERT_FALSE(db().DoesTableExist("foo"));
366 ASSERT_FALSE(db().DoesColumnExist("foo", "id"));
367 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
371 TEST_F(SQLConnectionTest, ErrorCallback) {
372 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
373 ASSERT_TRUE(db().Execute(kCreateSql));
374 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
376 int error = SQLITE_OK;
378 sql::ScopedErrorCallback sec(
379 &db(), base::Bind(&sql::CaptureErrorCallback, &error));
380 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
382 // Later versions of SQLite throw SQLITE_CONSTRAINT_UNIQUE. The specific
383 // sub-error isn't really important.
384 EXPECT_EQ(SQLITE_CONSTRAINT, (error&0xff));
387 // Callback is no longer in force due to reset.
389 error = SQLITE_OK;
390 sql::ScopedErrorIgnorer ignore_errors;
391 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
392 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
393 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
394 EXPECT_EQ(SQLITE_OK, error);
397 // base::Bind() can curry arguments to be passed by const reference
398 // to the callback function. If the callback function calls
399 // re/set_error_callback(), the storage for those arguments can be
400 // deleted while the callback function is still executing.
402 // RefCounter() counts how many objects are live using an external
403 // count. The same counter is passed to the callback, so that it
404 // can check directly even if the RefCounter object is no longer
405 // live.
407 size_t count = 0;
408 sql::ScopedErrorCallback sec(
409 &db(), base::Bind(&ErrorCallbackSetHelper,
410 &db(), &count, RefCounter(&count)));
412 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
415 // Same test, but reset_error_callback() case.
417 size_t count = 0;
418 sql::ScopedErrorCallback sec(
419 &db(), base::Bind(&ErrorCallbackResetHelper,
420 &db(), &count, RefCounter(&count)));
422 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
426 // Test that sql::Connection::Raze() results in a database without the
427 // tables from the original database.
428 TEST_F(SQLConnectionTest, Raze) {
429 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
430 ASSERT_TRUE(db().Execute(kCreateSql));
431 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
433 int pragma_auto_vacuum = 0;
435 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
436 ASSERT_TRUE(s.Step());
437 pragma_auto_vacuum = s.ColumnInt(0);
438 ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1);
441 // If auto_vacuum is set, there's an extra page to maintain a freelist.
442 const int kExpectedPageCount = 2 + pragma_auto_vacuum;
445 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
446 ASSERT_TRUE(s.Step());
447 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0));
451 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master"));
452 ASSERT_TRUE(s.Step());
453 EXPECT_EQ("table", s.ColumnString(0));
454 EXPECT_EQ("foo", s.ColumnString(1));
455 EXPECT_EQ("foo", s.ColumnString(2));
456 // Table "foo" is stored in the last page of the file.
457 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3));
458 EXPECT_EQ(kCreateSql, s.ColumnString(4));
461 ASSERT_TRUE(db().Raze());
464 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
465 ASSERT_TRUE(s.Step());
466 EXPECT_EQ(1, s.ColumnInt(0));
469 ASSERT_EQ(0, SqliteMasterCount(&db()));
472 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
473 ASSERT_TRUE(s.Step());
474 // The new database has the same auto_vacuum as a fresh database.
475 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0));
479 // Test that Raze() maintains page_size.
480 TEST_F(SQLConnectionTest, RazePageSize) {
481 // Fetch the default page size and double it for use in this test.
482 // Scoped to release statement before Close().
483 int default_page_size = 0;
485 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
486 ASSERT_TRUE(s.Step());
487 default_page_size = s.ColumnInt(0);
489 ASSERT_GT(default_page_size, 0);
490 const int kPageSize = 2 * default_page_size;
492 // Re-open the database to allow setting the page size.
493 db().Close();
494 db().set_page_size(kPageSize);
495 ASSERT_TRUE(db().Open(db_path()));
497 // page_size should match the indicated value.
498 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
499 ASSERT_TRUE(s.Step());
500 ASSERT_EQ(kPageSize, s.ColumnInt(0));
502 // After raze, page_size should still match the indicated value.
503 ASSERT_TRUE(db().Raze());
504 s.Reset(true);
505 ASSERT_TRUE(s.Step());
506 ASSERT_EQ(kPageSize, s.ColumnInt(0));
509 // Test that Raze() results are seen in other connections.
510 TEST_F(SQLConnectionTest, RazeMultiple) {
511 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
512 ASSERT_TRUE(db().Execute(kCreateSql));
514 sql::Connection other_db;
515 ASSERT_TRUE(other_db.Open(db_path()));
517 // Check that the second connection sees the table.
518 ASSERT_EQ(1, SqliteMasterCount(&other_db));
520 ASSERT_TRUE(db().Raze());
522 // The second connection sees the updated database.
523 ASSERT_EQ(0, SqliteMasterCount(&other_db));
526 // TODO(erg): Enable this in the next patch once I add locking.
527 #if !defined(MOJO_APPTEST_IMPL)
528 TEST_F(SQLConnectionTest, RazeLocked) {
529 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
530 ASSERT_TRUE(db().Execute(kCreateSql));
532 // Open a transaction and write some data in a second connection.
533 // This will acquire a PENDING or EXCLUSIVE transaction, which will
534 // cause the raze to fail.
535 sql::Connection other_db;
536 ASSERT_TRUE(other_db.Open(db_path()));
537 ASSERT_TRUE(other_db.BeginTransaction());
538 const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')";
539 ASSERT_TRUE(other_db.Execute(kInsertSql));
541 ASSERT_FALSE(db().Raze());
543 // Works after COMMIT.
544 ASSERT_TRUE(other_db.CommitTransaction());
545 ASSERT_TRUE(db().Raze());
547 // Re-create the database.
548 ASSERT_TRUE(db().Execute(kCreateSql));
549 ASSERT_TRUE(db().Execute(kInsertSql));
551 // An unfinished read transaction in the other connection also
552 // blocks raze.
553 const char *kQuery = "SELECT COUNT(*) FROM foo";
554 sql::Statement s(other_db.GetUniqueStatement(kQuery));
555 ASSERT_TRUE(s.Step());
556 ASSERT_FALSE(db().Raze());
558 // Complete the statement unlocks the database.
559 ASSERT_FALSE(s.Step());
560 ASSERT_TRUE(db().Raze());
562 #endif
564 // Verify that Raze() can handle an empty file. SQLite should treat
565 // this as an empty database.
566 TEST_F(SQLConnectionTest, RazeEmptyDB) {
567 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
568 ASSERT_TRUE(db().Execute(kCreateSql));
569 db().Close();
571 TruncateDatabase();
573 ASSERT_TRUE(db().Open(db_path()));
574 ASSERT_TRUE(db().Raze());
575 EXPECT_EQ(0, SqliteMasterCount(&db()));
578 // Verify that Raze() can handle a file of junk.
579 TEST_F(SQLConnectionTest, RazeNOTADB) {
580 db().Close();
581 sql::Connection::Delete(db_path());
582 ASSERT_FALSE(GetPathExists(db_path()));
584 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE_AND_TRUNCATE);
585 ASSERT_TRUE(GetPathExists(db_path()));
587 // SQLite will successfully open the handle, but fail when running PRAGMA
588 // statements that access the database.
590 sql::ScopedErrorIgnorer ignore_errors;
592 // Earlier versions of Chromium compiled against SQLite 3.6.7.3, which
593 // returned SQLITE_IOERR_SHORT_READ in this case. Some platforms may still
594 // compile against an earlier SQLite via USE_SYSTEM_SQLITE.
595 if (ignore_errors.SQLiteLibVersionNumber() < 3008005) {
596 ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ);
597 } else {
598 ignore_errors.IgnoreError(SQLITE_NOTADB);
601 EXPECT_TRUE(db().Open(db_path()));
602 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
604 EXPECT_TRUE(db().Raze());
605 db().Close();
607 // Now empty, the open should open an empty database.
608 EXPECT_TRUE(db().Open(db_path()));
609 EXPECT_EQ(0, SqliteMasterCount(&db()));
612 // Verify that Raze() can handle a database overwritten with garbage.
613 TEST_F(SQLConnectionTest, RazeNOTADB2) {
614 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
615 ASSERT_TRUE(db().Execute(kCreateSql));
616 ASSERT_EQ(1, SqliteMasterCount(&db()));
617 db().Close();
619 WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE);
621 // SQLite will successfully open the handle, but will fail with
622 // SQLITE_NOTADB on pragma statemenets which attempt to read the
623 // corrupted header.
625 sql::ScopedErrorIgnorer ignore_errors;
626 ignore_errors.IgnoreError(SQLITE_NOTADB);
627 EXPECT_TRUE(db().Open(db_path()));
628 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
630 EXPECT_TRUE(db().Raze());
631 db().Close();
633 // Now empty, the open should succeed with an empty database.
634 EXPECT_TRUE(db().Open(db_path()));
635 EXPECT_EQ(0, SqliteMasterCount(&db()));
638 // Test that a callback from Open() can raze the database. This is
639 // essential for cases where the Open() can fail entirely, so the
640 // Raze() cannot happen later. Additionally test that when the
641 // callback does this during Open(), the open is retried and succeeds.
642 TEST_F(SQLConnectionTest, RazeCallbackReopen) {
643 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
644 ASSERT_TRUE(db().Execute(kCreateSql));
645 ASSERT_EQ(1, SqliteMasterCount(&db()));
646 db().Close();
648 // Corrupt the database so that nothing works, including PRAGMAs.
649 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
651 // Open() will succeed, even though the PRAGMA calls within will
652 // fail with SQLITE_CORRUPT, as will this PRAGMA.
654 sql::ScopedErrorIgnorer ignore_errors;
655 ignore_errors.IgnoreError(SQLITE_CORRUPT);
656 ASSERT_TRUE(db().Open(db_path()));
657 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum"));
658 db().Close();
659 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
662 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback,
663 base::Unretained(this),
664 SQLITE_CORRUPT));
666 // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error
667 // callback will call RazeAndClose(). Open() will then fail and be
668 // retried. The second Open() on the empty database will succeed
669 // cleanly.
670 ASSERT_TRUE(db().Open(db_path()));
671 ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum"));
672 EXPECT_EQ(0, SqliteMasterCount(&db()));
675 // Basic test of RazeAndClose() operation.
676 TEST_F(SQLConnectionTest, RazeAndClose) {
677 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
678 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
680 // Test that RazeAndClose() closes the database, and that the
681 // database is empty when re-opened.
682 ASSERT_TRUE(db().Execute(kCreateSql));
683 ASSERT_TRUE(db().Execute(kPopulateSql));
684 ASSERT_TRUE(db().RazeAndClose());
685 ASSERT_FALSE(db().is_open());
686 db().Close();
687 ASSERT_TRUE(db().Open(db_path()));
688 ASSERT_EQ(0, SqliteMasterCount(&db()));
690 // Test that RazeAndClose() can break transactions.
691 ASSERT_TRUE(db().Execute(kCreateSql));
692 ASSERT_TRUE(db().Execute(kPopulateSql));
693 ASSERT_TRUE(db().BeginTransaction());
694 ASSERT_TRUE(db().RazeAndClose());
695 ASSERT_FALSE(db().is_open());
696 ASSERT_FALSE(db().CommitTransaction());
697 db().Close();
698 ASSERT_TRUE(db().Open(db_path()));
699 ASSERT_EQ(0, SqliteMasterCount(&db()));
702 // Test that various operations fail without crashing after
703 // RazeAndClose().
704 TEST_F(SQLConnectionTest, RazeAndCloseDiagnostics) {
705 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
706 const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)";
707 const char* kSimpleSql = "SELECT 1";
709 ASSERT_TRUE(db().Execute(kCreateSql));
710 ASSERT_TRUE(db().Execute(kPopulateSql));
712 // Test baseline expectations.
713 db().Preload();
714 ASSERT_TRUE(db().DoesTableExist("foo"));
715 ASSERT_TRUE(db().IsSQLValid(kSimpleSql));
716 ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql));
717 ASSERT_TRUE(db().Execute(kSimpleSql));
718 ASSERT_TRUE(db().is_open());
720 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
721 ASSERT_TRUE(s.Step());
724 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
725 ASSERT_TRUE(s.Step());
727 ASSERT_TRUE(db().BeginTransaction());
728 ASSERT_TRUE(db().CommitTransaction());
729 ASSERT_TRUE(db().BeginTransaction());
730 db().RollbackTransaction();
732 ASSERT_TRUE(db().RazeAndClose());
734 // At this point, they should all fail, but not crash.
735 db().Preload();
736 ASSERT_FALSE(db().DoesTableExist("foo"));
737 ASSERT_FALSE(db().IsSQLValid(kSimpleSql));
738 ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql));
739 ASSERT_FALSE(db().Execute(kSimpleSql));
740 ASSERT_FALSE(db().is_open());
742 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
743 ASSERT_FALSE(s.Step());
746 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
747 ASSERT_FALSE(s.Step());
749 ASSERT_FALSE(db().BeginTransaction());
750 ASSERT_FALSE(db().CommitTransaction());
751 ASSERT_FALSE(db().BeginTransaction());
752 db().RollbackTransaction();
754 // Close normally to reset the poisoned flag.
755 db().Close();
757 // DEATH tests not supported on Android or iOS.
758 #if !defined(OS_ANDROID) && !defined(OS_IOS)
759 // Once the real Close() has been called, various calls enforce API
760 // usage by becoming fatal in debug mode. Since DEATH tests are
761 // expensive, just test one of them.
762 if (DLOG_IS_ON(FATAL)) {
763 ASSERT_DEATH({
764 db().IsSQLValid(kSimpleSql);
765 }, "Illegal use of connection without a db");
767 #endif
770 // TODO(shess): Spin up a background thread to hold other_db, to more
771 // closely match real life. That would also allow testing
772 // RazeWithTimeout().
774 #if defined(OS_ANDROID)
775 TEST_F(SQLConnectionTest, SetTempDirForSQL) {
777 sql::MetaTable meta_table;
778 // Below call needs a temporary directory in sqlite3
779 // On Android, it can pass only when the temporary directory is set.
780 // Otherwise, sqlite3 doesn't find the correct directory to store
781 // temporary files and will report the error 'unable to open
782 // database file'.
783 ASSERT_TRUE(meta_table.Init(&db(), 4, 4));
785 #endif
787 TEST_F(SQLConnectionTest, Delete) {
788 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
789 db().Close();
791 // Should have both a main database file and a journal file because
792 // of journal_mode TRUNCATE.
793 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
794 ASSERT_TRUE(GetPathExists(db_path()));
795 ASSERT_TRUE(GetPathExists(journal));
797 sql::Connection::Delete(db_path());
798 EXPECT_FALSE(GetPathExists(db_path()));
799 EXPECT_FALSE(GetPathExists(journal));
802 // This test manually sets on disk permissions; this doesn't apply to the mojo
803 // fork.
804 #if defined(OS_POSIX) && !defined(MOJO_APPTEST_IMPL)
805 // Test that set_restrict_to_user() trims database permissions so that
806 // only the owner (and root) can read.
807 TEST_F(SQLConnectionTest, UserPermission) {
808 // If the bots all had a restrictive umask setting such that
809 // databases are always created with only the owner able to read
810 // them, then the code could break without breaking the tests.
811 // Temporarily provide a more permissive umask.
812 db().Close();
813 sql::Connection::Delete(db_path());
814 ASSERT_FALSE(GetPathExists(db_path()));
815 ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH);
816 ASSERT_TRUE(db().Open(db_path()));
818 // Cause the journal file to be created. If the default
819 // journal_mode is changed back to DELETE, then parts of this test
820 // will need to be updated.
821 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
823 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
824 int mode;
826 // Given a permissive umask, the database is created with permissive
827 // read access for the database and journal.
828 ASSERT_TRUE(GetPathExists(db_path()));
829 ASSERT_TRUE(GetPathExists(journal));
830 mode = base::FILE_PERMISSION_MASK;
831 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
832 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
833 mode = base::FILE_PERMISSION_MASK;
834 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
835 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
837 // Re-open with restricted permissions and verify that the modes
838 // changed for both the main database and the journal.
839 db().Close();
840 db().set_restrict_to_user();
841 ASSERT_TRUE(db().Open(db_path()));
842 ASSERT_TRUE(GetPathExists(db_path()));
843 ASSERT_TRUE(GetPathExists(journal));
844 mode = base::FILE_PERMISSION_MASK;
845 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
846 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
847 mode = base::FILE_PERMISSION_MASK;
848 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
849 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
851 // Delete and re-create the database, the restriction should still apply.
852 db().Close();
853 sql::Connection::Delete(db_path());
854 ASSERT_TRUE(db().Open(db_path()));
855 ASSERT_TRUE(GetPathExists(db_path()));
856 ASSERT_FALSE(GetPathExists(journal));
857 mode = base::FILE_PERMISSION_MASK;
858 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
859 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
861 // Verify that journal creation inherits the restriction.
862 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
863 ASSERT_TRUE(GetPathExists(journal));
864 mode = base::FILE_PERMISSION_MASK;
865 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
866 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
868 #endif // defined(OS_POSIX)
870 // Test that errors start happening once Poison() is called.
871 TEST_F(SQLConnectionTest, Poison) {
872 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
874 // Before the Poison() call, things generally work.
875 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
876 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
878 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
879 ASSERT_TRUE(s.is_valid());
880 ASSERT_TRUE(s.Step());
883 // Get a statement which is valid before and will exist across Poison().
884 sql::Statement valid_statement(
885 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master"));
886 ASSERT_TRUE(valid_statement.is_valid());
887 ASSERT_TRUE(valid_statement.Step());
888 valid_statement.Reset(true);
890 db().Poison();
892 // After the Poison() call, things fail.
893 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
894 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')"));
896 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
897 ASSERT_FALSE(s.is_valid());
898 ASSERT_FALSE(s.Step());
901 // The existing statement has become invalid.
902 ASSERT_FALSE(valid_statement.is_valid());
903 ASSERT_FALSE(valid_statement.Step());
906 // Test attaching and detaching databases from the connection.
907 TEST_F(SQLConnectionTest, Attach) {
908 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
910 // Create a database to attach to.
911 base::FilePath attach_path =
912 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
913 const char kAttachmentPoint[] = "other";
915 sql::Connection other_db;
916 ASSERT_TRUE(other_db.Open(attach_path));
917 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
918 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
921 // Cannot see the attached database, yet.
922 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
924 // Attach fails in a transaction.
925 EXPECT_TRUE(db().BeginTransaction());
927 sql::ScopedErrorIgnorer ignore_errors;
928 ignore_errors.IgnoreError(SQLITE_ERROR);
929 EXPECT_FALSE(db().AttachDatabase(attach_path, kAttachmentPoint));
930 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
933 // Attach succeeds when the transaction is closed.
934 db().RollbackTransaction();
935 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
936 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
938 // Queries can touch both databases.
939 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
941 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
942 ASSERT_TRUE(s.Step());
943 EXPECT_EQ(1, s.ColumnInt(0));
946 // Detach also fails in a transaction.
947 EXPECT_TRUE(db().BeginTransaction());
949 sql::ScopedErrorIgnorer ignore_errors;
950 ignore_errors.IgnoreError(SQLITE_ERROR);
951 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint));
952 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
953 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
956 // Detach succeeds outside of a transaction.
957 db().RollbackTransaction();
958 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
960 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
963 TEST_F(SQLConnectionTest, Basic_QuickIntegrityCheck) {
964 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
965 ASSERT_TRUE(db().Execute(kCreateSql));
966 EXPECT_TRUE(db().QuickIntegrityCheck());
967 db().Close();
969 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
972 sql::ScopedErrorIgnorer ignore_errors;
973 ignore_errors.IgnoreError(SQLITE_CORRUPT);
974 ASSERT_TRUE(db().Open(db_path()));
975 EXPECT_FALSE(db().QuickIntegrityCheck());
976 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
980 TEST_F(SQLConnectionTest, Basic_FullIntegrityCheck) {
981 const std::string kOk("ok");
982 std::vector<std::string> messages;
984 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
985 ASSERT_TRUE(db().Execute(kCreateSql));
986 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
987 EXPECT_EQ(1u, messages.size());
988 EXPECT_EQ(kOk, messages[0]);
989 db().Close();
991 ASSERT_TRUE(CorruptSizeInHeaderOfDB());
994 sql::ScopedErrorIgnorer ignore_errors;
995 ignore_errors.IgnoreError(SQLITE_CORRUPT);
996 ASSERT_TRUE(db().Open(db_path()));
997 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
998 EXPECT_LT(1u, messages.size());
999 EXPECT_NE(kOk, messages[0]);
1000 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
1003 // TODO(shess): CorruptTableOrIndex could be used to produce a
1004 // file that would pass the quick check and fail the full check.
1007 // Test Sqlite.Stats histogram for execute-oriented calls.
1008 TEST_F(SQLConnectionTest, EventsExecute) {
1009 // Re-open with histogram tag.
1010 db().Close();
1011 db().set_histogram_tag("Test");
1012 ASSERT_TRUE(db().Open(db_path()));
1014 // Open() uses Execute() extensively, don't track those calls.
1015 base::HistogramTester tester;
1017 const char kHistogramName[] = "Sqlite.Stats.Test";
1018 const char kGlobalHistogramName[] = "Sqlite.Stats";
1020 ASSERT_TRUE(db().BeginTransaction());
1021 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1022 EXPECT_TRUE(db().Execute(kCreateSql));
1023 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1024 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1025 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1026 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (13, 'text')"));
1027 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (14, 'text')"));
1028 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (15, 'text');"
1029 "INSERT INTO foo VALUES (16, 'text');"
1030 "INSERT INTO foo VALUES (17, 'text');"
1031 "INSERT INTO foo VALUES (18, 'text');"
1032 "INSERT INTO foo VALUES (19, 'text')"));
1033 ASSERT_TRUE(db().CommitTransaction());
1034 ASSERT_TRUE(db().BeginTransaction());
1035 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1036 db().RollbackTransaction();
1037 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1038 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (21, 'text')"));
1040 // The create, 5 inserts, multi-statement insert, rolled-back insert, 2
1041 // inserts outside transaction.
1042 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_EXECUTE, 10);
1043 tester.ExpectBucketCount(kGlobalHistogramName,
1044 sql::Connection::EVENT_EXECUTE, 10);
1046 // All of the executes, with the multi-statement inserts broken out, plus one
1047 // for each begin, commit, and rollback.
1048 tester.ExpectBucketCount(kHistogramName,
1049 sql::Connection::EVENT_STATEMENT_RUN, 18);
1050 tester.ExpectBucketCount(kGlobalHistogramName,
1051 sql::Connection::EVENT_STATEMENT_RUN, 18);
1053 tester.ExpectBucketCount(kHistogramName,
1054 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1055 tester.ExpectBucketCount(kGlobalHistogramName,
1056 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1057 tester.ExpectBucketCount(kHistogramName,
1058 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1059 tester.ExpectBucketCount(kGlobalHistogramName,
1060 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1062 // The 2 inserts outside the transaction.
1063 tester.ExpectBucketCount(kHistogramName,
1064 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1065 tester.ExpectBucketCount(kGlobalHistogramName,
1066 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1068 // 11 inserts inside transactions.
1069 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_CHANGES, 11);
1070 tester.ExpectBucketCount(kGlobalHistogramName,
1071 sql::Connection::EVENT_CHANGES, 11);
1073 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_BEGIN, 2);
1074 tester.ExpectBucketCount(kGlobalHistogramName,
1075 sql::Connection::EVENT_BEGIN, 2);
1076 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_COMMIT, 1);
1077 tester.ExpectBucketCount(kGlobalHistogramName,
1078 sql::Connection::EVENT_COMMIT, 1);
1079 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_ROLLBACK, 1);
1080 tester.ExpectBucketCount(kGlobalHistogramName,
1081 sql::Connection::EVENT_ROLLBACK, 1);
1084 // Test Sqlite.Stats histogram for prepared statements.
1085 TEST_F(SQLConnectionTest, EventsStatement) {
1086 // Re-open with histogram tag.
1087 db().Close();
1088 db().set_histogram_tag("Test");
1089 ASSERT_TRUE(db().Open(db_path()));
1091 const char kHistogramName[] = "Sqlite.Stats.Test";
1092 const char kGlobalHistogramName[] = "Sqlite.Stats";
1094 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1095 EXPECT_TRUE(db().Execute(kCreateSql));
1096 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1097 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1098 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1101 base::HistogramTester tester;
1104 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo"));
1105 while (s.Step()) {
1109 tester.ExpectBucketCount(kHistogramName,
1110 sql::Connection::EVENT_STATEMENT_RUN, 1);
1111 tester.ExpectBucketCount(kGlobalHistogramName,
1112 sql::Connection::EVENT_STATEMENT_RUN, 1);
1113 tester.ExpectBucketCount(kHistogramName,
1114 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1115 tester.ExpectBucketCount(kGlobalHistogramName,
1116 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1117 tester.ExpectBucketCount(kHistogramName,
1118 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1119 tester.ExpectBucketCount(kGlobalHistogramName,
1120 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1124 base::HistogramTester tester;
1127 sql::Statement s(db().GetUniqueStatement(
1128 "SELECT value FROM foo WHERE id > 10"));
1129 while (s.Step()) {
1133 tester.ExpectBucketCount(kHistogramName,
1134 sql::Connection::EVENT_STATEMENT_RUN, 1);
1135 tester.ExpectBucketCount(kGlobalHistogramName,
1136 sql::Connection::EVENT_STATEMENT_RUN, 1);
1137 tester.ExpectBucketCount(kHistogramName,
1138 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1139 tester.ExpectBucketCount(kGlobalHistogramName,
1140 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1141 tester.ExpectBucketCount(kHistogramName,
1142 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1143 tester.ExpectBucketCount(kGlobalHistogramName,
1144 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1148 // SQLite function to adjust mock time by |argv[0]| milliseconds.
1149 void sqlite_adjust_millis(sql::test::ScopedMockTimeSource* time_mock,
1150 sqlite3_context* context,
1151 int argc, sqlite3_value** argv) {
1152 int64 milliseconds = argc > 0 ? sqlite3_value_int64(argv[0]) : 1000;
1153 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
1154 sqlite3_result_int64(context, milliseconds);
1157 // Adjust mock time by |milliseconds| on commit.
1158 int adjust_commit_hook(sql::test::ScopedMockTimeSource* time_mock,
1159 int64 milliseconds) {
1160 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
1161 return SQLITE_OK;
1164 const char kCommitTime[] = "Sqlite.CommitTime.Test";
1165 const char kAutoCommitTime[] = "Sqlite.AutoCommitTime.Test";
1166 const char kUpdateTime[] = "Sqlite.UpdateTime.Test";
1167 const char kQueryTime[] = "Sqlite.QueryTime.Test";
1169 // Read-only query allocates time to QueryTime, but not others.
1170 TEST_F(SQLConnectionTest, TimeQuery) {
1171 // Re-open with histogram tag. Use an in-memory database to minimize variance
1172 // due to filesystem.
1173 db().Close();
1174 db().set_histogram_tag("Test");
1175 ASSERT_TRUE(db().OpenInMemory());
1177 sql::test::ScopedMockTimeSource time_mock(db());
1179 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1180 EXPECT_TRUE(db().Execute(kCreateSql));
1182 // Function to inject pauses into statements.
1183 sql::test::ScopedScalarFunction scoper(
1184 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1186 base::HistogramTester tester;
1188 EXPECT_TRUE(db().Execute("SELECT milliadjust(10)"));
1190 scoped_ptr<base::HistogramSamples> samples(
1191 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1192 ASSERT_TRUE(samples);
1193 // 10 for the adjust, 1 for the measurement.
1194 EXPECT_EQ(11, samples->sum());
1196 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1197 EXPECT_EQ(0, samples->sum());
1199 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1200 EXPECT_EQ(0, samples->sum());
1202 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1203 EXPECT_EQ(0, samples->sum());
1206 // Autocommit update allocates time to QueryTime, UpdateTime, and
1207 // AutoCommitTime.
1208 TEST_F(SQLConnectionTest, TimeUpdateAutocommit) {
1209 // Re-open with histogram tag. Use an in-memory database to minimize variance
1210 // due to filesystem.
1211 db().Close();
1212 db().set_histogram_tag("Test");
1213 ASSERT_TRUE(db().OpenInMemory());
1215 sql::test::ScopedMockTimeSource time_mock(db());
1217 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1218 EXPECT_TRUE(db().Execute(kCreateSql));
1220 // Function to inject pauses into statements.
1221 sql::test::ScopedScalarFunction scoper(
1222 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1224 base::HistogramTester tester;
1226 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, milliadjust(10))"));
1228 scoped_ptr<base::HistogramSamples> samples(
1229 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1230 ASSERT_TRUE(samples);
1231 // 10 for the adjust, 1 for the measurement.
1232 EXPECT_EQ(11, samples->sum());
1234 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1235 ASSERT_TRUE(samples);
1236 // 10 for the adjust, 1 for the measurement.
1237 EXPECT_EQ(11, samples->sum());
1239 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1240 EXPECT_EQ(0, samples->sum());
1242 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1243 ASSERT_TRUE(samples);
1244 // 10 for the adjust, 1 for the measurement.
1245 EXPECT_EQ(11, samples->sum());
1248 // Update with explicit transaction allocates time to QueryTime, UpdateTime, and
1249 // CommitTime.
1250 TEST_F(SQLConnectionTest, TimeUpdateTransaction) {
1251 // Re-open with histogram tag. Use an in-memory database to minimize variance
1252 // due to filesystem.
1253 db().Close();
1254 db().set_histogram_tag("Test");
1255 ASSERT_TRUE(db().OpenInMemory());
1257 sql::test::ScopedMockTimeSource time_mock(db());
1259 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1260 EXPECT_TRUE(db().Execute(kCreateSql));
1262 // Function to inject pauses into statements.
1263 sql::test::ScopedScalarFunction scoper(
1264 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1266 base::HistogramTester tester;
1269 // Make the commit slow.
1270 sql::test::ScopedCommitHook scoped_hook(
1271 db(), base::Bind(adjust_commit_hook, &time_mock, 100));
1272 ASSERT_TRUE(db().BeginTransaction());
1273 EXPECT_TRUE(db().Execute(
1274 "INSERT INTO foo VALUES (11, milliadjust(10))"));
1275 EXPECT_TRUE(db().Execute(
1276 "UPDATE foo SET value = milliadjust(10) WHERE id = 11"));
1277 EXPECT_TRUE(db().CommitTransaction());
1280 scoped_ptr<base::HistogramSamples> samples(
1281 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1282 ASSERT_TRUE(samples);
1283 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1284 // measuring each of BEGIN, INSERT, UPDATE, and COMMIT.
1285 EXPECT_EQ(124, samples->sum());
1287 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1288 ASSERT_TRUE(samples);
1289 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1290 // measuring each of INSERT, UPDATE, and COMMIT.
1291 EXPECT_EQ(123, samples->sum());
1293 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1294 ASSERT_TRUE(samples);
1295 // 100 for commit adjust, 1 for measuring COMMIT.
1296 EXPECT_EQ(101, samples->sum());
1298 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1299 EXPECT_EQ(0, samples->sum());
1302 } // namespace