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)";
220 TEST(DummyRPC
, TestCallAsyncIntInt
) {
221 auto Channels
= createPairedQueueChannels();
222 DummyRPCEndpoint
Client(*Channels
.first
);
223 DummyRPCEndpoint
Server(*Channels
.second
);
225 std::thread
ServerThread([&]() {
226 Server
.addHandler
<DummyRPCAPI::IntInt
>(
228 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
233 // Poke the server to handle the negotiate call.
234 auto Err
= Server
.handleOne();
235 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
239 // Poke the server to handle the int(int) call.
240 auto Err
= Server
.handleOne();
241 EXPECT_FALSE(!!Err
) << "Server failed to handle call to int(int)";
246 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
247 [](Expected
<int> Result
) {
248 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
249 EXPECT_EQ(*Result
, 42)
250 << "Async int(int) response handler received incorrect result";
251 return Error::success();
253 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
257 // Poke the client to process the result.
258 auto Err
= Client
.handleOne();
259 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
265 TEST(DummyRPC
, TestAsyncVoidBoolHandler
) {
266 auto Channels
= createPairedQueueChannels();
267 DummyRPCEndpoint
Client(*Channels
.first
);
268 DummyRPCEndpoint
Server(*Channels
.second
);
270 std::thread
ServerThread([&]() {
271 Server
.addAsyncHandler
<DummyRPCAPI::VoidBool
>(
272 [](std::function
<Error(Error
)> SendResult
,
274 EXPECT_EQ(B
, true) << "Server void(bool) receieved unexpected result";
275 cantFail(SendResult(Error::success()));
276 return Error::success();
280 // Poke the server to handle the negotiate call.
281 auto Err
= Server
.handleOne();
282 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
286 // Poke the server to handle the VoidBool call.
287 auto Err
= Server
.handleOne();
288 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
293 auto Err
= Client
.callAsync
<DummyRPCAPI::VoidBool
>(
295 EXPECT_FALSE(!!Result
) << "Async void(bool) response handler failed";
296 return Error::success();
298 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(bool)";
302 // Poke the client to process the result.
303 auto Err
= Client
.handleOne();
304 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
310 TEST(DummyRPC
, TestAsyncIntIntHandler
) {
311 auto Channels
= createPairedQueueChannels();
312 DummyRPCEndpoint
Client(*Channels
.first
);
313 DummyRPCEndpoint
Server(*Channels
.second
);
315 std::thread
ServerThread([&]() {
316 Server
.addAsyncHandler
<DummyRPCAPI::IntInt
>(
317 [](std::function
<Error(Expected
<int32_t>)> SendResult
,
319 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
320 return SendResult(2 * X
);
324 // Poke the server to handle the negotiate call.
325 auto Err
= Server
.handleOne();
326 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
330 // Poke the server to handle the VoidBool call.
331 auto Err
= Server
.handleOne();
332 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
337 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
338 [](Expected
<int> Result
) {
339 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
340 EXPECT_EQ(*Result
, 42)
341 << "Async int(int) response handler received incorrect result";
342 return Error::success();
344 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
348 // Poke the client to process the result.
349 auto Err
= Client
.handleOne();
350 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
356 TEST(DummyRPC
, TestAsyncIntIntHandlerMethod
) {
357 auto Channels
= createPairedQueueChannels();
358 DummyRPCEndpoint
Client(*Channels
.first
);
359 DummyRPCEndpoint
Server(*Channels
.second
);
363 Error
handler(std::function
<Error(Expected
<int32_t>)> SendResult
,
365 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
366 return SendResult(2 * X
);
370 std::thread
ServerThread([&]() {
372 Server
.addAsyncHandler
<DummyRPCAPI::IntInt
>(D
, &Dummy::handler
);
375 // Poke the server to handle the negotiate call.
376 auto Err
= Server
.handleOne();
377 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
381 // Poke the server to handle the VoidBool call.
382 auto Err
= Server
.handleOne();
383 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
388 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
389 [](Expected
<int> Result
) {
390 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
391 EXPECT_EQ(*Result
, 42)
392 << "Async int(int) response handler received incorrect result";
393 return Error::success();
395 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
399 // Poke the client to process the result.
400 auto Err
= Client
.handleOne();
401 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
407 TEST(DummyRPC
, TestCallAsyncVoidString
) {
408 auto Channels
= createPairedQueueChannels();
409 DummyRPCEndpoint
Client(*Channels
.first
);
410 DummyRPCEndpoint
Server(*Channels
.second
);
412 std::thread
ServerThread([&]() {
413 Server
.addHandler
<DummyRPCAPI::VoidString
>(
414 [](const std::string
&S
) {
415 EXPECT_EQ(S
, "hello")
416 << "Server void(std::string) received unexpected result";
419 // Poke the server to handle the negotiate call.
420 for (int I
= 0; I
< 4; ++I
) {
421 auto Err
= Server
.handleOne();
422 EXPECT_FALSE(!!Err
) << "Server failed to handle call";
427 // Make an call using a std::string.
428 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>(std::string("hello"));
429 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(std::string)";
433 // Make an call using a std::string.
434 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>(StringRef("hello"));
435 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(std::string)";
439 // Make an call using a std::string.
440 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>("hello");
441 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(string)";
447 TEST(DummyRPC
, TestSerialization
) {
448 auto Channels
= createPairedQueueChannels();
449 DummyRPCEndpoint
Client(*Channels
.first
);
450 DummyRPCEndpoint
Server(*Channels
.second
);
452 std::thread
ServerThread([&]() {
453 Server
.addHandler
<DummyRPCAPI::AllTheTypes
>([&](int8_t S8
, uint8_t U8
,
454 int16_t S16
, uint16_t U16
,
455 int32_t S32
, uint32_t U32
,
456 int64_t S64
, uint64_t U64
,
457 bool B
, std::string S
,
460 std::map
<int, bool> M
) {
461 EXPECT_EQ(S8
, -101) << "int8_t serialization broken";
462 EXPECT_EQ(U8
, 250) << "uint8_t serialization broken";
463 EXPECT_EQ(S16
, -10000) << "int16_t serialization broken";
464 EXPECT_EQ(U16
, 10000) << "uint16_t serialization broken";
465 EXPECT_EQ(S32
, -1000000000) << "int32_t serialization broken";
466 EXPECT_EQ(U32
, 1000000000ULL) << "uint32_t serialization broken";
467 EXPECT_EQ(S64
, -10000000000) << "int64_t serialization broken";
468 EXPECT_EQ(U64
, 10000000000ULL) << "uint64_t serialization broken";
469 EXPECT_EQ(B
, true) << "bool serialization broken";
470 EXPECT_EQ(S
, "foo") << "std::string serialization broken";
471 EXPECT_EQ(V
, std::vector
<int>({42, 7}))
472 << "std::vector serialization broken";
473 EXPECT_EQ(S2
, std::set
<int>({7, 42})) << "std::set serialization broken";
474 EXPECT_EQ(M
, (std::map
<int, bool>({{7, false}, {42, true}})))
475 << "std::map serialization broken";
476 return Error::success();
480 // Poke the server to handle the negotiate call.
481 auto Err
= Server
.handleOne();
482 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
486 // Poke the server to handle the AllTheTypes call.
487 auto Err
= Server
.handleOne();
488 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
493 // Make an async call.
494 std::vector
<int> V({42, 7});
495 std::set
<int> S({7, 42});
496 std::map
<int, bool> M({{7, false}, {42, true}});
497 auto Err
= Client
.callAsync
<DummyRPCAPI::AllTheTypes
>(
499 EXPECT_FALSE(!!Err
) << "Async AllTheTypes response handler failed";
500 return Error::success();
502 static_cast<int8_t>(-101), static_cast<uint8_t>(250),
503 static_cast<int16_t>(-10000), static_cast<uint16_t>(10000),
504 static_cast<int32_t>(-1000000000), static_cast<uint32_t>(1000000000),
505 static_cast<int64_t>(-10000000000), static_cast<uint64_t>(10000000000),
506 true, std::string("foo"), V
, S
, M
);
507 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for AllTheTypes";
511 // Poke the client to process the result of the AllTheTypes call.
512 auto Err
= Client
.handleOne();
513 EXPECT_FALSE(!!Err
) << "Client failed to handle response from AllTheTypes";
519 TEST(DummyRPC
, TestCustomType
) {
520 auto Channels
= createPairedQueueChannels();
521 DummyRPCEndpoint
Client(*Channels
.first
);
522 DummyRPCEndpoint
Server(*Channels
.second
);
524 std::thread
ServerThread([&]() {
525 Server
.addHandler
<DummyRPCAPI::CustomType
>(
529 // Poke the server to handle the negotiate call.
530 auto Err
= Server
.handleOne();
531 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
535 // Poke the server to handle the CustomType call.
536 auto Err
= Server
.handleOne();
537 EXPECT_FALSE(!!Err
) << "Server failed to handle call to RPCFoo(RPCFoo)";
542 // Make an async call.
543 auto Err
= Client
.callAsync
<DummyRPCAPI::CustomType
>(
544 [](Expected
<RPCFoo
> FOrErr
) {
545 EXPECT_TRUE(!!FOrErr
)
546 << "Async RPCFoo(RPCFoo) response handler failed";
547 return Error::success();
549 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for RPCFoo(RPCFoo)";
553 // Poke the client to process the result of the RPCFoo() call.
554 auto Err
= Client
.handleOne();
556 << "Client failed to handle response from RPCFoo(RPCFoo)";
562 TEST(DummyRPC
, TestWithAltCustomType
) {
563 auto Channels
= createPairedQueueChannels();
564 DummyRPCEndpoint
Client(*Channels
.first
);
565 DummyRPCEndpoint
Server(*Channels
.second
);
567 std::thread
ServerThread([&]() {
568 Server
.addHandler
<DummyRPCAPI::CustomType
>(
572 // Poke the server to handle the negotiate call.
573 auto Err
= Server
.handleOne();
574 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
578 // Poke the server to handle the CustomType call.
579 auto Err
= Server
.handleOne();
580 EXPECT_FALSE(!!Err
) << "Server failed to handle call to RPCFoo(RPCFoo)";
585 // Make an async call.
586 auto Err
= Client
.callAsync
<DummyRPCAPI::CustomType
>(
587 [](Expected
<RPCBar
> FOrErr
) {
588 EXPECT_TRUE(!!FOrErr
)
589 << "Async RPCFoo(RPCFoo) response handler failed";
590 return Error::success();
592 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for RPCFoo(RPCFoo)";
596 // Poke the client to process the result of the RPCFoo() call.
597 auto Err
= Client
.handleOne();
599 << "Client failed to handle response from RPCFoo(RPCFoo)";
605 TEST(DummyRPC
, ReturnErrorSuccess
) {
606 registerDummyErrorSerialization
<QueueChannel
>();
608 auto Channels
= createPairedQueueChannels();
609 DummyRPCEndpoint
Client(*Channels
.first
);
610 DummyRPCEndpoint
Server(*Channels
.second
);
612 std::thread
ServerThread([&]() {
613 Server
.addHandler
<DummyRPCAPI::ErrorFunc
>(
615 return Error::success();
618 // Handle the negotiate plus one call.
619 for (unsigned I
= 0; I
!= 2; ++I
)
620 cantFail(Server
.handleOne());
623 cantFail(Client
.callAsync
<DummyRPCAPI::ErrorFunc
>(
625 EXPECT_FALSE(!!Err
) << "Expected success value";
626 return Error::success();
629 cantFail(Client
.handleOne());
634 TEST(DummyRPC
, ReturnErrorFailure
) {
635 registerDummyErrorSerialization
<QueueChannel
>();
637 auto Channels
= createPairedQueueChannels();
638 DummyRPCEndpoint
Client(*Channels
.first
);
639 DummyRPCEndpoint
Server(*Channels
.second
);
641 std::thread
ServerThread([&]() {
642 Server
.addHandler
<DummyRPCAPI::ErrorFunc
>(
644 return make_error
<DummyError
>(42);
647 // Handle the negotiate plus one call.
648 for (unsigned I
= 0; I
!= 2; ++I
)
649 cantFail(Server
.handleOne());
652 cantFail(Client
.callAsync
<DummyRPCAPI::ErrorFunc
>(
654 EXPECT_TRUE(Err
.isA
<DummyError
>())
655 << "Incorrect error type";
658 [](const DummyError
&DE
) {
659 EXPECT_EQ(DE
.getValue(), 42ULL)
660 << "Incorrect DummyError serialization";
664 cantFail(Client
.handleOne());
669 TEST(DummyRPC
, ReturnExpectedSuccess
) {
670 registerDummyErrorSerialization
<QueueChannel
>();
672 auto Channels
= createPairedQueueChannels();
673 DummyRPCEndpoint
Client(*Channels
.first
);
674 DummyRPCEndpoint
Server(*Channels
.second
);
676 std::thread
ServerThread([&]() {
677 Server
.addHandler
<DummyRPCAPI::ExpectedFunc
>(
682 // Handle the negotiate plus one call.
683 for (unsigned I
= 0; I
!= 2; ++I
)
684 cantFail(Server
.handleOne());
687 cantFail(Client
.callAsync
<DummyRPCAPI::ExpectedFunc
>(
688 [&](Expected
<uint32_t> ValOrErr
) {
689 EXPECT_TRUE(!!ValOrErr
)
690 << "Expected success value";
691 EXPECT_EQ(*ValOrErr
, 42ULL)
692 << "Incorrect Expected<uint32_t> deserialization";
693 return Error::success();
696 cantFail(Client
.handleOne());
701 TEST(DummyRPC
, ReturnExpectedFailure
) {
702 registerDummyErrorSerialization
<QueueChannel
>();
704 auto Channels
= createPairedQueueChannels();
705 DummyRPCEndpoint
Client(*Channels
.first
);
706 DummyRPCEndpoint
Server(*Channels
.second
);
708 std::thread
ServerThread([&]() {
709 Server
.addHandler
<DummyRPCAPI::ExpectedFunc
>(
710 []() -> Expected
<uint32_t> {
711 return make_error
<DummyError
>(7);
714 // Handle the negotiate plus one call.
715 for (unsigned I
= 0; I
!= 2; ++I
)
716 cantFail(Server
.handleOne());
719 cantFail(Client
.callAsync
<DummyRPCAPI::ExpectedFunc
>(
720 [&](Expected
<uint32_t> ValOrErr
) {
721 EXPECT_FALSE(!!ValOrErr
)
722 << "Expected failure value";
723 auto Err
= ValOrErr
.takeError();
724 EXPECT_TRUE(Err
.isA
<DummyError
>())
725 << "Incorrect error type";
728 [](const DummyError
&DE
) {
729 EXPECT_EQ(DE
.getValue(), 7ULL)
730 << "Incorrect DummyError serialization";
734 cantFail(Client
.handleOne());
739 TEST(DummyRPC
, TestParallelCallGroup
) {
740 auto Channels
= createPairedQueueChannels();
741 DummyRPCEndpoint
Client(*Channels
.first
);
742 DummyRPCEndpoint
Server(*Channels
.second
);
744 std::thread
ServerThread([&]() {
745 Server
.addHandler
<DummyRPCAPI::IntInt
>(
750 // Handle the negotiate, plus three calls.
751 for (unsigned I
= 0; I
!= 4; ++I
) {
752 auto Err
= Server
.handleOne();
753 EXPECT_FALSE(!!Err
) << "Server failed to handle call to int(int)";
759 ParallelCallGroup PCG
;
763 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
764 [&A
](Expected
<int> Result
) {
765 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
767 return Error::success();
769 EXPECT_FALSE(!!Err
) << "First parallel call failed for int(int)";
774 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
775 [&B
](Expected
<int> Result
) {
776 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
778 return Error::success();
780 EXPECT_FALSE(!!Err
) << "Second parallel call failed for int(int)";
785 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
786 [&C
](Expected
<int> Result
) {
787 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
789 return Error::success();
791 EXPECT_FALSE(!!Err
) << "Third parallel call failed for int(int)";
794 // Handle the three int(int) results.
795 for (unsigned I
= 0; I
!= 3; ++I
) {
796 auto Err
= Client
.handleOne();
797 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
802 EXPECT_EQ(A
, 2) << "First parallel call returned bogus result";
803 EXPECT_EQ(B
, 4) << "Second parallel call returned bogus result";
804 EXPECT_EQ(C
, 6) << "Third parallel call returned bogus result";
810 TEST(DummyRPC
, TestAPICalls
) {
812 using DummyCalls1
= APICalls
<DummyRPCAPI::VoidBool
, DummyRPCAPI::IntInt
>;
813 using DummyCalls2
= APICalls
<DummyRPCAPI::AllTheTypes
>;
814 using DummyCalls3
= APICalls
<DummyCalls1
, DummyRPCAPI::CustomType
>;
815 using DummyCallsAll
= APICalls
<DummyCalls1
, DummyCalls2
, DummyRPCAPI::CustomType
>;
817 static_assert(DummyCalls1::Contains
<DummyRPCAPI::VoidBool
>::value
,
818 "Contains<Func> template should return true here");
819 static_assert(!DummyCalls1::Contains
<DummyRPCAPI::CustomType
>::value
,
820 "Contains<Func> template should return false here");
822 auto Channels
= createPairedQueueChannels();
823 DummyRPCEndpoint
Client(*Channels
.first
);
824 DummyRPCEndpoint
Server(*Channels
.second
);
826 std::thread
ServerThread(
828 Server
.addHandler
<DummyRPCAPI::VoidBool
>([](bool b
) { });
829 Server
.addHandler
<DummyRPCAPI::IntInt
>([](int x
) { return x
; });
830 Server
.addHandler
<DummyRPCAPI::CustomType
>([](RPCFoo F
) {});
832 for (unsigned I
= 0; I
< 4; ++I
) {
833 auto Err
= Server
.handleOne();
839 auto Err
= DummyCalls1::negotiate(Client
);
840 EXPECT_FALSE(!!Err
) << "DummyCalls1::negotiate failed";
844 auto Err
= DummyCalls3::negotiate(Client
);
845 EXPECT_FALSE(!!Err
) << "DummyCalls3::negotiate failed";
849 auto Err
= DummyCallsAll::negotiate(Client
);
850 EXPECT_TRUE(Err
.isA
<CouldNotNegotiate
>())
851 << "Expected CouldNotNegotiate error for attempted negotiate of "
852 "unsupported function";
853 consumeError(std::move(Err
));
859 TEST(DummyRPC
, TestRemoveHandler
) {
860 auto Channels
= createPairedQueueChannels();
861 DummyRPCEndpoint
Server(*Channels
.second
);
863 Server
.addHandler
<DummyRPCAPI::VoidBool
>(
866 << "Server void(bool) received unexpected result";
869 Server
.removeHandler
<DummyRPCAPI::VoidBool
>();
872 TEST(DummyRPC
, TestClearHandlers
) {
873 auto Channels
= createPairedQueueChannels();
874 DummyRPCEndpoint
Server(*Channels
.second
);
876 Server
.addHandler
<DummyRPCAPI::VoidBool
>(
879 << "Server void(bool) received unexpected result";
882 Server
.clearHandlers();