1#include <test/jtx/CaptureLogs.h>
2#include <test/jtx/Env.h>
3#include <test/jtx/envconfig.h>
4#include <test/unit_test/SuiteJournal.h>
6#include <xrpld/core/Config.h>
8#include <xrpl/beast/rfc2616.h>
9#include <xrpl/beast/unit_test/suite.h>
10#include <xrpl/beast/utility/Journal.h>
11#include <xrpl/config/Constants.h>
12#include <xrpl/server/Handoff.h>
13#include <xrpl/server/Port.h>
14#include <xrpl/server/Server.h>
15#include <xrpl/server/Session.h>
16#include <xrpl/server/WSSession.h>
17#include <xrpl/server/detail/ServerImpl.h>
19#include <boost/asio/buffer.hpp>
20#include <boost/asio/executor_work_guard.hpp>
21#include <boost/asio/io_context.hpp>
22#include <boost/asio/ip/address.hpp>
23#include <boost/asio/ip/tcp.hpp>
24#include <boost/asio/streambuf.hpp>
25#include <boost/beast/core/tcp_stream.hpp>
26#include <boost/beast/ssl/ssl_stream.hpp>
27#include <boost/system/detail/error_code.hpp>
60 ,
thread_([&]() { this->ioContext_.run(); })
70 boost::asio::io_context&
120 boost::asio::ip::tcp::endpoint remoteAddress)
129 boost::asio::ip::tcp::endpoint remoteAddress)
137 using namespace std::string_view_literals;
138 session.
write(
"Hello, world!\n"sv);
170 template <
class Socket>
172 connect(Socket& s, Socket::endpoint_type
const& ep)
189 template <
class SyncWriteStream>
195 boost::asio::write(s, boost::asio::buffer(text));
207 template <
class SyncReadStream>
211 boost::asio::streambuf b(1000);
214 auto const n = boost::asio::read_until(s, b,
'\n');
215 if (BEAST_EXPECT(n == match.size()))
219 boost::asio::buffer_copy(boost::asio::buffer(&got[0], n), b.data());
220 return BEAST_EXPECT(got == match);
237 boost::asio::io_context ios;
238 using socket = boost::asio::ip::tcp::socket;
247 "Connection: close\r\n"
254 boost::system::error_code ec;
255 s.shutdown(socket::shutdown_both, ec);
263 boost::asio::io_context ios;
264 using socket = boost::asio::ip::tcp::socket;
273 "Connection: Keep-Alive\r\n"
283 "Connection: close\r\n"
290 boost::system::error_code ec;
291 s.shutdown(socket::shutdown_both, ec);
306 serverPort.
back().port = 0;
307 serverPort.
back().protocol.insert(
"http");
308 auto eps = s->ports(serverPort);
323 onAccept(
Session& session, boost::asio::ip::tcp::endpoint endpoint)
333 boost::asio::ip::tcp::endpoint remoteAddress)
342 boost::asio::ip::tcp::endpoint remoteAddress)
360 onClose(
Session& session, boost::system::error_code
const&)
374 for (
int i = 0; i < 1000; ++i)
380 serverPort.
back().port = 0;
381 serverPort.
back().protocol.insert(
"http");
382 s->ports(serverPort);
390 testcase(
"Server config - invalid options");
404 BEAST_EXPECT(messages.contains(
"Missing 'ip' in [port_rpc]"));
416 BEAST_EXPECT(messages.contains(
"Missing 'port' in [port_rpc]"));
429 BEAST_EXPECT(!messages.contains(
"Invalid value '0' for key 'port' in [port_rpc]"));
440 BEAST_EXPECT(messages.contains(
"Invalid value '0' for key 'port' in [server]"));
454 BEAST_EXPECT(messages.contains(
"Missing 'protocol' in [port_rpc]"));
467 cfg->setupControl(
true,
true,
true);
483 BEAST_EXPECT(messages.contains(
"Required section [server] is missing"));
496 cfg->setupControl(
true,
true,
true);
504 BEAST_EXPECT(messages.contains(
"Missing section: [port_peer]"));
Abstraction for the underlying message destination.
virtual Severity threshold() const
Returns the minimum severity level this sink will report.
Sink(Sink const &sink)=default
A generic endpoint for log messages.
bool except(F &&f, String const &reason)
void pass()
Record a successful test condition.
void fail(String const &reason, char const *file, int line)
Record a failure.
TestcaseT testcase
Memberspace for declaring test cases.
Persistent state information for a connection session.
virtual void close(bool graceful)=0
Close the session.
void write(std::string_view s)
Send a copy of data asynchronously.
virtual void complete()=0
Indicate that the response is complete.
virtual http_request_type & request()=0
Returns the current HTTP request.
TestSink(beast::unit_test::Suite &suite)
void writeAlways(beast::Severity level, std::string const &text) override
Bypass filter and write text to the sink at the specified severity.
void write(beast::Severity level, std::string const &text) override
Write text to the sink at the specified severity.
beast::unit_test::Suite & suite_
boost::asio::io_context ioContext_
boost::asio::io_context & getIoContext()
std::optional< boost::asio::executor_work_guard< boost::asio::io_context::executor_type > > work_
bool write(SyncWriteStream &s, std::string const &text)
bool connect(Socket &s, Socket::endpoint_type const &ep)
void testRequest(boost::asio::ip::tcp::endpoint const &ep)
void testKeepalive(boost::asio::ip::tcp::endpoint const &ep)
bool expectRead(SyncReadStream &s, std::string const &match)
void run() override
Runs the suite.
A transaction testing environment.
bool isKeepAlive(boost::beast::http::message< IsRequest, Body, Fields > const &m)
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
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
char const * getEnvLocalhostAddr()
boost::beast::ssl_stream< socket_type > stream_type
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::unique_ptr< Server > makeServer(Handler &handler, boost::asio::io_context &ioContext, beast::Journal journal)
Create the HTTP server using the specified handler.
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Used to indicate the result of a server connection handoff.
static constexpr auto kProtocol
static constexpr auto kAdmin
static constexpr auto kPort
static constexpr auto kType
static constexpr auto kIp
static constexpr auto kPath
static constexpr auto kPortWs
static constexpr auto kImportNodeDatabase
static constexpr auto kServer
static constexpr auto kPortRpc
static constexpr auto kNodeDatabase
static constexpr auto kDatabasePath
static constexpr auto kPortPeer
static void onRequest(Session &session)
void onStopped(Server &server)
static Handoff onHandoff(Session &session, std::unique_ptr< stream_type > const &bundle, http_request_type const &request, boost::asio::ip::tcp::endpoint remoteAddress)
void onClose(Session &session, boost::system::error_code const &)
static bool onAccept(Session &session, boost::asio::ip::tcp::endpoint endpoint)
static Handoff onHandoff(Session &session, http_request_type const &request, boost::asio::ip::tcp::endpoint remoteAddress)
void onWSMessage(std::shared_ptr< WSSession > session, std::vector< boost::asio::const_buffer > const &)