[llvm] Ut tests (PR #192995)

Kseniya Tikhomirova via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 23 09:01:59 PDT 2026


https://github.com/KseniyaTikhomirova updated https://github.com/llvm/llvm-project/pull/192995

>From fcc9106a794f37349342b126e1c68a6e241c47ac 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/5] draft of mock impl

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/CMakeLists.txt                 |   2 +
 libsycl/unittests/CMakeLists.txt       |   1 +
 libsycl/unittests/mock/CMakeLists.txt  |  12 +++
 libsycl/unittests/mock/src/helpers.cpp |   8 ++
 libsycl/unittests/mock/src/helpers.hpp | 106 +++++++++++++++++++++++++
 libsycl/unittests/mock/src/mock.cpp    |  38 +++++++++
 6 files changed, 167 insertions(+)
 create mode 100644 libsycl/unittests/CMakeLists.txt
 create mode 100644 libsycl/unittests/mock/CMakeLists.txt
 create mode 100644 libsycl/unittests/mock/src/helpers.cpp
 create mode 100644 libsycl/unittests/mock/src/helpers.hpp
 create mode 100644 libsycl/unittests/mock/src/mock.cpp

diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt
index d2b0d79ea8e65..56f8ca56ac72b 100644
--- a/libsycl/CMakeLists.txt
+++ b/libsycl/CMakeLists.txt
@@ -140,6 +140,8 @@ if(LLVM_INCLUDE_TESTS)
   add_subdirectory(test)
 endif()
 
+add_subdirectory(unittests)
+
 add_custom_target(libsycl-toolchain ALL
   DEPENDS libsycl-runtime-libraries
           sycl-ls
diff --git a/libsycl/unittests/CMakeLists.txt b/libsycl/unittests/CMakeLists.txt
new file mode 100644
index 0000000000000..a0d65f27a108a
--- /dev/null
+++ b/libsycl/unittests/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(mock)
\ No newline at end of file
diff --git a/libsycl/unittests/mock/CMakeLists.txt b/libsycl/unittests/mock/CMakeLists.txt
new file mode 100644
index 0000000000000..9c63b40a9fe61
--- /dev/null
+++ b/libsycl/unittests/mock/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_library(ol_mock STATIC
+    "${CMAKE_CURRENT_SOURCE_DIR}/src/mock.cpp"
+)
+  add_dependencies(ol_mock
+    LLVMOffload
+  )
+
+target_include_directories(ol_mock
+  PRIVATE
+    "${CMAKE_CURRENT_SOURCE_DIR}"
+    $<TARGET_PROPERTY:LLVMOffload,INTERFACE_INCLUDE_DIRECTORIES>
+)
diff --git a/libsycl/unittests/mock/src/helpers.cpp b/libsycl/unittests/mock/src/helpers.cpp
new file mode 100644
index 0000000000000..f8a72934a948a
--- /dev/null
+++ b/libsycl/unittests/mock/src/helpers.cpp
@@ -0,0 +1,8 @@
+#include "ur_mock_helpers.hpp"
+
+namespace mock {
+static callbacks_t callbacks = {};
+
+callbacks_t &getCallbacks() { return callbacks; }
+
+} // namespace mock
diff --git a/libsycl/unittests/mock/src/helpers.hpp b/libsycl/unittests/mock/src/helpers.hpp
new file mode 100644
index 0000000000000..14d3c5d8fe28c
--- /dev/null
+++ b/libsycl/unittests/mock/src/helpers.hpp
@@ -0,0 +1,106 @@
+#pragma once
+
+#include <OffloadAPI.h>
+
+#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+// This is the callback function we accept to override or instrument
+// entry-points. pParams is expected to be a pointer to the appropriate params_t
+// struct for the given entry point.
+typedef ol_result_t (*ol_mock_callback_t)(void *pParams);
+
+namespace mock {
+
+struct dummy_handle_t_ {
+  dummy_handle_t_(size_t DataSize = 0)
+      : MStorage(DataSize), MData(MStorage.data()), MSize(DataSize) {}
+  dummy_handle_t_(unsigned char *Data, size_t Size)
+      : MData(Data), MSize(Size) {}
+  std::atomic<size_t> MRefCounter = 1;
+  std::vector<unsigned char> MStorage;
+  unsigned char *MData = nullptr;
+  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 = dummy_handle_t_ *;
+
+template <class T> inline T createDummyHandle(size_t Size = 0) {
+  dummy_handle_t DummyHandlePtr = new dummy_handle_t_(Size);
+  return reinterpret_cast<T>(DummyHandlePtr);
+}
+
+template <class T>
+inline T createDummyHandleWithData(unsigned char *Data, size_t Size) {
+  auto DummyHandlePtr = new 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;
+}
+
+struct Callbacks {
+  void setCallback(std::string name, ol_mock_callback_t callback) {
+    replaceCallbacks[name] = callback;
+  }
+
+  ol_mock_callback_t getCallback(std::string name) const {
+    auto callback = replaceCallbacks.find(name);
+
+    if (callback != replaceCallbacks.end()) {
+      return callback->second;
+    }
+    return nullptr;
+  }
+
+  void resetCallbacks() { replaceCallbacks.clear(); }
+  ol_error_struct_t *
+  getErrorUnimplementedFunction(const std::string &FunctionName) {
+    if (auto ErrorIt = errors.find(FunctionName); ErrorIt != errors.end())
+      return &ErrorIt->second.second;
+    auto [Iterator, Flag] = errors.insert(
+        {FunctionName,
+         {FunctionName + " is not implemented in mock OL library, add callback "
+                         "via setCAllback method.",
+          {}}});
+    assert(Flag);
+    auto &[MessageStr, ErrorStruct] = Iterator->second;
+    ErrorStruct = {OL_ERRC_UNIMPLEMENTED, MessageStr.c_str()};
+    return &ErrorStruct;
+  }
+
+private:
+  std::unordered_map<std::string, ol_mock_callback_t> replaceCallbacks;
+  std::unordered_map<std::string, std::pair<std::string, ol_error_struct_t>>
+      errors;
+};
+
+#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 Callbacks &getCallbacks();
+_LIB_EXPORT ol_error_struct_t *
+getErrorUnimplementedFunction(const std::string &FunctionName);
+
+} // namespace mock
diff --git a/libsycl/unittests/mock/src/mock.cpp b/libsycl/unittests/mock/src/mock.cpp
new file mode 100644
index 0000000000000..aef11c76492d6
--- /dev/null
+++ b/libsycl/unittests/mock/src/mock.cpp
@@ -0,0 +1,38 @@
+#include <list>
+#include <optional>
+
+#include "helpers.hpp"
+
+namespace unittest {
+
+class OffloadMock {
+public:
+  OffloadMock() = default;
+
+  OffloadMock(OffloadMock &&Other) = delete;
+  OffloadMock(const OffloadMock &) = delete;
+  OffloadMock &operator=(const OffloadMock &) = delete;
+  ~OffloadMock() {
+    // mock::getCallbacks() is an application lifetime object, we need to reset
+    // these between tests
+    mock::getCallbacks().resetCallbacks();
+  }
+
+  template <typename ParamType, typename... Args>
+  static ol_result_t callCallback(std::string FunctionName, Args &&...args) {
+    auto Callback = mock::getCallbacks().getCallback(FunctionName);
+    if (!Callback)
+      return mock::getErrorUnimplementedFunction(FunctionName);
+
+    ParamType params = {&args...};
+    return Callback(&params);
+  }
+};
+
+} // namespace unittest
+
+// C++20 std::source_location::function_name
+ol_result_t olCreateEvent(ol_queue_handle_t Queue, ol_event_handle_t *Event) {
+  return unittest::OffloadMock::callCallback<ol_create_event_params_t>(
+      __func__, Queue, Event);
+}

>From 5f39a55dce3aa8a280af408250c4cc3e155c650f Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Thu, 9 Apr 2026 04:04:22 -0700
Subject: [PATCH 2/5] amend please

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/src/CMakeLists.txt                    |  12 ++
 libsycl/unittests/CMakeLists.txt              |   3 +-
 .../unittests/usm_functions/CMakeLists.txt    | 140 ++++++++++++++++++
 3 files changed, 154 insertions(+), 1 deletion(-)
 create mode 100644 libsycl/unittests/usm_functions/CMakeLists.txt

diff --git a/libsycl/src/CMakeLists.txt b/libsycl/src/CMakeLists.txt
index 4501005e433e3..fe9ffe1fb232c 100644
--- a/libsycl/src/CMakeLists.txt
+++ b/libsycl/src/CMakeLists.txt
@@ -81,6 +81,18 @@ function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME)
     PROPERTIES
       OUTPUT_NAME ${LIB_OUTPUT_NAME})
 
