| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- #include <stdexcept>
- #include <string>
- #include <pqxx/result>
- #include <pqxx/row>
- namespace pqxx
- {
- namespace test
- {
- class test_failure : public std::logic_error
- {
- std::string const m_file;
- int m_line;
- public:
- test_failure(std::string const &ffile, int fline, std::string const &desc);
- ~test_failure() noexcept override;
- std::string const &file() const noexcept { return m_file; }
- int line() const noexcept { return m_line; }
- };
- /// Drop a table, if it exists.
- void drop_table(transaction_base &, std::string const &table);
- using testfunc = void (*)();
- void register_test(char const name[], testfunc func);
- /// Register a test while not inside a function.
- struct registrar
- {
- registrar(char const name[], testfunc func)
- {
- pqxx::test::register_test(name, func);
- }
- };
- // Register a test function, so the runner will run it.
- #define PQXX_REGISTER_TEST(func) \
- pqxx::test::registrar tst_##func { #func, func }
- // Unconditional test failure.
- #define PQXX_CHECK_NOTREACHED(desc) \
- pqxx::test::check_notreached(__FILE__, __LINE__, (desc))
- [[noreturn]] void
- check_notreached(char const file[], int line, std::string desc);
- // Verify that a condition is met, similar to assert()
- #define PQXX_CHECK(condition, desc) \
- pqxx::test::check(__FILE__, __LINE__, (condition), #condition, (desc))
- void check(
- char const file[], int line, bool condition, char const text[],
- std::string const &desc);
- // Verify that variable has the expected value.
- #define PQXX_CHECK_EQUAL(actual, expected, desc) \
- pqxx::test::check_equal( \
- __FILE__, __LINE__, (actual), #actual, (expected), #expected, (desc))
- template<typename ACTUAL, typename EXPECTED>
- inline void check_equal(
- char const file[], int line, ACTUAL actual, char const actual_text[],
- EXPECTED expected, char const expected_text[], std::string const &desc)
- {
- if (expected == actual)
- return;
- std::string const fulldesc = desc + " (" + actual_text + " <> " +
- expected_text +
- ": "
- "actual=" +
- to_string(actual) +
- ", "
- "expected=" +
- to_string(expected) + ")";
- throw test_failure(file, line, fulldesc);
- }
- // Verify that two values are not equal.
- #define PQXX_CHECK_NOT_EQUAL(value1, value2, desc) \
- pqxx::test::check_not_equal( \
- __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc))
- template<typename VALUE1, typename VALUE2>
- inline void check_not_equal(
- char const file[], int line, VALUE1 value1, char const text1[],
- VALUE2 value2, char const text2[], std::string const &desc)
- {
- if (value1 != value2)
- return;
- std::string const fulldesc = desc + " (" + text1 + " == " + text2 +
- ": "
- "both are " +
- to_string(value2) + ")";
- throw test_failure(file, line, fulldesc);
- }
- // Verify that value1 is less than value2.
- #define PQXX_CHECK_LESS(value1, value2, desc) \
- pqxx::test::check_less( \
- __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc))
- // Verify that value1 is greater than value2.
- #define PQXX_CHECK_GREATER(value2, value1, desc) \
- pqxx::test::check_less( \
- __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc))
- template<typename VALUE1, typename VALUE2>
- inline void check_less(
- char const file[], int line, VALUE1 value1, char const text1[],
- VALUE2 value2, char const text2[], std::string const &desc)
- {
- if (value1 < value2)
- return;
- std::string const fulldesc = desc + " (" + text1 + " >= " + text2 +
- ": "
- "\"lower\"=" +
- to_string(value1) +
- ", "
- "\"upper\"=" +
- to_string(value2) + ")";
- throw test_failure(file, line, fulldesc);
- }
- // Verify that value1 is less than or equal to value2.
- #define PQXX_CHECK_LESS_EQUAL(value1, value2, desc) \
- pqxx::test::check_less_equal( \
- __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc))
- // Verify that value1 is greater than or equal to value2.
- #define PQXX_CHECK_GREATER_EQUAL(value2, value1, desc) \
- pqxx::test::check_less_equal( \
- __FILE__, __LINE__, (value1), #value1, (value2), #value2, (desc))
- template<typename VALUE1, typename VALUE2>
- inline void check_less_equal(
- char const file[], int line, VALUE1 value1, char const text1[],
- VALUE2 value2, char const text2[], std::string const &desc)
- {
- if (value1 <= value2)
- return;
- std::string const fulldesc = desc + " (" + text1 + " > " + text2 +
- ": "
- "\"lower\"=" +
- to_string(value1) +
- ", "
- "\"upper\"=" +
- to_string(value2) + ")";
- throw test_failure(file, line, fulldesc);
- }
- struct failure_to_fail
- {};
- namespace internal
- {
- /// Syntactic placeholder: require (and accept) semicolon after block.
- inline void end_of_statement() {}
- } // namespace internal
- // Verify that "action" does not throw an exception.
- #define PQXX_CHECK_SUCCEEDS(action, desc) \
- { \
- try \
- { \
- action; \
- } \
- catch (std::exception const &e) \
- { \
- PQXX_CHECK_NOTREACHED( \
- std::string{desc} + " - \"" + \
- #action "\" threw exception: " + e.what()); \
- } \
- catch (...) \
- { \
- PQXX_CHECK_NOTREACHED( \
- std::string{desc} + " - \"" + #action "\" threw a non-exception!"); \
- } \
- } \
- pqxx::test::internal::end_of_statement()
- // Verify that "action" throws an exception, of any std::exception-based type.
- #define PQXX_CHECK_THROWS_EXCEPTION(action, desc) \
- { \
- try \
- { \
- action; \
- throw pqxx::test::failure_to_fail(); \
- } \
- catch (pqxx::test::failure_to_fail const &) \
- { \
- PQXX_CHECK_NOTREACHED( \
- std::string{desc} + " (\"" #action "\" did not throw)"); \
- } \
- catch (std::exception const &) \
- {} \
- catch (...) \
- { \
- PQXX_CHECK_NOTREACHED( \
- std::string{desc} + " (\"" #action "\" threw non-exception type)"); \
- } \
- } \
- pqxx::test::internal::end_of_statement()
- // Verify that "action" throws "exception_type" (which is not std::exception).
- #define PQXX_CHECK_THROWS(action, exception_type, desc) \
- { \
- try \
- { \
- action; \
- throw pqxx::test::failure_to_fail(); \
- } \
- catch (pqxx::test::failure_to_fail const &) \
- { \
- PQXX_CHECK_NOTREACHED( \
- std::string{desc} + " (\"" #action \
- "\" did not throw " #exception_type ")"); \
- } \
- catch (exception_type const &) \
- {} \
- catch (std::exception const &e) \
- { \
- PQXX_CHECK_NOTREACHED( \
- std::string{desc} + \
- " (\"" #action \
- "\" " \
- "threw exception other than " #exception_type ": " + \
- e.what() + ")"); \
- } \
- catch (...) \
- { \
- PQXX_CHECK_NOTREACHED( \
- std::string{desc} + " (\"" #action "\" threw non-exception type)"); \
- } \
- } \
- pqxx::test::internal::end_of_statement()
- #define PQXX_CHECK_BOUNDS(value, lower, upper, desc) \
- pqxx::test::check_bounds( \
- __FILE__, __LINE__, (value), #value, (lower), #lower, (upper), #upper, \
- (desc))
- template<typename VALUE, typename LOWER, typename UPPER>
- inline void check_bounds(
- char const file[], int line, VALUE value, char const text[], LOWER lower,
- char const lower_text[], UPPER upper, char const upper_text[],
- std::string const &desc)
- {
- std::string const range_check = std::string{lower_text} + " < " + upper_text,
- lower_check =
- std::string{"!("} + text + " < " + lower_text + ")",
- upper_check = std::string{text} + " < " + upper_text;
- pqxx::test::check(
- file, line, lower < upper, range_check.c_str(),
- desc + " (acceptable range is empty; value was " + text + ")");
- pqxx::test::check(
- file, line, not(value < lower), lower_check.c_str(),
- desc + " (" + text + " is below lower bound " + lower_text + ")");
- pqxx::test::check(
- file, line, value < upper, upper_check.c_str(),
- desc + " (" + text + " is not below upper bound " + upper_text + ")");
- }
- // Report expected exception
- void expected_exception(std::string const &);
- // Represent result row as string.
- std::string list_row(row);
- // Represent result as string.
- std::string list_result(result);
- // Represent result iterator as string.
- std::string list_result_iterator(result::const_iterator);
- // @deprecated Set up test data for legacy tests.
- void create_pqxxevents(transaction_base &);
- } // namespace test
- template<> inline std::string to_string(row const &value)
- {
- return pqxx::test::list_row(value);
- }
- template<> inline std::string to_string(result const &value)
- {
- return pqxx::test::list_result(value);
- }
- template<> inline std::string to_string(result::const_iterator const &value)
- {
- return pqxx::test::list_result_iterator(value);
- }
- } // namespace pqxx
|