Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 #if defined(OS_MACOSX) && !defined(OS_IOS) | 25 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 26 #include <CoreFoundation/CoreFoundation.h> | 26 #include <CoreFoundation/CoreFoundation.h> |
| 27 #include <CoreServices/CoreServices.h> | 27 #include <CoreServices/CoreServices.h> |
| 28 | 28 |
| 29 #include "base/mac/mac_util.h" | 29 #include "base/mac/mac_util.h" |
| 30 #include "base/mac/scoped_cftyperef.h" | 30 #include "base/mac/scoped_cftyperef.h" |
| 31 #endif | 31 #endif |
| 32 | 32 |
| 33 // Test that certain features are/are-not enabled in our SQLite. | 33 // Test that certain features are/are-not enabled in our SQLite. |
| 34 | 34 |
| 35 namespace sql { | |
| 35 namespace { | 36 namespace { |
| 36 | 37 |
| 38 using sql::test::ExecuteWithResult; | |
| 39 using sql::test::ExecuteWithResults; | |
| 40 | |
| 37 void CaptureErrorCallback(int* error_pointer, std::string* sql_text, | 41 void CaptureErrorCallback(int* error_pointer, std::string* sql_text, |
| 38 int error, sql::Statement* stmt) { | 42 int error, sql::Statement* stmt) { |
| 39 *error_pointer = error; | 43 *error_pointer = error; |
| 40 const char* text = stmt ? stmt->GetSQLStatement() : NULL; | 44 const char* text = stmt ? stmt->GetSQLStatement() : NULL; |
| 41 *sql_text = text ? text : "no statement available"; | 45 *sql_text = text ? text : "no statement available"; |
| 42 } | 46 } |
| 43 | 47 |
| 48 } // namespace | |
| 49 | |
| 44 class SQLiteFeaturesTest : public sql::SQLTestBase { | 50 class SQLiteFeaturesTest : public sql::SQLTestBase { |
| 45 public: | 51 public: |
| 46 SQLiteFeaturesTest() : error_(SQLITE_OK) {} | 52 SQLiteFeaturesTest() : error_(SQLITE_OK) {} |
| 47 | 53 |
| 48 void SetUp() override { | 54 void SetUp() override { |
| 49 SQLTestBase::SetUp(); | 55 SQLTestBase::SetUp(); |
| 50 | 56 |
| 51 // The error delegate will set |error_| and |sql_text_| when any sqlite | 57 // The error delegate will set |error_| and |sql_text_| when any sqlite |
| 52 // statement operation returns an error code. | 58 // statement operation returns an error code. |
| 53 db().set_error_callback( | 59 db().set_error_callback( |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 // Originally history used fts2, which Chromium patched to treat "foo*" as a | 101 // Originally history used fts2, which Chromium patched to treat "foo*" as a |
| 96 // prefix search, though the icu tokenizer would return it as two tokens {"foo", | 102 // prefix search, though the icu tokenizer would return it as two tokens {"foo", |
| 97 // "*"}. Test that fts3 works correctly. | 103 // "*"}. Test that fts3 works correctly. |
| 98 TEST_F(SQLiteFeaturesTest, FTS3_Prefix) { | 104 TEST_F(SQLiteFeaturesTest, FTS3_Prefix) { |
| 99 const char kCreateSql[] = | 105 const char kCreateSql[] = |
| 100 "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)"; | 106 "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)"; |
| 101 ASSERT_TRUE(db().Execute(kCreateSql)); | 107 ASSERT_TRUE(db().Execute(kCreateSql)); |
| 102 | 108 |
| 103 ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')")); | 109 ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')")); |
| 104 | 110 |
| 105 sql::Statement s(db().GetUniqueStatement( | 111 EXPECT_EQ("test", |
| 106 "SELECT x FROM foo WHERE x MATCH 'te*'")); | 112 ExecuteWithResult(&db(), "SELECT x FROM foo WHERE x MATCH 'te*'")); |
| 107 ASSERT_TRUE(s.Step()); | |
| 108 EXPECT_EQ("test", s.ColumnString(0)); | |
| 109 } | 113 } |
| 110 #endif | 114 #endif |
| 111 | 115 |
| 112 #if !defined(USE_SYSTEM_SQLITE) | 116 #if !defined(USE_SYSTEM_SQLITE) |
| 113 // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With | 117 // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With |
| 114 // HAVE_USLEEP, SQLite uses usleep() with millisecond granularity. Otherwise it | 118 // HAVE_USLEEP, SQLite uses usleep() with millisecond granularity. Otherwise it |
| 115 // uses sleep() with second granularity. | 119 // uses sleep() with second granularity. |
| 116 TEST_F(SQLiteFeaturesTest, UsesUsleep) { | 120 TEST_F(SQLiteFeaturesTest, UsesUsleep) { |
| 117 base::TimeTicks before = base::TimeTicks::Now(); | 121 base::TimeTicks before = base::TimeTicks::Now(); |
| 118 sqlite3_sleep(1); | 122 sqlite3_sleep(1); |
| 119 base::TimeDelta delta = base::TimeTicks::Now() - before; | 123 base::TimeDelta delta = base::TimeTicks::Now() - before; |
| 120 | 124 |
| 121 // It is not impossible for this to be over 1000 if things are compiled the | 125 // It is not impossible for this to be over 1000 if things are compiled |
| 122 // right way. But it is very unlikely, most platforms seem to be around | 126 // correctly, but that is very unlikely. Most platforms seem to be exactly |
| 123 // <TBD>. | 127 // 1ms, with the rest at 2ms, and the worst observed cases was ASAN at 7ms. |
| 124 LOG(ERROR) << "Milliseconds: " << delta.InMilliseconds(); | |
| 125 EXPECT_LT(delta.InMilliseconds(), 1000); | 128 EXPECT_LT(delta.InMilliseconds(), 1000); |
| 126 } | 129 } |
| 127 #endif | 130 #endif |
| 128 | 131 |
| 129 // Ensure that our SQLite version has working foreign key support with cascade | 132 // Ensure that our SQLite version has working foreign key support with cascade |
| 130 // delete support. | 133 // delete support. |
| 131 TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { | 134 TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { |
| 132 ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1")); | 135 ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1")); |
| 133 ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)")); | 136 ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)")); |
| 134 ASSERT_TRUE(db().Execute( | 137 ASSERT_TRUE(db().Execute( |
| 135 "CREATE TABLE children (" | 138 "CREATE TABLE children (" |
| 136 " id INTEGER PRIMARY KEY," | 139 " id INTEGER PRIMARY KEY," |
| 137 " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)")); | 140 " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)")); |
| 141 const char kSelectParents[] = "SELECT * FROM parents ORDER BY id"; | |
| 142 const char kSelectChildren[] = "SELECT * FROM children ORDER BY id"; | |
| 138 | 143 |
| 139 // Inserting without a matching parent should fail with constraint violation. | 144 // Inserting without a matching parent should fail with constraint violation. |
| 140 // Mask off any extended error codes for USE_SYSTEM_SQLITE. | 145 // Mask off any extended error codes for USE_SYSTEM_SQLITE. |
| 141 int insertErr = db().ExecuteAndReturnErrorCode( | 146 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents)); |
| 142 "INSERT INTO children VALUES (10, 1)"); | 147 const int insert_error = |
| 143 EXPECT_EQ(SQLITE_CONSTRAINT, (insertErr&0xff)); | 148 db().ExecuteAndReturnErrorCode("INSERT INTO children VALUES (10, 1)"); |
| 144 | 149 EXPECT_EQ(SQLITE_CONSTRAINT, (insert_error & 0xff)); |
| 145 size_t rows; | 150 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren)); |
| 146 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); | |
| 147 EXPECT_EQ(0u, rows); | |
| 148 | 151 |
| 149 // Inserting with a matching parent should work. | 152 // Inserting with a matching parent should work. |
| 150 ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)")); | 153 ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)")); |
| 154 EXPECT_EQ("1", ExecuteWithResults(&db(), kSelectParents, "|", "\n")); | |
| 151 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)")); | 155 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)")); |
| 152 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)")); | 156 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)")); |
| 153 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); | 157 EXPECT_EQ("11|1\n12|1", |
| 154 EXPECT_EQ(2u, rows); | 158 ExecuteWithResults(&db(), kSelectChildren, "|", "\n")); |
| 155 | 159 |
| 156 // Deleting the parent should cascade, i.e., delete the children as well. | 160 // Deleting the parent should cascade, deleting the children as well. |
| 157 ASSERT_TRUE(db().Execute("DELETE FROM parents")); | 161 ASSERT_TRUE(db().Execute("DELETE FROM parents")); |
| 158 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); | 162 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents)); |
| 159 EXPECT_EQ(0u, rows); | 163 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren)); |
| 160 } | 164 } |
| 161 | 165 |
| 162 #if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS) | 166 #if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS) |
| 163 // If the platform cannot support SQLite mmap'ed I/O, make sure SQLite isn't | 167 // If the platform cannot support SQLite mmap'ed I/O, make sure SQLite isn't |
| 164 // offering to support it. | 168 // offering to support it. |
| 165 TEST_F(SQLiteFeaturesTest, NoMmap) { | 169 TEST_F(SQLiteFeaturesTest, NoMmap) { |
| 166 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE) | 170 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE) |
| 167 if (base::ios::IsRunningOnIOS10OrLater()) { | 171 if (base::ios::IsRunningOnIOS10OrLater()) { |
| 168 // iOS 10 added mmap support for sqlite. | 172 // iOS 10 added mmap support for sqlite. |
| 169 return; | 173 return; |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 446 s.Reset(true); | 450 s.Reset(true); |
| 447 ASSERT_TRUE(s.Run()); | 451 ASSERT_TRUE(s.Run()); |
| 448 | 452 |
| 449 ASSERT_TRUE(base::GetFileSize(db_path(), &file_size_after)); | 453 ASSERT_TRUE(base::GetFileSize(db_path(), &file_size_after)); |
| 450 ASSERT_EQ(file_size_after, file_size_before - 4096); | 454 ASSERT_EQ(file_size_after, file_size_before - 4096); |
| 451 } | 455 } |
| 452 #endif | 456 #endif |
| 453 } | 457 } |
| 454 #endif // !defined(USE_SYSTEM_SQLITE) | 458 #endif // !defined(USE_SYSTEM_SQLITE) |
| 455 | 459 |
| 456 } // namespace | 460 #if !defined(USE_SYSTEM_SQLITE) |
|
pwnall
2017/04/19 20:02:23
Would tests fail anywhere if we removed this #if?
Scott Hess - ex-Googler
2017/04/19 20:15:33
iOS uses the system SQLite. Also maybe Linux dist
pwnall
2017/04/19 20:56:54
TL;DR: If the test passes on bots, I'd leave it on
Scott Hess - ex-Googler
2017/04/19 22:03:16
The SQLite change landed last fall, so it's pretty
| |
| 461 // SQLite WAL mode defaults to checkpointing the WAL on close. This would push | |
| 462 // additional work into Chromium shutdown. Verify that SQLite supports a config | |
| 463 // option to not checkpoint on close. | |
| 464 TEST_F(SQLiteFeaturesTest, WALNoClose) { | |
|
Scott Hess - ex-Googler
2017/04/18 23:53:39
Um, this is the main test for whether the desired
| |
| 465 base::FilePath wal_path(db_path().value() + FILE_PATH_LITERAL("-wal")); | |
| 466 | |
| 467 // Turn on WAL mode, then verify that the mode changed (WAL is supported). | |
| 468 ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL")); | |
| 469 ASSERT_EQ("wal", ExecuteWithResult(&db(), "PRAGMA journal_mode")); | |
| 470 | |
| 471 // The WAL file is created lazily on first change. | |
| 472 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); | |
| 473 | |
| 474 // By default, the WAL is checkpointed then deleted on close. | |
| 475 ASSERT_TRUE(GetPathExists(wal_path)); | |
| 476 db().Close(); | |
| 477 ASSERT_FALSE(GetPathExists(wal_path)); | |
| 478 | |
| 479 // Reopen and configure the database to not checkpoint WAL on close. | |
| 480 ASSERT_TRUE(Reopen()); | |
| 481 ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL")); | |
| 482 ASSERT_TRUE(db().Execute("ALTER TABLE foo ADD COLUMN c")); | |
| 483 ASSERT_EQ( | |
| 484 SQLITE_OK, | |
| 485 sqlite3_db_config(db().db_, SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, 1, NULL)); | |
| 486 ASSERT_TRUE(GetPathExists(wal_path)); | |
| 487 db().Close(); | |
| 488 ASSERT_TRUE(GetPathExists(wal_path)); | |
| 489 } | |
| 490 #endif | |
| 491 | |
| 492 } // namespace sql | |
| OLD | NEW |