Skip to content

Commit

Permalink
Add tests for the size threshold of the proxy library (Linux only)
Browse files Browse the repository at this point in the history
The proxyLib_size_threshold_* tests test the size threshold
of the proxy library (Linux only yet). The size threshold
is set to 64 bytes in this test, so all allocations of:
1) size <  64 go through the default system allocator
   and (umfPoolByPtr(ptr_size < 64) == nullptr)
2) size >= 64 go through the proxy lib allocator
   and (umfPoolByPtr(ptr_size >= 64) != nullptr).

Ref: oneapi-src#894

Signed-off-by: Lukasz Dorau <[email protected]>
  • Loading branch information
ldorau committed Nov 19, 2024
1 parent a4fced6 commit 3966c3a
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/reusable_proxy_lib.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ jobs:
working-directory: ${{env.BUILD_DIR}}
run: UMF_PROXY="page.disposition=shared-shm" LD_PRELOAD=./lib/libumf_proxy.so /usr/bin/date

# TODO enable the provider_file_memory_ipc test when the IPC tests with the proxy library are fixed
# see the issue: https://github.com/oneapi-src/unified-memory-framework/issues/864
- name: Run "ctest --output-on-failure" with proxy library and size.threshold=128
working-directory: ${{env.BUILD_DIR}}
run: >
UMF_PROXY="page.disposition=shared-shm;size.threshold=128"
LD_PRELOAD=./lib/libumf_proxy.so
ctest --output-on-failure -E provider_file_memory_ipc
- name: Check coverage
if: ${{ matrix.build_type == 'Debug' }}
working-directory: ${{env.BUILD_DIR}}
Expand Down
10 changes: 10 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,16 @@ if(UMF_PROXY_LIB_ENABLED AND UMF_BUILD_SHARED_LIBRARY)
SRCS ${BA_SOURCES_FOR_TEST} test_proxy_lib.cpp
LIBS ${UMF_UTILS_FOR_TEST} umf_proxy)

# TODO enable this test on Windows
if(LINUX)
add_umf_test(
NAME test_proxy_lib_size_threshold
SRCS ${BA_SOURCES_FOR_TEST} test_proxy_lib_size_threshold.cpp
LIBS ${UMF_UTILS_FOR_TEST} umf_proxy)
set_property(TEST umf-test_proxy_lib_size_threshold
PROPERTY ENVIRONMENT UMF_PROXY="size.threshold=64")
endif()

