| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- #include <numeric>
- #include <pqxx/transaction>
- #include "../test_helpers.hxx"
- namespace
- {
- void test_connection_string_constructor()
- {
- pqxx::connection c1{""};
- pqxx::connection c2{std::string{}};
- }
- void test_move_constructor()
- {
- pqxx::connection c1;
- PQXX_CHECK(c1.is_open(), "New connection is not open.");
- pqxx::connection c2{std::move(c1)};
- PQXX_CHECK(not c1.is_open(), "Moving did not close original connection.");
- PQXX_CHECK(c2.is_open(), "Moved constructor is not open.");
- pqxx::work tx{c2};
- PQXX_CHECK_EQUAL(tx.query_value<int>("SELECT 5"), 5, "Weird result!");
- PQXX_CHECK_THROWS(
- pqxx::connection c3{std::move(c2)}, pqxx::usage_error,
- "Moving a connection with a transaction open should be an error.");
- }
- void test_move_assign()
- {
- pqxx::connection c1;
- pqxx::connection c2;
- c2.close();
- c2 = std::move(c1);
- PQXX_CHECK(not c1.is_open(), "Connection still open after being moved out.");
- PQXX_CHECK(c2.is_open(), "Moved constructor is not open.");
- {
- pqxx::work tx1{c2};
- PQXX_CHECK_EQUAL(tx1.query_value<int>("SELECT 8"), 8, "What!?");
- pqxx::connection c3;
- PQXX_CHECK_THROWS(
- c3 = std::move(c2), pqxx::usage_error,
- "Moving a connection with a transaction open should be an error.");
- PQXX_CHECK_THROWS(
- c2 = std::move(c3), pqxx::usage_error,
- "Moving a connection onto one with a transaction open should be "
- "an error.");
- }
- // After failed move attempts, the connection is still usable.
- pqxx::work tx2{c2};
- PQXX_CHECK_EQUAL(tx2.query_value<int>("SELECT 6"), 6, "Huh!?");
- }
- void test_encrypt_password()
- {
- pqxx::connection c;
- auto pw{c.encrypt_password("user", "password")};
- PQXX_CHECK(not std::empty(pw), "Encrypted password was empty.");
- PQXX_CHECK_EQUAL(
- std::strlen(pw.c_str()), std::size(pw),
- "Encrypted password contains a null byte.");
- }
- void test_connection_string()
- {
- pqxx::connection c;
- std::string const connstr{c.connection_string()};
- #if defined(_MSC_VER)
- # pragma warning(push)
- # pragma warning(disable : 4996)
- #endif
- if (std::getenv("PGUSER") == nullptr)
- #if defined(_MSC_VER)
- # pragma warning(pop)
- #endif
- {
- PQXX_CHECK(
- connstr.find("user=" + std::string{c.username()}) != std::string::npos,
- "Connection string did not specify user name: " + connstr);
- }
- else
- {
- PQXX_CHECK(
- connstr.find("user=" + std::string{c.username()}) == std::string::npos,
- "Connection string specified user name, even when using default: " +
- connstr);
- }
- }
- #if defined(PQXX_HAVE_CONCEPTS)
- template<typename STR> std::size_t length(STR const &str)
- {
- return std::size(str);
- }
- std::size_t length(char const str[])
- {
- return std::strlen(str);
- }
- #endif // PQXX_HAVE_CONCEPTS
- template<typename MAP> void test_params_type()
- {
- #if defined(PQXX_HAVE_CONCEPTS)
- using item_t = std::remove_reference_t<
- decltype(*std::declval<std::ranges::iterator_t<MAP>>())>;
- using key_t = decltype(std::get<0>(std::declval<item_t>()));
- using value_t = decltype(std::get<1>(std::declval<item_t>()));
- // Set some parameters that are relatively safe to change arbitrarily.
- MAP const params{{
- {key_t{"application_name"}, value_t{"pqxx-test"}},
- {key_t{"connect_timeout"}, value_t{"96"}},
- {key_t{"keepalives_idle"}, value_t{"771"}},
- }};
- // Can we create a connection from these parameters?
- pqxx::connection c{params};
- // Check that the parameters came through in the connection string.
- // We don't know the exact format, but the parameters have to be in there.
- auto const min_size{std::accumulate(
- std::cbegin(params), std::cend(params), std::size(params) - 1,
- [](auto count, auto item) {
- return count + length(std::get<0>(item)) + 1 + length(std::get<1>(item));
- })};
- auto const connstr{c.connection_string()};
- PQXX_CHECK_GREATER_EQUAL(
- std::size(connstr), min_size,
- "Connection string can't possibly contain the options we gave.");
- for (auto const &[key, value] : params)
- {
- PQXX_CHECK_NOT_EQUAL(
- connstr.find(key), std::string::npos,
- "Could not find param name '" + std::string{key} +
- "' in connection string: " + connstr);
- PQXX_CHECK_NOT_EQUAL(
- connstr.find(value), std::string::npos,
- "Could not find value for '" + std::string{value} +
- "' in connection string: " + connstr);
- }
- #endif // PQXX_HAVE_CONCEPTS
- }
- void test_connection_params()
- {
- // Connecting in this way supports a wide variety of formats for the
- // parameters.
- test_params_type<std::map<char const *, char const *>>();
- test_params_type<std::map<pqxx::zview, pqxx::zview>>();
- test_params_type<std::map<std::string, std::string>>();
- test_params_type<std::map<std::string, pqxx::zview>>();
- test_params_type<std::map<pqxx::zview, char const *>>();
- test_params_type<std::vector<std::tuple<char const *, char const *>>>();
- test_params_type<std::vector<std::tuple<pqxx::zview, std::string>>>();
- test_params_type<std::vector<std::pair<std::string, char const *>>>();
- test_params_type<std::vector<std::array<std::string, 2>>>();
- }
- void test_raw_connection()
- {
- pqxx::connection conn1;
- PQXX_CHECK(conn1.is_open(), "Fresh connection is not open!");
- pqxx::work tx1{conn1};
- PQXX_CHECK_EQUAL(
- tx1.query_value<int>("SELECT 8"), 8, "Something weird happened.");
- pqxx::internal::pq::PGconn *raw{std::move(conn1).release_raw_connection()};
- PQXX_CHECK(raw != nullptr, "Raw connection is null.");
- PQXX_CHECK(
- not conn1.is_open(),
- "Releasing raw connection did not close pqxx::connection.");
- pqxx::connection conn2{pqxx::connection::seize_raw_connection(raw)};
- PQXX_CHECK(
- conn2.is_open(), "Can't produce open connection from raw connection.");
- pqxx::work tx2{conn2};
- PQXX_CHECK_EQUAL(
- tx2.query_value<int>("SELECT 9"), 9,
- "Raw connection did not produce a working new connection.");
- }
- PQXX_REGISTER_TEST(test_connection_string_constructor);
- PQXX_REGISTER_TEST(test_move_constructor);
- PQXX_REGISTER_TEST(test_move_assign);
- PQXX_REGISTER_TEST(test_encrypt_password);
- PQXX_REGISTER_TEST(test_connection_string);
- PQXX_REGISTER_TEST(test_connection_params);
- PQXX_REGISTER_TEST(test_raw_connection);
- } // namespace
|