+# Unit tests
+set (UT_LIB_TARGET_NAME ${LIB_TARGET_NAME}_ut)
+add_library(${UT_LIB_TARGET_NAME} STATIC $<TARGET_OBJECTS:${LIB_OBJ_NAME}>)
+target_link_libraries(${UT_LIB_TARGET_NAME}
+  PRIVATE
+    ol_mock
+    LLVMObject
+  )
+add_dependencies(${UT_LIB_TARGET_NAME}
+  ol_mock
+)
+
 endfunction(add_sycl_rt_library)
 
 set(LIBSYCL_SOURCES
diff --git a/libsycl/unittests/CMakeLists.txt b/libsycl/unittests/CMakeLists.txt
index a0d65f27a108a..052508d3224d8 100644
--- a/libsycl/unittests/CMakeLists.txt
+++ b/libsycl/unittests/CMakeLists.txt
@@ -1 +1,2 @@
-add_subdirectory(mock)
\ No newline at end of file
+add_subdirectory(mock)
+add_subdirectory(usm_functions)
\ No newline at end of file
diff --git a/libsycl/unittests/usm_functions/CMakeLists.txt b/libsycl/unittests/usm_functions/CMakeLists.txt
new file mode 100644
index 0000000000000..06c2e38e6660b
--- /dev/null
+++ b/libsycl/unittests/usm_functions/CMakeLists.txt
@@ -0,0 +1,140 @@
+function(add_sycl_unittest_internal test_dirname link_variant is_preview)
+  # Enable exception handling for these unit tests
+  set(LLVM_REQUIRES_EH ON)
+  set(LLVM_REQUIRES_RTTI ON)
+
+  get_target_property(SYCL_BINARY_DIR sycl-toolchain BINARY_DIR)
+
+  string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower)
+
+  # Select which sycl libraries and object to link based
+  # on whether this is a preview build.
+  if (MSVC AND build_type_lower MATCHES "debug")
+    if (${is_preview})
+      set(sycl_obj_target "sycl-previewd_object")
+      set(sycl_so_target "sycl-previewd")
+    else()
+      set(sycl_obj_target "sycld_object")
+      set(sycl_so_target "sycld")
+    endif()
+  else()
+    if (${is_preview})
+      set(sycl_obj_target "sycl-preview_object")
+      set(sycl_so_target "sycl-preview")
+    else()
+      set(sycl_obj_target "sycl_object")
+      set(sycl_so_target "sycl")
+    endif()
+  endif()
+
+  # This is done to ensure that preview tests are kept in a separate
+  # directory, so that they do not interfere with the non-preview tests.
+  # Chaning CMAKE_CURRENT_BINARY_DIR should not affect this variable in its
+  # parent scope.
+  if (${is_preview})
+      set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/Preview")
+  endif()
+
+  if ("${link_variant}" MATCHES "SHARED")
+    set(SYCL_LINK_LIBS ${sycl_so_target})
+    add_unittest(SYCLUnitTests ${test_dirname} ${ARGN})
+  else()
+    add_unittest(SYCLUnitTests ${test_dirname}
+                $<TARGET_OBJECTS:${sycl_obj_target}> ${ARGN})
+    target_compile_definitions(${test_dirname}
+                               PRIVATE __SYCL_BUILD_SYCL_DLL)
+
+    get_target_property(SYCL_LINK_LIBS ${sycl_so_target} LINK_LIBRARIES)
+  endif()
+
+  if (SYCL_ENABLE_COVERAGE)
+    target_compile_options(${test_dirname} PUBLIC
+      -fprofile-instr-generate -fcoverage-mapping
+    )
+    target_link_options(${test_dirname} PUBLIC
+      -fprofile-instr-generate -fcoverage-mapping
+    )
+  endif()
+
+  # Add preview-specific compile definition
+  if (${is_preview})
+    target_compile_definitions(${test_dirname}
+        PRIVATE __INTEL_PREVIEW_BREAKING_CHANGES)
+    set(sycl_cache_suffix "_preview")
+  endif()
+
+  if (SYCL_ENABLE_XPTI_TRACING)
+    target_compile_definitions(${test_dirname}
+      PRIVATE XPTI_ENABLE_INSTRUMENTATION XPTI_STATIC_LIBRARY)
+  endif()
+
+  # check-sycl-unittests was using an old sycl library. So, to get
+  # around this problem, we add the new sycl library to the PATH and
+  # LD_LIBRARY_PATH on Windows and Linux respectively.
+    add_custom_target(check-sycl-${test_dirname}
+        ${CMAKE_COMMAND} -E env
+        LLVM_PROFILE_FILE="${SYCL_COVERAGE_PATH}/${test_dirname}.profraw"
+        SYCL_CONFIG_FILE_NAME=null.cfg
+        SYCL_DEVICELIB_NO_FALLBACK=1
+        SYCL_CACHE_DIR="${CMAKE_BINARY_DIR}/sycl_cache${sycl_cache_suffix}"
+        "LD_LIBRARY_PATH=${SYCL_BINARY_DIR}/unittests/lib:${CMAKE_BINARY_DIR}/lib:$ENV{LD_LIBRARY_PATH}"
+        ${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
+      mockOpenCL
+      LLVMTestingSupport
+      OpenCL-Headers
+      emhash::emhash
+      unified-runtime::mock
+      ${SYCL_LINK_LIBS}
+    )
+
+  add_dependencies(${test_dirname} ur_adapter_mock mockOpenCL)
+
+  if(SYCL_ENABLE_EXTENSION_JIT)
+    target_link_libraries(${test_dirname} PRIVATE sycl-jit)
+  endif(SYCL_ENABLE_EXTENSION_JIT)
+
+  target_include_directories(${test_dirname}
+    PRIVATE SYSTEM
+      ${sycl_inc_dir}
+      ${SYCL_SOURCE_DIR}/source/
+      ${SYCL_SOURCE_DIR}/unittests/
+    )
+  if (UNIX)
+    # These warnings are coming from Google Test code.
+    target_compile_options(${test_dirname}
+      PRIVATE
+        -Wno-unused-parameter
+        -Wno-inconsistent-missing-override
+    )
+  endif()
+  target_compile_definitions(${test_dirname} PRIVATE SYCL_DISABLE_FSYCL_SYCLHPP_WARNING)
+endfunction()
+
+# add_sycl_unittest(test_name_prefix SHARED|OBJECT file1.cpp, file2.cpp ...)
+#
+# Will compile the list of files together to create two builds, with and without
+# the SYCL preview features enabled.
+# Produces two binaries, named `basename(test_name_prefix_Non_Preview_Tests)` and `basename(test_name_prefix_Preview_Tests)`
+# Note: in case of changing test names below, please also adjust the test suffix
+# in sycl/test/Unit/lit.cfg.py in the line which looks like this:
+#   `config.test_format = lit.formats.GoogleTest(config.llvm_build_mode, <...>)`
+macro(add_sycl_unittest test_name_prefix link_variant)
+  add_sycl_unittest_internal(${test_name_prefix}_Non_Preview_Tests ${link_variant} FALSE ${ARGN})
+  if(SYCL_ENABLE_MAJOR_RELEASE_PREVIEW_LIB)
+    add_sycl_unittest_internal(${test_name_prefix}_Preview_Tests ${link_variant} TRUE ${ARGN})
+  endif()
+endmacro()
+
+add_sycl_unittest(AllowListTests OBJECT 
+    ParseAllowList.cpp
+    DeviceIsAllowed.cpp
+)
\ No newline at end of file

>From db689d0fc0eb94306aac48a91430098c4caec7d2 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Fri, 17 Apr 2026 07:43:51 -0700
Subject: [PATCH 3/5] draft of build that works, need to extract common part,
 do renames

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/CMakeLists.txt                        |   4 +-
 libsycl/unittests/CMakeLists.txt              |   4 +
 .../unittests/usm_functions/CMakeLists.txt    | 105 ++----------------
 libsycl/unittests/usm_functions/usm_alloc.cpp |   0
 4 files changed, 18 insertions(+), 95 deletions(-)
 create mode 100644 libsycl/unittests/usm_functions/usm_alloc.cpp

diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt
index 56f8ca56ac72b..9586565d45b1d 100644
--- a/libsycl/CMakeLists.txt
+++ b/libsycl/CMakeLists.txt
@@ -140,10 +140,10 @@ if(LLVM_INCLUDE_TESTS)
   add_subdirectory(test)
 endif()
 
-add_subdirectory(unittests)
-
 add_custom_target(libsycl-toolchain ALL
   DEPENDS libsycl-runtime-libraries
           sycl-ls
   COMMENT "Building libsycl toolchain..."
 )
+
+add_subdirectory(unittests)
diff --git a/libsycl/unittests/CMakeLists.txt b/libsycl/unittests/CMakeLists.txt
index 052508d3224d8..f7bb233f97a90 100644
--- a/libsycl/unittests/CMakeLists.txt
+++ b/libsycl/unittests/CMakeLists.txt
@@ -1,2 +1,6 @@
+add_custom_target(LibsyclUnitTests)
+
+add_custom_target(check-sycl-unittests)
+
 add_subdirectory(mock)
 add_subdirectory(usm_functions)
\ No newline at end of file
diff --git a/libsycl/unittests/usm_functions/CMakeLists.txt b/libsycl/unittests/usm_functions/CMakeLists.txt
index 06c2e38e6660b..0d1c8d3933f90 100644
--- a/libsycl/unittests/usm_functions/CMakeLists.txt
+++ b/libsycl/unittests/usm_functions/CMakeLists.txt
@@ -1,72 +1,18 @@
-function(add_sycl_unittest_internal test_dirname link_variant is_preview)
+function(add_sycl_unittest test_dirname)
   # Enable exception handling for these unit tests
   set(LLVM_REQUIRES_EH ON)
   set(LLVM_REQUIRES_RTTI ON)
 
-  get_target_property(SYCL_BINARY_DIR sycl-toolchain BINARY_DIR)
+  get_target_property(LIBSYCL_BINARY_DIR libsycl-toolchain BINARY_DIR)
 
   string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower)
 
