Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions offload/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ function(add_offload_unittest test_dirname)

add_unittest(OffloadUnitTests "${target_name}"
${CMAKE_CURRENT_SOURCE_DIR}/common/Environment.cpp
${CMAKE_CURRENT_SOURCE_DIR}/common/Properties.cpp
${files})
add_dependencies(${target_name} ${PLUGINS_TEST_COMMON} offload_device_binaries)
target_compile_definitions(${target_name} PRIVATE DEVICE_CODE_PATH="${OFFLOAD_TEST_DEVICE_CODE_PATH}")
Expand Down
3 changes: 1 addition & 2 deletions offload/unittests/OffloadAPI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ add_subdirectory(device_code)
add_offload_unittest("device"
device/olIterateDevices.cpp
device/olGetDeviceInfo.cpp
device/olGetDeviceInfoSize.cpp
device/olGetHostInfo.cpp)
device/olGetDeviceInfoSize.cpp)

add_offload_unittest("event"
event/olCreateEvent.cpp
Expand Down
147 changes: 143 additions & 4 deletions offload/unittests/OffloadAPI/common/Fixtures.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <OffloadAPI.h>
#include <OffloadPrint.hpp>
#include <fstream>
#include <gtest/gtest.h>
#include <optional>
#include <string>
Expand Down Expand Up @@ -207,6 +208,40 @@ struct OffloadDeviceTest
ol_device_handle_t Device = nullptr;
};

template <class T> using OffloadParam = std::tuple<TestEnvironment::Device, T>;

template <class T>
struct OffloadDeviceTestWithParam
: OffloadTest,
::testing::WithParamInterface<OffloadParam<T>> {
void SetUp() override {
RETURN_ON_FATAL_FAILURE(OffloadTest::SetUp());

auto &DeviceParam = std::get<0>(this->GetParam());
Device = DeviceParam.Handle;
if (Device == nullptr)
GTEST_SKIP() << "No available devices.";
}

ol_platform_backend_t getPlatformBackend() const {
ol_platform_handle_t Platform = nullptr;
if (olGetDeviceInfo(Device, OL_DEVICE_INFO_PLATFORM,
sizeof(ol_platform_handle_t), &Platform))
return OL_PLATFORM_BACKEND_UNKNOWN;
ol_platform_backend_t Backend;
if (olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND,
sizeof(ol_platform_backend_t), &Backend))
return OL_PLATFORM_BACKEND_UNKNOWN;
return Backend;
}

const OffloadParam<T> &getParamTuple() const { return this->GetParam(); }

const T &getTestParam() { return std::get<1>(getParamTuple()); }

ol_device_handle_t Device = nullptr;
};

