Skip to content

Commit 9fc8846

Browse files
authored
chore: Add relevant changes from develop (#1762)
1 parent d001e35 commit 9fc8846

File tree

7 files changed

+155
-70
lines changed

7 files changed

+155
-70
lines changed

conanfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Clio(ConanFile):
2828
'protobuf/3.21.9',
2929
'grpc/1.50.1',
3030
'openssl/1.1.1u',
31-
'xrpl/2.3.0-rc2',
31+
'xrpl/2.3.0',
3232
'zlib/1.3.1',
3333
'libbacktrace/cci.20210118'
3434
]

src/rpc/common/APIVersion.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,13 @@ static constexpr uint32_t API_VERSION_DEFAULT = 1u;
3434

3535
/**
3636
* @brief Minimum API version supported by this build
37-
*
38-
* Note: Clio does not natively support v1 and only supports v2 or newer.
39-
* However, Clio will forward all v1 requests to rippled for backward compatibility.
4037
*/
4138
static constexpr uint32_t API_VERSION_MIN = 1u;
4239

4340
/**
4441
* @brief Maximum API version supported by this build
4542
*/
46-
static constexpr uint32_t API_VERSION_MAX = 2u;
43+
static constexpr uint32_t API_VERSION_MAX = 3u;
4744

4845
/**
4946
* @brief A baseclass for API version helper

src/web/impl/HttpBase.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@
6060

6161
namespace web::impl {
6262

63+
static auto constexpr HealthCheckHTML = R"html(
64+
<!DOCTYPE html>
65+
<html>
66+
<head><title>Test page for Clio</title></head>
67+
<body><h1>Clio Test</h1><p>This page shows Clio http(s) connectivity is working.</p></body>
68+
</html>
69+
)html";
70+
6371
using tcp = boost::asio::ip::tcp;
6472

6573
/**
@@ -205,6 +213,9 @@ class HttpBase : public ConnectionBase {
205213
if (ec)
206214
return httpFail(ec, "read");
207215

216+
if (req_.method() == http::verb::get and req_.target() == "/health")
217+
return sender_(httpResponse(http::status::ok, "text/html", HealthCheckHTML));
218+
208219
// Update isAdmin property of the connection
209220
ConnectionBase::isAdmin_ = adminVerification_->isAdmin(req_, this->clientIp);
210221

tests/common/util/TestHttpClient.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <boost/beast/http.hpp> // IWYU pragma: keep
3737
#include <boost/beast/http/field.hpp>
3838
#include <boost/beast/http/message.hpp>
39+
#include <boost/beast/http/status.hpp>
3940
#include <boost/beast/http/string_body.hpp>
4041
#include <boost/beast/http/verb.hpp>
4142
#include <boost/beast/http/write.hpp> // IWYU pragma: keep
@@ -58,7 +59,7 @@ using tcp = boost::asio::ip::tcp;
5859

5960
namespace {
6061

61-
std::string
62+
std::pair<boost::beast::http::status, std::string>
6263
syncRequest(
6364
std::string const& host,
6465
std::string const& port,
@@ -96,7 +97,7 @@ syncRequest(
9697
boost::beast::error_code ec;
9798
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
9899

99-
return res.body();
100+
return {res.result(), res.body()};
100101
}
101102

102103
} // namespace
@@ -105,7 +106,7 @@ WebHeader::WebHeader(http::field name, std::string value) : name(name), value(st
105106
{
106107
}
107108

108-
std::string
109+
std::pair<boost::beast::http::status, std::string>
109110
HttpSyncClient::post(
110111
std::string const& host,
111112
std::string const& port,
@@ -116,7 +117,7 @@ HttpSyncClient::post(
116117
return syncRequest(host, port, body, std::move(additionalHeaders), http::verb::post);
117118
}
118119

119-
std::string
120+
std::pair<boost::beast::http::status, std::string>
120121
HttpSyncClient::get(
121122
std::string const& host,
122123
std::string const& port,

tests/common/util/TestHttpClient.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
#include <boost/beast/core/tcp_stream.hpp>
2727
#include <boost/beast/http/field.hpp>
2828
#include <boost/beast/http/message.hpp>
29+
#include <boost/beast/http/status.hpp>
2930
#include <boost/beast/http/string_body.hpp>
3031

3132
#include <chrono>
3233
#include <expected>
3334
#include <optional>
3435
#include <string>
3536
#include <string_view>
37+
#include <utility>
3638
#include <vector>
3739

3840
struct WebHeader {
@@ -43,15 +45,15 @@ struct WebHeader {
4345
};
4446

4547
struct HttpSyncClient {
46-
static std::string
48+
static std::pair<boost::beast::http::status, std::string>
4749
post(
4850
std::string const& host,
4951
std::string const& port,
5052
std::string const& body,
5153
std::vector<WebHeader> additionalHeaders = {}
5254
);
5355

54-
static std::string
56+
static std::pair<boost::beast::http::status, std::string>
5557
get(std::string const& host,
5658
std::string const& port,
5759
std::string const& body,

tests/unit/web/RPCServerHandlerTests.cpp

Lines changed: 90 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,37 @@
1717
//==============================================================================
1818

1919
#include "rpc/Errors.hpp"
20+
#include "rpc/common/APIVersion.hpp"
2021
#include "rpc/common/Types.hpp"
2122
#include "util/AsioContextTestFixture.hpp"
2223
#include "util/MockBackendTestFixture.hpp"
2324
#include "util/MockETLService.hpp"
2425
#include "util/MockPrometheus.hpp"
2526
#include "util/MockRPCEngine.hpp"
27+
#include "util/NameGenerator.hpp"
2628
#include "util/Taggable.hpp"
2729
#include "util/config/Config.hpp"
2830
#include "web/RPCServerHandler.hpp"
2931
#include "web/interface/ConnectionBase.hpp"
3032

3133
#include <boost/beast/http/status.hpp>
3234
#include <boost/json/parse.hpp>
35+
#include <fmt/core.h>
3336
#include <gmock/gmock.h>
3437
#include <gtest/gtest.h>
3538

39+
#include <cstdint>
3640
#include <memory>
3741
#include <stdexcept>
3842
#include <string>
43+
#include <vector>
3944

4045
using namespace web;
4146

42-
constexpr static auto MINSEQ = 10;
43-
constexpr static auto MAXSEQ = 30;
47+
namespace {
48+
49+
constexpr auto MINSEQ = 10;
50+
constexpr auto MAXSEQ = 30;
4451

4552
struct MockWsBase : public web::ConnectionBase {
4653
std::string message;
@@ -466,54 +473,6 @@ TEST_F(WebRPCServerHandlerTest, WsNotReady)
466473
EXPECT_EQ(boost::json::parse(session->message), boost::json::parse(response));
467474
}
468475

469-
TEST_F(WebRPCServerHandlerTest, HTTPInvalidAPIVersion)
470-
{
471-
static auto constexpr request = R"({
472-
"method": "server_info",
473-
"params": [{
474-
"api_version": null
475-
}]
476-
})";
477-
478-
backend->setRange(MINSEQ, MAXSEQ);
479-
480-
static auto constexpr response = "invalid_API_version";
481-
482-
EXPECT_CALL(*rpcEngine, notifyBadSyntax).Times(1);
483-
484-
(*handler)(request, session);
485-
EXPECT_EQ(session->message, response);
486-
EXPECT_EQ(session->lastStatus, boost::beast::http::status::bad_request);
487-
}
488-
489-
TEST_F(WebRPCServerHandlerTest, WSInvalidAPIVersion)
490-
{
491-
session->upgraded = true;
492-
static auto constexpr request = R"({
493-
"method": "server_info",
494-
"api_version": null
495-
})";
496-
497-
backend->setRange(MINSEQ, MAXSEQ);
498-
499-
static auto constexpr response = R"({
500-
"error": "invalid_API_version",
501-
"error_code": 6000,
502-
"error_message": "API version must be an integer",
503-
"status": "error",
504-
"type": "response",
505-
"request": {
506-
"method": "server_info",
507-
"api_version": null
508-
}
509-
})";
510-
511-
EXPECT_CALL(*rpcEngine, notifyBadSyntax).Times(1);
512-
513-
(*handler)(request, session);
514-
EXPECT_EQ(boost::json::parse(session->message), boost::json::parse(response));
515-
}
516-
517476
TEST_F(WebRPCServerHandlerTest, HTTPBadSyntaxWhenRequestSubscribe)
518477
{
519478
static auto constexpr request = R"({"method": "subscribe"})";
@@ -872,3 +831,84 @@ TEST_F(WebRPCServerHandlerTest, WsRequestNotJson)
872831
(*handler)(request, session);
873832
EXPECT_EQ(boost::json::parse(session->message), boost::json::parse(response));
874833
}
834+
835+
struct InvalidAPIVersionTestBundle {
836+
std::string testName;
837+
std::string version;
838+
std::string wsMessage;
839+
};
840+
841+
// parameterized test cases for parameters check
842+
struct WebRPCServerHandlerInvalidAPIVersionParamTest : public WebRPCServerHandlerTest,
843+
public testing::WithParamInterface<InvalidAPIVersionTestBundle> {
844+
};
845+
846+
auto
847+
generateInvalidVersions()
848+
{
849+
return std::vector<InvalidAPIVersionTestBundle>{
850+
{"v0", "0", fmt::format("Requested API version is lower than minimum supported ({})", rpc::API_VERSION_MIN)},
851+
{"v4", "4", fmt::format("Requested API version is higher than maximum supported ({})", rpc::API_VERSION_MAX)},
852+
{"null", "null", "API version must be an integer"},
853+
{"str", "\"bogus\"", "API version must be an integer"},
854+
{"bool", "false", "API version must be an integer"},
855+
{"double", "12.34", "API version must be an integer"},
856+
};
857+
}
858+
859+
INSTANTIATE_TEST_CASE_P(
860+
WebRPCServerHandlerAPIVersionGroup,
861+
WebRPCServerHandlerInvalidAPIVersionParamTest,
862+
testing::ValuesIn(generateInvalidVersions()),
863+
tests::util::NameGenerator
864+
);
865+
866+
TEST_P(WebRPCServerHandlerInvalidAPIVersionParamTest, HTTPInvalidAPIVersion)
867+
{
868+
auto request = fmt::format(
869+
R"({{
870+
"method": "server_info",
871+
"params": [{{
872+
"api_version": {}
873+
}}]
874+
}})",
875+
GetParam().version
876+
);
877+
878+
backend->setRange(MINSEQ, MAXSEQ);
879+
880+
EXPECT_CALL(*rpcEngine, notifyBadSyntax).Times(1);
881+
882+
(*handler)(request, session);
883+
EXPECT_EQ(session->message, "invalid_API_version");
884+
EXPECT_EQ(session->lastStatus, boost::beast::http::status::bad_request);
885+
}
886+
887+
TEST_P(WebRPCServerHandlerInvalidAPIVersionParamTest, WSInvalidAPIVersion)
888+
{
889+
session->upgraded = true;
890+
auto request = fmt::format(
891+
R"({{
892+
"method": "server_info",
893+
"api_version": {}
894+
}})",
895+
GetParam().version
896+
);
897+
898+
backend->setRange(MINSEQ, MAXSEQ);
899+
900+
EXPECT_CALL(*rpcEngine, notifyBadSyntax).Times(1);
901+
902+
(*handler)(request, session);
903+
904+
auto response = boost::json::parse(session->message);
905+
EXPECT_TRUE(response.is_object());
906+
EXPECT_TRUE(response.as_object().contains("error"));
907+
EXPECT_EQ(response.at("error").as_string(), "invalid_API_version");
908+
EXPECT_TRUE(response.as_object().contains("error_message"));
909+
EXPECT_EQ(response.at("error_message").as_string(), GetParam().wsMessage);
910+
EXPECT_TRUE(response.as_object().contains("error_code"));
911+
EXPECT_EQ(response.at("error_code").as_int64(), static_cast<int64_t>(rpc::ClioError::rpcINVALID_API_VERSION));
912+
}
913+
914+
} // namespace

0 commit comments

Comments
 (0)