RPCUtilsTest.cpp 27 KB

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