mirror of
https://github.com/XRPLF/clio.git
synced 2025-12-06 17:27:58 +00:00
31
unittests/Playground.cpp
Normal file
31
unittests/Playground.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <util/Fixtures.h>
|
||||
|
||||
using namespace clio;
|
||||
|
||||
/*
|
||||
* Use this file for temporary tests and implementations.
|
||||
* Note: Please don't push your temporary work to the repo.
|
||||
*/
|
||||
|
||||
// TEST(PlaygroundTest, MyTest)
|
||||
// {
|
||||
// }
|
||||
245
unittests/rpc/BaseTests.cpp
Normal file
245
unittests/rpc/BaseTests.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <util/Fixtures.h>
|
||||
|
||||
#include <rpc/RPC.h>
|
||||
#include <rpc/common/AnyHandler.h>
|
||||
#include <rpc/common/Specs.h>
|
||||
#include <rpc/common/Validators.h>
|
||||
|
||||
#include <boost/json/parse.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
using namespace testing;
|
||||
using namespace clio;
|
||||
using namespace std;
|
||||
|
||||
using namespace RPCng;
|
||||
using namespace RPCng::validation;
|
||||
|
||||
namespace json = boost::json;
|
||||
|
||||
class RPCBaseTest : public NoLoggerFixture
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(RPCBaseTest, CheckType)
|
||||
{
|
||||
auto const jstr = json::value("a string");
|
||||
ASSERT_TRUE(checkType<string>(jstr));
|
||||
ASSERT_FALSE(checkType<int>(jstr));
|
||||
|
||||
auto const juint = json::value(123u);
|
||||
ASSERT_TRUE(checkType<uint32_t>(juint));
|
||||
ASSERT_TRUE(checkType<int32_t>(juint));
|
||||
ASSERT_FALSE(checkType<bool>(juint));
|
||||
|
||||
auto const jint = json::value(123);
|
||||
ASSERT_TRUE(checkType<int32_t>(jint));
|
||||
ASSERT_TRUE(checkType<uint32_t>(jint));
|
||||
ASSERT_FALSE(checkType<bool>(jint));
|
||||
|
||||
auto const jbool = json::value(true);
|
||||
ASSERT_TRUE(checkType<bool>(jbool));
|
||||
ASSERT_FALSE(checkType<int>(jbool));
|
||||
|
||||
auto const jdouble = json::value(0.123);
|
||||
ASSERT_TRUE(checkType<double>(jdouble));
|
||||
ASSERT_TRUE(checkType<float>(jdouble));
|
||||
ASSERT_FALSE(checkType<bool>(jdouble));
|
||||
|
||||
auto const jarr = json::value({1, 2, 3});
|
||||
ASSERT_TRUE(checkType<json::array>(jarr));
|
||||
ASSERT_FALSE(checkType<int>(jarr));
|
||||
}
|
||||
|
||||
TEST_F(RPCBaseTest, TypeValidator)
|
||||
{
|
||||
auto spec = RpcSpec{
|
||||
{"uint", Type<uint32_t>{}},
|
||||
{"int", Type<int32_t>{}},
|
||||
{"str", Type<string>{}},
|
||||
{"double", Type<double>{}},
|
||||
{"bool", Type<bool>{}},
|
||||
{"arr", Type<json::array>{}},
|
||||
};
|
||||
|
||||
auto passingInput = json::parse(R"({
|
||||
"uint": 123,
|
||||
"int": 321,
|
||||
"str": "a string",
|
||||
"double": 1.0,
|
||||
"bool": true,
|
||||
"arr": []
|
||||
})");
|
||||
ASSERT_TRUE(spec.validate(passingInput));
|
||||
|
||||
{
|
||||
auto failingInput = json::parse(R"({ "uint": "a string" })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
{
|
||||
auto failingInput = json::parse(R"({ "int": "a string" })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
{
|
||||
auto failingInput = json::parse(R"({ "str": 1234 })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
{
|
||||
auto failingInput = json::parse(R"({ "double": "a string" })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
{
|
||||
auto failingInput = json::parse(R"({ "bool": "a string" })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
{
|
||||
auto failingInput = json::parse(R"({ "arr": "a string" })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(RPCBaseTest, TypeValidatorMultipleTypes)
|
||||
{
|
||||
auto spec = RpcSpec{
|
||||
// either int or string
|
||||
{"test", Type<uint32_t, string>{}},
|
||||
};
|
||||
|
||||
auto passingInput = json::parse(R"({ "test": "1234" })");
|
||||
ASSERT_TRUE(spec.validate(passingInput));
|
||||
|
||||
auto passingInput2 = json::parse(R"({ "test": 1234 })");
|
||||
ASSERT_TRUE(spec.validate(passingInput2));
|
||||
|
||||
auto failingInput = json::parse(R"({ "test": true })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
|
||||
TEST_F(RPCBaseTest, RequiredValidator)
|
||||
{
|
||||
auto spec = RpcSpec{
|
||||
{"required", Required{}},
|
||||
};
|
||||
|
||||
auto passingInput = json::parse(R"({ "required": "present" })");
|
||||
ASSERT_TRUE(spec.validate(passingInput));
|
||||
|
||||
auto passingInput2 = json::parse(R"({ "required": true })");
|
||||
ASSERT_TRUE(spec.validate(passingInput2));
|
||||
|
||||
auto failingInput = json::parse(R"({})");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
|
||||
TEST_F(RPCBaseTest, BetweenValidator)
|
||||
{
|
||||
auto spec = RpcSpec{
|
||||
{"amount", Between<uint32_t>{10u, 20u}},
|
||||
};
|
||||
|
||||
auto passingInput = json::parse(R"({ "amount": 15 })");
|
||||
ASSERT_TRUE(spec.validate(passingInput));
|
||||
|
||||
auto passingInput2 = json::parse(R"({ "amount": 10 })");
|
||||
ASSERT_TRUE(spec.validate(passingInput2));
|
||||
|
||||
auto passingInput3 = json::parse(R"({ "amount": 20 })");
|
||||
ASSERT_TRUE(spec.validate(passingInput3));
|
||||
|
||||
auto failingInput = json::parse(R"({ "amount": 9 })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
|
||||
auto failingInput2 = json::parse(R"({ "amount": 21 })");
|
||||
ASSERT_FALSE(spec.validate(failingInput2));
|
||||
}
|
||||
|
||||
TEST_F(RPCBaseTest, OneOfValidator)
|
||||
{
|
||||
auto spec = RpcSpec{
|
||||
{"currency", OneOf{"XRP", "USD"}},
|
||||
};
|
||||
|
||||
auto passingInput = json::parse(R"({ "currency": "XRP" })");
|
||||
ASSERT_TRUE(spec.validate(passingInput));
|
||||
|
||||
auto passingInput2 = json::parse(R"({ "currency": "USD" })");
|
||||
ASSERT_TRUE(spec.validate(passingInput2));
|
||||
|
||||
auto failingInput = json::parse(R"({ "currency": "PRX" })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
|
||||
TEST_F(RPCBaseTest, EqualToValidator)
|
||||
{
|
||||
auto spec = RpcSpec{
|
||||
{"exact", EqualTo{"CaseSensitive"}},
|
||||
};
|
||||
|
||||
auto passingInput = json::parse(R"({ "exact": "CaseSensitive" })");
|
||||
ASSERT_TRUE(spec.validate(passingInput));
|
||||
|
||||
auto failingInput = json::parse(R"({ "exact": "Different" })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
|
||||
TEST_F(RPCBaseTest, ArrayAtValidator)
|
||||
{
|
||||
// clang-format off
|
||||
auto spec = RpcSpec{
|
||||
{"arr", Required{}, Type<json::array>{}, ValidateArrayAt{0, {
|
||||
{"limit", Required{}, Type<uint32_t>{}, Between<uint32_t>{0, 100}},
|
||||
}}},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
auto passingInput = json::parse(R"({ "arr": [{"limit": 42}] })");
|
||||
ASSERT_TRUE(spec.validate(passingInput));
|
||||
|
||||
auto failingInput = json::parse(R"({ "arr": [{"limit": "not int"}] })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
|
||||
TEST_F(RPCBaseTest, CustomValidator)
|
||||
{
|
||||
// clang-format off
|
||||
auto customFormatCheck = CustomValidator{
|
||||
[](json::value const& value, std::string_view key) -> MaybeError {
|
||||
return value.as_string().size() == 34 ?
|
||||
MaybeError{} : Error{RPC::Status{"Uh oh"}};
|
||||
}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
auto spec = RpcSpec{
|
||||
{"taker", customFormatCheck},
|
||||
};
|
||||
|
||||
auto passingInput =
|
||||
json::parse(R"({ "taker": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59" })");
|
||||
ASSERT_TRUE(spec.validate(passingInput));
|
||||
|
||||
auto failingInput = json::parse(R"({ "taker": "wrongformat" })");
|
||||
ASSERT_FALSE(spec.validate(failingInput));
|
||||
}
|
||||
66
unittests/rpc/handlers/DefaultProcessorTests.cpp
Normal file
66
unittests/rpc/handlers/DefaultProcessorTests.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <rpc/handlers/impl/FakesAndMocks.h>
|
||||
#include <util/Fixtures.h>
|
||||
|
||||
#include <rpc/common/impl/Processors.h>
|
||||
|
||||
#include <boost/json/parse.hpp>
|
||||
|
||||
using namespace testing;
|
||||
using namespace std;
|
||||
|
||||
using namespace RPCng;
|
||||
using namespace RPCng::validation;
|
||||
using namespace unittests::detail;
|
||||
|
||||
namespace json = boost::json;
|
||||
|
||||
class RPCDefaultProcessorTest : public NoLoggerFixture
|
||||
{
|
||||
};
|
||||
|
||||
TEST_F(RPCDefaultProcessorTest, ValidInput)
|
||||
{
|
||||
HandlerMock handler;
|
||||
RPCng::detail::DefaultProcessor<HandlerMock> processor;
|
||||
|
||||
auto const input = json::parse(R"({ "something": "works" })");
|
||||
auto const spec = RpcSpec{{"something", Required{}}};
|
||||
auto const data = InOutFake{"works"};
|
||||
EXPECT_CALL(handler, spec()).WillOnce(ReturnRef(spec));
|
||||
EXPECT_CALL(handler, process(Eq(data))).WillOnce(Return(data));
|
||||
|
||||
auto const ret = processor(handler, input);
|
||||
ASSERT_TRUE(ret); // no error
|
||||
}
|
||||
|
||||
TEST_F(RPCDefaultProcessorTest, InvalidInput)
|
||||
{
|
||||
HandlerMock handler;
|
||||
RPCng::detail::DefaultProcessor<HandlerMock> processor;
|
||||
|
||||
auto const input = json::parse(R"({ "other": "nope" })");
|
||||
auto const spec = RpcSpec{{"something", Required{}}};
|
||||
EXPECT_CALL(handler, spec()).WillOnce(ReturnRef(spec));
|
||||
|
||||
auto const ret = processor(handler, input);
|
||||
ASSERT_FALSE(ret); // returns error
|
||||
}
|
||||
84
unittests/rpc/handlers/TestHandlerTests.cpp
Normal file
84
unittests/rpc/handlers/TestHandlerTests.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include <rpc/common/AnyHandler.h>
|
||||
#include <rpc/handlers/impl/FakesAndMocks.h>
|
||||
#include <util/Fixtures.h>
|
||||
|
||||
#include <boost/json/parse.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace RPCng;
|
||||
using namespace RPCng::validation;
|
||||
using namespace unittests::detail;
|
||||
|
||||
namespace json = boost::json;
|
||||
|
||||
class RPCTestHandlerTest : public NoLoggerFixture
|
||||
{
|
||||
};
|
||||
|
||||
// example handler tests
|
||||
TEST_F(RPCTestHandlerTest, HandlerSuccess)
|
||||
{
|
||||
auto const handler = AnyHandler{HandlerFake{}};
|
||||
auto const input = json::parse(R"({
|
||||
"hello": "world",
|
||||
"limit": 10
|
||||
})");
|
||||
|
||||
auto const output = handler.process(input);
|
||||
ASSERT_TRUE(output);
|
||||
|
||||
auto const val = output.value();
|
||||
EXPECT_EQ(val.as_object().at("computed").as_string(), "world_10");
|
||||
}
|
||||
|
||||
TEST_F(RPCTestHandlerTest, HandlerErrorHandling)
|
||||
{
|
||||
auto const handler = AnyHandler{HandlerFake{}};
|
||||
auto const input = json::parse(R"({
|
||||
"hello": "not world",
|
||||
"limit": 10
|
||||
})");
|
||||
|
||||
auto const output = handler.process(input);
|
||||
ASSERT_FALSE(output);
|
||||
|
||||
auto const err = RPC::makeError(output.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "invalidParams");
|
||||
EXPECT_EQ(err.at("error_message").as_string(), "Invalid parameters.");
|
||||
EXPECT_EQ(err.at("error_code").as_uint64(), 31);
|
||||
}
|
||||
|
||||
TEST_F(RPCTestHandlerTest, HandlerInnerErrorHandling)
|
||||
{
|
||||
auto const handler = AnyHandler{FailingHandlerFake{}};
|
||||
auto const input = json::parse(R"({
|
||||
"hello": "world",
|
||||
"limit": 10
|
||||
})");
|
||||
|
||||
// validation succeeds but handler itself returns error
|
||||
auto const output = handler.process(input);
|
||||
ASSERT_FALSE(output);
|
||||
|
||||
auto const err = RPC::makeError(output.error());
|
||||
EXPECT_EQ(err.at("error").as_string(), "Very custom error");
|
||||
}
|
||||
168
unittests/rpc/handlers/impl/FakesAndMocks.h
Normal file
168
unittests/rpc/handlers/impl/FakesAndMocks.h
Normal file
@@ -0,0 +1,168 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of clio: https://github.com/XRPLF/clio
|
||||
Copyright (c) 2023, the clio developers.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rpc/RPC.h>
|
||||
#include <rpc/common/Specs.h>
|
||||
#include <rpc/common/Validators.h>
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/value_from.hpp>
|
||||
#include <boost/json/value_to.hpp>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace unittests::detail {
|
||||
|
||||
// input data for the test handlers below
|
||||
struct TestInput
|
||||
{
|
||||
std::string hello;
|
||||
std::optional<uint32_t> limit;
|
||||
};
|
||||
|
||||
// output data produced by the test handlers below
|
||||
struct TestOutput
|
||||
{
|
||||
std::string computed;
|
||||
};
|
||||
|
||||
// must be implemented as per rpc/common/Concepts.h
|
||||
inline TestInput
|
||||
tag_invoke(boost::json::value_to_tag<TestInput>, boost::json::value const& jv)
|
||||
{
|
||||
std::optional<uint32_t> optLimit;
|
||||
if (jv.as_object().contains("limit"))
|
||||
optLimit = jv.at("limit").as_int64();
|
||||
|
||||
return {jv.as_object().at("hello").as_string().c_str(), optLimit};
|
||||
}
|
||||
|
||||
// must be implemented as per rpc/common/Concepts.h
|
||||
inline void
|
||||
tag_invoke(
|
||||
boost::json::value_from_tag,
|
||||
boost::json::value& jv,
|
||||
TestOutput output)
|
||||
{
|
||||
jv = {{"computed", output.computed}};
|
||||
}
|
||||
|
||||
// example handler
|
||||
class HandlerFake
|
||||
{
|
||||
public:
|
||||
using Input = TestInput;
|
||||
using Output = TestOutput;
|
||||
using Result = RPCng::HandlerReturnType<Output>;
|
||||
|
||||
RPCng::RpcSpecConstRef
|
||||
spec() const
|
||||
{
|
||||
using namespace RPCng::validation;
|
||||
|
||||
// clang-format off
|
||||
static const RPCng::RpcSpec rpcSpec = {
|
||||
{"hello", Required{}, Type<std::string>{}, EqualTo{"world"}},
|
||||
{"limit", Type<uint32_t>{}, Between<uint32_t>{0, 100}} // optional field
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
return rpcSpec;
|
||||
}
|
||||
|
||||
Result
|
||||
process(Input input) const
|
||||
{
|
||||
return Output{
|
||||
input.hello + '_' + std::to_string(input.limit.value_or(0))};
|
||||
}
|
||||
};
|
||||
|
||||
// example handler that returns custom error
|
||||
class FailingHandlerFake
|
||||
{
|
||||
public:
|
||||
using Input = TestInput;
|
||||
using Output = TestOutput;
|
||||
using Result = RPCng::HandlerReturnType<Output>;
|
||||
|
||||
RPCng::RpcSpecConstRef
|
||||
spec() const
|
||||
{
|
||||
using namespace RPCng::validation;
|
||||
|
||||
// clang-format off
|
||||
static const RPCng::RpcSpec rpcSpec = {
|
||||
{"hello", Required{}, Type<std::string>{}, EqualTo{"world"}},
|
||||
{"limit", Type<uint32_t>{}, Between<uint32_t>{0u, 100u}} // optional field
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
return rpcSpec;
|
||||
}
|
||||
|
||||
Result
|
||||
process([[maybe_unused]] Input input) const
|
||||
{
|
||||
// always fail
|
||||
return RPCng::Error{RPC::Status{"Very custom error"}};
|
||||
}
|
||||
};
|
||||
|
||||
struct InOutFake
|
||||
{
|
||||
std::string something;
|
||||
|
||||
// Note: no spaceship comparison possible for std::string
|
||||
friend bool
|
||||
operator==(InOutFake const& lhs, InOutFake const& rhs) = default;
|
||||
};
|
||||
|
||||
// must be implemented as per rpc/common/Concepts.h
|
||||
inline InOutFake
|
||||
tag_invoke(boost::json::value_to_tag<InOutFake>, boost::json::value const& jv)
|
||||
{
|
||||
return {jv.as_object().at("something").as_string().c_str()};
|
||||
}
|
||||
|
||||
// must be implemented as per rpc/common/Concepts.h
|
||||
inline void
|
||||
tag_invoke(
|
||||
boost::json::value_from_tag,
|
||||
boost::json::value& jv,
|
||||
InOutFake output)
|
||||
{
|
||||
jv = {{"something", output.something}};
|
||||
}
|
||||
|
||||
struct HandlerMock
|
||||
{
|
||||
using Input = InOutFake;
|
||||
using Output = InOutFake;
|
||||
using Result = RPCng::HandlerReturnType<Output>;
|
||||
|
||||
MOCK_METHOD(RPCng::RpcSpecConstRef, spec, (), (const));
|
||||
MOCK_METHOD(Result, process, (Input), (const));
|
||||
};
|
||||
|
||||
} // namespace unittests::detail
|
||||
Reference in New Issue
Block a user