[llvm] [libsycl] Add UT build and min test set (PR #199915)
Kseniya Tikhomirova via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 05:01:17 PDT 2026
https://github.com/KseniyaTikhomirova updated https://github.com/llvm/llvm-project/pull/199915
>From d4199af55cdddc265454e2c3ed955f312e60c6ab Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Wed, 8 Apr 2026 08:24:49 -0700
Subject: [PATCH 1/2] [libsycl] Add UT build and min test set
Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
libsycl/CMakeLists.txt | 10 +
libsycl/cmake/Modules/AddUnitTest.cmake | 46 +++
libsycl/docs/index.rst | 3 +-
libsycl/src/CMakeLists.txt | 3 +-
libsycl/src/detail/device_kernel_info.hpp | 6 +-
libsycl/src/detail/program_manager.cpp | 5 +-
libsycl/src/detail/program_manager.hpp | 2 +-
libsycl/unittests/CMakeLists.txt | 10 +
libsycl/unittests/common/device_images.hpp | 57 ++++
libsycl/unittests/mock/CMakeLists.txt | 20 ++
libsycl/unittests/mock/helpers.cpp | 276 ++++++++++++++++++
libsycl/unittests/mock/helpers.hpp | 150 ++++++++++
libsycl/unittests/mock/mock.cpp | 93 ++++++
libsycl/unittests/platform/CMakeLists.txt | 3 +
libsycl/unittests/platform/get_platforms.cpp | 29 ++
.../unittests/program_manager/CMakeLists.txt | 3 +
.../register_and_unregister.cpp | 129 ++++++++
libsycl/unittests/queue/CMakeLists.txt | 3 +
libsycl/unittests/queue/queue.cpp | 30 ++
19 files changed, 870 insertions(+), 8 deletions(-)
create mode 100644 libsycl/cmake/Modules/AddUnitTest.cmake
create mode 100644 libsycl/unittests/CMakeLists.txt
create mode 100644 libsycl/unittests/common/device_images.hpp
create mode 100644 libsycl/unittests/mock/CMakeLists.txt
create mode 100644 libsycl/unittests/mock/helpers.cpp
create mode 100644 libsycl/unittests/mock/helpers.hpp
create mode 100644 libsycl/unittests/mock/mock.cpp
create mode 100644 libsycl/unittests/platform/CMakeLists.txt
create mode 100644 libsycl/unittests/platform/get_platforms.cpp
create mode 100644 libsycl/unittests/program_manager/CMakeLists.txt
create mode 100644 libsycl/unittests/program_manager/register_and_unregister.cpp
create mode 100644 libsycl/unittests/queue/CMakeLists.txt
create mode 100644 libsycl/unittests/queue/queue.cpp
diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt
index ae3fd4359c3f2..4aea6ba7fc60e 100644
--- a/libsycl/CMakeLists.txt
+++ b/libsycl/CMakeLists.txt
@@ -61,6 +61,7 @@ endif()
set(LIBSYCL_INCLUDE_DIR include)
set(LIBSYCL_BUILD_INCLUDE_DIR ${LLVM_BINARY_DIR}/${LIBSYCL_INCLUDE_DIR})
set(LIBSYCL_SOURCE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
+set(LIBSYCL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBSYCL_LIBRARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBSYCL_LIBRARY_DIR})
@@ -133,6 +134,9 @@ add_custom_target(libsycl-runtime-libraries
DEPENDS ${LIBSYCL_RT_LIBS}
)
+# Shared object-library target name used by libsycl and unit tests.
+set(LIBSYCL_OBJ_TARGET sycl_object)
+
add_subdirectory(src)
add_subdirectory(tools)
@@ -145,3 +149,9 @@ add_custom_target(libsycl-toolchain ALL
sycl-ls
COMMENT "Building libsycl toolchain..."
)
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
+
+if(LLVM_INCLUDE_TESTS)
+ add_subdirectory(unittests)
+endif()
diff --git a/libsycl/cmake/Modules/AddUnitTest.cmake b/libsycl/cmake/Modules/AddUnitTest.cmake
new file mode 100644
index 0000000000000..489f340ac9600
--- /dev/null
+++ b/libsycl/cmake/Modules/AddUnitTest.cmake
@@ -0,0 +1,46 @@
+function(add_sycl_unittest test_dirname)
+ # Enable exception handling for these unit tests
+ set(LLVM_REQUIRES_EH ON)
+ set(LLVM_REQUIRES_RTTI ON)
+
+ add_unittest(LibsyclUnitTests ${test_dirname}
+ $<TARGET_OBJECTS:${LIBSYCL_OBJ_TARGET}> ${ARGN})
+ target_compile_definitions(${test_dirname}
+ PRIVATE _LIBSYCL_BUILDING_LIBRARY)
+
+ add_custom_target(check-sycl-${test_dirname}
+ ${CMAKE_COMMAND} -E env
+ ${CMAKE_CURRENT_BINARY_DIR}/${test_dirname}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS
+ ${test_dirname}
+ )
+
+ add_dependencies(check-sycl-unittests check-sycl-${test_dirname})
+
+ target_link_libraries(${test_dirname}
+ PRIVATE
+ ol_mock
+ # required for fake device images creation
+ LLVMFrontendOffloading
+ LLVMObject
+ LLVMSupport
+ )
+
+ target_include_directories(${test_dirname}
+ PRIVATE SYSTEM
+ ${LIBSYCL_BUILD_INCLUDE_DIR}
+ ${LIBSYCL_SOURCE_DIR}/src/
+ ${LIBSYCL_SOURCE_DIR}/unittests/
+ $<TARGET_PROPERTY:LLVMOffload,INTERFACE_INCLUDE_DIRECTORIES>
+ ${LLVM_MAIN_INCLUDE_DIR}
+ )
+ if (UNIX)
+ # These warnings are coming from Google Test code.
+ target_compile_options(${test_dirname}
+ PRIVATE
+ -Wno-unused-parameter
+ -Wno-inconsistent-missing-override
+ )
+ endif()
+endfunction()
diff --git a/libsycl/docs/index.rst b/libsycl/docs/index.rst
index 9aa36b4a54c57..9fcfbffb22732 100644
--- a/libsycl/docs/index.rst
+++ b/libsycl/docs/index.rst
@@ -124,4 +124,5 @@ TODO for added SYCL classes
* ``event``: get_wait_list, get_info, get_profiling_info, wait_and_throw & default ctor are not implemented
* general opens:
- * define a way to report errors from object dtors.
\ No newline at end of file
+ * define a way to report errors from object dtors
+ * unittests: add functions to reset libsycl internal state completely (static variables)
diff --git a/libsycl/src/CMakeLists.txt b/libsycl/src/CMakeLists.txt
index 346251882dd78..c591a162db2f8 100644
--- a/libsycl/src/CMakeLists.txt
+++ b/libsycl/src/CMakeLists.txt
@@ -1,6 +1,5 @@
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../runtimes/cmake/Modules")
include(WarningFlags)
-
function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME)
cmake_parse_arguments(ARG "" "" "COMPILE_OPTIONS;SOURCES" ${ARGN})
@@ -107,7 +106,7 @@ set(LIBSYCL_SOURCES
)
add_sycl_rt_library(${LIBSYCL_LIB_NAME}
- sycl_object
+ ${LIBSYCL_OBJ_TARGET}
${LIBSYCL_SHARED_OUTPUT_NAME}
SOURCES
${LIBSYCL_SOURCES})
diff --git a/libsycl/src/detail/device_kernel_info.hpp b/libsycl/src/detail/device_kernel_info.hpp
index 148e2e366777d..d5194f7619cd5 100644
--- a/libsycl/src/detail/device_kernel_info.hpp
+++ b/libsycl/src/detail/device_kernel_info.hpp
@@ -40,6 +40,9 @@ class DeviceKernelInfo {
/// \return the name of this kernel.
std::string_view getName() { return MName; }
+ /// \return the device image containing the device code of this kernel.
+ DeviceImageManager &getDeviceImage() const { return MDeviceImage; }
+
private:
std::unordered_map<ol_device_handle_t, ol_symbol_handle_t> MBuiltKernels;
@@ -58,9 +61,6 @@ class DeviceKernelInfo {
return KernelIt->second;
}
- /// \return the device image containing the device code of this kernel.
- DeviceImageManager &getDeviceImage() const { return MDeviceImage; }
-
/// Attaches a liboffload kernel handle to this device kernel info object.
/// \param Device the device the kernel symbol was created for.
/// \param Kernel the liboffload kernel symbol to attach.
diff --git a/libsycl/src/detail/program_manager.cpp b/libsycl/src/detail/program_manager.cpp
index 08fe634614f51..4bea4aeb2abff 100644
--- a/libsycl/src/detail/program_manager.cpp
+++ b/libsycl/src/detail/program_manager.cpp
@@ -32,9 +32,12 @@ void ProgramAndKernelManager::registerFatBin(const void *BinaryStart,
llvm::StringRef(static_cast<const char *>(BinaryStart), Size),
/*Identifier=*/"");
auto BinOrErr = llvm::object::OffloadBinary::create(MBR);
- if (!BinOrErr || BinOrErr->empty())
+ if (!BinOrErr) {
+ llvm::consumeError(BinOrErr.takeError());
throw sycl::exception(sycl::make_error_code(sycl::errc::runtime),
"Failed to parse OffloadBinary");
+ }
+ assert(!BinOrErr->empty() && "OffloadBinary must contain at least one entry");
DeviceImageManagerVec Images;
Images.reserve(BinOrErr->size());
diff --git a/libsycl/src/detail/program_manager.hpp b/libsycl/src/detail/program_manager.hpp
index 6127f092b42e6..cf0c999054475 100644
--- a/libsycl/src/detail/program_manager.hpp
+++ b/libsycl/src/detail/program_manager.hpp
@@ -86,7 +86,7 @@ class ProgramAndKernelManager {
ol_symbol_handle_t getOrCreateKernel(DeviceKernelInfo &KernelInfo,
DeviceImpl &Device);
-private:
+protected:
ProgramAndKernelManager() = default;
~ProgramAndKernelManager() = default;
ProgramAndKernelManager(ProgramAndKernelManager const &) = delete;
diff --git a/libsycl/unittests/CMakeLists.txt b/libsycl/unittests/CMakeLists.txt
new file mode 100644
index 0000000000000..5fa7b6ada0cb4
--- /dev/null
+++ b/libsycl/unittests/CMakeLists.txt
@@ -0,0 +1,10 @@
+include(AddUnitTest)
+
+add_custom_target(LibsyclUnitTests)
+
+add_custom_target(check-sycl-unittests)
+
+add_subdirectory(mock)
+add_subdirectory(platform)
+add_subdirectory(program_manager)
+add_subdirectory(queue)
diff --git a/libsycl/unittests/common/device_images.hpp b/libsycl/unittests/common/device_images.hpp
new file mode 100644
index 0000000000000..e9b344a684b7a
--- /dev/null
+++ b/libsycl/unittests/common/device_images.hpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains common fake device-image data used by libsycl unit
+/// tests.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBSYCL_UNITTESTS_COMMON_DEVICE_IMAGES_HPP
+#define _LIBSYCL_UNITTESTS_COMMON_DEVICE_IMAGES_HPP
+
+#include <detail/device_binary_structures.hpp>
+
+#include <llvm/Frontend/Offloading/Utility.h>
+#include <llvm/Object/OffloadBinary.h>
+
+namespace sycl::unittest {
+
+inline llvm::object::OffloadBinary::OffloadingImage createSYCLImage(
+ llvm::StringRef SymbolsBlob,
+ llvm::object::ImageKind ImageKind = llvm::object::IMG_SPIRV,
+ llvm::object::OffloadKind OffloadKind = llvm::object::OFK_SYCL) {
+ llvm::object::OffloadBinary::OffloadingImage Image;
+ Image.TheImageKind = ImageKind;
+ Image.TheOffloadKind = OffloadKind;
+ Image.Flags = 0;
+ Image.StringData["triple"] = sycl::detail::DeviceBinaryTripleSPIRV64;
+ Image.StringData["compile-opts"] = "";
+ Image.StringData["link-opts"] = "";
+ Image.StringData["symbols"] = SymbolsBlob;
+ static constexpr char DummyImageData[] = "dummy image data";
+ Image.Image = llvm::MemoryBuffer::getMemBufferCopy(
+ llvm::StringRef(DummyImageData, sizeof(DummyImageData)));
+ return Image;
+}
+
+inline llvm::SmallString<0> createSYCLDeviceBinary(
+ llvm::ArrayRef<llvm::StringRef> KernelNames,
+ llvm::object::ImageKind ImageKind = llvm::object::IMG_SPIRV,
+ llvm::object::OffloadKind OffloadKind = llvm::object::OFK_SYCL) {
+ llvm::SmallString<0> SymbolsBlob;
+ llvm::offloading::sycl::writeSymbolTable(KernelNames, SymbolsBlob);
+
+ llvm::object::OffloadBinary::OffloadingImage Image =
+ createSYCLImage(SymbolsBlob, ImageKind, OffloadKind);
+ return llvm::object::OffloadBinary::write(Image);
+}
+
+} // namespace sycl::unittest
+
+#endif // _LIBSYCL_UNITTESTS_COMMON_DEVICE_IMAGES_HPP
diff --git a/libsycl/unittests/mock/CMakeLists.txt b/libsycl/unittests/mock/CMakeLists.txt
new file mode 100644
index 0000000000000..30999527fd095
--- /dev/null
+++ b/libsycl/unittests/mock/CMakeLists.txt
@@ -0,0 +1,20 @@
+add_library(ol_mock STATIC
+ "${CMAKE_CURRENT_SOURCE_DIR}/mock.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/helpers.cpp"
+)
+# LLVMOffload provides generated Offload API headers used by the mock.
+add_dependencies(ol_mock
+ LLVMOffload
+ llvm_gtest
+)
+target_include_directories(ol_mock
+ PRIVATE
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ $<TARGET_PROPERTY:LLVMOffload,INTERFACE_INCLUDE_DIRECTORIES>
+ $<TARGET_PROPERTY:llvm_gtest,INTERFACE_INCLUDE_DIRECTORIES>
+)
+
+target_link_libraries(ol_mock
+ PRIVATE
+ llvm_gtest
+)
diff --git a/libsycl/unittests/mock/helpers.cpp b/libsycl/unittests/mock/helpers.cpp
new file mode 100644
index 0000000000000..15f1500e7446b
--- /dev/null
+++ b/libsycl/unittests/mock/helpers.cpp
@@ -0,0 +1,276 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "helpers.hpp"
+
+namespace mock {
+
+_LIB_EXPORT MockLiboffload &getMockLiboffload() {
+ static MockLiboffload Mock;
+ return Mock;
+}
+
+} // namespace mock
+
+bool inline operator==(const ol_init_args_t &lhs, const ol_init_args_t &rhs) {
+ return (lhs.Size == rhs.Size) && (lhs.NumPlatforms == rhs.NumPlatforms) &&
+ std::memcmp(lhs.Platforms, rhs.Platforms,
+ lhs.NumPlatforms * sizeof(ol_platform_backend_t)) == 0;
+}
+
+bool inline operator!=(const ol_init_args_t &lhs, const ol_init_args_t &rhs) {
+ return !(lhs == rhs);
+}
+
+template <typename T> void assignAs(void *PropValue, T NewValue) {
+ *(static_cast<T *>(PropValue)) = NewValue;
+}
+
+void mock::MockLiboffload::initDefault() {
+ // Disable gmock warning of uninteresting mock calls.
+ ::testing::FLAGS_gmock_verbose = "error";
+ ON_CALL(*this, olInit)
+ .WillByDefault([this](const ol_init_args_t *InitArgs) -> ol_result_t {
+ // TODO: complicated cases with non-default settings are not covered.
+ const ol_init_args_t DefaultArgs = OL_INIT_ARGS_INIT;
+ if (InitArgs && (*InitArgs != DefaultArgs))
+ return makeEmptyStrError(OL_ERRC_UNIMPLEMENTED);
+
+ assert(!DefaultDevice);
+ DefaultPlatform = mock::createDummyHandle<ol_platform_handle_t>();
+ DefaultDevice = mock::createDummyHandleWithData<ol_device_handle_t>(
+ reinterpret_cast<unsigned char *>(DefaultPlatform),
+ sizeof(DefaultPlatform));
+
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olShutDown).WillByDefault([this]() -> ol_result_t {
+ assert(DefaultDevice);
+
+ mock::releaseDummyHandle(DefaultPlatform);
+ mock::releaseDummyHandle(DefaultDevice);
+
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olGetPlatformInfoSize)
+ .WillByDefault([this](ol_platform_handle_t Platform,
+ ol_platform_info_t PropName,
+ size_t *PropSizeRet) -> ol_result_t {
+ if (!Platform)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!PropSizeRet)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+
+ if (PropName == OL_PLATFORM_INFO_BACKEND) {
+ *PropSizeRet = sizeof(ol_platform_backend_t);
+ return OL_SUCCESS;
+ }
+
+ return makeEmptyStrError(OL_ERRC_UNIMPLEMENTED);
+ });
+
+ ON_CALL(*this, olGetPlatformInfo)
+ .WillByDefault([this](ol_platform_handle_t Platform,
+ ol_platform_info_t PropName, size_t PropSize,
+ void *PropValue) -> ol_result_t {
+ if (!Platform)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!PropSize)
+ return makeEmptyStrError(OL_ERRC_INVALID_SIZE);
+ if (!PropValue)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+
+ if (PropName == OL_PLATFORM_INFO_BACKEND) {
+ if (PropSize != sizeof(ol_platform_backend_t))
+ return makeEmptyStrError(OL_ERRC_INVALID_SIZE);
+ assignAs<ol_platform_backend_t>(PropValue,
+ OL_PLATFORM_BACKEND_LEVEL_ZERO);
+ return OL_SUCCESS;
+ }
+
+ return makeEmptyStrError(OL_ERRC_UNIMPLEMENTED);
+ });
+
+ ON_CALL(*this, olGetDeviceInfo)
+ .WillByDefault([this](ol_device_handle_t Device,
+ ol_device_info_t PropName, size_t PropSize,
+ void *PropValue) -> ol_result_t {
+ if (!Device)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!PropSize)
+ return makeEmptyStrError(OL_ERRC_INVALID_SIZE);
+ if (!PropValue)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+
+ switch (PropName) {
+ case OL_DEVICE_INFO_PLATFORM: {
+ if (PropSize != sizeof(ol_platform_handle_t))
+ return makeEmptyStrError(OL_ERRC_INVALID_SIZE);
+ assignAs<ol_platform_handle_t>(
+ PropValue, reinterpret_cast<mock::dummy_handle_t>(Device)
+ ->getDataAs<ol_platform_handle_t>());
+ return OL_SUCCESS;
+ }
+ case OL_DEVICE_INFO_TYPE: {
+ if (PropSize != sizeof(ol_device_type_t))
+ return makeEmptyStrError(OL_ERRC_INVALID_SIZE);
+ assignAs<ol_device_type_t>(PropValue, OL_DEVICE_TYPE_GPU);
+ return OL_SUCCESS;
+ }
+ default:
+ return makeEmptyStrError(OL_ERRC_UNIMPLEMENTED);
+ }
+ });
+
+ ON_CALL(*this, olGetDeviceInfoSize)
+ .WillByDefault([this](ol_device_handle_t Device,
+ ol_device_info_t PropName,
+ size_t *PropSizeRet) -> ol_result_t {
+ if (!Device)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!PropSizeRet)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+ switch (PropName) {
+ case OL_DEVICE_INFO_PLATFORM: {
+ *PropSizeRet = sizeof(ol_platform_handle_t);
+ return OL_SUCCESS;
+ }
+ case OL_DEVICE_INFO_TYPE: {
+ *PropSizeRet = sizeof(ol_device_type_t);
+ return OL_SUCCESS;
+ }
+ default:
+ return makeEmptyStrError(OL_ERRC_UNIMPLEMENTED);
+ }
+ });
+
+ ON_CALL(*this, olIterateDevices)
+ .WillByDefault([this](ol_device_iterate_cb_t Callback,
+ void *UserData) -> ol_result_t {
+ if (!Callback)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+
+ assert(DefaultDevice);
+ std::ignore = Callback(DefaultDevice, UserData);
+
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olDestroyProgram)
+ .WillByDefault([this](ol_program_handle_t Program) -> ol_result_t {
+ if (!Program)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ mock::releaseDummyHandle(Program);
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olCreateProgram)
+ .WillByDefault([this](ol_device_handle_t Device, const void *ProgData,
+ size_t ProgDataSize,
+ ol_program_handle_t *Program) -> ol_result_t {
+ if (!Device)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!ProgData || !Program || !ProgDataSize)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+
+ *Program = mock::createDummyHandleWithData<ol_program_handle_t>(
+ reinterpret_cast<unsigned char *>(&Device), sizeof(Device));
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olIsValidBinary)
+ .WillByDefault([this](ol_device_handle_t Device, const void *ProgData,
+ size_t ProgDataSize, bool *Valid) -> ol_result_t {
+ if (!Device)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!ProgData || !Valid || !ProgDataSize)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+ *Valid = true;
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olGetSymbol)
+ .WillByDefault([this](ol_program_handle_t Program, const char *Name,
+ ol_symbol_kind_t Kind,
+ ol_symbol_handle_t *Symbol) -> ol_result_t {
+ if (!Program)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!Name || !Symbol)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+ std::ignore = Kind;
+
+ *Symbol = mock::createDummyHandleWithData<ol_symbol_handle_t>(
+ reinterpret_cast<unsigned char *>(&Program), sizeof(Program));
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olCreateQueue)
+ .WillByDefault([this](ol_device_handle_t Device,
+ ol_queue_handle_t *Queue) -> ol_result_t {
+ if (!Device)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!Queue)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+ // Attach device as data to check what device queue belongs to if needed
+ *Queue = mock::createDummyHandleWithData<ol_queue_handle_t>(
+ reinterpret_cast<unsigned char *>(Device), sizeof(Device));
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olDestroyQueue)
+ .WillByDefault([this](ol_queue_handle_t Queue) -> ol_result_t {
+ if (!Queue)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ mock::releaseDummyHandle(Queue);
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olSyncQueue)
+ .WillByDefault([this](ol_queue_handle_t Queue) -> ol_result_t {
+ if (!Queue)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ std::ignore = Queue;
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olWaitEvents)
+ .WillByDefault([this](ol_queue_handle_t Queue, ol_event_handle_t *Events,
+ size_t NumEvents) -> ol_result_t {
+ if (!Queue)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!Events)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+ for (size_t I = 0; I < NumEvents; ++I) {
+ if (!Events[I])
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ }
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olCreateEvent)
+ .WillByDefault([this](ol_queue_handle_t Queue,
+ ol_event_handle_t *Event) -> ol_result_t {
+ if (!Queue)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ if (!Event)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+ *Event = mock::createDummyHandleWithData<ol_event_handle_t>(
+ reinterpret_cast<unsigned char *>(&Queue), sizeof(Queue));
+ return OL_SUCCESS;
+ });
+
+ ON_CALL(*this, olDestroyEvent)
+ .WillByDefault([this](ol_event_handle_t Event) -> ol_result_t {
+ if (!Event)
+ return makeEmptyStrError(OL_ERRC_INVALID_NULL_HANDLE);
+ mock::releaseDummyHandle(Event);
+ return OL_SUCCESS;
+ });
+}
diff --git a/libsycl/unittests/mock/helpers.hpp b/libsycl/unittests/mock/helpers.hpp
new file mode 100644
index 0000000000000..6f67c18890f39
--- /dev/null
+++ b/libsycl/unittests/mock/helpers.hpp
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains declarations and utilities for liboffload mocking in
+/// libsycl unit tests.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBSYCL_UNITTESTS_MOCK_HELPERS_HPP
+#define _LIBSYCL_UNITTESTS_MOCK_HELPERS_HPP
+
+#include <OffloadAPI.h>
+
+#include <gmock/gmock.h>
+
+#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <unordered_map>
+#include <vector>
+
+namespace mock {
+
+struct ol_dummy_handle_t {
+ ol_dummy_handle_t(size_t DataSize = 0)
+ : MStorage(DataSize), MSize(DataSize) {}
+ ol_dummy_handle_t(unsigned char *Data, size_t Size)
+ : MStorage(Size), MSize(Size) {
+ std::memcpy(MStorage.data(), Data, Size);
+ }
+ std::atomic<size_t> MRefCounter = 1;
+ std::vector<unsigned char> MStorage;
+ size_t MSize;
+
+ template <typename T> T getDataAs() {
+ assert(MStorage.size() >= sizeof(T));
+ return *reinterpret_cast<T *>(MStorage.data());
+ }
+
+ template <typename T> T setDataAs(T Val) {
+ assert(MStorage.size() >= sizeof(T));
+ return *reinterpret_cast<T *>(MStorage.data()) = Val;
+ }
+};
+
+using dummy_handle_t = ol_dummy_handle_t *;
+
+template <class T> inline T createDummyHandle(size_t Size = 0) {
+ dummy_handle_t DummyHandlePtr = new ol_dummy_handle_t(Size);
+ return reinterpret_cast<T>(DummyHandlePtr);
+}
+
+template <class T>
+inline T createDummyHandleWithData(unsigned char *Data, size_t Size) {
+ auto DummyHandlePtr = new ol_dummy_handle_t(Data, Size);
+ return reinterpret_cast<T>(DummyHandlePtr);
+}
+
+template <class T> inline void releaseDummyHandle(T Handle) {
+ auto DummyHandlePtr = reinterpret_cast<dummy_handle_t>(Handle);
+ delete DummyHandlePtr;
+}
+
+class MockLiboffload {
+public:
+ MockLiboffload() { initDefault(); }
+
+ MOCK_METHOD(ol_result_t, olInit, (const ol_init_args_t *));
+ MOCK_METHOD(ol_result_t, olShutDown, ());
+ MOCK_METHOD(ol_result_t, olGetPlatformInfoSize,
+ (ol_platform_handle_t, ol_platform_info_t, size_t *));
+ MOCK_METHOD(ol_result_t, olGetPlatformInfo,
+ (ol_platform_handle_t Platform, ol_platform_info_t PropName,
+ size_t PropSize, void *PropValue));
+ MOCK_METHOD(ol_result_t, olGetDeviceInfo,
+ (ol_device_handle_t Device, ol_device_info_t PropName,
+ size_t PropSize, void *PropValue));
+ MOCK_METHOD(ol_result_t, olGetDeviceInfoSize,
+ (ol_device_handle_t Device, ol_device_info_t PropName,
+ size_t *PropSizeRet));
+ MOCK_METHOD(ol_result_t, olIterateDevices,
+ (ol_device_iterate_cb_t Callback, void *UserData));
+ MOCK_METHOD(ol_result_t, olDestroyProgram, (ol_program_handle_t Program));
+ MOCK_METHOD(ol_result_t, olCreateQueue,
+ (ol_device_handle_t Device, ol_queue_handle_t *Queue));
+ MOCK_METHOD(ol_result_t, olDestroyQueue, (ol_queue_handle_t Queue));
+ MOCK_METHOD(ol_result_t, olSyncQueue, (ol_queue_handle_t Queue));
+ MOCK_METHOD(ol_result_t, olDestroyEvent, (ol_event_handle_t Event));
+ MOCK_METHOD(ol_result_t, olCreateProgram,
+ (ol_device_handle_t Device, const void *ProgData,
+ size_t ProgDataSize, ol_program_handle_t *Program));
+
+ MOCK_METHOD(ol_result_t, olGetSymbol,
+ (ol_program_handle_t Program, const char *Name,
+ ol_symbol_kind_t Kind, ol_symbol_handle_t *Symbol));
+ MOCK_METHOD(ol_result_t, olIsValidBinary,
+ (ol_device_handle_t Device, const void *ProgData,
+ size_t ProgDataSize, bool *Valid));
+ MOCK_METHOD(ol_result_t, olWaitEvents,
+ (ol_queue_handle_t Queue, ol_event_handle_t *Events,
+ size_t NumEvents));
+ MOCK_METHOD(ol_result_t, olCreateEvent,
+ (ol_queue_handle_t Queue, ol_event_handle_t *Event));
+
+ void initDefault();
+
+ ol_result_t makeEmptyStrError(ol_errc_t Code) {
+ auto [Iterator, Flag] =
+ Errors.emplace(std::make_pair(Code, ol_error_struct_t{Code, ""}));
+ return &Iterator->second;
+ }
+
+private:
+ std::unordered_map<ol_errc_t, ol_error_struct_t> Errors;
+ ol_platform_handle_t DefaultPlatform;
+ ol_device_handle_t DefaultDevice{};
+};
+
+#ifndef _LIB_EXPORT
+# ifdef _WIN32
+# define _LIB_EXPORT __declspec(dllexport)
+# else // _WIN32
+# define _LIB_EXPORT __attribute__((visibility("default")))
+# endif // _WIN32
+#endif // _LIB_EXPORT
+
+_LIB_EXPORT MockLiboffload &getMockLiboffload();
+
+class MockWrapper {
+public:
+ MockWrapper() : Mock(getMockLiboffload()) {}
+ ~MockWrapper() {
+ ::testing::Mock::VerifyAndClearExpectations(&Mock); // move to common
+ }
+ MockLiboffload &get() { return Mock; };
+
+private:
+ MockLiboffload &Mock;
+};
+
+} // namespace mock
+
+#endif // _LIBSYCL_UNITTESTS_MOCK_HELPERS_HPP
diff --git a/libsycl/unittests/mock/mock.cpp b/libsycl/unittests/mock/mock.cpp
new file mode 100644
index 0000000000000..4580bd8c6d602
--- /dev/null
+++ b/libsycl/unittests/mock/mock.cpp
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "helpers.hpp"
+
+ol_result_t olInit(const ol_init_args_t *InitArgs) {
+ return mock::getMockLiboffload().olInit(InitArgs);
+}
+
+ol_result_t olShutDown() { return mock::getMockLiboffload().olShutDown(); }
+
+ol_result_t olGetPlatformInfoSize(ol_platform_handle_t Platform,
+ ol_platform_info_t PropName,
+ size_t *PropSizeRet) {
+ return mock::getMockLiboffload().olGetPlatformInfoSize(Platform, PropName,
+ PropSizeRet);
+}
+
+ol_result_t olGetPlatformInfo(ol_platform_handle_t Platform,
+ ol_platform_info_t PropName, size_t PropSize,
+ void *PropValue) {
+ return mock::getMockLiboffload().olGetPlatformInfo(Platform, PropName,
+ PropSize, PropValue);
+}
+
+ol_result_t olGetDeviceInfo(ol_device_handle_t Device,
+ ol_device_info_t PropName, size_t PropSize,
+ void *PropValue) {
+ return mock::getMockLiboffload().olGetDeviceInfo(Device, PropName, PropSize,
+ PropValue);
+}
+
+ol_result_t olGetDeviceInfoSize(ol_device_handle_t Device,
+ ol_device_info_t PropName,
+ size_t *PropSizeRet) {
+ return mock::getMockLiboffload().olGetDeviceInfoSize(Device, PropName,
+ PropSizeRet);
+}
+
+ol_result_t olIterateDevices(ol_device_iterate_cb_t Callback, void *UserData) {
+ return mock::getMockLiboffload().olIterateDevices(Callback, UserData);
+}
+
+ol_result_t olDestroyProgram(ol_program_handle_t Program) {
+ return mock::getMockLiboffload().olDestroyProgram(Program);
+}
+
+ol_result_t olCreateQueue(ol_device_handle_t Device, ol_queue_handle_t *Queue) {
+ return mock::getMockLiboffload().olCreateQueue(Device, Queue);
+}
+
+ol_result_t olDestroyQueue(ol_queue_handle_t Queue) {
+ return mock::getMockLiboffload().olDestroyQueue(Queue);
+}
+
+ol_result_t olSyncQueue(ol_queue_handle_t Queue) {
+ return mock::getMockLiboffload().olSyncQueue(Queue);
+}
+
+ol_result_t olCreateProgram(ol_device_handle_t Device, const void *ProgData,
+ size_t ProgDataSize, ol_program_handle_t *Program) {
+ return mock::getMockLiboffload().olCreateProgram(Device, ProgData,
+ ProgDataSize, Program);
+}
+
+ol_result_t olGetSymbol(ol_program_handle_t Program, const char *Name,
+ ol_symbol_kind_t Kind, ol_symbol_handle_t *Symbol) {
+ return mock::getMockLiboffload().olGetSymbol(Program, Name, Kind, Symbol);
+}
+
+ol_result_t olIsValidBinary(ol_device_handle_t Device, const void *ProgData,
+ size_t ProgDataSize, bool *Valid) {
+ return mock::getMockLiboffload().olIsValidBinary(Device, ProgData,
+ ProgDataSize, Valid);
+}
+
+ol_result_t olWaitEvents(ol_queue_handle_t Queue, ol_event_handle_t *Events,
+ size_t NumEvents) {
+ return mock::getMockLiboffload().olWaitEvents(Queue, Events, NumEvents);
+}
+
+ol_result_t olCreateEvent(ol_queue_handle_t Queue, ol_event_handle_t *Event) {
+ return mock::getMockLiboffload().olCreateEvent(Queue, Event);
+}
+
+ol_result_t olDestroyEvent(ol_event_handle_t Event) {
+ return mock::getMockLiboffload().olDestroyEvent(Event);
+}
diff --git a/libsycl/unittests/platform/CMakeLists.txt b/libsycl/unittests/platform/CMakeLists.txt
new file mode 100644
index 0000000000000..b697bbde99a47
--- /dev/null
+++ b/libsycl/unittests/platform/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_sycl_unittest(PlatformTests
+ get_platforms.cpp
+)
diff --git a/libsycl/unittests/platform/get_platforms.cpp b/libsycl/unittests/platform/get_platforms.cpp
new file mode 100644
index 0000000000000..7a6d50bc75ca7
--- /dev/null
+++ b/libsycl/unittests/platform/get_platforms.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <sycl/sycl.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace sycl;
+
+TEST(PlatformTest, APIGetPlatformsDefaultMock) {
+ auto Platforms = sycl::platform::get_platforms();
+ ASSERT_EQ(Platforms.size(), 1u);
+ EXPECT_EQ(Platforms[0].get_backend(), sycl::backend::level_zero);
+
+ auto Devices = Platforms[0].get_devices();
+ ASSERT_EQ(Devices.size(), 1u);
+ EXPECT_EQ(Devices[0].get_backend(), sycl::backend::level_zero);
+
+ EXPECT_FALSE(Devices[0].is_cpu());
+ EXPECT_FALSE(Devices[0].is_accelerator());
+ EXPECT_TRUE(Devices[0].is_gpu());
+
+ EXPECT_EQ(Devices[0].get_platform(), Platforms[0]);
+}
diff --git a/libsycl/unittests/program_manager/CMakeLists.txt b/libsycl/unittests/program_manager/CMakeLists.txt
new file mode 100644
index 0000000000000..e8169beb8a808
--- /dev/null
+++ b/libsycl/unittests/program_manager/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_sycl_unittest(ProgramManagerTests
+ register_and_unregister.cpp
+)
diff --git a/libsycl/unittests/program_manager/register_and_unregister.cpp b/libsycl/unittests/program_manager/register_and_unregister.cpp
new file mode 100644
index 0000000000000..df9307c38709c
--- /dev/null
+++ b/libsycl/unittests/program_manager/register_and_unregister.cpp
@@ -0,0 +1,129 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <common/device_images.hpp>
+
+#include <detail/program_manager.hpp>
+
+#include <sycl/__impl/exception.hpp>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <array>
+#include <string>
+
+#include <llvm/ADT/SmallVector.h>
+
+using namespace sycl;
+
+using namespace ::testing;
+
+struct MockProgramAndKernelManager : public detail::ProgramAndKernelManager {
+ using detail::ProgramAndKernelManager::MDeviceImageManagers;
+ using detail::ProgramAndKernelManager::MDeviceKernelInfoMap;
+};
+
+TEST(ProgramAndKernelManager, CheckUnsupportedVersionOfFatbin) {
+ std::array<llvm::StringRef, 1> KernelNames = {"kernel"};
+ llvm::SmallString<0> Binary =
+ sycl::unittest::createSYCLDeviceBinary(KernelNames);
+
+ llvm::MemoryBufferRef MBR(
+ llvm::StringRef(static_cast<const char *>(Binary.data()), Binary.size()),
+ /*Identifier=*/"");
+ auto Header = llvm::object::OffloadBinary::extractHeader(MBR);
+ ASSERT_TRUE(static_cast<const bool>(Header));
+ // extractHeader returns const reference to the header, hacking it.
+ auto *ModifiableHeader =
+ const_cast<llvm::object::OffloadBinary::Header *>(Header.get());
+ ModifiableHeader->Version = llvm::object::OffloadBinary::Version + 1;
+
+ MockProgramAndKernelManager Manager;
+ EXPECT_THAT([&]() { Manager.registerFatBin(Binary.data(), Binary.size()); },
+ Throws<sycl::exception>(AllOf(
+ Property(&sycl::exception::what,
+ HasSubstr("Failed to parse OffloadBinary")),
+ Property(&sycl::exception::code, Eq(sycl::errc::runtime)))));
+
+ ModifiableHeader->Version = llvm::object::OffloadBinary::Version;
+ EXPECT_NO_THROW(Manager.registerFatBin(Binary.data(), Binary.size()));
+ EXPECT_NO_THROW(Manager.unregisterFatBin(Binary.data(), Binary.size()));
+}
+
+TEST(ProgramAndKernelManager, CheckUnsupportedVersionOfImage) {
+ std::array<llvm::StringRef, 1> KernelNames = {"kernel"};
+ llvm::SmallString<0> IncompatibleImageBinary =
+ sycl::unittest::createSYCLDeviceBinary(KernelNames,
+ llvm::object::IMG_Object);
+
+ MockProgramAndKernelManager Manager;
+
+ EXPECT_THAT(
+ [&]() {
+ Manager.registerFatBin(IncompatibleImageBinary.data(),
+ IncompatibleImageBinary.size());
+ },
+ Throws<sycl::exception>(
+ AllOf(Property(&sycl::exception::what,
+ HasSubstr("Incompatible device image")),
+ Property(&sycl::exception::code, Eq(sycl::errc::runtime)))));
+
+ llvm::SmallString<0> CompatibleImageBinary =
+ sycl::unittest::createSYCLDeviceBinary(KernelNames,
+ llvm::object::IMG_SPIRV);
+ EXPECT_NO_THROW(Manager.registerFatBin(CompatibleImageBinary.data(),
+ CompatibleImageBinary.size()));
+ EXPECT_NO_THROW(Manager.unregisterFatBin(CompatibleImageBinary.data(),
+ CompatibleImageBinary.size()));
+}
+
+TEST(ProgramAndKernelManager, CheckRegisterAndUnregister) {
+ std::array<std::string, 3> KernelNames = {"kernel1.1", "kernel1.2",
+ "kernel2.1"};
+ std::array<llvm::StringRef, 2> Image1Kernels = {KernelNames[0],
+ KernelNames[1]};
+ std::array<llvm::StringRef, 1> Image2Kernels = {KernelNames[2]};
+
+ std::array<llvm::SmallString<0>, 2> Symbols;
+ llvm::offloading::sycl::writeSymbolTable(Image1Kernels, Symbols[0]);
+ llvm::offloading::sycl::writeSymbolTable(Image2Kernels, Symbols[1]);
+
+ llvm::SmallVector<llvm::object::OffloadBinary::OffloadingImage, 2> Images;
+ Images.push_back(sycl::unittest::createSYCLImage(Symbols[0]));
+ Images.push_back(sycl::unittest::createSYCLImage(Symbols[1]));
+
+ llvm::SmallString<0> Binary = llvm::object::OffloadBinary::write(Images);
+
+ MockProgramAndKernelManager Manager;
+ EXPECT_NO_THROW(Manager.registerFatBin(Binary.data(), Binary.size()));
+
+ ASSERT_THAT(Manager.MDeviceImageManagers, SizeIs(1));
+ auto ImagesIt = Manager.MDeviceImageManagers.find(Binary.data());
+ ASSERT_NE(ImagesIt, Manager.MDeviceImageManagers.end());
+ ASSERT_THAT(ImagesIt->second, SizeIs(2));
+
+ ASSERT_THAT(Manager.MDeviceKernelInfoMap, SizeIs(KernelNames.size()));
+ for (auto &[Name, KernelInfo] : Manager.MDeviceKernelInfoMap) {
+ // Check all name related fields
+ EXPECT_EQ(Name, KernelInfo.getName());
+ EXPECT_THAT(KernelNames, Contains(Name));
+
+ // Check device image ref correctness in kernel info.
+ auto &DevImage = KernelInfo.getDeviceImage();
+ uint64_t ImageIndex = DevImage.getOffloadBinary().getIndex();
+ if (Name.find("kernel1") != Name.npos)
+ EXPECT_EQ(ImageIndex, 0u);
+ else
+ EXPECT_EQ(ImageIndex, 1u);
+ }
+
+ EXPECT_NO_THROW(Manager.unregisterFatBin(Binary.data(), Binary.size()));
+ EXPECT_THAT(Manager.MDeviceImageManagers, IsEmpty());
+ EXPECT_THAT(Manager.MDeviceKernelInfoMap, IsEmpty());
+}
diff --git a/libsycl/unittests/queue/CMakeLists.txt b/libsycl/unittests/queue/CMakeLists.txt
new file mode 100644
index 0000000000000..f03220ab10dd1
--- /dev/null
+++ b/libsycl/unittests/queue/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_sycl_unittest(QueueTests
+ queue.cpp
+)
diff --git a/libsycl/unittests/queue/queue.cpp b/libsycl/unittests/queue/queue.cpp
new file mode 100644
index 0000000000000..1234e5eb94281
--- /dev/null
+++ b/libsycl/unittests/queue/queue.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <mock/helpers.hpp>
+
+#include <sycl/__impl/detail/config.hpp>
+#include <sycl/__impl/queue.hpp>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace sycl;
+using namespace ::testing;
+
+TEST(Queue, CommonQueriesAndLifetime) {
+ mock::MockWrapper Mock;
+
+ EXPECT_CALL(Mock.get(), olCreateQueue(_, _)).Times(1);
+ EXPECT_CALL(Mock.get(), olDestroyQueue(_)).Times(1);
+ {
+ queue Q;
+ EXPECT_EQ(Q.get_backend(), sycl::backend::level_zero);
+ EXPECT_EQ(Q.is_in_order(), false);
+ }
+}
>From c566a1f965cd84911d19ef8ef3e77aa0661e7701 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Tue, 2 Jun 2026 04:20:31 -0700
Subject: [PATCH 2/2] fix code-review comments
Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
libsycl/cmake/Modules/AddUnitTest.cmake | 20 ++++++-------
libsycl/unittests/common/device_images.hpp | 3 --
libsycl/unittests/mock/helpers.cpp | 8 ++---
libsycl/unittests/mock/helpers.hpp | 29 ++++++++-----------
.../register_and_unregister.cpp | 2 +-
5 files changed, 27 insertions(+), 35 deletions(-)
diff --git a/libsycl/cmake/Modules/AddUnitTest.cmake b/libsycl/cmake/Modules/AddUnitTest.cmake
index 489f340ac9600..468b624b20049 100644
--- a/libsycl/cmake/Modules/AddUnitTest.cmake
+++ b/libsycl/cmake/Modules/AddUnitTest.cmake
@@ -1,24 +1,24 @@
-function(add_sycl_unittest test_dirname)
+function(add_sycl_unittest test_name)
# Enable exception handling for these unit tests
set(LLVM_REQUIRES_EH ON)
set(LLVM_REQUIRES_RTTI ON)
- add_unittest(LibsyclUnitTests ${test_dirname}
+ add_unittest(LibsyclUnitTests ${test_name}
$<TARGET_OBJECTS:${LIBSYCL_OBJ_TARGET}> ${ARGN})
- target_compile_definitions(${test_dirname}
+ target_compile_definitions(${test_name}
PRIVATE _LIBSYCL_BUILDING_LIBRARY)
- add_custom_target(check-sycl-${test_dirname}
+ add_custom_target(check-sycl-${test_name}
${CMAKE_COMMAND} -E env
- ${CMAKE_CURRENT_BINARY_DIR}/${test_dirname}
+ ${CMAKE_CURRENT_BINARY_DIR}/${test_name}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS
- ${test_dirname}
+ ${test_name}
)
- add_dependencies(check-sycl-unittests check-sycl-${test_dirname})
+ add_dependencies(check-sycl-unittests check-sycl-${test_name})
- target_link_libraries(${test_dirname}
+ target_link_libraries(${test_name}
PRIVATE
ol_mock
# required for fake device images creation
@@ -27,7 +27,7 @@ function(add_sycl_unittest test_dirname)
LLVMSupport
)
- target_include_directories(${test_dirname}
+ target_include_directories(${test_name}
PRIVATE SYSTEM
${LIBSYCL_BUILD_INCLUDE_DIR}
${LIBSYCL_SOURCE_DIR}/src/
@@ -37,7 +37,7 @@ function(add_sycl_unittest test_dirname)
)
if (UNIX)
# These warnings are coming from Google Test code.
- target_compile_options(${test_dirname}
+ target_compile_options(${test_name}
PRIVATE
-Wno-unused-parameter
-Wno-inconsistent-missing-override
diff --git a/libsycl/unittests/common/device_images.hpp b/libsycl/unittests/common/device_images.hpp
index e9b344a684b7a..3c53c097a9e78 100644
--- a/libsycl/unittests/common/device_images.hpp
+++ b/libsycl/unittests/common/device_images.hpp
@@ -29,10 +29,7 @@ inline llvm::object::OffloadBinary::OffloadingImage createSYCLImage(
llvm::object::OffloadBinary::OffloadingImage Image;
Image.TheImageKind = ImageKind;
Image.TheOffloadKind = OffloadKind;
- Image.Flags = 0;
Image.StringData["triple"] = sycl::detail::DeviceBinaryTripleSPIRV64;
- Image.StringData["compile-opts"] = "";
- Image.StringData["link-opts"] = "";
Image.StringData["symbols"] = SymbolsBlob;
static constexpr char DummyImageData[] = "dummy image data";
Image.Image = llvm::MemoryBuffer::getMemBufferCopy(
diff --git a/libsycl/unittests/mock/helpers.cpp b/libsycl/unittests/mock/helpers.cpp
index 15f1500e7446b..abc68fd2a29d3 100644
--- a/libsycl/unittests/mock/helpers.cpp
+++ b/libsycl/unittests/mock/helpers.cpp
@@ -17,13 +17,13 @@ _LIB_EXPORT MockLiboffload &getMockLiboffload() {
} // namespace mock
-bool inline operator==(const ol_init_args_t &lhs, const ol_init_args_t &rhs) {
+static bool operator==(const ol_init_args_t &lhs, const ol_init_args_t &rhs) {
return (lhs.Size == rhs.Size) && (lhs.NumPlatforms == rhs.NumPlatforms) &&
std::memcmp(lhs.Platforms, rhs.Platforms,
lhs.NumPlatforms * sizeof(ol_platform_backend_t)) == 0;
}
-bool inline operator!=(const ol_init_args_t &lhs, const ol_init_args_t &rhs) {
+static bool operator!=(const ol_init_args_t &lhs, const ol_init_args_t &rhs) {
return !(lhs == rhs);
}
@@ -44,7 +44,7 @@ void mock::MockLiboffload::initDefault() {
assert(!DefaultDevice);
DefaultPlatform = mock::createDummyHandle<ol_platform_handle_t>();
DefaultDevice = mock::createDummyHandleWithData<ol_device_handle_t>(
- reinterpret_cast<unsigned char *>(DefaultPlatform),
+ reinterpret_cast<unsigned char *>(&DefaultPlatform),
sizeof(DefaultPlatform));
return OL_SUCCESS;
@@ -220,7 +220,7 @@ void mock::MockLiboffload::initDefault() {
return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
// Attach device as data to check what device queue belongs to if needed
*Queue = mock::createDummyHandleWithData<ol_queue_handle_t>(
- reinterpret_cast<unsigned char *>(Device), sizeof(Device));
+ reinterpret_cast<unsigned char *>(&Device), sizeof(Device));
return OL_SUCCESS;
});
diff --git a/libsycl/unittests/mock/helpers.hpp b/libsycl/unittests/mock/helpers.hpp
index 6f67c18890f39..77a4b39ca8ced 100644
--- a/libsycl/unittests/mock/helpers.hpp
+++ b/libsycl/unittests/mock/helpers.hpp
@@ -29,19 +29,16 @@
namespace mock {
struct ol_dummy_handle_t {
- ol_dummy_handle_t(size_t DataSize = 0)
- : MStorage(DataSize), MSize(DataSize) {}
- ol_dummy_handle_t(unsigned char *Data, size_t Size)
- : MStorage(Size), MSize(Size) {
+ ol_dummy_handle_t(size_t DataSize = 0) : MStorage(DataSize) {}
+ ol_dummy_handle_t(unsigned char *Data, size_t Size) : MStorage(Size) {
std::memcpy(MStorage.data(), Data, Size);
}
- std::atomic<size_t> MRefCounter = 1;
+
std::vector<unsigned char> MStorage;
- size_t MSize;
- template <typename T> T getDataAs() {
+ template <typename T> const T getDataAs() const {
assert(MStorage.size() >= sizeof(T));
- return *reinterpret_cast<T *>(MStorage.data());
+ return *reinterpret_cast<const T *>(MStorage.data());
}
template <typename T> T setDataAs(T Val) {
@@ -52,18 +49,18 @@ struct ol_dummy_handle_t {
using dummy_handle_t = ol_dummy_handle_t *;
-template <class T> inline T createDummyHandle(size_t Size = 0) {
+template <class T> T createDummyHandle(size_t Size = 0) {
dummy_handle_t DummyHandlePtr = new ol_dummy_handle_t(Size);
return reinterpret_cast<T>(DummyHandlePtr);
}
template <class T>
-inline T createDummyHandleWithData(unsigned char *Data, size_t Size) {
+T createDummyHandleWithData(unsigned char *Data, size_t Size) {
auto DummyHandlePtr = new ol_dummy_handle_t(Data, Size);
return reinterpret_cast<T>(DummyHandlePtr);
}
-template <class T> inline void releaseDummyHandle(T Handle) {
+template <class T> void releaseDummyHandle(T Handle) {
auto DummyHandlePtr = reinterpret_cast<dummy_handle_t>(Handle);
delete DummyHandlePtr;
}
@@ -109,8 +106,6 @@ class MockLiboffload {
MOCK_METHOD(ol_result_t, olCreateEvent,
(ol_queue_handle_t Queue, ol_event_handle_t *Event));
- void initDefault();
-
ol_result_t makeEmptyStrError(ol_errc_t Code) {
auto [Iterator, Flag] =
Errors.emplace(std::make_pair(Code, ol_error_struct_t{Code, ""}));
@@ -118,8 +113,10 @@ class MockLiboffload {
}
private:
+ void initDefault();
+
std::unordered_map<ol_errc_t, ol_error_struct_t> Errors;
- ol_platform_handle_t DefaultPlatform;
+ ol_platform_handle_t DefaultPlatform{};
ol_device_handle_t DefaultDevice{};
};
@@ -136,9 +133,7 @@ _LIB_EXPORT MockLiboffload &getMockLiboffload();
class MockWrapper {
public:
MockWrapper() : Mock(getMockLiboffload()) {}
- ~MockWrapper() {
- ::testing::Mock::VerifyAndClearExpectations(&Mock); // move to common
- }
+ ~MockWrapper() { ::testing::Mock::VerifyAndClearExpectations(&Mock); }
MockLiboffload &get() { return Mock; };
private:
diff --git a/libsycl/unittests/program_manager/register_and_unregister.cpp b/libsycl/unittests/program_manager/register_and_unregister.cpp
index df9307c38709c..f266e98a02e14 100644
--- a/libsycl/unittests/program_manager/register_and_unregister.cpp
+++ b/libsycl/unittests/program_manager/register_and_unregister.cpp
@@ -60,7 +60,7 @@ TEST(ProgramAndKernelManager, CheckUnsupportedVersionOfImage) {
std::array<llvm::StringRef, 1> KernelNames = {"kernel"};
llvm::SmallString<0> IncompatibleImageBinary =
sycl::unittest::createSYCLDeviceBinary(KernelNames,
- llvm::object::IMG_Object);
+ llvm::object::IMG_Bitcode);
MockProgramAndKernelManager Manager;
More information about the llvm-commits
mailing list