| 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" |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/files/memory_mapped_file.h" | 12 #include "base/files/memory_mapped_file.h" |
| 13 #include "base/files/scoped_temp_dir.h" | 13 #include "base/files/scoped_temp_dir.h" |
| 14 #include "sql/connection.h" | 14 #include "sql/connection.h" |
| 15 #include "sql/statement.h" | 15 #include "sql/statement.h" |
| 16 #include "sql/test/sql_test_base.h" | 16 #include "sql/test/sql_test_base.h" |
| 17 #include "sql/test/test_helpers.h" | 17 #include "sql/test/test_helpers.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 #include "third_party/sqlite/sqlite3.h" | 19 #include "third_party/sqlite/sqlite3.h" |
| 20 | 20 |
| 21 #if defined(OS_IOS) | 21 #if defined(OS_IOS) |
| 22 #include "base/ios/ios_util.h" | 22 #include "base/ios/ios_util.h" |
| 23 #endif | 23 #endif |
| 24 | 24 |
| 25 // Test that certain features are/are-not enabled in our SQLite. | 25 // Test that certain features are/are-not enabled in our SQLite. |
| 26 | 26 |
| 27 namespace sql { |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 30 using sql::test::ExecuteWithResult; |
| 31 using sql::test::ExecuteWithResults; |
| 32 |
| 29 void CaptureErrorCallback(int* error_pointer, std::string* sql_text, | 33 void CaptureErrorCallback(int* error_pointer, std::string* sql_text, |
| 30 int error, sql::Statement* stmt) { | 34 int error, sql::Statement* stmt) { |
| 31 *error_pointer = error; | 35 *error_pointer = error; |
| 32 const char* text = stmt ? stmt->GetSQLStatement() : NULL; | 36 const char* text = stmt ? stmt->GetSQLStatement() : NULL; |
| 33 *sql_text = text ? text : "no statement available"; | 37 *sql_text = text ? text : "no statement available"; |
| 34 } | 38 } |
| 35 | 39 |
| 40 } // namespace |
| 41 |
| 36 class SQLiteFeaturesTest : public sql::SQLTestBase { | 42 class SQLiteFeaturesTest : public sql::SQLTestBase { |
| 37 public: | 43 public: |
| 38 SQLiteFeaturesTest() : error_(SQLITE_OK) {} | 44 SQLiteFeaturesTest() : error_(SQLITE_OK) {} |
| 39 | 45 |
| 40 void SetUp() override { | 46 void SetUp() override { |
| 41 SQLTestBase::SetUp(); | 47 SQLTestBase::SetUp(); |
| 42 | 48 |
| 43 // The error delegate will set |error_| and |sql_text_| when any sqlite | 49 // The error delegate will set |error_| and |sql_text_| when any sqlite |
| 44 // statement operation returns an error code. | 50 // statement operation returns an error code. |
| 45 db().set_error_callback( | 51 db().set_error_callback( |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 // Originally history used fts2, which Chromium patched to treat "foo*" as a | 93 // Originally history used fts2, which Chromium patched to treat "foo*" as a |
| 88 // prefix search, though the icu tokenizer would return it as two tokens {"foo", | 94 // prefix search, though the icu tokenizer would return it as two tokens {"foo", |
| 89 // "*"}. Test that fts3 works correctly. | 95 // "*"}. Test that fts3 works correctly. |
| 90 TEST_F(SQLiteFeaturesTest, FTS3_Prefix) { | 96 TEST_F(SQLiteFeaturesTest, FTS3_Prefix) { |
| 91 const char kCreateSql[] = | 97 const char kCreateSql[] = |
| 92 "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)"; | 98 "CREATE VIRTUAL TABLE foo USING fts3(x, tokenize icu)"; |
| 93 ASSERT_TRUE(db().Execute(kCreateSql)); | 99 ASSERT_TRUE(db().Execute(kCreateSql)); |
| 94 | 100 |
| 95 ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')")); | 101 ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')")); |
| 96 | 102 |
| 97 sql::Statement s(db().GetUniqueStatement( | 103 EXPECT_EQ("test", |
| 98 "SELECT x FROM foo WHERE x MATCH 'te*'")); | 104 ExecuteWithResult(&db(), "SELECT x FROM foo WHERE x MATCH 'te*'")); |
| 99 ASSERT_TRUE(s.Step()); | |
| 100 EXPECT_EQ("test", s.ColumnString(0)); | |
| 101 } | 105 } |
| 102 #endif | 106 #endif |
| 103 | 107 |
| 104 #if !defined(USE_SYSTEM_SQLITE) | 108 #if !defined(USE_SYSTEM_SQLITE) |
| 105 // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With | 109 // Verify that Chromium's SQLite is compiled with HAVE_USLEEP defined. With |
| 106 // HAVE_USLEEP, SQLite uses usleep() with millisecond granularity. Otherwise it | 110 // HAVE_USLEEP, SQLite uses usleep() with millisecond granularity. Otherwise it |
| 107 // uses sleep() with second granularity. | 111 // uses sleep() with second granularity. |
| 108 TEST_F(SQLiteFeaturesTest, UsesUsleep) { | 112 TEST_F(SQLiteFeaturesTest, UsesUsleep) { |
| 109 base::TimeTicks before = base::TimeTicks::Now(); | 113 base::TimeTicks before = base::TimeTicks::Now(); |
| 110 sqlite3_sleep(1); | 114 sqlite3_sleep(1); |
| 111 base::TimeDelta delta = base::TimeTicks::Now() - before; | 115 base::TimeDelta delta = base::TimeTicks::Now() - before; |
| 112 | 116 |
| 113 // It is not impossible for this to be over 1000 if things are compiled the | 117 // It is not impossible for this to be over 1000 if things are compiled |
| 114 // right way. But it is very unlikely, most platforms seem to be around | 118 // correctly, but that is very unlikely. Most platforms seem to be exactly |
| 115 // <TBD>. | 119 // 1ms, with the test at 2ms, the worst observed cases was ASAN at 7ms. |
| 116 LOG(ERROR) << "Milliseconds: " << delta.InMilliseconds(); | |
| 117 EXPECT_LT(delta.InMilliseconds(), 1000); | 120 EXPECT_LT(delta.InMilliseconds(), 1000); |
| 118 } | 121 } |
| 119 #endif | 122 #endif |
| 120 | 123 |
| 121 // Ensure that our SQLite version has working foreign key support with cascade | 124 // Ensure that our SQLite version has working foreign key support with cascade |
| 122 // delete support. | 125 // delete support. |
| 123 TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { | 126 TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { |
| 124 ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1")); | 127 ASSERT_TRUE(db().Execute("PRAGMA foreign_keys=1")); |
| 125 ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)")); | 128 ASSERT_TRUE(db().Execute("CREATE TABLE parents (id INTEGER PRIMARY KEY)")); |
| 126 ASSERT_TRUE(db().Execute( | 129 ASSERT_TRUE(db().Execute( |
| 127 "CREATE TABLE children (" | 130 "CREATE TABLE children (" |
| 128 " id INTEGER PRIMARY KEY," | 131 " id INTEGER PRIMARY KEY," |
| 129 " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)")); | 132 " pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)")); |
| 133 const char kSelectParents[] = "SELECT * FROM parents ORDER BY id"; |
| 134 const char kSelectChildren[] = "SELECT * FROM children ORDER BY id"; |
| 130 | 135 |
| 131 // Inserting without a matching parent should fail with constraint violation. | 136 // Inserting without a matching parent should fail with constraint violation. |
| 132 // Mask off any extended error codes for USE_SYSTEM_SQLITE. | 137 // Mask off any extended error codes for USE_SYSTEM_SQLITE. |
| 133 int insertErr = db().ExecuteAndReturnErrorCode( | 138 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents)); |
| 139 const int insert_error = db().ExecuteAndReturnErrorCode( |
| 134 "INSERT INTO children VALUES (10, 1)"); | 140 "INSERT INTO children VALUES (10, 1)"); |
| 135 EXPECT_EQ(SQLITE_CONSTRAINT, (insertErr&0xff)); | 141 EXPECT_EQ(SQLITE_CONSTRAINT, (insert_error&0xff)); |
| 136 | 142 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren)); |
| 137 size_t rows; | |
| 138 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); | |
| 139 EXPECT_EQ(0u, rows); | |
| 140 | 143 |
| 141 // Inserting with a matching parent should work. | 144 // Inserting with a matching parent should work. |
| 142 ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)")); | 145 ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)")); |
| 146 EXPECT_EQ("1", ExecuteWithResults(&db(), kSelectParents, "|", "\n")); |
| 143 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)")); | 147 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)")); |
| 144 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)")); | 148 EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)")); |
| 145 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); | 149 EXPECT_EQ("11|1\n12|1", |
| 146 EXPECT_EQ(2u, rows); | 150 ExecuteWithResults(&db(), kSelectChildren, "|", "\n")); |
| 147 | 151 |
| 148 // Deleting the parent should cascade, i.e., delete the children as well. | 152 // Deleting the parent should cascade, deleting the children as well. |
| 149 ASSERT_TRUE(db().Execute("DELETE FROM parents")); | 153 ASSERT_TRUE(db().Execute("DELETE FROM parents")); |
| 150 EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); | 154 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents)); |
| 151 EXPECT_EQ(0u, rows); | 155 EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren)); |
| 152 } | 156 } |
| 153 | 157 |
| 154 #if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS) | 158 #if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS) |
| 155 // If the platform cannot support SQLite mmap'ed I/O, make sure SQLite isn't | 159 // If the platform cannot support SQLite mmap'ed I/O, make sure SQLite isn't |
| 156 // offering to support it. | 160 // offering to support it. |
| 157 TEST_F(SQLiteFeaturesTest, NoMmap) { | 161 TEST_F(SQLiteFeaturesTest, NoMmap) { |
| 158 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE) | 162 #if defined(OS_IOS) && defined(USE_SYSTEM_SQLITE) |
| 159 if (base::ios::IsRunningOnIOS10OrLater()) { | 163 if (base::ios::IsRunningOnIOS10OrLater()) { |
| 160 // iOS 10 added mmap support for sqlite. | 164 // iOS 10 added mmap support for sqlite. |
| 161 return; | 165 return; |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 s.BindString(0, ".*test"); | 300 s.BindString(0, ".*test"); |
| 297 ASSERT_TRUE(s.Step()); | 301 ASSERT_TRUE(s.Step()); |
| 298 EXPECT_EQ(3, s.ColumnInt(0)); | 302 EXPECT_EQ(3, s.ColumnInt(0)); |
| 299 | 303 |
| 300 s.Reset(true); | 304 s.Reset(true); |
| 301 s.BindString(0, ".* s[a-z]+"); | 305 s.BindString(0, ".* s[a-z]+"); |
| 302 ASSERT_TRUE(s.Step()); | 306 ASSERT_TRUE(s.Step()); |
| 303 EXPECT_EQ(7, s.ColumnInt(0)); | 307 EXPECT_EQ(7, s.ColumnInt(0)); |
| 304 } | 308 } |
| 305 | 309 |
| 306 } // namespace | 310 #if !defined(USE_SYSTEM_SQLITE) |
| 311 // SQLite WAL mode defaults to checkpointing the WAL on close. This would push |
| 312 // additional work into Chromium shutdown. Verify that SQLite supports a config |
| 313 // option to not checkpoint on close. |
| 314 TEST_F(SQLiteFeaturesTest, WALNoClose) { |
| 315 base::FilePath wal(db_path().value() + FILE_PATH_LITERAL("-wal")); |
| 316 |
| 317 // Turn on WAL mode, then verify that it worked. |
| 318 ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL")); |
| 319 ASSERT_EQ("wal", ExecuteWithResult(&db(), "PRAGMA journal_mode")); |
| 320 |
| 321 // The WAL file is created lazily on first change. |
| 322 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); |
| 323 |
| 324 // By default, the WAL is checkpointed and deleted on close. |
| 325 ASSERT_TRUE(GetPathExists(wal)); |
| 326 db().Close(); |
| 327 ASSERT_FALSE(GetPathExists(wal)); |
| 328 |
| 329 // Reopen and configure the database to not checkpoint WAL on close. |
| 330 ASSERT_TRUE(Reopen()); |
| 331 ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL")); |
| 332 ASSERT_TRUE(db().Execute("ALTER TABLE foo ADD COLUMN c")); |
| 333 ASSERT_EQ(SQLITE_OK, |
| 334 sqlite3_db_config(db().db_, SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, |
| 335 1, NULL)); |
| 336 ASSERT_TRUE(GetPathExists(wal)); |
| 337 db().Close(); |
| 338 ASSERT_TRUE(GetPathExists(wal)); |
| 339 } |
| 340 #endif |
| 341 |
| 342 } // namespace sql |
| OLD | NEW |