blob: 08e2a64cde331f7b5302c147d4740130549dba3b [file] [log] [blame]
//===- AllocActionTest.cpp ------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Tests for orc-rt's AllocAction.h APIs.
//
//===----------------------------------------------------------------------===//
#include "orc-rt/AllocAction.h"
#include "orc-rt/ExecutorAddress.h"
#include "orc-rt/SPSAllocAction.h"
#include "AllocActionTestUtils.h"
#include "gtest/gtest.h"
using namespace orc_rt;
TEST(AllocActionTest, DefaultConstruct) {
AllocAction AA;
EXPECT_FALSE(AA);
}
static orc_rt_WrapperFunctionBuffer noopAction(const char *ArgData,
size_t ArgSize) {
return WrapperFunctionBuffer().release();
}
TEST(AllocActionTest, ConstructWithAction) {
AllocAction AA(noopAction, WrapperFunctionBuffer());
EXPECT_TRUE(AA);
}
// Increments int via pointer.
static orc_rt_WrapperFunctionBuffer
increment_sps_allocaction(const char *ArgData, size_t ArgSize) {
return SPSAllocActionFunction<SPSExecutorAddr>::handle(
ArgData, ArgSize,
[](ExecutorAddr IntPtr) {
*IntPtr.toPtr<int *>() += 1;
return WrapperFunctionBuffer();
})
.release();
}
// Increments int via pointer.
static orc_rt_WrapperFunctionBuffer
decrement_sps_allocaction(const char *ArgData, size_t ArgSize) {
return SPSAllocActionFunction<SPSExecutorAddr>::handle(
ArgData, ArgSize,
[](ExecutorAddr IntPtr) {
*IntPtr.toPtr<int *>() -= 1;
return WrapperFunctionBuffer();
})
.release();
}
template <typename T>
static WrapperFunctionBuffer makeExecutorAddrBuffer(T *P) {
return *spsSerialize<SPSArgList<SPSExecutorAddr>>(ExecutorAddr::fromPtr(P));
}
TEST(AllocActionTest, RunBasicAction) {
int Val = 0;
AllocAction IncVal(increment_sps_allocaction, makeExecutorAddrBuffer(&Val));
EXPECT_TRUE(IncVal);
auto B = IncVal();
EXPECT_TRUE(B.empty());
EXPECT_EQ(Val, 1);
}
TEST(AllocActionTest, RunFinalizationActionsComplete) {
int Val = 0;
std::vector<AllocActionPair> InitialActions;
auto MakeAAOnVal = [&](AllocActionFn Fn) {
return *MakeAllocAction<SPSExecutorAddr>::from(Fn,
ExecutorAddr::fromPtr(&Val));
};
InitialActions.push_back({MakeAAOnVal(increment_sps_allocaction),
MakeAAOnVal(decrement_sps_allocaction)});
InitialActions.push_back({MakeAAOnVal(increment_sps_allocaction),
MakeAAOnVal(decrement_sps_allocaction)});
auto DeallocActions = cantFail(runFinalizeActions(std::move(InitialActions)));
EXPECT_EQ(Val, 2);
runDeallocActions(std::move(DeallocActions));
EXPECT_EQ(Val, 0);
}
static orc_rt_WrapperFunctionBuffer fail_sps_allocaction(const char *ArgData,
size_t ArgSize) {
return WrapperFunctionBuffer::createOutOfBandError("failed").release();
}
TEST(AllocActionTest, RunFinalizeActionsFail) {
int Val = 0;
std::vector<AllocActionPair> InitialActions;
auto MakeAAOnVal = [&](AllocActionFn Fn) {
return *MakeAllocAction<SPSExecutorAddr>::from(Fn,
ExecutorAddr::fromPtr(&Val));
};
InitialActions.push_back({MakeAAOnVal(increment_sps_allocaction),
MakeAAOnVal(decrement_sps_allocaction)});
InitialActions.push_back({*MakeAllocAction<>::from(fail_sps_allocaction),
MakeAAOnVal(decrement_sps_allocaction)});
auto DeallocActions = runFinalizeActions(std::move(InitialActions));
if (DeallocActions) {
ADD_FAILURE() << "Failed to report error from runFinalizeActions";
return;
}
EXPECT_EQ(toString(DeallocActions.takeError()), std::string("failed"));
// Check that we ran the decrement corresponding to the first increment.
EXPECT_EQ(Val, 0);
}
TEST(AllocActionTest, RunFinalizeActionsNullFinalize) {
int Val = 0;
std::vector<AllocActionPair> InitialActions;
auto MakeAAOnVal = [&](AllocActionFn Fn) {
return *MakeAllocAction<SPSExecutorAddr>::from(Fn,
ExecutorAddr::fromPtr(&Val));
};
InitialActions.push_back({MakeAAOnVal(increment_sps_allocaction),
MakeAAOnVal(decrement_sps_allocaction)});
InitialActions.push_back({*MakeAllocAction<>::from(nullptr),
MakeAAOnVal(decrement_sps_allocaction)});
auto DeallocActions = cantFail(runFinalizeActions(std::move(InitialActions)));
// Both dealloc actions should be included in the returned list, despite one
// of them having a null finalize action.
EXPECT_EQ(DeallocActions.size(), 2U);
runDeallocActions(std::move(DeallocActions));
EXPECT_EQ(Val, -1);
}
TEST(AllocActionTest, RunFinalizeActionsNullDealloc) {
int Val = 0;
std::vector<AllocActionPair> InitialActions;
auto MakeAAOnVal = [&](AllocActionFn Fn) {
return *MakeAllocAction<SPSExecutorAddr>::from(Fn,
ExecutorAddr::fromPtr(&Val));
};
InitialActions.push_back({MakeAAOnVal(increment_sps_allocaction),
MakeAAOnVal(decrement_sps_allocaction)});
InitialActions.push_back({MakeAAOnVal(increment_sps_allocaction),
*MakeAllocAction<>::from(nullptr)});
auto DeallocActions = cantFail(runFinalizeActions(std::move(InitialActions)));
// Null dealloc actions should be filtered out of the returned list.
EXPECT_EQ(DeallocActions.size(), 1U);
runDeallocActions(std::move(DeallocActions));
EXPECT_EQ(Val, 1);
}