[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / unittests / ExecutionEngine / Orc / RPCUtilsTest.cpp
blob0f5cb14fec37cb7b5e5c77164d869a81b75e6be0
1 //===----------- RPCUtilsTest.cpp - Unit tests the Orc RPC utils ----------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ExecutionEngine/Orc/Shared/RPCUtils.h"
10 #include "QueueChannel.h"
11 #include "gtest/gtest.h"
13 #include <queue>
15 using namespace llvm;
16 using namespace llvm::orc;
17 using namespace llvm::orc::shared;
19 class RPCFoo {};
21 namespace llvm {
22 namespace orc {
23 namespace shared {
25 template <> class SerializationTypeName<RPCFoo> {
26 public:
27 static const char *getName() { return "RPCFoo"; }
30 template <>
31 class SerializationTraits<QueueChannel, RPCFoo, RPCFoo> {
32 public:
33 static Error serialize(QueueChannel&, const RPCFoo&) {
34 return Error::success();
37 static Error deserialize(QueueChannel&, RPCFoo&) {
38 return Error::success();
42 } // namespace shared
43 } // end namespace orc
44 } // end namespace llvm
46 class RPCBar {};
48 class DummyError : public ErrorInfo<DummyError> {
49 public:
51 static char ID;
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; }
68 public:
69 uint32_t 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>(
80 "DummyError",
81 [](ChannelT &C, const DummyError &DE) {
82 return serializeSeq(C, DE.getValue());
84 [](ChannelT &C, Error &Err) -> Error {
85 ErrorAsOutParameter EAO(&Err);
86 uint32_t Val;
87 if (auto Err = deserializeSeq(C, Val))
88 return Err;
89 Err = make_error<DummyError>(Val);
90 return Error::success();
91 });
92 AlreadyRegistered = true;
96 namespace llvm {
97 namespace orc {
98 namespace shared {
100 template <> class SerializationTraits<QueueChannel, RPCFoo, RPCBar> {
101 public:
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)> {
118 public:
119 static const char *getName() { return "VoidBool"; }
122 class IntInt : public RPCFunction<IntInt, int32_t(int32_t)> {
123 public:
124 static const char *getName() { return "IntInt"; }
127 class VoidString : public RPCFunction<VoidString, void(std::string)> {
128 public:
129 static const char *getName() { return "VoidString"; }
132 class AllTheTypes
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>)> {
138 public:
139 static const char *getName() { return "AllTheTypes"; }
142 class CustomType : public RPCFunction<CustomType, RPCFoo(RPCFoo)> {
143 public:
144 static const char *getName() { return "CustomType"; }
147 class ErrorFunc : public RPCFunction<ErrorFunc, Error()> {
148 public:
149 static const char *getName() { return "ErrorFunc"; }
152 class ExpectedFunc : public RPCFunction<ExpectedFunc, Expected<uint32_t>()> {
153 public:
154 static const char *getName() { return "ExpectedFunc"; }
158 class DummyRPCEndpoint : public SingleThreadedRPCEndpoint<QueueChannel> {
159 public:
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>(
181 [](bool B) {
182 EXPECT_EQ(B, true)
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>(
202 [](Error Err) {
203 EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed";
204 return Error::success();
205 }, true);
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)";
215 ServerThread.join();
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
219 // call.
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>(
236 [](int X) -> int {
237 EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
238 return 2 * X;
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();
261 }, 21);
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)";
271 ServerThread.join();
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,
282 bool B) {
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>(
303 [](Error Result) {
304 EXPECT_FALSE(!!Result) << "Async void(bool) response handler failed";
305 return Error::success();
306 }, true);
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)";
316 ServerThread.join();
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,
327 int32_t X) {
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();
352 }, 21);
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)";
362 ServerThread.join();
365 TEST(DummyRPC, TestAsyncIntIntHandlerMethod) {
366 auto Channels = createPairedQueueChannels();
367 DummyRPCEndpoint Client(*Channels.first);
368 DummyRPCEndpoint Server(*Channels.second);
370 class Dummy {
371 public:
372 Error handler(std::function<Error(Expected<int32_t>)> SendResult,
373 int32_t X) {
374 EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
375 return SendResult(2 * X);
379 std::thread ServerThread([&]() {
380 Dummy D;
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();
403 }, 21);
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)";
413 ServerThread.join();
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)";
453 ServerThread.join();
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,
467 std::vector<int> V,
468 std::set<int> S2,
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>(
507 [](Error Err) {
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";
525 ServerThread.join();
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>(
535 [](RPCFoo F) {});
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();
557 }, RPCFoo());
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();
564 EXPECT_FALSE(!!Err)
565 << "Client failed to handle response from RPCFoo(RPCFoo)";
568 ServerThread.join();
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>(
578 [](RPCBar F) {});
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();
600 }, RPCBar());
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();
607 EXPECT_FALSE(!!Err)
608 << "Client failed to handle response from RPCFoo(RPCFoo)";
611 ServerThread.join();
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>(
623 []() {
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>(
633 [&](Error Err) {
634 EXPECT_FALSE(!!Err) << "Expected success value";
635 return Error::success();
636 }));
638 cantFail(Client.handleOne());
640 ServerThread.join();
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>(
652 []() {
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>(
662 [&](Error Err) {
663 EXPECT_TRUE(Err.isA<DummyError>())
664 << "Incorrect error type";
665 return handleErrors(
666 std::move(Err),
667 [](const DummyError &DE) {
668 EXPECT_EQ(DE.getValue(), 42ULL)
669 << "Incorrect DummyError serialization";
671 }));
673 cantFail(Client.handleOne());
675 ServerThread.join();
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>(
687 []() -> uint32_t {
688 return 42;
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();
703 }));
705 cantFail(Client.handleOne());
707 ServerThread.join();
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";
735 return handleErrors(
736 std::move(Err),
737 [](const DummyError &DE) {
738 EXPECT_EQ(DE.getValue(), 7ULL)
739 << "Incorrect DummyError serialization";
741 }));
743 cantFail(Client.handleOne());
745 ServerThread.join();
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>(
755 [](int X) -> int {
756 return 2 * X;
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)";
767 int A, B, C;
768 ParallelCallGroup PCG;
771 auto Err = PCG.call(
772 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
773 [&A](Expected<int> Result) {
774 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
775 A = *Result;
776 return Error::success();
777 }, 1);
778 EXPECT_FALSE(!!Err) << "First parallel call failed for int(int)";
782 auto Err = PCG.call(
783 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
784 [&B](Expected<int> Result) {
785 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
786 B = *Result;
787 return Error::success();
788 }, 2);
789 EXPECT_FALSE(!!Err) << "Second parallel call failed for int(int)";
793 auto Err = PCG.call(
794 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
795 [&C](Expected<int> Result) {
796 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
797 C = *Result;
798 return Error::success();
799 }, 3);
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)";
809 PCG.wait();
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";
816 ServerThread.join();
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(
836 [&]() {
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();
843 (void)!!Err;
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));
865 ServerThread.join();
868 TEST(DummyRPC, TestRemoveHandler) {
869 auto Channels = createPairedQueueChannels();
870 DummyRPCEndpoint Server(*Channels.second);
872 Server.addHandler<DummyRPCAPI::VoidBool>(
873 [](bool B) {
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>(
885 [](bool B) {
886 llvm_unreachable("Server void(bool) received unexpected result");
889 Server.clearHandlers();