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