[Author: zork]
[google-gears.git] / gears / base / common / sqlite_wrapper_test.cc
blob0fd8d24211db99229e1968744d0bc178978a8341
1 // Copyright 2007, Google Inc.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are met:
5 //
6 // 1. Redistributions of source code must retain the above copyright notice,
7 // this list of conditions and the following disclaimer.
8 // 2. Redistributions in binary form must reproduce the above copyright notice,
9 // this list of conditions and the following disclaimer in the documentation
10 // and/or other materials provided with the distribution.
11 // 3. Neither the name of Google Inc. nor the names of its contributors may be
12 // used to endorse or promote products derived from this software without
13 // specific prior written permission.
15 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18 // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 #ifdef DEBUG
27 #include "gears/base/common/sqlite_wrapper.h"
28 #include "gears/base/common/sqlite_wrapper_test.h"
29 #include "gears/base/common/stopwatch.h"
30 #include "gears/base/common/string_utils.h"
32 static bool TestSQLDatabaseTransactions();
33 static bool TestSQLTransaction();
34 static bool CreateTable(SQLDatabase &db);
35 static bool InsertRow(SQLDatabase &db);
37 // Not static because this function is declared as a friend of SQLDatabase
38 bool TestSQLConcurrency();
41 //------------------------------------------------------------------------------
42 // TestSqliteUtilsAll
43 //------------------------------------------------------------------------------
44 bool TestSqliteUtilsAll() {
45 bool ok = true;
46 ok &= TestSQLDatabaseTransactions();
47 ok &= TestSQLTransaction();
48 ok &= TestSQLConcurrency();
49 return ok;
53 //------------------------------------------------------------------------------
54 // TestSQLDatabaseTransactions
55 //------------------------------------------------------------------------------
56 static bool TestSQLDatabaseTransactions() {
57 #undef TEST_ASSERT
58 #define TEST_ASSERT(b) \
59 { \
60 if (!(b)) { \
61 LOG(("TestSQLDatabaseTransactions - failed (%d)\n", __LINE__)); \
62 return false; \
63 } \
66 // Put something into the DB using a nested transaction
68 SQLDatabase db1;
69 TEST_ASSERT(db1.Open(STRING16(L"SqliteUtils_test.db")));
71 TEST_ASSERT(SQLITE_OK == db1.Execute("DROP TABLE IF EXISTS test"));
73 const char *kTransactionLabel = "TestSQLDatabaseTransactions";
75 TEST_ASSERT(db1.BeginTransaction(kTransactionLabel));
76 TEST_ASSERT(SQLITE_OK == db1.Execute("CREATE TABLE test (val TEXT)"));
78 TEST_ASSERT(db1.BeginTransaction(kTransactionLabel));
79 TEST_ASSERT(SQLITE_OK == db1.Execute("INSERT INTO test VALUES ('foo')"));
81 TEST_ASSERT(db1.CommitTransaction(kTransactionLabel));
82 TEST_ASSERT(db1.CommitTransaction(kTransactionLabel));
85 // Now check that it is there
87 SQLDatabase db2;
88 TEST_ASSERT(db2.Open(STRING16(L"SqliteUtils_test.db")));
90 SQLStatement stmt;
91 TEST_ASSERT(SQLITE_OK ==
92 stmt.prepare16(&db2, STRING16(L"SELECT 1 FROM test WHERE val='foo'")));
93 TEST_ASSERT(SQLITE_ROW == stmt.step());
94 TEST_ASSERT(1 == stmt.column_int(0));
97 LOG(("TestSQLDatabaseTransactions - passed\n"));
98 return true;
102 //------------------------------------------------------------------------------
103 // TestSQLTransaction
104 //------------------------------------------------------------------------------
105 static bool TestSQLTransaction() {
106 #undef TEST_ASSERT
107 #define TEST_ASSERT(b) \
109 if (!(b)) { \
110 LOG(("TestSQLTransaction - failed (%d)\n", __LINE__)); \
111 return false; \
115 // Put something into the DB using a nested transaction
117 SQLDatabase db1;
118 TEST_ASSERT(db1.Open(STRING16(L"SqliteUtils_test.db")));
120 TEST_ASSERT(SQLITE_OK == db1.Execute("DROP TABLE test"));
122 TEST_ASSERT(CreateTable(db1));
125 // Now verify that the table is not there
127 SQLDatabase db2;
128 TEST_ASSERT(db2.Open(STRING16(L"SqliteUtils_test.db")));
130 SQLStatement stmt;
131 TEST_ASSERT(SQLITE_OK ==
132 stmt.prepare16(&db2,
133 STRING16(L"SELECT 1 FROM sqlite_master WHERE tbl_name='test'")));
134 TEST_ASSERT(SQLITE_DONE == stmt.step());
137 LOG(("TestSQLTransaction - passed\n"));
138 return true;
142 //------------------------------------------------------------------------------
143 // CreateTable helper used by TestSQLTransaction
144 //------------------------------------------------------------------------------
145 static bool CreateTable(SQLDatabase &db) {
146 #undef TEST_ASSERT
147 #define TEST_ASSERT(b) \
149 if (!(b)) { \
150 LOG(("CreateTable - failed (%d)\n", __LINE__)); \
151 return false; \
155 SQLTransaction tx(&db, "TestSQLTransaction::CreateTable");
156 TEST_ASSERT(tx.Begin());
158 TEST_ASSERT(SQLITE_OK == db.Execute("CREATE TABLE test (val TEXT)"));
160 TEST_ASSERT(InsertRow(db));
161 return true;
165 //------------------------------------------------------------------------------
166 // InsertRow helper used by TestSQLTransaction
167 //------------------------------------------------------------------------------
168 static bool InsertRow(SQLDatabase &db) {
169 #undef TEST_ASSERT
170 #define TEST_ASSERT(b) \
172 if (!(b)) { \
173 LOG(("InsertRow - failed (%d)\n", __LINE__)); \
174 return false; \
178 SQLTransaction tx(&db, "TestSQLTransaction::InsertRow");
180 TEST_ASSERT(tx.Begin());
182 // There should be an error because test doesn't exist
183 TEST_ASSERT(SQLITE_OK == db.Execute("INSERT INTO test VALUES ('foo')"));
185 // Now roll it back
186 tx.Rollback();
188 return true;
192 bool TestSQLConcurrency() {
193 #undef TEST_ASSERT
194 #define TEST_ASSERT(b) \
196 if (!(b)) { \
197 LOG(("TestSQLConcurrency - failed (%d)\n", __LINE__)); \
198 return false; \
202 // db1, open and configure our connection with pragmas as desired
203 SQLDatabase db1;
204 TEST_ASSERT(db1.Open(STRING16(L"SqliteUtils_test.db")));
206 // db2, open a connection but don't configure yet
207 SQLDatabase db2;
208 TEST_ASSERT(db2.OpenConnection(STRING16(L"SqliteUtils_test.db")));
210 // db1, get an exclusive lock
211 TEST_ASSERT(SQLITE_OK == db1.Execute("BEGIN EXCLUSIVE"));
213 // db2, now try to configure our pragmas.
214 // This should fail with a busy error after a timeout
215 int64 start_msec = GetCurrentTimeMillis();
216 TEST_ASSERT(!db2.ConfigureConnection());
217 TEST_ASSERT(db2.GetErrorCode() == SQLITE_BUSY);
218 int kSlopMillis = 500;
219 TEST_ASSERT(GetCurrentTimeMillis() - start_msec >
220 SQLDatabase::kBusyTimeout - kSlopMillis);
221 db2.Close(); // cleanup
223 // After releasing the exclusive lock, we should be able to
224 // open and configure a second connection
225 TEST_ASSERT(SQLITE_OK == db1.Execute("ROLLBACK"));
226 TEST_ASSERT(db2.Open(STRING16(L"SqliteUtils_test.db")));
228 return true;
232 #endif // DEBUG