-  # Select which sycl libraries and object to link based
-  # on whether this is a preview build.
-  if (MSVC AND build_type_lower MATCHES "debug")
-    if (${is_preview})
-      set(sycl_obj_target "sycl-previewd_object")
-      set(sycl_so_target "sycl-previewd")
-    else()
-      set(sycl_obj_target "sycld_object")
-      set(sycl_so_target "sycld")
-    endif()
-  else()
-    if (${is_preview})
-      set(sycl_obj_target "sycl-preview_object")
-      set(sycl_so_target "sycl-preview")
-    else()
-      set(sycl_obj_target "sycl_object")
-      set(sycl_so_target "sycl")
-    endif()
-  endif()
-
-  # This is done to ensure that preview tests are kept in a separate
-  # directory, so that they do not interfere with the non-preview tests.
-  # Chaning CMAKE_CURRENT_BINARY_DIR should not affect this variable in its
-  # parent scope.
-  if (${is_preview})
-      set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/Preview")
-  endif()
+  set(sycl_obj_target "sycl_object")
 
-  if ("${link_variant}" MATCHES "SHARED")
-    set(SYCL_LINK_LIBS ${sycl_so_target})
-    add_unittest(SYCLUnitTests ${test_dirname} ${ARGN})
-  else()
-    add_unittest(SYCLUnitTests ${test_dirname}
-                $<TARGET_OBJECTS:${sycl_obj_target}> ${ARGN})
-    target_compile_definitions(${test_dirname}
-                               PRIVATE __SYCL_BUILD_SYCL_DLL)
-
-    get_target_property(SYCL_LINK_LIBS ${sycl_so_target} LINK_LIBRARIES)
-  endif()
-
-  if (SYCL_ENABLE_COVERAGE)
-    target_compile_options(${test_dirname} PUBLIC
-      -fprofile-instr-generate -fcoverage-mapping
-    )
-    target_link_options(${test_dirname} PUBLIC
-      -fprofile-instr-generate -fcoverage-mapping
-    )
-  endif()
-
-  # Add preview-specific compile definition
-  if (${is_preview})
-    target_compile_definitions(${test_dirname}
-        PRIVATE __INTEL_PREVIEW_BREAKING_CHANGES)
-    set(sycl_cache_suffix "_preview")
-  endif()
-
-  if (SYCL_ENABLE_XPTI_TRACING)
-    target_compile_definitions(${test_dirname}
-      PRIVATE XPTI_ENABLE_INSTRUMENTATION XPTI_STATIC_LIBRARY)
-  endif()
+  add_unittest(LibsyclUnitTests ${test_dirname}
+              $<TARGET_OBJECTS:${sycl_obj_target}> ${ARGN})
+  target_compile_definitions(${test_dirname}
+                              PRIVATE _LIBSYCL_BUILDING_LIBRARY)
 
   # check-sycl-unittests was using an old sycl library. So, to get
   # around this problem, we add the new sycl library to the PATH and
