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/exceptions.hpp"
30
31extern "C" {
32#include <sqlite3.h>
33}
34
35#include <cstring>
36#include <string>
37
38#include <atf-c++.hpp>
39
40#include "utils/fs/path.hpp"
41#include "utils/optional.ipp"
42#include "utils/sqlite/c_gate.hpp"
43#include "utils/sqlite/database.hpp"
44
45namespace fs = utils::fs;
46namespace sqlite = utils::sqlite;
47
48using utils::none;
49
50
51ATF_TEST_CASE_WITHOUT_HEAD(error__no_filename);
52ATF_TEST_CASE_BODY(error__no_filename)
53{
54    const sqlite::database db = sqlite::database::in_memory();
55    const sqlite::error e(db.db_filename(), "Some text");
56    ATF_REQUIRE_EQ("Some text (sqlite db: in-memory or temporary)",
57                   std::string(e.what()));
58    ATF_REQUIRE_EQ(db.db_filename(), e.db_filename());
59}
60
61
62ATF_TEST_CASE_WITHOUT_HEAD(error__with_filename);
63ATF_TEST_CASE_BODY(error__with_filename)
64{
65    const sqlite::database db = sqlite::database::open(
66        fs::path("test.db"), sqlite::open_readwrite | sqlite::open_create);
67    const sqlite::error e(db.db_filename(), "Some text");
68    ATF_REQUIRE_EQ("Some text (sqlite db: test.db)", std::string(e.what()));
69    ATF_REQUIRE_EQ(db.db_filename(), e.db_filename());
70}
71
72
73ATF_TEST_CASE_WITHOUT_HEAD(api_error__explicit);
74ATF_TEST_CASE_BODY(api_error__explicit)
75{
76    const sqlite::api_error e(none, "some_function", "Some text");
77    ATF_REQUIRE_EQ(
78        "Some text (sqlite op: some_function) "
79        "(sqlite db: in-memory or temporary)",
80        std::string(e.what()));
81    ATF_REQUIRE_EQ("some_function", e.api_function());
82}
83
84
85ATF_TEST_CASE_WITHOUT_HEAD(api_error__from_database);
86ATF_TEST_CASE_BODY(api_error__from_database)
87{
88    sqlite::database db = sqlite::database::open(
89        fs::path("test.db"), sqlite::open_readwrite | sqlite::open_create);
90
91    // Use the raw sqlite3 API to cause an error.  Our C++ wrappers catch all
92    // errors and reraise them as exceptions, but here we want to handle the raw
93    // error directly for testing purposes.
94    sqlite::database_c_gate gate(db);
95    ::sqlite3_stmt* dummy_stmt;
96    const char* query = "ABCDE INVALID QUERY";
97    (void)::sqlite3_prepare_v2(gate.c_database(), query, std::strlen(query),
98                               &dummy_stmt, NULL);
99
100    const sqlite::api_error e = sqlite::api_error::from_database(
101        db, "real_function");
102    ATF_REQUIRE_MATCH(
103        ".*ABCDE.*\\(sqlite op: real_function\\) \\(sqlite db: test.db\\)",
104        std::string(e.what()));
105    ATF_REQUIRE_EQ("real_function", e.api_function());
106}
107
108
109ATF_TEST_CASE_WITHOUT_HEAD(invalid_column_error);
110ATF_TEST_CASE_BODY(invalid_column_error)
111{
112    const sqlite::invalid_column_error e(none, "some_name");
113    ATF_REQUIRE_EQ("Unknown column 'some_name' "
114                   "(sqlite db: in-memory or temporary)",
115                   std::string(e.what()));
116    ATF_REQUIRE_EQ("some_name", e.column_name());
117}
118
119
120ATF_INIT_TEST_CASES(tcs)
121{
122    ATF_ADD_TEST_CASE(tcs, error__no_filename);
123    ATF_ADD_TEST_CASE(tcs, error__with_filename);
124
125    ATF_ADD_TEST_CASE(tcs, api_error__explicit);
126    ATF_ADD_TEST_CASE(tcs, api_error__from_database);
127
128    ATF_ADD_TEST_CASE(tcs, invalid_column_error);
129}
130