encryption_test: Make PyKMIP run under seastar::experimental::process

Removes the requirement of boost::process, and all its non-seastar-ness.
Hopefully also makes the IO and shutdown handling a bit more reliable.
This commit is contained in:
Calle Wilund
2025-07-09 09:17:35 +00:00
parent 253323bb64
commit 722e2bce96
2 changed files with 71 additions and 72 deletions

View File

@@ -2134,7 +2134,6 @@ def kmip_arch():
kmipc_dir = f'kmipc/kmipc-2.1.0t-{kmiplib()}_{kmip_arch()}'
kmipc_lib = f'{kmipc_dir}/lib/libkmip.a'
libs += ' -lboost_filesystem'
if os.path.exists(kmipc_lib):
libs += f' {kmipc_lib}'
user_cflags += f' -I{kmipc_dir}/include -DHAVE_KMIP'

View File

@@ -5,7 +5,6 @@
#include <boost/test/unit_test.hpp>
#include <boost/process.hpp>
#include <stdint.h>
#include <random>
@@ -32,6 +31,7 @@
#include "test/lib/cql_test_env.hh"
#include "test/lib/cql_assertions.hh"
#include "test/lib/log.hh"
#include "test/lib/proc_utils.hh"
#include "db/config.hh"
#include "db/extensions.hh"
#include "db/commitlog/commitlog.hh"
@@ -309,16 +309,9 @@ struct kmip_test_info {
std::string prio;
};
namespace bp = boost::process;
static future<> kmip_test_helper(const std::function<future<>(const kmip_test_info&, const tmpdir&)>& f) {
tmpdir tmp;
bool host_set = false;
bp::child python;
bp::group gp;
bp::ipstream is;
std::future<void> pykmip_status;
static const char* def_resourcedir = "./test/resource/certs";
const char* resourcedir = std::getenv("KMIP_RESOURCE_DIR");
@@ -334,14 +327,6 @@ static future<> kmip_test_helper(const std::function<future<>(const kmip_test_in
.prio = get_var_or_default("KMIP_PRIO", "SECURE128:+RSA:-VERS-TLS1.0:-ECDHE-ECDSA")
};
auto cleanup = defer([&] {
if (python.running()) {
BOOST_TEST_MESSAGE("Stopping PyKMIP server"); // debug print. Why not.
gp.terminate();
pykmip_status.get();
}
});
// note: default kmip port = 5696;
if (!host_set) {
@@ -370,74 +355,89 @@ database_path={}/pykmip.db
of << cfg;
}
auto pyexec = bp::search_path("python");
auto pyexec = tests::proc::find_file_in_path("python");
BOOST_TEST_MESSAGE("Starting PyKMIP server"); // debug print. Why not.
promise<int> port_promise;
auto port_future = port_promise.get_future();
python = bp::child(pyexec, gp,
"test/boost/kmip_wrapper.py",
"-l", log,
"-f", cfgfile,
"-v", "DEBUG",
(bp::std_out & bp::std_err) > is, bp::std_in.close(),
bp::env["TMPDIR"]=tmp.path().string()
auto python = co_await tests::proc::process_fixture::create(pyexec,
{ // args
pyexec.string(),
"test/boost/kmip_wrapper.py",
"-l", log,
"-f", cfgfile,
"-v", "DEBUG",
},
{ // env
fmt::format("TMPDIR={}", tmp.path().string())
},
// stdout handler
[port_promise = std::move(port_promise), b = false](std::string_view line) mutable -> future<consumption_result<char>> {
static std::regex port_ex("Listening on (\\d+)");
std::cout << line << std::endl;
std::match_results<typename std::string_view::const_iterator> m;
if (!b && std::regex_match(line.begin(), line.end(), m, port_ex)) {
port_promise.set_value(std::stoi(m[1].str()));
BOOST_TEST_MESSAGE("Matched PyKMIP port: " + m[1].str());
b = true;
}
co_return continue_consuming{};
},
// stderr handler
tests::proc::process_fixture::create_copy_handler(std::cerr)
);
std::promise<int> port_promise;
auto f = port_promise.get_future();
std::exception_ptr ep;
pykmip_status = std::async([&] {
static std::regex port_ex("Listening on (\\d+)");
try {
// arbitrary timeout of 20s for the server to make some output. Very generous.
auto port = co_await with_timeout(std::chrono::steady_clock::now() + 20s, std::move(port_future));
std::string line;
bool b = false;
if (port <= 0) {
throw std::runtime_error("Invalid port");
}
do {
while (std::getline(is, line)) {
std::cout << line << std::endl;
std::smatch m;
if (!b && std::regex_match(line, m, port_ex)) {
port_promise.set_value(std::stoi(m[1].str()));
b = true;
}
tls::credentials_builder b;
co_await b.set_x509_trust_file(info.ca, seastar::tls::x509_crt_format::PEM);
co_await b.set_x509_key_file(info.cert, info.key, seastar::tls::x509_crt_format::PEM);
auto certs = b.build_certificate_credentials();
// wait for port.
for (;;) {
try {
// TODO: seastar does not have a connect with timeout. That would be helpful here. But alas...
auto c = co_await seastar::tls::connect(certs, socket_address(net::inet_address("127.0.0.1"), port));
BOOST_TEST_MESSAGE("PyKMIP server up and available"); // debug print. Why not.
co_await tls::check_session_is_resumed(c); // forces handshake. Make python ssl happy.
c.shutdown_output();
break;
} catch (...) {
}
} while (python.running());
if (!b) {
port_promise.set_value(-1);
co_await sleep(100ms);
}
});
// arbitrary timeout of 20s for the server to make some output. Very generous.
if (f.wait_for(20s) == std::future_status::timeout) {
throw std::runtime_error("Could not start pykmip");
}
auto port = f.get();
if (port <= 0) {
throw std::runtime_error("Invalid port");
}
// wait for port.
tls::credentials_builder b;
co_await b.set_x509_trust_file(info.ca, seastar::tls::x509_crt_format::PEM);
co_await b.set_x509_key_file(info.cert, info.key, seastar::tls::x509_crt_format::PEM);
auto certs = b.build_certificate_credentials();
for (;;) {
try {
// TODO: seastar does not have a connect with timeout. That would be helpful here. But alas...
auto c = co_await seastar::tls::connect(certs, socket_address(net::inet_address("127.0.0.1"), port));
BOOST_TEST_MESSAGE("PyKMIP server up and available"); // debug print. Why not.
co_await tls::check_session_is_resumed(c); // forces handshake. Make python ssl happy.
c.shutdown_output();
break;
} catch (...) {
}
co_await sleep(100ms);
info.host = fmt::format("127.0.0.1:{}", port);
co_await f(info, tmp);
} catch (timed_out_error&) {
ep = std::make_exception_ptr(std::runtime_error("Could not start pykmip"));
} catch (...) {
ep = std::current_exception();
}
info.host = fmt::format("127.0.0.1:{}", port);
BOOST_TEST_MESSAGE("Stopping PyKMIP server"); // debug print. Why not.
python.terminate();
co_await python.wait();
if (ep) {
std::rethrow_exception(ep);
}
} else {
co_await f(info, tmp);
}
co_await f(info, tmp);
}
SEASTAR_TEST_CASE(test_kmip_provider, *check_run_test_decorator("ENABLE_KMIP_TEST", true)) {