@@ -88,24 +34,14 @@ function(add_sycl_unittest_internal test_dirname link_variant is_preview)
 
   target_link_libraries(${test_dirname}
     PRIVATE
-      mockOpenCL
-      LLVMTestingSupport
-      OpenCL-Headers
-      emhash::emhash
-      unified-runtime::mock
-      ${SYCL_LINK_LIBS}
+      ${UT_LIB_TARGET_NAME}
+      ol_mock
     )
 
-  add_dependencies(${test_dirname} ur_adapter_mock mockOpenCL)
-
-  if(SYCL_ENABLE_EXTENSION_JIT)
-    target_link_libraries(${test_dirname} PRIVATE sycl-jit)
-  endif(SYCL_ENABLE_EXTENSION_JIT)
-
   target_include_directories(${test_dirname}
     PRIVATE SYSTEM
       ${sycl_inc_dir}
-      ${SYCL_SOURCE_DIR}/source/
+      ${SYCL_SOURCE_DIR}/src/
       ${SYCL_SOURCE_DIR}/unittests/
     )
   if (UNIX)
@@ -116,25 +52,8 @@ function(add_sycl_unittest_internal test_dirname link_variant is_preview)
         -Wno-inconsistent-missing-override
     )
   endif()
-  target_compile_definitions(${test_dirname} PRIVATE SYCL_DISABLE_FSYCL_SYCLHPP_WARNING)
 endfunction()
 
-# add_sycl_unittest(test_name_prefix SHARED|OBJECT file1.cpp, file2.cpp ...)
-#
-# Will compile the list of files together to create two builds, with and without
-# the SYCL preview features enabled.
-# Produces two binaries, named `basename(test_name_prefix_Non_Preview_Tests)` and `basename(test_name_prefix_Preview_Tests)`
-# Note: in case of changing test names below, please also adjust the test suffix
-# in sycl/test/Unit/lit.cfg.py in the line which looks like this:
-#   `config.test_format = lit.formats.GoogleTest(config.llvm_build_mode, <...>)`
-macro(add_sycl_unittest test_name_prefix link_variant)
-  add_sycl_unittest_internal(${test_name_prefix}_Non_Preview_Tests ${link_variant} FALSE ${ARGN})
-  if(SYCL_ENABLE_MAJOR_RELEASE_PREVIEW_LIB)
-    add_sycl_unittest_internal(${test_name_prefix}_Preview_Tests ${link_variant} TRUE ${ARGN})
-  endif()
-endmacro()
-
-add_sycl_unittest(AllowListTests OBJECT 
-    ParseAllowList.cpp
-    DeviceIsAllowed.cpp
+add_sycl_unittest(USMTests 
+    usm_alloc.cpp
 )
\ No newline at end of file
diff --git a/libsycl/unittests/usm_functions/usm_alloc.cpp b/libsycl/unittests/usm_functions/usm_alloc.cpp
new file mode 100644
index 0000000000000..e69de29bb2d1d

>From 5718f44a638df2601f217ac85ecf87f2e719b4dd Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Mon, 20 Apr 2026 04:53:54 -0700
Subject: [PATCH 4/5] test draft

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/CMakeLists.txt                        |   1 +
 libsycl/src/CMakeLists.txt                    |   2 +-
 libsycl/unittests/mock/CMakeLists.txt         |   5 +-
 libsycl/unittests/mock/helpers.cpp            |   8 +
 libsycl/unittests/mock/{src => }/helpers.hpp  |  38 +++-
 libsycl/unittests/mock/mock.cpp               | 164 ++++++++++++++++++
 libsycl/unittests/mock/src/helpers.cpp        |   8 -
 libsycl/unittests/mock/src/mock.cpp           |  38 ----
 .../unittests/usm_functions/CMakeLists.txt    |   7 +-
 libsycl/unittests/usm_functions/usm_alloc.cpp |  53 ++++++
 10 files changed, 268 insertions(+), 56 deletions(-)
 create mode 100644 libsycl/unittests/mock/helpers.cpp
 rename libsycl/unittests/mock/{src => }/helpers.hpp (75%)
 create mode 100644 libsycl/unittests/mock/mock.cpp
 delete mode 100644 libsycl/unittests/mock/src/helpers.cpp
 delete mode 100644 libsycl/unittests/mock/src/mock.cpp

diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt
index 9586565d45b1d..13740cd4dd909 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})
diff --git a/libsycl/src/CMakeLists.txt b/libsycl/src/CMakeLists.txt
index fe9ffe1fb232c..ccc47e892e3c2 100644
--- a/libsycl/src/CMakeLists.txt
+++ b/libsycl/src/CMakeLists.txt
@@ -1,6 +1,6 @@
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../runtimes/cmake/Modules")
 include(WarningFlags)
