[InstCombine] Signed saturation patterns
[llvm-core.git] / unittests / ExecutionEngine / Orc / RPCUtilsTest.cpp
blob2a0ed07725241d4fdec5b32266e2ddf4194e708e
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();
219 // The client should have made two calls to send: One implicit call to
220 // negotiate the VoidBool function key, and a second to make the VoidBool
221 // call.
222 EXPECT_EQ(Channels.first->SendCalls, 2U)
223 << "Expected one send call to have been made by client";
225 // The server should have made two calls to send: One to send the response to
226 // the negotiate call, and another to send the response to the VoidBool call.
227 EXPECT_EQ(Channels.second->SendCalls, 2U)
228 << "Expected two send calls to have been made by server";
231 TEST(DummyRPC, TestCallAsyncIntInt) {
232 auto Channels = createPairedQueueChannels();
233 DummyRPCEndpoint Client(*Channels.first);
234 DummyRPCEndpoint Server(*Channels.second);
236 std::thread ServerThread([&]() {
237 Server.addHandler<DummyRPCAPI::IntInt>(
238 [](int X) -> int {
239 EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
240 return 2 * X;
244 // Poke the server to handle the negotiate call.
245 auto Err = Server.handleOne();
246 EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
250 // Poke the server to handle the int(int) call.
251 auto Err = Server.handleOne();
252 EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)";
257 auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
258 [](Expected<int> Result) {
259 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
260 EXPECT_EQ(*Result, 42)
261 << "Async int(int) response handler received incorrect result";
262 return Error::success();
263 }, 21);
264 EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
268 // Poke the client to process the result.
269 auto Err = Client.handleOne();
270 EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
273 ServerThread.join();
276 TEST(DummyRPC, TestAsyncVoidBoolHandler) {
277 auto Channels = createPairedQueueChannels();
278 DummyRPCEndpoint Client(*Channels.first);
279 DummyRPCEndpoint Server(*Channels.second);
281 std::thread ServerThread([&]() {
282 Server.addAsyncHandler<DummyRPCAPI::VoidBool>(
283 [](std::function<Error(Error)> SendResult,
284 bool B) {
285 EXPECT_EQ(B, true) << "Server void(bool) receieved unexpected result";
286 cantFail(SendResult(Error::success()));
287 return Error::success();
291 // Poke the server to handle the negotiate call.
292 auto Err = Server.handleOne();
293 EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
297 // Poke the server to handle the VoidBool call.
298 auto Err = Server.handleOne();
299 EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
304 auto Err = Client.callAsync<DummyRPCAPI::VoidBool>(
305 [](Error Result) {
306 EXPECT_FALSE(!!Result) << "Async void(bool) response handler failed";
307 return Error::success();
308 }, true);
309 EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)";
313 // Poke the client to process the result.
314 auto Err = Client.handleOne();
315 EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
318 ServerThread.join();
321 TEST(DummyRPC, TestAsyncIntIntHandler) {
322 auto Channels = createPairedQueueChannels();
323 DummyRPCEndpoint Client(*Channels.first);
324 DummyRPCEndpoint Server(*Channels.second);
326 std::thread ServerThread([&]() {
327 Server.addAsyncHandler<DummyRPCAPI::IntInt>(
328 [](std::function<Error(Expected<int32_t>)> SendResult,
329 int32_t X) {
330 EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
331 return SendResult(2 * X);
335 // Poke the server to handle the negotiate call.
336 auto Err = Server.handleOne();
337 EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
341 // Poke the server to handle the VoidBool call.
342 auto Err = Server.handleOne();
343 EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
348 auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
349 [](Expected<int> Result) {
350 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
351 EXPECT_EQ(*Result, 42)
352 << "Async int(int) response handler received incorrect result";
353 return Error::success();
354 }, 21);
355 EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
359 // Poke the client to process the result.
360 auto Err = Client.handleOne();
361 EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
364 ServerThread.join();
367 TEST(DummyRPC, TestAsyncIntIntHandlerMethod) {
368 auto Channels = createPairedQueueChannels();
369 DummyRPCEndpoint Client(*Channels.first);
370 DummyRPCEndpoint Server(*Channels.second);
372 class Dummy {
373 public:
374 Error handler(std::function<Error(Expected<int32_t>)> SendResult,
375 int32_t X) {
376 EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
377 return SendResult(2 * X);
381 std::thread ServerThread([&]() {
382 Dummy D;
383 Server.addAsyncHandler<DummyRPCAPI::IntInt>(D, &Dummy::handler);
386 // Poke the server to handle the negotiate call.
387 auto Err = Server.handleOne();
388 EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
392 // Poke the server to handle the VoidBool call.
393 auto Err = Server.handleOne();
394 EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
399 auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
400 [](Expected<int> Result) {
401 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
402 EXPECT_EQ(*Result, 42)
403 << "Async int(int) response handler received incorrect result";
404 return Error::success();
405 }, 21);
406 EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
410 // Poke the client to process the result.
411 auto Err = Client.handleOne();
412 EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
415 ServerThread.join();
418 TEST(DummyRPC, TestCallAsyncVoidString) {
419 auto Channels = createPairedQueueChannels();
420 DummyRPCEndpoint Client(*Channels.first);
421 DummyRPCEndpoint Server(*Channels.second);
423 std::thread ServerThread([&]() {
424 Server.addHandler<DummyRPCAPI::VoidString>(
425 [](const std::string &S) {
426 EXPECT_EQ(S, "hello")
427 << "Server void(std::string) received unexpected result";
430 // Poke the server to handle the negotiate call.
431 for (int I = 0; I < 4; ++I) {
432 auto Err = Server.handleOne();
433 EXPECT_FALSE(!!Err) << "Server failed to handle call";
438 // Make an call using a std::string.
439 auto Err = Client.callB<DummyRPCAPI::VoidString>(std::string("hello"));
440 EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(std::string)";
444 // Make an call using a std::string.
445 auto Err = Client.callB<DummyRPCAPI::VoidString>(StringRef("hello"));
446 EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(std::string)";
450 // Make an call using a std::string.
451 auto Err = Client.callB<DummyRPCAPI::VoidString>("hello");
452 EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(string)";
455 ServerThread.join();
458 TEST(DummyRPC, TestSerialization) {
459 auto Channels = createPairedQueueChannels();
460 DummyRPCEndpoint Client(*Channels.first);
461 DummyRPCEndpoint Server(*Channels.second);
463 std::thread ServerThread([&]() {
464 Server.addHandler<DummyRPCAPI::AllTheTypes>([&](int8_t S8, uint8_t U8,
465 int16_t S16, uint16_t U16,
466 int32_t S32, uint32_t U32,
467 int64_t S64, uint64_t U64,
468 bool B, std::string S,
469 std::vector<int> V,
470 std::set<int> S2,
471 std::map<int, bool> M) {
472 EXPECT_EQ(S8, -101) << "int8_t serialization broken";
473 EXPECT_EQ(U8, 250) << "uint8_t serialization broken";
474 EXPECT_EQ(S16, -10000) << "int16_t serialization broken";
475 EXPECT_EQ(U16, 10000) << "uint16_t serialization broken";
476 EXPECT_EQ(S32, -1000000000) << "int32_t serialization broken";
477 EXPECT_EQ(U32, 1000000000ULL) << "uint32_t serialization broken";
478 EXPECT_EQ(S64, -10000000000) << "int64_t serialization broken";
479 EXPECT_EQ(U64, 10000000000ULL) << "uint64_t serialization broken";
480 EXPECT_EQ(B, true) << "bool serialization broken";
481 EXPECT_EQ(S, "foo") << "std::string serialization broken";
482 EXPECT_EQ(V, std::vector<int>({42, 7}))
483 << "std::vector serialization broken";
484 EXPECT_EQ(S2, std::set<int>({7, 42})) << "std::set serialization broken";
485 EXPECT_EQ(M, (std::map<int, bool>({{7, false}, {42, true}})))
486 << "std::map serialization broken";
487 return Error::success();
491 // Poke the server to handle the negotiate call.
492 auto Err = Server.handleOne();
493 EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
497 // Poke the server to handle the AllTheTypes call.
498 auto Err = Server.handleOne();
499 EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
504 // Make an async call.
505 std::vector<int> V({42, 7});
506 std::set<int> S({7, 42});
507 std::map<int, bool> M({{7, false}, {42, true}});
508 auto Err = Client.callAsync<DummyRPCAPI::AllTheTypes>(
509 [](Error Err) {
510 EXPECT_FALSE(!!Err) << "Async AllTheTypes response handler failed";
511 return Error::success();
513 static_cast<int8_t>(-101), static_cast<uint8_t>(250),
514 static_cast<int16_t>(-10000), static_cast<uint16_t>(10000),
515 static_cast<int32_t>(-1000000000), static_cast<uint32_t>(1000000000),
516 static_cast<int64_t>(-10000000000), static_cast<uint64_t>(10000000000),
517 true, std::string("foo"), V, S, M);
518 EXPECT_FALSE(!!Err) << "Client.callAsync failed for AllTheTypes";
522 // Poke the client to process the result of the AllTheTypes call.
523 auto Err = Client.handleOne();
524 EXPECT_FALSE(!!Err) << "Client failed to handle response from AllTheTypes";
527 ServerThread.join();
530 TEST(DummyRPC, TestCustomType) {
531 auto Channels = createPairedQueueChannels();
532 DummyRPCEndpoint Client(*Channels.first);
533 DummyRPCEndpoint Server(*Channels.second);
535 std::thread ServerThread([&]() {
536 Server.addHandler<DummyRPCAPI::CustomType>(
537 [](RPCFoo F) {});
540 // Poke the server to handle the negotiate call.
541 auto Err = Server.handleOne();
542 EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
546 // Poke the server to handle the CustomType call.
547 auto Err = Server.handleOne();
548 EXPECT_FALSE(!!Err) << "Server failed to handle call to RPCFoo(RPCFoo)";
553 // Make an async call.
554 auto Err = Client.callAsync<DummyRPCAPI::CustomType>(
555 [](Expected<RPCFoo> FOrErr) {
556 EXPECT_TRUE(!!FOrErr)
557 << "Async RPCFoo(RPCFoo) response handler failed";
558 return Error::success();
559 }, RPCFoo());
560 EXPECT_FALSE(!!Err) << "Client.callAsync failed for RPCFoo(RPCFoo)";
564 // Poke the client to process the result of the RPCFoo() call.
565 auto Err = Client.handleOne();
566 EXPECT_FALSE(!!Err)
567 << "Client failed to handle response from RPCFoo(RPCFoo)";
570 ServerThread.join();
573 TEST(DummyRPC, TestWithAltCustomType) {
574 auto Channels = createPairedQueueChannels();
575 DummyRPCEndpoint Client(*Channels.first);
576 DummyRPCEndpoint Server(*Channels.second);
578 std::thread ServerThread([&]() {
579 Server.addHandler<DummyRPCAPI::CustomType>(
580 [](RPCBar F) {});
583 // Poke the server to handle the negotiate call.
584 auto Err = Server.handleOne();
585 EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
589 // Poke the server to handle the CustomType call.
590 auto Err = Server.handleOne();
591 EXPECT_FALSE(!!Err) << "Server failed to handle call to RPCFoo(RPCFoo)";
596 // Make an async call.
597 auto Err = Client.callAsync<DummyRPCAPI::CustomType>(
598 [](Expected<RPCBar> FOrErr) {
599 EXPECT_TRUE(!!FOrErr)
600 << "Async RPCFoo(RPCFoo) response handler failed";
601 return Error::success();
602 }, RPCBar());
603 EXPECT_FALSE(!!Err) << "Client.callAsync failed for RPCFoo(RPCFoo)";
607 // Poke the client to process the result of the RPCFoo() call.
608 auto Err = Client.handleOne();
609 EXPECT_FALSE(!!Err)
610 << "Client failed to handle response from RPCFoo(RPCFoo)";
613 ServerThread.join();
616 TEST(DummyRPC, ReturnErrorSuccess) {
617 registerDummyErrorSerialization<QueueChannel>();
619 auto Channels = createPairedQueueChannels();
620 DummyRPCEndpoint Client(*Channels.first);
621 DummyRPCEndpoint Server(*Channels.second);
623 std::thread ServerThread([&]() {
624 Server.addHandler<DummyRPCAPI::ErrorFunc>(
625 []() {
626 return Error::success();
629 // Handle the negotiate plus one call.
630 for (unsigned I = 0; I != 2; ++I)
631 cantFail(Server.handleOne());
634 cantFail(Client.callAsync<DummyRPCAPI::ErrorFunc>(
635 [&](Error Err) {
636 EXPECT_FALSE(!!Err) << "Expected success value";
637 return Error::success();
638 }));
640 cantFail(Client.handleOne());
642 ServerThread.join();
645 TEST(DummyRPC, ReturnErrorFailure) {
646 registerDummyErrorSerialization<QueueChannel>();
648 auto Channels = createPairedQueueChannels();
649 DummyRPCEndpoint Client(*Channels.first);
650 DummyRPCEndpoint Server(*Channels.second);
652 std::thread ServerThread([&]() {
653 Server.addHandler<DummyRPCAPI::ErrorFunc>(
654 []() {
655 return make_error<DummyError>(42);
658 // Handle the negotiate plus one call.
659 for (unsigned I = 0; I != 2; ++I)
660 cantFail(Server.handleOne());
663 cantFail(Client.callAsync<DummyRPCAPI::ErrorFunc>(
664 [&](Error Err) {
665 EXPECT_TRUE(Err.isA<DummyError>())
666 << "Incorrect error type";
667 return handleErrors(
668 std::move(Err),
669 [](const DummyError &DE) {
670 EXPECT_EQ(DE.getValue(), 42ULL)
671 << "Incorrect DummyError serialization";
673 }));
675 cantFail(Client.handleOne());
677 ServerThread.join();
680 TEST(DummyRPC, ReturnExpectedSuccess) {
681 registerDummyErrorSerialization<QueueChannel>();
683 auto Channels = createPairedQueueChannels();
684 DummyRPCEndpoint Client(*Channels.first);
685 DummyRPCEndpoint Server(*Channels.second);
687 std::thread ServerThread([&]() {
688 Server.addHandler<DummyRPCAPI::ExpectedFunc>(
689 []() -> uint32_t {
690 return 42;
693 // Handle the negotiate plus one call.
694 for (unsigned I = 0; I != 2; ++I)
695 cantFail(Server.handleOne());
698 cantFail(Client.callAsync<DummyRPCAPI::ExpectedFunc>(
699 [&](Expected<uint32_t> ValOrErr) {
700 EXPECT_TRUE(!!ValOrErr)
701 << "Expected success value";
702 EXPECT_EQ(*ValOrErr, 42ULL)
703 << "Incorrect Expected<uint32_t> deserialization";
704 return Error::success();
705 }));
707 cantFail(Client.handleOne());
709 ServerThread.join();
712 TEST(DummyRPC, ReturnExpectedFailure) {
713 registerDummyErrorSerialization<QueueChannel>();
715 auto Channels = createPairedQueueChannels();
716 DummyRPCEndpoint Client(*Channels.first);
717 DummyRPCEndpoint Server(*Channels.second);
719 std::thread ServerThread([&]() {
720 Server.addHandler<DummyRPCAPI::ExpectedFunc>(
721 []() -> Expected<uint32_t> {
722 return make_error<DummyError>(7);
725 // Handle the negotiate plus one call.
726 for (unsigned I = 0; I != 2; ++I)
727 cantFail(Server.handleOne());
730 cantFail(Client.callAsync<DummyRPCAPI::ExpectedFunc>(
731 [&](Expected<uint32_t> ValOrErr) {
732 EXPECT_FALSE(!!ValOrErr)
733 << "Expected failure value";
734 auto Err = ValOrErr.takeError();
735 EXPECT_TRUE(Err.isA<DummyError>())
736 << "Incorrect error type";
737 return handleErrors(
738 std::move(Err),
739 [](const DummyError &DE) {
740 EXPECT_EQ(DE.getValue(), 7ULL)
741 << "Incorrect DummyError serialization";
743 }));
745 cantFail(Client.handleOne());
747 ServerThread.join();
750 TEST(DummyRPC, TestParallelCallGroup) {
751 auto Channels = createPairedQueueChannels();
752 DummyRPCEndpoint Client(*Channels.first);
753 DummyRPCEndpoint Server(*Channels.second);
755 std::thread ServerThread([&]() {
756 Server.addHandler<DummyRPCAPI::IntInt>(
757 [](int X) -> int {
758 return 2 * X;
761 // Handle the negotiate, plus three calls.
762 for (unsigned I = 0; I != 4; ++I) {
763 auto Err = Server.handleOne();
764 EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)";
769 int A, B, C;
770 ParallelCallGroup PCG;
773 auto Err = PCG.call(
774 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
775 [&A](Expected<int> Result) {
776 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
777 A = *Result;
778 return Error::success();
779 }, 1);
780 EXPECT_FALSE(!!Err) << "First parallel call failed for int(int)";
784 auto Err = PCG.call(
785 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
786 [&B](Expected<int> Result) {
787 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
788 B = *Result;
789 return Error::success();
790 }, 2);
791 EXPECT_FALSE(!!Err) << "Second parallel call failed for int(int)";
795 auto Err = PCG.call(
796 rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
797 [&C](Expected<int> Result) {
798 EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
799 C = *Result;
800 return Error::success();
801 }, 3);
802 EXPECT_FALSE(!!Err) << "Third parallel call failed for int(int)";
805 // Handle the three int(int) results.
806 for (unsigned I = 0; I != 3; ++I) {
807 auto Err = Client.handleOne();
808 EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
811 PCG.wait();
813 EXPECT_EQ(A, 2) << "First parallel call returned bogus result";
814 EXPECT_EQ(B, 4) << "Second parallel call returned bogus result";
815 EXPECT_EQ(C, 6) << "Third parallel call returned bogus result";
818 ServerThread.join();
821 TEST(DummyRPC, TestAPICalls) {
823 using DummyCalls1 = APICalls<DummyRPCAPI::VoidBool, DummyRPCAPI::IntInt>;
824 using DummyCalls2 = APICalls<DummyRPCAPI::AllTheTypes>;
825 using DummyCalls3 = APICalls<DummyCalls1, DummyRPCAPI::CustomType>;
826 using DummyCallsAll = APICalls<DummyCalls1, DummyCalls2, DummyRPCAPI::CustomType>;
828 static_assert(DummyCalls1::Contains<DummyRPCAPI::VoidBool>::value,
829 "Contains<Func> template should return true here");
830 static_assert(!DummyCalls1::Contains<DummyRPCAPI::CustomType>::value,
831 "Contains<Func> template should return false here");
833 auto Channels = createPairedQueueChannels();
834 DummyRPCEndpoint Client(*Channels.first);
835 DummyRPCEndpoint Server(*Channels.second);
837 std::thread ServerThread(
838 [&]() {
839 Server.addHandler<DummyRPCAPI::VoidBool>([](bool b) { });
840 Server.addHandler<DummyRPCAPI::IntInt>([](int x) { return x; });
841 Server.addHandler<DummyRPCAPI::CustomType>([](RPCFoo F) {});
843 for (unsigned I = 0; I < 4; ++I) {
844 auto Err = Server.handleOne();
845 (void)!!Err;
850 auto Err = DummyCalls1::negotiate(Client);
851 EXPECT_FALSE(!!Err) << "DummyCalls1::negotiate failed";
855 auto Err = DummyCalls3::negotiate(Client);
856 EXPECT_FALSE(!!Err) << "DummyCalls3::negotiate failed";
860 auto Err = DummyCallsAll::negotiate(Client);
861 EXPECT_TRUE(Err.isA<CouldNotNegotiate>())
862 << "Expected CouldNotNegotiate error for attempted negotiate of "
863 "unsupported function";
864 consumeError(std::move(Err));
867 ServerThread.join();
870 TEST(DummyRPC, TestRemoveHandler) {
871 auto Channels = createPairedQueueChannels();
872 DummyRPCEndpoint Server(*Channels.second);
874 Server.addHandler<DummyRPCAPI::VoidBool>(
875 [](bool B) {
876 EXPECT_EQ(B, true)
877 << "Server void(bool) received unexpected result";
880 Server.removeHandler<DummyRPCAPI::VoidBool>();
883 TEST(DummyRPC, TestClearHandlers) {
884 auto Channels = createPairedQueueChannels();
885 DummyRPCEndpoint Server(*Channels.second);
887 Server.addHandler<DummyRPCAPI::VoidBool>(
888 [](bool B) {
889 EXPECT_EQ(B, true)
890 << "Server void(bool) received unexpected result";
893 Server.clearHandlers();