[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