Index: sql/sqlite_features_unittest.cc |
diff --git a/sql/sqlite_features_unittest.cc b/sql/sqlite_features_unittest.cc |
index 0f124af3c50a6d5ad8a7bff9f9bdd89150ee87a1..88f7802fc02d5a56fb98a5b3dab7f3268e7220c6 100644 |
--- a/sql/sqlite_features_unittest.cc |
+++ b/sql/sqlite_features_unittest.cc |
@@ -32,8 +32,12 @@ |
// Test that certain features are/are-not enabled in our SQLite. |
+namespace sql { |
namespace { |
+using sql::test::ExecuteWithResult; |
+using sql::test::ExecuteWithResults; |
+ |
void CaptureErrorCallback(int* error_pointer, std::string* sql_text, |
int error, sql::Statement* stmt) { |
*error_pointer = error; |
@@ -41,6 +45,8 @@ void CaptureErrorCallback(int* error_pointer, std::string* sql_text, |
*sql_text = text ? text : "no statement available"; |
} |
+} // namespace |
+ |
class SQLiteFeaturesTest : public sql::SQLTestBase { |
public: |
SQLiteFeaturesTest() : error_(SQLITE_OK) {} |
@@ -102,10 +108,8 @@ TEST_F(SQLiteFeaturesTest, FTS3_Prefix) { |
ASSERT_TRUE(db().Execute("INSERT INTO foo (x) VALUES ('test')")); |
- sql::Statement s(db().GetUniqueStatement( |
- "SELECT x FROM foo WHERE x MATCH 'te*'")); |
- ASSERT_TRUE(s.Step()); |
- EXPECT_EQ("test", s.ColumnString(0)); |
+ EXPECT_EQ("test", |
+ ExecuteWithResult(&db(), "SELECT x FROM foo WHERE x MATCH 'te*'")); |
} |
#endif |
@@ -118,10 +122,9 @@ TEST_F(SQLiteFeaturesTest, UsesUsleep) { |
sqlite3_sleep(1); |
base::TimeDelta delta = base::TimeTicks::Now() - before; |
- // It is not impossible for this to be over 1000 if things are compiled the |
- // right way. But it is very unlikely, most platforms seem to be around |
- // <TBD>. |
- LOG(ERROR) << "Milliseconds: " << delta.InMilliseconds(); |
+ // It is not impossible for this to be over 1000 if things are compiled |
+ // correctly, but that is very unlikely. Most platforms seem to be exactly |
+ // 1ms, with the rest at 2ms, and the worst observed cases was ASAN at 7ms. |
EXPECT_LT(delta.InMilliseconds(), 1000); |
} |
#endif |
@@ -135,28 +138,29 @@ TEST_F(SQLiteFeaturesTest, ForeignKeySupport) { |
"CREATE TABLE children (" |
" id INTEGER PRIMARY KEY," |
" pid INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE)")); |
+ const char kSelectParents[] = "SELECT * FROM parents ORDER BY id"; |
+ const char kSelectChildren[] = "SELECT * FROM children ORDER BY id"; |
// Inserting without a matching parent should fail with constraint violation. |
// Mask off any extended error codes for USE_SYSTEM_SQLITE. |
- int insertErr = db().ExecuteAndReturnErrorCode( |
- "INSERT INTO children VALUES (10, 1)"); |
- EXPECT_EQ(SQLITE_CONSTRAINT, (insertErr&0xff)); |
- |
- size_t rows; |
- EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); |
- EXPECT_EQ(0u, rows); |
+ EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents)); |
+ const int insert_error = |
+ db().ExecuteAndReturnErrorCode("INSERT INTO children VALUES (10, 1)"); |
+ EXPECT_EQ(SQLITE_CONSTRAINT, (insert_error & 0xff)); |
+ EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren)); |
// Inserting with a matching parent should work. |
ASSERT_TRUE(db().Execute("INSERT INTO parents VALUES (1)")); |
+ EXPECT_EQ("1", ExecuteWithResults(&db(), kSelectParents, "|", "\n")); |
EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (11, 1)")); |
EXPECT_TRUE(db().Execute("INSERT INTO children VALUES (12, 1)")); |
- EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); |
- EXPECT_EQ(2u, rows); |
+ EXPECT_EQ("11|1\n12|1", |
+ ExecuteWithResults(&db(), kSelectChildren, "|", "\n")); |
- // Deleting the parent should cascade, i.e., delete the children as well. |
+ // Deleting the parent should cascade, deleting the children as well. |
ASSERT_TRUE(db().Execute("DELETE FROM parents")); |
- EXPECT_TRUE(sql::test::CountTableRows(&db(), "children", &rows)); |
- EXPECT_EQ(0u, rows); |
+ EXPECT_EQ("", ExecuteWithResult(&db(), kSelectParents)); |
+ EXPECT_EQ("", ExecuteWithResult(&db(), kSelectChildren)); |
} |
#if defined(MOJO_APPTEST_IMPL) || defined(OS_IOS) |
@@ -453,4 +457,36 @@ TEST_F(SQLiteFeaturesTest, SmartAutoVacuum) { |
} |
#endif // !defined(USE_SYSTEM_SQLITE) |
-} // namespace |
+#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
|
+// SQLite WAL mode defaults to checkpointing the WAL on close. This would push |
+// additional work into Chromium shutdown. Verify that SQLite supports a config |
+// option to not checkpoint on close. |
+TEST_F(SQLiteFeaturesTest, WALNoClose) { |
Scott Hess - ex-Googler
2017/04/18 23:53:39
Um, this is the main test for whether the desired
|
+ base::FilePath wal_path(db_path().value() + FILE_PATH_LITERAL("-wal")); |
+ |
+ // Turn on WAL mode, then verify that the mode changed (WAL is supported). |
+ ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL")); |
+ ASSERT_EQ("wal", ExecuteWithResult(&db(), "PRAGMA journal_mode")); |
+ |
+ // The WAL file is created lazily on first change. |
+ ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); |
+ |
+ // By default, the WAL is checkpointed then deleted on close. |
+ ASSERT_TRUE(GetPathExists(wal_path)); |
+ db().Close(); |
+ ASSERT_FALSE(GetPathExists(wal_path)); |
+ |
+ // Reopen and configure the database to not checkpoint WAL on close. |
+ ASSERT_TRUE(Reopen()); |
+ ASSERT_TRUE(db().Execute("PRAGMA journal_mode = WAL")); |
+ ASSERT_TRUE(db().Execute("ALTER TABLE foo ADD COLUMN c")); |
+ ASSERT_EQ( |
+ SQLITE_OK, |
+ sqlite3_db_config(db().db_, SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, 1, NULL)); |
+ ASSERT_TRUE(GetPathExists(wal_path)); |
+ db().Close(); |
+ ASSERT_TRUE(GetPathExists(wal_path)); |
+} |
+#endif |
+ |
+} // namespace sql |