Path: blob/main/contrib/kyua/utils/sqlite/database_test.cpp
48196 views
// Copyright 2011 The Kyua Authors.1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are5// met:6//7// * Redistributions of source code must retain the above copyright8// notice, this list of conditions and the following disclaimer.9// * Redistributions in binary form must reproduce the above copyright10// notice, this list of conditions and the following disclaimer in the11// documentation and/or other materials provided with the distribution.12// * Neither the name of Google Inc. nor the names of its contributors13// may be used to endorse or promote products derived from this software14// without specific prior written permission.15//16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2728#include "utils/sqlite/database.hpp"2930#include <atf-c++.hpp>3132#include "utils/fs/operations.hpp"33#include "utils/fs/path.hpp"34#include "utils/optional.ipp"35#include "utils/sqlite/statement.ipp"36#include "utils/sqlite/test_utils.hpp"37#include "utils/sqlite/transaction.hpp"3839namespace fs = utils::fs;40namespace sqlite = utils::sqlite;4142using utils::optional;434445ATF_TEST_CASE_WITHOUT_HEAD(in_memory);46ATF_TEST_CASE_BODY(in_memory)47{48sqlite::database db = sqlite::database::in_memory();49create_test_table(raw(db));50verify_test_table(raw(db));5152ATF_REQUIRE(!fs::exists(fs::path(":memory:")));53}545556ATF_TEST_CASE_WITHOUT_HEAD(open__readonly__ok);57ATF_TEST_CASE_BODY(open__readonly__ok)58{59{60::sqlite3* db;61ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2("test.db", &db,62SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL));63create_test_table(db);64::sqlite3_close(db);65}66{67sqlite::database db = sqlite::database::open(fs::path("test.db"),68sqlite::open_readonly);69verify_test_table(raw(db));70}71}727374ATF_TEST_CASE_WITHOUT_HEAD(open__readonly__fail);75ATF_TEST_CASE_BODY(open__readonly__fail)76{77REQUIRE_API_ERROR("sqlite3_open_v2",78sqlite::database::open(fs::path("missing.db"), sqlite::open_readonly));79ATF_REQUIRE(!fs::exists(fs::path("missing.db")));80}818283ATF_TEST_CASE_WITHOUT_HEAD(open__create__ok);84ATF_TEST_CASE_BODY(open__create__ok)85{86{87sqlite::database db = sqlite::database::open(fs::path("test.db"),88sqlite::open_readwrite | sqlite::open_create);89ATF_REQUIRE(fs::exists(fs::path("test.db")));90create_test_table(raw(db));91}92{93::sqlite3* db;94ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2("test.db", &db,95SQLITE_OPEN_READONLY, NULL));96verify_test_table(db);97::sqlite3_close(db);98}99}100101102ATF_TEST_CASE(open__create__fail);103ATF_TEST_CASE_HEAD(open__create__fail)104{105set_md_var("require.user", "unprivileged");106}107ATF_TEST_CASE_BODY(open__create__fail)108{109fs::mkdir(fs::path("protected"), 0555);110REQUIRE_API_ERROR("sqlite3_open_v2",111sqlite::database::open(fs::path("protected/test.db"),112sqlite::open_readwrite | sqlite::open_create));113}114115116ATF_TEST_CASE_WITHOUT_HEAD(temporary);117ATF_TEST_CASE_BODY(temporary)118{119// We could validate if files go to disk by setting the temp_store_directory120// PRAGMA to a subdirectory of pwd, and then ensuring the subdirectory is121// not empty. However, there does not seem to be a way to force SQLite to122// unconditionally write the temporary database to disk (even with123// temp_store = FILE), so this scenary is hard to reproduce.124sqlite::database db = sqlite::database::temporary();125create_test_table(raw(db));126verify_test_table(raw(db));127}128129130ATF_TEST_CASE_WITHOUT_HEAD(close);131ATF_TEST_CASE_BODY(close)132{133sqlite::database db = sqlite::database::in_memory();134db.close();135// The destructor for the database will run now. If it does a second close,136// we may crash, so let's see if we don't.137}138139140ATF_TEST_CASE_WITHOUT_HEAD(copy);141ATF_TEST_CASE_BODY(copy)142{143sqlite::database db1 = sqlite::database::in_memory();144{145sqlite::database db2 = sqlite::database::in_memory();146create_test_table(raw(db2));147db1 = db2;148verify_test_table(raw(db1));149}150// db2 went out of scope. If the destruction is not properly managed, the151// memory of db1 may have been invalidated and this would not work.152verify_test_table(raw(db1));153}154155156ATF_TEST_CASE_WITHOUT_HEAD(db_filename__in_memory);157ATF_TEST_CASE_BODY(db_filename__in_memory)158{159const sqlite::database db = sqlite::database::in_memory();160ATF_REQUIRE(!db.db_filename());161}162163164ATF_TEST_CASE_WITHOUT_HEAD(db_filename__file);165ATF_TEST_CASE_BODY(db_filename__file)166{167const sqlite::database db = sqlite::database::open(fs::path("test.db"),168sqlite::open_readwrite | sqlite::open_create);169ATF_REQUIRE(db.db_filename());170ATF_REQUIRE_EQ(fs::path("test.db"), db.db_filename().get());171}172173174ATF_TEST_CASE_WITHOUT_HEAD(db_filename__temporary);175ATF_TEST_CASE_BODY(db_filename__temporary)176{177const sqlite::database db = sqlite::database::temporary();178ATF_REQUIRE(!db.db_filename());179}180181182ATF_TEST_CASE_WITHOUT_HEAD(db_filename__ok_after_close);183ATF_TEST_CASE_BODY(db_filename__ok_after_close)184{185sqlite::database db = sqlite::database::open(fs::path("test.db"),186sqlite::open_readwrite | sqlite::open_create);187const optional< fs::path > db_filename = db.db_filename();188ATF_REQUIRE(db_filename);189db.close();190ATF_REQUIRE_EQ(db_filename, db.db_filename());191}192193194ATF_TEST_CASE_WITHOUT_HEAD(exec__ok);195ATF_TEST_CASE_BODY(exec__ok)196{197sqlite::database db = sqlite::database::in_memory();198db.exec(create_test_table_sql);199verify_test_table(raw(db));200}201202203ATF_TEST_CASE_WITHOUT_HEAD(exec__fail);204ATF_TEST_CASE_BODY(exec__fail)205{206sqlite::database db = sqlite::database::in_memory();207REQUIRE_API_ERROR("sqlite3_exec",208db.exec("SELECT * FROM test"));209REQUIRE_API_ERROR("sqlite3_exec",210db.exec("CREATE TABLE test (col INTEGER PRIMARY KEY);"211"FOO BAR"));212db.exec("SELECT * FROM test");213}214215216ATF_TEST_CASE_WITHOUT_HEAD(create_statement__ok);217ATF_TEST_CASE_BODY(create_statement__ok)218{219sqlite::database db = sqlite::database::in_memory();220sqlite::statement stmt = db.create_statement("SELECT 3");221// Statement testing happens in statement_test. We are only interested here222// in ensuring that the API call exists and runs.223}224225226ATF_TEST_CASE_WITHOUT_HEAD(begin_transaction);227ATF_TEST_CASE_BODY(begin_transaction)228{229sqlite::database db = sqlite::database::in_memory();230sqlite::transaction stmt = db.begin_transaction();231// Transaction testing happens in transaction_test. We are only interested232// here in ensuring that the API call exists and runs.233}234235236ATF_TEST_CASE_WITHOUT_HEAD(create_statement__fail);237ATF_TEST_CASE_BODY(create_statement__fail)238{239sqlite::database db = sqlite::database::in_memory();240REQUIRE_API_ERROR("sqlite3_prepare_v2",241db.create_statement("SELECT * FROM missing"));242}243244245ATF_TEST_CASE_WITHOUT_HEAD(last_insert_rowid);246ATF_TEST_CASE_BODY(last_insert_rowid)247{248sqlite::database db = sqlite::database::in_memory();249db.exec("CREATE TABLE test (a INTEGER PRIMARY KEY, b INTEGER)");250db.exec("INSERT INTO test VALUES (723, 5)");251ATF_REQUIRE_EQ(723, db.last_insert_rowid());252db.exec("INSERT INTO test VALUES (145, 20)");253ATF_REQUIRE_EQ(145, db.last_insert_rowid());254}255256257ATF_INIT_TEST_CASES(tcs)258{259ATF_ADD_TEST_CASE(tcs, in_memory);260261ATF_ADD_TEST_CASE(tcs, open__readonly__ok);262ATF_ADD_TEST_CASE(tcs, open__readonly__fail);263ATF_ADD_TEST_CASE(tcs, open__create__ok);264ATF_ADD_TEST_CASE(tcs, open__create__fail);265266ATF_ADD_TEST_CASE(tcs, temporary);267268ATF_ADD_TEST_CASE(tcs, close);269270ATF_ADD_TEST_CASE(tcs, copy);271272ATF_ADD_TEST_CASE(tcs, db_filename__in_memory);273ATF_ADD_TEST_CASE(tcs, db_filename__file);274ATF_ADD_TEST_CASE(tcs, db_filename__temporary);275ATF_ADD_TEST_CASE(tcs, db_filename__ok_after_close);276277ATF_ADD_TEST_CASE(tcs, exec__ok);278ATF_ADD_TEST_CASE(tcs, exec__fail);279280ATF_ADD_TEST_CASE(tcs, begin_transaction);281282ATF_ADD_TEST_CASE(tcs, create_statement__ok);283ATF_ADD_TEST_CASE(tcs, create_statement__fail);284285ATF_ADD_TEST_CASE(tcs, last_insert_rowid);286}287288289