15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/bind.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/connection.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/meta_table.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sql/statement.h" 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "sql/test/error_callback_support.h" 137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "sql/test/scoped_error_ignorer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/sqlite/sqlite3.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace { 187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Helper to return the count of items in sqlite_master. Return -1 in 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// case of error. 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint SqliteMasterCount(sql::Connection* db) { 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const char* kMasterCount = "SELECT COUNT(*) FROM sqlite_master"; 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::Statement s(db->GetUniqueStatement(kMasterCount)); 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return s.Step() ? s.ColumnInt(0) : -1; 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Track the number of valid references which share the same pointer. 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// This is used to allow testing an implicitly use-after-free case by 297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// explicitly having the ref count live longer than the object. 307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass RefCounter { 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public: 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RefCounter(size_t* counter) 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch : counter_(counter) { 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (*counter_)++; 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RefCounter(const RefCounter& other) 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch : counter_(other.counter_) { 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (*counter_)++; 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ~RefCounter() { 417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (*counter_)--; 427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch private: 457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t* counter_; 467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DISALLOW_ASSIGN(RefCounter); 487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}; 497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Empty callback for implementation of ErrorCallbackSetHelper(). 517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid IgnoreErrorCallback(int error, sql::Statement* stmt) { 527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ErrorCallbackSetHelper(sql::Connection* db, 557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t* counter, 567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const RefCounter& r, 577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int error, sql::Statement* stmt) { 587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The ref count should not go to zero when changing the callback. 597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_GT(*counter, 0u); 607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db->set_error_callback(base::Bind(&IgnoreErrorCallback)); 617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_GT(*counter, 0u); 627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ErrorCallbackResetHelper(sql::Connection* db, 657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t* counter, 667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const RefCounter& r, 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int error, sql::Statement* stmt) { 687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The ref count should not go to zero when clearing the callback. 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_GT(*counter, 0u); 707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db->reset_error_callback(); 717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_GT(*counter, 0u); 727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#if defined(OS_POSIX) 759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Set a umask and restore the old mask on destruction. Cribbed from 769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// shared_memory_unittest.cc. Used by POSIX-only UserPermission test. 779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass ScopedUmaskSetter { 789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public: 799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch explicit ScopedUmaskSetter(mode_t target_mask) { 809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch old_umask_ = umask(target_mask); 819ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 829ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ~ScopedUmaskSetter() { umask(old_umask_); } 839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch private: 849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch mode_t old_umask_; 859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter); 869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#endif 889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SQLConnectionTest : public testing::Test { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SQLConnectionTest() {} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void SetUp() { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db_.Open(db_path())); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void TearDown() { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.Close(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Connection& db() { return db_; } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath db_path() { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return temp_dir_.path().AppendASCII("SQLConnectionTest.db"); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Handle errors by blowing away the database. 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch void RazeErrorCallback(int expected_error, int error, sql::Statement* stmt) { 1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(expected_error, error); 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db_.RazeAndClose(); 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ScopedTempDir temp_dir_; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Connection db_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, Execute) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Valid statement should return true. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SQLITE_OK, db().GetErrorCode()); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invalid statement should fail. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(SQLITE_ERROR, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b")); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, ExecuteWithErrorCode) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(SQLITE_OK, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)")); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(SQLITE_ERROR, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE")); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(SQLITE_ERROR, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db().ExecuteAndReturnErrorCode( 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)")); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, CachedStatement) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::StatementID id1("foo", 12); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)")); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a new cached statement. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetCachedStatement(id1, "SELECT a FROM foo")); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.is_valid()); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(12, s.ColumnInt(0)); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The statement should be cached still. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(db().HasCachedStatement(id1)); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get the same statement using different SQL. This should ignore our 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SQL and use the cached one (so it will be valid). 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetCachedStatement(id1, "something invalid(")); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.is_valid()); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(12, s.ColumnInt(0)); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure other statements aren't marked as cached. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(db().HasCachedStatement(SQL_FROM_HERE)); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, IsSQLValidTest) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo")); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo")); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, DoesStuffExist) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test DoesTableExist. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(db().DoesTableExist("foo")); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(db().DoesTableExist("foo")); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Should be case sensitive. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(db().DoesTableExist("FOO")); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test DoesColumnExist. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(db().DoesColumnExist("foo", "bar")); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(db().DoesColumnExist("foo", "a")); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Testing for a column on a nonexistent table. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(db().DoesColumnExist("bar", "b")); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, GetLastInsertRowId) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)")); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Last insert row ID should be valid. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 row = db().GetLastInsertRowId(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LT(0, row); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It should be the primary key of the row we just inserted. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?")); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt64(0, row); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(12, s.ColumnInt(0)); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, Rollback) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().BeginTransaction()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().BeginTransaction()); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(2, db().transaction_nesting()); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db().RollbackTransaction(); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(db().CommitTransaction()); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(db().BeginTransaction()); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Test the scoped error ignorer by attempting to insert a duplicate 2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// value into an index. 2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TEST_F(SQLConnectionTest, ScopedIgnoreError) { 2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; 2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ASSERT_TRUE(db().Execute(kCreateSql)); 2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) sql::ScopedErrorIgnorer ignore_errors; 2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochTEST_F(SQLConnectionTest, ErrorCallback) { 2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)"; 2357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Execute(kCreateSql)); 2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 2377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int error = SQLITE_OK; 2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorCallback sec( 2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &db(), base::Bind(&sql::CaptureErrorCallback, &error)); 2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 2437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(SQLITE_CONSTRAINT, error); 2447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Callback is no longer in force due to reset. 2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch error = SQLITE_OK; 2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorIgnorer ignore_errors; 2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ignore_errors.IgnoreError(SQLITE_CONSTRAINT); 2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(SQLITE_OK, error); 2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // base::Bind() can curry arguments to be passed by const reference 2579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // to the callback function. If the callback function calls 2589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // re/set_error_callback(), the storage for those arguments can be 2599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // deleted while the callback function is still executing. 2607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // 2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // RefCounter() counts how many objects are live using an external 2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // count. The same counter is passed to the callback, so that it 2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // can check directly even if the RefCounter object is no longer 2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // live. 2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t count = 0; 2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorCallback sec( 2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &db(), base::Bind(&ErrorCallbackSetHelper, 2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &db(), &count, RefCounter(&count))); 2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Same test, but reset_error_callback() case. 2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t count = 0; 2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorCallback sec( 2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &db(), base::Bind(&ErrorCallbackResetHelper, 2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &db(), &count, RefCounter(&count))); 2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)")); 2827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that sql::Connection::Raze() results in a database without the 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tables from the original database. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, Raze) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute(kCreateSql)); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pragma_auto_vacuum = 0; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pragma_auto_vacuum = s.ColumnInt(0); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(pragma_auto_vacuum == 0 || pragma_auto_vacuum == 1); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If auto_vacuum is set, there's an extra page to maintain a freelist. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kExpectedPageCount = 2 + pragma_auto_vacuum; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("PRAGMA page_count")); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kExpectedPageCount, s.ColumnInt(0)); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master")); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("table", s.ColumnString(0)); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("foo", s.ColumnString(1)); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ("foo", s.ColumnString(2)); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Table "foo" is stored in the last page of the file. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kExpectedPageCount, s.ColumnInt(3)); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kCreateSql, s.ColumnString(4)); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Raze()); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("PRAGMA page_count")); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, s.ColumnInt(0)); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(0, SqliteMasterCount(&db())); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("PRAGMA auto_vacuum")); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The new database has the same auto_vacuum as a fresh database. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(pragma_auto_vacuum, s.ColumnInt(0)); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that Raze() maintains page_size. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, RazePageSize) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fetch the default page size and double it for use in this test. 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Scoped to release statement before Close(). 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int default_page_size = 0; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_page_size = s.ColumnInt(0); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(default_page_size, 0); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kPageSize = 2 * default_page_size; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-open the database to allow setting the page size. 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db().Close(); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db().set_page_size(kPageSize); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Open(db_path())); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // page_size should match the indicated value. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(kPageSize, s.ColumnInt(0)); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After raze, page_size should still match the indicated value. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Raze()); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.Reset(true); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(kPageSize, s.ColumnInt(0)); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that Raze() results are seen in other connections. 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, RazeMultiple) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute(kCreateSql)); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Connection other_db; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(other_db.Open(db_path())); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the second connection sees the table. 3777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(1, SqliteMasterCount(&other_db)); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Raze()); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The second connection sees the updated database. 3827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(0, SqliteMasterCount(&other_db)); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, RazeLocked) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute(kCreateSql)); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open a transaction and write some data in a second connection. 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will acquire a PENDING or EXCLUSIVE transaction, which will 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cause the raze to fail. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Connection other_db; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(other_db.Open(db_path())); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(other_db.BeginTransaction()); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')"; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(other_db.Execute(kInsertSql)); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(db().Raze()); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Works after COMMIT. 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(other_db.CommitTransaction()); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Raze()); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-create the database. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute(kCreateSql)); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute(kInsertSql)); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An unfinished read transaction in the other connection also 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blocks raze. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *kQuery = "SELECT COUNT(*) FROM foo"; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(other_db.GetUniqueStatement(kQuery)); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(db().Raze()); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Complete the statement unlocks the database. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(s.Step()); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Raze()); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Verify that Raze() can handle an empty file. SQLite should treat 4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// this as an empty database. 4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochTEST_F(SQLConnectionTest, RazeEmptyDB) { 4237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Execute(kCreateSql)); 4257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db().Close(); 4267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 4282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch file_util::ScopedFILE file(file_util::OpenFile(db_path(), "rb+")); 4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(file.get() != NULL); 4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET)); 4317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(file_util::TruncateFile(file.get())); 4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Open(db_path())); 4357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Raze()); 4367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(0, SqliteMasterCount(&db())); 4377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Verify that Raze() can handle a file of junk. 4407dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochTEST_F(SQLConnectionTest, RazeNOTADB) { 4417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db().Close(); 4427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::Connection::Delete(db_path()); 4437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_FALSE(base::PathExists(db_path())); 4447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 4462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch file_util::ScopedFILE file(file_util::OpenFile(db_path(), "wb")); 4477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(file.get() != NULL); 4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const char* kJunk = "This is the hour of our discontent."; 4507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fputs(kJunk, file.get()); 4517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(base::PathExists(db_path())); 4537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SQLite will successfully open the handle, but will fail with 4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SQLITE_IOERR_SHORT_READ on pragma statemenets which read the 4567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // header. 4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 4587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorIgnorer ignore_errors; 4597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ignore_errors.IgnoreError(SQLITE_IOERR_SHORT_READ); 4607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(db().Open(db_path())); 4617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 4627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(db().Raze()); 4647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db().Close(); 4657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Now empty, the open should open an empty database. 4677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(db().Open(db_path())); 4687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(0, SqliteMasterCount(&db())); 4697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Verify that Raze() can handle a database overwritten with garbage. 4727dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochTEST_F(SQLConnectionTest, RazeNOTADB2) { 4737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 4747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Execute(kCreateSql)); 4757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(1, SqliteMasterCount(&db())); 4767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db().Close(); 4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 4792385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch file_util::ScopedFILE file(file_util::OpenFile(db_path(), "rb+")); 4807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(file.get() != NULL); 4817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(0, fseek(file.get(), 0, SEEK_SET)); 4827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const char* kJunk = "This is the hour of our discontent."; 4847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fputs(kJunk, file.get()); 4857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SQLite will successfully open the handle, but will fail with 4887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // SQLITE_NOTADB on pragma statemenets which attempt to read the 4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // corrupted header. 4907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 4917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorIgnorer ignore_errors; 4927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ignore_errors.IgnoreError(SQLITE_NOTADB); 4937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(db().Open(db_path())); 4947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 4957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(db().Raze()); 4977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db().Close(); 4987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Now empty, the open should succeed with an empty database. 5007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(db().Open(db_path())); 5017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(0, SqliteMasterCount(&db())); 5027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 5037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Test that a callback from Open() can raze the database. This is 5057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// essential for cases where the Open() can fail entirely, so the 5067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Raze() cannot happen later. Additionally test that when the 5077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// callback does this during Open(), the open is retried and succeeds. 5087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// 5097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Most corruptions seen in the wild seem to happen when two pages in 5107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// the database were not written transactionally (the transaction 5117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// changed both, but one wasn't successfully written for some reason). 5127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// A special case of that is when the header indicates that the 5137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// database contains more pages than are in the file. This breaks 5147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// things at a very basic level, verify that Raze() can handle it. 5157dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochTEST_F(SQLConnectionTest, RazeCallbackReopen) { 5167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 5177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Execute(kCreateSql)); 5187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(1, SqliteMasterCount(&db())); 5197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int page_size = 0; 5207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 5217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); 5227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(s.Step()); 5237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch page_size = s.ColumnInt(0); 5247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db().Close(); 5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Trim a single page from the end of the file. 5287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 5292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch file_util::ScopedFILE file(file_util::OpenFile(db_path(), "rb+")); 5307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(file.get() != NULL); 5317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(0, fseek(file.get(), -page_size, SEEK_END)); 5327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(file_util::TruncateFile(file.get())); 5337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Open() will succeed, even though the PRAGMA calls within will 5367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // fail with SQLITE_CORRUPT, as will this PRAGMA. 5377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch { 5387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorIgnorer ignore_errors; 5397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ignore_errors.IgnoreError(SQLITE_CORRUPT); 5407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Open(db_path())); 5417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_FALSE(db().Execute("PRAGMA auto_vacuum")); 5427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db().Close(); 5437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 5447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch db().set_error_callback(base::Bind(&SQLConnectionTest::RazeErrorCallback, 5477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Unretained(this), 5487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SQLITE_CORRUPT)); 5497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // When the PRAGMA calls in Open() raise SQLITE_CORRUPT, the error 5517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // callback will call RazeAndClose(). Open() will then fail and be 5527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // retried. The second Open() on the empty database will succeed 5537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // cleanly. 5547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Open(db_path())); 5557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Execute("PRAGMA auto_vacuum")); 5567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(0, SqliteMasterCount(&db())); 5577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 5587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Basic test of RazeAndClose() operation. 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SQLConnectionTest, RazeAndClose) { 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)"; 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Test that RazeAndClose() closes the database, and that the 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // database is empty when re-opened. 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Execute(kCreateSql)); 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Execute(kPopulateSql)); 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().RazeAndClose()); 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().is_open()); 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db().Close(); 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Open(db_path())); 5727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(0, SqliteMasterCount(&db())); 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Test that RazeAndClose() can break transactions. 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Execute(kCreateSql)); 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Execute(kPopulateSql)); 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().BeginTransaction()); 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().RazeAndClose()); 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().is_open()); 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().CommitTransaction()); 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db().Close(); 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Open(db_path())); 5837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_EQ(0, SqliteMasterCount(&db())); 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Test that various operations fail without crashing after 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RazeAndClose(). 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(SQLConnectionTest, RazeAndCloseDiagnostics) { 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* kPopulateSql = "INSERT INTO foo (value) VALUES (12)"; 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* kSimpleSql = "SELECT 1"; 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Execute(kCreateSql)); 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Execute(kPopulateSql)); 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Test baseline expectations. 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db().Preload(); 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().DoesTableExist("foo")); 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().IsSQLValid(kSimpleSql)); 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(SQLITE_OK, db().ExecuteAndReturnErrorCode(kSimpleSql)); 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().Execute(kSimpleSql)); 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().is_open()); 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement s(db().GetUniqueStatement(kSimpleSql)); 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(s.Step()); 6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(s.Step()); 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().BeginTransaction()); 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().CommitTransaction()); 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().BeginTransaction()); 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db().RollbackTransaction(); 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_TRUE(db().RazeAndClose()); 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // At this point, they should all fail, but not crash. 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db().Preload(); 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().DoesTableExist("foo")); 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().IsSQLValid(kSimpleSql)); 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_EQ(SQLITE_ERROR, db().ExecuteAndReturnErrorCode(kSimpleSql)); 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().Execute(kSimpleSql)); 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().is_open()); 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement s(db().GetUniqueStatement(kSimpleSql)); 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(s.Step()); 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sql::Statement s(db().GetCachedStatement(SQL_FROM_HERE, kSimpleSql)); 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(s.Step()); 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().BeginTransaction()); 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().CommitTransaction()); 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_FALSE(db().BeginTransaction()); 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db().RollbackTransaction(); 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Close normally to reset the poisoned flag. 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db().Close(); 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DEATH tests not supported on Android or iOS. 6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID) && !defined(OS_IOS) 6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Once the real Close() has been called, various calls enforce API 6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // usage by becoming fatal in debug mode. Since DEATH tests are 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // expensive, just test one of them. 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (DLOG_IS_ON(FATAL)) { 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ASSERT_DEATH({ 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) db().IsSQLValid(kSimpleSql); 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }, "Illegal use of connection without a db"); 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(shess): Spin up a background thread to hold other_db, to more 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// closely match real life. That would also allow testing 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RazeWithTimeout(). 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLConnectionTest, SetTempDirForSQL) { 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::MetaTable meta_table; 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Below call needs a temporary directory in sqlite3 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Android, it can pass only when the temporary directory is set. 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise, sqlite3 doesn't find the correct directory to store 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // temporary files and will report the error 'unable to open 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database file'. 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(meta_table.Init(&db(), 4, 4)); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_F(SQLConnectionTest, Delete) { 672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); 673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch db().Close(); 674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Should have both a main database file and a journal file because 676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // of journal_mode PERSIST. 677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); 6787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(base::PathExists(db_path())); 6797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(base::PathExists(journal)); 680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch sql::Connection::Delete(db_path()); 6827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(base::PathExists(db_path())); 6837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_FALSE(base::PathExists(journal)); 684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 6857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 6869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#if defined(OS_POSIX) 6879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Test that set_restrict_to_user() trims database permissions so that 6889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// only the owner (and root) can read. 6899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(SQLConnectionTest, UserPermission) { 6909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // If the bots all had a restrictive umask setting such that 6919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // databases are always created with only the owner able to read 6929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // them, then the code could break without breaking the tests. 6939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Temporarily provide a more permissive umask. 6949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch db().Close(); 6959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch sql::Connection::Delete(db_path()); 6969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_FALSE(base::PathExists(db_path())); 6979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ScopedUmaskSetter permissive_umask(S_IWGRP | S_IWOTH); 6989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(db().Open(db_path())); 6999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Cause the journal file to be created. If the default 7019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // journal_mode is changed back to DELETE, then parts of this test 7029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // will need to be updated. 7039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); 7049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7059ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::FilePath journal(db_path().value() + FILE_PATH_LITERAL("-journal")); 7069ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch int mode; 7079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7089ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Given a permissive umask, the database is created with permissive 7099ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // read access for the database and journal. 7109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(base::PathExists(db_path())); 7119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(base::PathExists(journal)); 7129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch mode = file_util::FILE_PERMISSION_MASK; 7139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_TRUE(file_util::GetPosixFilePermissions(db_path(), &mode)); 7149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_NE((mode & file_util::FILE_PERMISSION_USER_MASK), mode); 7159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch mode = file_util::FILE_PERMISSION_MASK; 7169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_TRUE(file_util::GetPosixFilePermissions(journal, &mode)); 7179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_NE((mode & file_util::FILE_PERMISSION_USER_MASK), mode); 7189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Re-open with restricted permissions and verify that the modes 7209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // changed for both the main database and the journal. 7219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch db().Close(); 7229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch db().set_restrict_to_user(); 7239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(db().Open(db_path())); 7249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(base::PathExists(db_path())); 7259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(base::PathExists(journal)); 7269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch mode = file_util::FILE_PERMISSION_MASK; 7279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_TRUE(file_util::GetPosixFilePermissions(db_path(), &mode)); 7289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_EQ((mode & file_util::FILE_PERMISSION_USER_MASK), mode); 7299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch mode = file_util::FILE_PERMISSION_MASK; 7309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_TRUE(file_util::GetPosixFilePermissions(journal, &mode)); 7319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_EQ((mode & file_util::FILE_PERMISSION_USER_MASK), mode); 7329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Delete and re-create the database, the restriction should still apply. 7349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch db().Close(); 7359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch sql::Connection::Delete(db_path()); 7369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(db().Open(db_path())); 7379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(base::PathExists(db_path())); 7389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_FALSE(base::PathExists(journal)); 7399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch mode = file_util::FILE_PERMISSION_MASK; 7409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_TRUE(file_util::GetPosixFilePermissions(db_path(), &mode)); 7419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_EQ((mode & file_util::FILE_PERMISSION_USER_MASK), mode); 7429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Verify that journal creation inherits the restriction. 7449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); 7459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_TRUE(base::PathExists(journal)); 7469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch mode = file_util::FILE_PERMISSION_MASK; 7479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_TRUE(file_util::GetPosixFilePermissions(journal, &mode)); 7489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ASSERT_EQ((mode & file_util::FILE_PERMISSION_USER_MASK), mode); 7499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 7509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#endif // defined(OS_POSIX) 7519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test that errors start happening once Poison() is called. 753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_F(SQLConnectionTest, Poison) { 754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().Execute("CREATE TABLE x (x)")); 755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Before the Poison() call, things generally work. 757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().IsSQLValid("INSERT INTO x VALUES ('x')")); 758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().Execute("INSERT INTO x VALUES ('x')")); 759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x")); 761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(s.is_valid()); 762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(s.Step()); 763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Get a statement which is valid before and will exist across Poison(). 766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sql::Statement valid_statement( 767ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db().GetUniqueStatement("SELECT COUNT(*) FROM sqlite_master")); 768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(valid_statement.is_valid()); 769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(valid_statement.Step()); 770ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch valid_statement.Reset(true); 771ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 772ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db().Poison(); 773ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 774ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // After the Poison() call, things fail. 775ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(db().IsSQLValid("INSERT INTO x VALUES ('x')")); 776ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(db().Execute("INSERT INTO x VALUES ('x')")); 777ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 778ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM x")); 779ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_FALSE(s.is_valid()); 780ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_FALSE(s.Step()); 781ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 782ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 783ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // The existing statement has become invalid. 784ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_FALSE(valid_statement.is_valid()); 785ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_FALSE(valid_statement.Step()); 786ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 787ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 788ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Test attaching and detaching databases from the connection. 789ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_F(SQLConnectionTest, Attach) { 790ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 791ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 792ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Create a database to attach to. 793ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath attach_path = 794ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db_path().DirName().AppendASCII("SQLConnectionAttach.db"); 795ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const char kAttachmentPoint[] = "other"; 796ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 797ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sql::Connection other_db; 798ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(other_db.Open(attach_path)); 799ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(other_db.Execute("CREATE TABLE bar (a, b)")); 800ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(other_db.Execute("INSERT INTO bar VALUES ('hello', 'world')")); 801ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Cannot see the attached database, yet. 804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar")); 805ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 806ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Attach fails in a transaction. 807ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().BeginTransaction()); 808ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 809ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sql::ScopedErrorIgnorer ignore_errors; 810ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ignore_errors.IgnoreError(SQLITE_ERROR); 811ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(db().AttachDatabase(attach_path, kAttachmentPoint)); 812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 814ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Attach succeeds when the transaction is closed. 816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db().RollbackTransaction(); 817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().AttachDatabase(attach_path, kAttachmentPoint)); 818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar")); 819ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 820ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Queries can touch both databases. 821ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().Execute("INSERT INTO foo SELECT a, b FROM other.bar")); 822ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 823ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sql::Statement s(db().GetUniqueStatement("SELECT COUNT(*) FROM foo")); 824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(s.Step()); 825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_EQ(1, s.ColumnInt(0)); 826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 827ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 828ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Detach also fails in a transaction. 829ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().BeginTransaction()); 830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sql::ScopedErrorIgnorer ignore_errors; 832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ignore_errors.IgnoreError(SQLITE_ERROR); 833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(db().DetachDatabase(kAttachmentPoint)); 834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().IsSQLValid("SELECT count(*) from other.bar")); 835ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 836ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 837ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 838ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Detach succeeds outside of a transaction. 839ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch db().RollbackTransaction(); 840ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_TRUE(db().DetachDatabase(kAttachmentPoint)); 841ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 842ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch EXPECT_FALSE(db().IsSQLValid("SELECT count(*) from other.bar")); 843ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 844ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 8457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 846