Skip to content

Commit f988831

Browse files
authored
Merge pull request #467 from vinser52/svinogra_ipc_tests
Refactor IPC tests to run with different providers and pools
2 parents 425bb8c + 7b12ce0 commit f988831

File tree

2 files changed

+253
-232
lines changed

2 files changed

+253
-232
lines changed

test/ipcAPI.cpp

Lines changed: 10 additions & 232 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,14 @@
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
// This file contains tests for UMF pool API
55

6-
#include "multithread_helpers.hpp"
7-
#include "pool.hpp"
6+
#include "ipcFixtures.hpp"
7+
88
#include "provider.hpp"
9-
#include "test_helpers.h"
109

11-
#include <umf/ipc.h>
12-
#include <umf/memory_pool.h>
13-
#include <umf/pools/pool_proxy.h>
10+
#include <umf/pools/pool_disjoint.h>
1411

15-
#include <array>
16-
#include <atomic>
17-
#include <cstdlib>
18-
#include <cstring>
19-
#include <mutex>
20-
#include <numeric>
2112
#include <shared_mutex>
22-
#include <thread>
2313
#include <unordered_map>
24-
#include <vector>
2514

2615
struct provider_mock_ipc : public umf_test::provider_base_t {
2716
using allocations_map_type = std::unordered_map<const void *, size_t>;
@@ -39,7 +28,6 @@ struct provider_mock_ipc : public umf_test::provider_base_t {
3928
allocations_mutex_type alloc_mutex;
4029
allocations_map_type allocations;
4130

42-
umf_result_t initialize(void *) noexcept { return UMF_RESULT_SUCCESS; }
4331
enum umf_result_t alloc(size_t size, size_t align, void **ptr) noexcept {
4432
auto ret = helper_prov.alloc(size, align, ptr);
4533
if (ret == UMF_RESULT_SUCCESS) {
@@ -78,7 +66,7 @@ struct provider_mock_ipc : public umf_test::provider_base_t {
7866
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
7967
}
8068
ipcData->ptr = ptr;
81-
ipcData->size = it->second; // size of the base allocation
69+
ipcData->size = size; // size of the base allocation
8270
return UMF_RESULT_SUCCESS;
8371
}
8472
enum umf_result_t put_ipc_handle(void *providerIpcData) noexcept {
@@ -118,220 +106,10 @@ struct provider_mock_ipc : public umf_test::provider_base_t {
118106
}
119107
};
120108

121-
struct umfIpcTest : umf_test::test {
122-
umfIpcTest() : pool(nullptr, nullptr) {}
123-
void SetUp() override {
124-
test::SetUp();
125-
this->pool = makePool();
126-
}
127-
128-
void TearDown() override { test::TearDown(); }
129-
130-
umf::pool_unique_handle_t makePool() {
131-
// TODO: The function is similar to poolCreateExt function
132-
// from memoryPool.hpp
133-
umf_memory_provider_handle_t hProvider;
134-
umf_memory_pool_handle_t hPool;
135-
136-
auto ret =
137-
umfMemoryProviderCreate(&IPC_MOCK_PROVIDER_OPS, &stat, &hProvider);
138-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
139-
140-
auto trace = [](void *trace_context, const char *name) {
141-
stats_type *stat = static_cast<stats_type *>(trace_context);
142-
if (std::strcmp(name, "get_ipc_handle") == 0) {
143-
++stat->getCount;
144-
} else if (std::strcmp(name, "put_ipc_handle") == 0) {
145-
++stat->putCount;
146-
} else if (std::strcmp(name, "open_ipc_handle") == 0) {
147-
++stat->openCount;
148-
} else if (std::strcmp(name, "close_ipc_handle") == 0) {
149-
++stat->closeCount;
150-
}
151-
};
152-
153-
umf_memory_provider_handle_t hTraceProvider =
154-
traceProviderCreate(hProvider, true, (void *)&stat, trace);
155-
156-
ret = umfPoolCreate(umfProxyPoolOps(), hTraceProvider, nullptr,
157-
UMF_POOL_CREATE_FLAG_OWN_PROVIDER, &hPool);
158-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
159-
160-
return umf::pool_unique_handle_t(hPool, &umfPoolDestroy);
161-
}
162-
163-
struct stats_type {
164-
std::atomic<size_t> getCount;
165-
std::atomic<size_t> putCount;
166-
std::atomic<size_t> openCount;
167-
std::atomic<size_t> closeCount;
168-
169-
stats_type() : getCount(0), putCount(0), openCount(0), closeCount(0) {}
170-
};
171-
172-
umf_memory_provider_ops_t IPC_MOCK_PROVIDER_OPS =
173-
umf::providerMakeCOps<provider_mock_ipc, stats_type>();
174-
umf::pool_unique_handle_t pool;
175-
static constexpr int NTHREADS = 10;
176-
stats_type stat;
177-
};
178-
179-
TEST_F(umfIpcTest, BasicFlow) {
180-
constexpr size_t SIZE = 100;
181-
int *ptr = (int *)umfPoolMalloc(pool.get(), SIZE * sizeof(int));
182-
EXPECT_NE(ptr, nullptr);
183-
184-
std::iota(ptr, ptr + SIZE, 0);
185-
186-
umf_ipc_handle_t ipcHandleFull = nullptr;
187-
size_t handleFullSize = 0;
188-
umf_result_t ret = umfGetIPCHandle(ptr, &ipcHandleFull, &handleFullSize);
189-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
190-
umf_ipc_handle_t ipcHandleHalf = nullptr;
191-
size_t handleHalfSize = 0;
192-
ret = umfGetIPCHandle(ptr + SIZE / 2, &ipcHandleHalf, &handleHalfSize);
193-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
194-
ASSERT_EQ(handleFullSize, handleHalfSize);
195-
196-
void *fullArray = nullptr;
197-
ret = umfOpenIPCHandle(pool.get(), ipcHandleFull, &fullArray);
198-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
199-
200-
void *halfArray = nullptr;
201-
ret = umfOpenIPCHandle(pool.get(), ipcHandleHalf, &halfArray);
202-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
203-
204-
for (int i = 0; i < (int)SIZE; ++i) {
205-
ASSERT_EQ(reinterpret_cast<int *>(fullArray)[i], i);
206-
}
207-
// Close fullArray before reading halfArray
208-
ret = umfCloseIPCHandle(fullArray);
209-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
210-
211-
for (int i = 0; i < (int)SIZE / 2; ++i) {
212-
ASSERT_EQ(reinterpret_cast<int *>(halfArray)[i], i + SIZE / 2);
213-
}
214-
ret = umfCloseIPCHandle(halfArray);
215-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
216-
217-
ret = umfPutIPCHandle(ipcHandleFull);
218-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
219-
220-
ret = umfPutIPCHandle(ipcHandleHalf);
221-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
222-
223-
ret = umfPoolFree(pool.get(), ptr);
224-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
225-
226-
EXPECT_EQ(stat.getCount, 1);
227-
EXPECT_EQ(stat.putCount, stat.getCount);
228-
// TODO: enale check below once cache for open IPC handles is implemented
229-
// EXPECT_EQ(stat.openCount, 1);
230-
EXPECT_EQ(stat.closeCount, stat.openCount);
231-
}
232-
233-
TEST_F(umfIpcTest, ConcurrentGetPutHandles) {
234-
std::vector<void *> ptrs;
235-
constexpr size_t ALLOC_SIZE = 100;
236-
constexpr size_t NUM_POINTERS = 100;
237-
for (size_t i = 0; i < NUM_POINTERS; ++i) {
238-
void *ptr = umfPoolMalloc(pool.get(), ALLOC_SIZE);
239-
EXPECT_NE(ptr, nullptr);
240-
ptrs.push_back(ptr);
241-
}
242-
243-
std::array<std::vector<umf_ipc_handle_t>, NTHREADS> ipcHandles;
244-
245-
umf_test::syncthreads_barrier syncthreads(NTHREADS);
246-
247-
auto getHandlesFn = [&ipcHandles, &ptrs, &syncthreads](size_t tid) {
248-
syncthreads();
249-
for (void *ptr : ptrs) {
250-
umf_ipc_handle_t ipcHandle;
251-
size_t handleSize;
252-
umf_result_t ret = umfGetIPCHandle(ptr, &ipcHandle, &handleSize);
253-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
254-
ipcHandles[tid].push_back(ipcHandle);
255-
}
256-
};
257-
258-
umf_test::parallel_exec(NTHREADS, getHandlesFn);
259-
260-
auto putHandlesFn = [&ipcHandles, &syncthreads](size_t tid) {
261-
syncthreads();
262-
for (umf_ipc_handle_t ipcHandle : ipcHandles[tid]) {
263-
umf_result_t ret = umfPutIPCHandle(ipcHandle);
264-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
265-
}
266-
};
267-
268-
umf_test::parallel_exec(NTHREADS, putHandlesFn);
269-
270-
for (void *ptr : ptrs) {
271-
umf_result_t ret = umfPoolFree(pool.get(), ptr);
272-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
273-
}
274-
275-
EXPECT_GE(stat.getCount, NUM_POINTERS);
276-
EXPECT_LE(stat.getCount, NUM_POINTERS * NTHREADS);
277-
EXPECT_EQ(stat.putCount, stat.getCount);
278-
}
279-
280-
TEST_F(umfIpcTest, ConcurrentOpenCloseHandles) {
281-
std::vector<void *> ptrs;
282-
constexpr size_t ALLOC_SIZE = 100;
283-
constexpr size_t NUM_POINTERS = 100;
284-
for (size_t i = 0; i < NUM_POINTERS; ++i) {
285-
void *ptr = umfPoolMalloc(pool.get(), ALLOC_SIZE);
286-
EXPECT_NE(ptr, nullptr);
287-
ptrs.push_back(ptr);
288-
}
289-
290-
std::array<umf_ipc_handle_t, NUM_POINTERS> ipcHandles;
291-
for (size_t i = 0; i < NUM_POINTERS; ++i) {
292-
umf_ipc_handle_t ipcHandle;
293-
size_t handleSize;
294-
umf_result_t ret = umfGetIPCHandle(ptrs[i], &ipcHandle, &handleSize);
295-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
296-
ipcHandles[i] = ipcHandle;
297-
}
298-
299-
std::array<std::vector<void *>, NTHREADS> openedIpcHandles;
300-
301-
umf_test::syncthreads_barrier syncthreads(NTHREADS);
302-
303-
auto openHandlesFn = [this, &ipcHandles, &openedIpcHandles,
304-
&syncthreads](size_t tid) {
305-
syncthreads();
306-
for (auto ipcHandle : ipcHandles) {
307-
void *ptr;
308-
umf_result_t ret = umfOpenIPCHandle(pool.get(), ipcHandle, &ptr);
309-
ASSERT_EQ(ret, UMF_RESULT_SUCCESS);
310-
openedIpcHandles[tid].push_back(ptr);
311-
}
312-
};
313-
314-
umf_test::parallel_exec(NTHREADS, openHandlesFn);
315-
316-
auto closeHandlesFn = [&openedIpcHandles, &syncthreads](size_t tid) {
317-
syncthreads();
318-
for (void *ptr : openedIpcHandles[tid]) {
319-
umf_result_t ret = umfCloseIPCHandle(ptr);
320-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
321-
}
322-
};
323-
324-
umf_test::parallel_exec(NTHREADS, closeHandlesFn);
325-
326-
for (auto ipcHandle : ipcHandles) {
327-
umf_result_t ret = umfPutIPCHandle(ipcHandle);
328-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
329-
}
330-
331-
for (void *ptr : ptrs) {
332-
umf_result_t ret = umfPoolFree(pool.get(), ptr);
333-
EXPECT_EQ(ret, UMF_RESULT_SUCCESS);
334-
}
109+
static umf_memory_provider_ops_t IPC_MOCK_PROVIDER_OPS =
110+
umf::providerMakeCOps<provider_mock_ipc, void>();
335111

336-
EXPECT_EQ(stat.openCount, stat.closeCount);
337-
}
112+
INSTANTIATE_TEST_SUITE_P(umfIpcTestSuite, umfIpcTest,
113+
::testing::Values(testParams{
114+
umfProxyPoolOps(), nullptr, &IPC_MOCK_PROVIDER_OPS,
115+
nullptr}));

0 commit comments

Comments
 (0)