Files
FEX-Emu--FEX/unittests/FEXLinuxTests/tests/thunks/thunk_testlib.cpp
T

115 lines
3.1 KiB
C++

#define GUEST_THUNK_LIBRARY
#include <dlfcn.h>
#include <stdexcept>
#include <catch2/catch_test_macros.hpp>
#include "../../../../ThunkLibs/libfex_thunk_test/api.h"
struct Fixture {
void* lib = []() {
auto ret = dlopen("libfex_thunk_test.so", RTLD_LAZY);
if (!ret) {
throw std::runtime_error("Failed to open lib\n");
}
return ret;
}();
#define GET_SYMBOL(name) decltype(&::name) name = (decltype(name))dlsym(lib, #name)
GET_SYMBOL(GetDoubledValue);
GET_SYMBOL(MakeOpaqueType);
GET_SYMBOL(ReadOpaqueTypeData);
GET_SYMBOL(DestroyOpaqueType);
GET_SYMBOL(MakeUnionType);
GET_SYMBOL(GetUnionTypeA);
GET_SYMBOL(MakeReorderingType);
GET_SYMBOL(GetReorderingTypeMember);
GET_SYMBOL(GetReorderingTypeMemberWithoutRepacking);
GET_SYMBOL(ModifyReorderingTypeMembers);
GET_SYMBOL(QueryOffsetOf);
GET_SYMBOL(RanCustomRepack);
GET_SYMBOL(FunctionWithDivergentSignature);
GET_SYMBOL(ReadData1);
};
TEST_CASE_METHOD(Fixture, "Trivial") {
CHECK(GetDoubledValue(10) == 20);
}
TEST_CASE_METHOD(Fixture, "Opaque data types") {
{
auto data = MakeOpaqueType(0x1234);
CHECK(ReadOpaqueTypeData(data) == 0x1234);
DestroyOpaqueType(data);
}
{
auto data = MakeUnionType(0x1, 0x2, 0x3, 0x4);
CHECK(GetUnionTypeA(&data) == 0x04030201);
}
}
TEST_CASE_METHOD(Fixture, "Automatic struct repacking") {
{
// Test repacking of return values
ReorderingType test_struct = MakeReorderingType(0x1234, 0x5678);
REQUIRE(test_struct.a == 0x1234);
REQUIRE(test_struct.b == 0x5678);
// Test offsets of the host-side guest_layout wrapper match the guest-side ones
CHECK(QueryOffsetOf(&test_struct, 0) == offsetof(ReorderingType, a));
CHECK(QueryOffsetOf(&test_struct, 1) == offsetof(ReorderingType, b));
// Test repacking of input pointers
CHECK(GetReorderingTypeMember(&test_struct, 0) == 0x1234);
CHECK(GetReorderingTypeMember(&test_struct, 1) == 0x5678);
// Test that we can force reinterpreting the data in guest layout as host layout
CHECK(GetReorderingTypeMemberWithoutRepacking(&test_struct, 0) == 0x5678);
CHECK(GetReorderingTypeMemberWithoutRepacking(&test_struct, 1) == 0x1234);
// Test repacking of output pointers
ModifyReorderingTypeMembers(&test_struct);
CHECK(GetReorderingTypeMember(&test_struct, 0) == 0x1235);
CHECK(GetReorderingTypeMember(&test_struct, 1) == 0x567a);
};
}
TEST_CASE_METHOD(Fixture, "Assisted struct repacking") {
CustomRepackedType data {};
CHECK(RanCustomRepack(&data) == 1);
}
TEST_CASE_METHOD(Fixture, "Function signature with differing parameter sizes") {
CHECK(FunctionWithDivergentSignature(DivType {1}, DivType {2}, DivType {3}, DivType {4}) == 0x01020304);
}
// Test Vulkan-like linked lists
TEST_CASE_METHOD(Fixture, "Assisted repacking of linked lists") {
const int s2_data = 0xcddeeff;
TestStruct2 s2 {
.Next = nullptr,
.Type = StructType::Struct2,
.Data1 = s2_data,
};
const int s1_data = 0x1234567;
TestStruct1 s1 {
.Next = &s2,
.Type = StructType::Struct1,
.Data2 = 0xab,
.Data1 = s1_data,
};
CHECK(ReadData1(&s1, 0) == s1_data);
CHECK(ReadData1(&s1, 1) == s2_data);
}