blob: 7d55641e4ce2b3fa1b3850e7b501baab601d13d9 [file] [log] [blame]
Lang Hames4d0a5a9e2016-01-11 01:40:11 +00001//===----------- 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/RPCChannel.h"
11#include "llvm/ExecutionEngine/Orc/RPCUtils.h"
12#include "gtest/gtest.h"
13
14#include <queue>
15
16using namespace llvm;
17using namespace llvm::orc;
18using namespace llvm::orc::remote;
19
Lang Hames679c4362016-04-19 04:43:09 +000020class Queue : public std::queue<char> {
21public:
Lang Hames1fa0e0e2016-04-25 21:21:20 +000022 std::mutex &getLock() { return Lock; }
23
Lang Hames679c4362016-04-19 04:43:09 +000024private:
25 std::mutex Lock;
26};
27
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000028class QueueChannel : public RPCChannel {
29public:
Lang Hames679c4362016-04-19 04:43:09 +000030 QueueChannel(Queue &InQueue, Queue &OutQueue)
Lang Hames1fa0e0e2016-04-25 21:21:20 +000031 : InQueue(InQueue), OutQueue(OutQueue) {}
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000032
Lang Hamesef5a0ee2016-04-25 19:56:45 +000033 Error readBytes(char *Dst, unsigned Size) override {
Lang Hames679c4362016-04-19 04:43:09 +000034 while (Size != 0) {
35 // If there's nothing to read then yield.
36 while (InQueue.empty())
37 std::this_thread::yield();
38
39 // Lock the channel and read what we can.
40 std::lock_guard<std::mutex> Lock(InQueue.getLock());
41 while (!InQueue.empty() && Size) {
42 *Dst++ = InQueue.front();
43 --Size;
44 InQueue.pop();
45 }
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000046 }
Lang Hamesef5a0ee2016-04-25 19:56:45 +000047 return Error::success();
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000048 }
49
Lang Hamesef5a0ee2016-04-25 19:56:45 +000050 Error appendBytes(const char *Src, unsigned Size) override {
Lang Hames679c4362016-04-19 04:43:09 +000051 std::lock_guard<std::mutex> Lock(OutQueue.getLock());
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000052 while (Size--)
Lang Hames679c4362016-04-19 04:43:09 +000053 OutQueue.push(*Src++);
Lang Hamesef5a0ee2016-04-25 19:56:45 +000054 return Error::success();
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000055 }
56
Lang Hamesef5a0ee2016-04-25 19:56:45 +000057 Error send() override { return Error::success(); }
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000058
59private:
Lang Hames679c4362016-04-19 04:43:09 +000060 Queue &InQueue;
61 Queue &OutQueue;
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000062};
63
Lang Hames1fa0e0e2016-04-25 21:21:20 +000064class DummyRPC : public testing::Test, public RPC<QueueChannel> {
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000065public:
Lang Hames679c4362016-04-19 04:43:09 +000066 enum FuncId : uint32_t {
67 VoidBoolId = RPCFunctionIdTraits<FuncId>::FirstValidId,
68 IntIntId,
69 AllTheTypesId
70 };
71
72 typedef Function<VoidBoolId, void(bool)> VoidBool;
73 typedef Function<IntIntId, int32_t(int32_t)> IntInt;
Lang Hames1fa0e0e2016-04-25 21:21:20 +000074 typedef Function<AllTheTypesId,
75 void(int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
76 int64_t, uint64_t, bool, std::string, std::vector<int>)>
77 AllTheTypes;
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000078};
79
Lang Hames679c4362016-04-19 04:43:09 +000080TEST_F(DummyRPC, TestAsyncVoidBool) {
81 Queue Q1, Q2;
82 QueueChannel C1(Q1, Q2);
83 QueueChannel C2(Q2, Q1);
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000084
Lang Hames3fde6522016-04-18 19:55:43 +000085 // Make an async call.
Lang Hames679c4362016-04-19 04:43:09 +000086 auto ResOrErr = callAsyncWithSeq<VoidBool>(C1, true);
Lang Hames3fde6522016-04-18 19:55:43 +000087 EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000088
89 {
90 // Expect a call to Proc1.
Lang Hames1fa0e0e2016-04-25 21:21:20 +000091 auto EC = expect<VoidBool>(C2, [&](bool &B) {
92 EXPECT_EQ(B, true) << "Bool serialization broken";
93 return Error::success();
94 });
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000095 EXPECT_FALSE(EC) << "Simple expect over queue failed";
96 }
Lang Hames3fde6522016-04-18 19:55:43 +000097
98 {
99 // Wait for the result.
Lang Hames679c4362016-04-19 04:43:09 +0000100 auto EC = waitForResult(C1, ResOrErr->second, handleNone);
Lang Hames3fde6522016-04-18 19:55:43 +0000101 EXPECT_FALSE(EC) << "Could not read result.";
102 }
103
104 // Verify that the function returned ok.
105 auto Val = ResOrErr->first.get();
106 EXPECT_TRUE(Val) << "Remote void function failed to execute.";
107}
108
Lang Hames679c4362016-04-19 04:43:09 +0000109TEST_F(DummyRPC, TestAsyncIntInt) {
110 Queue Q1, Q2;
111 QueueChannel C1(Q1, Q2);
112 QueueChannel C2(Q2, Q1);
Lang Hames3fde6522016-04-18 19:55:43 +0000113
114 // Make an async call.
Lang Hames679c4362016-04-19 04:43:09 +0000115 auto ResOrErr = callAsyncWithSeq<IntInt>(C1, 21);
Lang Hames3fde6522016-04-18 19:55:43 +0000116 EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
117
118 {
119 // Expect a call to Proc1.
Lang Hames1fa0e0e2016-04-25 21:21:20 +0000120 auto EC = expect<IntInt>(C2, [&](int32_t I) -> Expected<int32_t> {
121 EXPECT_EQ(I, 21) << "Bool serialization broken";
122 return 2 * I;
123 });
Lang Hames3fde6522016-04-18 19:55:43 +0000124 EXPECT_FALSE(EC) << "Simple expect over queue failed";
125 }
126
127 {
128 // Wait for the result.
Lang Hames679c4362016-04-19 04:43:09 +0000129 auto EC = waitForResult(C1, ResOrErr->second, handleNone);
Lang Hames3fde6522016-04-18 19:55:43 +0000130 EXPECT_FALSE(EC) << "Could not read result.";
131 }
132
133 // Verify that the function returned ok.
134 auto Val = ResOrErr->first.get();
135 EXPECT_TRUE(!!Val) << "Remote int function failed to execute.";
136 EXPECT_EQ(*Val, 42) << "Remote int function return wrong value.";
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000137}
138
139TEST_F(DummyRPC, TestSerialization) {
Lang Hames679c4362016-04-19 04:43:09 +0000140 Queue Q1, Q2;
141 QueueChannel C1(Q1, Q2);
142 QueueChannel C2(Q2, Q1);
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000143
Lang Hames3fde6522016-04-18 19:55:43 +0000144 // Make a call to Proc1.
145 std::vector<int> v({42, 7});
Lang Hames1fa0e0e2016-04-25 21:21:20 +0000146 auto ResOrErr = callAsyncWithSeq<AllTheTypes>(
147 C1, -101, 250, -10000, 10000, -1000000000, 1000000000, -10000000000,
148 10000000000, true, "foo", v);
149 EXPECT_TRUE(!!ResOrErr) << "Big (serialization test) call over queue failed";
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000150
151 {
152 // Expect a call to Proc1.
Lang Hames1fa0e0e2016-04-25 21:21:20 +0000153 auto EC = expect<AllTheTypes>(
154 C2, [&](int8_t &s8, uint8_t &u8, int16_t &s16, uint16_t &u16,
155 int32_t &s32, uint32_t &u32, int64_t &s64, uint64_t &u64,
156 bool &b, std::string &s, std::vector<int> &v) {
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000157
Lang Hames1fa0e0e2016-04-25 21:21:20 +0000158 EXPECT_EQ(s8, -101) << "int8_t serialization broken";
159 EXPECT_EQ(u8, 250) << "uint8_t serialization broken";
160 EXPECT_EQ(s16, -10000) << "int16_t serialization broken";
161 EXPECT_EQ(u16, 10000) << "uint16_t serialization broken";
162 EXPECT_EQ(s32, -1000000000) << "int32_t serialization broken";
163 EXPECT_EQ(u32, 1000000000ULL) << "uint32_t serialization broken";
164 EXPECT_EQ(s64, -10000000000) << "int64_t serialization broken";
165 EXPECT_EQ(u64, 10000000000ULL) << "uint64_t serialization broken";
166 EXPECT_EQ(b, true) << "bool serialization broken";
167 EXPECT_EQ(s, "foo") << "std::string serialization broken";
168 EXPECT_EQ(v, std::vector<int>({42, 7}))
169 << "std::vector serialization broken";
170 return Error::success();
171 });
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000172 EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
173 }
Lang Hames3fde6522016-04-18 19:55:43 +0000174
175 {
176 // Wait for the result.
Lang Hames679c4362016-04-19 04:43:09 +0000177 auto EC = waitForResult(C1, ResOrErr->second, handleNone);
Lang Hames3fde6522016-04-18 19:55:43 +0000178 EXPECT_FALSE(EC) << "Could not read result.";
179 }
180
181 // Verify that the function returned ok.
182 auto Val = ResOrErr->first.get();
183 EXPECT_TRUE(Val) << "Remote void function failed to execute.";
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000184}
Lang Hames679c4362016-04-19 04:43:09 +0000185
186// Test the synchronous call API.
Lang Hamesde33d592016-04-19 06:01:51 +0000187// FIXME: Re-enable once deadlock encountered on S390 has been debugged / fixed,
188// see http://lab.llvm.org:8011/builders/clang-s390x-linux/builds/3459
189// TEST_F(DummyRPC, TestSynchronousCall) {
190// Queue Q1, Q2;
191// QueueChannel C1(Q1, Q2);
192// QueueChannel C2(Q2, Q1);
193//
194// auto ServerResult =
195// std::async(std::launch::async,
196// [&]() {
197// return expect<IntInt>(C2, [&](int32_t V) { return V; });
198// });
199//
200// auto ValOrErr = callST<IntInt>(C1, 42);
201//
202// EXPECT_FALSE(!!ServerResult.get())
203// << "Server returned an error.";
204// EXPECT_TRUE(!!ValOrErr)
205// << "callST returned an error.";
206// EXPECT_EQ(*ValOrErr, 42)
207// << "Incorrect callST<IntInt> result";
208// }