123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894 |
- //===----------- RPCUtilsTest.cpp - Unit tests the Orc RPC utils ----------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ExecutionEngine/Orc/RPCUtils.h"
- #include "QueueChannel.h"
- #include "gtest/gtest.h"
- #include <queue>
- using namespace llvm;
- using namespace llvm::orc;
- using namespace llvm::orc::rpc;
- class RPCFoo {};
- namespace llvm {
- namespace orc {
- namespace rpc {
- template <>
- class RPCTypeName<RPCFoo> {
- public:
- static const char* getName() { return "RPCFoo"; }
- };
- template <>
- class SerializationTraits<QueueChannel, RPCFoo, RPCFoo> {
- public:
- static Error serialize(QueueChannel&, const RPCFoo&) {
- return Error::success();
- }
- static Error deserialize(QueueChannel&, RPCFoo&) {
- return Error::success();
- }
- };
- } // end namespace rpc
- } // end namespace orc
- } // end namespace llvm
- class RPCBar {};
- class DummyError : public ErrorInfo<DummyError> {
- public:
- static char ID;
- DummyError(uint32_t Val) : Val(Val) {}
- std::error_code convertToErrorCode() const override {
- // Use a nonsense error code - we want to verify that errors
- // transmitted over the network are replaced with
- // OrcErrorCode::UnknownErrorCodeFromRemote.
- return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
- }
- void log(raw_ostream &OS) const override {
- OS << "Dummy error " << Val;
- }
- uint32_t getValue() const { return Val; }
- public:
- uint32_t Val;
- };
- char DummyError::ID = 0;
- template <typename ChannelT>
- void registerDummyErrorSerialization() {
- static bool AlreadyRegistered = false;
- if (!AlreadyRegistered) {
- SerializationTraits<ChannelT, Error>::
- template registerErrorType<DummyError>(
- "DummyError",
- [](ChannelT &C, const DummyError &DE) {
- return serializeSeq(C, DE.getValue());
- },
- [](ChannelT &C, Error &Err) -> Error {
- ErrorAsOutParameter EAO(&Err);
- uint32_t Val;
- if (auto Err = deserializeSeq(C, Val))
- return Err;
- Err = make_error<DummyError>(Val);
- return Error::success();
- });
- AlreadyRegistered = true;
- }
- }
- namespace llvm {
- namespace orc {
- namespace rpc {
- template <>
- class SerializationTraits<QueueChannel, RPCFoo, RPCBar> {
- public:
- static Error serialize(QueueChannel&, const RPCBar&) {
- return Error::success();
- }
- static Error deserialize(QueueChannel&, RPCBar&) {
- return Error::success();
- }
- };
- } // end namespace rpc
- } // end namespace orc
- } // end namespace llvm
- namespace DummyRPCAPI {
- class VoidBool : public Function<VoidBool, void(bool)> {
- public:
- static const char* getName() { return "VoidBool"; }
- };
- class IntInt : public Function<IntInt, int32_t(int32_t)> {
- public:
- static const char* getName() { return "IntInt"; }
- };
- class VoidString : public Function<VoidString, void(std::string)> {
- public:
- static const char* getName() { return "VoidString"; }
- };
- class AllTheTypes
- : public Function<AllTheTypes, void(int8_t, uint8_t, int16_t, uint16_t,
- int32_t, uint32_t, int64_t, uint64_t,
- bool, std::string, std::vector<int>,
- std::set<int>, std::map<int, bool>)> {
- public:
- static const char* getName() { return "AllTheTypes"; }
- };
- class CustomType : public Function<CustomType, RPCFoo(RPCFoo)> {
- public:
- static const char* getName() { return "CustomType"; }
- };
- class ErrorFunc : public Function<ErrorFunc, Error()> {
- public:
- static const char* getName() { return "ErrorFunc"; }
- };
- class ExpectedFunc : public Function<ExpectedFunc, Expected<uint32_t>()> {
- public:
- static const char* getName() { return "ExpectedFunc"; }
- };
- }
- class DummyRPCEndpoint : public SingleThreadedRPCEndpoint<QueueChannel> {
- public:
- DummyRPCEndpoint(QueueChannel &C)
- : SingleThreadedRPCEndpoint(C, true) {}
- };
- void freeVoidBool(bool B) {
- }
- TEST(DummyRPC, TestFreeFunctionHandler) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Server(*Channels.first);
- Server.addHandler<DummyRPCAPI::VoidBool>(freeVoidBool);
- }
- TEST(DummyRPC, TestCallAsyncVoidBool) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::VoidBool>(
- [](bool B) {
- EXPECT_EQ(B, true)
- << "Server void(bool) received unexpected result";
- });
- {
- // Poke the server to handle the negotiate call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
- }
- {
- // Poke the server to handle the VoidBool call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
- }
- });
- {
- // Make an async call.
- auto Err = Client.callAsync<DummyRPCAPI::VoidBool>(
- [](Error Err) {
- EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed";
- return Error::success();
- }, true);
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)";
- }
- {
- // Poke the client to process the result of the void(bool) call.
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
- }
- // The client should have made two calls to send: One implicit call to
- // negotiate the VoidBool function key, and a second to make the VoidBool
- // call.
- EXPECT_EQ(Channels.first->SendCalls, 2U)
- << "Expected one send call to have been made by client";
- // The server should have made two calls to send: One to send the response to
- // the negotiate call, and another to send the response to the VoidBool call.
- EXPECT_EQ(Channels.second->SendCalls, 2U)
- << "Expected two send calls to have been made by server";
- ServerThread.join();
- }
- TEST(DummyRPC, TestCallAsyncIntInt) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::IntInt>(
- [](int X) -> int {
- EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
- return 2 * X;
- });
- {
- // Poke the server to handle the negotiate call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
- }
- {
- // Poke the server to handle the int(int) call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)";
- }
- });
- {
- auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
- [](Expected<int> Result) {
- EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
- EXPECT_EQ(*Result, 42)
- << "Async int(int) response handler received incorrect result";
- return Error::success();
- }, 21);
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
- }
- {
- // Poke the client to process the result.
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestAsyncVoidBoolHandler) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addAsyncHandler<DummyRPCAPI::VoidBool>(
- [](std::function<Error(Error)> SendResult,
- bool B) {
- EXPECT_EQ(B, true) << "Server void(bool) receieved unexpected result";
- cantFail(SendResult(Error::success()));
- return Error::success();
- });
- {
- // Poke the server to handle the negotiate call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
- }
- {
- // Poke the server to handle the VoidBool call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
- }
- });
- {
- auto Err = Client.callAsync<DummyRPCAPI::VoidBool>(
- [](Error Result) {
- EXPECT_FALSE(!!Result) << "Async void(bool) response handler failed";
- return Error::success();
- }, true);
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)";
- }
- {
- // Poke the client to process the result.
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestAsyncIntIntHandler) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addAsyncHandler<DummyRPCAPI::IntInt>(
- [](std::function<Error(Expected<int32_t>)> SendResult,
- int32_t X) {
- EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
- return SendResult(2 * X);
- });
- {
- // Poke the server to handle the negotiate call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
- }
- {
- // Poke the server to handle the VoidBool call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
- }
- });
- {
- auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
- [](Expected<int> Result) {
- EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
- EXPECT_EQ(*Result, 42)
- << "Async int(int) response handler received incorrect result";
- return Error::success();
- }, 21);
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
- }
- {
- // Poke the client to process the result.
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestAsyncIntIntHandlerMethod) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- class Dummy {
- public:
- Error handler(std::function<Error(Expected<int32_t>)> SendResult,
- int32_t X) {
- EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
- return SendResult(2 * X);
- }
- };
- std::thread ServerThread([&]() {
- Dummy D;
- Server.addAsyncHandler<DummyRPCAPI::IntInt>(D, &Dummy::handler);
- {
- // Poke the server to handle the negotiate call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
- }
- {
- // Poke the server to handle the VoidBool call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
- }
- });
- {
- auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
- [](Expected<int> Result) {
- EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
- EXPECT_EQ(*Result, 42)
- << "Async int(int) response handler received incorrect result";
- return Error::success();
- }, 21);
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
- }
- {
- // Poke the client to process the result.
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestCallAsyncVoidString) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::VoidString>(
- [](const std::string &S) {
- EXPECT_EQ(S, "hello")
- << "Server void(std::string) received unexpected result";
- });
- // Poke the server to handle the negotiate call.
- for (int I = 0; I < 4; ++I) {
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call";
- }
- });
- {
- // Make an call using a std::string.
- auto Err = Client.callB<DummyRPCAPI::VoidString>(std::string("hello"));
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(std::string)";
- }
- {
- // Make an call using a std::string.
- auto Err = Client.callB<DummyRPCAPI::VoidString>(StringRef("hello"));
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(std::string)";
- }
- {
- // Make an call using a std::string.
- auto Err = Client.callB<DummyRPCAPI::VoidString>("hello");
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(string)";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestSerialization) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::AllTheTypes>([&](int8_t S8, uint8_t U8,
- int16_t S16, uint16_t U16,
- int32_t S32, uint32_t U32,
- int64_t S64, uint64_t U64,
- bool B, std::string S,
- std::vector<int> V,
- std::set<int> S2,
- std::map<int, bool> M) {
- EXPECT_EQ(S8, -101) << "int8_t serialization broken";
- EXPECT_EQ(U8, 250) << "uint8_t serialization broken";
- EXPECT_EQ(S16, -10000) << "int16_t serialization broken";
- EXPECT_EQ(U16, 10000) << "uint16_t serialization broken";
- EXPECT_EQ(S32, -1000000000) << "int32_t serialization broken";
- EXPECT_EQ(U32, 1000000000ULL) << "uint32_t serialization broken";
- EXPECT_EQ(S64, -10000000000) << "int64_t serialization broken";
- EXPECT_EQ(U64, 10000000000ULL) << "uint64_t serialization broken";
- EXPECT_EQ(B, true) << "bool serialization broken";
- EXPECT_EQ(S, "foo") << "std::string serialization broken";
- EXPECT_EQ(V, std::vector<int>({42, 7}))
- << "std::vector serialization broken";
- EXPECT_EQ(S2, std::set<int>({7, 42})) << "std::set serialization broken";
- EXPECT_EQ(M, (std::map<int, bool>({{7, false}, {42, true}})))
- << "std::map serialization broken";
- return Error::success();
- });
- {
- // Poke the server to handle the negotiate call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
- }
- {
- // Poke the server to handle the AllTheTypes call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
- }
- });
- {
- // Make an async call.
- std::vector<int> V({42, 7});
- std::set<int> S({7, 42});
- std::map<int, bool> M({{7, false}, {42, true}});
- auto Err = Client.callAsync<DummyRPCAPI::AllTheTypes>(
- [](Error Err) {
- EXPECT_FALSE(!!Err) << "Async AllTheTypes response handler failed";
- return Error::success();
- },
- static_cast<int8_t>(-101), static_cast<uint8_t>(250),
- static_cast<int16_t>(-10000), static_cast<uint16_t>(10000),
- static_cast<int32_t>(-1000000000), static_cast<uint32_t>(1000000000),
- static_cast<int64_t>(-10000000000), static_cast<uint64_t>(10000000000),
- true, std::string("foo"), V, S, M);
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for AllTheTypes";
- }
- {
- // Poke the client to process the result of the AllTheTypes call.
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err) << "Client failed to handle response from AllTheTypes";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestCustomType) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::CustomType>(
- [](RPCFoo F) {});
- {
- // Poke the server to handle the negotiate call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
- }
- {
- // Poke the server to handle the CustomType call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to RPCFoo(RPCFoo)";
- }
- });
- {
- // Make an async call.
- auto Err = Client.callAsync<DummyRPCAPI::CustomType>(
- [](Expected<RPCFoo> FOrErr) {
- EXPECT_TRUE(!!FOrErr)
- << "Async RPCFoo(RPCFoo) response handler failed";
- return Error::success();
- }, RPCFoo());
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for RPCFoo(RPCFoo)";
- }
- {
- // Poke the client to process the result of the RPCFoo() call.
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err)
- << "Client failed to handle response from RPCFoo(RPCFoo)";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestWithAltCustomType) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::CustomType>(
- [](RPCBar F) {});
- {
- // Poke the server to handle the negotiate call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
- }
- {
- // Poke the server to handle the CustomType call.
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to RPCFoo(RPCFoo)";
- }
- });
- {
- // Make an async call.
- auto Err = Client.callAsync<DummyRPCAPI::CustomType>(
- [](Expected<RPCBar> FOrErr) {
- EXPECT_TRUE(!!FOrErr)
- << "Async RPCFoo(RPCFoo) response handler failed";
- return Error::success();
- }, RPCBar());
- EXPECT_FALSE(!!Err) << "Client.callAsync failed for RPCFoo(RPCFoo)";
- }
- {
- // Poke the client to process the result of the RPCFoo() call.
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err)
- << "Client failed to handle response from RPCFoo(RPCFoo)";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, ReturnErrorSuccess) {
- registerDummyErrorSerialization<QueueChannel>();
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::ErrorFunc>(
- []() {
- return Error::success();
- });
- // Handle the negotiate plus one call.
- for (unsigned I = 0; I != 2; ++I)
- cantFail(Server.handleOne());
- });
- cantFail(Client.callAsync<DummyRPCAPI::ErrorFunc>(
- [&](Error Err) {
- EXPECT_FALSE(!!Err) << "Expected success value";
- return Error::success();
- }));
- cantFail(Client.handleOne());
- ServerThread.join();
- }
- TEST(DummyRPC, ReturnErrorFailure) {
- registerDummyErrorSerialization<QueueChannel>();
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::ErrorFunc>(
- []() {
- return make_error<DummyError>(42);
- });
- // Handle the negotiate plus one call.
- for (unsigned I = 0; I != 2; ++I)
- cantFail(Server.handleOne());
- });
- cantFail(Client.callAsync<DummyRPCAPI::ErrorFunc>(
- [&](Error Err) {
- EXPECT_TRUE(Err.isA<DummyError>())
- << "Incorrect error type";
- return handleErrors(
- std::move(Err),
- [](const DummyError &DE) {
- EXPECT_EQ(DE.getValue(), 42ULL)
- << "Incorrect DummyError serialization";
- });
- }));
- cantFail(Client.handleOne());
- ServerThread.join();
- }
- TEST(DummyRPC, ReturnExpectedSuccess) {
- registerDummyErrorSerialization<QueueChannel>();
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::ExpectedFunc>(
- []() -> uint32_t {
- return 42;
- });
- // Handle the negotiate plus one call.
- for (unsigned I = 0; I != 2; ++I)
- cantFail(Server.handleOne());
- });
- cantFail(Client.callAsync<DummyRPCAPI::ExpectedFunc>(
- [&](Expected<uint32_t> ValOrErr) {
- EXPECT_TRUE(!!ValOrErr)
- << "Expected success value";
- EXPECT_EQ(*ValOrErr, 42ULL)
- << "Incorrect Expected<uint32_t> deserialization";
- return Error::success();
- }));
- cantFail(Client.handleOne());
- ServerThread.join();
- }
- TEST(DummyRPC, ReturnExpectedFailure) {
- registerDummyErrorSerialization<QueueChannel>();
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::ExpectedFunc>(
- []() -> Expected<uint32_t> {
- return make_error<DummyError>(7);
- });
- // Handle the negotiate plus one call.
- for (unsigned I = 0; I != 2; ++I)
- cantFail(Server.handleOne());
- });
- cantFail(Client.callAsync<DummyRPCAPI::ExpectedFunc>(
- [&](Expected<uint32_t> ValOrErr) {
- EXPECT_FALSE(!!ValOrErr)
- << "Expected failure value";
- auto Err = ValOrErr.takeError();
- EXPECT_TRUE(Err.isA<DummyError>())
- << "Incorrect error type";
- return handleErrors(
- std::move(Err),
- [](const DummyError &DE) {
- EXPECT_EQ(DE.getValue(), 7ULL)
- << "Incorrect DummyError serialization";
- });
- }));
- cantFail(Client.handleOne());
- ServerThread.join();
- }
- TEST(DummyRPC, TestParallelCallGroup) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread([&]() {
- Server.addHandler<DummyRPCAPI::IntInt>(
- [](int X) -> int {
- return 2 * X;
- });
- // Handle the negotiate, plus three calls.
- for (unsigned I = 0; I != 4; ++I) {
- auto Err = Server.handleOne();
- EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)";
- }
- });
- {
- int A, B, C;
- ParallelCallGroup PCG;
- {
- auto Err = PCG.call(
- rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
- [&A](Expected<int> Result) {
- EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
- A = *Result;
- return Error::success();
- }, 1);
- EXPECT_FALSE(!!Err) << "First parallel call failed for int(int)";
- }
- {
- auto Err = PCG.call(
- rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
- [&B](Expected<int> Result) {
- EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
- B = *Result;
- return Error::success();
- }, 2);
- EXPECT_FALSE(!!Err) << "Second parallel call failed for int(int)";
- }
- {
- auto Err = PCG.call(
- rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
- [&C](Expected<int> Result) {
- EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
- C = *Result;
- return Error::success();
- }, 3);
- EXPECT_FALSE(!!Err) << "Third parallel call failed for int(int)";
- }
- // Handle the three int(int) results.
- for (unsigned I = 0; I != 3; ++I) {
- auto Err = Client.handleOne();
- EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
- }
- PCG.wait();
- EXPECT_EQ(A, 2) << "First parallel call returned bogus result";
- EXPECT_EQ(B, 4) << "Second parallel call returned bogus result";
- EXPECT_EQ(C, 6) << "Third parallel call returned bogus result";
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestAPICalls) {
- using DummyCalls1 = APICalls<DummyRPCAPI::VoidBool, DummyRPCAPI::IntInt>;
- using DummyCalls2 = APICalls<DummyRPCAPI::AllTheTypes>;
- using DummyCalls3 = APICalls<DummyCalls1, DummyRPCAPI::CustomType>;
- using DummyCallsAll = APICalls<DummyCalls1, DummyCalls2, DummyRPCAPI::CustomType>;
- static_assert(DummyCalls1::Contains<DummyRPCAPI::VoidBool>::value,
- "Contains<Func> template should return true here");
- static_assert(!DummyCalls1::Contains<DummyRPCAPI::CustomType>::value,
- "Contains<Func> template should return false here");
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Client(*Channels.first);
- DummyRPCEndpoint Server(*Channels.second);
- std::thread ServerThread(
- [&]() {
- Server.addHandler<DummyRPCAPI::VoidBool>([](bool b) { });
- Server.addHandler<DummyRPCAPI::IntInt>([](int x) { return x; });
- Server.addHandler<DummyRPCAPI::CustomType>([](RPCFoo F) {});
- for (unsigned I = 0; I < 4; ++I) {
- auto Err = Server.handleOne();
- (void)!!Err;
- }
- });
- {
- auto Err = DummyCalls1::negotiate(Client);
- EXPECT_FALSE(!!Err) << "DummyCalls1::negotiate failed";
- }
- {
- auto Err = DummyCalls3::negotiate(Client);
- EXPECT_FALSE(!!Err) << "DummyCalls3::negotiate failed";
- }
- {
- auto Err = DummyCallsAll::negotiate(Client);
- EXPECT_TRUE(Err.isA<CouldNotNegotiate>())
- << "Expected CouldNotNegotiate error for attempted negotiate of "
- "unsupported function";
- consumeError(std::move(Err));
- }
- ServerThread.join();
- }
- TEST(DummyRPC, TestRemoveHandler) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Server(*Channels.second);
- Server.addHandler<DummyRPCAPI::VoidBool>(
- [](bool B) {
- EXPECT_EQ(B, true)
- << "Server void(bool) received unexpected result";
- });
- Server.removeHandler<DummyRPCAPI::VoidBool>();
- }
- TEST(DummyRPC, TestClearHandlers) {
- auto Channels = createPairedQueueChannels();
- DummyRPCEndpoint Server(*Channels.second);
- Server.addHandler<DummyRPCAPI::VoidBool>(
- [](bool B) {
- EXPECT_EQ(B, true)
- << "Server void(bool) received unexpected result";
- });
- Server.clearHandlers();
- }
|