Change Auto Lo-Fi field trial name.
[chromium-blink-merge.git] / sql / connection_unittest.cc
bloba09721a0f73723fc93e29e513eeb45449838f43e
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/meta_table.h"
14 #include "sql/proxy.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 sql::sqlite3_create_function_v2(db_, function_name, args, SQLITE_UTF8,
89 this, &Run, NULL, NULL, NULL);
91 ~ScopedScalarFunction() {
92 sql::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 sql::sqlite3_commit_hook(db_, &Run, this);
119 ~ScopedCommitHook() {
120 sql::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 testing::Test {
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 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
218 db_path_ = temp_dir_.path().AppendASCII("SQLConnectionTest.db");
219 ASSERT_TRUE(db_.Open(db_path_));
222 void TearDown() override { db_.Close(); }
224 sql::Connection& db() { return db_; }
225 const base::FilePath& db_path() { return db_path_; }
227 // Handle errors by blowing away the database.
228 void RazeErrorCallback(int expected_error, int error, sql::Statement* stmt) {
229 EXPECT_EQ(expected_error, error);
230 db_.RazeAndClose();
233 private:
234 sql::Connection db_;
235 base::FilePath db_path_;
236 base::ScopedTempDir temp_dir_;
239 TEST_F(SQLConnectionTest, Execute) {
240 // Valid statement should return true.
241 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
242 EXPECT_EQ(SQLITE_OK, db().GetErrorCode());
244 // Invalid statement should fail.
245 ASSERT_EQ(SQLITE_ERROR,
246 db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b"));
247 EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode());
250 TEST_F(SQLConnectionTest, ExecuteWithErrorCode) {
251 ASSERT_EQ(SQLITE_OK,
252 db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)"));
253 ASSERT_EQ(SQLITE_ERROR,
254 db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE"));
255 ASSERT_EQ(SQLITE_ERROR,
256 db().ExecuteAndReturnErrorCode(
257 "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)"));
260 TEST_F(SQLConnectionTest, CachedStatement) {
261 sql::StatementID id1("foo", 12);
263 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
264 ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)"));
266 // Create a new cached statement.
268 sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo"));
269 ASSERT_TRUE(s.is_valid());
271 ASSERT_TRUE(s.Step());
272 EXPECT_EQ(12, s.ColumnInt(0));
275 // The statement should be cached still.
276 EXPECT_TRUE(db().HasCachedStatement(id1));
279 // Get the same statement using different SQL. This should ignore our
280 // SQL and use the cached one (so it will be valid).
281 sql::Statement s(db().GetCachedStatement(id1, "something invalid("));
282 ASSERT_TRUE(s.is_valid());
284 ASSERT_TRUE(s.Step());
285 EXPECT_EQ(12, s.ColumnInt(0));
288 // Make sure other statements aren't marked as cached.
289 EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE));
292 TEST_F(SQLConnectionTest, IsSQLValidTest) {
293 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
294 ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo"));
295 ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo"));
298 TEST_F(SQLConnectionTest, DoesStuffExist) {
299 // Test DoesTableExist.
300 EXPECT_FALSE(db().DoesTableExist("foo"));
301 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
302 ASSERT_TRUE(db().Execute("CREATE INDEX foo_a ON foo (a)"));
303 EXPECT_TRUE(db().DoesTableExist("foo"));
304 EXPECT_TRUE(db().DoesIndexExist("foo_a"));
306 // Test DoesColumnExist.
307 EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
308 EXPECT_TRUE(db().DoesColumnExist("foo", "a"));
310 // Testing for a column on a nonexistent table.
311 EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
313 // Names are not case sensitive.
314 EXPECT_TRUE(db().DoesTableExist("FOO"));
315 EXPECT_TRUE(db().DoesColumnExist("FOO", "A"));
318 TEST_F(SQLConnectionTest, GetLastInsertRowId) {
319 ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"));
321 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
323 // Last insert row ID should be valid.
324 int64_t row = db().GetLastInsertRowId();
325 EXPECT_LT(0, row);
327 // It should be the primary key of the row we just inserted.
328 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?"));
329 s.BindInt64(0, row);
330 ASSERT_TRUE(s.Step());
331 EXPECT_EQ(12, s.ColumnInt(0));
334 TEST_F(SQLConnectionTest, Rollback) {
335 ASSERT_TRUE(db().BeginTransaction());
336 ASSERT_TRUE(db().BeginTransaction());
337 EXPECT_EQ(2, db().transaction_nesting());
338 db().RollbackTransaction();
339 EXPECT_FALSE(db().CommitTransaction());
340 EXPECT_TRUE(db().BeginTransaction());
343 // Test the scoped error ignorer by attempting to insert a duplicate
344 // value into an index.
345 TEST_F(SQLConnectionTest, ScopedIgnoreError) {
346 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
347 ASSERT_TRUE(db().Execute(kCreateSql));
348 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
351 sql::ScopedErrorIgnorer ignore_errors;
352 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
353 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
354 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
358 // Test that clients of GetUntrackedStatement() can test corruption-handling
359 // with ScopedErrorIgnorer.
360 TEST_F(SQLConnectionTest, ScopedIgnoreUntracked) {
361 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
362 ASSERT_TRUE(db().Execute(kCreateSql));
363 ASSERT_FALSE(db().DoesTableExist("bar"));
364 ASSERT_TRUE(db().DoesTableExist("foo"));
365 ASSERT_TRUE(db().DoesColumnExist("foo", "id"));
366 db().Close();
368 // Corrupt the database so that nothing works, including PRAGMAs.
369 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
372 sql::ScopedErrorIgnorer ignore_errors;
373 ignore_errors.IgnoreError(SQLITE_CORRUPT);
374 ASSERT_TRUE(db().Open(db_path()));
375 ASSERT_FALSE(db().DoesTableExist("bar"));
376 ASSERT_FALSE(db().DoesTableExist("foo"));
377 ASSERT_FALSE(db().DoesColumnExist("foo", "id"));
378 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
382 TEST_F(SQLConnectionTest, ErrorCallback) {
383 const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
384 ASSERT_TRUE(db().Execute(kCreateSql));
385 ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
387 int error = SQLITE_OK;
389 sql::ScopedErrorCallback sec(
390 &db(), base::Bind(&sql::CaptureErrorCallback, &error));
391 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
393 // Later versions of SQLite throw SQLITE_CONSTRAINT_UNIQUE. The specific
394 // sub-error isn't really important.
395 EXPECT_EQ(SQLITE_CONSTRAINT, (error&0xff));
398 // Callback is no longer in force due to reset.
400 error = SQLITE_OK;
401 sql::ScopedErrorIgnorer ignore_errors;
402 ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
403 ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
404 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
405 EXPECT_EQ(SQLITE_OK, error);
408 // base::Bind() can curry arguments to be passed by const reference
409 // to the callback function. If the callback function calls
410 // re/set_error_callback(), the storage for those arguments can be
411 // deleted while the callback function is still executing.
413 // RefCounter() counts how many objects are live using an external
414 // count. The same counter is passed to the callback, so that it
415 // can check directly even if the RefCounter object is no longer
416 // live.
418 size_t count = 0;
419 sql::ScopedErrorCallback sec(
420 &db(), base::Bind(&ErrorCallbackSetHelper,
421 &db(), &count, RefCounter(&count)));
423 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
426 // Same test, but reset_error_callback() case.
428 size_t count = 0;
429 sql::ScopedErrorCallback sec(
430 &db(), base::Bind(&ErrorCallbackResetHelper,
431 &db(), &count, RefCounter(&count)));
433 EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
437 // Test that sql::Connection::Raze() results in a database without the
438 // tables from the original database.
439 TEST_F(SQLConnectionTest, Raze) {
440 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
441 ASSERT_TRUE(db().Execute(kCreateSql));
442 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)"));
444 int pragma_auto_vacuum = 0;
446 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
447 ASSERT_TRUE(s.Step());
448 pragma_auto_vacuum = s.ColumnInt(0);
449 ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1);
452 // If auto_vacuum is set, there's an extra page to maintain a freelist.
453 const int kExpectedPageCount = 2 + pragma_auto_vacuum;
456 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
457 ASSERT_TRUE(s.Step());
458 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0));
462 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master"));
463 ASSERT_TRUE(s.Step());
464 EXPECT_EQ("table", s.ColumnString(0));
465 EXPECT_EQ("foo", s.ColumnString(1));
466 EXPECT_EQ("foo", s.ColumnString(2));
467 // Table "foo" is stored in the last page of the file.
468 EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3));
469 EXPECT_EQ(kCreateSql, s.ColumnString(4));
472 ASSERT_TRUE(db().Raze());
475 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count"));
476 ASSERT_TRUE(s.Step());
477 EXPECT_EQ(1, s.ColumnInt(0));
480 ASSERT_EQ(0, SqliteMasterCount(&db()));
483 sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum"));
484 ASSERT_TRUE(s.Step());
485 // The new database has the same auto_vacuum as a fresh database.
486 EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0));
490 // Test that Raze() maintains page_size.
491 TEST_F(SQLConnectionTest, RazePageSize) {
492 // Fetch the default page size and double it for use in this test.
493 // Scoped to release statement before Close().
494 int default_page_size = 0;
496 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
497 ASSERT_TRUE(s.Step());
498 default_page_size = s.ColumnInt(0);
500 ASSERT_GT(default_page_size, 0);
501 const int kPageSize = 2 * default_page_size;
503 // Re-open the database to allow setting the page size.
504 db().Close();
505 db().set_page_size(kPageSize);
506 ASSERT_TRUE(db().Open(db_path()));
508 // page_size should match the indicated value.
509 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size"));
510 ASSERT_TRUE(s.Step());
511 ASSERT_EQ(kPageSize, s.ColumnInt(0));
513 // After raze, page_size should still match the indicated value.
514 ASSERT_TRUE(db().Raze());
515 s.Reset(true);
516 ASSERT_TRUE(s.Step());
517 ASSERT_EQ(kPageSize, s.ColumnInt(0));
520 // Test that Raze() results are seen in other connections.
521 TEST_F(SQLConnectionTest, RazeMultiple) {
522 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
523 ASSERT_TRUE(db().Execute(kCreateSql));
525 sql::Connection other_db;
526 ASSERT_TRUE(other_db.Open(db_path()));
528 // Check that the second connection sees the table.
529 ASSERT_EQ(1, SqliteMasterCount(&other_db));
531 ASSERT_TRUE(db().Raze());
533 // The second connection sees the updated database.
534 ASSERT_EQ(0, SqliteMasterCount(&other_db));
537 TEST_F(SQLConnectionTest, RazeLocked) {
538 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
539 ASSERT_TRUE(db().Execute(kCreateSql));
541 // Open a transaction and write some data in a second connection.
542 // This will acquire a PENDING or EXCLUSIVE transaction, which will
543 // cause the raze to fail.
544 sql::Connection other_db;
545 ASSERT_TRUE(other_db.Open(db_path()));
546 ASSERT_TRUE(other_db.BeginTransaction());
547 const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')";
548 ASSERT_TRUE(other_db.Execute(kInsertSql));
550 ASSERT_FALSE(db().Raze());
552 // Works after COMMIT.
553 ASSERT_TRUE(other_db.CommitTransaction());
554 ASSERT_TRUE(db().Raze());
556 // Re-create the database.
557 ASSERT_TRUE(db().Execute(kCreateSql));
558 ASSERT_TRUE(db().Execute(kInsertSql));
560 // An unfinished read transaction in the other connection also
561 // blocks raze.
562 const char *kQuery = "SELECT COUNT(*) FROM foo";
563 sql::Statement s(other_db.GetUniqueStatement(kQuery));
564 ASSERT_TRUE(s.Step());
565 ASSERT_FALSE(db().Raze());
567 // Complete the statement unlocks the database.
568 ASSERT_FALSE(s.Step());
569 ASSERT_TRUE(db().Raze());
572 // Verify that Raze() can handle an empty file. SQLite should treat
573 // this as an empty database.
574 TEST_F(SQLConnectionTest, RazeEmptyDB) {
575 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
576 ASSERT_TRUE(db().Execute(kCreateSql));
577 db().Close();
580 base::ScopedFILE file(base::OpenFile(db_path(), "rb+"));
581 ASSERT_TRUE(file.get() != NULL);
582 ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
583 ASSERT_TRUE(base::TruncateFile(file.get()));
586 ASSERT_TRUE(db().Open(db_path()));
587 ASSERT_TRUE(db().Raze());
588 EXPECT_EQ(0, SqliteMasterCount(&db()));
591 // Verify that Raze() can handle a file of junk.
592 TEST_F(SQLConnectionTest, RazeNOTADB) {
593 db().Close();
594 sql::Connection::Delete(db_path());
595 ASSERT_FALSE(base::PathExists(db_path()));
598 base::ScopedFILE file(base::OpenFile(db_path(), "wb"));
599 ASSERT_TRUE(file.get() != NULL);
601 const char* kJunk = "This is the hour of our discontent.";
602 fputs(kJunk, file.get());
604 ASSERT_TRUE(base::PathExists(db_path()));
606 // SQLite will successfully open the handle, but fail when running PRAGMA
607 // statements that access the database.
609 sql::ScopedErrorIgnorer ignore_errors;
611 // Earlier versions of Chromium compiled against SQLite 3.6.7.3, which
612 // returned SQLITE_IOERR_SHORT_READ in this case. Some platforms may still
613 // compile against an earlier SQLite via USE_SYSTEM_SQLITE.
614 if (ignore_errors.SQLiteLibVersionNumber() < 3008005) {
615 ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ);
616 } else {
617 ignore_errors.IgnoreError(SQLITE_NOTADB);
620 EXPECT_TRUE(db().Open(db_path()));
621 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
623 EXPECT_TRUE(db().Raze());
624 db().Close();
626 // Now empty, the open should open an empty database.
627 EXPECT_TRUE(db().Open(db_path()));
628 EXPECT_EQ(0, SqliteMasterCount(&db()));
631 // Verify that Raze() can handle a database overwritten with garbage.
632 TEST_F(SQLConnectionTest, RazeNOTADB2) {
633 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
634 ASSERT_TRUE(db().Execute(kCreateSql));
635 ASSERT_EQ(1, SqliteMasterCount(&db()));
636 db().Close();
639 base::ScopedFILE file(base::OpenFile(db_path(), "rb+"));
640 ASSERT_TRUE(file.get() != NULL);
641 ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET));
643 const char* kJunk = "This is the hour of our discontent.";
644 fputs(kJunk, file.get());
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.
651 sql::ScopedErrorIgnorer ignore_errors;
652 ignore_errors.IgnoreError(SQLITE_NOTADB);
653 EXPECT_TRUE(db().Open(db_path()));
654 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
656 EXPECT_TRUE(db().Raze());
657 db().Close();
659 // Now empty, the open should succeed with an empty database.
660 EXPECT_TRUE(db().Open(db_path()));
661 EXPECT_EQ(0, SqliteMasterCount(&db()));
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
666 // Raze() cannot happen later. Additionally test that when the
667 // callback does this during Open(), the open is retried and succeeds.
668 TEST_F(SQLConnectionTest, RazeCallbackReopen) {
669 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
670 ASSERT_TRUE(db().Execute(kCreateSql));
671 ASSERT_EQ(1, SqliteMasterCount(&db()));
672 db().Close();
674 // Corrupt the database so that nothing works, including PRAGMAs.
675 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
677 // Open() will succeed, even though the PRAGMA calls within will
678 // fail with SQLITE_CORRUPT, as will this PRAGMA.
680 sql::ScopedErrorIgnorer ignore_errors;
681 ignore_errors.IgnoreError(SQLITE_CORRUPT);
682 ASSERT_TRUE(db().Open(db_path()));
683 ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum"));
684 db().Close();
685 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
688 db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback,
689 base::Unretained(this),
690 SQLITE_CORRUPT));
692 // 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"));
698 EXPECT_EQ(0, SqliteMasterCount(&db()));
701 // Basic test of RazeAndClose() operation.
702 TEST_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)";
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()));
714 ASSERT_EQ(0, SqliteMasterCount(&db()));
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()));
725 ASSERT_EQ(0, SqliteMasterCount(&db()));
728 // Test that various operations fail without crashing after
729 // RazeAndClose().
730 TEST_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";
735 ASSERT_TRUE(db().Execute(kCreateSql));
736 ASSERT_TRUE(db().Execute(kPopulateSql));
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());
746 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
747 ASSERT_TRUE(s.Step());
750 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
751 ASSERT_TRUE(s.Step());
753 ASSERT_TRUE(db().BeginTransaction());
754 ASSERT_TRUE(db().CommitTransaction());
755 ASSERT_TRUE(db().BeginTransaction());
756 db().RollbackTransaction();
758 ASSERT_TRUE(db().RazeAndClose());
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());
768 sql::Statement s(db().GetUniqueStatement(kSimpleSql));
769 ASSERT_FALSE(s.Step());
772 sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql));
773 ASSERT_FALSE(s.Step());
775 ASSERT_FALSE(db().BeginTransaction());
776 ASSERT_FALSE(db().CommitTransaction());
777 ASSERT_FALSE(db().BeginTransaction());
778 db().RollbackTransaction();
780 // Close normally to reset the poisoned flag.
781 db().Close();
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");
793 #endif
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().
800 #if defined(OS_ANDROID)
801 TEST_F(SQLConnectionTest, SetTempDirForSQL) {
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));
811 #endif
813 TEST_F(SQLConnectionTest, Delete) {
814 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
815 db().Close();
817 // Should have both a main database file and a journal file because
818 // of journal_mode TRUNCATE.
819 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
820 ASSERT_TRUE(base::PathExists(db_path()));
821 ASSERT_TRUE(base::PathExists(journal));
823 sql::Connection::Delete(db_path());
824 EXPECT_FALSE(base::PathExists(db_path()));
825 EXPECT_FALSE(base::PathExists(journal));
828 #if defined(OS_POSIX)
829 // Test that set_restrict_to_user() trims database permissions so that
830 // only the owner (and root) can read.
831 TEST_F(SQLConnectionTest, UserPermission) {
832 // If the bots all had a restrictive umask setting such that
833 // databases are always created with only the owner able to read
834 // them, then the code could break without breaking the tests.
835 // Temporarily provide a more permissive umask.
836 db().Close();
837 sql::Connection::Delete(db_path());
838 ASSERT_FALSE(base::PathExists(db_path()));
839 ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH);
840 ASSERT_TRUE(db().Open(db_path()));
842 // Cause the journal file to be created. If the default
843 // journal_mode is changed back to DELETE, then parts of this test
844 // will need to be updated.
845 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
847 base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal"));
848 int mode;
850 // Given a permissive umask, the database is created with permissive
851 // read access for the database and journal.
852 ASSERT_TRUE(base::PathExists(db_path()));
853 ASSERT_TRUE(base::PathExists(journal));
854 mode = base::FILE_PERMISSION_MASK;
855 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
856 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
857 mode = base::FILE_PERMISSION_MASK;
858 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
859 ASSERT_NE((mode & base::FILE_PERMISSION_USER_MASK), mode);
861 // Re-open with restricted permissions and verify that the modes
862 // changed for both the main database and the journal.
863 db().Close();
864 db().set_restrict_to_user();
865 ASSERT_TRUE(db().Open(db_path()));
866 ASSERT_TRUE(base::PathExists(db_path()));
867 ASSERT_TRUE(base::PathExists(journal));
868 mode = base::FILE_PERMISSION_MASK;
869 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
870 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
871 mode = base::FILE_PERMISSION_MASK;
872 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
873 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
875 // Delete and re-create the database, the restriction should still apply.
876 db().Close();
877 sql::Connection::Delete(db_path());
878 ASSERT_TRUE(db().Open(db_path()));
879 ASSERT_TRUE(base::PathExists(db_path()));
880 ASSERT_FALSE(base::PathExists(journal));
881 mode = base::FILE_PERMISSION_MASK;
882 EXPECT_TRUE(base::GetPosixFilePermissions(db_path(), &mode));
883 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
885 // Verify that journal creation inherits the restriction.
886 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
887 ASSERT_TRUE(base::PathExists(journal));
888 mode = base::FILE_PERMISSION_MASK;
889 EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
890 ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
892 #endif // defined(OS_POSIX)
894 // Test that errors start happening once Poison() is called.
895 TEST_F(SQLConnectionTest, Poison) {
896 EXPECT_TRUE(db().Execute("CREATE TABLE x (x)"));
898 // Before the Poison() call, things generally work.
899 EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
900 EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')"));
902 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
903 ASSERT_TRUE(s.is_valid());
904 ASSERT_TRUE(s.Step());
907 // Get a statement which is valid before and will exist across Poison().
908 sql::Statement valid_statement(
909 db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master"));
910 ASSERT_TRUE(valid_statement.is_valid());
911 ASSERT_TRUE(valid_statement.Step());
912 valid_statement.Reset(true);
914 db().Poison();
916 // After the Poison() call, things fail.
917 EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')"));
918 EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')"));
920 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x"));
921 ASSERT_FALSE(s.is_valid());
922 ASSERT_FALSE(s.Step());
925 // The existing statement has become invalid.
926 ASSERT_FALSE(valid_statement.is_valid());
927 ASSERT_FALSE(valid_statement.Step());
930 // Test attaching and detaching databases from the connection.
931 TEST_F(SQLConnectionTest, Attach) {
932 EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
934 // Create a database to attach to.
935 base::FilePath attach_path =
936 db_path().DirName().AppendASCII("SQLConnectionAttach.db");
937 const char kAttachmentPoint[] = "other";
939 sql::Connection other_db;
940 ASSERT_TRUE(other_db.Open(attach_path));
941 EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)"));
942 EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')"));
945 // Cannot see the attached database, yet.
946 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
948 // Attach fails in a transaction.
949 EXPECT_TRUE(db().BeginTransaction());
951 sql::ScopedErrorIgnorer ignore_errors;
952 ignore_errors.IgnoreError(SQLITE_ERROR);
953 EXPECT_FALSE(db().AttachDatabase(attach_path, kAttachmentPoint));
954 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
957 // Attach succeeds when the transaction is closed.
958 db().RollbackTransaction();
959 EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint));
960 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
962 // Queries can touch both databases.
963 EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar"));
965 sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo"));
966 ASSERT_TRUE(s.Step());
967 EXPECT_EQ(1, s.ColumnInt(0));
970 // Detach also fails in a transaction.
971 EXPECT_TRUE(db().BeginTransaction());
973 sql::ScopedErrorIgnorer ignore_errors;
974 ignore_errors.IgnoreError(SQLITE_ERROR);
975 EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint));
976 EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar"));
977 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
980 // Detach succeeds outside of a transaction.
981 db().RollbackTransaction();
982 EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint));
984 EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar"));
987 TEST_F(SQLConnectionTest, Basic_QuickIntegrityCheck) {
988 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
989 ASSERT_TRUE(db().Execute(kCreateSql));
990 EXPECT_TRUE(db().QuickIntegrityCheck());
991 db().Close();
993 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
996 sql::ScopedErrorIgnorer ignore_errors;
997 ignore_errors.IgnoreError(SQLITE_CORRUPT);
998 ASSERT_TRUE(db().Open(db_path()));
999 EXPECT_FALSE(db().QuickIntegrityCheck());
1000 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
1004 TEST_F(SQLConnectionTest, Basic_FullIntegrityCheck) {
1005 const std::string kOk("ok");
1006 std::vector<std::string> messages;
1008 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1009 ASSERT_TRUE(db().Execute(kCreateSql));
1010 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
1011 EXPECT_EQ(1u, messages.size());
1012 EXPECT_EQ(kOk, messages[0]);
1013 db().Close();
1015 ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
1018 sql::ScopedErrorIgnorer ignore_errors;
1019 ignore_errors.IgnoreError(SQLITE_CORRUPT);
1020 ASSERT_TRUE(db().Open(db_path()));
1021 EXPECT_TRUE(db().FullIntegrityCheck(&messages));
1022 EXPECT_LT(1u, messages.size());
1023 EXPECT_NE(kOk, messages[0]);
1024 ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
1027 // TODO(shess): CorruptTableOrIndex could be used to produce a
1028 // file that would pass the quick check and fail the full check.
1031 // Test Sqlite.Stats histogram for execute-oriented calls.
1032 TEST_F(SQLConnectionTest, EventsExecute) {
1033 // Re-open with histogram tag.
1034 db().Close();
1035 db().set_histogram_tag("Test");
1036 ASSERT_TRUE(db().Open(db_path()));
1038 // Open() uses Execute() extensively, don't track those calls.
1039 base::HistogramTester tester;
1041 const char kHistogramName[] = "Sqlite.Stats.Test";
1042 const char kGlobalHistogramName[] = "Sqlite.Stats";
1044 ASSERT_TRUE(db().BeginTransaction());
1045 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1046 EXPECT_TRUE(db().Execute(kCreateSql));
1047 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1048 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1049 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1050 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (13, 'text')"));
1051 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (14, 'text')"));
1052 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (15, 'text');"
1053 "INSERT INTO foo VALUES (16, 'text');"
1054 "INSERT INTO foo VALUES (17, 'text');"
1055 "INSERT INTO foo VALUES (18, 'text');"
1056 "INSERT INTO foo VALUES (19, 'text')"));
1057 ASSERT_TRUE(db().CommitTransaction());
1058 ASSERT_TRUE(db().BeginTransaction());
1059 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1060 db().RollbackTransaction();
1061 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (20, 'text')"));
1062 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (21, 'text')"));
1064 // The create, 5 inserts, multi-statement insert, rolled-back insert, 2
1065 // inserts outside transaction.
1066 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_EXECUTE, 10);
1067 tester.ExpectBucketCount(kGlobalHistogramName,
1068 sql::Connection::EVENT_EXECUTE, 10);
1070 // All of the executes, with the multi-statement inserts broken out, plus one
1071 // for each begin, commit, and rollback.
1072 tester.ExpectBucketCount(kHistogramName,
1073 sql::Connection::EVENT_STATEMENT_RUN, 18);
1074 tester.ExpectBucketCount(kGlobalHistogramName,
1075 sql::Connection::EVENT_STATEMENT_RUN, 18);
1077 tester.ExpectBucketCount(kHistogramName,
1078 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1079 tester.ExpectBucketCount(kGlobalHistogramName,
1080 sql::Connection::EVENT_STATEMENT_ROWS, 0);
1081 tester.ExpectBucketCount(kHistogramName,
1082 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1083 tester.ExpectBucketCount(kGlobalHistogramName,
1084 sql::Connection::EVENT_STATEMENT_SUCCESS, 18);
1086 // The 2 inserts outside the transaction.
1087 tester.ExpectBucketCount(kHistogramName,
1088 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1089 tester.ExpectBucketCount(kGlobalHistogramName,
1090 sql::Connection::EVENT_CHANGES_AUTOCOMMIT, 2);
1092 // 11 inserts inside transactions.
1093 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_CHANGES, 11);
1094 tester.ExpectBucketCount(kGlobalHistogramName,
1095 sql::Connection::EVENT_CHANGES, 11);
1097 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_BEGIN, 2);
1098 tester.ExpectBucketCount(kGlobalHistogramName,
1099 sql::Connection::EVENT_BEGIN, 2);
1100 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_COMMIT, 1);
1101 tester.ExpectBucketCount(kGlobalHistogramName,
1102 sql::Connection::EVENT_COMMIT, 1);
1103 tester.ExpectBucketCount(kHistogramName, sql::Connection::EVENT_ROLLBACK, 1);
1104 tester.ExpectBucketCount(kGlobalHistogramName,
1105 sql::Connection::EVENT_ROLLBACK, 1);
1108 // Test Sqlite.Stats histogram for prepared statements.
1109 TEST_F(SQLConnectionTest, EventsStatement) {
1110 // Re-open with histogram tag.
1111 db().Close();
1112 db().set_histogram_tag("Test");
1113 ASSERT_TRUE(db().Open(db_path()));
1115 const char kHistogramName[] = "Sqlite.Stats.Test";
1116 const char kGlobalHistogramName[] = "Sqlite.Stats";
1118 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1119 EXPECT_TRUE(db().Execute(kCreateSql));
1120 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, 'text')"));
1121 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (11, 'text')"));
1122 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (12, 'text')"));
1125 base::HistogramTester tester;
1128 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo"));
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, 3);
1139 tester.ExpectBucketCount(kGlobalHistogramName,
1140 sql::Connection::EVENT_STATEMENT_ROWS, 3);
1141 tester.ExpectBucketCount(kHistogramName,
1142 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1143 tester.ExpectBucketCount(kGlobalHistogramName,
1144 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1148 base::HistogramTester tester;
1151 sql::Statement s(db().GetUniqueStatement(
1152 "SELECT value FROM foo WHERE id > 10"));
1153 while (s.Step()) {
1157 tester.ExpectBucketCount(kHistogramName,
1158 sql::Connection::EVENT_STATEMENT_RUN, 1);
1159 tester.ExpectBucketCount(kGlobalHistogramName,
1160 sql::Connection::EVENT_STATEMENT_RUN, 1);
1161 tester.ExpectBucketCount(kHistogramName,
1162 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1163 tester.ExpectBucketCount(kGlobalHistogramName,
1164 sql::Connection::EVENT_STATEMENT_ROWS, 2);
1165 tester.ExpectBucketCount(kHistogramName,
1166 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1167 tester.ExpectBucketCount(kGlobalHistogramName,
1168 sql::Connection::EVENT_STATEMENT_SUCCESS, 1);
1172 // SQLite function to adjust mock time by |argv[0]| milliseconds.
1173 void sqlite_adjust_millis(sql::test::ScopedMockTimeSource* time_mock,
1174 sqlite3_context* context,
1175 int argc, sqlite3_value** argv) {
1176 int64 milliseconds = argc > 0 ? sqlite3_value_int64(argv[0]) : 1000;
1177 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
1178 sqlite3_result_int64(context, milliseconds);
1181 // Adjust mock time by |milliseconds| on commit.
1182 int adjust_commit_hook(sql::test::ScopedMockTimeSource* time_mock,
1183 int64 milliseconds) {
1184 time_mock->adjust(base::TimeDelta::FromMilliseconds(milliseconds));
1185 return SQLITE_OK;
1188 const char kCommitTime[] = "Sqlite.CommitTime.Test";
1189 const char kAutoCommitTime[] = "Sqlite.AutoCommitTime.Test";
1190 const char kUpdateTime[] = "Sqlite.UpdateTime.Test";
1191 const char kQueryTime[] = "Sqlite.QueryTime.Test";
1193 // Read-only query allocates time to QueryTime, but not others.
1194 TEST_F(SQLConnectionTest, TimeQuery) {
1195 // Re-open with histogram tag. Use an in-memory database to minimize variance
1196 // due to filesystem.
1197 db().Close();
1198 db().set_histogram_tag("Test");
1199 ASSERT_TRUE(db().OpenInMemory());
1201 sql::test::ScopedMockTimeSource time_mock(db());
1203 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1204 EXPECT_TRUE(db().Execute(kCreateSql));
1206 // Function to inject pauses into statements.
1207 sql::test::ScopedScalarFunction scoper(
1208 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1210 base::HistogramTester tester;
1212 EXPECT_TRUE(db().Execute("SELECT milliadjust(10)"));
1214 scoped_ptr<base::HistogramSamples> samples(
1215 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1216 ASSERT_TRUE(samples);
1217 // 10 for the adjust, 1 for the measurement.
1218 EXPECT_EQ(11, samples->sum());
1220 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1221 EXPECT_TRUE(!samples || samples->sum() == 0);
1223 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1224 EXPECT_TRUE(!samples || samples->sum() == 0);
1226 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1227 EXPECT_TRUE(!samples || samples->sum() == 0);
1230 // Autocommit update allocates time to QueryTime, UpdateTime, and
1231 // AutoCommitTime.
1232 TEST_F(SQLConnectionTest, TimeUpdateAutocommit) {
1233 // Re-open with histogram tag. Use an in-memory database to minimize variance
1234 // due to filesystem.
1235 db().Close();
1236 db().set_histogram_tag("Test");
1237 ASSERT_TRUE(db().OpenInMemory());
1239 sql::test::ScopedMockTimeSource time_mock(db());
1241 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1242 EXPECT_TRUE(db().Execute(kCreateSql));
1244 // Function to inject pauses into statements.
1245 sql::test::ScopedScalarFunction scoper(
1246 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1248 base::HistogramTester tester;
1250 EXPECT_TRUE(db().Execute("INSERT INTO foo VALUES (10, milliadjust(10))"));
1252 scoped_ptr<base::HistogramSamples> samples(
1253 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1254 ASSERT_TRUE(samples);
1255 // 10 for the adjust, 1 for the measurement.
1256 EXPECT_EQ(11, samples->sum());
1258 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1259 ASSERT_TRUE(samples);
1260 // 10 for the adjust, 1 for the measurement.
1261 EXPECT_EQ(11, samples->sum());
1263 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1264 EXPECT_TRUE(!samples || samples->sum() == 0);
1266 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1267 ASSERT_TRUE(samples);
1268 // 10 for the adjust, 1 for the measurement.
1269 EXPECT_EQ(11, samples->sum());
1272 // Update with explicit transaction allocates time to QueryTime, UpdateTime, and
1273 // CommitTime.
1274 TEST_F(SQLConnectionTest, TimeUpdateTransaction) {
1275 // Re-open with histogram tag. Use an in-memory database to minimize variance
1276 // due to filesystem.
1277 db().Close();
1278 db().set_histogram_tag("Test");
1279 ASSERT_TRUE(db().OpenInMemory());
1281 sql::test::ScopedMockTimeSource time_mock(db());
1283 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)";
1284 EXPECT_TRUE(db().Execute(kCreateSql));
1286 // Function to inject pauses into statements.
1287 sql::test::ScopedScalarFunction scoper(
1288 db(), "milliadjust", 1, base::Bind(&sqlite_adjust_millis, &time_mock));
1290 base::HistogramTester tester;
1293 // Make the commit slow.
1294 sql::test::ScopedCommitHook scoped_hook(
1295 db(), base::Bind(adjust_commit_hook, &time_mock, 100));
1296 ASSERT_TRUE(db().BeginTransaction());
1297 EXPECT_TRUE(db().Execute(
1298 "INSERT INTO foo VALUES (11, milliadjust(10))"));
1299 EXPECT_TRUE(db().Execute(
1300 "UPDATE foo SET value = milliadjust(10) WHERE id = 11"));
1301 EXPECT_TRUE(db().CommitTransaction());
1304 scoped_ptr<base::HistogramSamples> samples(
1305 tester.GetHistogramSamplesSinceCreation(kQueryTime));
1306 ASSERT_TRUE(samples);
1307 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1308 // measuring each of BEGIN, INSERT, UPDATE, and COMMIT.
1309 EXPECT_EQ(124, samples->sum());
1311 samples = tester.GetHistogramSamplesSinceCreation(kUpdateTime);
1312 ASSERT_TRUE(samples);
1313 // 10 for insert adjust, 10 for update adjust, 100 for commit adjust, 1 for
1314 // measuring each of INSERT, UPDATE, and COMMIT.
1315 EXPECT_EQ(123, samples->sum());
1317 samples = tester.GetHistogramSamplesSinceCreation(kCommitTime);
1318 ASSERT_TRUE(samples);
1319 // 100 for commit adjust, 1 for measuring COMMIT.
1320 EXPECT_EQ(101, samples->sum());
1322 samples = tester.GetHistogramSamplesSinceCreation(kAutoCommitTime);
1323 EXPECT_TRUE(!samples || samples->sum() == 0);
1326 } // namespace