1*b0d29bc4SBrooks Davis // Copyright 2011 The Kyua Authors.
2*b0d29bc4SBrooks Davis // All rights reserved.
3*b0d29bc4SBrooks Davis //
4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without
5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are
6*b0d29bc4SBrooks Davis // met:
7*b0d29bc4SBrooks Davis //
8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright
9*b0d29bc4SBrooks Davis //   notice, this list of conditions and the following disclaimer.
10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
11*b0d29bc4SBrooks Davis //   notice, this list of conditions and the following disclaimer in the
12*b0d29bc4SBrooks Davis //   documentation and/or other materials provided with the distribution.
13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
14*b0d29bc4SBrooks Davis //   may be used to endorse or promote products derived from this software
15*b0d29bc4SBrooks Davis //   without specific prior written permission.
16*b0d29bc4SBrooks Davis //
17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*b0d29bc4SBrooks Davis 
29*b0d29bc4SBrooks Davis #include "utils/sqlite/database.hpp"
30*b0d29bc4SBrooks Davis 
31*b0d29bc4SBrooks Davis #include <atf-c++.hpp>
32*b0d29bc4SBrooks Davis 
33*b0d29bc4SBrooks Davis #include "utils/fs/operations.hpp"
34*b0d29bc4SBrooks Davis #include "utils/fs/path.hpp"
35*b0d29bc4SBrooks Davis #include "utils/optional.ipp"
36*b0d29bc4SBrooks Davis #include "utils/sqlite/statement.ipp"
37*b0d29bc4SBrooks Davis #include "utils/sqlite/test_utils.hpp"
38*b0d29bc4SBrooks Davis #include "utils/sqlite/transaction.hpp"
39*b0d29bc4SBrooks Davis 
40*b0d29bc4SBrooks Davis namespace fs = utils::fs;
41*b0d29bc4SBrooks Davis namespace sqlite = utils::sqlite;
42*b0d29bc4SBrooks Davis 
43*b0d29bc4SBrooks Davis using utils::optional;
44*b0d29bc4SBrooks Davis 
45*b0d29bc4SBrooks Davis 
46*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(in_memory);
ATF_TEST_CASE_BODY(in_memory)47*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(in_memory)
48*b0d29bc4SBrooks Davis {
49*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::in_memory();
50*b0d29bc4SBrooks Davis     create_test_table(raw(db));
51*b0d29bc4SBrooks Davis     verify_test_table(raw(db));
52*b0d29bc4SBrooks Davis 
53*b0d29bc4SBrooks Davis     ATF_REQUIRE(!fs::exists(fs::path(":memory:")));
54*b0d29bc4SBrooks Davis }
55*b0d29bc4SBrooks Davis 
56*b0d29bc4SBrooks Davis 
57*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(open__readonly__ok);
ATF_TEST_CASE_BODY(open__readonly__ok)58*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(open__readonly__ok)
59*b0d29bc4SBrooks Davis {
60*b0d29bc4SBrooks Davis     {
61*b0d29bc4SBrooks Davis         ::sqlite3* db;
62*b0d29bc4SBrooks Davis         ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2("test.db", &db,
63*b0d29bc4SBrooks Davis             SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL));
64*b0d29bc4SBrooks Davis         create_test_table(db);
65*b0d29bc4SBrooks Davis         ::sqlite3_close(db);
66*b0d29bc4SBrooks Davis     }
67*b0d29bc4SBrooks Davis     {
68*b0d29bc4SBrooks Davis         sqlite::database db = sqlite::database::open(fs::path("test.db"),
69*b0d29bc4SBrooks Davis             sqlite::open_readonly);
70*b0d29bc4SBrooks Davis         verify_test_table(raw(db));
71*b0d29bc4SBrooks Davis     }
72*b0d29bc4SBrooks Davis }
73*b0d29bc4SBrooks Davis 
74*b0d29bc4SBrooks Davis 
75*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(open__readonly__fail);
ATF_TEST_CASE_BODY(open__readonly__fail)76*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(open__readonly__fail)
77*b0d29bc4SBrooks Davis {
78*b0d29bc4SBrooks Davis     REQUIRE_API_ERROR("sqlite3_open_v2",
79*b0d29bc4SBrooks Davis         sqlite::database::open(fs::path("missing.db"), sqlite::open_readonly));
80*b0d29bc4SBrooks Davis     ATF_REQUIRE(!fs::exists(fs::path("missing.db")));
81*b0d29bc4SBrooks Davis }
82*b0d29bc4SBrooks Davis 
83*b0d29bc4SBrooks Davis 
84*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(open__create__ok);
ATF_TEST_CASE_BODY(open__create__ok)85*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(open__create__ok)
86*b0d29bc4SBrooks Davis {
87*b0d29bc4SBrooks Davis     {
88*b0d29bc4SBrooks Davis         sqlite::database db = sqlite::database::open(fs::path("test.db"),
89*b0d29bc4SBrooks Davis             sqlite::open_readwrite | sqlite::open_create);
90*b0d29bc4SBrooks Davis         ATF_REQUIRE(fs::exists(fs::path("test.db")));
91*b0d29bc4SBrooks Davis         create_test_table(raw(db));
92*b0d29bc4SBrooks Davis     }
93*b0d29bc4SBrooks Davis     {
94*b0d29bc4SBrooks Davis         ::sqlite3* db;
95*b0d29bc4SBrooks Davis         ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2("test.db", &db,
96*b0d29bc4SBrooks Davis             SQLITE_OPEN_READONLY, NULL));
97*b0d29bc4SBrooks Davis         verify_test_table(db);
98*b0d29bc4SBrooks Davis         ::sqlite3_close(db);
99*b0d29bc4SBrooks Davis     }
100*b0d29bc4SBrooks Davis }
101*b0d29bc4SBrooks Davis 
102*b0d29bc4SBrooks Davis 
103*b0d29bc4SBrooks Davis ATF_TEST_CASE(open__create__fail);
ATF_TEST_CASE_HEAD(open__create__fail)104*b0d29bc4SBrooks Davis ATF_TEST_CASE_HEAD(open__create__fail)
105*b0d29bc4SBrooks Davis {
106*b0d29bc4SBrooks Davis     set_md_var("require.user", "unprivileged");
107*b0d29bc4SBrooks Davis }
ATF_TEST_CASE_BODY(open__create__fail)108*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(open__create__fail)
109*b0d29bc4SBrooks Davis {
110*b0d29bc4SBrooks Davis     fs::mkdir(fs::path("protected"), 0555);
111*b0d29bc4SBrooks Davis     REQUIRE_API_ERROR("sqlite3_open_v2",
112*b0d29bc4SBrooks Davis         sqlite::database::open(fs::path("protected/test.db"),
113*b0d29bc4SBrooks Davis                                sqlite::open_readwrite | sqlite::open_create));
114*b0d29bc4SBrooks Davis }
115*b0d29bc4SBrooks Davis 
116*b0d29bc4SBrooks Davis 
117*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(temporary);
ATF_TEST_CASE_BODY(temporary)118*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(temporary)
119*b0d29bc4SBrooks Davis {
120*b0d29bc4SBrooks Davis     // We could validate if files go to disk by setting the temp_store_directory
121*b0d29bc4SBrooks Davis     // PRAGMA to a subdirectory of pwd, and then ensuring the subdirectory is
122*b0d29bc4SBrooks Davis     // not empty.  However, there does not seem to be a way to force SQLite to
123*b0d29bc4SBrooks Davis     // unconditionally write the temporary database to disk (even with
124*b0d29bc4SBrooks Davis     // temp_store = FILE), so this scenary is hard to reproduce.
125*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::temporary();
126*b0d29bc4SBrooks Davis     create_test_table(raw(db));
127*b0d29bc4SBrooks Davis     verify_test_table(raw(db));
128*b0d29bc4SBrooks Davis }
129*b0d29bc4SBrooks Davis 
130*b0d29bc4SBrooks Davis 
131*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(close);
ATF_TEST_CASE_BODY(close)132*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(close)
133*b0d29bc4SBrooks Davis {
134*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::in_memory();
135*b0d29bc4SBrooks Davis     db.close();
136*b0d29bc4SBrooks Davis     // The destructor for the database will run now.  If it does a second close,
137*b0d29bc4SBrooks Davis     // we may crash, so let's see if we don't.
138*b0d29bc4SBrooks Davis }
139*b0d29bc4SBrooks Davis 
140*b0d29bc4SBrooks Davis 
141*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(copy);
ATF_TEST_CASE_BODY(copy)142*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(copy)
143*b0d29bc4SBrooks Davis {
144*b0d29bc4SBrooks Davis     sqlite::database db1 = sqlite::database::in_memory();
145*b0d29bc4SBrooks Davis     {
146*b0d29bc4SBrooks Davis         sqlite::database db2 = sqlite::database::in_memory();
147*b0d29bc4SBrooks Davis         create_test_table(raw(db2));
148*b0d29bc4SBrooks Davis         db1 = db2;
149*b0d29bc4SBrooks Davis         verify_test_table(raw(db1));
150*b0d29bc4SBrooks Davis     }
151*b0d29bc4SBrooks Davis     // db2 went out of scope.  If the destruction is not properly managed, the
152*b0d29bc4SBrooks Davis     // memory of db1 may have been invalidated and this would not work.
153*b0d29bc4SBrooks Davis     verify_test_table(raw(db1));
154*b0d29bc4SBrooks Davis }
155*b0d29bc4SBrooks Davis 
156*b0d29bc4SBrooks Davis 
157*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(db_filename__in_memory);
ATF_TEST_CASE_BODY(db_filename__in_memory)158*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(db_filename__in_memory)
159*b0d29bc4SBrooks Davis {
160*b0d29bc4SBrooks Davis     const sqlite::database db = sqlite::database::in_memory();
161*b0d29bc4SBrooks Davis     ATF_REQUIRE(!db.db_filename());
162*b0d29bc4SBrooks Davis }
163*b0d29bc4SBrooks Davis 
164*b0d29bc4SBrooks Davis 
165*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(db_filename__file);
ATF_TEST_CASE_BODY(db_filename__file)166*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(db_filename__file)
167*b0d29bc4SBrooks Davis {
168*b0d29bc4SBrooks Davis     const sqlite::database db = sqlite::database::open(fs::path("test.db"),
169*b0d29bc4SBrooks Davis         sqlite::open_readwrite | sqlite::open_create);
170*b0d29bc4SBrooks Davis     ATF_REQUIRE(db.db_filename());
171*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(fs::path("test.db"), db.db_filename().get());
172*b0d29bc4SBrooks Davis }
173*b0d29bc4SBrooks Davis 
174*b0d29bc4SBrooks Davis 
175*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(db_filename__temporary);
ATF_TEST_CASE_BODY(db_filename__temporary)176*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(db_filename__temporary)
177*b0d29bc4SBrooks Davis {
178*b0d29bc4SBrooks Davis     const sqlite::database db = sqlite::database::temporary();
179*b0d29bc4SBrooks Davis     ATF_REQUIRE(!db.db_filename());
180*b0d29bc4SBrooks Davis }
181*b0d29bc4SBrooks Davis 
182*b0d29bc4SBrooks Davis 
183*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(db_filename__ok_after_close);
ATF_TEST_CASE_BODY(db_filename__ok_after_close)184*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(db_filename__ok_after_close)
185*b0d29bc4SBrooks Davis {
186*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::open(fs::path("test.db"),
187*b0d29bc4SBrooks Davis         sqlite::open_readwrite | sqlite::open_create);
188*b0d29bc4SBrooks Davis     const optional< fs::path > db_filename = db.db_filename();
189*b0d29bc4SBrooks Davis     ATF_REQUIRE(db_filename);
190*b0d29bc4SBrooks Davis     db.close();
191*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(db_filename, db.db_filename());
192*b0d29bc4SBrooks Davis }
193*b0d29bc4SBrooks Davis 
194*b0d29bc4SBrooks Davis 
195*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exec__ok);
ATF_TEST_CASE_BODY(exec__ok)196*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exec__ok)
197*b0d29bc4SBrooks Davis {
198*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::in_memory();
199*b0d29bc4SBrooks Davis     db.exec(create_test_table_sql);
200*b0d29bc4SBrooks Davis     verify_test_table(raw(db));
201*b0d29bc4SBrooks Davis }
202*b0d29bc4SBrooks Davis 
203*b0d29bc4SBrooks Davis 
204*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exec__fail);
ATF_TEST_CASE_BODY(exec__fail)205*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exec__fail)
206*b0d29bc4SBrooks Davis {
207*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::in_memory();
208*b0d29bc4SBrooks Davis     REQUIRE_API_ERROR("sqlite3_exec",
209*b0d29bc4SBrooks Davis                       db.exec("SELECT * FROM test"));
210*b0d29bc4SBrooks Davis     REQUIRE_API_ERROR("sqlite3_exec",
211*b0d29bc4SBrooks Davis                       db.exec("CREATE TABLE test (col INTEGER PRIMARY KEY);"
212*b0d29bc4SBrooks Davis                               "FOO BAR"));
213*b0d29bc4SBrooks Davis     db.exec("SELECT * FROM test");
214*b0d29bc4SBrooks Davis }
215*b0d29bc4SBrooks Davis 
216*b0d29bc4SBrooks Davis 
217*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(create_statement__ok);
ATF_TEST_CASE_BODY(create_statement__ok)218*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(create_statement__ok)
219*b0d29bc4SBrooks Davis {
220*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::in_memory();
221*b0d29bc4SBrooks Davis     sqlite::statement stmt = db.create_statement("SELECT 3");
222*b0d29bc4SBrooks Davis     // Statement testing happens in statement_test.  We are only interested here
223*b0d29bc4SBrooks Davis     // in ensuring that the API call exists and runs.
224*b0d29bc4SBrooks Davis }
225*b0d29bc4SBrooks Davis 
226*b0d29bc4SBrooks Davis 
227*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(begin_transaction);
ATF_TEST_CASE_BODY(begin_transaction)228*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(begin_transaction)
229*b0d29bc4SBrooks Davis {
230*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::in_memory();
231*b0d29bc4SBrooks Davis     sqlite::transaction stmt = db.begin_transaction();
232*b0d29bc4SBrooks Davis     // Transaction testing happens in transaction_test.  We are only interested
233*b0d29bc4SBrooks Davis     // here in ensuring that the API call exists and runs.
234*b0d29bc4SBrooks Davis }
235*b0d29bc4SBrooks Davis 
236*b0d29bc4SBrooks Davis 
237*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(create_statement__fail);
ATF_TEST_CASE_BODY(create_statement__fail)238*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(create_statement__fail)
239*b0d29bc4SBrooks Davis {
240*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::in_memory();
241*b0d29bc4SBrooks Davis     REQUIRE_API_ERROR("sqlite3_prepare_v2",
242*b0d29bc4SBrooks Davis                       db.create_statement("SELECT * FROM missing"));
243*b0d29bc4SBrooks Davis }
244*b0d29bc4SBrooks Davis 
245*b0d29bc4SBrooks Davis 
246*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(last_insert_rowid);
ATF_TEST_CASE_BODY(last_insert_rowid)247*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(last_insert_rowid)
248*b0d29bc4SBrooks Davis {
249*b0d29bc4SBrooks Davis     sqlite::database db = sqlite::database::in_memory();
250*b0d29bc4SBrooks Davis     db.exec("CREATE TABLE test (a INTEGER PRIMARY KEY, b INTEGER)");
251*b0d29bc4SBrooks Davis     db.exec("INSERT INTO test VALUES (723, 5)");
252*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(723, db.last_insert_rowid());
253*b0d29bc4SBrooks Davis     db.exec("INSERT INTO test VALUES (145, 20)");
254*b0d29bc4SBrooks Davis     ATF_REQUIRE_EQ(145, db.last_insert_rowid());
255*b0d29bc4SBrooks Davis }
256*b0d29bc4SBrooks Davis 
257*b0d29bc4SBrooks Davis 
ATF_INIT_TEST_CASES(tcs)258*b0d29bc4SBrooks Davis ATF_INIT_TEST_CASES(tcs)
259*b0d29bc4SBrooks Davis {
260*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, in_memory);
261*b0d29bc4SBrooks Davis 
262*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, open__readonly__ok);
263*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, open__readonly__fail);
264*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, open__create__ok);
265*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, open__create__fail);
266*b0d29bc4SBrooks Davis 
267*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, temporary);
268*b0d29bc4SBrooks Davis 
269*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, close);
270*b0d29bc4SBrooks Davis 
271*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, copy);
272*b0d29bc4SBrooks Davis 
273*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, db_filename__in_memory);
274*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, db_filename__file);
275*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, db_filename__temporary);
276*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, db_filename__ok_after_close);
277*b0d29bc4SBrooks Davis 
278*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, exec__ok);
279*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, exec__fail);
280*b0d29bc4SBrooks Davis 
281*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, begin_transaction);
282*b0d29bc4SBrooks Davis 
283*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, create_statement__ok);
284*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, create_statement__fail);
285*b0d29bc4SBrooks Davis 
286*b0d29bc4SBrooks Davis     ATF_ADD_TEST_CASE(tcs, last_insert_rowid);
287*b0d29bc4SBrooks Davis }
288