1 //===----------- RPCUtilsTest.cpp - Unit tests the Orc RPC utils ----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/RPCUtils.h"
10 #include "QueueChannel.h"
11 #include "gtest/gtest.h"
16 using namespace llvm::orc
;
17 using namespace llvm::orc::rpc
;
26 class RPCTypeName
<RPCFoo
> {
28 static const char* getName() { return "RPCFoo"; }
32 class SerializationTraits
<QueueChannel
, RPCFoo
, RPCFoo
> {
34 static Error
serialize(QueueChannel
&, const RPCFoo
&) {
35 return Error::success();
38 static Error
deserialize(QueueChannel
&, RPCFoo
&) {
39 return Error::success();
43 } // end namespace rpc
44 } // end namespace orc
45 } // end namespace llvm
49 class DummyError
: public ErrorInfo
<DummyError
> {
54 DummyError(uint32_t Val
) : Val(Val
) {}
56 std::error_code
convertToErrorCode() const override
{
57 // Use a nonsense error code - we want to verify that errors
58 // transmitted over the network are replaced with
59 // OrcErrorCode::UnknownErrorCodeFromRemote.
60 return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist
);
63 void log(raw_ostream
&OS
) const override
{
64 OS
<< "Dummy error " << Val
;
67 uint32_t getValue() const { return Val
; }
73 char DummyError::ID
= 0;
75 template <typename ChannelT
>
76 void registerDummyErrorSerialization() {
77 static bool AlreadyRegistered
= false;
78 if (!AlreadyRegistered
) {
79 SerializationTraits
<ChannelT
, Error
>::
80 template registerErrorType
<DummyError
>(
82 [](ChannelT
&C
, const DummyError
&DE
) {
83 return serializeSeq(C
, DE
.getValue());
85 [](ChannelT
&C
, Error
&Err
) -> Error
{
86 ErrorAsOutParameter
EAO(&Err
);
88 if (auto Err
= deserializeSeq(C
, Val
))
90 Err
= make_error
<DummyError
>(Val
);
91 return Error::success();
93 AlreadyRegistered
= true;
102 class SerializationTraits
<QueueChannel
, RPCFoo
, RPCBar
> {
104 static Error
serialize(QueueChannel
&, const RPCBar
&) {
105 return Error::success();
108 static Error
deserialize(QueueChannel
&, RPCBar
&) {
109 return Error::success();
113 } // end namespace rpc
114 } // end namespace orc
115 } // end namespace llvm
117 namespace DummyRPCAPI
{
119 class VoidBool
: public Function
<VoidBool
, void(bool)> {
121 static const char* getName() { return "VoidBool"; }
124 class IntInt
: public Function
<IntInt
, int32_t(int32_t)> {
126 static const char* getName() { return "IntInt"; }
129 class VoidString
: public Function
<VoidString
, void(std::string
)> {
131 static const char* getName() { return "VoidString"; }
135 : public Function
<AllTheTypes
, void(int8_t, uint8_t, int16_t, uint16_t,
136 int32_t, uint32_t, int64_t, uint64_t,
137 bool, std::string
, std::vector
<int>,
138 std::set
<int>, std::map
<int, bool>)> {
140 static const char* getName() { return "AllTheTypes"; }
143 class CustomType
: public Function
<CustomType
, RPCFoo(RPCFoo
)> {
145 static const char* getName() { return "CustomType"; }
148 class ErrorFunc
: public Function
<ErrorFunc
, Error()> {
150 static const char* getName() { return "ErrorFunc"; }
153 class ExpectedFunc
: public Function
<ExpectedFunc
, Expected
<uint32_t>()> {
155 static const char* getName() { return "ExpectedFunc"; }
160 class DummyRPCEndpoint
: public SingleThreadedRPCEndpoint
<QueueChannel
> {
162 DummyRPCEndpoint(QueueChannel
&C
)
163 : SingleThreadedRPCEndpoint(C
, true) {}
167 void freeVoidBool(bool B
) {
170 TEST(DummyRPC
, TestFreeFunctionHandler
) {
171 auto Channels
= createPairedQueueChannels();
172 DummyRPCEndpoint
Server(*Channels
.first
);
173 Server
.addHandler
<DummyRPCAPI::VoidBool
>(freeVoidBool
);
176 TEST(DummyRPC
, TestCallAsyncVoidBool
) {
177 auto Channels
= createPairedQueueChannels();
178 DummyRPCEndpoint
Client(*Channels
.first
);
179 DummyRPCEndpoint
Server(*Channels
.second
);
181 std::thread
ServerThread([&]() {
182 Server
.addHandler
<DummyRPCAPI::VoidBool
>(
185 << "Server void(bool) received unexpected result";
189 // Poke the server to handle the negotiate call.
190 auto Err
= Server
.handleOne();
191 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
195 // Poke the server to handle the VoidBool call.
196 auto Err
= Server
.handleOne();
197 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
202 // Make an async call.
203 auto Err
= Client
.callAsync
<DummyRPCAPI::VoidBool
>(
205 EXPECT_FALSE(!!Err
) << "Async void(bool) response handler failed";
206 return Error::success();
208 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(bool)";
212 // Poke the client to process the result of the void(bool) call.
213 auto Err
= Client
.handleOne();
214 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
219 // The client should have made two calls to send: One implicit call to
220 // negotiate the VoidBool function key, and a second to make the VoidBool
222 EXPECT_EQ(Channels
.first
->SendCalls
, 2U)
223 << "Expected one send call to have been made by client";
225 // The server should have made two calls to send: One to send the response to
226 // the negotiate call, and another to send the response to the VoidBool call.
227 EXPECT_EQ(Channels
.second
->SendCalls
, 2U)
228 << "Expected two send calls to have been made by server";
231 TEST(DummyRPC
, TestCallAsyncIntInt
) {
232 auto Channels
= createPairedQueueChannels();
233 DummyRPCEndpoint
Client(*Channels
.first
);
234 DummyRPCEndpoint
Server(*Channels
.second
);
236 std::thread
ServerThread([&]() {
237 Server
.addHandler
<DummyRPCAPI::IntInt
>(
239 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
244 // Poke the server to handle the negotiate call.
245 auto Err
= Server
.handleOne();
246 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
250 // Poke the server to handle the int(int) call.
251 auto Err
= Server
.handleOne();
252 EXPECT_FALSE(!!Err
) << "Server failed to handle call to int(int)";
257 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
258 [](Expected
<int> Result
) {
259 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
260 EXPECT_EQ(*Result
, 42)
261 << "Async int(int) response handler received incorrect result";
262 return Error::success();
264 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
268 // Poke the client to process the result.
269 auto Err
= Client
.handleOne();
270 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
276 TEST(DummyRPC
, TestAsyncVoidBoolHandler
) {
277 auto Channels
= createPairedQueueChannels();
278 DummyRPCEndpoint
Client(*Channels
.first
);
279 DummyRPCEndpoint
Server(*Channels
.second
);
281 std::thread
ServerThread([&]() {
282 Server
.addAsyncHandler
<DummyRPCAPI::VoidBool
>(
283 [](std::function
<Error(Error
)> SendResult
,
285 EXPECT_EQ(B
, true) << "Server void(bool) receieved unexpected result";
286 cantFail(SendResult(Error::success()));
287 return Error::success();
291 // Poke the server to handle the negotiate call.
292 auto Err
= Server
.handleOne();
293 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
297 // Poke the server to handle the VoidBool call.
298 auto Err
= Server
.handleOne();
299 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
304 auto Err
= Client
.callAsync
<DummyRPCAPI::VoidBool
>(
306 EXPECT_FALSE(!!Result
) << "Async void(bool) response handler failed";
307 return Error::success();
309 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(bool)";
313 // Poke the client to process the result.
314 auto Err
= Client
.handleOne();
315 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
321 TEST(DummyRPC
, TestAsyncIntIntHandler
) {
322 auto Channels
= createPairedQueueChannels();
323 DummyRPCEndpoint
Client(*Channels
.first
);
324 DummyRPCEndpoint
Server(*Channels
.second
);
326 std::thread
ServerThread([&]() {
327 Server
.addAsyncHandler
<DummyRPCAPI::IntInt
>(
328 [](std::function
<Error(Expected
<int32_t>)> SendResult
,
330 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
331 return SendResult(2 * X
);
335 // Poke the server to handle the negotiate call.
336 auto Err
= Server
.handleOne();
337 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
341 // Poke the server to handle the VoidBool call.
342 auto Err
= Server
.handleOne();
343 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
348 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
349 [](Expected
<int> Result
) {
350 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
351 EXPECT_EQ(*Result
, 42)
352 << "Async int(int) response handler received incorrect result";
353 return Error::success();
355 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
359 // Poke the client to process the result.
360 auto Err
= Client
.handleOne();
361 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
367 TEST(DummyRPC
, TestAsyncIntIntHandlerMethod
) {
368 auto Channels
= createPairedQueueChannels();
369 DummyRPCEndpoint
Client(*Channels
.first
);
370 DummyRPCEndpoint
Server(*Channels
.second
);
374 Error
handler(std::function
<Error(Expected
<int32_t>)> SendResult
,
376 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
377 return SendResult(2 * X
);
381 std::thread
ServerThread([&]() {
383 Server
.addAsyncHandler
<DummyRPCAPI::IntInt
>(D
, &Dummy::handler
);
386 // Poke the server to handle the negotiate call.
387 auto Err
= Server
.handleOne();
388 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
392 // Poke the server to handle the VoidBool call.
393 auto Err
= Server
.handleOne();
394 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
399 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
400 [](Expected
<int> Result
) {
401 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
402 EXPECT_EQ(*Result
, 42)
403 << "Async int(int) response handler received incorrect result";
404 return Error::success();
406 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
410 // Poke the client to process the result.
411 auto Err
= Client
.handleOne();
412 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
418 TEST(DummyRPC
, TestCallAsyncVoidString
) {
419 auto Channels
= createPairedQueueChannels();
420 DummyRPCEndpoint
Client(*Channels
.first
);
421 DummyRPCEndpoint
Server(*Channels
.second
);
423 std::thread
ServerThread([&]() {
424 Server
.addHandler
<DummyRPCAPI::VoidString
>(
425 [](const std::string
&S
) {
426 EXPECT_EQ(S
, "hello")
427 << "Server void(std::string) received unexpected result";
430 // Poke the server to handle the negotiate call.
431 for (int I
= 0; I
< 4; ++I
) {
432 auto Err
= Server
.handleOne();
433 EXPECT_FALSE(!!Err
) << "Server failed to handle call";
438 // Make an call using a std::string.
439 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>(std::string("hello"));
440 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(std::string)";
444 // Make an call using a std::string.
445 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>(StringRef("hello"));
446 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(std::string)";
450 // Make an call using a std::string.
451 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>("hello");
452 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(string)";
458 TEST(DummyRPC
, TestSerialization
) {
459 auto Channels
= createPairedQueueChannels();
460 DummyRPCEndpoint
Client(*Channels
.first
);
461 DummyRPCEndpoint
Server(*Channels
.second
);
463 std::thread
ServerThread([&]() {
464 Server
.addHandler
<DummyRPCAPI::AllTheTypes
>([&](int8_t S8
, uint8_t U8
,
465 int16_t S16
, uint16_t U16
,
466 int32_t S32
, uint32_t U32
,
467 int64_t S64
, uint64_t U64
,
468 bool B
, std::string S
,
471 std::map
<int, bool> M
) {
472 EXPECT_EQ(S8
, -101) << "int8_t serialization broken";
473 EXPECT_EQ(U8
, 250) << "uint8_t serialization broken";
474 EXPECT_EQ(S16
, -10000) << "int16_t serialization broken";
475 EXPECT_EQ(U16
, 10000) << "uint16_t serialization broken";
476 EXPECT_EQ(S32
, -1000000000) << "int32_t serialization broken";
477 EXPECT_EQ(U32
, 1000000000ULL) << "uint32_t serialization broken";
478 EXPECT_EQ(S64
, -10000000000) << "int64_t serialization broken";
479 EXPECT_EQ(U64
, 10000000000ULL) << "uint64_t serialization broken";
480 EXPECT_EQ(B
, true) << "bool serialization broken";
481 EXPECT_EQ(S
, "foo") << "std::string serialization broken";
482 EXPECT_EQ(V
, std::vector
<int>({42, 7}))
483 << "std::vector serialization broken";
484 EXPECT_EQ(S2
, std::set
<int>({7, 42})) << "std::set serialization broken";
485 EXPECT_EQ(M
, (std::map
<int, bool>({{7, false}, {42, true}})))
486 << "std::map serialization broken";
487 return Error::success();
491 // Poke the server to handle the negotiate call.
492 auto Err
= Server
.handleOne();
493 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
497 // Poke the server to handle the AllTheTypes call.
498 auto Err
= Server
.handleOne();
499 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
504 // Make an async call.
505 std::vector
<int> V({42, 7});
506 std::set
<int> S({7, 42});
507 std::map
<int, bool> M({{7, false}, {42, true}});
508 auto Err
= Client
.callAsync
<DummyRPCAPI::AllTheTypes
>(
510 EXPECT_FALSE(!!Err
) << "Async AllTheTypes response handler failed";
511 return Error::success();
513 static_cast<int8_t>(-101), static_cast<uint8_t>(250),
514 static_cast<int16_t>(-10000), static_cast<uint16_t>(10000),
515 static_cast<int32_t>(-1000000000), static_cast<uint32_t>(1000000000),
516 static_cast<int64_t>(-10000000000), static_cast<uint64_t>(10000000000),
517 true, std::string("foo"), V
, S
, M
);
518 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for AllTheTypes";
522 // Poke the client to process the result of the AllTheTypes call.
523 auto Err
= Client
.handleOne();
524 EXPECT_FALSE(!!Err
) << "Client failed to handle response from AllTheTypes";
530 TEST(DummyRPC
, TestCustomType
) {
531 auto Channels
= createPairedQueueChannels();
532 DummyRPCEndpoint
Client(*Channels
.first
);
533 DummyRPCEndpoint
Server(*Channels
.second
);
535 std::thread
ServerThread([&]() {
536 Server
.addHandler
<DummyRPCAPI::CustomType
>(
540 // Poke the server to handle the negotiate call.
541 auto Err
= Server
.handleOne();
542 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
546 // Poke the server to handle the CustomType call.
547 auto Err
= Server
.handleOne();
548 EXPECT_FALSE(!!Err
) << "Server failed to handle call to RPCFoo(RPCFoo)";
553 // Make an async call.
554 auto Err
= Client
.callAsync
<DummyRPCAPI::CustomType
>(
555 [](Expected
<RPCFoo
> FOrErr
) {
556 EXPECT_TRUE(!!FOrErr
)
557 << "Async RPCFoo(RPCFoo) response handler failed";
558 return Error::success();
560 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for RPCFoo(RPCFoo)";
564 // Poke the client to process the result of the RPCFoo() call.
565 auto Err
= Client
.handleOne();
567 << "Client failed to handle response from RPCFoo(RPCFoo)";
573 TEST(DummyRPC
, TestWithAltCustomType
) {
574 auto Channels
= createPairedQueueChannels();
575 DummyRPCEndpoint
Client(*Channels
.first
);
576 DummyRPCEndpoint
Server(*Channels
.second
);
578 std::thread
ServerThread([&]() {
579 Server
.addHandler
<DummyRPCAPI::CustomType
>(
583 // Poke the server to handle the negotiate call.
584 auto Err
= Server
.handleOne();
585 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
589 // Poke the server to handle the CustomType call.
590 auto Err
= Server
.handleOne();
591 EXPECT_FALSE(!!Err
) << "Server failed to handle call to RPCFoo(RPCFoo)";
596 // Make an async call.
597 auto Err
= Client
.callAsync
<DummyRPCAPI::CustomType
>(
598 [](Expected
<RPCBar
> FOrErr
) {
599 EXPECT_TRUE(!!FOrErr
)
600 << "Async RPCFoo(RPCFoo) response handler failed";
601 return Error::success();
603 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for RPCFoo(RPCFoo)";
607 // Poke the client to process the result of the RPCFoo() call.
608 auto Err
= Client
.handleOne();
610 << "Client failed to handle response from RPCFoo(RPCFoo)";
616 TEST(DummyRPC
, ReturnErrorSuccess
) {
617 registerDummyErrorSerialization
<QueueChannel
>();
619 auto Channels
= createPairedQueueChannels();
620 DummyRPCEndpoint
Client(*Channels
.first
);
621 DummyRPCEndpoint
Server(*Channels
.second
);
623 std::thread
ServerThread([&]() {
624 Server
.addHandler
<DummyRPCAPI::ErrorFunc
>(
626 return Error::success();
629 // Handle the negotiate plus one call.
630 for (unsigned I
= 0; I
!= 2; ++I
)
631 cantFail(Server
.handleOne());
634 cantFail(Client
.callAsync
<DummyRPCAPI::ErrorFunc
>(
636 EXPECT_FALSE(!!Err
) << "Expected success value";
637 return Error::success();
640 cantFail(Client
.handleOne());
645 TEST(DummyRPC
, ReturnErrorFailure
) {
646 registerDummyErrorSerialization
<QueueChannel
>();
648 auto Channels
= createPairedQueueChannels();
649 DummyRPCEndpoint
Client(*Channels
.first
);
650 DummyRPCEndpoint
Server(*Channels
.second
);
652 std::thread
ServerThread([&]() {
653 Server
.addHandler
<DummyRPCAPI::ErrorFunc
>(
655 return make_error
<DummyError
>(42);
658 // Handle the negotiate plus one call.
659 for (unsigned I
= 0; I
!= 2; ++I
)
660 cantFail(Server
.handleOne());
663 cantFail(Client
.callAsync
<DummyRPCAPI::ErrorFunc
>(
665 EXPECT_TRUE(Err
.isA
<DummyError
>())
666 << "Incorrect error type";
669 [](const DummyError
&DE
) {
670 EXPECT_EQ(DE
.getValue(), 42ULL)
671 << "Incorrect DummyError serialization";
675 cantFail(Client
.handleOne());
680 TEST(DummyRPC
, ReturnExpectedSuccess
) {
681 registerDummyErrorSerialization
<QueueChannel
>();
683 auto Channels
= createPairedQueueChannels();
684 DummyRPCEndpoint
Client(*Channels
.first
);
685 DummyRPCEndpoint
Server(*Channels
.second
);
687 std::thread
ServerThread([&]() {
688 Server
.addHandler
<DummyRPCAPI::ExpectedFunc
>(
693 // Handle the negotiate plus one call.
694 for (unsigned I
= 0; I
!= 2; ++I
)
695 cantFail(Server
.handleOne());
698 cantFail(Client
.callAsync
<DummyRPCAPI::ExpectedFunc
>(
699 [&](Expected
<uint32_t> ValOrErr
) {
700 EXPECT_TRUE(!!ValOrErr
)
701 << "Expected success value";
702 EXPECT_EQ(*ValOrErr
, 42ULL)
703 << "Incorrect Expected<uint32_t> deserialization";
704 return Error::success();
707 cantFail(Client
.handleOne());
712 TEST(DummyRPC
, ReturnExpectedFailure
) {
713 registerDummyErrorSerialization
<QueueChannel
>();
715 auto Channels
= createPairedQueueChannels();
716 DummyRPCEndpoint
Client(*Channels
.first
);
717 DummyRPCEndpoint
Server(*Channels
.second
);
719 std::thread
ServerThread([&]() {
720 Server
.addHandler
<DummyRPCAPI::ExpectedFunc
>(
721 []() -> Expected
<uint32_t> {
722 return make_error
<DummyError
>(7);
725 // Handle the negotiate plus one call.
726 for (unsigned I
= 0; I
!= 2; ++I
)
727 cantFail(Server
.handleOne());
730 cantFail(Client
.callAsync
<DummyRPCAPI::ExpectedFunc
>(
731 [&](Expected
<uint32_t> ValOrErr
) {
732 EXPECT_FALSE(!!ValOrErr
)
733 << "Expected failure value";
734 auto Err
= ValOrErr
.takeError();
735 EXPECT_TRUE(Err
.isA
<DummyError
>())
736 << "Incorrect error type";
739 [](const DummyError
&DE
) {
740 EXPECT_EQ(DE
.getValue(), 7ULL)
741 << "Incorrect DummyError serialization";
745 cantFail(Client
.handleOne());
750 TEST(DummyRPC
, TestParallelCallGroup
) {
751 auto Channels
= createPairedQueueChannels();
752 DummyRPCEndpoint
Client(*Channels
.first
);
753 DummyRPCEndpoint
Server(*Channels
.second
);
755 std::thread
ServerThread([&]() {
756 Server
.addHandler
<DummyRPCAPI::IntInt
>(
761 // Handle the negotiate, plus three calls.
762 for (unsigned I
= 0; I
!= 4; ++I
) {
763 auto Err
= Server
.handleOne();
764 EXPECT_FALSE(!!Err
) << "Server failed to handle call to int(int)";
770 ParallelCallGroup PCG
;
774 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
775 [&A
](Expected
<int> Result
) {
776 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
778 return Error::success();
780 EXPECT_FALSE(!!Err
) << "First parallel call failed for int(int)";
785 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
786 [&B
](Expected
<int> Result
) {
787 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
789 return Error::success();
791 EXPECT_FALSE(!!Err
) << "Second parallel call failed for int(int)";
796 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
797 [&C
](Expected
<int> Result
) {
798 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
800 return Error::success();
802 EXPECT_FALSE(!!Err
) << "Third parallel call failed for int(int)";
805 // Handle the three int(int) results.
806 for (unsigned I
= 0; I
!= 3; ++I
) {
807 auto Err
= Client
.handleOne();
808 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
813 EXPECT_EQ(A
, 2) << "First parallel call returned bogus result";
814 EXPECT_EQ(B
, 4) << "Second parallel call returned bogus result";
815 EXPECT_EQ(C
, 6) << "Third parallel call returned bogus result";
821 TEST(DummyRPC
, TestAPICalls
) {
823 using DummyCalls1
= APICalls
<DummyRPCAPI::VoidBool
, DummyRPCAPI::IntInt
>;
824 using DummyCalls2
= APICalls
<DummyRPCAPI::AllTheTypes
>;
825 using DummyCalls3
= APICalls
<DummyCalls1
, DummyRPCAPI::CustomType
>;
826 using DummyCallsAll
= APICalls
<DummyCalls1
, DummyCalls2
, DummyRPCAPI::CustomType
>;
828 static_assert(DummyCalls1::Contains
<DummyRPCAPI::VoidBool
>::value
,
829 "Contains<Func> template should return true here");
830 static_assert(!DummyCalls1::Contains
<DummyRPCAPI::CustomType
>::value
,
831 "Contains<Func> template should return false here");
833 auto Channels
= createPairedQueueChannels();
834 DummyRPCEndpoint
Client(*Channels
.first
);
835 DummyRPCEndpoint
Server(*Channels
.second
);
837 std::thread
ServerThread(
839 Server
.addHandler
<DummyRPCAPI::VoidBool
>([](bool b
) { });
840 Server
.addHandler
<DummyRPCAPI::IntInt
>([](int x
) { return x
; });
841 Server
.addHandler
<DummyRPCAPI::CustomType
>([](RPCFoo F
) {});
843 for (unsigned I
= 0; I
< 4; ++I
) {
844 auto Err
= Server
.handleOne();
850 auto Err
= DummyCalls1::negotiate(Client
);
851 EXPECT_FALSE(!!Err
) << "DummyCalls1::negotiate failed";
855 auto Err
= DummyCalls3::negotiate(Client
);
856 EXPECT_FALSE(!!Err
) << "DummyCalls3::negotiate failed";
860 auto Err
= DummyCallsAll::negotiate(Client
);
861 EXPECT_TRUE(Err
.isA
<CouldNotNegotiate
>())
862 << "Expected CouldNotNegotiate error for attempted negotiate of "
863 "unsupported function";
864 consumeError(std::move(Err
));
870 TEST(DummyRPC
, TestRemoveHandler
) {
871 auto Channels
= createPairedQueueChannels();
872 DummyRPCEndpoint
Server(*Channels
.second
);
874 Server
.addHandler
<DummyRPCAPI::VoidBool
>(
877 << "Server void(bool) received unexpected result";
880 Server
.removeHandler
<DummyRPCAPI::VoidBool
>();
883 TEST(DummyRPC
, TestClearHandlers
) {
884 auto Channels
= createPairedQueueChannels();
885 DummyRPCEndpoint
Server(*Channels
.second
);
887 Server
.addHandler
<DummyRPCAPI::VoidBool
>(
890 << "Server void(bool) received unexpected result";
893 Server
.clearHandlers();