-
+add_definitions(-g -O0)
 function(add_sycl_rt_library LIB_TARGET_NAME LIB_OBJ_NAME LIB_OUTPUT_NAME)
   cmake_parse_arguments(ARG "" "" "COMPILE_OPTIONS;SOURCES" ${ARGN})
 
diff --git a/libsycl/unittests/mock/CMakeLists.txt b/libsycl/unittests/mock/CMakeLists.txt
index 9c63b40a9fe61..38b7c9cdb63b8 100644
--- a/libsycl/unittests/mock/CMakeLists.txt
+++ b/libsycl/unittests/mock/CMakeLists.txt
@@ -1,10 +1,11 @@
 add_library(ol_mock STATIC
-    "${CMAKE_CURRENT_SOURCE_DIR}/src/mock.cpp"
+    "${CMAKE_CURRENT_SOURCE_DIR}/mock.cpp"
+    "${CMAKE_CURRENT_SOURCE_DIR}/helpers.cpp"
 )
   add_dependencies(ol_mock
     LLVMOffload
   )
-
+add_definitions(-g -O0)
 target_include_directories(ol_mock
   PRIVATE
     "${CMAKE_CURRENT_SOURCE_DIR}"
diff --git a/libsycl/unittests/mock/helpers.cpp b/libsycl/unittests/mock/helpers.cpp
new file mode 100644
index 0000000000000..eb5420953e7ce
--- /dev/null
+++ b/libsycl/unittests/mock/helpers.cpp
@@ -0,0 +1,8 @@
+#include "helpers.hpp"
+
+namespace mock {
+static Callbacks callbacks = {};
+
+Callbacks &getCallbacks() { return callbacks; }
+
+} // namespace mock
diff --git a/libsycl/unittests/mock/src/helpers.hpp b/libsycl/unittests/mock/helpers.hpp
similarity index 75%
rename from libsycl/unittests/mock/src/helpers.hpp
rename to libsycl/unittests/mock/helpers.hpp
index 14d3c5d8fe28c..c41b5ba566ffd 100644
--- a/libsycl/unittests/mock/src/helpers.hpp
+++ b/libsycl/unittests/mock/helpers.hpp
@@ -5,6 +5,8 @@
 #include <atomic>
 #include <cassert>
 #include <cstddef>
+#include <cstring>
+#include <iterator>
 #include <string>
 #include <unordered_map>
 #include <vector>
@@ -17,13 +19,13 @@ typedef ol_result_t (*ol_mock_callback_t)(void *pParams);
 namespace mock {
 
 struct dummy_handle_t_ {
-  dummy_handle_t_(size_t DataSize = 0)
-      : MStorage(DataSize), MData(MStorage.data()), MSize(DataSize) {}
+  dummy_handle_t_(size_t DataSize = 0) : MStorage(DataSize), MSize(DataSize) {}
   dummy_handle_t_(unsigned char *Data, size_t Size)
-      : MData(Data), MSize(Size) {}
+      : MStorage(Size), MSize(Size) {
+    std::memcpy(MStorage.data(), Data, Size);
+  }
   std::atomic<size_t> MRefCounter = 1;
   std::vector<unsigned char> MStorage;
-  unsigned char *MData = nullptr;
   size_t MSize;
 
   template <typename T> T getDataAs() {
@@ -104,3 +106,31 @@ _LIB_EXPORT ol_error_struct_t *
 getErrorUnimplementedFunction(const std::string &FunctionName);
 
 } // namespace mock
+
+namespace unittest {
+
+class OffloadMock {
+public:
+  OffloadMock() = default;
+
+  OffloadMock(OffloadMock &&Other) = delete;
+  OffloadMock(const OffloadMock &) = delete;
+  OffloadMock &operator=(const OffloadMock &) = delete;
+  ~OffloadMock() {
+    // mock::getCallbacks() is an application lifetime object, we need to reset
+    // these between tests
+    mock::getCallbacks().resetCallbacks();
+  }
+
+  template <typename ParamType, typename... Args>
+  static ol_result_t callCallback(std::string FunctionName, Args &&...args) {
+    auto Callback = mock::getCallbacks().getCallback(FunctionName);
+    if (!Callback)
+      return mock::getErrorUnimplementedFunction(FunctionName);
+
+    ParamType params = {&args...};
+    return Callback(&params);
+  }
+};
+
+} // namespace unittest
diff --git a/libsycl/unittests/mock/mock.cpp b/libsycl/unittests/mock/mock.cpp
new file mode 100644
index 0000000000000..b814b6ad755e1
--- /dev/null
+++ b/libsycl/unittests/mock/mock.cpp
@@ -0,0 +1,164 @@
+#include <cstring>
+#include <list>
+#include <memory>
+#include <optional>
+#include <unordered_map>
+
+#include "helpers.hpp"
+
+std::unordered_map<ol_errc_t, ol_error_struct_t> Errors;
+ol_platform_handle_t DefaultPlatform;
+ol_device_handle_t DefaultDevice{};
+
+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;
+}
+
+// C++20 std::source_location::function_name
+ol_result_t olCreateEvent(ol_queue_handle_t Queue, ol_event_handle_t *Event) {
+  return unittest::OffloadMock::callCallback<ol_create_event_params_t>(
+      __func__, Queue, Event);
+}
+
+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 operator!=(const ol_init_args_t &lhs, const ol_init_args_t &rhs) {
+  return !(lhs == rhs);
+}
+
+ol_result_t olInit(const ol_init_args_t *InitArgs) {
+  // 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;
+}
+
+ol_result_t olShutDown() {
+  assert(DefaultDevice);
+
+  // release platform.
+  mock::releaseDummyHandle(DefaultPlatform);
+  // release device.
+  mock::releaseDummyHandle(DefaultDevice);
+
+  return OL_SUCCESS;
+}
+
+ol_result_t olGetPlatformInfoSize(ol_platform_handle_t Platform,
+                                  ol_platform_info_t PropName,
+                                  size_t *PropSizeRet) {
+  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);
+}
+
+template <typename T> void assignAs(void *PropValue, T NewValue) {
+  *(static_cast<T *>(PropValue)) = NewValue;
+}
+
+OL_APIEXPORT ol_result_t OL_APICALL
+olGetPlatformInfo(ol_platform_handle_t Platform, ol_platform_info_t PropName,
+                  size_t PropSize, void *PropValue) {
+  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);
+}
+
+ol_result_t olGetDeviceInfo(ol_device_handle_t Device,
+                            ol_device_info_t PropName, size_t PropSize,
+                            void *PropValue) {
+  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);
+  }
+}
+
+ol_result_t olGetDeviceInfoSize(ol_device_handle_t Device,
+                                ol_device_info_t PropName,
+                                size_t *PropSizeRet) {
+  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);
+  }
+}
+
+ol_result_t olIterateDevices(
+    // [in] User-provided function called for each available device
+    ol_device_iterate_cb_t Callback,
+    // [in][optional] Optional user data to pass to the callback
+    void *UserData) {
+  if (!Callback)
+    return makeEmptyStrError(OL_ERRC_INVALID_NULL_POINTER);
+
+  assert(DefaultDevice);
+  [[maybe_unused]] bool Result = Callback(DefaultDevice, UserData);
+
+  return OL_SUCCESS;
+}
diff --git a/libsycl/unittests/mock/src/helpers.cpp b/libsycl/unittests/mock/src/helpers.cpp
deleted file mode 100644
index f8a72934a948a..0000000000000
--- a/libsycl/unittests/mock/src/helpers.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "ur_mock_helpers.hpp"
-
-namespace mock {
-static callbacks_t callbacks = {};
-
-callbacks_t &getCallbacks() { return callbacks; }
-
-} // namespace mock
diff --git a/libsycl/unittests/mock/src/mock.cpp b/libsycl/unittests/mock/src/mock.cpp
deleted file mode 100644
index aef11c76492d6..0000000000000
--- a/libsycl/unittests/mock/src/mock.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include <list>
-#include <optional>
-
-#include "helpers.hpp"
-
-namespace unittest {
-
-class OffloadMock {
-public:
-  OffloadMock() = default;
-
-  OffloadMock(OffloadMock &&Other) = delete;
-  OffloadMock(const OffloadMock &) = delete;
-  OffloadMock &operator=(const OffloadMock &) = delete;
-  ~OffloadMock() {
-    // mock::getCallbacks() is an application lifetime object, we need to reset
-    // these between tests
-    mock::getCallbacks().resetCallbacks();
-  }
-
-  template <typename ParamType, typename... Args>
-  static ol_result_t callCallback(std::string FunctionName, Args &&...args) {
-    auto Callback = mock::getCallbacks().getCallback(FunctionName);
-    if (!Callback)
-      return mock::getErrorUnimplementedFunction(FunctionName);
-
-    ParamType params = {&args...};
-    return Callback(&params);
-  }
-};
-
-} // namespace unittest
-
-// C++20 std::source_location::function_name
-ol_result_t olCreateEvent(ol_queue_handle_t Queue, ol_event_handle_t *Event) {
-  return unittest::OffloadMock::callCallback<ol_create_event_params_t>(
-      __func__, Queue, Event);
-}
diff --git a/libsycl/unittests/usm_functions/CMakeLists.txt b/libsycl/unittests/usm_functions/CMakeLists.txt
index 0d1c8d3933f90..bbfa302501be3 100644
--- a/libsycl/unittests/usm_functions/CMakeLists.txt
+++ b/libsycl/unittests/usm_functions/CMakeLists.txt
@@ -40,9 +40,10 @@ function(add_sycl_unittest test_dirname)
 
   target_include_directories(${test_dirname}
     PRIVATE SYSTEM
-      ${sycl_inc_dir}
-      ${SYCL_SOURCE_DIR}/src/
-      ${SYCL_SOURCE_DIR}/unittests/
+      ${LIBSYCL_BUILD_INCLUDE_DIR}
+      ${LIBSYCL_SOURCE_DIR}/src/
+      ${LIBSYCL_SOURCE_DIR}/unittests/
+      $<TARGET_PROPERTY:LLVMOffload,INTERFACE_INCLUDE_DIRECTORIES>
     )
   if (UNIX)
     # These warnings are coming from Google Test code.
