|  | //===----- WrapperFunctionUtilsTest.cpp - Test Wrapper-Function utils -----===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" | 
|  | #include "llvm/ADT/FunctionExtras.h" | 
|  | #include "llvm/Testing/Support/Error.h" | 
|  | #include "gtest/gtest.h" | 
|  |  | 
|  | #include <future> | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::orc; | 
|  | using namespace llvm::orc::shared; | 
|  |  | 
|  | namespace { | 
|  | constexpr const char *TestString = "test string"; | 
|  | } // end anonymous namespace | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, DefaultWrapperFunctionResult) { | 
|  | WrapperFunctionResult R; | 
|  | EXPECT_TRUE(R.empty()); | 
|  | EXPECT_EQ(R.size(), 0U); | 
|  | EXPECT_EQ(R.getOutOfBandError(), nullptr); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromRange) { | 
|  | auto R = WrapperFunctionResult::copyFrom(TestString, strlen(TestString) + 1); | 
|  | EXPECT_EQ(R.size(), strlen(TestString) + 1); | 
|  | EXPECT_TRUE(strcmp(R.data(), TestString) == 0); | 
|  | EXPECT_FALSE(R.empty()); | 
|  | EXPECT_EQ(R.getOutOfBandError(), nullptr); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromCString) { | 
|  | auto R = WrapperFunctionResult::copyFrom(TestString); | 
|  | EXPECT_EQ(R.size(), strlen(TestString) + 1); | 
|  | EXPECT_TRUE(strcmp(R.data(), TestString) == 0); | 
|  | EXPECT_FALSE(R.empty()); | 
|  | EXPECT_EQ(R.getOutOfBandError(), nullptr); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromStdString) { | 
|  | auto R = WrapperFunctionResult::copyFrom(std::string(TestString)); | 
|  | EXPECT_EQ(R.size(), strlen(TestString) + 1); | 
|  | EXPECT_TRUE(strcmp(R.data(), TestString) == 0); | 
|  | EXPECT_FALSE(R.empty()); | 
|  | EXPECT_EQ(R.getOutOfBandError(), nullptr); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromOutOfBandError) { | 
|  | auto R = WrapperFunctionResult::createOutOfBandError(TestString); | 
|  | EXPECT_FALSE(R.empty()); | 
|  | EXPECT_TRUE(strcmp(R.getOutOfBandError(), TestString) == 0); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionCCallCreateEmpty) { | 
|  | EXPECT_THAT_EXPECTED( | 
|  | WrapperFunctionCall::Create<SPSArgList<>>(ExecutorAddr()), Succeeded()); | 
|  | } | 
|  |  | 
|  | static void voidNoop() {} | 
|  |  | 
|  | class AddClass { | 
|  | public: | 
|  | AddClass(int32_t X) : X(X) {} | 
|  | int32_t addMethod(int32_t Y) { return X + Y; } | 
|  | private: | 
|  | int32_t X; | 
|  | }; | 
|  |  | 
|  | static WrapperFunctionResult voidNoopWrapper(const char *ArgData, | 
|  | size_t ArgSize) { | 
|  | return WrapperFunction<void()>::handle(ArgData, ArgSize, voidNoop); | 
|  | } | 
|  |  | 
|  | static WrapperFunctionResult addWrapper(const char *ArgData, size_t ArgSize) { | 
|  | return WrapperFunction<int32_t(int32_t, int32_t)>::handle( | 
|  | ArgData, ArgSize, [](int32_t X, int32_t Y) -> int32_t { return X + Y; }); | 
|  | } | 
|  |  | 
|  | static WrapperFunctionResult addMethodWrapper(const char *ArgData, | 
|  | size_t ArgSize) { | 
|  | return WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::handle( | 
|  | ArgData, ArgSize, makeMethodWrapperHandler(&AddClass::addMethod)); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleVoid) { | 
|  | EXPECT_FALSE(!!WrapperFunction<void()>::call(voidNoopWrapper)); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleRet) { | 
|  | int32_t Result; | 
|  | EXPECT_FALSE(!!WrapperFunction<int32_t(int32_t, int32_t)>::call( | 
|  | addWrapper, Result, 1, 2)); | 
|  | EXPECT_EQ(Result, (int32_t)3); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionMethodCallAndHandleRet) { | 
|  | int32_t Result; | 
|  | AddClass AddObj(1); | 
|  | EXPECT_FALSE(!!WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::call( | 
|  | addMethodWrapper, Result, ExecutorAddr::fromPtr(&AddObj), 2)); | 
|  | EXPECT_EQ(Result, (int32_t)3); | 
|  | } | 
|  |  | 
|  | static void voidNoopAsync(unique_function<void(SPSEmpty)> SendResult) { | 
|  | SendResult(SPSEmpty()); | 
|  | } | 
|  |  | 
|  | static WrapperFunctionResult voidNoopAsyncWrapper(const char *ArgData, | 
|  | size_t ArgSize) { | 
|  | std::promise<WrapperFunctionResult> RP; | 
|  | auto RF = RP.get_future(); | 
|  |  | 
|  | WrapperFunction<void()>::handleAsync( | 
|  | ArgData, ArgSize, voidNoopAsync, | 
|  | [&](WrapperFunctionResult R) { RP.set_value(std::move(R)); }); | 
|  |  | 
|  | return RF.get(); | 
|  | } | 
|  |  | 
|  | static WrapperFunctionResult addAsyncWrapper(const char *ArgData, | 
|  | size_t ArgSize) { | 
|  | std::promise<WrapperFunctionResult> RP; | 
|  | auto RF = RP.get_future(); | 
|  |  | 
|  | WrapperFunction<int32_t(int32_t, int32_t)>::handleAsync( | 
|  | ArgData, ArgSize, | 
|  | [](unique_function<void(int32_t)> SendResult, int32_t X, int32_t Y) { | 
|  | SendResult(X + Y); | 
|  | }, | 
|  | [&](WrapperFunctionResult R) { RP.set_value(std::move(R)); }); | 
|  | return RF.get(); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleAsyncVoid) { | 
|  | EXPECT_FALSE(!!WrapperFunction<void()>::call(voidNoopAsyncWrapper)); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionCallAndHandleAsyncRet) { | 
|  | int32_t Result; | 
|  | EXPECT_FALSE(!!WrapperFunction<int32_t(int32_t, int32_t)>::call( | 
|  | addAsyncWrapper, Result, 1, 2)); | 
|  | EXPECT_EQ(Result, (int32_t)3); | 
|  | } | 
|  |  | 
|  | static WrapperFunctionResult failingWrapper(const char *ArgData, | 
|  | size_t ArgSize) { | 
|  | return WrapperFunctionResult::createOutOfBandError("failed"); | 
|  | } | 
|  |  | 
|  | void asyncFailingWrapperCaller(unique_function<void(WrapperFunctionResult)> F, | 
|  | const char *ArgData, size_t ArgSize) { | 
|  | F(failingWrapper(ArgData, ArgSize)); | 
|  | } | 
|  |  | 
|  | TEST(WrapperFunctionUtilsTest, WrapperFunctionCallFailingAsync) { | 
|  | WrapperFunction<void()>::callAsync(asyncFailingWrapperCaller, [](Error Err) { | 
|  | EXPECT_THAT_ERROR(std::move(Err), Failed()); | 
|  | }); | 
|  | } |