1 //===----------- RPCUtilsTest.cpp - Unit tests the Orc RPC utils ----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/ExecutionEngine/Orc/RPCUtils.h"
11 #include "QueueChannel.h"
12 #include "gtest/gtest.h"
13 
14 #include <queue>
15 
16 using namespace llvm;
17 using namespace llvm::orc;
18 using namespace llvm::orc::rpc;
19 
20 class RPCFoo {};
21 
22 namespace llvm {
23 namespace orc {
24 namespace rpc {
25 
26   template <>
27   class RPCTypeName<RPCFoo> {
28   public:
getName()29     static const char* getName() { return "RPCFoo"; }
30   };
31 
32   template <>
33   class SerializationTraits<QueueChannel, RPCFoo, RPCFoo> {
34   public:
serialize(QueueChannel &,const RPCFoo &)35     static Error serialize(QueueChannel&, const RPCFoo&) {
36       return Error::success();
37     }
38 
deserialize(QueueChannel &,RPCFoo &)39     static Error deserialize(QueueChannel&, RPCFoo&) {
40       return Error::success();
41     }
42   };
43 
44 } // end namespace rpc
45 } // end namespace orc
46 } // end namespace llvm
47 
48 class RPCBar {};
49 
50 class DummyError : public ErrorInfo<DummyError> {
51 public:
52 
53   static char ID;
54 
DummyError(uint32_t Val)55   DummyError(uint32_t Val) : Val(Val) {}
56 
convertToErrorCode() const57   std::error_code convertToErrorCode() const override {
58     // Use a nonsense error code - we want to verify that errors
59     // transmitted over the network are replaced with
60     // OrcErrorCode::UnknownErrorCodeFromRemote.
61     return orcError(OrcErrorCode::RemoteAllocatorDoesNotExist);
62   }
63 
log(raw_ostream & OS) const64   void log(raw_ostream &OS) const override {
65     OS << "Dummy error " << Val;
66   }
67 
getValue() const68   uint32_t getValue() const { return Val; }
69 
70 public:
71   uint32_t Val;
72 };
73 
74 char DummyError::ID = 0;
75 
76 template <typename ChannelT>
registerDummyErrorSerialization()77 void registerDummyErrorSerialization() {
78   static bool AlreadyRegistered = false;
79   if (!AlreadyRegistered) {
80     SerializationTraits<ChannelT, Error>::
81       template registerErrorType<DummyError>(
82         "DummyError",
83         [](ChannelT &C, const DummyError &DE) {
84           return serializeSeq(C, DE.getValue());
85         },
86         [](ChannelT &C, Error &Err) -> Error {
87           ErrorAsOutParameter EAO(&Err);
88           uint32_t Val;
89           if (auto Err = deserializeSeq(C, Val))
90             return Err;
91           Err = make_error<DummyError>(Val);
92           return Error::success();
93         });
94     AlreadyRegistered = true;
95   }
96 }
97 
98 namespace llvm {
99 namespace orc {
100 namespace rpc {
101 
102   template <>
103   class SerializationTraits<QueueChannel, RPCFoo, RPCBar> {
104   public:
serialize(QueueChannel &,const RPCBar &)105     static Error serialize(QueueChannel&, const RPCBar&) {
106       return Error::success();
107     }
108 
deserialize(QueueChannel &,RPCBar &)109     static Error deserialize(QueueChannel&, RPCBar&) {
110       return Error::success();
111     }
112 };
113 
114 } // end namespace rpc
115 } // end namespace orc
116 } // end namespace llvm
117 
118 namespace DummyRPCAPI {
119 
120   class VoidBool : public Function<VoidBool, void(bool)> {
121   public:
getName()122     static const char* getName() { return "VoidBool"; }
123   };
124 
125   class IntInt : public Function<IntInt, int32_t(int32_t)> {
126   public:
getName()127     static const char* getName() { return "IntInt"; }
128   };
129 
130   class VoidString : public Function<VoidString, void(std::string)> {
131   public:
getName()132     static const char* getName() { return "VoidString"; }
133   };
134 
135   class AllTheTypes
136       : public Function<AllTheTypes, void(int8_t, uint8_t, int16_t, uint16_t,
137                                           int32_t, uint32_t, int64_t, uint64_t,
138                                           bool, std::string, std::vector<int>,
139                                           std::set<int>, std::map<int, bool>)> {
140   public:
getName()141     static const char* getName() { return "AllTheTypes"; }
142   };
143 
144   class CustomType : public Function<CustomType, RPCFoo(RPCFoo)> {
145   public:
getName()146     static const char* getName() { return "CustomType"; }
147   };
148 
149   class ErrorFunc : public Function<ErrorFunc, Error()> {
150   public:
getName()151     static const char* getName() { return "ErrorFunc"; }
152   };
153 
154   class ExpectedFunc : public Function<ExpectedFunc, Expected<uint32_t>()> {
155   public:
getName()156     static const char* getName() { return "ExpectedFunc"; }
157   };
158 
159 }
160 
161 class DummyRPCEndpoint : public SingleThreadedRPCEndpoint<QueueChannel> {
162 public:
DummyRPCEndpoint(QueueChannel & C)163   DummyRPCEndpoint(QueueChannel &C)
164       : SingleThreadedRPCEndpoint(C, true) {}
165 };
166 
167 
freeVoidBool(bool B)168 void freeVoidBool(bool B) {
169 }
170 
TEST(DummyRPC,TestFreeFunctionHandler)171 TEST(DummyRPC, TestFreeFunctionHandler) {
172   auto Channels = createPairedQueueChannels();
173   DummyRPCEndpoint Server(*Channels.first);
174   Server.addHandler<DummyRPCAPI::VoidBool>(freeVoidBool);
175 }
176 
TEST(DummyRPC,TestCallAsyncVoidBool)177 TEST(DummyRPC, TestCallAsyncVoidBool) {
178   auto Channels = createPairedQueueChannels();
179   DummyRPCEndpoint Client(*Channels.first);
180   DummyRPCEndpoint Server(*Channels.second);
181 
182   std::thread ServerThread([&]() {
183       Server.addHandler<DummyRPCAPI::VoidBool>(
184           [](bool B) {
185             EXPECT_EQ(B, true)
186               << "Server void(bool) received unexpected result";
187           });
188 
189       {
190         // Poke the server to handle the negotiate call.
191         auto Err = Server.handleOne();
192         EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
193       }
194 
195       {
196         // Poke the server to handle the VoidBool call.
197         auto Err = Server.handleOne();
198         EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
199       }
200   });
201 
202   {
203     // Make an async call.
204     auto Err = Client.callAsync<DummyRPCAPI::VoidBool>(
205         [](Error Err) {
206           EXPECT_FALSE(!!Err) << "Async void(bool) response handler failed";
207           return Error::success();
208         }, true);
209     EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)";
210   }
211 
212   {
213     // Poke the client to process the result of the void(bool) call.
214     auto Err = Client.handleOne();
215     EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
216   }
217 
218   ServerThread.join();
219 }
220 
TEST(DummyRPC,TestCallAsyncIntInt)221 TEST(DummyRPC, TestCallAsyncIntInt) {
222   auto Channels = createPairedQueueChannels();
223   DummyRPCEndpoint Client(*Channels.first);
224   DummyRPCEndpoint Server(*Channels.second);
225 
226   std::thread ServerThread([&]() {
227       Server.addHandler<DummyRPCAPI::IntInt>(
228           [](int X) -> int {
229             EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
230             return 2 * X;
231           });
232 
233       {
234         // Poke the server to handle the negotiate call.
235         auto Err = Server.handleOne();
236         EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
237       }
238 
239       {
240         // Poke the server to handle the int(int) call.
241         auto Err = Server.handleOne();
242         EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)";
243       }
244     });
245 
246   {
247     auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
248         [](Expected<int> Result) {
249           EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
250           EXPECT_EQ(*Result, 42)
251             << "Async int(int) response handler received incorrect result";
252           return Error::success();
253         }, 21);
254     EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
255   }
256 
257   {
258     // Poke the client to process the result.
259     auto Err = Client.handleOne();
260     EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
261   }
262 
263   ServerThread.join();
264 }
265 
TEST(DummyRPC,TestAsyncVoidBoolHandler)266 TEST(DummyRPC, TestAsyncVoidBoolHandler) {
267   auto Channels = createPairedQueueChannels();
268   DummyRPCEndpoint Client(*Channels.first);
269   DummyRPCEndpoint Server(*Channels.second);
270 
271   std::thread ServerThread([&]() {
272       Server.addAsyncHandler<DummyRPCAPI::VoidBool>(
273           [](std::function<Error(Error)> SendResult,
274              bool B) {
275             EXPECT_EQ(B, true) << "Server void(bool) receieved unexpected result";
276             cantFail(SendResult(Error::success()));
277             return Error::success();
278           });
279 
280       {
281         // Poke the server to handle the negotiate call.
282         auto Err = Server.handleOne();
283         EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
284       }
285 
286       {
287         // Poke the server to handle the VoidBool call.
288         auto Err = Server.handleOne();
289         EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
290       }
291   });
292 
293   {
294     auto Err = Client.callAsync<DummyRPCAPI::VoidBool>(
295         [](Error Result) {
296           EXPECT_FALSE(!!Result) << "Async void(bool) response handler failed";
297           return Error::success();
298         }, true);
299     EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(bool)";
300   }
301 
302   {
303     // Poke the client to process the result.
304     auto Err = Client.handleOne();
305     EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
306   }
307 
308   ServerThread.join();
309 }
310 
TEST(DummyRPC,TestAsyncIntIntHandler)311 TEST(DummyRPC, TestAsyncIntIntHandler) {
312   auto Channels = createPairedQueueChannels();
313   DummyRPCEndpoint Client(*Channels.first);
314   DummyRPCEndpoint Server(*Channels.second);
315 
316   std::thread ServerThread([&]() {
317       Server.addAsyncHandler<DummyRPCAPI::IntInt>(
318           [](std::function<Error(Expected<int32_t>)> SendResult,
319              int32_t X) {
320             EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
321             return SendResult(2 * X);
322           });
323 
324       {
325         // Poke the server to handle the negotiate call.
326         auto Err = Server.handleOne();
327         EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
328       }
329 
330       {
331         // Poke the server to handle the VoidBool call.
332         auto Err = Server.handleOne();
333         EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
334       }
335   });
336 
337   {
338     auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
339         [](Expected<int> Result) {
340           EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
341           EXPECT_EQ(*Result, 42)
342             << "Async int(int) response handler received incorrect result";
343           return Error::success();
344         }, 21);
345     EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
346   }
347 
348   {
349     // Poke the client to process the result.
350     auto Err = Client.handleOne();
351     EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
352   }
353 
354   ServerThread.join();
355 }
356 
TEST(DummyRPC,TestAsyncIntIntHandlerMethod)357 TEST(DummyRPC, TestAsyncIntIntHandlerMethod) {
358   auto Channels = createPairedQueueChannels();
359   DummyRPCEndpoint Client(*Channels.first);
360   DummyRPCEndpoint Server(*Channels.second);
361 
362   class Dummy {
363   public:
364     Error handler(std::function<Error(Expected<int32_t>)> SendResult,
365              int32_t X) {
366       EXPECT_EQ(X, 21) << "Server int(int) receieved unexpected result";
367       return SendResult(2 * X);
368     }
369   };
370 
371   std::thread ServerThread([&]() {
372       Dummy D;
373       Server.addAsyncHandler<DummyRPCAPI::IntInt>(D, &Dummy::handler);
374 
375       {
376         // Poke the server to handle the negotiate call.
377         auto Err = Server.handleOne();
378         EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
379       }
380 
381       {
382         // Poke the server to handle the VoidBool call.
383         auto Err = Server.handleOne();
384         EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
385       }
386   });
387 
388   {
389     auto Err = Client.callAsync<DummyRPCAPI::IntInt>(
390         [](Expected<int> Result) {
391           EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
392           EXPECT_EQ(*Result, 42)
393             << "Async int(int) response handler received incorrect result";
394           return Error::success();
395         }, 21);
396     EXPECT_FALSE(!!Err) << "Client.callAsync failed for int(int)";
397   }
398 
399   {
400     // Poke the client to process the result.
401     auto Err = Client.handleOne();
402     EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
403   }
404 
405   ServerThread.join();
406 }
407 
TEST(DummyRPC,TestCallAsyncVoidString)408 TEST(DummyRPC, TestCallAsyncVoidString) {
409   auto Channels = createPairedQueueChannels();
410   DummyRPCEndpoint Client(*Channels.first);
411   DummyRPCEndpoint Server(*Channels.second);
412 
413   std::thread ServerThread([&]() {
414       Server.addHandler<DummyRPCAPI::VoidString>(
415           [](const std::string &S) {
416             EXPECT_EQ(S, "hello")
417               << "Server void(std::string) received unexpected result";
418           });
419 
420       // Poke the server to handle the negotiate call.
421       for (int I = 0; I < 4; ++I) {
422         auto Err = Server.handleOne();
423         EXPECT_FALSE(!!Err) << "Server failed to handle call";
424       }
425   });
426 
427   {
428     // Make an call using a std::string.
429     auto Err = Client.callB<DummyRPCAPI::VoidString>(std::string("hello"));
430     EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(std::string)";
431   }
432 
433   {
434     // Make an call using a std::string.
435     auto Err = Client.callB<DummyRPCAPI::VoidString>(StringRef("hello"));
436     EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(std::string)";
437   }
438 
439   {
440     // Make an call using a std::string.
441     auto Err = Client.callB<DummyRPCAPI::VoidString>("hello");
442     EXPECT_FALSE(!!Err) << "Client.callAsync failed for void(string)";
443   }
444 
445   ServerThread.join();
446 }
447 
TEST(DummyRPC,TestSerialization)448 TEST(DummyRPC, TestSerialization) {
449   auto Channels = createPairedQueueChannels();
450   DummyRPCEndpoint Client(*Channels.first);
451   DummyRPCEndpoint Server(*Channels.second);
452 
453   std::thread ServerThread([&]() {
454     Server.addHandler<DummyRPCAPI::AllTheTypes>([&](int8_t S8, uint8_t U8,
455                                                     int16_t S16, uint16_t U16,
456                                                     int32_t S32, uint32_t U32,
457                                                     int64_t S64, uint64_t U64,
458                                                     bool B, std::string S,
459                                                     std::vector<int> V,
460                                                     std::set<int> S2,
461                                                     std::map<int, bool> M) {
462       EXPECT_EQ(S8, -101) << "int8_t serialization broken";
463       EXPECT_EQ(U8, 250) << "uint8_t serialization broken";
464       EXPECT_EQ(S16, -10000) << "int16_t serialization broken";
465       EXPECT_EQ(U16, 10000) << "uint16_t serialization broken";
466       EXPECT_EQ(S32, -1000000000) << "int32_t serialization broken";
467       EXPECT_EQ(U32, 1000000000ULL) << "uint32_t serialization broken";
468       EXPECT_EQ(S64, -10000000000) << "int64_t serialization broken";
469       EXPECT_EQ(U64, 10000000000ULL) << "uint64_t serialization broken";
470       EXPECT_EQ(B, true) << "bool serialization broken";
471       EXPECT_EQ(S, "foo") << "std::string serialization broken";
472       EXPECT_EQ(V, std::vector<int>({42, 7}))
473           << "std::vector serialization broken";
474       EXPECT_EQ(S2, std::set<int>({7, 42})) << "std::set serialization broken";
475       EXPECT_EQ(M, (std::map<int, bool>({{7, false}, {42, true}})))
476           << "std::map serialization broken";
477       return Error::success();
478     });
479 
480     {
481       // Poke the server to handle the negotiate call.
482       auto Err = Server.handleOne();
483       EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
484     }
485 
486     {
487       // Poke the server to handle the AllTheTypes call.
488       auto Err = Server.handleOne();
489       EXPECT_FALSE(!!Err) << "Server failed to handle call to void(bool)";
490     }
491   });
492 
493   {
494     // Make an async call.
495     std::vector<int> V({42, 7});
496     std::set<int> S({7, 42});
497     std::map<int, bool> M({{7, false}, {42, true}});
498     auto Err = Client.callAsync<DummyRPCAPI::AllTheTypes>(
499         [](Error Err) {
500           EXPECT_FALSE(!!Err) << "Async AllTheTypes response handler failed";
501           return Error::success();
502         },
503         static_cast<int8_t>(-101), static_cast<uint8_t>(250),
504         static_cast<int16_t>(-10000), static_cast<uint16_t>(10000),
505         static_cast<int32_t>(-1000000000), static_cast<uint32_t>(1000000000),
506         static_cast<int64_t>(-10000000000), static_cast<uint64_t>(10000000000),
507         true, std::string("foo"), V, S, M);
508     EXPECT_FALSE(!!Err) << "Client.callAsync failed for AllTheTypes";
509   }
510 
511   {
512     // Poke the client to process the result of the AllTheTypes call.
513     auto Err = Client.handleOne();
514     EXPECT_FALSE(!!Err) << "Client failed to handle response from AllTheTypes";
515   }
516 
517   ServerThread.join();
518 }
519 
TEST(DummyRPC,TestCustomType)520 TEST(DummyRPC, TestCustomType) {
521   auto Channels = createPairedQueueChannels();
522   DummyRPCEndpoint Client(*Channels.first);
523   DummyRPCEndpoint Server(*Channels.second);
524 
525   std::thread ServerThread([&]() {
526       Server.addHandler<DummyRPCAPI::CustomType>(
527           [](RPCFoo F) {});
528 
529       {
530         // Poke the server to handle the negotiate call.
531         auto Err = Server.handleOne();
532         EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
533       }
534 
535       {
536         // Poke the server to handle the CustomType call.
537         auto Err = Server.handleOne();
538         EXPECT_FALSE(!!Err) << "Server failed to handle call to RPCFoo(RPCFoo)";
539       }
540   });
541 
542   {
543     // Make an async call.
544     auto Err = Client.callAsync<DummyRPCAPI::CustomType>(
545         [](Expected<RPCFoo> FOrErr) {
546           EXPECT_TRUE(!!FOrErr)
547             << "Async RPCFoo(RPCFoo) response handler failed";
548           return Error::success();
549         }, RPCFoo());
550     EXPECT_FALSE(!!Err) << "Client.callAsync failed for RPCFoo(RPCFoo)";
551   }
552 
553   {
554     // Poke the client to process the result of the RPCFoo() call.
555     auto Err = Client.handleOne();
556     EXPECT_FALSE(!!Err)
557       << "Client failed to handle response from RPCFoo(RPCFoo)";
558   }
559 
560   ServerThread.join();
561 }
562 
TEST(DummyRPC,TestWithAltCustomType)563 TEST(DummyRPC, TestWithAltCustomType) {
564   auto Channels = createPairedQueueChannels();
565   DummyRPCEndpoint Client(*Channels.first);
566   DummyRPCEndpoint Server(*Channels.second);
567 
568   std::thread ServerThread([&]() {
569       Server.addHandler<DummyRPCAPI::CustomType>(
570           [](RPCBar F) {});
571 
572       {
573         // Poke the server to handle the negotiate call.
574         auto Err = Server.handleOne();
575         EXPECT_FALSE(!!Err) << "Server failed to handle call to negotiate";
576       }
577 
578       {
579         // Poke the server to handle the CustomType call.
580         auto Err = Server.handleOne();
581         EXPECT_FALSE(!!Err) << "Server failed to handle call to RPCFoo(RPCFoo)";
582       }
583   });
584 
585   {
586     // Make an async call.
587     auto Err = Client.callAsync<DummyRPCAPI::CustomType>(
588         [](Expected<RPCBar> FOrErr) {
589           EXPECT_TRUE(!!FOrErr)
590             << "Async RPCFoo(RPCFoo) response handler failed";
591           return Error::success();
592         }, RPCBar());
593     EXPECT_FALSE(!!Err) << "Client.callAsync failed for RPCFoo(RPCFoo)";
594   }
595 
596   {
597     // Poke the client to process the result of the RPCFoo() call.
598     auto Err = Client.handleOne();
599     EXPECT_FALSE(!!Err)
600       << "Client failed to handle response from RPCFoo(RPCFoo)";
601   }
602 
603   ServerThread.join();
604 }
605 
TEST(DummyRPC,ReturnErrorSuccess)606 TEST(DummyRPC, ReturnErrorSuccess) {
607   registerDummyErrorSerialization<QueueChannel>();
608 
609   auto Channels = createPairedQueueChannels();
610   DummyRPCEndpoint Client(*Channels.first);
611   DummyRPCEndpoint Server(*Channels.second);
612 
613   std::thread ServerThread([&]() {
614       Server.addHandler<DummyRPCAPI::ErrorFunc>(
615         []() {
616           return Error::success();
617         });
618 
619       // Handle the negotiate plus one call.
620       for (unsigned I = 0; I != 2; ++I)
621         cantFail(Server.handleOne());
622     });
623 
624   cantFail(Client.callAsync<DummyRPCAPI::ErrorFunc>(
625              [&](Error Err) {
626                EXPECT_FALSE(!!Err) << "Expected success value";
627                return Error::success();
628              }));
629 
630   cantFail(Client.handleOne());
631 
632   ServerThread.join();
633 }
634 
TEST(DummyRPC,ReturnErrorFailure)635 TEST(DummyRPC, ReturnErrorFailure) {
636   registerDummyErrorSerialization<QueueChannel>();
637 
638   auto Channels = createPairedQueueChannels();
639   DummyRPCEndpoint Client(*Channels.first);
640   DummyRPCEndpoint Server(*Channels.second);
641 
642   std::thread ServerThread([&]() {
643       Server.addHandler<DummyRPCAPI::ErrorFunc>(
644         []() {
645           return make_error<DummyError>(42);
646         });
647 
648       // Handle the negotiate plus one call.
649       for (unsigned I = 0; I != 2; ++I)
650         cantFail(Server.handleOne());
651     });
652 
653   cantFail(Client.callAsync<DummyRPCAPI::ErrorFunc>(
654              [&](Error Err) {
655                EXPECT_TRUE(Err.isA<DummyError>())
656                  << "Incorrect error type";
657                return handleErrors(
658                         std::move(Err),
659                         [](const DummyError &DE) {
660                           EXPECT_EQ(DE.getValue(), 42ULL)
661                             << "Incorrect DummyError serialization";
662                         });
663              }));
664 
665   cantFail(Client.handleOne());
666 
667   ServerThread.join();
668 }
669 
TEST(DummyRPC,ReturnExpectedSuccess)670 TEST(DummyRPC, ReturnExpectedSuccess) {
671   registerDummyErrorSerialization<QueueChannel>();
672 
673   auto Channels = createPairedQueueChannels();
674   DummyRPCEndpoint Client(*Channels.first);
675   DummyRPCEndpoint Server(*Channels.second);
676 
677   std::thread ServerThread([&]() {
678       Server.addHandler<DummyRPCAPI::ExpectedFunc>(
679         []() -> uint32_t {
680           return 42;
681         });
682 
683       // Handle the negotiate plus one call.
684       for (unsigned I = 0; I != 2; ++I)
685         cantFail(Server.handleOne());
686     });
687 
688   cantFail(Client.callAsync<DummyRPCAPI::ExpectedFunc>(
689                [&](Expected<uint32_t> ValOrErr) {
690                  EXPECT_TRUE(!!ValOrErr)
691                    << "Expected success value";
692                  EXPECT_EQ(*ValOrErr, 42ULL)
693                    << "Incorrect Expected<uint32_t> deserialization";
694                  return Error::success();
695                }));
696 
697   cantFail(Client.handleOne());
698 
699   ServerThread.join();
700 }
701 
TEST(DummyRPC,ReturnExpectedFailure)702 TEST(DummyRPC, ReturnExpectedFailure) {
703   registerDummyErrorSerialization<QueueChannel>();
704 
705   auto Channels = createPairedQueueChannels();
706   DummyRPCEndpoint Client(*Channels.first);
707   DummyRPCEndpoint Server(*Channels.second);
708 
709   std::thread ServerThread([&]() {
710       Server.addHandler<DummyRPCAPI::ExpectedFunc>(
711         []() -> Expected<uint32_t> {
712           return make_error<DummyError>(7);
713         });
714 
715       // Handle the negotiate plus one call.
716       for (unsigned I = 0; I != 2; ++I)
717         cantFail(Server.handleOne());
718     });
719 
720   cantFail(Client.callAsync<DummyRPCAPI::ExpectedFunc>(
721                [&](Expected<uint32_t> ValOrErr) {
722                  EXPECT_FALSE(!!ValOrErr)
723                    << "Expected failure value";
724                  auto Err = ValOrErr.takeError();
725                  EXPECT_TRUE(Err.isA<DummyError>())
726                    << "Incorrect error type";
727                  return handleErrors(
728                           std::move(Err),
729                           [](const DummyError &DE) {
730                             EXPECT_EQ(DE.getValue(), 7ULL)
731                               << "Incorrect DummyError serialization";
732                           });
733                }));
734 
735   cantFail(Client.handleOne());
736 
737   ServerThread.join();
738 }
739 
TEST(DummyRPC,TestParallelCallGroup)740 TEST(DummyRPC, TestParallelCallGroup) {
741   auto Channels = createPairedQueueChannels();
742   DummyRPCEndpoint Client(*Channels.first);
743   DummyRPCEndpoint Server(*Channels.second);
744 
745   std::thread ServerThread([&]() {
746       Server.addHandler<DummyRPCAPI::IntInt>(
747           [](int X) -> int {
748             return 2 * X;
749           });
750 
751       // Handle the negotiate, plus three calls.
752       for (unsigned I = 0; I != 4; ++I) {
753         auto Err = Server.handleOne();
754         EXPECT_FALSE(!!Err) << "Server failed to handle call to int(int)";
755       }
756     });
757 
758   {
759     int A, B, C;
760     ParallelCallGroup PCG;
761 
762     {
763       auto Err = PCG.call(
764         rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
765         [&A](Expected<int> Result) {
766           EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
767           A = *Result;
768           return Error::success();
769         }, 1);
770       EXPECT_FALSE(!!Err) << "First parallel call failed for int(int)";
771     }
772 
773     {
774       auto Err = PCG.call(
775         rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
776         [&B](Expected<int> Result) {
777           EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
778           B = *Result;
779           return Error::success();
780         }, 2);
781       EXPECT_FALSE(!!Err) << "Second parallel call failed for int(int)";
782     }
783 
784     {
785       auto Err = PCG.call(
786         rpcAsyncDispatch<DummyRPCAPI::IntInt>(Client),
787         [&C](Expected<int> Result) {
788           EXPECT_TRUE(!!Result) << "Async int(int) response handler failed";
789           C = *Result;
790           return Error::success();
791         }, 3);
792       EXPECT_FALSE(!!Err) << "Third parallel call failed for int(int)";
793     }
794 
795     // Handle the three int(int) results.
796     for (unsigned I = 0; I != 3; ++I) {
797       auto Err = Client.handleOne();
798       EXPECT_FALSE(!!Err) << "Client failed to handle response from void(bool)";
799     }
800 
801     PCG.wait();
802 
803     EXPECT_EQ(A, 2) << "First parallel call returned bogus result";
804     EXPECT_EQ(B, 4) << "Second parallel call returned bogus result";
805     EXPECT_EQ(C, 6) << "Third parallel call returned bogus result";
806   }
807 
808   ServerThread.join();
809 }
810 
TEST(DummyRPC,TestAPICalls)811 TEST(DummyRPC, TestAPICalls) {
812 
813   using DummyCalls1 = APICalls<DummyRPCAPI::VoidBool, DummyRPCAPI::IntInt>;
814   using DummyCalls2 = APICalls<DummyRPCAPI::AllTheTypes>;
815   using DummyCalls3 = APICalls<DummyCalls1, DummyRPCAPI::CustomType>;
816   using DummyCallsAll = APICalls<DummyCalls1, DummyCalls2, DummyRPCAPI::CustomType>;
817 
818   static_assert(DummyCalls1::Contains<DummyRPCAPI::VoidBool>::value,
819                 "Contains<Func> template should return true here");
820   static_assert(!DummyCalls1::Contains<DummyRPCAPI::CustomType>::value,
821                 "Contains<Func> template should return false here");
822 
823   auto Channels = createPairedQueueChannels();
824   DummyRPCEndpoint Client(*Channels.first);
825   DummyRPCEndpoint Server(*Channels.second);
826 
827   std::thread ServerThread(
828     [&]() {
829       Server.addHandler<DummyRPCAPI::VoidBool>([](bool b) { });
830       Server.addHandler<DummyRPCAPI::IntInt>([](int x) { return x; });
831       Server.addHandler<DummyRPCAPI::CustomType>([](RPCFoo F) {});
832 
833       for (unsigned I = 0; I < 4; ++I) {
834         auto Err = Server.handleOne();
835         (void)!!Err;
836       }
837     });
838 
839   {
840     auto Err = DummyCalls1::negotiate(Client);
841     EXPECT_FALSE(!!Err) << "DummyCalls1::negotiate failed";
842   }
843 
844   {
845     auto Err = DummyCalls3::negotiate(Client);
846     EXPECT_FALSE(!!Err) << "DummyCalls3::negotiate failed";
847   }
848 
849   {
850     auto Err = DummyCallsAll::negotiate(Client);
851     EXPECT_TRUE(Err.isA<CouldNotNegotiate>())
852       << "Expected CouldNotNegotiate error for attempted negotiate of "
853          "unsupported function";
854     consumeError(std::move(Err));
855   }
856 
857   ServerThread.join();
858 }
859 
TEST(DummyRPC,TestRemoveHandler)860 TEST(DummyRPC, TestRemoveHandler) {
861   auto Channels = createPairedQueueChannels();
862   DummyRPCEndpoint Server(*Channels.second);
863 
864   Server.addHandler<DummyRPCAPI::VoidBool>(
865     [](bool B) {
866       EXPECT_EQ(B, true)
867         << "Server void(bool) received unexpected result";
868     });
869 
870   Server.removeHandler<DummyRPCAPI::VoidBool>();
871 }
872 
TEST(DummyRPC,TestClearHandlers)873 TEST(DummyRPC, TestClearHandlers) {
874   auto Channels = createPairedQueueChannels();
875   DummyRPCEndpoint Server(*Channels.second);
876 
877   Server.addHandler<DummyRPCAPI::VoidBool>(
878     [](bool B) {
879       EXPECT_EQ(B, true)
880         << "Server void(bool) received unexpected result";
881     });
882 
883   Server.clearHandlers();
884 }
885