Skip to content

Commit a531874

Browse files
committed
Add tests for tracking provider
Signed-off-by: Lukasz Dorau <[email protected]>
1 parent 7a9b4b1 commit a531874

File tree

2 files changed

+319
-0
lines changed

2 files changed

+319
-0
lines changed

test/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ if(LINUX AND (NOT UMF_DISABLE_HWLOC)) # OS-specific functions are implemented
343343
NAME provider_fixed_memory
344344
SRCS provider_fixed_memory.cpp
345345
LIBS ${UMF_UTILS_FOR_TEST})
346+
add_umf_test(
347+
NAME provider_tracking
348+
SRCS provider_tracking.cpp
349+
LIBS ${UMF_UTILS_FOR_TEST})
346350

347351
# This test requires Linux-only file memory provider
348352
if(UMF_POOL_JEMALLOC_ENABLED)

test/provider_tracking.cpp

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
// Copyright (C) 2025 Intel Corporation
2+
// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
#include "base.hpp"
6+
7+
#include "cpp_helpers.hpp"
8+
#include "test_helpers.h"
9+
#ifndef _WIN32
10+
#include "test_helpers_linux.h"
11+
#endif
12+
13+
#include <umf/memory_provider.h>
14+
#include <umf/pools/pool_proxy.h>
15+
#include <umf/providers/provider_fixed_memory.h>
16+
17+
using umf_test::test;
18+
19+
#define FIXED_BUFFER_SIZE (512 * utils_get_page_size())
20+
#define INVALID_PTR ((void *)0x01)
21+
22+
using providerCreateExtParams = std::tuple<umf_memory_provider_ops_t *, void *>;
23+
24+
static void providerCreateExt(providerCreateExtParams params,
25+
umf::provider_unique_handle_t *handle) {
26+
umf_memory_provider_handle_t hProvider = nullptr;
27+
auto [provider_ops, provider_params] = params;
28+
29+
auto ret =
30+
umfMemoryProviderCreate(provider_ops, provider_params, &hProvider);
31+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
32+
ASSERT_NE(hProvider, nullptr);
33+
34+
*handle =
35+
umf::provider_unique_handle_t(hProvider, &umfMemoryProviderDestroy);
36+
}
37+
38+
struct TrackingProviderTest
39+
: umf_test::test,
40+
::testing::WithParamInterface<providerCreateExtParams> {
41+
void SetUp() override {
42+
test::SetUp();
43+
44+
// Allocate a memory buffer to use with the fixed memory provider
45+
memory_size = FIXED_BUFFER_SIZE;
46+
memory_buffer = malloc(memory_size);
47+
ASSERT_NE(memory_buffer, nullptr);
48+
49+
// Create provider parameters
50+
umf_fixed_memory_provider_params_handle_t params = nullptr;
51+
umf_result_t res = umfFixedMemoryProviderParamsCreate(
52+
&params, memory_buffer, memory_size);
53+
ASSERT_EQ(res, UMF_RESULT_SUCCESS);
54+
ASSERT_NE(params, nullptr);
55+
56+
providerCreateExt(std::make_tuple(umfFixedMemoryProviderOps(), params),
57+
&provider);
58+
59+
umfFixedMemoryProviderParamsDestroy(params);
60+
umf_result_t umf_result =
61+
umfMemoryProviderGetMinPageSize(provider.get(), NULL, &page_size);
62+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
63+
64+
page_plus_64 = page_size + 64;
65+
66+
umf_memory_pool_handle_t hPool = nullptr;
67+
umf_result = umfPoolCreate(umfProxyPoolOps(), provider.get(), nullptr,
68+
0, &hPool);
69+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
70+
71+
pool = umf::pool_unique_handle_t(hPool, &umfPoolDestroy);
72+
}
73+
74+
void TearDown() override {
75+
if (memory_buffer) {
76+
free(memory_buffer);
77+
memory_buffer = nullptr;
78+
}
79+
test::TearDown();
80+
}
81+
82+
umf::provider_unique_handle_t provider;
83+
umf::pool_unique_handle_t pool;
84+
size_t page_size;
85+
size_t page_plus_64;
86+
void *memory_buffer = nullptr;
87+
size_t memory_size = 0;
88+
};
89+
90+
// TESTS
91+
92+
INSTANTIATE_TEST_SUITE_P(trackingProviderTest, TrackingProviderTest,
93+
::testing::Values(providerCreateExtParams{
94+
umfFixedMemoryProviderOps(), nullptr}));
95+
96+
TEST_P(TrackingProviderTest, create_destroy) {
97+
// Creation and destruction are handled in SetUp and TearDown
98+
}
99+
100+
TEST_P(TrackingProviderTest, merge) {
101+
umf_result_t umf_result;
102+
void *ptr1 = nullptr;
103+
void *ptr2 = nullptr;
104+
size_t size = page_size;
105+
size_t alignment = page_size;
106+
107+
umf_result = umfMemoryProviderAlloc(provider.get(), size, alignment, &ptr1);
108+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
109+
ASSERT_NE(ptr1, nullptr);
110+
111+
umf_result = umfMemoryProviderAlloc(provider.get(), size, alignment, &ptr2);
112+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
113+
ASSERT_NE(ptr2, nullptr);
114+
115+
ASSERT_EQ((uintptr_t)ptr2 - (uintptr_t)ptr1, size);
116+
117+
memset(ptr1, 0x11, size);
118+
memset(ptr2, 0x22, size);
119+
120+
size_t merged_size = size * 2;
121+
umf_result = umfMemoryProviderAllocationMerge(provider.get(), ptr1, ptr2,
122+
merged_size);
123+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
124+
125+
umf_result = umfMemoryProviderFree(provider.get(), ptr1, merged_size);
126+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
127+
}
128+
129+
TEST_P(TrackingProviderTest, split) {
130+
umf_result_t umf_result;
131+
void *ptr1 = nullptr;
132+
void *ptr2 = nullptr;
133+
size_t size = page_size;
134+
size_t alignment = page_size;
135+
136+
umf_result =
137+
umfMemoryProviderAlloc(provider.get(), size * 2, alignment, &ptr1);
138+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
139+
ASSERT_NE(ptr1, nullptr);
140+
141+
umf_result =
142+
umfMemoryProviderAllocationSplit(provider.get(), ptr1, size * 2, size);
143+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
144+
145+
ptr2 = (void *)((uintptr_t)ptr1 + size);
146+
memset(ptr1, 0x11, size);
147+
148+
umf_result = umfMemoryProviderFree(provider.get(), ptr1, size);
149+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
150+
151+
memset(ptr2, 0x22, size);
152+
umf_result = umfMemoryProviderFree(provider.get(), ptr2, size);
153+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
154+
}
155+
156+
static void
157+
createPoolFromAllocation(void *ptr0, size_t size1,
158+
umf_memory_provider_handle_t *_providerFromPtr,
159+
umf_memory_pool_handle_t *_poolFromPtr) {
160+
umf_result_t umf_result;
161+
162+
// Create provider parameters
163+
umf_fixed_memory_provider_params_handle_t params = nullptr;
164+
umf_result = umfFixedMemoryProviderParamsCreate(&params, ptr0, size1);
165+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
166+
ASSERT_NE(params, nullptr);
167+
168+
umf_memory_provider_handle_t provider1 = nullptr;
169+
umf_result = umfMemoryProviderCreate(umfFixedMemoryProviderOps(), params,
170+
&provider1);
171+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
172+
ASSERT_NE(provider1, nullptr);
173+
174+
umf_memory_pool_handle_t pool1 = nullptr;
175+
umf_result =
176+
umfPoolCreate(umfProxyPoolOps(), provider1, nullptr, 0, &pool1);
177+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
178+
179+
umfFixedMemoryProviderParamsDestroy(params);
180+
181+
*_providerFromPtr = provider1;
182+
*_poolFromPtr = pool1;
183+
}
184+
185+
TEST_P(TrackingProviderTest, whole_size_success) {
186+
umf_result_t umf_result;
187+
size_t size0;
188+
size_t size1;
189+
void *ptr0 = nullptr;
190+
void *ptr1 = nullptr;
191+
192+
umf_memory_pool_handle_t pool0 = pool.get();
193+
194+
size0 = FIXED_BUFFER_SIZE - (2 * page_size);
195+
ptr0 = umfPoolAlignedMalloc(pool0, size0, utils_get_page_size());
196+
ASSERT_NE(ptr0, nullptr);
197+
198+
size1 = size0; // whole size
199+
200+
umf_memory_provider_handle_t provider1 = nullptr;
201+
umf_memory_pool_handle_t pool1 = nullptr;
202+
createPoolFromAllocation(ptr0, size1, &provider1, &pool1);
203+
204+
ptr1 = umfPoolMalloc(pool1, size1);
205+
ASSERT_NE(ptr1, nullptr);
206+
207+
umf_result = umfPoolFree(pool1, ptr1);
208+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
209+
210+
umfPoolDestroy(pool1);
211+
umfMemoryProviderDestroy(provider1);
212+
213+
umf_result = umfPoolFree(pool0, ptr0);
214+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
215+
}
216+
217+
TEST_P(TrackingProviderTest, half_size_success) {
218+
umf_result_t umf_result;
219+
size_t size0;
220+
size_t size1;
221+
void *ptr0 = nullptr;
222+
void *ptr1 = nullptr;
223+
224+
umf_memory_pool_handle_t pool0 = pool.get();
225+
226+
size0 = FIXED_BUFFER_SIZE - (2 * page_size);
227+
ptr0 = umfPoolAlignedMalloc(pool0, size0, utils_get_page_size());
228+
ASSERT_NE(ptr0, nullptr);
229+
230+
size1 = size0 / 2; // half size
231+
232+
umf_memory_provider_handle_t provider1 = nullptr;
233+
umf_memory_pool_handle_t pool1 = nullptr;
234+
createPoolFromAllocation(ptr0, size1, &provider1, &pool1);
235+
236+
ptr1 = umfPoolMalloc(pool1, size1);
237+
ASSERT_NE(ptr1, nullptr);
238+
239+
umf_result = umfPoolFree(pool1, ptr1);
240+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
241+
242+
umfPoolDestroy(pool1);
243+
umfMemoryProviderDestroy(provider1);
244+
245+
umf_result = umfPoolFree(pool0, ptr0);
246+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
247+
}
248+
249+
TEST_P(TrackingProviderTest, failure_exceeding_size) {
250+
umf_result_t umf_result;
251+
size_t size0;
252+
size_t size1;
253+
void *ptr0 = nullptr;
254+
void *ptr1 = nullptr;
255+
256+
umf_memory_pool_handle_t pool0 = pool.get();
257+
258+
size0 = FIXED_BUFFER_SIZE - (2 * page_size);
259+
ptr0 = umfPoolAlignedMalloc(pool0, size0, utils_get_page_size());
260+
ASSERT_NE(ptr0, nullptr);
261+
262+
size1 = FIXED_BUFFER_SIZE - page_size; // exceeding size
263+
264+
umf_memory_provider_handle_t provider1 = nullptr;
265+
umf_memory_pool_handle_t pool1 = nullptr;
266+
createPoolFromAllocation(ptr0, size1, &provider1, &pool1);
267+
268+
ptr1 = umfPoolMalloc(pool1, size1);
269+
ASSERT_EQ(ptr1, nullptr);
270+
271+
umfPoolDestroy(pool1);
272+
umfMemoryProviderDestroy(provider1);
273+
274+
umf_result = umfPoolFree(pool0, ptr0);
275+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
276+
}
277+
278+
#define TEST_LEVEL 9
279+
280+
TEST_P(TrackingProviderTest, failure_exceeding_levels) {
281+
umf_result_t umf_result;
282+
size_t size;
283+
void *ptr[TEST_LEVEL] = {0};
284+
umf_memory_provider_handle_t providers[TEST_LEVEL] = {0};
285+
umf_memory_pool_handle_t pools[TEST_LEVEL] = {0};
286+
287+
size = FIXED_BUFFER_SIZE - (2 * page_size);
288+
pools[0] = pool.get();
289+
290+
for (int i = 0; i < TEST_LEVEL - 1; i++) {
291+
fprintf(stderr, "Alloc #%d\n", i);
292+
ptr[i] = umfPoolAlignedMalloc(pools[i], size, utils_get_page_size());
293+
ASSERT_NE(ptr[i], nullptr);
294+
295+
createPoolFromAllocation(ptr[i], size, &providers[i + 1],
296+
&pools[i + 1]);
297+
}
298+
299+
// tracker level is too high
300+
fprintf(stderr, "Alloc #%d\n", 8);
301+
ptr[8] = umfPoolAlignedMalloc(pools[8], size, utils_get_page_size());
302+
ASSERT_EQ(ptr[8], nullptr);
303+
304+
for (int i = TEST_LEVEL - 2; i >= 0; i--) {
305+
fprintf(stderr, "Free #%d\n", i);
306+
umfPoolDestroy(pools[i + 1]);
307+
umfMemoryProviderDestroy(providers[i + 1]);
308+
309+
umf_result = umfPoolFree(pools[i], ptr[i]);
310+
ASSERT_EQ(umf_result, UMF_RESULT_SUCCESS);
311+
}
312+
313+
// umfPoolDestroy(pools[0]);
314+
// umfMemoryProviderDestroy(providers[0]);
315+
}

0 commit comments

Comments
 (0)