108334c51SBrooks Davis // Copyright 2011 The Kyua Authors.
208334c51SBrooks Davis // All rights reserved.
308334c51SBrooks Davis //
408334c51SBrooks Davis // Redistribution and use in source and binary forms, with or without
508334c51SBrooks Davis // modification, are permitted provided that the following conditions are
608334c51SBrooks Davis // met:
708334c51SBrooks Davis //
808334c51SBrooks Davis // * Redistributions of source code must retain the above copyright
908334c51SBrooks Davis // notice, this list of conditions and the following disclaimer.
1008334c51SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
1108334c51SBrooks Davis // notice, this list of conditions and the following disclaimer in the
1208334c51SBrooks Davis // documentation and/or other materials provided with the distribution.
1308334c51SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
1408334c51SBrooks Davis // may be used to endorse or promote products derived from this software
1508334c51SBrooks Davis // without specific prior written permission.
1608334c51SBrooks Davis //
1708334c51SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1808334c51SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1908334c51SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2008334c51SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2108334c51SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2208334c51SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2308334c51SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2408334c51SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2508334c51SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2608334c51SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2708334c51SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2808334c51SBrooks Davis
2908334c51SBrooks Davis #include "utils/sqlite/exceptions.hpp"
3008334c51SBrooks Davis
3108334c51SBrooks Davis extern "C" {
3208334c51SBrooks Davis #include <sqlite3.h>
3308334c51SBrooks Davis }
3408334c51SBrooks Davis
3508334c51SBrooks Davis #include <cstring>
3608334c51SBrooks Davis #include <string>
3708334c51SBrooks Davis
3808334c51SBrooks Davis #include <atf-c++.hpp>
3908334c51SBrooks Davis
4008334c51SBrooks Davis #include "utils/fs/path.hpp"
4108334c51SBrooks Davis #include "utils/optional.ipp"
4208334c51SBrooks Davis #include "utils/sqlite/c_gate.hpp"
4308334c51SBrooks Davis #include "utils/sqlite/database.hpp"
4408334c51SBrooks Davis
4508334c51SBrooks Davis namespace fs = utils::fs;
4608334c51SBrooks Davis namespace sqlite = utils::sqlite;
4708334c51SBrooks Davis
4808334c51SBrooks Davis using utils::none;
4908334c51SBrooks Davis
5008334c51SBrooks Davis
5108334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(error__no_filename);
ATF_TEST_CASE_BODY(error__no_filename)5208334c51SBrooks Davis ATF_TEST_CASE_BODY(error__no_filename)
5308334c51SBrooks Davis {
5408334c51SBrooks Davis const sqlite::database db = sqlite::database::in_memory();
5508334c51SBrooks Davis const sqlite::error e(db.db_filename(), "Some text");
5608334c51SBrooks Davis ATF_REQUIRE_EQ("Some text (sqlite db: in-memory or temporary)",
5708334c51SBrooks Davis std::string(e.what()));
5808334c51SBrooks Davis ATF_REQUIRE_EQ(db.db_filename(), e.db_filename());
5908334c51SBrooks Davis }
6008334c51SBrooks Davis
6108334c51SBrooks Davis
6208334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(error__with_filename);
ATF_TEST_CASE_BODY(error__with_filename)6308334c51SBrooks Davis ATF_TEST_CASE_BODY(error__with_filename)
6408334c51SBrooks Davis {
6508334c51SBrooks Davis const sqlite::database db = sqlite::database::open(
6608334c51SBrooks Davis fs::path("test.db"), sqlite::open_readwrite | sqlite::open_create);
6708334c51SBrooks Davis const sqlite::error e(db.db_filename(), "Some text");
6808334c51SBrooks Davis ATF_REQUIRE_EQ("Some text (sqlite db: test.db)", std::string(e.what()));
6908334c51SBrooks Davis ATF_REQUIRE_EQ(db.db_filename(), e.db_filename());
7008334c51SBrooks Davis }
7108334c51SBrooks Davis
7208334c51SBrooks Davis
7308334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(api_error__explicit);
ATF_TEST_CASE_BODY(api_error__explicit)7408334c51SBrooks Davis ATF_TEST_CASE_BODY(api_error__explicit)
7508334c51SBrooks Davis {
7608334c51SBrooks Davis const sqlite::api_error e(none, "some_function", "Some text");
7708334c51SBrooks Davis ATF_REQUIRE_EQ(
7808334c51SBrooks Davis "Some text (sqlite op: some_function) "
7908334c51SBrooks Davis "(sqlite db: in-memory or temporary)",
8008334c51SBrooks Davis std::string(e.what()));
8108334c51SBrooks Davis ATF_REQUIRE_EQ("some_function", e.api_function());
8208334c51SBrooks Davis }
8308334c51SBrooks Davis
8408334c51SBrooks Davis
8508334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(api_error__from_database);
ATF_TEST_CASE_BODY(api_error__from_database)8608334c51SBrooks Davis ATF_TEST_CASE_BODY(api_error__from_database)
8708334c51SBrooks Davis {
8808334c51SBrooks Davis sqlite::database db = sqlite::database::open(
8908334c51SBrooks Davis fs::path("test.db"), sqlite::open_readwrite | sqlite::open_create);
9008334c51SBrooks Davis
9108334c51SBrooks Davis // Use the raw sqlite3 API to cause an error. Our C++ wrappers catch all
9208334c51SBrooks Davis // errors and reraise them as exceptions, but here we want to handle the raw
9308334c51SBrooks Davis // error directly for testing purposes.
9408334c51SBrooks Davis sqlite::database_c_gate gate(db);
9508334c51SBrooks Davis ::sqlite3_stmt* dummy_stmt;
9608334c51SBrooks Davis const char* query = "ABCDE INVALID QUERY";
9708334c51SBrooks Davis (void)::sqlite3_prepare_v2(gate.c_database(), query, std::strlen(query),
9808334c51SBrooks Davis &dummy_stmt, NULL);
9908334c51SBrooks Davis
10008334c51SBrooks Davis const sqlite::api_error e = sqlite::api_error::from_database(
10108334c51SBrooks Davis db, "real_function");
10208334c51SBrooks Davis ATF_REQUIRE_MATCH(
10308334c51SBrooks Davis ".*ABCDE.*\\(sqlite op: real_function\\) \\(sqlite db: test.db\\)",
10408334c51SBrooks Davis std::string(e.what()));
10508334c51SBrooks Davis ATF_REQUIRE_EQ("real_function", e.api_function());
10608334c51SBrooks Davis }
10708334c51SBrooks Davis
10808334c51SBrooks Davis
10908334c51SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(invalid_column_error);
ATF_TEST_CASE_BODY(invalid_column_error)11008334c51SBrooks Davis ATF_TEST_CASE_BODY(invalid_column_error)
11108334c51SBrooks Davis {
11208334c51SBrooks Davis const sqlite::invalid_column_error e(none, "some_name");
11308334c51SBrooks Davis ATF_REQUIRE_EQ("Unknown column 'some_name' "
11408334c51SBrooks Davis "(sqlite db: in-memory or temporary)",
11508334c51SBrooks Davis std::string(e.what()));
11608334c51SBrooks Davis ATF_REQUIRE_EQ("some_name", e.column_name());
11708334c51SBrooks Davis }
11808334c51SBrooks Davis
11908334c51SBrooks Davis
ATF_INIT_TEST_CASES(tcs)12008334c51SBrooks Davis ATF_INIT_TEST_CASES(tcs)
12108334c51SBrooks Davis {
12208334c51SBrooks Davis ATF_ADD_TEST_CASE(tcs, error__no_filename);
12308334c51SBrooks Davis ATF_ADD_TEST_CASE(tcs, error__with_filename);
12408334c51SBrooks Davis
12508334c51SBrooks Davis ATF_ADD_TEST_CASE(tcs, api_error__explicit);
12608334c51SBrooks Davis ATF_ADD_TEST_CASE(tcs, api_error__from_database);
12708334c51SBrooks Davis
12808334c51SBrooks Davis ATF_ADD_TEST_CASE(tcs, invalid_column_error);
12908334c51SBrooks Davis }
130