|
10 | 10 | //
|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
| 13 | +#include "CommonTestUtils.h" |
| 14 | + |
13 | 15 | #include "orc-rt/SPSWrapperFunction.h"
|
14 | 16 | #include "orc-rt/WrapperFunction.h"
|
15 | 17 | #include "orc-rt/move_only_function.h"
|
@@ -218,3 +220,80 @@ TEST(SPSWrapperFunctionUtilsTest, TestFunctionReturningExpectedFailureCase) {
|
218 | 220 |
|
219 | 221 | EXPECT_EQ(ErrMsg, "N is not a multiple of 2");
|
220 | 222 | }
|
| 223 | + |
| 224 | +template <size_t N> struct SPSOpCounter {}; |
| 225 | + |
| 226 | +namespace orc_rt { |
| 227 | +template <size_t N> |
| 228 | +class SPSSerializationTraits<SPSOpCounter<N>, OpCounter<N>> { |
| 229 | +public: |
| 230 | + static size_t size(const OpCounter<N> &O) { return 0; } |
| 231 | + static bool serialize(SPSOutputBuffer &OB, const OpCounter<N> &O) { |
| 232 | + return true; |
| 233 | + } |
| 234 | + static bool deserialize(SPSInputBuffer &OB, OpCounter<N> &O) { return true; } |
| 235 | +}; |
| 236 | +} // namespace orc_rt |
| 237 | + |
| 238 | +static void |
| 239 | +handle_with_reference_types_sps_wrapper(orc_rt_SessionRef Session, |
| 240 | + void *CallCtx, |
| 241 | + orc_rt_WrapperFunctionReturn Return, |
| 242 | + orc_rt_WrapperFunctionBuffer ArgBytes) { |
| 243 | + SPSWrapperFunction<void( |
| 244 | + SPSOpCounter<0>, SPSOpCounter<1>, SPSOpCounter<2>, |
| 245 | + SPSOpCounter<3>)>::handle(Session, CallCtx, Return, ArgBytes, |
| 246 | + [](move_only_function<void()> Return, |
| 247 | + OpCounter<0>, OpCounter<1> &, |
| 248 | + const OpCounter<2> &, |
| 249 | + OpCounter<3> &&) { Return(); }); |
| 250 | +} |
| 251 | + |
| 252 | +TEST(SPSWrapperFunctionUtilsTest, TestHandlerWithReferences) { |
| 253 | + // Test that we can handle by-value, by-ref, by-const-ref, and by-rvalue-ref |
| 254 | + // arguments, and that we generate the expected number of moves. |
| 255 | + OpCounter<0>::reset(); |
| 256 | + OpCounter<1>::reset(); |
| 257 | + OpCounter<2>::reset(); |
| 258 | + OpCounter<3>::reset(); |
| 259 | + |
| 260 | + bool DidRun = false; |
| 261 | + SPSWrapperFunction<void(SPSOpCounter<0>, SPSOpCounter<1>, SPSOpCounter<2>, |
| 262 | + SPSOpCounter<3>)>:: |
| 263 | + call( |
| 264 | + DirectCaller(nullptr, handle_with_reference_types_sps_wrapper), |
| 265 | + [&](Error R) { |
| 266 | + cantFail(std::move(R)); |
| 267 | + DidRun = true; |
| 268 | + }, |
| 269 | + OpCounter<0>(), OpCounter<1>(), OpCounter<2>(), OpCounter<3>()); |
| 270 | + |
| 271 | + EXPECT_TRUE(DidRun); |
| 272 | + |
| 273 | + // We expect two default constructions for each parameter: one for the |
| 274 | + // argument to call, and one for the object to deserialize into. |
| 275 | + EXPECT_EQ(OpCounter<0>::defaultConstructions(), 2U); |
| 276 | + EXPECT_EQ(OpCounter<1>::defaultConstructions(), 2U); |
| 277 | + EXPECT_EQ(OpCounter<2>::defaultConstructions(), 2U); |
| 278 | + EXPECT_EQ(OpCounter<3>::defaultConstructions(), 2U); |
| 279 | + |
| 280 | + // Pass-by-value: we expect two moves (one for SPS transparent conversion, |
| 281 | + // one to copy the value to the parameter), and no copies. |
| 282 | + EXPECT_EQ(OpCounter<0>::moves(), 2U); |
| 283 | + EXPECT_EQ(OpCounter<0>::copies(), 0U); |
| 284 | + |
| 285 | + // Pass-by-lvalue-reference: we expect one move (for SPS transparent |
| 286 | + // conversion), no copies. |
| 287 | + EXPECT_EQ(OpCounter<1>::moves(), 1U); |
| 288 | + EXPECT_EQ(OpCounter<1>::copies(), 0U); |
| 289 | + |
| 290 | + // Pass-by-const-lvalue-reference: we expect one move (for SPS transparent |
| 291 | + // conversion), no copies. |
| 292 | + EXPECT_EQ(OpCounter<2>::moves(), 1U); |
| 293 | + EXPECT_EQ(OpCounter<2>::copies(), 0U); |
| 294 | + |
| 295 | + // Pass-by-rvalue-reference: we expect one move (for SPS transparent |
| 296 | + // conversion), no copies. |
| 297 | + EXPECT_EQ(OpCounter<3>::moves(), 1U); |
| 298 | + EXPECT_EQ(OpCounter<3>::copies(), 0U); |
| 299 | +} |
0 commit comments