diff --git a/libsycl/unittests/usm_functions/usm_alloc.cpp b/libsycl/unittests/usm_functions/usm_alloc.cpp
index e69de29bb2d1d..d429532fb9931 100644
--- a/libsycl/unittests/usm_functions/usm_alloc.cpp
+++ b/libsycl/unittests/usm_functions/usm_alloc.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/sycl.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace sycl;
+
+// inline ur_result_t redefinedEventsWaitWithBarrier(void *pParams) {
+//   GEventsWaitCounter++;
+//   return UR_RESULT_SUCCESS;
+// }
+
+TEST(PlatformTest, APIGetPlatformsDefaultMock) {
+  // Use default callbacks.
+  unittest::OffloadMock mock;
+  auto Platforms = sycl::platform::get_platforms();
+  ASSERT_EQ(Platforms.size(), 1);
+  EXPECT_EQ(Platforms[0].get_backend(), sycl::backend::level_zero);
+
+  auto Devices = Platforms[0].get_devices();
+  ASSERT_EQ(Devices.size(), 1);
+  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]);
+
+  // mock::getCallbacks().set_before_callback("urEnqueueEventsWaitWithBarrier",
+  //                                          &redefinedEventsWaitWithBarrier);
+
+  // context Ctx{Plt};
+  // queue InOrderQueue{Ctx, default_selector_v, property::queue::in_order()};
+
+  // auto buf = sycl::malloc_device<int>(1, InOrderQueue);
+  // event Evt = InOrderQueue.submit(
+  //     [&](sycl::handler &CGH) { CGH.memset(buf, 0, sizeof(buf[0])); });
+  // InOrderQueue.submit([&](sycl::handler &CGH) { CGH.host_task([=] {}); })
+  //     .wait();
+
+  // size_t expectedCount = 1u;
+  // EXPECT_EQ(GEventsWaitCounter, expectedCount);
+}

