brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.6 KiB · 1365491 Raw
318 lines · cpp
1//===-- SPSWrapperFunctionTest.cpp ----------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// Test SPSWrapperFunction and associated utilities.10//11//===----------------------------------------------------------------------===//12 13#include "CommonTestUtils.h"14 15#include "orc-rt/SPSWrapperFunction.h"16#include "orc-rt/WrapperFunction.h"17#include "orc-rt/move_only_function.h"18 19#include "DirectCaller.h"20 21#include "gtest/gtest.h"22 23using namespace orc_rt;24 25static void void_noop_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,26                                  orc_rt_WrapperFunctionReturn Return,27                                  orc_rt_WrapperFunctionBuffer ArgBytes) {28  SPSWrapperFunction<void()>::handle(29      S, CallId, Return, ArgBytes,30      [](move_only_function<void()> Return) { Return(); });31}32 33TEST(SPSWrapperFunctionUtilsTest, VoidNoop) {34  bool Ran = false;35  SPSWrapperFunction<void()>::call(DirectCaller(nullptr, void_noop_sps_wrapper),36                                   [&](Error Err) {37                                     cantFail(std::move(Err));38                                     Ran = true;39                                   });40  EXPECT_TRUE(Ran);41}42 43static void add_via_lambda_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,44                                       orc_rt_WrapperFunctionReturn Return,45                                       orc_rt_WrapperFunctionBuffer ArgBytes) {46  SPSWrapperFunction<int32_t(int32_t, int32_t)>::handle(47      S, CallId, Return, ArgBytes,48      [](move_only_function<void(int32_t)> Return, int32_t X, int32_t Y) {49        Return(X + Y);50      });51}52 53TEST(SPSWrapperFunctionUtilsTest, BinaryOpViaLambda) {54  int32_t Result = 0;55  SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(56      DirectCaller(nullptr, add_via_lambda_sps_wrapper),57      [&](Expected<int32_t> R) { Result = cantFail(std::move(R)); }, 41, 1);58  EXPECT_EQ(Result, 42);59}60 61static void add_via_function(move_only_function<void(int32_t)> Return,62                             int32_t X, int32_t Y) {63  Return(X + Y);64}65 66static void67add_via_function_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,68                             orc_rt_WrapperFunctionReturn Return,69                             orc_rt_WrapperFunctionBuffer ArgBytes) {70  SPSWrapperFunction<int32_t(int32_t, int32_t)>::handle(71      S, CallId, Return, ArgBytes, add_via_function);72}73 74TEST(SPSWrapperFunctionUtilsTest, BinaryOpViaFunction) {75  int32_t Result = 0;76  SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(77      DirectCaller(nullptr, add_via_function_sps_wrapper),78      [&](Expected<int32_t> R) { Result = cantFail(std::move(R)); }, 41, 1);79  EXPECT_EQ(Result, 42);80}81 82static void83add_via_function_pointer_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,84                                     orc_rt_WrapperFunctionReturn Return,85                                     orc_rt_WrapperFunctionBuffer ArgBytes) {86  SPSWrapperFunction<int32_t(int32_t, int32_t)>::handle(87      S, CallId, Return, ArgBytes, &add_via_function);88}89 90TEST(SPSWrapperFunctionUtilsTest, BinaryOpViaFunctionPointer) {91  int32_t Result = 0;92  SPSWrapperFunction<int32_t(int32_t, int32_t)>::call(93      DirectCaller(nullptr, add_via_function_pointer_sps_wrapper),94      [&](Expected<int32_t> R) { Result = cantFail(std::move(R)); }, 41, 1);95  EXPECT_EQ(Result, 42);96}97 98static void99round_trip_string_via_span_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,100                                       orc_rt_WrapperFunctionReturn Return,101                                       orc_rt_WrapperFunctionBuffer ArgBytes) {102  SPSWrapperFunction<SPSString(SPSString)>::handle(103      S, CallId, Return, ArgBytes,104      [](move_only_function<void(std::string)> Return, span<const char> S) {105        Return({S.data(), S.size()});106      });107}108 109TEST(SPSWrapperFunctionUtilsTest, RoundTripStringViaSpan) {110  /// Test that the SPSWrapperFunction<...>::handle call in111  /// round_trip_string_via_span_sps_wrapper can deserialize into a usable112  /// span<const char>.113  std::string Result;114  SPSWrapperFunction<SPSString(SPSString)>::call(115      DirectCaller(nullptr, round_trip_string_via_span_sps_wrapper),116      [&](Expected<std::string> R) { Result = cantFail(std::move(R)); },117      std::string_view("hello, world!"));118  EXPECT_EQ(Result, "hello, world!");119}120 121static void improbable_feat_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,122                                        orc_rt_WrapperFunctionReturn Return,123                                        orc_rt_WrapperFunctionBuffer ArgBytes) {124  SPSWrapperFunction<SPSError(bool)>::handle(125      S, CallId, Return, ArgBytes,126      [](move_only_function<void(Error)> Return, bool LuckyHat) {127        if (LuckyHat)128          Return(Error::success());129        else130          Return(make_error<StringError>("crushed by boulder"));131      });132}133 134TEST(SPSWrapperFunctionUtilsTest, TransparentConversionErrorSuccessCase) {135  bool DidRun = false;136  SPSWrapperFunction<SPSError(bool)>::call(137      DirectCaller(nullptr, improbable_feat_sps_wrapper),138      [&](Expected<Error> E) {139        DidRun = true;140        cantFail(cantFail(std::move(E)));141      },142      true);143 144  EXPECT_TRUE(DidRun);145}146 147TEST(SPSWrapperFunctionUtilsTest, TransparentConversionErrorFailureCase) {148  std::string ErrMsg;149  SPSWrapperFunction<SPSError(bool)>::call(150      DirectCaller(nullptr, improbable_feat_sps_wrapper),151      [&](Expected<Error> E) { ErrMsg = toString(cantFail(std::move(E))); },152      false);153 154  EXPECT_EQ(ErrMsg, "crushed by boulder");155}156 157static void halve_number_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,158                                     orc_rt_WrapperFunctionReturn Return,159                                     orc_rt_WrapperFunctionBuffer ArgBytes) {160  SPSWrapperFunction<SPSExpected<int32_t>(int32_t)>::handle(161      S, CallId, Return, ArgBytes,162      [](move_only_function<void(Expected<int32_t>)> Return, int N) {163        if (N % 2 == 0)164          Return(N >> 1);165        else166          Return(make_error<StringError>("N is not a multiple of 2"));167      });168}169 170TEST(SPSWrapperFunctionUtilsTest, TransparentConversionExpectedSuccessCase) {171  int32_t Result = 0;172  SPSWrapperFunction<SPSExpected<int32_t>(int32_t)>::call(173      DirectCaller(nullptr, halve_number_sps_wrapper),174      [&](Expected<Expected<int32_t>> R) {175        Result = cantFail(cantFail(std::move(R)));176      },177      2);178 179  EXPECT_EQ(Result, 1);180}181 182TEST(SPSWrapperFunctionUtilsTest, TransparentConversionExpectedFailureCase) {183  std::string ErrMsg;184  SPSWrapperFunction<SPSExpected<int32_t>(int32_t)>::call(185      DirectCaller(nullptr, halve_number_sps_wrapper),186      [&](Expected<Expected<int32_t>> R) {187        ErrMsg = toString(cantFail(std::move(R)).takeError());188      },189      3);190 191  EXPECT_EQ(ErrMsg, "N is not a multiple of 2");192}193 194template <size_t N> struct SPSOpCounter {};195 196namespace orc_rt {197template <size_t N>198class SPSSerializationTraits<SPSOpCounter<N>, OpCounter<N>> {199public:200  static size_t size(const OpCounter<N> &O) { return 0; }201  static bool serialize(SPSOutputBuffer &OB, const OpCounter<N> &O) {202    return true;203  }204  static bool deserialize(SPSInputBuffer &OB, OpCounter<N> &O) { return true; }205};206} // namespace orc_rt207 208static void209handle_with_reference_types_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,210                                        orc_rt_WrapperFunctionReturn Return,211                                        orc_rt_WrapperFunctionBuffer ArgBytes) {212  SPSWrapperFunction<void(213      SPSOpCounter<0>, SPSOpCounter<1>, SPSOpCounter<2>,214      SPSOpCounter<3>)>::handle(S, CallId, Return, ArgBytes,215                                [](move_only_function<void()> Return,216                                   OpCounter<0>, OpCounter<1> &,217                                   const OpCounter<2> &,218                                   OpCounter<3> &&) { Return(); });219}220 221TEST(SPSWrapperFunctionUtilsTest, HandlerWithReferences) {222  // Test that we can handle by-value, by-ref, by-const-ref, and by-rvalue-ref223  // arguments, and that we generate the expected number of moves.224  OpCounter<0>::reset();225  OpCounter<1>::reset();226  OpCounter<2>::reset();227  OpCounter<3>::reset();228 229  bool DidRun = false;230  SPSWrapperFunction<void(SPSOpCounter<0>, SPSOpCounter<1>, SPSOpCounter<2>,231                          SPSOpCounter<3>)>::232      call(233          DirectCaller(nullptr, handle_with_reference_types_sps_wrapper),234          [&](Error R) {235            cantFail(std::move(R));236            DidRun = true;237          },238          OpCounter<0>(), OpCounter<1>(), OpCounter<2>(), OpCounter<3>());239 240  EXPECT_TRUE(DidRun);241 242  // We expect two default constructions for each parameter: one for the243  // argument to call, and one for the object to deserialize into.244  EXPECT_EQ(OpCounter<0>::defaultConstructions(), 2U);245  EXPECT_EQ(OpCounter<1>::defaultConstructions(), 2U);246  EXPECT_EQ(OpCounter<2>::defaultConstructions(), 2U);247  EXPECT_EQ(OpCounter<3>::defaultConstructions(), 2U);248 249  // Pass-by-value: we expect two moves (one for SPS transparent conversion,250  // one to copy the value to the parameter), and no copies.251  EXPECT_EQ(OpCounter<0>::moves(), 2U);252  EXPECT_EQ(OpCounter<0>::copies(), 0U);253 254  // Pass-by-lvalue-reference: we expect one move (for SPS transparent255  // conversion), no copies.256  EXPECT_EQ(OpCounter<1>::moves(), 1U);257  EXPECT_EQ(OpCounter<1>::copies(), 0U);258 259  // Pass-by-const-lvalue-reference: we expect one move (for SPS transparent260  // conversion), no copies.261  EXPECT_EQ(OpCounter<2>::moves(), 1U);262  EXPECT_EQ(OpCounter<2>::copies(), 0U);263 264  // Pass-by-rvalue-reference: we expect one move (for SPS transparent265  // conversion), no copies.266  EXPECT_EQ(OpCounter<3>::moves(), 1U);267  EXPECT_EQ(OpCounter<3>::copies(), 0U);268}269 270namespace {271class Adder {272public:273  int32_t addSync(int32_t X, int32_t Y) { return X + Y; }274  void addAsync(move_only_function<void(int32_t)> Return, int32_t X,275                int32_t Y) {276    Return(addSync(X, Y));277  }278};279} // anonymous namespace280 281static void adder_add_async_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,282                                        orc_rt_WrapperFunctionReturn Return,283                                        orc_rt_WrapperFunctionBuffer ArgBytes) {284  SPSWrapperFunction<int32_t(SPSExecutorAddr, int32_t, int32_t)>::handle(285      S, CallId, Return, ArgBytes,286      WrapperFunction::handleWithAsyncMethod(&Adder::addAsync));287}288 289TEST(SPSWrapperFunctionUtilsTest, HandleWtihAsyncMethod) {290  auto A = std::make_unique<Adder>();291  int32_t Result = 0;292  SPSWrapperFunction<int32_t(SPSExecutorAddr, int32_t, int32_t)>::call(293      DirectCaller(nullptr, adder_add_async_sps_wrapper),294      [&](Expected<int32_t> R) { Result = cantFail(std::move(R)); },295      ExecutorAddr::fromPtr(A.get()), 41, 1);296 297  EXPECT_EQ(Result, 42);298}299 300static void adder_add_sync_sps_wrapper(orc_rt_SessionRef S, uint64_t CallId,301                                       orc_rt_WrapperFunctionReturn Return,302                                       orc_rt_WrapperFunctionBuffer ArgBytes) {303  SPSWrapperFunction<int32_t(SPSExecutorAddr, int32_t, int32_t)>::handle(304      S, CallId, Return, ArgBytes,305      WrapperFunction::handleWithSyncMethod(&Adder::addSync));306}307 308TEST(SPSWrapperFunctionUtilsTest, HandleWithSyncMethod) {309  auto A = std::make_unique<Adder>();310  int32_t Result = 0;311  SPSWrapperFunction<int32_t(SPSExecutorAddr, int32_t, int32_t)>::call(312      DirectCaller(nullptr, adder_add_sync_sps_wrapper),313      [&](Expected<int32_t> R) { Result = cantFail(std::move(R)); },314      ExecutorAddr::fromPtr(A.get()), 41, 1);315 316  EXPECT_EQ(Result, 42);317}318