1 //===----- WrapperFunctionUtilsTest.cpp - Test Wrapper-Function 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 9 #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" 10 #include "llvm/ADT/FunctionExtras.h" 11 #include "llvm/Testing/Support/Error.h" 12 #include "gtest/gtest.h" 13 14 #include <future> 15 16 using namespace llvm; 17 using namespace llvm::orc; 18 using namespace llvm::orc::shared; 19 20 namespace { 21 constexpr const char *TestString = "test string"; 22 } // end anonymous namespace 23 24 TEST(WrapperFunctionUtilsTest, DefaultWrapperFunctionResult) { 25 WrapperFunctionResult R; 26 EXPECT_TRUE(R.empty()); 27 EXPECT_EQ(R.size(), 0U); 28 EXPECT_EQ(R.getOutOfBandError(), nullptr); 29 } 30 31 TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromRange) { 32 auto R = WrapperFunctionResult::copyFrom(TestString, strlen(TestString) + 1); 33 EXPECT_EQ(R.size(), strlen(TestString) + 1); 34 EXPECT_TRUE(strcmp(R.data(), TestString) == 0); 35 EXPECT_FALSE(R.empty()); 36 EXPECT_EQ(R.getOutOfBandError(), nullptr); 37 } 38 39 TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromCString) { 40 auto R = WrapperFunctionResult::copyFrom(TestString); 41 EXPECT_EQ(R.size(), strlen(TestString) + 1); 42 EXPECT_TRUE(strcmp(R.data(), TestString) == 0); 43 EXPECT_FALSE(R.empty()); 44 EXPECT_EQ(R.getOutOfBandError(), nullptr); 45 } 46 47 TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromStdString) { 48 auto R = WrapperFunctionResult::copyFrom(std::string(TestString)); 49 EXPECT_EQ(R.size(), strlen(TestString) + 1); 50 EXPECT_TRUE(strcmp(R.data(), TestString) == 0); 51 EXPECT_FALSE(R.empty()); 52 EXPECT_EQ(R.getOutOfBandError(), nullptr); 53 } 54 55 TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromOutOfBandError) { 56 auto R = WrapperFunctionResult::createOutOfBandError(TestString); 57 EXPECT_FALSE(R.empty()); 58 EXPECT_TRUE(strcmp(R.getOutOfBandError(), TestString) == 0); 59 } 60 61 static void voidNoop() {} 62 63 class AddClass { 64 public: 65 AddClass(int32_t X) : X(X) {} 66 int32_t addMethod(int32_t Y) { return X + Y; } 67 private: 68 int32_t X; 69 }; 70 71 static WrapperFunctionResult voidNoopWrapper(const char *ArgData, 72 size_t ArgSize) { 73 return WrapperFunction<void()>::handle(ArgData, ArgSize, voidNoop); 74 } 75 76 static WrapperFunctionResult addWrapper(const char *ArgData, size_t ArgSize) { 77 return WrapperFunction<int32_t(int32_t, int32_t)>::handle( 78 ArgData, ArgSize, [](int32_t X, int32_t Y) -> int32_t { return X + Y; }); 79 } 80 81 static WrapperFunctionResult addMethodWrapper(const char *ArgData, 82 size_t ArgSize) { 83 return WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::handle( 84 ArgData, ArgSize, makeMethodWrapperHandler(&AddClass::addMethod)); 85 } 86 87 TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleVoid) { 88 EXPECT_FALSE(!!WrapperFunction<void()>::call(voidNoopWrapper)); 89 } 90 91 TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleRet) { 92 int32_t Result; 93 EXPECT_FALSE(!!WrapperFunction<int32_t(int32_t, int32_t)>::call( 94 addWrapper, Result, 1, 2)); 95 EXPECT_EQ(Result, (int32_t)3); 96 } 97 98 TEST(WrapperFunctionUtilsTest, WrapperFunctionMethodCallAndHandleRet) { 99 int32_t Result; 100 AddClass AddObj(1); 101 EXPECT_FALSE(!!WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::call( 102 addMethodWrapper, Result, ExecutorAddr::fromPtr(&AddObj), 2)); 103 EXPECT_EQ(Result, (int32_t)3); 104 } 105 106 static void voidNoopAsync(unique_function<void(SPSEmpty)> SendResult) { 107 SendResult(SPSEmpty()); 108 } 109 110 static WrapperFunctionResult voidNoopAsyncWrapper(const char *ArgData, 111 size_t ArgSize) { 112 std::promise<WrapperFunctionResult> RP; 113 auto RF = RP.get_future(); 114 115 WrapperFunction<void()>::handleAsync( 116 ArgData, ArgSize, voidNoopAsync, 117 [&](WrapperFunctionResult R) { RP.set_value(std::move(R)); }); 118 119 return RF.get(); 120 } 121 122 static WrapperFunctionResult addAsyncWrapper(const char *ArgData, 123 size_t ArgSize) { 124 std::promise<WrapperFunctionResult> RP; 125 auto RF = RP.get_future(); 126 127 WrapperFunction<int32_t(int32_t, int32_t)>::handleAsync( 128 ArgData, ArgSize, 129 [](unique_function<void(int32_t)> SendResult, int32_t X, int32_t Y) { 130 SendResult(X + Y); 131 }, 132 [&](WrapperFunctionResult R) { RP.set_value(std::move(R)); }); 133 return RF.get(); 134 } 135 136 TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleAsyncVoid) { 137 EXPECT_FALSE(!!WrapperFunction<void()>::call(voidNoopAsyncWrapper)); 138 } 139 140 TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleAsyncRet) { 141 int32_t Result; 142 EXPECT_FALSE(!!WrapperFunction<int32_t(int32_t, int32_t)>::call( 143 addAsyncWrapper, Result, 1, 2)); 144 EXPECT_EQ(Result, (int32_t)3); 145 } 146 147 static WrapperFunctionResult failingWrapper(const char *ArgData, 148 size_t ArgSize) { 149 return WrapperFunctionResult::createOutOfBandError("failed"); 150 } 151 152 void asyncFailingWrapperCaller(unique_function<void(WrapperFunctionResult)> F, 153 const char *ArgData, size_t ArgSize) { 154 F(failingWrapper(ArgData, ArgSize)); 155 } 156 157 TEST(WrapperFunctionUtilsTest, WrapperFunctionCallFailingAsync) { 158 WrapperFunction<void()>::callAsync(asyncFailingWrapperCaller, [](Error Err) { 159 EXPECT_THAT_ERROR(std::move(Err), Failed()); 160 }); 161 } 162