mirror of
https://github.com/boostorg/mysql.git
synced 2026-02-14 00:42:53 +00:00
Integ tests now run with and without ssl
This commit is contained in:
4
TODO.txt
4
TODO.txt
@@ -1,6 +1,4 @@
|
||||
SSL
|
||||
Add an integ test in handshake to verify encrypted connections
|
||||
Add a new integ test that proves using every feature over a non-encrypted connection
|
||||
Update README
|
||||
Make ssl context in channel lazy
|
||||
Multiresultset
|
||||
@@ -25,6 +23,8 @@ Usability
|
||||
connection::run_sql that hides the resultset concept
|
||||
Consider if header-only is a good idea
|
||||
Technical debt
|
||||
Review convention in test names
|
||||
Review named_param
|
||||
Copy operations for handshake
|
||||
Review handshake auth_plugin_data - seems like buffer overrun is possible (auth data string_lenenc?)
|
||||
Take fetch_many() algorithm out into network_algorithms (e.g. read_many_rows)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "boost/mysql/value.hpp"
|
||||
#include "boost/mysql/row.hpp"
|
||||
#include "boost/mysql/error.hpp"
|
||||
#include "boost/mysql/connection_params.hpp"
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
@@ -12,6 +13,7 @@
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <ostream>
|
||||
#include <cassert>
|
||||
|
||||
namespace boost {
|
||||
namespace mysql {
|
||||
@@ -140,6 +142,16 @@ inline std::vector<std::uint8_t> concat_copy(
|
||||
return std::move(lhs);
|
||||
}
|
||||
|
||||
inline const char* to_string(ssl_mode m)
|
||||
{
|
||||
switch (m)
|
||||
{
|
||||
case ssl_mode::disable: return "nossl";
|
||||
case ssl_mode::require: return "ssl";
|
||||
default: assert(false); return "";
|
||||
}
|
||||
}
|
||||
|
||||
struct named_param {};
|
||||
|
||||
template <typename T, typename=std::enable_if_t<std::is_base_of_v<named_param, T>>>
|
||||
|
||||
@@ -12,13 +12,13 @@ using namespace boost::mysql::test;
|
||||
namespace
|
||||
{
|
||||
|
||||
struct CloseStatementTest : NetworkTest<>
|
||||
struct CloseStatementTest : NetworkTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(CloseStatementTest, ExistingOrClosedStatement)
|
||||
{
|
||||
auto* net = GetParam();
|
||||
auto* net = GetParam().net;
|
||||
|
||||
// Prepare a statement
|
||||
auto stmt = net->prepare_statement(conn, "SELECT * FROM empty_table");
|
||||
|
||||
@@ -55,8 +55,10 @@ std::ostream& operator<<(std::ostream& os, const database_types_testcase& v)
|
||||
return os << v.table << "." << v.field << "." << v.row_id;
|
||||
}
|
||||
|
||||
struct DatabaseTypesTest : IntegTestAfterHandshake, WithParamInterface<database_types_testcase>
|
||||
struct DatabaseTypesTest : IntegTestAfterHandshake,
|
||||
WithParamInterface<database_types_testcase>
|
||||
{
|
||||
DatabaseTypesTest(): IntegTestAfterHandshake(boost::mysql::ssl_mode::disable) {}
|
||||
};
|
||||
|
||||
TEST_P(DatabaseTypesTest, Query_MetadataAndValueCorrect)
|
||||
|
||||
@@ -19,14 +19,16 @@ using boost::mysql::tcp_prepared_statement;
|
||||
namespace
|
||||
{
|
||||
|
||||
struct ExecuteStatementTest : public NetworkTest<> {};
|
||||
struct ExecuteStatementTest : public NetworkTest
|
||||
{
|
||||
};
|
||||
|
||||
// Iterator version
|
||||
TEST_P(ExecuteStatementTest, Iterator_OkNoParams)
|
||||
{
|
||||
std::forward_list<value> params;
|
||||
auto stmt = conn.prepare_statement("SELECT * FROM empty_table");
|
||||
auto result = GetParam()->execute_statement(stmt, params.begin(), params.end()); // execute
|
||||
auto result = GetParam().net->execute_statement(stmt, params.begin(), params.end()); // execute
|
||||
result.validate_no_error();
|
||||
EXPECT_TRUE(result.value.valid());
|
||||
}
|
||||
@@ -35,7 +37,7 @@ TEST_P(ExecuteStatementTest, Iterator_OkWithParams)
|
||||
{
|
||||
std::forward_list<value> params { value("item"), value(42) };
|
||||
auto stmt = conn.prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)");
|
||||
auto result = GetParam()->execute_statement(stmt, params.begin(), params.end());
|
||||
auto result = GetParam().net->execute_statement(stmt, params.begin(), params.end());
|
||||
result.validate_no_error();
|
||||
EXPECT_TRUE(result.value.valid());
|
||||
}
|
||||
@@ -44,7 +46,7 @@ TEST_P(ExecuteStatementTest, Iterator_MismatchedNumParams)
|
||||
{
|
||||
std::forward_list<value> params { value("item") };
|
||||
auto stmt = conn.prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)");
|
||||
auto result = GetParam()->execute_statement(stmt, params.begin(), params.end());
|
||||
auto result = GetParam().net->execute_statement(stmt, params.begin(), params.end());
|
||||
result.validate_error(errc::wrong_num_params, {"param", "2", "1", "statement", "execute"});
|
||||
EXPECT_FALSE(result.value.valid());
|
||||
}
|
||||
@@ -53,7 +55,7 @@ TEST_P(ExecuteStatementTest, Iterator_ServerError)
|
||||
{
|
||||
std::forward_list<value> params { value("f0"), value("bad_date") };
|
||||
auto stmt = conn.prepare_statement("INSERT INTO inserts_table (field_varchar, field_date) VALUES (?, ?)");
|
||||
auto result = GetParam()->execute_statement(stmt, params.begin(), params.end());
|
||||
auto result = GetParam().net->execute_statement(stmt, params.begin(), params.end());
|
||||
result.validate_error(errc::truncated_wrong_value, {"field_date", "bad_date", "incorrect date value"});
|
||||
EXPECT_FALSE(result.value.valid());
|
||||
}
|
||||
@@ -62,7 +64,7 @@ TEST_P(ExecuteStatementTest, Iterator_ServerError)
|
||||
TEST_P(ExecuteStatementTest, Container_OkNoParams)
|
||||
{
|
||||
auto stmt = conn.prepare_statement("SELECT * FROM empty_table");
|
||||
auto result = GetParam()->execute_statement(stmt, std::vector<value>()); // execute
|
||||
auto result = GetParam().net->execute_statement(stmt, std::vector<value>()); // execute
|
||||
result.validate_no_error();
|
||||
EXPECT_TRUE(result.value.valid());
|
||||
}
|
||||
@@ -71,7 +73,7 @@ TEST_P(ExecuteStatementTest, Container_OkWithParams)
|
||||
{
|
||||
std::vector<value> params { value("item"), value(42) };
|
||||
auto stmt = conn.prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)");
|
||||
auto result = GetParam()->execute_statement(stmt, params);
|
||||
auto result = GetParam().net->execute_statement(stmt, params);
|
||||
result.validate_no_error();
|
||||
EXPECT_TRUE(result.value.valid());
|
||||
}
|
||||
@@ -80,7 +82,7 @@ TEST_P(ExecuteStatementTest, Container_MismatchedNumParams)
|
||||
{
|
||||
std::vector<value> params { value("item") };
|
||||
auto stmt = conn.prepare_statement("SELECT * FROM empty_table WHERE id IN (?, ?)");
|
||||
auto result = GetParam()->execute_statement(stmt, params);
|
||||
auto result = GetParam().net->execute_statement(stmt, params);
|
||||
result.validate_error(errc::wrong_num_params, {"param", "2", "1", "statement", "execute"});
|
||||
EXPECT_FALSE(result.value.valid());
|
||||
}
|
||||
@@ -88,7 +90,7 @@ TEST_P(ExecuteStatementTest, Container_MismatchedNumParams)
|
||||
TEST_P(ExecuteStatementTest, Container_ServerError)
|
||||
{
|
||||
auto stmt = conn.prepare_statement("INSERT INTO inserts_table (field_varchar, field_date) VALUES (?, ?)");
|
||||
auto result = GetParam()->execute_statement(stmt, makevalues("f0", "bad_date"));
|
||||
auto result = GetParam().net->execute_statement(stmt, makevalues("f0", "bad_date"));
|
||||
result.validate_error(errc::truncated_wrong_value, {"field_date", "bad_date", "incorrect date value"});
|
||||
EXPECT_FALSE(result.value.valid());
|
||||
}
|
||||
|
||||
@@ -22,18 +22,23 @@ using boost::mysql::error_code;
|
||||
namespace
|
||||
{
|
||||
|
||||
struct HandshakeTest : public NetworkTest<IntegTest>
|
||||
struct HandshakeTest : public IntegTest,
|
||||
public testing::WithParamInterface<network_testcase>
|
||||
{
|
||||
auto do_handshake() { return GetParam()->handshake(conn, connection_params); }
|
||||
auto do_handshake()
|
||||
{
|
||||
connection_params.set_ssl(boost::mysql::ssl_options(GetParam().ssl));
|
||||
return GetParam().net->handshake(conn, connection_params);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(HandshakeTest, FastAuthSuccessfulLogin)
|
||||
TEST_P(HandshakeTest, SuccessfulLogin)
|
||||
{
|
||||
auto result = do_handshake();
|
||||
result.validate_no_error();
|
||||
}
|
||||
|
||||
TEST_P(HandshakeTest, FastAuthSuccessfulLoginEmptyPassword)
|
||||
TEST_P(HandshakeTest, SuccessfulLoginEmptyPassword)
|
||||
{
|
||||
connection_params.set_username("empty_password_user");
|
||||
connection_params.set_password("");
|
||||
@@ -41,14 +46,14 @@ TEST_P(HandshakeTest, FastAuthSuccessfulLoginEmptyPassword)
|
||||
result.validate_no_error();
|
||||
}
|
||||
|
||||
TEST_P(HandshakeTest, FastAuthSuccessfulLoginNoDatabase)
|
||||
TEST_P(HandshakeTest, SuccessfulLoginNoDatabase)
|
||||
{
|
||||
connection_params.set_database("");
|
||||
auto result = do_handshake();
|
||||
result.validate_no_error();
|
||||
}
|
||||
|
||||
TEST_P(HandshakeTest, FastAuthBadUser)
|
||||
TEST_P(HandshakeTest, BadUser)
|
||||
{
|
||||
connection_params.set_username("non_existing_user");
|
||||
auto result = do_handshake();
|
||||
@@ -57,14 +62,14 @@ TEST_P(HandshakeTest, FastAuthBadUser)
|
||||
// EXPECT_EQ(errc, make_error_code(mysql::errc::access_denied_error));
|
||||
}
|
||||
|
||||
TEST_P(HandshakeTest, FastAuthBadPassword)
|
||||
TEST_P(HandshakeTest, BadPassword)
|
||||
{
|
||||
connection_params.set_password("bad_password");
|
||||
auto result = do_handshake();
|
||||
result.validate_error(errc::access_denied_error, {"access denied", "integ_user"});
|
||||
}
|
||||
|
||||
TEST_P(HandshakeTest, FastAuthBadDatabase)
|
||||
TEST_P(HandshakeTest, BadDatabase)
|
||||
{
|
||||
connection_params.set_database("bad_database");
|
||||
auto result = do_handshake();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "boost/mysql/connection.hpp"
|
||||
#include "boost/mysql/detail/auxiliar/stringize.hpp"
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <future>
|
||||
@@ -47,8 +48,9 @@ struct IntegTest : testing::Test
|
||||
runner.join();
|
||||
}
|
||||
|
||||
void handshake()
|
||||
void handshake(ssl_mode m = ssl_mode::require)
|
||||
{
|
||||
connection_params.set_ssl(ssl_options(m));
|
||||
conn.handshake(connection_params);
|
||||
}
|
||||
|
||||
@@ -91,17 +93,46 @@ struct IntegTest : testing::Test
|
||||
|
||||
struct IntegTestAfterHandshake : IntegTest
|
||||
{
|
||||
IntegTestAfterHandshake() { handshake(); }
|
||||
IntegTestAfterHandshake(ssl_mode m = ssl_mode::require) { handshake(m); }
|
||||
};
|
||||
|
||||
template <typename BaseType = IntegTestAfterHandshake>
|
||||
struct NetworkTest : public BaseType,
|
||||
public testing::WithParamInterface<network_functions*>
|
||||
struct network_testcase
|
||||
{
|
||||
network_functions* net;
|
||||
ssl_mode ssl;
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
return detail::stringize(net->name(), '_', to_string(ssl));
|
||||
}
|
||||
};
|
||||
|
||||
inline std::vector<network_testcase> make_all_network_testcases()
|
||||
{
|
||||
std::vector<network_testcase> res;
|
||||
for (auto* net: all_network_functions)
|
||||
{
|
||||
for (auto ssl: {ssl_mode::require, ssl_mode::disable})
|
||||
{
|
||||
res.push_back(network_testcase{net, ssl});
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct NetworkTest : public IntegTestAfterHandshake,
|
||||
public testing::WithParamInterface<network_testcase>
|
||||
{
|
||||
NetworkTest(): IntegTestAfterHandshake(GetParam().ssl) {}
|
||||
};
|
||||
|
||||
} // test
|
||||
} // mysql
|
||||
} // boost
|
||||
|
||||
#define MYSQL_NETWORK_TEST_SUITE(TestSuiteName) \
|
||||
INSTANTIATE_TEST_SUITE_P(Default, TestSuiteName, testing::ValuesIn( \
|
||||
make_all_network_testcases() \
|
||||
), [](const auto& param_info) { return param_info.param.name(); })
|
||||
|
||||
#endif /* TEST_INTEGRATION_INTEGRATION_TEST_COMMON_HPP_ */
|
||||
|
||||
@@ -97,11 +97,6 @@ inline network_functions* all_network_functions [] = {
|
||||
async_future_noerrinfo_network_functions
|
||||
};
|
||||
|
||||
#define MYSQL_NETWORK_TEST_SUITE(TestSuiteName) \
|
||||
INSTANTIATE_TEST_SUITE_P(Default, TestSuiteName, testing::ValuesIn( \
|
||||
all_network_functions \
|
||||
), [](const auto& param_info) { return param_info.param->name(); })
|
||||
|
||||
|
||||
} // test
|
||||
} // mysql
|
||||
|
||||
@@ -17,13 +17,13 @@ using boost::mysql::tcp_connection;
|
||||
namespace
|
||||
{
|
||||
|
||||
struct PrepareStatementTest : public NetworkTest<>
|
||||
struct PrepareStatementTest : public NetworkTest
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(PrepareStatementTest, OkNoParams)
|
||||
{
|
||||
auto stmt = GetParam()->prepare_statement(conn, "SELECT * FROM empty_table");
|
||||
auto stmt = GetParam().net->prepare_statement(conn, "SELECT * FROM empty_table");
|
||||
stmt.validate_no_error();
|
||||
ASSERT_TRUE(stmt.value.valid());
|
||||
EXPECT_GT(stmt.value.id(), 0u);
|
||||
@@ -32,7 +32,7 @@ TEST_P(PrepareStatementTest, OkNoParams)
|
||||
|
||||
TEST_P(PrepareStatementTest, OkWithParams)
|
||||
{
|
||||
auto stmt = GetParam()->prepare_statement(conn, "SELECT * FROM empty_table WHERE id IN (?, ?)");
|
||||
auto stmt = GetParam().net->prepare_statement(conn, "SELECT * FROM empty_table WHERE id IN (?, ?)");
|
||||
stmt.validate_no_error();
|
||||
ASSERT_TRUE(stmt.value.valid());
|
||||
EXPECT_GT(stmt.value.id(), 0u);
|
||||
@@ -41,7 +41,7 @@ TEST_P(PrepareStatementTest, OkWithParams)
|
||||
|
||||
TEST_P(PrepareStatementTest, Error)
|
||||
{
|
||||
auto stmt = GetParam()->prepare_statement(conn, "SELECT * FROM bad_table WHERE id IN (?, ?)");
|
||||
auto stmt = GetParam().net->prepare_statement(conn, "SELECT * FROM bad_table WHERE id IN (?, ?)");
|
||||
stmt.validate_error(errc::no_such_table, {"table", "doesn't exist", "bad_table"});
|
||||
EXPECT_FALSE(stmt.value.valid());
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ using boost::mysql::value;
|
||||
namespace
|
||||
{
|
||||
|
||||
struct PreparedStatementLifecycleTest : NetworkTest<>
|
||||
struct PreparedStatementLifecycleTest : NetworkTest
|
||||
{
|
||||
std::int64_t get_table_size(const std::string& table)
|
||||
{
|
||||
@@ -31,7 +31,7 @@ struct PreparedStatementLifecycleTest : NetworkTest<>
|
||||
|
||||
TEST_P(PreparedStatementLifecycleTest, SelectWithParametersMultipleExecutions)
|
||||
{
|
||||
auto* net = GetParam();
|
||||
auto* net = GetParam().net;
|
||||
|
||||
// Prepare a statement
|
||||
auto stmt = net->prepare_statement(
|
||||
@@ -74,7 +74,7 @@ TEST_P(PreparedStatementLifecycleTest, SelectWithParametersMultipleExecutions)
|
||||
|
||||
TEST_P(PreparedStatementLifecycleTest, InsertWithParametersMultipleExecutions)
|
||||
{
|
||||
auto* net = GetParam();
|
||||
auto* net = GetParam().net;
|
||||
|
||||
// Get the number of rows before insertion
|
||||
auto rows_before = get_table_size("inserts_table");
|
||||
@@ -111,7 +111,7 @@ TEST_P(PreparedStatementLifecycleTest, InsertWithParametersMultipleExecutions)
|
||||
|
||||
TEST_P(PreparedStatementLifecycleTest, UpdateWithParametersMultipleExecutions)
|
||||
{
|
||||
auto* net = GetParam();
|
||||
auto* net = GetParam().net;
|
||||
|
||||
// Prepare a statement
|
||||
auto stmt = net->prepare_statement(
|
||||
@@ -147,7 +147,7 @@ TEST_P(PreparedStatementLifecycleTest, UpdateWithParametersMultipleExecutions)
|
||||
|
||||
TEST_P(PreparedStatementLifecycleTest, MultipleStatements)
|
||||
{
|
||||
auto* net = GetParam();
|
||||
auto* net = GetParam().net;
|
||||
|
||||
// Prepare an update
|
||||
auto stmt_update = net->prepare_statement(
|
||||
@@ -203,7 +203,7 @@ TEST_P(PreparedStatementLifecycleTest, MultipleStatements)
|
||||
|
||||
TEST_P(PreparedStatementLifecycleTest, InsertWithNullValues)
|
||||
{
|
||||
auto* net = GetParam();
|
||||
auto* net = GetParam().net;
|
||||
|
||||
// Statement to perform the updates
|
||||
auto stmt = net->prepare_statement(
|
||||
|
||||
@@ -23,9 +23,9 @@ using boost::mysql::errc;
|
||||
namespace
|
||||
{
|
||||
|
||||
struct QueryTest : public NetworkTest<>
|
||||
struct QueryTest : public NetworkTest
|
||||
{
|
||||
auto do_query(std::string_view sql) { return GetParam()->query(conn, sql); }
|
||||
auto do_query(std::string_view sql) { return GetParam().net->query(conn, sql); }
|
||||
};
|
||||
|
||||
TEST_P(QueryTest, InsertQueryOk)
|
||||
|
||||
@@ -16,6 +16,7 @@ using boost::mysql::error_code;
|
||||
using boost::mysql::error_info;
|
||||
using boost::mysql::tcp_resultset;
|
||||
using boost::mysql::tcp_connection;
|
||||
using boost::mysql::ssl_mode;
|
||||
namespace net = boost::asio;
|
||||
|
||||
namespace
|
||||
@@ -29,23 +30,25 @@ public:
|
||||
virtual tcp_resultset generate(tcp_connection&, std::string_view) = 0;
|
||||
};
|
||||
|
||||
struct ResultsetTestParam : named_param
|
||||
struct resultset_testcase : named_param, network_testcase
|
||||
{
|
||||
resultset_generator* gen;
|
||||
network_functions* net;
|
||||
|
||||
ResultsetTestParam(resultset_generator* gen, network_functions* net):
|
||||
gen(gen), net(net) {}
|
||||
resultset_testcase(network_testcase base, resultset_generator* gen):
|
||||
network_testcase(base), gen(gen) {}
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ResultsetTestParam& v)
|
||||
std::ostream& operator<<(std::ostream& os, const resultset_testcase& v)
|
||||
{
|
||||
return os << v.gen->name() << '.' << v.net->name();
|
||||
return os << v.gen->name() << '.'
|
||||
<< v.net->name() << '.'
|
||||
<< to_string(v.ssl);
|
||||
}
|
||||
|
||||
struct ResultsetTest : public IntegTestAfterHandshake,
|
||||
public testing::WithParamInterface<ResultsetTestParam>
|
||||
public testing::WithParamInterface<resultset_testcase>
|
||||
{
|
||||
ResultsetTest(): IntegTestAfterHandshake(GetParam().ssl) {}
|
||||
auto do_generate(std::string_view query) { return GetParam().gen->generate(conn, query); }
|
||||
auto do_fetch_one(tcp_resultset& r) { return GetParam().net->fetch_one(r); }
|
||||
auto do_fetch_many(tcp_resultset& r, std::size_t count) { return GetParam().net->fetch_many(r, count); }
|
||||
@@ -273,14 +276,14 @@ resultset_generator* all_resultset_generators [] = {
|
||||
&binary_obj
|
||||
};
|
||||
|
||||
std::vector<ResultsetTestParam> make_resultset_test_params()
|
||||
std::vector<resultset_testcase> make_all_resultset_testcases()
|
||||
{
|
||||
std::vector<ResultsetTestParam> res;
|
||||
std::vector<resultset_testcase> res;
|
||||
for (auto* gen: all_resultset_generators)
|
||||
{
|
||||
for (auto* net: all_network_functions)
|
||||
for (auto base: make_all_network_testcases())
|
||||
{
|
||||
res.push_back(ResultsetTestParam{gen, net});
|
||||
res.push_back(resultset_testcase(base, gen));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@@ -288,7 +291,7 @@ std::vector<ResultsetTestParam> make_resultset_test_params()
|
||||
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(Default, ResultsetTest, testing::ValuesIn(
|
||||
make_resultset_test_params()
|
||||
make_all_resultset_testcases()
|
||||
), test_name_generator);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user