mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
Add unit tests for monotonic_buffer_resource.
This commit is contained in:
parent
665a347447
commit
eee15dda02
@ -22,7 +22,8 @@ struct has_allocate : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_allocate<T,
|
||||
typename std::enable_if<std::is_convertible<
|
||||
decltype(std::declval<T &>().allocate(std::declval<std::size_t>())), void *
|
||||
decltype(std::declval<T &>().allocate(std::declval<std::size_t>(),
|
||||
std::declval<std::size_t>())), void *
|
||||
>::value>::type> : std::true_type {};
|
||||
|
||||
template <typename T, typename = void>
|
||||
@ -31,6 +32,7 @@ struct has_deallocate : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_deallocate<T,
|
||||
decltype(std::declval<T &>().deallocate(std::declval<void *>(),
|
||||
std::declval<std::size_t>(),
|
||||
std::declval<std::size_t>()))
|
||||
> : std::true_type {};
|
||||
|
||||
|
||||
@ -17,7 +17,8 @@ Node *make_node(allocator const &upstream, std::size_t initial_size, std::size_t
|
||||
auto sz = ::LIBIMP::round_up(sizeof(Node), alignment) + initial_size;
|
||||
auto *node = static_cast<Node *>(upstream.allocate(sz));
|
||||
if (node == nullptr) {
|
||||
log.error("failed: allocate memory for `monotonic_buffer_resource`.");
|
||||
log.error("failed: allocate memory for `monotonic_buffer_resource`'s node.",
|
||||
" bytes = ", initial_size, ", alignment = ", alignment);
|
||||
return nullptr;
|
||||
}
|
||||
node->next = nullptr;
|
||||
@ -104,7 +105,15 @@ void *monotonic_buffer_resource::allocate(std::size_t bytes, std::size_t alignme
|
||||
node->next = free_list_;
|
||||
free_list_ = node;
|
||||
next_size_ = next_buffer_size(next_size_);
|
||||
p = reinterpret_cast<::LIBIMP::byte *>(free_list_) + ::LIBIMP::round_up(sizeof(node), alignment);
|
||||
// try again
|
||||
s = node->size - sizeof(monotonic_buffer_resource::node);
|
||||
p = std::align(alignment, bytes, (p = node + 1), s);
|
||||
if (p == nullptr) {
|
||||
log.error("failed: allocate memory for `monotonic_buffer_resource`.",
|
||||
" bytes = ", bytes, ", alignment = ", alignment);
|
||||
return nullptr;
|
||||
}
|
||||
tail_ = static_cast<::LIBIMP::byte *>(p) + s;
|
||||
}
|
||||
head_ = static_cast<::LIBIMP::byte *>(p) + bytes;
|
||||
return p;
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
|
||||
#include <type_traits>
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "libpmr/monotonic_buffer_resource.h"
|
||||
@ -13,3 +17,124 @@ TEST(monotonic_buffer_resource, construct) {
|
||||
pmr::monotonic_buffer_resource{imp::span<imp::byte>{}, pmr::allocator{}};
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
TEST(monotonic_buffer_resource, no_copy) {
|
||||
EXPECT_FALSE(std::is_copy_constructible<pmr::monotonic_buffer_resource>::value);
|
||||
EXPECT_FALSE(std::is_copy_assignable<pmr::monotonic_buffer_resource>::value);
|
||||
EXPECT_FALSE(std::is_move_constructible<pmr::monotonic_buffer_resource>::value);
|
||||
EXPECT_FALSE(std::is_move_assignable<pmr::monotonic_buffer_resource>::value);
|
||||
}
|
||||
|
||||
TEST(monotonic_buffer_resource, upstream_resource) {
|
||||
struct dummy_allocator {
|
||||
bool allocated = false;
|
||||
void *allocate(std::size_t, std::size_t) noexcept { allocated = true; return nullptr; }
|
||||
void deallocate(void *, std::size_t, std::size_t) noexcept {}
|
||||
} dummy;
|
||||
pmr::monotonic_buffer_resource tmp{&dummy};
|
||||
ASSERT_EQ(tmp.upstream_resource().allocate(1), nullptr);
|
||||
ASSERT_TRUE(dummy.allocated);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct dummy_allocator {
|
||||
std::size_t allocated = 0;
|
||||
void *allocate(std::size_t size, std::size_t) noexcept {
|
||||
allocated += size;
|
||||
return std::malloc(size);
|
||||
}
|
||||
void deallocate(void *p, std::size_t size, std::size_t) noexcept {
|
||||
allocated -= size;
|
||||
std::free(p);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(monotonic_buffer_resource, allocate) {
|
||||
dummy_allocator dummy;
|
||||
{
|
||||
pmr::monotonic_buffer_resource tmp{&dummy};
|
||||
ASSERT_EQ(tmp.allocate(0), nullptr);
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
}
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
{
|
||||
pmr::monotonic_buffer_resource tmp{&dummy};
|
||||
std::size_t sz = 0;
|
||||
for (std::size_t i = 1; i < 1024; ++i) {
|
||||
ASSERT_NE(tmp.allocate(i), nullptr);
|
||||
sz += i;
|
||||
}
|
||||
for (std::size_t i = 1; i < 1024; ++i) {
|
||||
ASSERT_NE(tmp.allocate(1024 - i), nullptr);
|
||||
sz += 1024 - i;
|
||||
}
|
||||
ASSERT_GE(dummy.allocated, sz);
|
||||
}
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
}
|
||||
|
||||
TEST(monotonic_buffer_resource, allocate_by_buffer) {
|
||||
dummy_allocator dummy;
|
||||
std::array<imp::byte, 4096> buffer;
|
||||
{
|
||||
pmr::monotonic_buffer_resource tmp{buffer, &dummy};
|
||||
for (std::size_t i = 1; i < 64; ++i) {
|
||||
ASSERT_NE(tmp.allocate(i), nullptr);
|
||||
}
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
std::size_t sz = 0;
|
||||
for (std::size_t i = 1; i < 64; ++i) {
|
||||
ASSERT_NE(tmp.allocate(64 - i), nullptr);
|
||||
sz += 64 - i;
|
||||
}
|
||||
ASSERT_GT(dummy.allocated, sz);
|
||||
}
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
}
|
||||
#include <memory_resource>
|
||||
TEST(monotonic_buffer_resource, release) {
|
||||
dummy_allocator dummy;
|
||||
{
|
||||
pmr::monotonic_buffer_resource tmp{&dummy};
|
||||
tmp.release();
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
ASSERT_NE(tmp.allocate(1024), nullptr);
|
||||
ASSERT_GE(dummy.allocated, 1024);
|
||||
ASSERT_LE(dummy.allocated, 1024 * 1.5);
|
||||
tmp.release();
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
ASSERT_NE(tmp.allocate(1024), nullptr);
|
||||
ASSERT_GE(dummy.allocated, 1024);
|
||||
ASSERT_LE(dummy.allocated, 1024 * 1.5);
|
||||
}
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
std::array<imp::byte, 4096> buffer;
|
||||
{
|
||||
pmr::monotonic_buffer_resource tmp{buffer, &dummy};
|
||||
auto *p = tmp.allocate(1024);
|
||||
ASSERT_EQ(p, buffer.data());
|
||||
p = tmp.allocate(10240);
|
||||
ASSERT_NE(p, buffer.data());
|
||||
ASSERT_LE(dummy.allocated, 10240 + 1024);
|
||||
tmp.release();
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
p = tmp.allocate(1024);
|
||||
ASSERT_EQ(p, buffer.data());
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
}
|
||||
ASSERT_EQ(dummy.allocated, 0);
|
||||
// {
|
||||
// std::pmr::monotonic_buffer_resource res{buffer.data(), buffer.size()};
|
||||
// std::pmr::polymorphic_allocator<imp::byte> tmp{&res};
|
||||
// auto *p = tmp.allocate(1024);
|
||||
// ASSERT_EQ(p, buffer.data());
|
||||
// p = tmp.allocate(10240);
|
||||
// ASSERT_NE(p, buffer.data());
|
||||
// res.release();
|
||||
// p = tmp.allocate(1024);
|
||||
// ASSERT_EQ(p, buffer.data());
|
||||
// }
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user