struct OffloadPlatformTest : OffloadDeviceTest {
void SetUp() override {
RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::SetUp());
Expand All @@ -219,6 +254,19 @@ struct OffloadPlatformTest : OffloadDeviceTest {
ol_platform_handle_t Platform = nullptr;
};

template <typename T>
struct OffloadPlatformTestWithParam : OffloadDeviceTestWithParam<T> {
void SetUp() override {
RETURN_ON_FATAL_FAILURE(OffloadDeviceTestWithParam<T>::SetUp());

ASSERT_SUCCESS(olGetDeviceInfo(this->Device, OL_DEVICE_INFO_PLATFORM,
sizeof(Platform), &Platform));
ASSERT_NE(Platform, nullptr);
}

ol_platform_handle_t Platform = nullptr;
};

// Fixture for a generic program test. If you want a different program, use
// offloadQueueTest and create your own program handle with the binary you want.
struct OffloadProgramTest : OffloadDeviceTest {
Expand All @@ -244,6 +292,30 @@ struct OffloadProgramTest : OffloadDeviceTest {
std::unique_ptr<llvm::MemoryBuffer> DeviceBin;
};

template <typename T>
struct OffloadProgramTestWithParam : OffloadDeviceTestWithParam<T> {
void SetUp() override { SetUpWith("foo"); }

void SetUpWith(const char *ProgramName) {
RETURN_ON_FATAL_FAILURE(OffloadDeviceTestWithParam<T>::SetUp());
ASSERT_TRUE(TestEnvironment::loadDeviceBinary(ProgramName, this->Device,
DeviceBin));
ASSERT_GE(DeviceBin->getBufferSize(), 0lu);
ASSERT_SUCCESS(olCreateProgram(this->Device, DeviceBin->getBufferStart(),
DeviceBin->getBufferSize(), &Program));
}

void TearDown() override {
if (Program) {
olDestroyProgram(Program);
}
RETURN_ON_FATAL_FAILURE(OffloadDeviceTestWithParam<T>::TearDown());
}

ol_program_handle_t Program = nullptr;
std::unique_ptr<llvm::MemoryBuffer> DeviceBin;
};

struct OffloadKernelTest : OffloadProgramTest {
void SetUp() override {
RETURN_ON_FATAL_FAILURE(OffloadProgramTest::SetUp());
Expand Down Expand Up @@ -271,6 +343,22 @@ struct OffloadGlobalTest : OffloadProgramTest {
ol_symbol_handle_t Global = nullptr;
};

template <typename T>
struct OffloadGlobalTestWithParam : OffloadProgramTestWithParam<T> {
void SetUp() override {
RETURN_ON_FATAL_FAILURE(
OffloadProgramTestWithParam<T>::SetUpWith("global"));
ASSERT_SUCCESS(olGetSymbol(this->Program, "global",
OL_SYMBOL_KIND_GLOBAL_VARIABLE, &Global));
}

void TearDown() override {
RETURN_ON_FATAL_FAILURE(OffloadProgramTestWithParam<T>::TearDown());
}

ol_symbol_handle_t Global = nullptr;
};

struct OffloadQueueTest : OffloadDeviceTest {
void SetUp() override {
RETURN_ON_FATAL_FAILURE(OffloadDeviceTest::SetUp());
Expand Down Expand Up @@ -338,13 +426,64 @@ struct LaunchSingleKernelTestBase : LaunchKernelTestBase {
ol_symbol_handle_t Kernel = nullptr;
};

using DevicesVec = std::vector<TestEnvironment::Device>;

inline DevicesVec getDevicesAndHost() {
DevicesVec Res(TestEnvironment::getDevices());
TestEnvironment::Device Host{TestEnvironment::getHostDevice(), "HOST"};

Res.push_back(Host);

return Res;
}

template <class T>
inline std::string
defaultPrinterWithParam(const ::testing::TestParamInfo<OffloadParam<T>> &info) {
auto device = std::get<0>(info.param);
auto param = std::get<1>(info.param);

std::string placeholder;
llvm::raw_string_ostream ss(placeholder);

ss << device.Name << "__" << param;

return SanitizeString(ss.str());
}

inline std::string
defaultPrinter(const ::testing::TestParamInfo<TestEnvironment::Device> &info) {
return SanitizeString(info.param.Name);
}

// Devices might not be available for offload testing, so allow uninstantiated
// tests (as the device list will be empty). This means that all tests requiring
// a device will be silently skipped.
#define OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE(FIXTURE) \
INSTANTIATE_TEST_SUITE_P(, FIXTURE, \
::testing::ValuesIn(TestEnvironment::getDevices()), \
defaultPrinter); \
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FIXTURE)

#define OFFLOAD_TESTS_INSTANTIATE_DEVICE_FIXTURE_WITH_PARAM(FIXTURE, VALUES, \
PRINTER) \
INSTANTIATE_TEST_SUITE_P( \
, FIXTURE, \
testing::Combine(::testing::ValuesIn(TestEnvironment::getDevices()), \
::testing::ValuesIn(VALUES)), \
PRINTER); \
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FIXTURE)

#define OFFLOAD_TESTS_INSTANTIATE_HOST_DEVICE_FIXTURE_WITH_PARAM( \
FIXTURE, VALUES, PRINTER) \
INSTANTIATE_TEST_SUITE_P( \
, FIXTURE, \
testing::Combine(::testing::ValuesIn(getDevicesAndHost()), \
::testing::ValuesIn(VALUES)), \
PRINTER); \
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FIXTURE)

#define OFFLOAD_TESTS_INSTANTIATE_HOST_DEVICE_FIXTURE(FIXTURE) \
INSTANTIATE_TEST_SUITE_P( \
, FIXTURE, ::testing::ValuesIn(TestEnvironment::getDevices()), \
[](const ::testing::TestParamInfo<TestEnvironment::Device> &info) { \
return SanitizeString(info.param.Name); \
}); \
, FIXTURE, ::testing::ValuesIn(getDevicesAndHost()), defaultPrinter); \
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FIXTURE)
87 changes: 87 additions & 0 deletions offload/unittests/OffloadAPI/common/Properties.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "Properties.hpp"

// ol_device_info_t
DeviceInfoProp PropBool{OL_DEVICE_INFO_SINGLE_FP_SUPPORT,
OL_DEVICE_INFO_DOUBLE_FP_SUPPORT,
OL_DEVICE_INFO_HALF_FP_SUPPORT};
DeviceInfoProperties BoolProperties =
createPropertyTuples(sizeof(bool), PropBool);

