21#include <test/jtx/CaptureLogs.h>
22#include <test/jtx/envconfig.h>
23#include <test/unit_test/SuiteJournal.h>
24#include <xrpld/core/ConfigSections.h>
25#include <xrpl/basics/make_SSLContext.h>
26#include <xrpl/beast/rfc2616.h>
27#include <xrpl/beast/unit_test.h>
28#include <xrpl/server/Server.h>
29#include <xrpl/server/Session.h>
31#include <boost/asio.hpp>
32#include <boost/beast/core/tcp_stream.hpp>
33#include <boost/beast/ssl/ssl_stream.hpp>
34#include <boost/utility/in_place_factory.hpp>
60 ,
thread_([&]() { this->io_service_.run(); })
70 boost::asio::io_service&
122 boost::asio::ip::tcp::endpoint remote_address)
131 boost::asio::ip::tcp::endpoint remote_address)
167 template <
class Socket>
169 connect(Socket& s,
typename Socket::endpoint_type
const& ep)
186 template <
class SyncWriteStream>
192 boost::asio::write(s, boost::asio::buffer(text));
204 template <
class SyncReadStream>
208 boost::asio::streambuf b(1000);
211 auto const n = boost::asio::read_until(s, b,
'\n');
212 if (BEAST_EXPECT(n ==
match.size()))
216 boost::asio::buffer_copy(
217 boost::asio::buffer(&got[0], n), b.data());
218 return BEAST_EXPECT(got ==
match);
235 boost::asio::io_service ios;
236 using socket = boost::asio::ip::tcp::socket;
245 "Connection: close\r\n"
252 boost::system::error_code ec;
253 s.shutdown(socket::shutdown_both, ec);
261 boost::asio::io_service ios;
262 using socket = boost::asio::ip::tcp::socket;
271 "Connection: Keep-Alive\r\n"
281 "Connection: close\r\n"
288 boost::system::error_code ec;
289 s.shutdown(socket::shutdown_both, ec);
303 serverPort.
back().ip =
305 serverPort.
back().port = 0;
306 serverPort.
back().protocol.insert(
"http");
307 auto eps = s->ports(serverPort);
322 onAccept(
Session& session, boost::asio::ip::tcp::endpoint endpoint)
332 boost::asio::ip::tcp::endpoint remote_address)
341 boost::asio::ip::tcp::endpoint remote_address)
359 onClose(
Session& session, boost::system::error_code
const&)
373 for (
int i = 0; i < 1000; ++i)
378 serverPort.
back().ip =
380 serverPort.
back().port = 0;
381 serverPort.
back().protocol.insert(
"http");
382 s->ports(serverPort);
390 testcase(
"Server config - invalid options");
391 using namespace test::jtx;
399 (*cfg).deprecatedClearSection(
"port_rpc");
402 std::make_unique<CaptureLogs>(&messages)};
405 messages.
find(
"Missing 'ip' in [port_rpc]") != std::string::npos);
411 (*cfg).deprecatedClearSection(
"port_rpc");
415 std::make_unique<CaptureLogs>(&messages)};
418 messages.
find(
"Missing 'port' in [port_rpc]") != std::string::npos);
424 (*cfg).deprecatedClearSection(
"port_rpc");
426 (*cfg)[
"port_rpc"].set(
"port",
"0");
429 std::make_unique<CaptureLogs>(&messages)};
432 messages.
find(
"Invalid value '0' for key 'port' in [port_rpc]") ==
439 (*cfg)[
"server"].set(
"port",
"0");
442 std::make_unique<CaptureLogs>(&messages)};
445 messages.
find(
"Invalid value '0' for key 'port' in [server]") !=
452 (*cfg).deprecatedClearSection(
"port_rpc");
454 (*cfg)[
"port_rpc"].set(
"port",
"8081");
455 (*cfg)[
"port_rpc"].set(
"protocol",
"");
458 std::make_unique<CaptureLogs>(&messages)};
461 messages.
find(
"Missing 'protocol' in [port_rpc]") !=
471 cfg = std::make_unique<Config>();
476 cfg->deprecatedClearSection(
478 cfg->legacy(
"database_path",
"");
479 cfg->setupControl(
true,
true,
true);
481 (*cfg)[
"port_peer"].set(
"port",
"8080");
482 (*cfg)[
"port_peer"].set(
"protocol",
"peer");
484 (*cfg)[
"port_rpc"].set(
"port",
"8081");
485 (*cfg)[
"port_rpc"].set(
"protocol",
"http,ws2");
488 (*cfg)[
"port_ws"].set(
"port",
"8082");
489 (*cfg)[
"port_ws"].set(
"protocol",
"ws");
493 std::make_unique<CaptureLogs>(&messages)};
496 messages.
find(
"Required section [server] is missing") !=
505 cfg = std::make_unique<Config>();
510 cfg->deprecatedClearSection(
512 cfg->legacy(
"database_path",
"");
513 cfg->setupControl(
true,
true,
true);
514 (*cfg)[
"server"].append(
"port_peer");
515 (*cfg)[
"server"].append(
"port_rpc");
516 (*cfg)[
"server"].append(
"port_ws");
519 std::make_unique<CaptureLogs>(&messages)};
522 messages.
find(
"Missing section: [port_peer]") != std::string::npos);
Abstraction for the underlying message destination.
virtual Severity threshold() const
Returns the minimum severity level this sink will report.
A generic endpoint for log messages.
log_os< char > log
Logging output stream.
void pass()
Record a successful test condition.
testcase_t testcase
Memberspace for declaring test cases.
bool except(F &&f, String const &reason)
void fail(String const &reason, char const *file, int line)
Record a failure.
Persistent state information for a connection session.
virtual void close(bool graceful)=0
Close the session.
virtual http_request_type & request()=0
Returns the current HTTP request.
void write(std::string const &s)
Send a copy of data asynchronously.
virtual void complete()=0
Indicate that the response is complete.
void writeAlways(beast::severities::Severity level, std::string const &text) override
Bypass filter and write text to the sink at the specified severity.
TestSink(beast::unit_test::suite &suite)
void write(beast::severities::Severity level, std::string const &text) override
Write text to the sink at the specified severity.
beast::unit_test::suite & suite_
boost::asio::io_service & get_io_service()
std::optional< boost::asio::io_service::work > work_
boost::asio::io_service io_service_
bool expect_read(SyncReadStream &s, std::string const &match)
bool connect(Socket &s, typename Socket::endpoint_type const &ep)
bool write(SyncWriteStream &s, std::string const &text)
void test_keepalive(boost::asio::ip::tcp::endpoint const &ep)
void test_request(boost::asio::ip::tcp::endpoint const &ep)
void run() override
Runs the suite.
A transaction testing environment.
bool is_keep_alive(boost::beast::http::message< isRequest, Body, Fields > const &m)
A namespace for easy access to logging severity values.
Severity
Severity level / threshold of a Journal message.
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
boost::beast::tcp_stream socket_type
const char * getEnvLocalhostAddr()
boost::beast::ssl_stream< socket_type > stream_type
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
std::unique_ptr< Server > make_Server(Handler &handler, boost::asio::io_service &io_service, beast::Journal journal)
Create the HTTP server using the specified handler.
static std::string nodeDatabase()
static std::string importNodeDatabase()
Used to indicate the result of a server connection handoff.
void onClose(Session &session, boost::system::error_code const &)
bool onAccept(Session &session, boost::asio::ip::tcp::endpoint endpoint)
Handoff onHandoff(Session &session, std::unique_ptr< stream_type > &&bundle, http_request_type &&request, boost::asio::ip::tcp::endpoint remote_address)
void onWSMessage(std::shared_ptr< WSSession > session, std::vector< boost::asio::const_buffer > const &)
void onRequest(Session &session)
void onStopped(Server &server)
Handoff onHandoff(Session &session, http_request_type &&request, boost::asio::ip::tcp::endpoint remote_address)