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/Shared/RPCUtils.h"
10 #include "QueueChannel.h"
11 #include "gtest/gtest.h"
16 using namespace llvm::orc
;
17 using namespace llvm::orc::shared
;
25 template <> class SerializationTypeName
<RPCFoo
> {
27 static const char *getName() { return "RPCFoo"; }
31 class SerializationTraits
<QueueChannel
, RPCFoo
, RPCFoo
> {
33 static Error
serialize(QueueChannel
&, const RPCFoo
&) {
34 return Error::success();
37 static Error
deserialize(QueueChannel
&, RPCFoo
&) {
38 return Error::success();
43 } // end namespace orc
44 } // end namespace llvm
48 class DummyError
: public ErrorInfo
<DummyError
> {
53 DummyError(uint32_t Val
) : Val(Val
) {}
55 std::error_code
convertToErrorCode() const override
{
56 // Use a nonsense error code - we want to verify that errors
57 // transmitted over the network are replaced with
58 // OrcErrorCode::UnknownErrorCodeFromRemote.
59 return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist
);
62 void log(raw_ostream
&OS
) const override
{
63 OS
<< "Dummy error " << Val
;
66 uint32_t getValue() const { return Val
; }
72 char DummyError::ID
= 0;
74 template <typename ChannelT
>
75 void registerDummyErrorSerialization() {
76 static bool AlreadyRegistered
= false;
77 if (!AlreadyRegistered
) {
78 SerializationTraits
<ChannelT
, Error
>::
79 template registerErrorType
<DummyError
>(
81 [](ChannelT
&C
, const DummyError
&DE
) {
82 return serializeSeq(C
, DE
.getValue());
84 [](ChannelT
&C
, Error
&Err
) -> Error
{
85 ErrorAsOutParameter
EAO(&Err
);
87 if (auto Err
= deserializeSeq(C
, Val
))
89 Err
= make_error
<DummyError
>(Val
);
90 return Error::success();
92 AlreadyRegistered
= true;
100 template <> class SerializationTraits
<QueueChannel
, RPCFoo
, RPCBar
> {
102 static Error
serialize(QueueChannel
&, const RPCBar
&) {
103 return Error::success();
106 static Error
deserialize(QueueChannel
&, RPCBar
&) {
107 return Error::success();
111 } // end namespace shared
112 } // end namespace orc
113 } // end namespace llvm
115 namespace DummyRPCAPI
{
117 class VoidBool
: public RPCFunction
<VoidBool
, void(bool)> {
119 static const char *getName() { return "VoidBool"; }
122 class IntInt
: public RPCFunction
<IntInt
, int32_t(int32_t)> {
124 static const char *getName() { return "IntInt"; }
127 class VoidString
: public RPCFunction
<VoidString
, void(std::string
)> {
129 static const char *getName() { return "VoidString"; }
133 : public RPCFunction
<AllTheTypes
,
134 void(int8_t, uint8_t, int16_t, uint16_t, int32_t,
135 uint32_t, int64_t, uint64_t, bool, std::string
,
136 std::vector
<int>, std::set
<int>,
137 std::map
<int, bool>)> {
139 static const char *getName() { return "AllTheTypes"; }
142 class CustomType
: public RPCFunction
<CustomType
, RPCFoo(RPCFoo
)> {
144 static const char *getName() { return "CustomType"; }
147 class ErrorFunc
: public RPCFunction
<ErrorFunc
, Error()> {
149 static const char *getName() { return "ErrorFunc"; }
152 class ExpectedFunc
: public RPCFunction
<ExpectedFunc
, Expected
<uint32_t>()> {
154 static const char *getName() { return "ExpectedFunc"; }
158 class DummyRPCEndpoint
: public SingleThreadedRPCEndpoint
<QueueChannel
> {
160 DummyRPCEndpoint(QueueChannel
&C
)
161 : SingleThreadedRPCEndpoint(C
, true) {}
165 void freeVoidBool(bool B
) {
168 TEST(DummyRPC
, TestFreeFunctionHandler
) {
169 auto Channels
= createPairedQueueChannels();
170 DummyRPCEndpoint
Server(*Channels
.first
);
171 Server
.addHandler
<DummyRPCAPI::VoidBool
>(freeVoidBool
);
174 TEST(DummyRPC
, TestCallAsyncVoidBool
) {
175 auto Channels
= createPairedQueueChannels();
176 DummyRPCEndpoint
Client(*Channels
.first
);
177 DummyRPCEndpoint
Server(*Channels
.second
);
179 std::thread
ServerThread([&]() {
180 Server
.addHandler
<DummyRPCAPI::VoidBool
>(
183 << "Server void(bool) received unexpected result";
187 // Poke the server to handle the negotiate call.
188 auto Err
= Server
.handleOne();
189 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
193 // Poke the server to handle the VoidBool call.
194 auto Err
= Server
.handleOne();
195 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
200 // Make an async call.
201 auto Err
= Client
.callAsync
<DummyRPCAPI::VoidBool
>(
203 EXPECT_FALSE(!!Err
) << "Async void(bool) response handler failed";
204 return Error::success();
206 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(bool)";
210 // Poke the client to process the result of the void(bool) call.
211 auto Err
= Client
.handleOne();
212 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
217 // The client should have made two calls to send: One implicit call to
218 // negotiate the VoidBool function key, and a second to make the VoidBool
220 EXPECT_EQ(Channels
.first
->SendCalls
, 2U)
221 << "Expected one send call to have been made by client";
223 // The server should have made two calls to send: One to send the response to
224 // the negotiate call, and another to send the response to the VoidBool call.
225 EXPECT_EQ(Channels
.second
->SendCalls
, 2U)
226 << "Expected two send calls to have been made by server";
229 TEST(DummyRPC
, TestCallAsyncIntInt
) {
230 auto Channels
= createPairedQueueChannels();
231 DummyRPCEndpoint
Client(*Channels
.first
);
232 DummyRPCEndpoint
Server(*Channels
.second
);
234 std::thread
ServerThread([&]() {
235 Server
.addHandler
<DummyRPCAPI::IntInt
>(
237 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
242 // Poke the server to handle the negotiate call.
243 auto Err
= Server
.handleOne();
244 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
248 // Poke the server to handle the int(int) call.
249 auto Err
= Server
.handleOne();
250 EXPECT_FALSE(!!Err
) << "Server failed to handle call to int(int)";
255 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
256 [](Expected
<int> Result
) {
257 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
258 EXPECT_EQ(*Result
, 42)
259 << "Async int(int) response handler received incorrect result";
260 return Error::success();
262 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
266 // Poke the client to process the result.
267 auto Err
= Client
.handleOne();
268 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
274 TEST(DummyRPC
, TestAsyncVoidBoolHandler
) {
275 auto Channels
= createPairedQueueChannels();
276 DummyRPCEndpoint
Client(*Channels
.first
);
277 DummyRPCEndpoint
Server(*Channels
.second
);
279 std::thread
ServerThread([&]() {
280 Server
.addAsyncHandler
<DummyRPCAPI::VoidBool
>(
281 [](std::function
<Error(Error
)> SendResult
,
283 EXPECT_EQ(B
, true) << "Server void(bool) receieved unexpected result";
284 cantFail(SendResult(Error::success()));
285 return Error::success();
289 // Poke the server to handle the negotiate call.
290 auto Err
= Server
.handleOne();
291 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
295 // Poke the server to handle the VoidBool call.
296 auto Err
= Server
.handleOne();
297 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
302 auto Err
= Client
.callAsync
<DummyRPCAPI::VoidBool
>(
304 EXPECT_FALSE(!!Result
) << "Async void(bool) response handler failed";
305 return Error::success();
307 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(bool)";
311 // Poke the client to process the result.
312 auto Err
= Client
.handleOne();
313 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
319 TEST(DummyRPC
, TestAsyncIntIntHandler
) {
320 auto Channels
= createPairedQueueChannels();
321 DummyRPCEndpoint
Client(*Channels
.first
);
322 DummyRPCEndpoint
Server(*Channels
.second
);
324 std::thread
ServerThread([&]() {
325 Server
.addAsyncHandler
<DummyRPCAPI::IntInt
>(
326 [](std::function
<Error(Expected
<int32_t>)> SendResult
,
328 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
329 return SendResult(2 * X
);
333 // Poke the server to handle the negotiate call.
334 auto Err
= Server
.handleOne();
335 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
339 // Poke the server to handle the VoidBool call.
340 auto Err
= Server
.handleOne();
341 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
346 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
347 [](Expected
<int> Result
) {
348 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
349 EXPECT_EQ(*Result
, 42)
350 << "Async int(int) response handler received incorrect result";
351 return Error::success();
353 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
357 // Poke the client to process the result.
358 auto Err
= Client
.handleOne();
359 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
365 TEST(DummyRPC
, TestAsyncIntIntHandlerMethod
) {
366 auto Channels
= createPairedQueueChannels();
367 DummyRPCEndpoint
Client(*Channels
.first
);
368 DummyRPCEndpoint
Server(*Channels
.second
);
372 Error
handler(std::function
<Error(Expected
<int32_t>)> SendResult
,
374 EXPECT_EQ(X
, 21) << "Server int(int) receieved unexpected result";
375 return SendResult(2 * X
);
379 std::thread
ServerThread([&]() {
381 Server
.addAsyncHandler
<DummyRPCAPI::IntInt
>(D
, &Dummy::handler
);
384 // Poke the server to handle the negotiate call.
385 auto Err
= Server
.handleOne();
386 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
390 // Poke the server to handle the VoidBool call.
391 auto Err
= Server
.handleOne();
392 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
397 auto Err
= Client
.callAsync
<DummyRPCAPI::IntInt
>(
398 [](Expected
<int> Result
) {
399 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
400 EXPECT_EQ(*Result
, 42)
401 << "Async int(int) response handler received incorrect result";
402 return Error::success();
404 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for int(int)";
408 // Poke the client to process the result.
409 auto Err
= Client
.handleOne();
410 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
416 TEST(DummyRPC
, TestCallAsyncVoidString
) {
417 auto Channels
= createPairedQueueChannels();
418 DummyRPCEndpoint
Client(*Channels
.first
);
419 DummyRPCEndpoint
Server(*Channels
.second
);
421 std::thread
ServerThread([&]() {
422 Server
.addHandler
<DummyRPCAPI::VoidString
>(
423 [](const std::string
&S
) {
424 EXPECT_EQ(S
, "hello")
425 << "Server void(std::string) received unexpected result";
428 // Poke the server to handle the negotiate call.
429 for (int I
= 0; I
< 4; ++I
) {
430 auto Err
= Server
.handleOne();
431 EXPECT_FALSE(!!Err
) << "Server failed to handle call";
436 // Make an call using a std::string.
437 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>(std::string("hello"));
438 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(std::string)";
442 // Make an call using a std::string.
443 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>(StringRef("hello"));
444 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(std::string)";
448 // Make an call using a std::string.
449 auto Err
= Client
.callB
<DummyRPCAPI::VoidString
>("hello");
450 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for void(string)";
456 TEST(DummyRPC
, TestSerialization
) {
457 auto Channels
= createPairedQueueChannels();
458 DummyRPCEndpoint
Client(*Channels
.first
);
459 DummyRPCEndpoint
Server(*Channels
.second
);
461 std::thread
ServerThread([&]() {
462 Server
.addHandler
<DummyRPCAPI::AllTheTypes
>([&](int8_t S8
, uint8_t U8
,
463 int16_t S16
, uint16_t U16
,
464 int32_t S32
, uint32_t U32
,
465 int64_t S64
, uint64_t U64
,
466 bool B
, std::string S
,
469 std::map
<int, bool> M
) {
470 EXPECT_EQ(S8
, -101) << "int8_t serialization broken";
471 EXPECT_EQ(U8
, 250) << "uint8_t serialization broken";
472 EXPECT_EQ(S16
, -10000) << "int16_t serialization broken";
473 EXPECT_EQ(U16
, 10000) << "uint16_t serialization broken";
474 EXPECT_EQ(S32
, -1000000000) << "int32_t serialization broken";
475 EXPECT_EQ(U32
, 1000000000ULL) << "uint32_t serialization broken";
476 EXPECT_EQ(S64
, -10000000000) << "int64_t serialization broken";
477 EXPECT_EQ(U64
, 10000000000ULL) << "uint64_t serialization broken";
478 EXPECT_EQ(B
, true) << "bool serialization broken";
479 EXPECT_EQ(S
, "foo") << "std::string serialization broken";
480 EXPECT_EQ(V
, std::vector
<int>({42, 7}))
481 << "std::vector serialization broken";
482 EXPECT_EQ(S2
, std::set
<int>({7, 42})) << "std::set serialization broken";
483 EXPECT_EQ(M
, (std::map
<int, bool>({{7, false}, {42, true}})))
484 << "std::map serialization broken";
485 return Error::success();
489 // Poke the server to handle the negotiate call.
490 auto Err
= Server
.handleOne();
491 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
495 // Poke the server to handle the AllTheTypes call.
496 auto Err
= Server
.handleOne();
497 EXPECT_FALSE(!!Err
) << "Server failed to handle call to void(bool)";
502 // Make an async call.
503 std::vector
<int> V({42, 7});
504 std::set
<int> S({7, 42});
505 std::map
<int, bool> M({{7, false}, {42, true}});
506 auto Err
= Client
.callAsync
<DummyRPCAPI::AllTheTypes
>(
508 EXPECT_FALSE(!!Err
) << "Async AllTheTypes response handler failed";
509 return Error::success();
511 static_cast<int8_t>(-101), static_cast<uint8_t>(250),
512 static_cast<int16_t>(-10000), static_cast<uint16_t>(10000),
513 static_cast<int32_t>(-1000000000), static_cast<uint32_t>(1000000000),
514 static_cast<int64_t>(-10000000000), static_cast<uint64_t>(10000000000),
515 true, std::string("foo"), V
, S
, M
);
516 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for AllTheTypes";
520 // Poke the client to process the result of the AllTheTypes call.
521 auto Err
= Client
.handleOne();
522 EXPECT_FALSE(!!Err
) << "Client failed to handle response from AllTheTypes";
528 TEST(DummyRPC
, TestCustomType
) {
529 auto Channels
= createPairedQueueChannels();
530 DummyRPCEndpoint
Client(*Channels
.first
);
531 DummyRPCEndpoint
Server(*Channels
.second
);
533 std::thread
ServerThread([&]() {
534 Server
.addHandler
<DummyRPCAPI::CustomType
>(
538 // Poke the server to handle the negotiate call.
539 auto Err
= Server
.handleOne();
540 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
544 // Poke the server to handle the CustomType call.
545 auto Err
= Server
.handleOne();
546 EXPECT_FALSE(!!Err
) << "Server failed to handle call to RPCFoo(RPCFoo)";
551 // Make an async call.
552 auto Err
= Client
.callAsync
<DummyRPCAPI::CustomType
>(
553 [](Expected
<RPCFoo
> FOrErr
) {
554 EXPECT_TRUE(!!FOrErr
)
555 << "Async RPCFoo(RPCFoo) response handler failed";
556 return Error::success();
558 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for RPCFoo(RPCFoo)";
562 // Poke the client to process the result of the RPCFoo() call.
563 auto Err
= Client
.handleOne();
565 << "Client failed to handle response from RPCFoo(RPCFoo)";
571 TEST(DummyRPC
, TestWithAltCustomType
) {
572 auto Channels
= createPairedQueueChannels();
573 DummyRPCEndpoint
Client(*Channels
.first
);
574 DummyRPCEndpoint
Server(*Channels
.second
);
576 std::thread
ServerThread([&]() {
577 Server
.addHandler
<DummyRPCAPI::CustomType
>(
581 // Poke the server to handle the negotiate call.
582 auto Err
= Server
.handleOne();
583 EXPECT_FALSE(!!Err
) << "Server failed to handle call to negotiate";
587 // Poke the server to handle the CustomType call.
588 auto Err
= Server
.handleOne();
589 EXPECT_FALSE(!!Err
) << "Server failed to handle call to RPCFoo(RPCFoo)";
594 // Make an async call.
595 auto Err
= Client
.callAsync
<DummyRPCAPI::CustomType
>(
596 [](Expected
<RPCBar
> FOrErr
) {
597 EXPECT_TRUE(!!FOrErr
)
598 << "Async RPCFoo(RPCFoo) response handler failed";
599 return Error::success();
601 EXPECT_FALSE(!!Err
) << "Client.callAsync failed for RPCFoo(RPCFoo)";
605 // Poke the client to process the result of the RPCFoo() call.
606 auto Err
= Client
.handleOne();
608 << "Client failed to handle response from RPCFoo(RPCFoo)";
614 TEST(DummyRPC
, ReturnErrorSuccess
) {
615 registerDummyErrorSerialization
<QueueChannel
>();
617 auto Channels
= createPairedQueueChannels();
618 DummyRPCEndpoint
Client(*Channels
.first
);
619 DummyRPCEndpoint
Server(*Channels
.second
);
621 std::thread
ServerThread([&]() {
622 Server
.addHandler
<DummyRPCAPI::ErrorFunc
>(
624 return Error::success();
627 // Handle the negotiate plus one call.
628 for (unsigned I
= 0; I
!= 2; ++I
)
629 cantFail(Server
.handleOne());
632 cantFail(Client
.callAsync
<DummyRPCAPI::ErrorFunc
>(
634 EXPECT_FALSE(!!Err
) << "Expected success value";
635 return Error::success();
638 cantFail(Client
.handleOne());
643 TEST(DummyRPC
, ReturnErrorFailure
) {
644 registerDummyErrorSerialization
<QueueChannel
>();
646 auto Channels
= createPairedQueueChannels();
647 DummyRPCEndpoint
Client(*Channels
.first
);
648 DummyRPCEndpoint
Server(*Channels
.second
);
650 std::thread
ServerThread([&]() {
651 Server
.addHandler
<DummyRPCAPI::ErrorFunc
>(
653 return make_error
<DummyError
>(42);
656 // Handle the negotiate plus one call.
657 for (unsigned I
= 0; I
!= 2; ++I
)
658 cantFail(Server
.handleOne());
661 cantFail(Client
.callAsync
<DummyRPCAPI::ErrorFunc
>(
663 EXPECT_TRUE(Err
.isA
<DummyError
>())
664 << "Incorrect error type";
667 [](const DummyError
&DE
) {
668 EXPECT_EQ(DE
.getValue(), 42ULL)
669 << "Incorrect DummyError serialization";
673 cantFail(Client
.handleOne());
678 TEST(DummyRPC
, ReturnExpectedSuccess
) {
679 registerDummyErrorSerialization
<QueueChannel
>();
681 auto Channels
= createPairedQueueChannels();
682 DummyRPCEndpoint
Client(*Channels
.first
);
683 DummyRPCEndpoint
Server(*Channels
.second
);
685 std::thread
ServerThread([&]() {
686 Server
.addHandler
<DummyRPCAPI::ExpectedFunc
>(
691 // Handle the negotiate plus one call.
692 for (unsigned I
= 0; I
!= 2; ++I
)
693 cantFail(Server
.handleOne());
696 cantFail(Client
.callAsync
<DummyRPCAPI::ExpectedFunc
>(
697 [&](Expected
<uint32_t> ValOrErr
) {
698 EXPECT_TRUE(!!ValOrErr
)
699 << "Expected success value";
700 EXPECT_EQ(*ValOrErr
, 42ULL)
701 << "Incorrect Expected<uint32_t> deserialization";
702 return Error::success();
705 cantFail(Client
.handleOne());
710 TEST(DummyRPC
, ReturnExpectedFailure
) {
711 registerDummyErrorSerialization
<QueueChannel
>();
713 auto Channels
= createPairedQueueChannels();
714 DummyRPCEndpoint
Client(*Channels
.first
);
715 DummyRPCEndpoint
Server(*Channels
.second
);
717 std::thread
ServerThread([&]() {
718 Server
.addHandler
<DummyRPCAPI::ExpectedFunc
>(
719 []() -> Expected
<uint32_t> {
720 return make_error
<DummyError
>(7);
723 // Handle the negotiate plus one call.
724 for (unsigned I
= 0; I
!= 2; ++I
)
725 cantFail(Server
.handleOne());
728 cantFail(Client
.callAsync
<DummyRPCAPI::ExpectedFunc
>(
729 [&](Expected
<uint32_t> ValOrErr
) {
730 EXPECT_FALSE(!!ValOrErr
)
731 << "Expected failure value";
732 auto Err
= ValOrErr
.takeError();
733 EXPECT_TRUE(Err
.isA
<DummyError
>())
734 << "Incorrect error type";
737 [](const DummyError
&DE
) {
738 EXPECT_EQ(DE
.getValue(), 7ULL)
739 << "Incorrect DummyError serialization";
743 cantFail(Client
.handleOne());
748 TEST(DummyRPC
, TestParallelCallGroup
) {
749 auto Channels
= createPairedQueueChannels();
750 DummyRPCEndpoint
Client(*Channels
.first
);
751 DummyRPCEndpoint
Server(*Channels
.second
);
753 std::thread
ServerThread([&]() {
754 Server
.addHandler
<DummyRPCAPI::IntInt
>(
759 // Handle the negotiate, plus three calls.
760 for (unsigned I
= 0; I
!= 4; ++I
) {
761 auto Err
= Server
.handleOne();
762 EXPECT_FALSE(!!Err
) << "Server failed to handle call to int(int)";
768 ParallelCallGroup PCG
;
772 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
773 [&A
](Expected
<int> Result
) {
774 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
776 return Error::success();
778 EXPECT_FALSE(!!Err
) << "First parallel call failed for int(int)";
783 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
784 [&B
](Expected
<int> Result
) {
785 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
787 return Error::success();
789 EXPECT_FALSE(!!Err
) << "Second parallel call failed for int(int)";
794 rpcAsyncDispatch
<DummyRPCAPI::IntInt
>(Client
),
795 [&C
](Expected
<int> Result
) {
796 EXPECT_TRUE(!!Result
) << "Async int(int) response handler failed";
798 return Error::success();
800 EXPECT_FALSE(!!Err
) << "Third parallel call failed for int(int)";
803 // Handle the three int(int) results.
804 for (unsigned I
= 0; I
!= 3; ++I
) {
805 auto Err
= Client
.handleOne();
806 EXPECT_FALSE(!!Err
) << "Client failed to handle response from void(bool)";
811 EXPECT_EQ(A
, 2) << "First parallel call returned bogus result";
812 EXPECT_EQ(B
, 4) << "Second parallel call returned bogus result";
813 EXPECT_EQ(C
, 6) << "Third parallel call returned bogus result";
819 TEST(DummyRPC
, TestAPICalls
) {
821 using DummyCalls1
= APICalls
<DummyRPCAPI::VoidBool
, DummyRPCAPI::IntInt
>;
822 using DummyCalls2
= APICalls
<DummyRPCAPI::AllTheTypes
>;
823 using DummyCalls3
= APICalls
<DummyCalls1
, DummyRPCAPI::CustomType
>;
824 using DummyCallsAll
= APICalls
<DummyCalls1
, DummyCalls2
, DummyRPCAPI::CustomType
>;
826 static_assert(DummyCalls1::Contains
<DummyRPCAPI::VoidBool
>::value
,
827 "Contains<Func> template should return true here");
828 static_assert(!DummyCalls1::Contains
<DummyRPCAPI::CustomType
>::value
,
829 "Contains<Func> template should return false here");
831 auto Channels
= createPairedQueueChannels();
832 DummyRPCEndpoint
Client(*Channels
.first
);
833 DummyRPCEndpoint
Server(*Channels
.second
);
835 std::thread
ServerThread(
837 Server
.addHandler
<DummyRPCAPI::VoidBool
>([](bool b
) { });
838 Server
.addHandler
<DummyRPCAPI::IntInt
>([](int x
) { return x
; });
839 Server
.addHandler
<DummyRPCAPI::CustomType
>([](RPCFoo F
) {});
841 for (unsigned I
= 0; I
< 4; ++I
) {
842 auto Err
= Server
.handleOne();
848 auto Err
= DummyCalls1::negotiate(Client
);
849 EXPECT_FALSE(!!Err
) << "DummyCalls1::negotiate failed";
853 auto Err
= DummyCalls3::negotiate(Client
);
854 EXPECT_FALSE(!!Err
) << "DummyCalls3::negotiate failed";
858 auto Err
= DummyCallsAll::negotiate(Client
);
859 EXPECT_TRUE(Err
.isA
<CouldNotNegotiate
>())
860 << "Expected CouldNotNegotiate error for attempted negotiate of "
861 "unsupported function";
862 consumeError(std::move(Err
));
868 TEST(DummyRPC
, TestRemoveHandler
) {
869 auto Channels
= createPairedQueueChannels();
870 DummyRPCEndpoint
Server(*Channels
.second
);
872 Server
.addHandler
<DummyRPCAPI::VoidBool
>(
874 llvm_unreachable("Server void(bool) received unexpected result");
877 Server
.removeHandler
<DummyRPCAPI::VoidBool
>();
880 TEST(DummyRPC
, TestClearHandlers
) {
881 auto Channels
= createPairedQueueChannels();
882 DummyRPCEndpoint
Server(*Channels
.second
);
884 Server
.addHandler
<DummyRPCAPI::VoidBool
>(
886 llvm_unreachable("Server void(bool) received unexpected result");
889 Server
.clearHandlers();