DeviceInfoProp PropUint32{OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE,
OL_DEVICE_INFO_MAX_WORK_SIZE,
OL_DEVICE_INFO_VENDOR_ID,
OL_DEVICE_INFO_NUM_COMPUTE_UNITS,
OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_CHAR,
OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_SHORT,
OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_INT,
OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_LONG,
OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_FLOAT,
OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_DOUBLE,
OL_DEVICE_INFO_NATIVE_VECTOR_WIDTH_HALF,
OL_DEVICE_INFO_MAX_CLOCK_FREQUENCY,
OL_DEVICE_INFO_MEMORY_CLOCK_RATE,
OL_DEVICE_INFO_ADDRESS_BITS};
DeviceInfoProperties Uint32Properties =
createPropertyTuples(sizeof(uint32_t), PropUint32);

DeviceInfoProp PropUint64{OL_DEVICE_INFO_MAX_MEM_ALLOC_SIZE,
OL_DEVICE_INFO_GLOBAL_MEM_SIZE,
OL_DEVICE_INFO_WORK_GROUP_LOCAL_MEM_SIZE};
DeviceInfoProperties Uint64Properties =
createPropertyTuples(sizeof(uint64_t), PropUint64);

DeviceInfoProp PropCapabilitiesFlags{OL_DEVICE_INFO_SINGLE_FP_CONFIG,
OL_DEVICE_INFO_HALF_FP_CONFIG,
OL_DEVICE_INFO_DOUBLE_FP_CONFIG};
// sizeof(ol_device_fp_capability_flags_t) == sizegof(uint32_t)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

siegof?.

maybe static assert if you need check like this

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not needed, I have thought that an informative reminder in a comment would be useful

DeviceInfoProperties CapabilitesFlagsProperties = createPropertyTuples(
sizeof(ol_device_fp_capability_flags_t), PropCapabilitiesFlags);

DeviceInfoProp PropDeviceType{OL_DEVICE_INFO_TYPE};
DeviceInfoProperties DeviceTypeProperties =
createPropertyTuples(sizeof(ol_device_type_t), PropDeviceType);

DeviceInfoProp PropPlatform{OL_DEVICE_INFO_PLATFORM};
DeviceInfoProperties PlatformProperties =
createPropertyTuples(sizeof(ol_platform_handle_t), PropPlatform);

DeviceInfoProp PropNames{OL_DEVICE_INFO_NAME, OL_DEVICE_INFO_PRODUCT_NAME,
OL_DEVICE_INFO_UID, OL_DEVICE_INFO_VENDOR,
OL_DEVICE_INFO_DRIVER_VERSION};
DeviceInfoProperties NamesProperties = createPropertyTuples(0, PropNames);

DeviceInfoProp PropDimensions{OL_DEVICE_INFO_MAX_WORK_GROUP_SIZE_PER_DIMENSION,
OL_DEVICE_INFO_MAX_WORK_SIZE_PER_DIMENSION};
DeviceInfoProperties DimensionsProperties =
createPropertyTuples(sizeof(ol_dimensions_t), PropDimensions);

DeviceInfoPropertiesTypes propertiesTypes =
createTypesMap({BoolProperties, Uint32Properties, Uint64Properties,
CapabilitesFlagsProperties});

// ol_symbol_info_t
SymbolInfoProp PropSymbolInfoGlobal{OL_SYMBOL_INFO_KIND,
OL_SYMBOL_INFO_GLOBAL_VARIABLE_ADDRESS,
OL_SYMBOL_INFO_GLOBAL_VARIABLE_SIZE};
SymbolInfoProperties SymbolGlobalProperties{
{sizeof(ol_symbol_kind_t), OL_SYMBOL_INFO_KIND},
{sizeof(void *), OL_SYMBOL_INFO_GLOBAL_VARIABLE_ADDRESS},
{sizeof(size_t), OL_SYMBOL_INFO_GLOBAL_VARIABLE_SIZE}};

// ol_platform_info_t
ol_platform_info_t PlatformInfoNames[3] = {OL_PLATFORM_INFO_NAME,
OL_PLATFORM_INFO_VENDOR_NAME,
OL_PLATFORM_INFO_VERSION};

// ol_alloc_type_t
ol_alloc_type_t AllocTypes[3] = {OL_ALLOC_TYPE_DEVICE, OL_ALLOC_TYPE_MANAGED,
OL_ALLOC_TYPE_HOST};

// ol_mem_info_t
MemInfoProp PropMemInfo{OL_MEM_INFO_DEVICE, OL_MEM_INFO_BASE, OL_MEM_INFO_SIZE,
OL_MEM_INFO_TYPE};
MemInfoProperties MemInfoSizeProperties{
{sizeof(ol_device_handle_t), OL_MEM_INFO_DEVICE},
{sizeof(void *), OL_MEM_INFO_BASE},
{sizeof(size_t), OL_MEM_INFO_SIZE},
{sizeof(ol_alloc_type_t), OL_MEM_INFO_TYPE}};
Loading