blob: b2680aa7d8a5d9a8fb000ddac1b12c52fc8bc51f [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:
22 std::mutex& getLock() { return Lock; }
23private:
24 std::mutex Lock;
25};
26
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000027class QueueChannel : public RPCChannel {
28public:
Lang Hames679c4362016-04-19 04:43:09 +000029 QueueChannel(Queue &InQueue, Queue &OutQueue)
30 : InQueue(InQueue), OutQueue(OutQueue) {}
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000031
Lang Hamesef5a0ee2016-04-25 19:56:45 +000032 Error readBytes(char *Dst, unsigned Size) override {
Lang Hames679c4362016-04-19 04:43:09 +000033 while (Size != 0) {
34 // If there's nothing to read then yield.
35 while (InQueue.empty())
36 std::this_thread::yield();
37
38 // Lock the channel and read what we can.
39 std::lock_guard<std::mutex> Lock(InQueue.getLock());
40 while (!InQueue.empty() && Size) {
41 *Dst++ = InQueue.front();
42 --Size;
43 InQueue.pop();
44 }
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000045 }
Lang Hamesef5a0ee2016-04-25 19:56:45 +000046 return Error::success();
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000047 }
48
Lang Hamesef5a0ee2016-04-25 19:56:45 +000049 Error appendBytes(const char *Src, unsigned Size) override {
Lang Hames679c4362016-04-19 04:43:09 +000050 std::lock_guard<std::mutex> Lock(OutQueue.getLock());
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000051 while (Size--)
Lang Hames679c4362016-04-19 04:43:09 +000052 OutQueue.push(*Src++);
Lang Hamesef5a0ee2016-04-25 19:56:45 +000053 return Error::success();
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000054 }
55
Lang Hamesef5a0ee2016-04-25 19:56:45 +000056 Error send() override { return Error::success(); }
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000057
58private:
Lang Hames679c4362016-04-19 04:43:09 +000059 Queue &InQueue;
60 Queue &OutQueue;
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000061};
62
63class DummyRPC : public testing::Test,
64 public RPC<QueueChannel> {
65public:
Lang Hames679c4362016-04-19 04:43:09 +000066
67 enum FuncId : uint32_t {
68 VoidBoolId = RPCFunctionIdTraits<FuncId>::FirstValidId,
69 IntIntId,
70 AllTheTypesId
71 };
72
73 typedef Function<VoidBoolId, void(bool)> VoidBool;
74 typedef Function<IntIntId, int32_t(int32_t)> IntInt;
75 typedef Function<AllTheTypesId, void(int8_t, uint8_t, int16_t, uint16_t,
76 int32_t, uint32_t, int64_t, uint64_t,
77 bool, std::string, std::vector<int>)>
78 AllTheTypes;
79
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000080};
81
82
Lang Hames679c4362016-04-19 04:43:09 +000083TEST_F(DummyRPC, TestAsyncVoidBool) {
84 Queue Q1, Q2;
85 QueueChannel C1(Q1, Q2);
86 QueueChannel C2(Q2, Q1);
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000087
Lang Hames3fde6522016-04-18 19:55:43 +000088 // Make an async call.
Lang Hames679c4362016-04-19 04:43:09 +000089 auto ResOrErr = callAsyncWithSeq<VoidBool>(C1, true);
Lang Hames3fde6522016-04-18 19:55:43 +000090 EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000091
92 {
93 // Expect a call to Proc1.
Lang Hames679c4362016-04-19 04:43:09 +000094 auto EC = expect<VoidBool>(C2,
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000095 [&](bool &B) {
96 EXPECT_EQ(B, true)
97 << "Bool serialization broken";
Lang Hamesef5a0ee2016-04-25 19:56:45 +000098 return Error::success();
Lang Hames4d0a5a9e2016-01-11 01:40:11 +000099 });
100 EXPECT_FALSE(EC) << "Simple expect over queue failed";
101 }
Lang Hames3fde6522016-04-18 19:55:43 +0000102
103 {
104 // Wait for the result.
Lang Hames679c4362016-04-19 04:43:09 +0000105 auto EC = waitForResult(C1, ResOrErr->second, handleNone);
Lang Hames3fde6522016-04-18 19:55:43 +0000106 EXPECT_FALSE(EC) << "Could not read result.";
107 }
108
109 // Verify that the function returned ok.
110 auto Val = ResOrErr->first.get();
111 EXPECT_TRUE(Val) << "Remote void function failed to execute.";
112}
113
Lang Hames679c4362016-04-19 04:43:09 +0000114TEST_F(DummyRPC, TestAsyncIntInt) {
115 Queue Q1, Q2;
116 QueueChannel C1(Q1, Q2);
117 QueueChannel C2(Q2, Q1);
Lang Hames3fde6522016-04-18 19:55:43 +0000118
119 // Make an async call.
Lang Hames679c4362016-04-19 04:43:09 +0000120 auto ResOrErr = callAsyncWithSeq<IntInt>(C1, 21);
Lang Hames3fde6522016-04-18 19:55:43 +0000121 EXPECT_TRUE(!!ResOrErr) << "Simple call over queue failed";
122
123 {
124 // Expect a call to Proc1.
Lang Hames679c4362016-04-19 04:43:09 +0000125 auto EC = expect<IntInt>(C2,
Lang Hamesef5a0ee2016-04-25 19:56:45 +0000126 [&](int32_t I) -> Expected<int32_t> {
Lang Hames679c4362016-04-19 04:43:09 +0000127 EXPECT_EQ(I, 21)
Lang Hames3fde6522016-04-18 19:55:43 +0000128 << "Bool serialization broken";
Lang Hames679c4362016-04-19 04:43:09 +0000129 return 2 * I;
Lang Hames3fde6522016-04-18 19:55:43 +0000130 });
131 EXPECT_FALSE(EC) << "Simple expect over queue failed";
132 }
133
134 {
135 // Wait for the result.
Lang Hames679c4362016-04-19 04:43:09 +0000136 auto EC = waitForResult(C1, ResOrErr->second, handleNone);
Lang Hames3fde6522016-04-18 19:55:43 +0000137 EXPECT_FALSE(EC) << "Could not read result.";
138 }
139
140 // Verify that the function returned ok.
141 auto Val = ResOrErr->first.get();
142 EXPECT_TRUE(!!Val) << "Remote int function failed to execute.";
143 EXPECT_EQ(*Val, 42) << "Remote int function return wrong value.";
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000144}
145
146TEST_F(DummyRPC, TestSerialization) {
Lang Hames679c4362016-04-19 04:43:09 +0000147 Queue Q1, Q2;
148 QueueChannel C1(Q1, Q2);
149 QueueChannel C2(Q2, Q1);
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000150
Lang Hames3fde6522016-04-18 19:55:43 +0000151 // Make a call to Proc1.
152 std::vector<int> v({42, 7});
Lang Hames679c4362016-04-19 04:43:09 +0000153 auto ResOrErr = callAsyncWithSeq<AllTheTypes>(C1,
154 -101,
155 250,
156 -10000,
157 10000,
158 -1000000000,
159 1000000000,
160 -10000000000,
161 10000000000,
162 true,
163 "foo",
164 v);
Lang Hames3fde6522016-04-18 19:55:43 +0000165 EXPECT_TRUE(!!ResOrErr)
166 << "Big (serialization test) call over queue failed";
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000167
168 {
169 // Expect a call to Proc1.
Lang Hames679c4362016-04-19 04:43:09 +0000170 auto EC = expect<AllTheTypes>(C2,
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000171 [&](int8_t &s8,
172 uint8_t &u8,
173 int16_t &s16,
174 uint16_t &u16,
175 int32_t &s32,
176 uint32_t &u32,
177 int64_t &s64,
178 uint64_t &u64,
179 bool &b,
180 std::string &s,
181 std::vector<int> &v) {
182
183 EXPECT_EQ(s8, -101)
184 << "int8_t serialization broken";
185 EXPECT_EQ(u8, 250)
186 << "uint8_t serialization broken";
187 EXPECT_EQ(s16, -10000)
188 << "int16_t serialization broken";
189 EXPECT_EQ(u16, 10000)
190 << "uint16_t serialization broken";
191 EXPECT_EQ(s32, -1000000000)
192 << "int32_t serialization broken";
193 EXPECT_EQ(u32, 1000000000ULL)
194 << "uint32_t serialization broken";
195 EXPECT_EQ(s64, -10000000000)
196 << "int64_t serialization broken";
197 EXPECT_EQ(u64, 10000000000ULL)
198 << "uint64_t serialization broken";
199 EXPECT_EQ(b, true)
200 << "bool serialization broken";
201 EXPECT_EQ(s, "foo")
202 << "std::string serialization broken";
203 EXPECT_EQ(v, std::vector<int>({42, 7}))
204 << "std::vector serialization broken";
Lang Hamesef5a0ee2016-04-25 19:56:45 +0000205 return Error::success();
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000206 });
207 EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
208 }
Lang Hames3fde6522016-04-18 19:55:43 +0000209
210 {
211 // Wait for the result.
Lang Hames679c4362016-04-19 04:43:09 +0000212 auto EC = waitForResult(C1, ResOrErr->second, handleNone);
Lang Hames3fde6522016-04-18 19:55:43 +0000213 EXPECT_FALSE(EC) << "Could not read result.";
214 }
215
216 // Verify that the function returned ok.
217 auto Val = ResOrErr->first.get();
218 EXPECT_TRUE(Val) << "Remote void function failed to execute.";
Lang Hames4d0a5a9e2016-01-11 01:40:11 +0000219}
Lang Hames679c4362016-04-19 04:43:09 +0000220
221// Test the synchronous call API.
Lang Hamesde33d592016-04-19 06:01:51 +0000222// FIXME: Re-enable once deadlock encountered on S390 has been debugged / fixed,
223// see http://lab.llvm.org:8011/builders/clang-s390x-linux/builds/3459
224// TEST_F(DummyRPC, TestSynchronousCall) {
225// Queue Q1, Q2;
226// QueueChannel C1(Q1, Q2);
227// QueueChannel C2(Q2, Q1);
228//
229// auto ServerResult =
230// std::async(std::launch::async,
231// [&]() {
232// return expect<IntInt>(C2, [&](int32_t V) { return V; });
233// });
234//
235// auto ValOrErr = callST<IntInt>(C1, 42);
236//
237// EXPECT_FALSE(!!ServerResult.get())
238// << "Server returned an error.";
239// EXPECT_TRUE(!!ValOrErr)
240// << "callST returned an error.";
241// EXPECT_EQ(*ValOrErr, 42)
242// << "Incorrect callST<IntInt> result";
243// }