14eb9fe2eSLang Hames //===----- WrapperFunctionUtilsTest.cpp - Test Wrapper-Function utils -----===//
24eb9fe2eSLang Hames //
34eb9fe2eSLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44eb9fe2eSLang Hames // See https://llvm.org/LICENSE.txt for license information.
54eb9fe2eSLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64eb9fe2eSLang Hames //
74eb9fe2eSLang Hames //===----------------------------------------------------------------------===//
84eb9fe2eSLang Hames
94eb9fe2eSLang Hames #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
1039f64c4cSLang Hames #include "llvm/ADT/FunctionExtras.h"
118abf46d3SLang Hames #include "llvm/Testing/Support/Error.h"
124eb9fe2eSLang Hames #include "gtest/gtest.h"
134eb9fe2eSLang Hames
1439f64c4cSLang Hames #include <future>
1539f64c4cSLang Hames
164eb9fe2eSLang Hames using namespace llvm;
17a01f772dSLang Hames using namespace llvm::orc;
184eb9fe2eSLang Hames using namespace llvm::orc::shared;
194eb9fe2eSLang Hames
204eb9fe2eSLang Hames namespace {
214eb9fe2eSLang Hames constexpr const char *TestString = "test string";
224eb9fe2eSLang Hames } // end anonymous namespace
234eb9fe2eSLang Hames
TEST(WrapperFunctionUtilsTest,DefaultWrapperFunctionResult)244eb9fe2eSLang Hames TEST(WrapperFunctionUtilsTest, DefaultWrapperFunctionResult) {
254eb9fe2eSLang Hames WrapperFunctionResult R;
264eb9fe2eSLang Hames EXPECT_TRUE(R.empty());
274eb9fe2eSLang Hames EXPECT_EQ(R.size(), 0U);
284eb9fe2eSLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
294eb9fe2eSLang Hames }
304eb9fe2eSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromRange)314eb9fe2eSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromRange) {
324eb9fe2eSLang Hames auto R = WrapperFunctionResult::copyFrom(TestString, strlen(TestString) + 1);
334eb9fe2eSLang Hames EXPECT_EQ(R.size(), strlen(TestString) + 1);
344eb9fe2eSLang Hames EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
354eb9fe2eSLang Hames EXPECT_FALSE(R.empty());
364eb9fe2eSLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
374eb9fe2eSLang Hames }
384eb9fe2eSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromCString)394eb9fe2eSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromCString) {
404eb9fe2eSLang Hames auto R = WrapperFunctionResult::copyFrom(TestString);
414eb9fe2eSLang Hames EXPECT_EQ(R.size(), strlen(TestString) + 1);
424eb9fe2eSLang Hames EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
434eb9fe2eSLang Hames EXPECT_FALSE(R.empty());
444eb9fe2eSLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
454eb9fe2eSLang Hames }
464eb9fe2eSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromStdString)474eb9fe2eSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromStdString) {
484eb9fe2eSLang Hames auto R = WrapperFunctionResult::copyFrom(std::string(TestString));
494eb9fe2eSLang Hames EXPECT_EQ(R.size(), strlen(TestString) + 1);
504eb9fe2eSLang Hames EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
514eb9fe2eSLang Hames EXPECT_FALSE(R.empty());
524eb9fe2eSLang Hames EXPECT_EQ(R.getOutOfBandError(), nullptr);
534eb9fe2eSLang Hames }
544eb9fe2eSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionResultFromOutOfBandError)554eb9fe2eSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromOutOfBandError) {
564eb9fe2eSLang Hames auto R = WrapperFunctionResult::createOutOfBandError(TestString);
574eb9fe2eSLang Hames EXPECT_FALSE(R.empty());
584eb9fe2eSLang Hames EXPECT_TRUE(strcmp(R.getOutOfBandError(), TestString) == 0);
594eb9fe2eSLang Hames }
604eb9fe2eSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionCCallCreateEmpty)61*0e43f3b0SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionCCallCreateEmpty) {
62*0e43f3b0SLang Hames EXPECT_THAT_EXPECTED(
63*0e43f3b0SLang Hames WrapperFunctionCall::Create<SPSArgList<>>(ExecutorAddr()), Succeeded());
64*0e43f3b0SLang Hames }
65*0e43f3b0SLang Hames
voidNoop()665a28bdeeSLang Hames static void voidNoop() {}
675a28bdeeSLang Hames
68a01f772dSLang Hames class AddClass {
69a01f772dSLang Hames public:
AddClass(int32_t X)70a01f772dSLang Hames AddClass(int32_t X) : X(X) {}
addMethod(int32_t Y)71a01f772dSLang Hames int32_t addMethod(int32_t Y) { return X + Y; }
72a01f772dSLang Hames private:
73a01f772dSLang Hames int32_t X;
74a01f772dSLang Hames };
75a01f772dSLang Hames
voidNoopWrapper(const char * ArgData,size_t ArgSize)764eb9fe2eSLang Hames static WrapperFunctionResult voidNoopWrapper(const char *ArgData,
774eb9fe2eSLang Hames size_t ArgSize) {
784eb9fe2eSLang Hames return WrapperFunction<void()>::handle(ArgData, ArgSize, voidNoop);
794eb9fe2eSLang Hames }
804eb9fe2eSLang Hames
addWrapper(const char * ArgData,size_t ArgSize)814eb9fe2eSLang Hames static WrapperFunctionResult addWrapper(const char *ArgData, size_t ArgSize) {
824eb9fe2eSLang Hames return WrapperFunction<int32_t(int32_t, int32_t)>::handle(
834eb9fe2eSLang Hames ArgData, ArgSize, [](int32_t X, int32_t Y) -> int32_t { return X + Y; });
844eb9fe2eSLang Hames }
854eb9fe2eSLang Hames
addMethodWrapper(const char * ArgData,size_t ArgSize)86a01f772dSLang Hames static WrapperFunctionResult addMethodWrapper(const char *ArgData,
87a01f772dSLang Hames size_t ArgSize) {
88ef391df2SLang Hames return WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::handle(
89a01f772dSLang Hames ArgData, ArgSize, makeMethodWrapperHandler(&AddClass::addMethod));
90a01f772dSLang Hames }
91a01f772dSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionCallAndHandleVoid)9239f64c4cSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleVoid) {
935a28bdeeSLang Hames EXPECT_FALSE(!!WrapperFunction<void()>::call(voidNoopWrapper));
944eb9fe2eSLang Hames }
954eb9fe2eSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionCallAndHandleRet)9639f64c4cSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleRet) {
974eb9fe2eSLang Hames int32_t Result;
984eb9fe2eSLang Hames EXPECT_FALSE(!!WrapperFunction<int32_t(int32_t, int32_t)>::call(
994eb9fe2eSLang Hames addWrapper, Result, 1, 2));
1004eb9fe2eSLang Hames EXPECT_EQ(Result, (int32_t)3);
1014eb9fe2eSLang Hames }
10239f64c4cSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionMethodCallAndHandleRet)103a01f772dSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionMethodCallAndHandleRet) {
104a01f772dSLang Hames int32_t Result;
105a01f772dSLang Hames AddClass AddObj(1);
106ef391df2SLang Hames EXPECT_FALSE(!!WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::call(
107ef391df2SLang Hames addMethodWrapper, Result, ExecutorAddr::fromPtr(&AddObj), 2));
108a01f772dSLang Hames EXPECT_EQ(Result, (int32_t)3);
109a01f772dSLang Hames }
110a01f772dSLang Hames
voidNoopAsync(unique_function<void (SPSEmpty)> SendResult)11139f64c4cSLang Hames static void voidNoopAsync(unique_function<void(SPSEmpty)> SendResult) {
11239f64c4cSLang Hames SendResult(SPSEmpty());
11339f64c4cSLang Hames }
11439f64c4cSLang Hames
voidNoopAsyncWrapper(const char * ArgData,size_t ArgSize)11539f64c4cSLang Hames static WrapperFunctionResult voidNoopAsyncWrapper(const char *ArgData,
11639f64c4cSLang Hames size_t ArgSize) {
11739f64c4cSLang Hames std::promise<WrapperFunctionResult> RP;
11839f64c4cSLang Hames auto RF = RP.get_future();
11939f64c4cSLang Hames
12039f64c4cSLang Hames WrapperFunction<void()>::handleAsync(
12139f64c4cSLang Hames ArgData, ArgSize, voidNoopAsync,
12239f64c4cSLang Hames [&](WrapperFunctionResult R) { RP.set_value(std::move(R)); });
12339f64c4cSLang Hames
12439f64c4cSLang Hames return RF.get();
12539f64c4cSLang Hames }
12639f64c4cSLang Hames
addAsyncWrapper(const char * ArgData,size_t ArgSize)12739f64c4cSLang Hames static WrapperFunctionResult addAsyncWrapper(const char *ArgData,
12839f64c4cSLang Hames size_t ArgSize) {
12939f64c4cSLang Hames std::promise<WrapperFunctionResult> RP;
13039f64c4cSLang Hames auto RF = RP.get_future();
13139f64c4cSLang Hames
13239f64c4cSLang Hames WrapperFunction<int32_t(int32_t, int32_t)>::handleAsync(
13339f64c4cSLang Hames ArgData, ArgSize,
13439f64c4cSLang Hames [](unique_function<void(int32_t)> SendResult, int32_t X, int32_t Y) {
13539f64c4cSLang Hames SendResult(X + Y);
13639f64c4cSLang Hames },
13739f64c4cSLang Hames [&](WrapperFunctionResult R) { RP.set_value(std::move(R)); });
13839f64c4cSLang Hames return RF.get();
13939f64c4cSLang Hames }
14039f64c4cSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionCallAndHandleAsyncVoid)14139f64c4cSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleAsyncVoid) {
14239f64c4cSLang Hames EXPECT_FALSE(!!WrapperFunction<void()>::call(voidNoopAsyncWrapper));
14339f64c4cSLang Hames }
14439f64c4cSLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionCallAndHandleAsyncRet)14539f64c4cSLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleAsyncRet) {
14639f64c4cSLang Hames int32_t Result;
14739f64c4cSLang Hames EXPECT_FALSE(!!WrapperFunction<int32_t(int32_t, int32_t)>::call(
14839f64c4cSLang Hames addAsyncWrapper, Result, 1, 2));
14939f64c4cSLang Hames EXPECT_EQ(Result, (int32_t)3);
15039f64c4cSLang Hames }
1518abf46d3SLang Hames
failingWrapper(const char * ArgData,size_t ArgSize)1528abf46d3SLang Hames static WrapperFunctionResult failingWrapper(const char *ArgData,
1538abf46d3SLang Hames size_t ArgSize) {
1548abf46d3SLang Hames return WrapperFunctionResult::createOutOfBandError("failed");
1558abf46d3SLang Hames }
1568abf46d3SLang Hames
asyncFailingWrapperCaller(unique_function<void (WrapperFunctionResult)> F,const char * ArgData,size_t ArgSize)1578abf46d3SLang Hames void asyncFailingWrapperCaller(unique_function<void(WrapperFunctionResult)> F,
1588abf46d3SLang Hames const char *ArgData, size_t ArgSize) {
1598abf46d3SLang Hames F(failingWrapper(ArgData, ArgSize));
1608abf46d3SLang Hames }
1618abf46d3SLang Hames
TEST(WrapperFunctionUtilsTest,WrapperFunctionCallFailingAsync)1628abf46d3SLang Hames TEST(WrapperFunctionUtilsTest, WrapperFunctionCallFailingAsync) {
1638abf46d3SLang Hames WrapperFunction<void()>::callAsync(asyncFailingWrapperCaller, [](Error Err) {
1648abf46d3SLang Hames EXPECT_THAT_ERROR(std::move(Err), Failed());
1658abf46d3SLang Hames });
1668abf46d3SLang Hames }
167