#include #include #include #include #include #include "gtest/gtest.h" #include "libpmr/new.h" TEST(pmr_new, regular_sizeof) { ASSERT_EQ(pmr::regular_sizeof(), pmr::regular_head_size + alignof(std::max_align_t)); ASSERT_EQ(pmr::regular_sizeof(), pmr::regular_head_size + alignof(std::max_align_t)); ASSERT_EQ(pmr::regular_sizeof(), pmr::regular_head_size + alignof(std::max_align_t)); ASSERT_EQ(pmr::regular_sizeof(), pmr::regular_head_size + alignof(std::max_align_t)); ASSERT_EQ((pmr::regular_sizeof>()), ::LIBIMP::round_up(pmr::regular_head_size + 10 , alignof(std::max_align_t))); ASSERT_EQ((pmr::regular_sizeof>()), ::LIBIMP::round_up(pmr::regular_head_size + 100 , alignof(std::max_align_t))); ASSERT_EQ((pmr::regular_sizeof>()), ::LIBIMP::round_up(pmr::regular_head_size + 1000 , 128)); ASSERT_EQ((pmr::regular_sizeof>()), ::LIBIMP::round_up(pmr::regular_head_size + 10000, 8192)); ASSERT_EQ((pmr::regular_sizeof>()), (std::numeric_limits::max)()); } TEST(pmr_new, $new) { auto p = pmr::$new(); ASSERT_NE(p, nullptr); *p = -1; ASSERT_EQ(*p, -1); pmr::$delete(p); } TEST(pmr_new, $new_value) { auto p = pmr::$new((std::numeric_limits::max)()); ASSERT_NE(p, nullptr); ASSERT_EQ(*p, (std::numeric_limits::max)()); pmr::$delete(p); } namespace { template void test_new$array() { std::array pts; using T = std::array; for (int i = 0; i < (int)pts.size(); ++i) { auto p = pmr::$new(); pts[i] = p; std::memset(p, i, sizeof(T)); } for (int i = 0; i < (int)pts.size(); ++i) { T tmp; std::memset(&tmp, i, sizeof(T)); ASSERT_EQ(std::memcmp(pts[i], &tmp, sizeof(T)), 0); pmr::$delete(static_cast(pts[i])); } } } // namespace TEST(pmr_new, $new_array) { test_new$array<1000, 10>(); test_new$array<1000, 100>(); test_new$array<1000, 1000>(); test_new$array<1000, 10000>(); test_new$array<1000, 100000>(); // test_new$array<1000, 1000000>(); } namespace { int construct_count__ = 0; class Base { public: virtual ~Base() = default; virtual int get() const = 0; }; class Derived : public Base { public: Derived(int value) : value_(value) { construct_count__ = value_; } ~Derived() override { construct_count__ = 0; } int get() const override { return value_; } private: int value_; }; class Derived64K : public Derived { public: using Derived::Derived; private: std::array padding_; }; } // namespace TEST(pmr_new, $delete_poly) { Base *p = pmr::$new(-1); ASSERT_NE(p, nullptr); ASSERT_EQ(p->get(), -1); ASSERT_EQ(construct_count__, -1); pmr::$delete(p); ASSERT_EQ(construct_count__, 0); ASSERT_EQ(p, pmr::$new((std::numeric_limits::max)())); ASSERT_EQ(p->get(), (std::numeric_limits::max)()); ASSERT_EQ(construct_count__, (std::numeric_limits::max)()); pmr::$delete(p); ASSERT_EQ(construct_count__, 0); } TEST(pmr_new, $delete_poly64k) { Base *p = pmr::$new(-1); ASSERT_NE(p, nullptr); ASSERT_EQ(p->get(), -1); ASSERT_EQ(construct_count__, -1); pmr::$delete(p); ASSERT_EQ(construct_count__, 0); Base *q = pmr::$new((std::numeric_limits::max)()); ASSERT_EQ(q->get(), (std::numeric_limits::max)()); ASSERT_EQ(construct_count__, (std::numeric_limits::max)()); pmr::$delete(q); ASSERT_EQ(construct_count__, 0); } TEST(pmr_new, $delete_null) { Base *p = nullptr; pmr::$delete(p); SUCCEED(); } TEST(pmr_new, multi_thread) { std::array threads; for (auto &t : threads) { t = std::thread([] { for (int i = 0; i < 10000; ++i) { auto p = pmr::$new(); *p = i; pmr::$delete(p); } std::array pts; for (int i = 0; i < 10000; ++i) { auto p = pmr::$new>(); pts[i] = p; std::memset(p, i, sizeof(std::array)); } for (int i = 0; i < 10000; ++i) { std::array tmp; std::memset(&tmp, i, sizeof(std::array)); ASSERT_EQ(std::memcmp(pts[i], &tmp, sizeof(std::array)), 0); pmr::$delete(static_cast *>(pts[i])); } }); } for (auto &t : threads) { t.join(); } SUCCEED(); }