Skip to content

Commit caaa19a

Browse files
committed
add memtarget rollback tests
1 parent 04aa67b commit caaa19a

2 files changed

Lines changed: 267 additions & 4 deletions

File tree

test/CMakeLists.txt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022-2025 Intel Corporation
1+
# Copyright (C) 2022-2026 Intel Corporation
22
# Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
33
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

@@ -377,8 +377,10 @@ if(LINUX) # OS-specific functions are implemented
377377
LIBS ${LIBNUMA_LIBRARIES})
378378
add_umf_test(
379379
NAME memtarget
380-
SRCS memspaces/memtarget.cpp
381-
LIBS ${LIBNUMA_LIBRARIES} ${UMF_HWLOC_NAME})
380+
SRCS memspaces/memtarget.cpp ${UMF_SRC_DIR}/memtarget.c
381+
${UMF_SRC_DIR}/libumf_linux.c
382+
LIBS ${UMF_UTILS_FOR_TEST} ${UMF_BA_FOR_TEST} ${LIBNUMA_LIBRARIES}
383+
${UMF_HWLOC_NAME})
382384
add_umf_test(
383385
NAME provider_devdax_memory
384386
SRCS provider_devdax_memory.cpp

test/memspaces/memtarget.cpp

Lines changed: 262 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2024-2025 Intel Corporation
1+
// Copyright (C) 2024-2026 Intel Corporation
22
// Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44

@@ -9,8 +9,143 @@
99
#include <umf/experimental/memspace.h>
1010
#include <umf/experimental/memtarget.h>
1111

12+
#include "memtarget_internal.h"
13+
#include "memtarget_ops.h"
14+
1215
using umf_test::test;
1316

17+
namespace {
18+
19+
struct fake_target_t {
20+
unsigned id;
21+
};
22+
23+
int finalizeCount;
24+
25+
umf_result_t fakeInitialize(void *params, void **memoryTarget) {
26+
if (!params || !memoryTarget) {
27+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
28+
}
29+
30+
auto target = static_cast<fake_target_t *>(malloc(sizeof(fake_target_t)));
31+
if (!target) {
32+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
33+
}
34+
35+
target->id = *static_cast<unsigned *>(params);
36+
*memoryTarget = target;
37+
return UMF_RESULT_SUCCESS;
38+
}
39+
40+
void fakeFinalize(void *memoryTarget) {
41+
finalizeCount++;
42+
free(memoryTarget);
43+
}
44+
45+
umf_result_t fakeClone(void *memoryTarget, void **outMemoryTarget) {
46+
if (!memoryTarget || !outMemoryTarget) {
47+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
48+
}
49+
50+
auto source = static_cast<fake_target_t *>(memoryTarget);
51+
auto target = static_cast<fake_target_t *>(malloc(sizeof(fake_target_t)));
52+
if (!target) {
53+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
54+
}
55+
56+
target->id = source->id;
57+
*outMemoryTarget = target;
58+
return UMF_RESULT_SUCCESS;
59+
}
60+
61+
umf_result_t fakePoolCreateFromMemspace(umf_const_memspace_handle_t memspace,
62+
void **memoryTargets, size_t numTargets,
63+
umf_const_mempolicy_handle_t policy,
64+
umf_memory_pool_handle_t *pool) {
65+
(void)memspace;
66+
(void)memoryTargets;
67+
(void)numTargets;
68+
(void)policy;
69+
(void)pool;
70+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
71+
}
72+
73+
umf_result_t
74+
fakeMemoryProviderCreateFromMemspace(umf_const_memspace_handle_t memspace,
75+
void **memoryTargets, size_t numTargets,
76+
umf_const_mempolicy_handle_t policy,
77+
umf_memory_provider_handle_t *provider) {
78+
(void)memspace;
79+
(void)memoryTargets;
80+
(void)numTargets;
81+
(void)policy;
82+
(void)provider;
83+
return UMF_RESULT_ERROR_NOT_SUPPORTED;
84+
}
85+
86+
umf_result_t fakeGetCapacity(void *memoryTarget, size_t *capacity) {
87+
(void)memoryTarget;
88+
*capacity = 4096;
89+
return UMF_RESULT_SUCCESS;
90+
}
91+
92+
umf_result_t fakeGetBandwidth(void *srcMemoryTarget, void *dstMemoryTarget,
93+
size_t *bandwidth) {
94+
(void)srcMemoryTarget;
95+
(void)dstMemoryTarget;
96+
*bandwidth = 1;
97+
return UMF_RESULT_SUCCESS;
98+
}
99+
100+
umf_result_t fakeGetLatency(void *srcMemoryTarget, void *dstMemoryTarget,
101+
size_t *latency) {
102+
(void)srcMemoryTarget;
103+
(void)dstMemoryTarget;
104+
*latency = 1;
105+
return UMF_RESULT_SUCCESS;
106+
}
107+
108+
umf_result_t fakeGetType(void *memoryTarget, umf_memtarget_type_t *type) {
109+
(void)memoryTarget;
110+
*type = UMF_MEMTARGET_TYPE_NUMA;
111+
return UMF_RESULT_SUCCESS;
112+
}
113+
114+
umf_result_t fakeGetId(void *memoryTarget, unsigned *id) {
115+
*id = static_cast<fake_target_t *>(memoryTarget)->id;
116+
return UMF_RESULT_SUCCESS;
117+
}
118+
119+
umf_result_t fakeCompare(void *memTarget, void *otherMemTarget, int *result) {
120+
auto left = static_cast<fake_target_t *>(memTarget);
121+
auto right = static_cast<fake_target_t *>(otherMemTarget);
122+
123+
if (finalizeCount > 0 && left->id == 2 && right->id == 2) {
124+
return UMF_RESULT_ERROR_UNKNOWN;
125+
}
126+
127+
*result = left->id == right->id ? 0 : 1;
128+
return UMF_RESULT_SUCCESS;
129+
}
130+
131+
const umf_memtarget_ops_t FAKE_OPS = {
132+
.version = UMF_MEMTARGET_OPS_VERSION_CURRENT,
133+
.initialize = fakeInitialize,
134+
.finalize = fakeFinalize,
135+
.clone = fakeClone,
136+
.pool_create_from_memspace = fakePoolCreateFromMemspace,
137+
.memory_provider_create_from_memspace =
138+
fakeMemoryProviderCreateFromMemspace,
139+
.get_capacity = fakeGetCapacity,
140+
.get_bandwidth = fakeGetBandwidth,
141+
.get_latency = fakeGetLatency,
142+
.get_type = fakeGetType,
143+
.get_id = fakeGetId,
144+
.compare = fakeCompare,
145+
};
146+
147+
} // namespace
148+
14149
TEST_F(test, memTargetNuma) {
15150
auto memspace = umfMemspaceHostAllGet();
16151
ASSERT_NE(memspace, nullptr);
@@ -172,3 +307,129 @@ TEST_F(test, memTargetRemoveAll) {
172307
ret = umfMemspaceDestroy(memspace);
173308
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
174309
}
310+
311+
TEST_F(test, memTargetFilterRollback) {
312+
finalizeCount = 0;
313+
314+
umf_memspace_handle_t memspace = nullptr;
315+
umf_result_t ret = umfMemspaceNew(&memspace);
316+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
317+
ASSERT_NE(memspace, nullptr);
318+
319+
umf_memtarget_handle_t target1 = nullptr;
320+
umf_memtarget_handle_t target2 = nullptr;
321+
umf_memtarget_handle_t target3 = nullptr;
322+
unsigned id1 = 1;
323+
unsigned id2 = 2;
324+
unsigned id3 = 3;
325+
326+
ret = umfMemtargetCreate(&FAKE_OPS, &id1, &target1);
327+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
328+
ret = umfMemtargetCreate(&FAKE_OPS, &id2, &target2);
329+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
330+
ret = umfMemtargetCreate(&FAKE_OPS, &id3, &target3);
331+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
332+
333+
ret = umfMemspaceMemtargetAdd(memspace, target1);
334+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
335+
ret = umfMemspaceMemtargetAdd(memspace, target2);
336+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
337+
ret = umfMemspaceMemtargetAdd(memspace, target3);
338+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
339+
340+
ret = umfMemspaceUserFilter(
341+
memspace,
342+
[](umf_const_memspace_handle_t, umf_const_memtarget_handle_t,
343+
void *) -> int {
344+
// filter everything
345+
return 0;
346+
},
347+
nullptr);
348+
EXPECT_EQ(ret, UMF_RESULT_ERROR_UNKNOWN);
349+
ASSERT_EQ(umfMemspaceMemtargetNum(memspace), 3u);
350+
351+
std::vector<unsigned> ids;
352+
for (size_t targetIdx = 0; targetIdx < umfMemspaceMemtargetNum(memspace);
353+
targetIdx++) {
354+
auto target = umfMemspaceMemtargetGet(memspace, targetIdx);
355+
ASSERT_NE(target, nullptr);
356+
357+
unsigned id = 0;
358+
ret = umfMemtargetGetId(target, &id);
359+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
360+
ids.push_back(id);
361+
}
362+
363+
std::sort(ids.begin(), ids.end());
364+
EXPECT_EQ(ids, (std::vector<unsigned>{1, 2, 3}));
365+
366+
ret = umfMemspaceDestroy(memspace);
367+
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
368+
umfMemtargetDestroy(target1);
369+
umfMemtargetDestroy(target2);
370+
umfMemtargetDestroy(target3);
371+
}
372+
373+
TEST_F(test, memTargetFilterRemoveOnlyId2) {
374+
finalizeCount = 0;
375+
376+
umf_memspace_handle_t memspace = nullptr;
377+
umf_result_t ret = umfMemspaceNew(&memspace);
378+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
379+
ASSERT_NE(memspace, nullptr);
380+
381+
umf_memtarget_handle_t target1 = nullptr;
382+
umf_memtarget_handle_t target2 = nullptr;
383+
umf_memtarget_handle_t target3 = nullptr;
384+
unsigned id1 = 1;
385+
unsigned id2 = 2;
386+
unsigned id3 = 3;
387+
388+
ret = umfMemtargetCreate(&FAKE_OPS, &id1, &target1);
389+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
390+
ret = umfMemtargetCreate(&FAKE_OPS, &id2, &target2);
391+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
392+
ret = umfMemtargetCreate(&FAKE_OPS, &id3, &target3);
393+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
394+
395+
ret = umfMemspaceMemtargetAdd(memspace, target1);
396+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
397+
ret = umfMemspaceMemtargetAdd(memspace, target2);
398+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
399+
ret = umfMemspaceMemtargetAdd(memspace, target3);
400+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
401+
402+
ret = umfMemspaceUserFilter(
403+
memspace,
404+
[](umf_const_memspace_handle_t, umf_const_memtarget_handle_t target,
405+
void *args) -> int {
406+
// filter out target with id passed in args, keep the rest
407+
unsigned targetId = 0;
408+
(void)umfMemtargetGetId(target, &targetId);
409+
return targetId == *static_cast<unsigned *>(args) ? 0 : 1;
410+
},
411+
&id2);
412+
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
413+
ASSERT_EQ(umfMemspaceMemtargetNum(memspace), 2u);
414+
415+
std::vector<unsigned> ids;
416+
for (size_t targetIdx = 0; targetIdx < umfMemspaceMemtargetNum(memspace);
417+
targetIdx++) {
418+
auto target = umfMemspaceMemtargetGet(memspace, targetIdx);
419+
ASSERT_NE(target, nullptr);
420+
421+
unsigned id = 0;
422+
ret = umfMemtargetGetId(target, &id);
423+
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
424+
ids.push_back(id);
425+
}
426+
427+
std::sort(ids.begin(), ids.end());
428+
EXPECT_EQ(ids, (std::vector<unsigned>{1, 3}));
429+
430+
ret = umfMemspaceDestroy(memspace);
431+
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
432+
umfMemtargetDestroy(target1);
433+
umfMemtargetDestroy(target2);
434+
umfMemtargetDestroy(target3);
435+
}

0 commit comments

Comments
 (0)