# the memoryPool test run with the proxy library
add_umf_test(
NAME proxy_lib_memoryPool
Expand Down
183 changes: 183 additions & 0 deletions test/test_proxy_lib_size_threshold.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/

#if defined(__APPLE__)
#include <malloc/malloc.h>
#else
#include <malloc.h>
#endif

#include <umf/proxy_lib_new_delete.h>

#include "base.hpp"
#include "test_helpers.h"
#include "utils_common.h"

using umf_test::test;

// size threshold defined by the env variable UMF_PROXY="size.threshold=64"
#define SIZE_THRESHOLD 64
#define SIZE_EQ (SIZE_THRESHOLD)
#define SIZE_LT (SIZE_THRESHOLD - 1)

#define ALIGN_1024 1024

TEST_F(test, proxyLib_basic) {
// a check to verify we are running the proxy library
void *ptr = (void *)0x01;

#ifdef _WIN32
size_t size = _msize(ptr);
#elif __APPLE__
size_t size = ::malloc_size(ptr);
#else
size_t size = ::malloc_usable_size(ptr);
#endif

ASSERT_EQ(size, 0xDEADBEEF);
}

TEST_F(test, proxyLib_realloc_size0) {
// realloc(ptr, 0) == free(ptr)
// realloc(ptr, 0) returns NULL
ASSERT_EQ(::realloc(::malloc(SIZE_EQ), 0), nullptr);
}

// The proxyLib_size_threshold_* tests test the size threshold of the proxy library.
// The size threshold is set to SIZE_THRESHOLD bytes in this test, so all allocations of:
// 1) size < SIZE_THRESHOLD go through the default system allocator
// (umfPoolByPtr(ptr_size < SIZE_THRESHOLD) == nullptr)
// 2) size >= SIZE_THRESHOLD go through the proxy library allocator
// (umfPoolByPtr(ptr_size >= SIZE_THRESHOLD) != nullptr)

TEST_F(test, proxyLib_size_threshold_aligned_alloc) {
#ifdef _WIN32
void *ptr_LT = _aligned_malloc(SIZE_LT, ALIGN_1024);
void *ptr_EQ = _aligned_malloc(SIZE_EQ, ALIGN_1024);
#else
void *ptr_LT = ::aligned_alloc(ALIGN_1024, SIZE_LT);
void *ptr_EQ = ::aligned_alloc(ALIGN_1024, SIZE_EQ);
#endif

ASSERT_NE(ptr_LT, nullptr);
ASSERT_NE(ptr_EQ, nullptr);

// verify alignment
ASSERT_EQ((int)(IS_ALIGNED((uintptr_t)ptr_LT, ALIGN_1024)), 1);
ASSERT_EQ((int)(IS_ALIGNED((uintptr_t)ptr_EQ, ALIGN_1024)), 1);

ASSERT_EQ(umfPoolByPtr(ptr_LT), nullptr);
ASSERT_NE(umfPoolByPtr(ptr_EQ), nullptr);

#ifdef _WIN32
_aligned_free(ptr_LT);
_aligned_free(ptr_EQ);
#else
::free(ptr_LT);
::free(ptr_EQ);
#endif
}

TEST_F(test, proxyLib_size_threshold_malloc) {
void *ptr_LT = malloc(SIZE_LT);
void *ptr_EQ = malloc(SIZE_EQ);

ASSERT_NE(ptr_LT, nullptr);
ASSERT_NE(ptr_EQ, nullptr);

ASSERT_EQ(umfPoolByPtr(ptr_LT), nullptr);
ASSERT_NE(umfPoolByPtr(ptr_EQ), nullptr);

::free(ptr_LT);
::free(ptr_EQ);
}

TEST_F(test, proxyLib_size_threshold_calloc) {
void *ptr_LT = calloc(SIZE_LT, 1);
void *ptr_EQ = calloc(SIZE_EQ, 1);

ASSERT_NE(ptr_LT, nullptr);
ASSERT_NE(ptr_EQ, nullptr);

ASSERT_EQ(umfPoolByPtr(ptr_LT), nullptr);
ASSERT_NE(umfPoolByPtr(ptr_EQ), nullptr);

::free(ptr_LT);
::free(ptr_EQ);
}

TEST_F(test, proxyLib_size_threshold_realloc_up) {
void *ptr_LT = malloc(SIZE_LT);
void *ptr_EQ = malloc(SIZE_EQ);

ASSERT_NE(ptr_LT, nullptr);
ASSERT_NE(ptr_EQ, nullptr);

void *ptr_LT_r = realloc(ptr_LT, 2 * SIZE_LT);
void *ptr_EQ_r = realloc(ptr_EQ, 2 * SIZE_EQ);

ASSERT_NE(ptr_LT_r, nullptr);
ASSERT_NE(ptr_EQ_r, nullptr);

ASSERT_EQ(umfPoolByPtr(ptr_LT_r), nullptr);
ASSERT_NE(umfPoolByPtr(ptr_EQ_r), nullptr);

::free(ptr_LT_r);
::free(ptr_EQ_r);
}

TEST_F(test, proxyLib_size_threshold_realloc_down) {
void *ptr_LT = malloc(SIZE_LT);
void *ptr_EQ = malloc(SIZE_EQ);

ASSERT_NE(ptr_LT, nullptr);
ASSERT_NE(ptr_EQ, nullptr);

void *ptr_LT_r = realloc(ptr_LT, SIZE_LT / 2);
void *ptr_EQ_r = realloc(ptr_EQ, SIZE_EQ / 2);

ASSERT_NE(ptr_LT_r, nullptr);
ASSERT_NE(ptr_EQ_r, nullptr);

ASSERT_EQ(umfPoolByPtr(ptr_LT_r), nullptr);
ASSERT_NE(umfPoolByPtr(ptr_EQ_r), nullptr);

::free(ptr_LT_r);
::free(ptr_EQ_r);
}

TEST_F(test, proxyLib_size_threshold_malloc_usable_size) {

void *ptr_LT = ::malloc(SIZE_LT);
void *ptr_EQ = ::malloc(SIZE_EQ);

ASSERT_NE(ptr_LT, nullptr);
ASSERT_NE(ptr_EQ, nullptr);

if (ptr_LT == nullptr || ptr_EQ == nullptr) {
// Fix for the following CodeQL's warning on Windows:
// 'ptr' could be '0': this does not adhere to the specification for the function '_msize'.
return;
}

#ifdef _WIN32
size_t size_LT = _msize(ptr_LT);
size_t size_EQ = _msize(ptr_EQ);
#elif __APPLE__
size_t size_LT = ::malloc_size(ptr_LT);
size_t size_EQ = ::malloc_size(ptr_EQ);
#else
size_t size_LT = ::malloc_usable_size(ptr_LT);
size_t size_EQ = ::malloc_usable_size(ptr_EQ);
#endif

ASSERT_EQ((int)(size_LT == 0 || size_LT >= SIZE_LT), 1);
ASSERT_EQ((int)(size_EQ == 0 || size_EQ >= SIZE_EQ), 1);

::free(ptr_LT);
::free(ptr_EQ);
}
7 changes: 7 additions & 0 deletions test/utils/utils_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,20 @@ TEST_F(test, utils_shm_create_invalid_args) {
TEST_F(test, utils_get_size_threshold) {
// Expected input to utils_get_size_threshold():
// char *str_threshold = utils_env_var_get_str("UMF_PROXY", "size.threshold=");

// positive tests
EXPECT_EQ(utils_get_size_threshold((char *)"size.threshold=111"), 111);
EXPECT_EQ(utils_get_size_threshold((char *)"size.threshold=222;abcd"), 222);
EXPECT_EQ(utils_get_size_threshold((char *)"size.threshold=333;var=value"),
333);
// LONG_MAX = 9223372036854775807
EXPECT_EQ(utils_get_size_threshold(
(char *)"size.threshold=9223372036854775807;var=value"),
9223372036854775807);

// negative tests
EXPECT_EQ(utils_get_size_threshold(NULL), 0);
EXPECT_EQ(utils_get_size_threshold((char *)"size.threshold="), -1);
EXPECT_EQ(utils_get_size_threshold((char *)"size.threshold=abc"), -1);
EXPECT_EQ(utils_get_size_threshold((char *)"size.threshold=-111"), -1);
}

0 comments on commit 3966c3a

Please sign in to comment.