OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/file_util.h" | 5 #include "base/file_util.h" |
6 #include "base/scoped_temp_dir.h" | 6 #include "base/scoped_temp_dir.h" |
7 #include "sql/connection.h" | 7 #include "sql/connection.h" |
8 #include "sql/statement.h" | 8 #include "sql/statement.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 #include "third_party/sqlite/sqlite3.h" | 10 #include "third_party/sqlite/sqlite3.h" |
11 | 11 |
12 class SQLConnectionTest : public testing::Test { | 12 class SQLConnectionTest : public testing::Test { |
13 public: | 13 public: |
14 SQLConnectionTest() {} | 14 SQLConnectionTest() {} |
15 | 15 |
16 void SetUp() { | 16 void SetUp() { |
17 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | 17 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
18 ASSERT_TRUE(db_.Open(temp_dir_.path().AppendASCII("SQLConnectionTest.db"))); | 18 ASSERT_TRUE(db_.Open(db_path())); |
19 } | 19 } |
20 | 20 |
21 void TearDown() { | 21 void TearDown() { |
22 db_.Close(); | 22 db_.Close(); |
23 } | 23 } |
24 | 24 |
25 sql::Connection& db() { return db_; } | 25 sql::Connection& db() { return db_; } |
26 | 26 |
27 FilePath db_path() { | |
28 return temp_dir_.path().AppendASCII("SQLConnectionTest.db"); | |
29 } | |
30 | |
27 private: | 31 private: |
28 ScopedTempDir temp_dir_; | 32 ScopedTempDir temp_dir_; |
29 sql::Connection db_; | 33 sql::Connection db_; |
30 }; | 34 }; |
31 | 35 |
32 TEST_F(SQLConnectionTest, Execute) { | 36 TEST_F(SQLConnectionTest, Execute) { |
33 // Valid statement should return true. | 37 // Valid statement should return true. |
34 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); | 38 ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); |
35 EXPECT_EQ(SQLITE_OK, db().GetErrorCode()); | 39 EXPECT_EQ(SQLITE_OK, db().GetErrorCode()); |
36 | 40 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 // Last insert row ID should be valid. | 117 // Last insert row ID should be valid. |
114 int64 row = db().GetLastInsertRowId(); | 118 int64 row = db().GetLastInsertRowId(); |
115 EXPECT_LT(0, row); | 119 EXPECT_LT(0, row); |
116 | 120 |
117 // It should be the primary key of the row we just inserted. | 121 // It should be the primary key of the row we just inserted. |
118 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?")); | 122 sql::Statement s(db().GetUniqueStatement("SELECT value FROM foo WHERE id=?")); |
119 s.BindInt64(0, row); | 123 s.BindInt64(0, row); |
120 ASSERT_TRUE(s.Step()); | 124 ASSERT_TRUE(s.Step()); |
121 EXPECT_EQ(12, s.ColumnInt(0)); | 125 EXPECT_EQ(12, s.ColumnInt(0)); |
122 } | 126 } |
127 | |
128 // Test that sql::Connection::Raze() results in a database without the | |
129 // tables from the original database. | |
130 TEST_F(SQLConnectionTest, Raze) { | |
131 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | |
132 ASSERT_TRUE(db().Execute(kCreateSql)); | |
133 ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); | |
134 | |
135 { | |
136 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count")); | |
137 ASSERT_TRUE(s.Step()); | |
138 EXPECT_EQ(2, s.ColumnInt(0)); | |
Greg Billock
2012/03/31 01:23:50
is this impl-dependent? that is, won't the page co
Scott Hess - ex-Googler
2012/04/04 01:28:25
Shouldn't ever vary. There should be the special
| |
139 } | |
140 | |
141 { | |
142 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master")); | |
143 ASSERT_TRUE(s.Step()); | |
144 EXPECT_EQ("table", s.ColumnString(0)); | |
145 EXPECT_EQ("foo", s.ColumnString(1)); | |
146 EXPECT_EQ("foo", s.ColumnString(2)); | |
147 EXPECT_EQ(2, s.ColumnInt(3)); | |
148 EXPECT_EQ(kCreateSql, s.ColumnString(4)); | |
149 } | |
150 | |
151 ASSERT_TRUE(db().Raze()); | |
152 | |
153 { | |
154 sql::Statement s(db().GetUniqueStatement("PRAGMA page_count")); | |
155 ASSERT_TRUE(s.Step()); | |
156 EXPECT_EQ(1, s.ColumnInt(0)); | |
157 } | |
158 | |
159 { | |
160 sql::Statement s(db().GetUniqueStatement("SELECT * FROM sqlite_master")); | |
161 ASSERT_FALSE(s.Step()); | |
162 } | |
163 } | |
164 | |
165 // Test that Raze() maintains page_size. | |
166 TEST_F(SQLConnectionTest, RazePageSize) { | |
167 const int kPageSize = 4096; | |
168 | |
169 // Make sure that the default size isn't already |kPageSize|. | |
170 // Scoped to release statement before Close(). | |
171 { | |
172 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); | |
173 ASSERT_TRUE(s.Step()); | |
174 ASSERT_NE(kPageSize, s.ColumnInt(0)); | |
175 } | |
176 | |
177 // Re-open the database to allow setting the page size. | |
178 db().Close(); | |
179 db().set_page_size(kPageSize); | |
180 ASSERT_TRUE(db().Open(db_path())); | |
181 | |
182 // page_size should match the indicated value. | |
183 sql::Statement s(db().GetUniqueStatement("PRAGMA page_size")); | |
184 ASSERT_TRUE(s.Step()); | |
185 ASSERT_EQ(kPageSize, s.ColumnInt(0)); | |
186 | |
187 // After raze, page_size should still match the indicated value. | |
188 ASSERT_TRUE(db().Raze()); | |
189 s.Reset(); | |
190 ASSERT_TRUE(s.Step()); | |
191 ASSERT_EQ(kPageSize, s.ColumnInt(0)); | |
192 } | |
193 | |
194 // Test that Raze() results are seen in other connections. | |
195 TEST_F(SQLConnectionTest, RazeMultiple) { | |
196 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | |
197 ASSERT_TRUE(db().Execute(kCreateSql)); | |
198 | |
199 sql::Connection other_db; | |
200 ASSERT_TRUE(other_db.Open(db_path())); | |
201 | |
202 // Check that the second connection sees the table. | |
203 const char *kTablesQuery = "SELECT COUNT(*) FROM sqlite_master"; | |
204 sql::Statement s(other_db.GetUniqueStatement(kTablesQuery)); | |
205 ASSERT_TRUE(s.Step()); | |
206 ASSERT_EQ(1, s.ColumnInt(0)); | |
207 ASSERT_FALSE(s.Step()); // Releases the shared lock. | |
208 | |
209 ASSERT_TRUE(db().Raze()); | |
210 | |
211 // The second connection sees the updated database. | |
212 s.Reset(); | |
213 ASSERT_TRUE(s.Step()); | |
214 ASSERT_EQ(0, s.ColumnInt(0)); | |
215 } | |
216 | |
217 TEST_F(SQLConnectionTest, RazeLocked) { | |
218 const char* kCreateSql = "CREATE TABLE foo (id INTEGER PRIMARY KEY, value)"; | |
219 ASSERT_TRUE(db().Execute(kCreateSql)); | |
220 | |
221 // Open a transaction and write some data in a second connection. | |
222 // This will acquire a PENDING or EXCLUSIVE transaction, which will | |
223 // cause the raze to fail. | |
224 sql::Connection other_db; | |
225 ASSERT_TRUE(other_db.Open(db_path())); | |
226 ASSERT_TRUE(other_db.BeginTransaction()); | |
227 const char* kInsertSql = "INSERT INTO foo VALUES (1, 'data')"; | |
228 ASSERT_TRUE(other_db.Execute(kInsertSql)); | |
229 | |
230 ASSERT_FALSE(db().Raze()); | |
231 | |
232 // Works after COMMIT. | |
233 ASSERT_TRUE(other_db.CommitTransaction()); | |
234 ASSERT_TRUE(db().Raze()); | |
235 | |
236 // Re-create the database. | |
237 ASSERT_TRUE(db().Execute(kCreateSql)); | |
238 ASSERT_TRUE(db().Execute(kInsertSql)); | |
239 | |
240 // An unfinished read transaction in the other connection also | |
241 // blocks raze. | |
242 const char *kQuery = "SELECT COUNT(*) FROM foo"; | |
243 sql::Statement s(other_db.GetUniqueStatement(kQuery)); | |
244 ASSERT_TRUE(s.Step()); | |
245 ASSERT_FALSE(db().Raze()); | |
246 | |
247 // Complete the statement unlocks the database. | |
248 ASSERT_FALSE(s.Step()); | |
249 ASSERT_TRUE(db().Raze()); | |
250 } | |
251 | |
252 // TODO(shess): Spin up a background thread to hold other_db, to more | |
253 // closely match real life. That would also allow testing | |
254 // RazeWithTimeout(). | |
OLD | NEW |