Skip to content

Commit 835323e

Browse files
committed
Add OS memory provider config tests
Testing a single NUMA node: - tests for protection flags except the UMF_PROTECTION_EXEC flag, - tests for numa modes except unsupported values, - tests for visibility.
1 parent c1c55b6 commit 835323e

File tree

3 files changed

+197
-2
lines changed

3 files changed

+197
-2
lines changed

.github/workflows/basic.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ jobs:
103103
- name: Run tests
104104
working-directory: ${{env.BUILD_DIR}}
105105
run: |
106-
ctest --output-on-failure
106+
ctest --output-on-failure --verbose
107107
108108
- name: Test make install
109109
working-directory: ${{env.BUILD_DIR}}

test/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022-2023 Intel Corporation
1+
# Copyright (C) 2022-2024 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

@@ -105,4 +105,7 @@ if(UMF_BUILD_OS_MEMORY_PROVIDER AND LINUX) # OS-specific functions are implement
105105
add_umf_test(NAME memspace_numa
106106
SRCS memspace_numa.cpp
107107
LIBS numa)
108+
add_umf_test(NAME provider_os_memory_config
109+
SRCS provider_os_memory_config.cpp
110+
LIBS umf_utils numa)
108111
endif()

test/provider_os_memory_config.cpp

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
*
3+
* Copyright (C) 2024 Intel Corporation
4+
*
5+
* Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT.
6+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
*
8+
*/
9+
10+
#include "base.hpp"
11+
#include "provider_os_memory_internal.h"
12+
#include "umf/providers/provider_os_memory.h"
13+
14+
#include <numa.h>
15+
#include <numaif.h>
16+
#include <unistd.h>
17+
18+
struct providerConfigTest : testing::Test {
19+
umf_result_t res;
20+
umf_memory_provider_handle_t provider = nullptr;
21+
umf_os_memory_provider_params_t params = {
22+
/* .protection = */ UMF_PROTECTION_READ | UMF_PROTECTION_WRITE,
23+
/* .visibility = */ UMF_VISIBILITY_PRIVATE,
24+
25+
// NUMA config
26+
/* .nodemask = */ NULL,
27+
/* .maxnode = */ 0,
28+
/* .numa_mode = */ UMF_NUMA_MODE_DEFAULT,
29+
/* .numa_flags = */ 0,
30+
31+
// others
32+
/* .traces = */ 1,
33+
};
34+
size_t size = 128;
35+
void *ptr = nullptr;
36+
char *dest = nullptr;
37+
38+
void SetUp() override {
39+
int ret = numa_available();
40+
if (ret) {
41+
GTEST_SKIP() << "Test skipped, NUMA not available";
42+
}
43+
dest = (char *)malloc(size);
44+
}
45+
46+
void TearDown() override {
47+
if (ptr) {
48+
umfMemoryProviderFree(provider, ptr, size);
49+
}
50+
free(dest);
51+
if (provider) {
52+
umfMemoryProviderDestroy(provider);
53+
}
54+
}
55+
56+
void create_provider(umf_os_memory_provider_params_t *params) {
57+
res = umfMemoryProviderCreate(&UMF_OS_MEMORY_PROVIDER_OPS, params,
58+
&provider);
59+
ASSERT_EQ(res, UMF_RESULT_SUCCESS);
60+
ASSERT_NE(provider, nullptr);
61+
}
62+
63+
void allocate_memory() {
64+
res = umfMemoryProviderAlloc(provider, size, os_get_page_size(), &ptr);
65+
ASSERT_EQ(res, UMF_RESULT_SUCCESS);
66+
ASSERT_NE(ptr, nullptr);
67+
}
68+
69+
void copy_ptr_data() {
70+
*dest = 'B';
71+
memcpy(dest, ptr, size);
72+
}
73+
74+
void read_memory() {
75+
copy_ptr_data();
76+
EXPECT_EQ(*static_cast<char *>(ptr), *dest);
77+
}
78+
79+
void write_memory(char c) {
80+
memset(ptr, c, size);
81+
EXPECT_EQ(static_cast<char *>(ptr)[0], c);
82+
}
83+
};
84+
85+
TEST_F(providerConfigTest, protection_flag_none) {
86+
// pages may not be accessed - PROT_NONE
87+
params.protection = UMF_PROTECTION_NONE;
88+
create_provider(&params);
89+
allocate_memory();
90+
91+
// read failure
92+
EXPECT_DEATH(copy_ptr_data(), "");
93+
94+
// write failure
95+
EXPECT_DEATH(memset(ptr, 'A', size), "");
96+
}
97+
98+
TEST_F(providerConfigTest, protection_flag_read) {
99+
// pages may be read - PROT_READ
100+
params.protection = UMF_PROTECTION_READ;
101+
create_provider(&params);
102+
allocate_memory();
103+
104+
// read success
105+
read_memory();
106+
107+
// write failure
108+
EXPECT_DEATH(memset(ptr, 'A', size), "");
109+
}
110+
111+
TEST_F(providerConfigTest, protection_flag_write) {
112+
// pages may be written to - PROT_WRITE
113+
params.protection = UMF_PROTECTION_WRITE;
114+
create_provider(&params);
115+
allocate_memory();
116+
117+
// write success
118+
write_memory('A');
119+
}
120+
121+
struct providerConfigTestNumaMode
122+
: providerConfigTest,
123+
testing::WithParamInterface<umf_numa_mode_t> {
124+
void SetUp() override {
125+
providerConfigTest::SetUp();
126+
params.numa_mode = GetParam();
127+
}
128+
};
129+
130+
INSTANTIATE_TEST_SUITE_P(numa_modes, providerConfigTestNumaMode,
131+
testing::Values(UMF_NUMA_MODE_DEFAULT,
132+
UMF_NUMA_MODE_BIND,
133+
UMF_NUMA_MODE_INTERLEAVE,
134+
UMF_NUMA_MODE_PREFERRED,
135+
UMF_NUMA_MODE_LOCAL));
136+
137+
TEST_P(providerConfigTestNumaMode, numa_modes) {
138+
if (params.numa_mode != UMF_NUMA_MODE_DEFAULT &&
139+
params.numa_mode != UMF_NUMA_MODE_LOCAL) {
140+
struct bitmask *allowed_nodes = numa_get_mems_allowed();
141+
params.nodemask = allowed_nodes->maskp;
142+
params.maxnode = allowed_nodes->size;
143+
}
144+
145+
create_provider(&params);
146+
allocate_memory();
147+
write_memory('A');
148+
149+
int actual_mode = -1;
150+
long ret = get_mempolicy(&actual_mode, nullptr, 0, ptr, MPOL_F_ADDR);
151+
ASSERT_EQ(ret, 0);
152+
ASSERT_EQ(os_translate_numa_mode(params.numa_mode), actual_mode);
153+
}
154+
155+
struct providerConfigTestVisibility
156+
: providerConfigTest,
157+
testing::WithParamInterface<umf_mem_visibility_t> {
158+
const char primary_char = 'A';
159+
const char new_char = 'B';
160+
char expected_char;
161+
void SetUp() override {
162+
params.visibility = GetParam();
163+
if (params.visibility == UMF_VISIBILITY_PRIVATE) {
164+
expected_char = primary_char;
165+
} else if (params.visibility == UMF_VISIBILITY_SHARED) {
166+
expected_char = new_char;
167+
}
168+
}
169+
};
170+
171+
INSTANTIATE_TEST_SUITE_P(visibility, providerConfigTestVisibility,
172+
testing::Values(UMF_VISIBILITY_PRIVATE,
173+
UMF_VISIBILITY_SHARED));
174+
175+
TEST_P(providerConfigTestVisibility, visibility) {
176+
create_provider(&params);
177+
allocate_memory();
178+
write_memory(primary_char);
179+
180+
int pid = fork();
181+
if (pid == 0) {
182+
// child process
183+
write_memory('B');
184+
} else if (pid > 0) {
185+
// main process
186+
int status;
187+
while (-1 == waitpid(0, &status, 0)) {
188+
// wait for the child process to complete
189+
}
190+
EXPECT_EQ(static_cast<char *>(ptr)[0], expected_char);
191+
}
192+
}

0 commit comments

Comments
 (0)