>From 705e4315f7cc5b779dc1a119c274b184ae6baa22 Mon Sep 17 00:00:00 2001
From: "Tikhomirova, Kseniya" <kseniya.tikhomirova at intel.com>
Date: Thu, 23 Apr 2026 09:01:43 -0700
Subject: [PATCH 5/5] draft of pm test

Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova at intel.com>
---
 libsycl/CMakeLists.txt                        |   2 +
 libsycl/cmake/Modules/AddUnitTest.cmake       |  48 +++++
 libsycl/src/detail/program_manager.hpp        |   2 +-
 libsycl/unittests/CMakeLists.txt              |   5 +-
 .../unittests/program_manager/CMakeLists.txt  |   3 +
 .../register_and_unregister.cpp               | 166 ++++++++++++++++++
 .../unittests/usm_functions/CMakeLists.txt    |  57 ------
 7 files changed, 224 insertions(+), 59 deletions(-)
 create mode 100644 libsycl/cmake/Modules/AddUnitTest.cmake
 create mode 100644 libsycl/unittests/program_manager/CMakeLists.txt
 create mode 100644 libsycl/unittests/program_manager/register_and_unregister.cpp

diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt
index 13740cd4dd909..0e8e96da019cb 100644
--- a/libsycl/CMakeLists.txt
+++ b/libsycl/CMakeLists.txt
@@ -147,4 +147,6 @@ add_custom_target(libsycl-toolchain ALL
   COMMENT "Building libsycl toolchain..."
 )
 
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
+
 add_subdirectory(unittests)
