#include // std::aligned_storage_t #include #include #include "gtest/gtest.h" #include "libimp/construct.h" #include "libimp/pimpl.h" #include "libimp/countof.h" #include "libimp/horrible_cast.h" #include "libimp/detect_plat.h" TEST(utility, construct) { struct Foo { int a_; short b_; char c_; }; std::aligned_storage_t foo; Foo *pfoo = imp::construct(&foo, 123, short{321}, '1'); EXPECT_EQ(pfoo->a_, 123); EXPECT_EQ(pfoo->b_, 321); EXPECT_EQ(pfoo->c_, '1'); imp::destroy(pfoo); static int bar_test_flag = 0; struct Bar : Foo { Bar(int a, short b, char c) : Foo{a, b, c} { ++bar_test_flag; } ~Bar() { --bar_test_flag; } }; std::aligned_storage_t bar; Bar *pbar = imp::construct(&bar, 123, short(321), '1'); EXPECT_EQ(pbar->a_, 123); EXPECT_EQ(pbar->b_, 321); EXPECT_EQ(pbar->c_, '1'); EXPECT_EQ(bar_test_flag, 1); imp::destroy(pbar); EXPECT_EQ(bar_test_flag, 0); std::aligned_storage_t bars[3]; for (auto &b : bars) { auto pb = imp::construct(&b, 321, short(123), '3'); EXPECT_EQ(pb->a_, 321); EXPECT_EQ(pb->b_, 123); EXPECT_EQ(pb->c_, '3'); } //EXPECT_EQ(bar_test_flag, imp::countof(bars)); imp::destroy(reinterpret_cast(&bars)); EXPECT_EQ(bar_test_flag, 0); } namespace { struct Foo : imp::pimpl::Obj { int *pi_; Foo(int *pi) : pi_(pi) {} }; struct Bar : imp::pimpl::Obj { int *pi_; int *pj_; Bar(int *pi, int *pj) : pi_(pi), pj_(pj) {} }; } // namespace TEST(utility, pimpl_is_comfortable) { EXPECT_TRUE ((imp::pimpl::is_comfortable::value)); EXPECT_TRUE ((imp::pimpl::is_comfortable::value)); EXPECT_FALSE((imp::pimpl::is_comfortable::value)); EXPECT_TRUE ((imp::pimpl::is_comfortable::value)); EXPECT_FALSE((imp::pimpl::is_comfortable::value)); } TEST(utility, pimpl_inherit) { int i = 123; Foo *pfoo = Foo::make(&i); EXPECT_EQ(imp::pimpl::get(pfoo)->pi_, &i); pfoo->clear(); int j = 321; Bar *pbar = Bar::make(&i, &j); EXPECT_EQ(imp::pimpl::get(pbar)->pi_, &i); EXPECT_EQ(imp::pimpl::get(pbar)->pj_, &j); pbar->clear(); } TEST(utility, countof) { struct { constexpr int Size() const noexcept { return 3; } } sv; EXPECT_FALSE(imp::detail::countof_trait_has_size::value); EXPECT_TRUE (imp::detail::countof_trait_has_Size::value); std::vector vec {1, 2, 3, 4, 5}; int arr[] {7, 6, 5, 4, 3, 2, 1}; EXPECT_EQ(imp::countof(sv) , sv.Size()); EXPECT_EQ(imp::countof(vec), vec.size()); EXPECT_EQ(imp::countof(arr), sizeof(arr) / sizeof(arr[0])); } TEST(utility, horrible_cast) { struct A { int a_; } a {123}; struct B { char a_[sizeof(int)]; } b = imp::horrible_cast(a); EXPECT_EQ(b.a_[1], 0); EXPECT_EQ(b.a_[2], 0); #if LIBIMP_ENDIAN_LIT EXPECT_EQ(b.a_[0], 123); EXPECT_EQ(b.a_[3], 0); #else EXPECT_EQ(b.a_[3], 123); EXPECT_EQ(b.a_[0], 0); #endif // imp::horrible_cast(0ll); }