From 3196ef59c1b350ab5f831cbd166d0ffd3d114aea Mon Sep 17 00:00:00 2001 From: Alex Kremer Date: Wed, 12 Aug 2026 13:47:44 +0100 Subject: [PATCH] Use errors from rpcspec --- src/etl/Errors.hpp | 11 + src/etl/LoadBalancer.cpp | 3 +- src/etl/Source.hpp | 4 +- src/etl/impl/ForwardingSource.cpp | 14 +- src/etl/impl/ForwardingSource.hpp | 4 +- src/etl/impl/SourceImpl.hpp | 6 +- src/rpc/Errors.cpp | 199 ++++++++++-------- src/rpc/Errors.hpp | 218 +------------------- src/web/impl/ErrorHandling.hpp | 6 +- src/web/ng/impl/ErrorHandling.cpp | 6 +- tests/common/util/MockSource.hpp | 6 +- tests/unit/etl/ETLStateTests.cpp | 4 +- tests/unit/etl/ForwardingSourceTests.cpp | 14 +- tests/unit/etl/LoadBalancerTests.cpp | 49 ++--- tests/unit/etl/SourceImplTests.cpp | 3 +- tests/unit/rpc/ErrorTests.cpp | 6 +- tests/unit/rpc/ForwardingProxyTests.cpp | 4 +- tests/unit/rpc/handlers/ServerInfoTests.cpp | 8 +- tests/unit/web/RPCServerHandlerTests.cpp | 20 +- 19 files changed, 216 insertions(+), 369 deletions(-) create mode 100644 src/etl/Errors.hpp diff --git a/src/etl/Errors.hpp b/src/etl/Errors.hpp new file mode 100644 index 000000000..55a360e2d --- /dev/null +++ b/src/etl/Errors.hpp @@ -0,0 +1,11 @@ +/** @file */ +#pragma once + +#include + +namespace etl { + +/** @brief Error codes produced by ETL source operations. Aliased from rpc::EtlError. */ +using EtlError = rpc::EtlError; + +} // namespace etl diff --git a/src/etl/LoadBalancer.cpp b/src/etl/LoadBalancer.cpp index 9bb14b777..f19bc0788 100644 --- a/src/etl/LoadBalancer.cpp +++ b/src/etl/LoadBalancer.cpp @@ -1,6 +1,7 @@ #include "etl/LoadBalancer.hpp" #include "data/BackendInterface.hpp" +#include "etl/Errors.hpp" #include "etl/ETLState.hpp" #include "etl/InitialLoadObserverInterface.hpp" #include "etl/LoadBalancerInterface.hpp" @@ -292,7 +293,7 @@ LoadBalancer::forwardToRippled( auto xUserValue = isAdmin ? kAdminForwardingXUserValue : kUserForwardingXUserValue; std::optional response; - rpc::ClioError error = rpc::ClioError::EtlConnectionError; + etl::EtlError error = etl::EtlError::ConnectionError; while (numAttempts < sources_.size()) { auto [res, duration] = util::timed([&]() { return sources_[sourceIdx]->forwardToRippled(request, clientIp, xUserValue, yield); diff --git a/src/etl/Source.hpp b/src/etl/Source.hpp index ca7acb9b8..58659c0f4 100644 --- a/src/etl/Source.hpp +++ b/src/etl/Source.hpp @@ -4,7 +4,7 @@ #include "etl/LoadBalancerInterface.hpp" #include "etl/NetworkValidatedLedgersInterface.hpp" #include "feed/SubscriptionManagerInterface.hpp" -#include "rpc/Errors.hpp" +#include "etl/Errors.hpp" #include "util/config/ObjectView.hpp" #include @@ -131,7 +131,7 @@ public: * @param yield The coroutine context * @return Response on success or error on failure */ - [[nodiscard]] virtual std::expected + [[nodiscard]] virtual std::expected forwardToRippled( boost::json::object const& request, std::optional const& forwardToRippledClientIp, diff --git a/src/etl/impl/ForwardingSource.cpp b/src/etl/impl/ForwardingSource.cpp index 1ea8512ef..df997507e 100644 --- a/src/etl/impl/ForwardingSource.cpp +++ b/src/etl/impl/ForwardingSource.cpp @@ -1,6 +1,6 @@ #include "etl/impl/ForwardingSource.hpp" -#include "rpc/Errors.hpp" +#include "etl/Errors.hpp" #include "util/log/Logger.hpp" #include @@ -38,7 +38,7 @@ ForwardingSource::ForwardingSource( ); } -std::expected +std::expected ForwardingSource::forwardToRippled( boost::json::object const& request, std::optional const& forwardToRippledClientIp, @@ -58,14 +58,14 @@ ForwardingSource::forwardToRippled( auto expectedConnection = connectionBuilder.connect(yield); if (not expectedConnection) { LOG(log_.debug()) << "Couldn't connect to rippled to forward request."; - return std::unexpected{rpc::ClioError::EtlConnectionError}; + return std::unexpected{EtlError::ConnectionError}; } auto& connection = expectedConnection.value(); auto writeError = connection->write(boost::json::serialize(request), yield, forwardingTimeout_); if (writeError) { LOG(log_.debug()) << "Error sending request to rippled to forward request."; - return std::unexpected{rpc::ClioError::EtlRequestError}; + return std::unexpected{EtlError::RequestError}; } auto response = connection->read(yield, forwardingTimeout_); @@ -73,10 +73,10 @@ ForwardingSource::forwardToRippled( if (auto errorCode = response.error().errorCode(); errorCode.has_value() and errorCode->value() == boost::system::errc::timed_out) { LOG(log_.debug()) << "Request to rippled timed out"; - return std::unexpected{rpc::ClioError::EtlRequestTimeout}; + return std::unexpected{EtlError::RequestTimeout}; } LOG(log_.debug()) << "Error sending request to rippled to forward request."; - return std::unexpected{rpc::ClioError::EtlRequestError}; + return std::unexpected{EtlError::RequestError}; } boost::json::value parsedResponse; @@ -87,7 +87,7 @@ ForwardingSource::forwardToRippled( } catch (std::exception const& e) { LOG(log_.debug()) << "Error parsing response from rippled: " << e.what() << ". Response: " << *response; - return std::unexpected{rpc::ClioError::EtlInvalidResponse}; + return std::unexpected{EtlError::InvalidResponse}; } auto responseObject = parsedResponse.as_object(); diff --git a/src/etl/impl/ForwardingSource.hpp b/src/etl/impl/ForwardingSource.hpp index 3806b9b71..0f7114e68 100644 --- a/src/etl/impl/ForwardingSource.hpp +++ b/src/etl/impl/ForwardingSource.hpp @@ -1,6 +1,6 @@ #pragma once -#include "rpc/Errors.hpp" +#include "etl/Errors.hpp" #include "util/log/Logger.hpp" #include "util/requests/WsConnection.hpp" @@ -39,7 +39,7 @@ public: * @param yield The coroutine context * @return Response on success or error on failure */ - [[nodiscard]] std::expected + [[nodiscard]] std::expected forwardToRippled( boost::json::object const& request, std::optional const& forwardToRippledClientIp, diff --git a/src/etl/impl/SourceImpl.hpp b/src/etl/impl/SourceImpl.hpp index 211c65d11..34d3cc8e6 100644 --- a/src/etl/impl/SourceImpl.hpp +++ b/src/etl/impl/SourceImpl.hpp @@ -6,7 +6,7 @@ #include "etl/impl/ForwardingSource.hpp" #include "etl/impl/GrpcSource.hpp" #include "etl/impl/SubscriptionSource.hpp" -#include "rpc/Errors.hpp" +#include "etl/Errors.hpp" #include #include @@ -208,9 +208,9 @@ public: * @param forwardToRippledClientIp IP of the client forwarding this request if known * @param xUserValue Optional value of the X-User header * @param yield The coroutine context - * @return Response or ClioError + * @return Response or EtlError */ - [[nodiscard]] std::expected + [[nodiscard]] std::expected forwardToRippled( boost::json::object const& request, std::optional const& forwardToRippledClientIp, diff --git a/src/rpc/Errors.cpp b/src/rpc/Errors.cpp index f8ec37cfa..807eb842a 100644 --- a/src/rpc/Errors.cpp +++ b/src/rpc/Errors.cpp @@ -4,10 +4,12 @@ #include "util/OverloadSet.hpp" #include +#include #include #include #include +#include #include #include #include @@ -46,6 +48,16 @@ operator<<(std::ostream& stream, Status const& status) } else { stream << ", Message: " << getErrorInfo(err).message; } + }, + [&stream, &status](EtlError err) { + stream << "Code: " << static_cast>(err); + if (!status.error.empty()) + stream << ", Error: " << status.error; + if (!status.message.empty()) { + stream << ", Message: " << status.message; + } else { + stream << ", Message: " << getEtlErrorInfo(err).message; + } } }, status.code @@ -57,100 +69,111 @@ operator<<(std::ostream& stream, Status const& status) return stream; } -WarningInfo const& -getWarningInfo(WarningCode code) +EtlErrorInfo const& +getEtlErrorInfo(EtlError code) { - static constexpr WarningInfo kInfos[]{ - {WarningCode::WarnUnknown, "Unknown warning"}, - {WarningCode::WarnRpcClio, - "This is a clio server. clio only serves validated data. If you want to talk to rippled, " - "include " - "'ledger_index':'current' in your request"}, - {WarningCode::WarnRpcOutdated, "This server may be out of date"}, - {WarningCode::WarnRpcRateLimit, "You are about to be rate limited"}, - {WarningCode::WarnRpcDeprecated, - "Some fields from your request are deprecated. Please check the documentation at " - "https://xrpl.org/docs/references/http-websocket-apis/ and update your request."} - }; + static constexpr auto kInfos = std::to_array({ + { + .code = EtlError::ConnectionError, + .error = "connectionError", + .message = "Couldn't connect to rippled.", + }, + { + .code = EtlError::RequestError, + .error = "requestError", + .message = "Error sending request to rippled.", + }, + { + .code = EtlError::RequestTimeout, + .error = "timeout", + .message = "Request to rippled timed out.", + }, + { + .code = EtlError::InvalidResponse, + .error = "invalidResponse", + .message = "Rippled returned an invalid response.", + }, + }); - auto matchByCode = [code](auto const& info) { return info.code == code; }; - if (auto it = ranges::find_if(kInfos, matchByCode); it != end(kInfos)) + if (auto it = ranges::find(kInfos, code, &EtlErrorInfo::code); it != end(kInfos)) return *it; - throw(out_of_range("Invalid WarningCode")); -} - -boost::json::object -makeWarning(WarningCode code) -{ - auto json = boost::json::object{}; - auto const& info = getWarningInfo(code); - json["id"] = static_cast(code); - json["message"] = info.message; - return json; + throw(out_of_range("Invalid EtlError code")); } ClioErrorInfo const& getErrorInfo(ClioError code) { - static constexpr ClioErrorInfo kInfos[]{ - {.code = ClioError::RpcMalformedCurrency, - .error = "malformedCurrency", - .message = "Malformed currency."}, - {.code = ClioError::RpcMalformedRequest, - .error = "malformedRequest", - .message = "Malformed request."}, - {.code = ClioError::RpcMalformedOwner, - .error = "malformedOwner", - .message = "Malformed owner."}, - {.code = ClioError::RpcMalformedAddress, - .error = "malformedAddress", - .message = "Malformed address."}, - {.code = ClioError::RpcUnknownOption, - .error = "unknownOption", - .message = "Unknown option."}, - {.code = ClioError::RpcFieldNotFoundTransaction, - .error = "fieldNotFoundTransaction", - .message = "Missing field."}, - {.code = ClioError::RpcMalformedOracleDocumentId, - .error = "malformedDocumentID", - .message = "Malformed oracle_document_id."}, - {.code = ClioError::RpcMalformedAuthorizedCredentials, - .error = "malformedAuthorizedCredentials", - .message = "Malformed authorized credentials."}, + static constexpr auto kInfos = std::to_array({ + { + .code = ClioError::RpcMalformedCurrency, + .error = "malformedCurrency", + .message = "Malformed currency.", + }, + { + .code = ClioError::RpcMalformedRequest, + .error = "malformedRequest", + .message = "Malformed request.", + }, + { + .code = ClioError::RpcMalformedOwner, + .error = "malformedOwner", + .message = "Malformed owner.", + }, + { + .code = ClioError::RpcMalformedAddress, + .error = "malformedAddress", + .message = "Malformed address.", + }, + { + .code = ClioError::RpcUnknownOption, + .error = "unknownOption", + .message = "Unknown option.", + }, + { + .code = ClioError::RpcFieldNotFoundTransaction, + .error = "fieldNotFoundTransaction", + .message = "Missing field.", + }, + { + .code = ClioError::RpcMalformedOracleDocumentId, + .error = "malformedDocumentID", + .message = "Malformed oracle_document_id.", + }, + { + .code = ClioError::RpcMalformedAuthorizedCredentials, + .error = "malformedAuthorizedCredentials", + .message = "Malformed authorized credentials.", + }, // special system errors - {.code = ClioError::RpcInvalidApiVersion, - .error = JS(invalid_API_version), - .message = "Invalid API version."}, - {.code = ClioError::RpcCommandIsMissing, - .error = JS(missingCommand), - .message = "Method is not specified or is not a string."}, - {.code = ClioError::RpcCommandNotString, - .error = "commandNotString", - .message = "Method is not a string."}, - {.code = ClioError::RpcCommandIsEmpty, - .error = "emptyCommand", - .message = "Method is an empty string."}, - {.code = ClioError::RpcParamsUnparsable, - .error = "paramsUnparsable", - .message = "Params must be an array holding exactly one object."}, - // etl related errors - {.code = ClioError::EtlConnectionError, - .error = "connectionError", - .message = "Couldn't connect to rippled."}, - {.code = ClioError::EtlRequestError, - .error = "requestError", - .message = "Error sending request to rippled."}, - {.code = ClioError::EtlRequestTimeout, - .error = "timeout", - .message = "Request to rippled timed out."}, - {.code = ClioError::EtlInvalidResponse, - .error = "invalidResponse", - .message = "Rippled returned an invalid response."} - }; + { + .code = ClioError::RpcInvalidApiVersion, + .error = JS(invalid_API_version), + .message = "Invalid API version.", + }, + { + .code = ClioError::RpcCommandIsMissing, + .error = JS(missingCommand), + .message = "Method is not specified or is not a string.", + }, + { + .code = ClioError::RpcCommandNotString, + .error = "commandNotString", + .message = "Method is not a string.", + }, + { + .code = ClioError::RpcCommandIsEmpty, + .error = "emptyCommand", + .message = "Method is an empty string.", + }, + { + .code = ClioError::RpcParamsUnparsable, + .error = "paramsUnparsable", + .message = "Params must be an array holding exactly one object.", + }, + }); - auto matchByCode = [code](auto const& info) { return info.code == code; }; - if (auto it = ranges::find_if(kInfos, matchByCode); it != end(kInfos)) + if (auto it = ranges::find(kInfos, code, &ClioErrorInfo::code); it != end(kInfos)) return *it; throw(out_of_range("Invalid error code")); @@ -215,6 +238,16 @@ makeError(Status const& status) [&status, &wrapOptional](ClioError err) { return makeError(err, wrapOptional(status.error), wrapOptional(status.message)); }, + [](EtlError err) { + auto const& info = getEtlErrorInfo(err); + return boost::json::object{ + {"error", info.error}, + {"error_code", static_cast(err)}, + {"error_message", info.message}, + {"status", "error"}, + {"type", "response"} + }; + }, }, status.code ); diff --git a/src/rpc/Errors.hpp b/src/rpc/Errors.hpp index 5b06c365a..d05e3f05c 100644 --- a/src/rpc/Errors.hpp +++ b/src/rpc/Errors.hpp @@ -2,49 +2,16 @@ #pragma once #include -#include +#include #include #include #include #include #include -#include namespace rpc { -/** - * @brief Custom clio RPC Errors. - */ -enum class ClioError { - // normal clio errors start with 5000 - RpcMalformedCurrency = 5000, - RpcMalformedRequest = 5001, - RpcMalformedOwner = 5002, - RpcMalformedAddress = 5003, - RpcUnknownOption = 5005, - RpcFieldNotFoundTransaction = 5006, - RpcMalformedOracleDocumentId = 5007, - RpcMalformedAuthorizedCredentials = 5008, - // NOTE: RpcEntryNotFound is replaced with RippledError::RpcEntryNotFound - // RpcEntryNotFound = 5009, - - // special system errors start with 6000 - RpcInvalidApiVersion = 6000, - RpcCommandIsMissing = 6001, - RpcCommandNotString = 6002, - RpcCommandIsEmpty = 6003, - RpcParamsUnparsable = 6004, - - // TODO: Since it is not only rpc errors here now, we should move it to util - // etl related errors start with 7000 - // Higher value in this errors means better progress in the forwarding - EtlConnectionError = 7000, - EtlRequestError = 7001, - EtlRequestTimeout = 7002, - EtlInvalidResponse = 7003, -}; - /** * @brief Holds info about a particular @ref ClioError. */ @@ -55,166 +22,12 @@ struct ClioErrorInfo { }; /** - * @brief Clio uses compatible Rippled error codes for most RPC errors. + * @brief Holds info about a particular @ref rpc::EtlError. */ -using RippledError = xrpl::ErrorCodeI; - -/** - * @brief Clio operates on a combination of Rippled and Custom Clio error codes. - * - * @see RippledError For rippled error codes - * @see ClioError For custom clio error codes - */ -using CombinedError = std::variant; - -/** - * @brief A status returned from any RPC handler. - */ -struct Status { - CombinedError code = RippledError::RpcSuccess; - std::string error; - std::string message; - std::optional extraInfo; - - Status() = default; - - /** - * @brief Construct a new Status object - * - * @param code The error code - */ - /* implicit */ Status(CombinedError code) : code(code) {}; - - /** - * @brief Construct a new Status object - * - * @param code The error code - * @param extraInfo The extra info - */ - Status(CombinedError code, boost::json::object&& extraInfo) - : code(code), extraInfo(std::move(extraInfo)) {}; - - /** - * @brief Construct a new Status object with a custom message - * - * @note HACK. Some rippled handlers explicitly specify errors. This means that we have to be - * able to duplicate this functionality. - * - * @param message The message - */ - explicit Status(std::string message) : code(xrpl::RpcUnknown), message(std::move(message)) - { - } - - /** - * @brief Construct a new Status object - * - * @param code The error code - * @param message The message - */ - Status(CombinedError code, std::string message) : code(code), message(std::move(message)) - { - } - - /** - * @brief Construct a new Status object - * - * @param code The error code - * @param error The error - * @param message The message - */ - Status(CombinedError code, std::string error, std::string message) - : code(code), error(std::move(error)), message(std::move(message)) - { - } - - bool - operator==(Status const& other) const = default; - - /** - * @brief Check if the status is not OK - * - * @return true if the status is not OK; false otherwise - */ - operator bool() const - { - if (auto err = std::get_if(&code)) - return *err != RippledError::RpcSuccess; - - return true; - } - - /** - * @brief Returns true if the @ref rpc::Status contains the desired @ref rpc::RippledError - * - * @param other The @ref rpc::RippledError to match - * @return true if status matches given error; false otherwise - */ - bool - operator==(RippledError other) const - { - if (auto err = std::get_if(&code)) - return *err == other; - - return false; - } - - /** - * @brief Returns true if the Status contains the desired @ref ClioError - * - * @param other The RippledError to match - * @return true if status matches given error; false otherwise - */ - bool - operator==(ClioError other) const - { - if (auto err = std::get_if(&code)) - return *err == other; - - return false; - } - - /** - * @brief Custom output stream for Status - * - * @param stream The output stream - * @param status The Status - * @return The same ostream we were given - */ - friend std::ostream& - operator<<(std::ostream& stream, Status const& status); -}; - -/** - * @brief Warning codes that can be returned by clio. - */ -// NOLINTNEXTLINE(cppcoreguidelines-use-enum-class) -enum WarningCode { - WarnUnknown = -1, - WarnRpcClio = 2001, - WarnRpcOutdated = 2002, - WarnRpcRateLimit = 2003, - WarnRpcDeprecated = 2004 -}; - -/** - * @brief Holds information about a clio warning. - */ -struct WarningInfo { - constexpr WarningInfo() = default; - - /** - * @brief Construct a new Warning Info object - * - * @param code The warning code - * @param message The warning message - */ - constexpr WarningInfo(WarningCode code, char const* message) : code(code), message(message) - { - } - - WarningCode code = WarningCode::WarnUnknown; - std::string_view const message = "unknown warning"; +struct EtlErrorInfo { + EtlError const code; + std::string_view const error; + std::string_view const message; }; /** @@ -278,15 +91,6 @@ public: */ static Status gOk; -/** - * @brief Get the warning info object from a warning code. - * - * @param code The warning code - * @return A reference to the static warning info - */ -WarningInfo const& -getWarningInfo(WarningCode code); - /** * @brief Get the error info object from an clio-specific error code. * @@ -297,13 +101,13 @@ ClioErrorInfo const& getErrorInfo(ClioError code); /** - * @brief Generate JSON from a @ref rpc::WarningCode. + * @brief Get the ETL error info object from an ETL error code. * - * @param code The warning code - * @return The JSON output + * @param code The error code + * @return A reference to the static error info */ -boost::json::object -makeWarning(WarningCode code); +EtlErrorInfo const& +getEtlErrorInfo(EtlError code); /** * @brief Generate JSON from a @ref rpc::Status. diff --git a/src/web/impl/ErrorHandling.hpp b/src/web/impl/ErrorHandling.hpp index 2f631b448..fbc1b765c 100644 --- a/src/web/impl/ErrorHandling.hpp +++ b/src/web/impl/ErrorHandling.hpp @@ -80,15 +80,13 @@ public: case rpc::ClioError::RpcFieldNotFoundTransaction: case rpc::ClioError::RpcMalformedOracleDocumentId: case rpc::ClioError::RpcMalformedAuthorizedCredentials: - case rpc::ClioError::EtlConnectionError: - case rpc::ClioError::EtlRequestError: - case rpc::ClioError::EtlRequestTimeout: - case rpc::ClioError::EtlInvalidResponse: ASSERT( false, "Unknown rpc error code {}", static_cast(*clioCode) ); // this should never happen break; } + } else if (std::get_if(&err.code) != nullptr) { + ASSERT(false, "ETL error should not reach HTTP error handler"); // this should never happen } else { connection_->send( boost::json::serialize(composeError(err)), diff --git a/src/web/ng/impl/ErrorHandling.cpp b/src/web/ng/impl/ErrorHandling.cpp index c86ce259a..d8a964811 100644 --- a/src/web/ng/impl/ErrorHandling.cpp +++ b/src/web/ng/impl/ErrorHandling.cpp @@ -92,15 +92,13 @@ ErrorHelper::makeError(rpc::Status const& err) const case rpc::ClioError::RpcFieldNotFoundTransaction: case rpc::ClioError::RpcMalformedOracleDocumentId: case rpc::ClioError::RpcMalformedAuthorizedCredentials: - case rpc::ClioError::EtlConnectionError: - case rpc::ClioError::EtlRequestError: - case rpc::ClioError::EtlRequestTimeout: - case rpc::ClioError::EtlInvalidResponse: ASSERT( false, "Unknown rpc error code {}", static_cast(*clioCode) ); // this should never happen break; } + } else if (std::get_if(&err.code) != nullptr) { + ASSERT(false, "ETL error should not reach HTTP error handler"); // this should never happen } return Response{http::status::bad_request, composeError(err), rawRequest_}; diff --git a/tests/common/util/MockSource.hpp b/tests/common/util/MockSource.hpp index fbc4c4bbc..ce15e75ed 100644 --- a/tests/common/util/MockSource.hpp +++ b/tests/common/util/MockSource.hpp @@ -5,7 +5,7 @@ #include "etl/NetworkValidatedLedgersInterface.hpp" #include "etl/Source.hpp" #include "feed/SubscriptionManagerInterface.hpp" -#include "rpc/Errors.hpp" +#include "etl/Errors.hpp" #include "util/config/ObjectView.hpp" #include @@ -50,7 +50,7 @@ struct MockSource : etl::SourceBase { (override) ); - using ForwardToRippledReturnType = std::expected; + using ForwardToRippledReturnType = std::expected; MOCK_METHOD( ForwardToRippledReturnType, forwardToRippled, @@ -132,7 +132,7 @@ public: return mock_->loadInitialLedger(sequence, maxLedger, observer); } - [[nodiscard]] std::expected + [[nodiscard]] std::expected forwardToRippled( boost::json::object const& request, std::optional const& forwardToRippledClientIp, diff --git a/tests/unit/etl/ETLStateTests.cpp b/tests/unit/etl/ETLStateTests.cpp index 3db5702f6..e5641b17c 100644 --- a/tests/unit/etl/ETLStateTests.cpp +++ b/tests/unit/etl/ETLStateTests.cpp @@ -1,5 +1,5 @@ #include "etl/ETLState.hpp" -#include "rpc/Errors.hpp" +#include "etl/Errors.hpp" #include "util/MockSource.hpp" #include @@ -18,7 +18,7 @@ struct ETLStateTest : public virtual ::testing::Test { TEST_F(ETLStateTest, Error) { EXPECT_CALL(source, forwardToRippled) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse})); + .WillOnce(Return(std::unexpected{etl::EtlError::InvalidResponse})); auto const state = etl::ETLState::fetchETLStateFromSource(source); EXPECT_FALSE(state); } diff --git a/tests/unit/etl/ForwardingSourceTests.cpp b/tests/unit/etl/ForwardingSourceTests.cpp index f85d7ba93..40ba3efde 100644 --- a/tests/unit/etl/ForwardingSourceTests.cpp +++ b/tests/unit/etl/ForwardingSourceTests.cpp @@ -1,5 +1,5 @@ #include "etl/impl/ForwardingSource.hpp" -#include "rpc/Errors.hpp" +#include "etl/Errors.hpp" #include "util/AsioContextTestFixture.hpp" #include "util/Spawn.hpp" #include "util/TestWsServer.hpp" @@ -35,7 +35,7 @@ TEST_F(ForwardingSourceTests, ConnectionFailed) runSpawn([&](boost::asio::yield_context yield) { auto result = forwardingSource_.forwardToRippled({}, {}, {}, yield); ASSERT_FALSE(result); - EXPECT_EQ(result.error(), rpc::ClioError::EtlConnectionError); + EXPECT_EQ(result.error(), etl::EtlError::ConnectionError); }); } @@ -79,7 +79,7 @@ TEST_F(ForwardingSourceOperationsTests, XUserHeader) boost::json::parse(message_).as_object(), {}, xUserValue, yield ); ASSERT_FALSE(result); - EXPECT_EQ(result.error(), rpc::ClioError::EtlRequestError); + EXPECT_EQ(result.error(), etl::EtlError::RequestError); }); } @@ -95,7 +95,7 @@ TEST_F(ForwardingSourceOperationsTests, ReadFailed) boost::json::parse(message_).as_object(), {}, {}, yield ); ASSERT_FALSE(result); - EXPECT_EQ(result.error(), rpc::ClioError::EtlRequestError); + EXPECT_EQ(result.error(), etl::EtlError::RequestError); }); } @@ -111,7 +111,7 @@ TEST_F(ForwardingSourceOperationsTests, ReadTimeout) boost::json::parse(message_).as_object(), {}, {}, yield ); ASSERT_FALSE(result); - EXPECT_EQ(result.error(), rpc::ClioError::EtlRequestTimeout); + EXPECT_EQ(result.error(), etl::EtlError::RequestTimeout); }); } @@ -136,7 +136,7 @@ TEST_F(ForwardingSourceOperationsTests, ParseFailed) boost::json::parse(message_).as_object(), {}, {}, yield ); ASSERT_FALSE(result); - EXPECT_EQ(result.error(), rpc::ClioError::EtlInvalidResponse); + EXPECT_EQ(result.error(), etl::EtlError::InvalidResponse); }); } @@ -162,7 +162,7 @@ TEST_F(ForwardingSourceOperationsTests, GotNotAnObject) boost::json::parse(message_).as_object(), {}, {}, yield ); ASSERT_FALSE(result); - EXPECT_EQ(result.error(), rpc::ClioError::EtlInvalidResponse); + EXPECT_EQ(result.error(), etl::EtlError::InvalidResponse); }); } diff --git a/tests/unit/etl/LoadBalancerTests.cpp b/tests/unit/etl/LoadBalancerTests.cpp index 243c27616..b383c4a71 100644 --- a/tests/unit/etl/LoadBalancerTests.cpp +++ b/tests/unit/etl/LoadBalancerTests.cpp @@ -3,6 +3,7 @@ #include "etl/LoadBalancerInterface.hpp" #include "etl/Models.hpp" #include "etl/Source.hpp" +#include "etl/Errors.hpp" #include "rpc/Errors.hpp" #include "util/AsioContextTestFixture.hpp" #include "util/MockBackendTestFixture.hpp" @@ -203,9 +204,9 @@ TEST_F(LoadBalancerConstructorTests, fetchETLState_AllSourcesFail) { EXPECT_CALL(sourceFactory_, makeSource).Times(2); EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError})); + .WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError})); EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError})); + .WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError})); EXPECT_THROW({ makeLoadBalancer(); }, std::logic_error); } @@ -225,7 +226,7 @@ TEST_F(LoadBalancerConstructorTests, fetchETLState_Source1Fails0OK) EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled) .WillOnce(Return(boost::json::object{})); EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError})); + .WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError})); EXPECT_CALL(sourceFactory_.sourceAt(0), run); EXPECT_CALL(sourceFactory_.sourceAt(1), run); makeLoadBalancer(); @@ -235,7 +236,7 @@ TEST_F(LoadBalancerConstructorTests, fetchETLState_Source0Fails1OK) { EXPECT_CALL(sourceFactory_, makeSource).Times(2); EXPECT_CALL(sourceFactory_.sourceAt(0), forwardToRippled) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError})); + .WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError})); EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled) .WillOnce(Return(boost::json::object{})); EXPECT_CALL(sourceFactory_.sourceAt(0), run); @@ -265,7 +266,7 @@ TEST_F(LoadBalancerConstructorTests, fetchETLState_AllSourcesFailButAllowNoEtlIs .WillOnce(Return(boost::json::object{})); EXPECT_CALL(sourceFactory_.sourceAt(0), run); EXPECT_CALL(sourceFactory_.sourceAt(1), forwardToRippled) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError})); + .WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError})); EXPECT_CALL(sourceFactory_.sourceAt(1), run); configJson_.as_object()["allow_no_etl"] = true; @@ -716,7 +717,7 @@ TEST_F(LoadBalancerForwardToRippledTests, source0Fails) sourceFactory_.sourceAt(0), forwardToRippled(request_, clientIP_, LoadBalancer::kUserForwardingXUserValue, testing::_) ) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError})); + .WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError})); EXPECT_CALL( sourceFactory_.sourceAt(1), forwardToRippled(request_, clientIP_, LoadBalancer::kUserForwardingXUserValue, testing::_) @@ -819,7 +820,7 @@ TEST_F(LoadBalancerForwardToRippledPrometheusTests, source0Fails) sourceFactory_.sourceAt(0), forwardToRippled(request_, clientIP_, LoadBalancer::kUserForwardingXUserValue, testing::_) ) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlConnectionError})); + .WillOnce(Return(std::unexpected{etl::EtlError::ConnectionError})); EXPECT_CALL( sourceFactory_.sourceAt(1), forwardToRippled(request_, clientIP_, LoadBalancer::kUserForwardingXUserValue, testing::_) @@ -861,8 +862,8 @@ TEST_F(LoadBalancerForwardToRippledPrometheusTests, adminRequestAlwaysCacheMiss) struct LoadBalancerForwardToRippledErrorTestBundle { std::string testName; - rpc::ClioError firstSourceError; - rpc::ClioError secondSourceError; + etl::EtlError firstSourceError; + etl::EtlError secondSourceError; rpc::CombinedError responseExpectedError; }; @@ -876,33 +877,33 @@ INSTANTIATE_TEST_SUITE_P( testing::Values( LoadBalancerForwardToRippledErrorTestBundle{ "ConnectionError_RequestError", - rpc::ClioError::EtlConnectionError, - rpc::ClioError::EtlRequestError, - rpc::ClioError::EtlRequestError + etl::EtlError::ConnectionError, + etl::EtlError::RequestError, + etl::EtlError::RequestError }, LoadBalancerForwardToRippledErrorTestBundle{ "RequestError_RequestTimeout", - rpc::ClioError::EtlRequestError, - rpc::ClioError::EtlRequestTimeout, - rpc::ClioError::EtlRequestTimeout + etl::EtlError::RequestError, + etl::EtlError::RequestTimeout, + etl::EtlError::RequestTimeout }, LoadBalancerForwardToRippledErrorTestBundle{ "RequestTimeout_InvalidResponse", - rpc::ClioError::EtlRequestTimeout, - rpc::ClioError::EtlInvalidResponse, - rpc::ClioError::EtlInvalidResponse + etl::EtlError::RequestTimeout, + etl::EtlError::InvalidResponse, + etl::EtlError::InvalidResponse }, LoadBalancerForwardToRippledErrorTestBundle{ "BothRequestTimeout", - rpc::ClioError::EtlRequestTimeout, - rpc::ClioError::EtlRequestTimeout, - rpc::ClioError::EtlRequestTimeout + etl::EtlError::RequestTimeout, + etl::EtlError::RequestTimeout, + etl::EtlError::RequestTimeout }, LoadBalancerForwardToRippledErrorTestBundle{ "InvalidResponse_RequestError", - rpc::ClioError::EtlInvalidResponse, - rpc::ClioError::EtlRequestError, - rpc::ClioError::EtlInvalidResponse + etl::EtlError::InvalidResponse, + etl::EtlError::RequestError, + etl::EtlError::InvalidResponse } ), tests::util::kNameGenerator diff --git a/tests/unit/etl/SourceImplTests.cpp b/tests/unit/etl/SourceImplTests.cpp index f644b2bad..c250a9253 100644 --- a/tests/unit/etl/SourceImplTests.cpp +++ b/tests/unit/etl/SourceImplTests.cpp @@ -2,6 +2,7 @@ #include "etl/LoadBalancerInterface.hpp" #include "etl/Models.hpp" #include "etl/impl/SourceImpl.hpp" +#include "etl/Errors.hpp" #include "rpc/Errors.hpp" #include "util/Spawn.hpp" @@ -62,7 +63,7 @@ struct ForwardingSourceMock { (std::string const&, std::string const&, std::chrono::steady_clock::duration) ); - using ForwardToRippledReturnType = std::expected; + using ForwardToRippledReturnType = std::expected; using ClientIpOpt = std::optional; MOCK_METHOD( ForwardToRippledReturnType, diff --git a/tests/unit/rpc/ErrorTests.cpp b/tests/unit/rpc/ErrorTests.cpp index 2f7866254..207d17787 100644 --- a/tests/unit/rpc/ErrorTests.cpp +++ b/tests/unit/rpc/ErrorTests.cpp @@ -150,7 +150,7 @@ INSTANTIATE_TEST_SUITE_P( "Clio", WarningCode::WarnRpcClio, "This is a clio server. clio only serves validated data. If you want to talk to " - "rippled, include " + "xrpld, include " "'ledger_index':'current' in your request" }, WarningCodeTestBundle{ @@ -234,7 +234,7 @@ INSTANTIATE_TEST_SUITE_P( }, StatusStreamTestBundle{ .testName = "StatusWithCodeAndExtraInfo", - .status = Status{ClioError::EtlConnectionError, boost::json::object{}}, + .status = Status{EtlError::ConnectionError, boost::json::object{}}, .expectedOutput = "Code: 7000, Message: Couldn't connect to rippled., Extra Info: {}" }, StatusStreamTestBundle{ @@ -256,7 +256,7 @@ INSTANTIATE_TEST_SUITE_P( .testName = "StatusWithCodeErrorMessage", .status = Status{ - ClioError::EtlInvalidResponse, + EtlError::InvalidResponse, "invalidResponse", "Rippled returned an invalid response." }, diff --git a/tests/unit/rpc/ForwardingProxyTests.cpp b/tests/unit/rpc/ForwardingProxyTests.cpp index 396bfb5eb..8f8e255ac 100644 --- a/tests/unit/rpc/ForwardingProxyTests.cpp +++ b/tests/unit/rpc/ForwardingProxyTests.cpp @@ -338,7 +338,7 @@ TEST_F(RPCForwardingProxyTest, ForwardingFailYieldsErrorStatus) *rawBalancerPtr, forwardToRippled(forwarded.as_object(), std::make_optional(kClientIp), true, _) ) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse})); + .WillOnce(Return(std::unexpected{rpc::EtlError::InvalidResponse})); EXPECT_CALL(*rawHandlerProviderPtr, contains(method)).WillOnce(Return(true)); @@ -360,6 +360,6 @@ TEST_F(RPCForwardingProxyTest, ForwardingFailYieldsErrorStatus) auto const res = proxy_.forward(ctx); EXPECT_FALSE(res.response.has_value()); - EXPECT_EQ(res.response.error(), rpc::ClioError::EtlInvalidResponse); + EXPECT_EQ(res.response.error(), rpc::EtlError::InvalidResponse); }); } diff --git a/tests/unit/rpc/handlers/ServerInfoTests.cpp b/tests/unit/rpc/handlers/ServerInfoTests.cpp index c1e7cbdfc..0a37ba802 100644 --- a/tests/unit/rpc/handlers/ServerInfoTests.cpp +++ b/tests/unit/rpc/handlers/ServerInfoTests.cpp @@ -177,7 +177,7 @@ TEST_F(RPCServerInfoHandlerTest, DefaultOutputIsPresent) EXPECT_CALL( *rawBalancerPtr, forwardToRippled(testing::_, testing::Eq(kClientIp), false, testing::_) ) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse})); + .WillOnce(Return(std::unexpected{rpc::EtlError::InvalidResponse})); EXPECT_CALL(*rawCountersPtr, uptime).WillOnce(Return(std::chrono::seconds{1234})); @@ -220,7 +220,7 @@ TEST_F(RPCServerInfoHandlerTest, AmendmentBlockedIsPresentIfSet) EXPECT_CALL( *rawBalancerPtr, forwardToRippled(testing::_, testing::Eq(kClientIp), false, testing::_) ) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse})); + .WillOnce(Return(std::unexpected{rpc::EtlError::InvalidResponse})); EXPECT_CALL(*rawCountersPtr, uptime).WillOnce(Return(std::chrono::seconds{1234})); @@ -261,7 +261,7 @@ TEST_F(RPCServerInfoHandlerTest, CorruptionDetectedIsPresentIfSet) EXPECT_CALL( *rawBalancerPtr, forwardToRippled(testing::_, testing::Eq(kClientIp), false, testing::_) ) - .WillOnce(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse})); + .WillOnce(Return(std::unexpected{rpc::EtlError::InvalidResponse})); EXPECT_CALL(*rawCountersPtr, uptime).WillOnce(Return(std::chrono::seconds{1234})); @@ -302,7 +302,7 @@ TEST_F(RPCServerInfoHandlerTest, CacheReportsEnabledFlagCorrectly) *rawBalancerPtr, forwardToRippled(testing::_, testing::Eq(kClientIp), false, testing::_) ) .Times(2) - .WillRepeatedly(Return(std::unexpected{rpc::ClioError::EtlInvalidResponse})); + .WillRepeatedly(Return(std::unexpected{rpc::EtlError::InvalidResponse})); EXPECT_CALL(*rawCountersPtr, uptime) .Times(2) diff --git a/tests/unit/web/RPCServerHandlerTests.cpp b/tests/unit/web/RPCServerHandlerTests.cpp index 4b5fb0fdd..13d12c4f8 100644 --- a/tests/unit/web/RPCServerHandlerTests.cpp +++ b/tests/unit/web/RPCServerHandlerTests.cpp @@ -122,7 +122,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPDefaultPath) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" } ] })JSON"; @@ -190,7 +190,7 @@ TEST_F(WebRPCServerHandlerTest, WsNormalPath) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" } ] })JSON"; @@ -265,7 +265,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPForwardedPath) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" } ] })JSON"; @@ -314,7 +314,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPForwardedErrorPath) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" } ] })JSON"; @@ -361,7 +361,7 @@ TEST_F(WebRPCServerHandlerTest, WsForwardedPath) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" } ] })JSON"; @@ -412,7 +412,7 @@ TEST_F(WebRPCServerHandlerTest, WsForwardedErrorPath) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" } ] })JSON"; @@ -453,7 +453,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPErrorPath) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" } ] })JSON"; @@ -510,7 +510,7 @@ TEST_F(WebRPCServerHandlerTest, WsErrorPath) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" } ] })JSON"; @@ -860,7 +860,7 @@ TEST_F(WebRPCServerHandlerTest, HTTPOutDated) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" }, { "id": 2002, @@ -903,7 +903,7 @@ TEST_F(WebRPCServerHandlerTest, WsOutdated) "warnings": [ { "id": 2001, - "message": "This is a clio server. clio only serves validated data. If you want to talk to rippled, include 'ledger_index':'current' in your request" + "message": "This is a clio server. clio only serves validated data. If you want to talk to xrpld, include 'ledger_index':'current' in your request" }, { "id": 2002,