diff --git a/libsycl/cmake/Modules/AddUnitTest.cmake b/libsycl/cmake/Modules/AddUnitTest.cmake
new file mode 100644
index 0000000000000..19f943e0be5e4
--- /dev/null
+++ b/libsycl/cmake/Modules/AddUnitTest.cmake
@@ -0,0 +1,48 @@
+function(add_sycl_unittest test_dirname)
+  # Enable exception handling for these unit tests
+  set(LLVM_REQUIRES_EH ON)
+  set(LLVM_REQUIRES_RTTI ON)
+
+  get_target_property(LIBSYCL_BINARY_DIR libsycl-toolchain BINARY_DIR)
+
+  set(sycl_obj_target "sycl_object")
+
+  add_unittest(LibsyclUnitTests ${test_dirname}
+              $<TARGET_OBJECTS:${sycl_obj_target}> ${ARGN})
+  target_compile_definitions(${test_dirname}
+                              PRIVATE _LIBSYCL_BUILDING_LIBRARY)
+
+    add_custom_target(check-sycl-${test_dirname}
+        ${CMAKE_COMMAND} -E env
+        LLVM_PROFILE_FILE="${SYCL_COVERAGE_PATH}/${test_dirname}.profraw"
+        ${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
+      ${UT_LIB_TARGET_NAME}
+      ol_mock
+    )
+
+  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/src/detail/program_manager.hpp b/libsycl/src/detail/program_manager.hpp
index 7d66602151d64..6099a2488d4e8 100644
--- a/libsycl/src/detail/program_manager.hpp
+++ b/libsycl/src/detail/program_manager.hpp
@@ -63,7 +63,7 @@ class ProgramManager {
   /// data passed to addImages.
   void removeImages(__sycl_tgt_bin_desc *FatbinDesc);
 
-private:
+protected:
   ProgramManager() = default;
   ~ProgramManager() = default;
   ProgramManager(ProgramManager const &) = delete;
diff --git a/libsycl/unittests/CMakeLists.txt b/libsycl/unittests/CMakeLists.txt
index f7bb233f97a90..66b2aeecc9384 100644
--- a/libsycl/unittests/CMakeLists.txt
+++ b/libsycl/unittests/CMakeLists.txt
@@ -1,6 +1,9 @@
+include(AddUnitTest)
+
 add_custom_target(LibsyclUnitTests)
 
 add_custom_target(check-sycl-unittests)
 
 add_subdirectory(mock)
-add_subdirectory(usm_functions)
\ No newline at end of file
+add_subdirectory(usm_functions)
+add_subdirectory(program_manager)
\ No newline at end of file
diff --git a/libsycl/unittests/program_manager/CMakeLists.txt b/libsycl/unittests/program_manager/CMakeLists.txt
new file mode 100644
index 0000000000000..ba5c33d2bde26
--- /dev/null
+++ b/libsycl/unittests/program_manager/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_sycl_unittest(ProgramManagerTests 
+    register_and_unregister.cpp
+)
\ No newline at end of file
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..f7b5bc92a37e0
--- /dev/null
+++ b/libsycl/unittests/program_manager/register_and_unregister.cpp
@@ -0,0 +1,166 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <detail/program_manager.hpp>
+
+#include <sycl/__impl/exception.hpp>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace sycl;
+
+using namespace ::testing;
+
+struct MockProgramAndKernelManager : public sycl::detail::ProgramManager {};
+
+constexpr llvm::offloading::EntryTy GGenericEntryTy = {
+    /// Reserved bytes used to detect an older version of the struct, always
+    /// zero.
+    0,
+    /// The current version of the struct for runtime forward compatibility.
+    1,
+    /// The expected consumer of this entry, e.g. CUDA or OpenMP.
+    llvm::object::OFK_SYCL,
+    /// Flags associated with the global.
+    0,
+    /// The address of the global to be registered by the runtime.
+    nullptr,
+    /// The name of the symbol in the device image.
+    nullptr,
+    /// The number of bytes the symbol takes.
+    0,
+    /// Extra generic data used to register this entry.
+    0,
+    /// An extra pointer, usually null.
+    nullptr};
+
+constexpr sycl::detail::__sycl_tgt_device_image GGenericDeviceImage = {
+    // Version
+    3,
+    // OffloadKind
+    llvm::object::OFK_SYCL,
+    // ImageFormat
+    llvm::object::IMG_SPIRV,
+    // TripleString
+    "spirv64-unknown-unknown",
+    // CompileOptions
+    "",
+    // LinkOptions
+    "",
+    // ImageStart
+    nullptr,
+    // ImageEnd
+    nullptr,
+    // EntriesBegin
+    nullptr,
+    // EntriesEnd
+    nullptr,
+    // PropertiesBegin
+    nullptr,
+    // PropertiesEnd
+    nullptr};
+
+TEST(ProgramAndKernelManager, CheckUnsupportedVersionOfFatbin) {
+  sycl::detail::__sycl_tgt_bin_desc DeviceImages = {// Version.
+                                                    3,
+                                                    // Num binaries
+                                                    0,
+                                                    /// Device binaries data.
+                                                    nullptr,
+                                                    // HostEntriesBegin.
+                                                    nullptr,
+                                                    // HostEntriesEnd.
+                                                    nullptr};
+
+  MockProgramAndKernelManager Manager;
+  bool ExceptionIsThrown{};
+  try {
+    Manager.addImages(&DeviceImages);
+  } catch (sycl::exception &E) {
+
+    EXPECT_EQ(E.code(), sycl::errc::runtime);
+    std::string_view MessageView(E.what());
+    EXPECT_TRUE(MessageView.find("Incompatible version") != MessageView.npos);
+    ExceptionIsThrown = true;
+  }
+  EXPECT_TRUE(ExceptionIsThrown);
+
+  DeviceImages.Version = 1;
+  EXPECT_NO_THROW(Manager.addImages(&DeviceImages));
+}
+
+TEST(ProgramAndKernelManager, CheckUnsupportedVersionOfImage) {
+  std::array<sycl::detail::__sycl_tgt_device_image, 1> DevImage{
+      GGenericDeviceImage};
+  DevImage[0].Version = 2;
+  sycl::detail::__sycl_tgt_bin_desc DeviceImages = {// Version.
+                                                    1,
+                                                    // Num binaries
+                                                    DevImage.size(),
+                                                    /// Device binaries data.
+                                                    DevImage.data(),
+                                                    // HostEntriesBegin.
+                                                    nullptr,
+                                                    // HostEntriesEnd.
+                                                    nullptr};
+
+  MockProgramAndKernelManager Manager;
+  bool ExceptionIsThrown{};
+  try {
+    Manager.addImages(&DeviceImages);
+  } catch (sycl::exception &E) {
+
+    EXPECT_EQ(E.code(), sycl::errc::runtime);
+    std::string_view MessageView(E.what());
+    EXPECT_TRUE(MessageView.find("Incompatible device image") !=
+                MessageView.npos);
+    ExceptionIsThrown = true;
+  }
+  EXPECT_TRUE(ExceptionIsThrown);
+
+  DevImage[0].Version = 3;
+  EXPECT_NO_THROW(Manager.addImages(&DeviceImages));
+}
+
+TEST(ProgramAndKernelManager, ChecksInternalStructures) {
+  std::array<std::string, 3> KernelNames = {"kernel1", "kernel2", "kernel3"};
+  std::array<llvm::offloading::EntryTy, 2> Entries1 = {GGenericEntryTy,
+                                                       GGenericEntryTy};
+  Entries1[0].SymbolName = KernelNames[0].data();
+  Entries1[0].Size = KernelNames[0].size();
+  Entries1[1].SymbolName = KernelNames[1].data();
+  Entries1[1].Size = KernelNames[1].size();
+
+  std::array<llvm::offloading::EntryTy, 1> Entries2 = {GGenericEntryTy};
+  Entries2[0].SymbolName = KernelNames[2].data();
+  Entries2[0].Size = KernelNames[2].size();
+
+  std::array<sycl::detail::__sycl_tgt_device_image, 2> DevImages = {
+      GGenericDeviceImage, GGenericDeviceImage};
+  DevImages[0].EntriesBegin = Entries1.begin();
+  DevImages[0].EntriesEnd = Entries1.end();
+  DevImages[1].EntriesBegin = Entries2.begin();
+  DevImages[1].EntriesEnd = Entries2.end();
+
+  sycl::detail::__sycl_tgt_bin_desc DeviceImages = {// Version.
+                                                    1,
+                                                    // Num binaries
+                                                    DevImages.size(),
+                                                    /// Device binaries data.
+                                                    DevImages.data(),
+                                                    // HostEntriesBegin.
+                                                    nullptr,
+                                                    // HostEntriesEnd.
+                                                    nullptr};
+
+  MockProgramAndKernelManager Manager;
+  EXPECT_NO_THROW(Manager.addImages(&DeviceImages));
+}
diff --git a/libsycl/unittests/usm_functions/CMakeLists.txt b/libsycl/unittests/usm_functions/CMakeLists.txt
index bbfa302501be3..efe7e89a1a6be 100644
--- a/libsycl/unittests/usm_functions/CMakeLists.txt
+++ b/libsycl/unittests/usm_functions/CMakeLists.txt
@@ -1,60 +1,3 @@
-function(add_sycl_unittest test_dirname)
-  # Enable exception handling for these unit tests
-  set(LLVM_REQUIRES_EH ON)
-  set(LLVM_REQUIRES_RTTI ON)
-
-  get_target_property(LIBSYCL_BINARY_DIR libsycl-toolchain BINARY_DIR)
-
-  string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower)
-
-  set(sycl_obj_target "sycl_object")
-
-  add_unittest(LibsyclUnitTests ${test_dirname}
-              $<TARGET_OBJECTS:${sycl_obj_target}> ${ARGN})
-  target_compile_definitions(${test_dirname}
-                              PRIVATE _LIBSYCL_BUILDING_LIBRARY)
-
-  # check-sycl-unittests was using an old sycl library. So, to get
-  # around this problem, we add the new sycl library to the PATH and
-  # LD_LIBRARY_PATH on Windows and Linux respectively.
-    add_custom_target(check-sycl-${test_dirname}
-        ${CMAKE_COMMAND} -E env
-        LLVM_PROFILE_FILE="${SYCL_COVERAGE_PATH}/${test_dirname}.profraw"
-        SYCL_CONFIG_FILE_NAME=null.cfg
-        SYCL_DEVICELIB_NO_FALLBACK=1
-        SYCL_CACHE_DIR="${CMAKE_BINARY_DIR}/sycl_cache${sycl_cache_suffix}"
-        "LD_LIBRARY_PATH=${SYCL_BINARY_DIR}/unittests/lib:${CMAKE_BINARY_DIR}/lib:$ENV{LD_LIBRARY_PATH}"
-        ${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
-      ${UT_LIB_TARGET_NAME}
-      ol_mock
-    )
-
-  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>
-    )
-  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()
-
 add_sycl_unittest(USMTests 
     usm_alloc.cpp
 )
\ No newline at end of file



More information about the llvm-commits mailing list