1 // Copyright 2011 The Kyua Authors. 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/optional.ipp" 36 #include "utils/sqlite/statement.ipp" 37 #include "utils/sqlite/test_utils.hpp" 38 #include "utils/sqlite/transaction.hpp" 39 40 namespace fs = utils::fs; 41 namespace sqlite = utils::sqlite; 42 43 using utils::optional; 44 45 46 ATF_TEST_CASE_WITHOUT_HEAD(in_memory); 47 ATF_TEST_CASE_BODY(in_memory) 48 { 49 sqlite::database db = sqlite::database::in_memory(); 50 create_test_table(raw(db)); 51 verify_test_table(raw(db)); 52 53 ATF_REQUIRE(!fs::exists(fs::path(":memory:"))); 54 } 55 56 57 ATF_TEST_CASE_WITHOUT_HEAD(open__readonly__ok); 58 ATF_TEST_CASE_BODY(open__readonly__ok) 59 { 60 { 61 ::sqlite3* db; 62 ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2("test.db", &db, 63 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)); 64 create_test_table(db); 65 ::sqlite3_close(db); 66 } 67 { 68 sqlite::database db = sqlite::database::open(fs::path("test.db"), 69 sqlite::open_readonly); 70 verify_test_table(raw(db)); 71 } 72 } 73 74 75 ATF_TEST_CASE_WITHOUT_HEAD(open__readonly__fail); 76 ATF_TEST_CASE_BODY(open__readonly__fail) 77 { 78 REQUIRE_API_ERROR("sqlite3_open_v2", 79 sqlite::database::open(fs::path("missing.db"), sqlite::open_readonly)); 80 ATF_REQUIRE(!fs::exists(fs::path("missing.db"))); 81 } 82 83 84 ATF_TEST_CASE_WITHOUT_HEAD(open__create__ok); 85 ATF_TEST_CASE_BODY(open__create__ok) 86 { 87 { 88 sqlite::database db = sqlite::database::open(fs::path("test.db"), 89 sqlite::open_readwrite | sqlite::open_create); 90 ATF_REQUIRE(fs::exists(fs::path("test.db"))); 91 create_test_table(raw(db)); 92 } 93 { 94 ::sqlite3* db; 95 ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2("test.db", &db, 96 SQLITE_OPEN_READONLY, NULL)); 97 verify_test_table(db); 98 ::sqlite3_close(db); 99 } 100 } 101 102 103 ATF_TEST_CASE(open__create__fail); 104 ATF_TEST_CASE_HEAD(open__create__fail) 105 { 106 set_md_var("require.user", "unprivileged"); 107 } 108 ATF_TEST_CASE_BODY(open__create__fail) 109 { 110 fs::mkdir(fs::path("protected"), 0555); 111 REQUIRE_API_ERROR("sqlite3_open_v2", 112 sqlite::database::open(fs::path("protected/test.db"), 113 sqlite::open_readwrite | sqlite::open_create)); 114 } 115 116 117 ATF_TEST_CASE_WITHOUT_HEAD(temporary); 118 ATF_TEST_CASE_BODY(temporary) 119 { 120 // We could validate if files go to disk by setting the temp_store_directory 121 // PRAGMA to a subdirectory of pwd, and then ensuring the subdirectory is 122 // not empty. However, there does not seem to be a way to force SQLite to 123 // unconditionally write the temporary database to disk (even with 124 // temp_store = FILE), so this scenary is hard to reproduce. 125 sqlite::database db = sqlite::database::temporary(); 126 create_test_table(raw(db)); 127 verify_test_table(raw(db)); 128 } 129 130 131 ATF_TEST_CASE_WITHOUT_HEAD(close); 132 ATF_TEST_CASE_BODY(close) 133 { 134 sqlite::database db = sqlite::database::in_memory(); 135 db.close(); 136 // The destructor for the database will run now. If it does a second close, 137 // we may crash, so let's see if we don't. 138 } 139 140 141 ATF_TEST_CASE_WITHOUT_HEAD(copy); 142 ATF_TEST_CASE_BODY(copy) 143 { 144 sqlite::database db1 = sqlite::database::in_memory(); 145 { 146 sqlite::database db2 = sqlite::database::in_memory(); 147 create_test_table(raw(db2)); 148 db1 = db2; 149 verify_test_table(raw(db1)); 150 } 151 // db2 went out of scope. If the destruction is not properly managed, the 152 // memory of db1 may have been invalidated and this would not work. 153 verify_test_table(raw(db1)); 154 } 155 156 157 ATF_TEST_CASE_WITHOUT_HEAD(db_filename__in_memory); 158 ATF_TEST_CASE_BODY(db_filename__in_memory) 159 { 160 const sqlite::database db = sqlite::database::in_memory(); 161 ATF_REQUIRE(!db.db_filename()); 162 } 163 164 165 ATF_TEST_CASE_WITHOUT_HEAD(db_filename__file); 166 ATF_TEST_CASE_BODY(db_filename__file) 167 { 168 const sqlite::database db = sqlite::database::open(fs::path("test.db"), 169 sqlite::open_readwrite | sqlite::open_create); 170 ATF_REQUIRE(db.db_filename()); 171 ATF_REQUIRE_EQ(fs::path("test.db"), db.db_filename().get()); 172 } 173 174 175 ATF_TEST_CASE_WITHOUT_HEAD(db_filename__temporary); 176 ATF_TEST_CASE_BODY(db_filename__temporary) 177 { 178 const sqlite::database db = sqlite::database::temporary(); 179 ATF_REQUIRE(!db.db_filename()); 180 } 181 182 183 ATF_TEST_CASE_WITHOUT_HEAD(db_filename__ok_after_close); 184 ATF_TEST_CASE_BODY(db_filename__ok_after_close) 185 { 186 sqlite::database db = sqlite::database::open(fs::path("test.db"), 187 sqlite::open_readwrite | sqlite::open_create); 188 const optional< fs::path > db_filename = db.db_filename(); 189 ATF_REQUIRE(db_filename); 190 db.close(); 191 ATF_REQUIRE_EQ(db_filename, db.db_filename()); 192 } 193 194 195 ATF_TEST_CASE_WITHOUT_HEAD(exec__ok); 196 ATF_TEST_CASE_BODY(exec__ok) 197 { 198 sqlite::database db = sqlite::database::in_memory(); 199 db.exec(create_test_table_sql); 200 verify_test_table(raw(db)); 201 } 202 203 204 ATF_TEST_CASE_WITHOUT_HEAD(exec__fail); 205 ATF_TEST_CASE_BODY(exec__fail) 206 { 207 sqlite::database db = sqlite::database::in_memory(); 208 REQUIRE_API_ERROR("sqlite3_exec", 209 db.exec("SELECT * FROM test")); 210 REQUIRE_API_ERROR("sqlite3_exec", 211 db.exec("CREATE TABLE test (col INTEGER PRIMARY KEY);" 212 "FOO BAR")); 213 db.exec("SELECT * FROM test"); 214 } 215 216 217 ATF_TEST_CASE_WITHOUT_HEAD(create_statement__ok); 218 ATF_TEST_CASE_BODY(create_statement__ok) 219 { 220 sqlite::database db = sqlite::database::in_memory(); 221 sqlite::statement stmt = db.create_statement("SELECT 3"); 222 // Statement testing happens in statement_test. We are only interested here 223 // in ensuring that the API call exists and runs. 224 } 225 226 227 ATF_TEST_CASE_WITHOUT_HEAD(begin_transaction); 228 ATF_TEST_CASE_BODY(begin_transaction) 229 { 230 sqlite::database db = sqlite::database::in_memory(); 231 sqlite::transaction stmt = db.begin_transaction(); 232 // Transaction testing happens in transaction_test. We are only interested 233 // here in ensuring that the API call exists and runs. 234 } 235 236 237 ATF_TEST_CASE_WITHOUT_HEAD(create_statement__fail); 238 ATF_TEST_CASE_BODY(create_statement__fail) 239 { 240 sqlite::database db = sqlite::database::in_memory(); 241 REQUIRE_API_ERROR("sqlite3_prepare_v2", 242 db.create_statement("SELECT * FROM missing")); 243 } 244 245 246 ATF_TEST_CASE_WITHOUT_HEAD(last_insert_rowid); 247 ATF_TEST_CASE_BODY(last_insert_rowid) 248 { 249 sqlite::database db = sqlite::database::in_memory(); 250 db.exec("CREATE TABLE test (a INTEGER PRIMARY KEY, b INTEGER)"); 251 db.exec("INSERT INTO test VALUES (723, 5)"); 252 ATF_REQUIRE_EQ(723, db.last_insert_rowid()); 253 db.exec("INSERT INTO test VALUES (145, 20)"); 254 ATF_REQUIRE_EQ(145, db.last_insert_rowid()); 255 } 256 257 258 ATF_INIT_TEST_CASES(tcs) 259 { 260 ATF_ADD_TEST_CASE(tcs, in_memory); 261 262 ATF_ADD_TEST_CASE(tcs, open__readonly__ok); 263 ATF_ADD_TEST_CASE(tcs, open__readonly__fail); 264 ATF_ADD_TEST_CASE(tcs, open__create__ok); 265 ATF_ADD_TEST_CASE(tcs, open__create__fail); 266 267 ATF_ADD_TEST_CASE(tcs, temporary); 268 269 ATF_ADD_TEST_CASE(tcs, close); 270 271 ATF_ADD_TEST_CASE(tcs, copy); 272 273 ATF_ADD_TEST_CASE(tcs, db_filename__in_memory); 274 ATF_ADD_TEST_CASE(tcs, db_filename__file); 275 ATF_ADD_TEST_CASE(tcs, db_filename__temporary); 276 ATF_ADD_TEST_CASE(tcs, db_filename__ok_after_close); 277 278 ATF_ADD_TEST_CASE(tcs, exec__ok); 279 ATF_ADD_TEST_CASE(tcs, exec__fail); 280 281 ATF_ADD_TEST_CASE(tcs, begin_transaction); 282 283 ATF_ADD_TEST_CASE(tcs, create_statement__ok); 284 ATF_ADD_TEST_CASE(tcs, create_statement__fail); 285 286 ATF_ADD_TEST_CASE(tcs, last_insert_rowid); 287 } 288