2
0
mirror of https://github.com/boostorg/mysql.git synced 2026-02-14 12:52:17 +00:00
Files
mysql/test/integration/reconnect.cpp
2021-03-09 08:24:39 +01:00

160 lines
5.6 KiB
C++

//
// Copyright (c) 2019-2021 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/asio/ssl/verify_mode.hpp>
#include <boost/mysql/socket_connection.hpp>
#include <boost/test/tools/interface.hpp>
#include <boost/test/unit_test_suite.hpp>
#include "boost/mysql/connection_params.hpp"
#include "boost/mysql/errc.hpp"
#include "get_endpoint.hpp"
#include "integration_test_common.hpp"
#include "network_functions.hpp"
using namespace boost::mysql::test;
using boost::mysql::ssl_mode;
BOOST_AUTO_TEST_SUITE(test_reconnect)
template <class Stream>
struct reconnect_fixture : network_fixture<Stream>
{
using network_fixture<Stream>::network_fixture;
void do_connect_ok(network_functions<Stream>* net, ssl_mode m)
{
this->params.set_ssl(m);
auto result = net->connect(this->conn, get_endpoint<Stream>(endpoint_kind::localhost), this->params);
result.validate_no_error();
validate_ssl(this->conn, m);
}
void do_query_ok(network_functions<Stream>* net)
{
auto result = net->query(this->conn, "SELECT * FROM empty_table");
result.validate_no_error();
auto read_result = net->read_all(result.value);
read_result.validate_no_error();
BOOST_TEST(read_result.value.empty());
}
};
template <class Stream>
struct reconnect_fixture_external_ctx : reconnect_fixture<Stream>
{
reconnect_fixture_external_ctx(): reconnect_fixture<Stream>(use_external_ctx) {}
};
// Using default SSL context
BOOST_AUTO_TEST_SUITE(default_ssl_ctx)
BOOST_MYSQL_NETWORK_TEST(reconnect_after_close, reconnect_fixture, network_ssl_gen)
{
// Connect and use the connection
this->do_connect_ok(sample.net, sample.ssl);
this->do_query_ok(sample.net);
// Close
auto result = sample.net->close(this->conn);
result.validate_no_error();
// Reopen and use the connection normally
this->do_connect_ok(sample.net, sample.ssl);
this->do_query_ok(sample.net);
}
BOOST_MYSQL_NETWORK_TEST(reconnect_after_handshake_error, reconnect_fixture, network_ssl_gen)
{
// Error during server handshake
this->params.set_ssl(sample.ssl);
this->params.set_database("bad_database");
auto result = sample.net->connect(this->conn, get_endpoint<Stream>(endpoint_kind::localhost), this->params);
result.validate_error(boost::mysql::errc::dbaccess_denied_error, {"database", "bad_database"});
// Reopen with correct parameters and use the connection normally
this->params.set_database("boost_mysql_integtests");
this->do_connect_ok(sample.net, sample.ssl);
this->do_query_ok(sample.net);
}
BOOST_MYSQL_NETWORK_TEST(reconnect_after_physical_connect_error, reconnect_fixture, network_ssl_gen)
{
// Error during connection
this->params.set_ssl(sample.ssl);
auto result = sample.net->connect(this->conn, get_endpoint<Stream>(endpoint_kind::inexistent), this->params);
result.validate_any_error({"physical connect failed"});
// Reopen with and use the connection normally
this->do_connect_ok(sample.net, sample.ssl);
this->do_query_ok(sample.net);
}
BOOST_AUTO_TEST_SUITE_END()
// Using custom SSL context
BOOST_AUTO_TEST_SUITE(external_ssl_ctx)
BOOST_MYSQL_NETWORK_TEST(reconnect_after_close, reconnect_fixture_external_ctx, network_ssl_gen)
{
// Connect and use the connection
this->do_connect_ok(sample.net, sample.ssl);
this->do_query_ok(sample.net);
// Close
auto result = sample.net->close(this->conn);
result.validate_no_error();
// Reopen and use the connection normally
this->do_connect_ok(sample.net, sample.ssl);
this->do_query_ok(sample.net);
}
BOOST_MYSQL_NETWORK_TEST(reconnect_after_handshake_error, reconnect_fixture_external_ctx, network_ssl_gen)
{
// Error during server handshake
this->params.set_ssl(sample.ssl);
this->params.set_database("bad_database");
auto result = sample.net->connect(this->conn, get_endpoint<Stream>(endpoint_kind::localhost), this->params);
result.validate_error(boost::mysql::errc::dbaccess_denied_error, {"database", "bad_database"});
// Reopen with correct parameters and use the connection normally
this->params.set_database("boost_mysql_integtests");
this->do_connect_ok(sample.net, sample.ssl);
this->do_query_ok(sample.net);
}
BOOST_MYSQL_NETWORK_TEST(reconnect_after_physical_connect_error, reconnect_fixture_external_ctx, network_ssl_gen)
{
// Error during connection
this->params.set_ssl(sample.ssl);
auto result = sample.net->connect(this->conn, get_endpoint<Stream>(endpoint_kind::inexistent), this->params);
result.validate_any_error({"physical connect failed"});
// Reopen with and use the connection normally
this->do_connect_ok(sample.net, sample.ssl);
this->do_query_ok(sample.net);
}
BOOST_MYSQL_NETWORK_TEST(reconnect_after_ssl_handshake_error, reconnect_fixture_external_ctx, network_gen)
{
// Error during SSL certificate validation
this->external_ctx.set_verify_mode(boost::asio::ssl::verify_peer);
this->params.set_ssl(boost::mysql::ssl_mode::require);
auto result = sample.net->connect(this->conn, get_endpoint<Stream>(endpoint_kind::localhost), this->params);
BOOST_TEST(result.err.message() == "certificate verify failed");
// Disable certificate validation and use the connection normally
this->external_ctx.set_verify_mode(boost::asio::ssl::verify_none);
this->do_connect_ok(sample.net, boost::mysql::ssl_mode::require);
this->do_query_ok(sample.net);
}
BOOST_AUTO_TEST_SUITE_END() // external ssl ctx
BOOST_AUTO_TEST_SUITE_END() // test_reconnect