[Alignment][NFC] Use Align with TargetLowering::setMinFunctionAlignment
[llvm-core.git] / unittests / ExecutionEngine / Orc / RPCUtilsTest.cpp
blob1f7c88d93d068783d862a66eda42048a14a98a6e
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/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::rpc;
19 class RPCFoo {};
21 namespace llvm {
22 namespace orc {
23 namespace rpc {
25 template <>
26 class RPCTypeName<RPCFoo> {
27 public:
28 static const char* getName() { return "RPCFoo"; }
31 template <>
32 class SerializationTraits<QueueChannel, RPCFoo, RPCFoo> {
33 public:
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
47 class RPCBar {};
49 class DummyError : public ErrorInfo<DummyError> {
50 public:
52 static char ID;
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; }
69 public:
70 uint32_t 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>(
81 "DummyError",
82 [](ChannelT &C, const DummyError &DE) {
83 return serializeSeq(C, DE.getValue());
85 [](ChannelT &C, Error &Err) -> Error {
86 ErrorAsOutParameter EAO(&Err);
87 uint32_t Val;
88 if (auto Err = deserializeSeq(C, Val))
89 return Err;
90 Err = make_error<DummyError>(Val);
91 return Error::success();
92 });
93 AlreadyRegistered = true;
97 namespace llvm {
98 namespace orc {
99 namespace rpc {
101 template <>
102 class SerializationTraits<QueueChannel, RPCFoo, RPCBar> {
103 public:
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)> {
120 public:
121 static const char* getName() { return "VoidBool"; }
124 class IntInt : public Function<IntInt, int32_t(int32_t)> {
125 public:
126 static const char* getName() { return "IntInt"; }
129 class VoidString : public Function<VoidString, void(std::string)> {
130 public:
131 static const char* getName() { return "VoidString"; }
134 class AllTheTypes
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>)> {
139 public:
140 static const char* getName() { return "AllTheTypes"; }
143 class CustomType : public Function<CustomType, RPCFoo(RPCFoo)> {
144 public:
145 static const char* getName() { return "CustomType"; }
148 class ErrorFunc : public Function<ErrorFunc, Error()> {
149 public:
150 static const char* getName() { return "ErrorFunc"; }
153 class ExpectedFunc : public Function<ExpectedFunc, Expected<uint32_t>()> {
154 public:
155 static const char* getName() { return "ExpectedFunc"; }
160 class DummyRPCEndpoint : public SingleThreadedRPCEndpoint<QueueChannel> {
161 public:
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>(
183 [](bool B) {
184 EXPECT_EQ(B, true)
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>(
204 [](Error Err) {
205 EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed";
206 return Error::success();
207 }, true);
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)";
217 ServerThread.join();
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>(
227 [](int X) -> int {
228 EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
229 return 2 * X;
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();
252 }, 21);
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)";
262 ServerThread.join();
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,
273 bool B) {
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>(
294 [](Error Result) {
295 EXPECT_FALSE(!!Result) << "Async void(bool) response handler failed";
296 return Error::success();
297 }, true);
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)";
307 ServerThread.join();
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,
318 int32_t X) {
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();
343 }, 21);
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)";
353 ServerThread.join();
356 TEST(DummyRPC, TestAsyncIntIntHandlerMethod) {
357 auto Channels = createPairedQueueChannels();
358 DummyRPCEndpoint Client(*Channels.first);
359 DummyRPCEndpoint Server(*Channels.second);
361 class Dummy {
362 public:
363 Error handler(std::function<Error(Expected<int32_t>)> SendResult,
364 int32_t X) {
365 EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
366 return SendResult(2 * X);
370 std::thread ServerThread([&]() {
371 Dummy D;
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();
394 }, 21);
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)";
404 ServerThread.join();
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)";
444 ServerThread.join();
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,
458 std::vector<int> V,
459 std::set<int> S2,
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>(
498 [](Error Err) {
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";
516 ServerThread.join();
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>(
526 [](RPCFoo F) {});
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();
548 }, RPCFoo());
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();
555 EXPECT_FALSE(!!Err)
556 << "Client failed to handle response from RPCFoo(RPCFoo)";
559 ServerThread.join();
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>(
569 [](RPCBar F) {});
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();
591 }, RPCBar());
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();
598 EXPECT_FALSE(!!Err)
599 << "Client failed to handle response from RPCFoo(RPCFoo)";
602 ServerThread.join();
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>(
614 []() {
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>(
624 [&](Error Err) {
625 EXPECT_FALSE(!!Err) << "Expected success value";
626 return Error::success();
627 }));
629 cantFail(Client.handleOne());
631 ServerThread.join();
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>(
643 []() {
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>(
653 [&](Error Err) {
654 EXPECT_TRUE(Err.isA<DummyError>())
655 << "Incorrect error type";
656 return handleErrors(
657 std::move(Err),
658 [](const DummyError &DE) {
659 EXPECT_EQ(DE.getValue(), 42ULL)
660 << "Incorrect DummyError serialization";
662 }));
664 cantFail(Client.handleOne());
666 ServerThread.join();
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>(
678 []() -> uint32_t {
679 return 42;
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();
694 }));
696 cantFail(Client.handleOne());
698 ServerThread.join();
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";
726 return handleErrors(
727 std::move(Err),
728 [](const DummyError &DE) {
729 EXPECT_EQ(DE.getValue(), 7ULL)
730 << "Incorrect DummyError serialization";
732 }));
734 cantFail(Client.handleOne());
736 ServerThread.join();
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>(
746 [](int X) -> int {
747 return 2 * X;
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)";
758 int A, B, C;
759 ParallelCallGroup PCG;
762 auto Err = PCG.call(
763 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
764 [&A](Expected<int> Result) {
765 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
766 A = *Result;
767 return Error::success();
768 }, 1);
769 EXPECT_FALSE(!!Err) << "First parallel call failed for int(int)";
773 auto Err = PCG.call(
774 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
775 [&B](Expected<int> Result) {
776 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
777 B = *Result;
778 return Error::success();
779 }, 2);
780 EXPECT_FALSE(!!Err) << "Second parallel call failed for int(int)";
784 auto Err = PCG.call(
785 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
786 [&C](Expected<int> Result) {
787 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
788 C = *Result;
789 return Error::success();
790 }, 3);
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)";
800 PCG.wait();
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";
807 ServerThread.join();
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(
827 [&]() {
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();
834 (void)!!Err;
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));
856 ServerThread.join();
859 TEST(DummyRPC, TestRemoveHandler) {
860 auto Channels = createPairedQueueChannels();
861 DummyRPCEndpoint Server(*Channels.second);
863 Server.addHandler<DummyRPCAPI::VoidBool>(
864 [](bool B) {
865 EXPECT_EQ(B, true)
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>(
877 [](bool B) {
878 EXPECT_EQ(B, true)
879 << "Server void(bool) received unexpected result";
882 Server.clearHandlers();