#include "catch.hpp" #include "shm_manager.h" #include "shm.h" #include "shm_object.h" #if defined(__GNUC__) #include #endif extern bg::detail::ShmContext g_shm_ctx; TEST_CASE("ShmManager, AllocateRawMemory") { bg::ShmOptions opts(false, "Test", nullptr); opts.fix_vptr_on_init = false; REQUIRE(bg::ShmInit(opts) == true); REQUIRE(g_shm_ctx.mgr); for(size_t i = 8; i < 0x100000000LL; i = i << 8) { size_t real_bytes = i - 1; void* memory = g_shm_ctx.mgr->AllocateRawMemory(&real_bytes, i); REQUIRE(memory); memset(memory, 0, real_bytes); REQUIRE(real_bytes == i); } bg::ShmFini(); } struct TestSigleton { TestSigleton(int a, char b, void* c) { this->a = a; this->b = b; this->c = c; } int a{}; char b{}; void* c{}; }; TEST_CASE("ShmManager, Singleton") { bg::ShmOptions opts(false, "Test", nullptr); opts.fix_vptr_on_init = false; REQUIRE(bg::ShmInit(opts) == true); REQUIRE(g_shm_ctx.mgr); bg::detail::TypeName type(typeid(TestSigleton).name(), sizeof(TestSigleton)); REQUIRE(g_shm_ctx.mgr->HasSingleton(type) == false); int a = 3; REQUIRE(bg::ShmGetSingleton(1, 2, &a)); REQUIRE(g_shm_ctx.mgr->HasSingleton(type) == true); TestSigleton* temp = bg::ShmGetSingleton(1, 1, &a); REQUIRE(temp->a == 1); REQUIRE(temp->b == 2); REQUIRE(temp->c == &a); bg::ShmDeleteSingleton(); REQUIRE(g_shm_ctx.mgr->HasSingleton(type) == false); bg::ShmFini(); } class TestBase { public: virtual int Do1() { return a; } virtual ~TestBase() = default; int a = 2; }; class TestBase2 { public: virtual int Do1() { return b; } virtual ~TestBase2() = default; int b = 3; }; class TestDrvied :public TestBase, public TestBase2 { public: virtual ~TestDrvied() = default; }; TEST_CASE("ShmManager, creat/resume") { bg::ShmOptions opts(false, "Test", nullptr); opts.fix_vptr_on_init = true; REQUIRE(bg::ShmInit(opts) == true); int a = 3; REQUIRE(g_shm_ctx.mgr); bg::detail::TypeName type(typeid(TestSigleton).name(), sizeof(TestSigleton)); REQUIRE(g_shm_ctx.mgr->HasSingleton(type) == false); REQUIRE(bg::ShmGetSingleton(1, 2, &a)); REQUIRE(g_shm_ctx.mgr->HasSingleton(type) == true); TestDrvied* drv = bg::ShmNew(); uintptr_t drv_ptr = *reinterpret_cast(drv); TestBase* base = static_cast(drv); base->a = 2; TestBase2* base2 = static_cast(drv); base2->b = 3; opts.resume = true; size_t real_size = sizeof(bg::detail::ShmManager); #if defined(__GNUC__) munmap(g_shm_ctx.mgr, real_size); g_shm_ctx.mgr = nullptr; REQUIRE(bg::ShmInit(opts) == true); #elif defined(_MSC_VER) // 占住共享内存 windows 会自动释放 char path[256]; snprintf(path, 256, "%s-mgr.mmap", opts.identifier); void* memory1 = bg::detail::ShmObjectAttach(path, 0, &real_size, &real_size); REQUIRE(memory1); bg::detail::ShmObjectDelete(g_shm_ctx.mgr, real_size, path); real_size = 0x100000000; void* memory2 = bg::detail::ShmObjectAttach("Test-000.mmap", 0, &real_size, &real_size); REQUIRE(memory2); bg::detail::ShmObjectDelete((void*)0x00006f0000000000, real_size, "Test-000.mmap"); g_shm_ctx.mgr = nullptr; REQUIRE(bg::ShmInit(opts) == true); bg::detail::ShmObjectDelete(memory1, real_size, path); bg::detail::ShmObjectDelete(memory2, real_size, "Test-000.mmap"); #endif REQUIRE(bg::detail::ShmCurrentVersion() == 2); TestSigleton* temp = bg::ShmGetSingleton(1, 1, &a); REQUIRE(temp->a == 1); REQUIRE(temp->b == 2); REQUIRE(temp->c == &a); REQUIRE(*reinterpret_cast(base) == drv_ptr); REQUIRE(*reinterpret_cast(base2) != 0); REQUIRE(base->Do1() == 2); REQUIRE(base2->Do1() == 3); bg::ShmDelete(base); bg::ShmDeleteSingleton(); REQUIRE(g_shm_ctx.mgr->HasSingleton(type) == false); bg::ShmFini(); } TEST_CASE("ShmManager, malloc realloc Free Calloc") { bg::ShmOptions opts(false, "Test", nullptr); opts.fix_vptr_on_init = false; REQUIRE(bg::ShmInit(opts) == true); REQUIRE(g_shm_ctx.mgr); for(size_t bytes = 8; bytes < (CLASS_MAX_BYTES << 4); bytes = bytes << 1) { void* memory = g_shm_ctx.mgr->Malloc(bytes); REQUIRE(memory); memset(memory, 0, bytes); *(int*)memory = 1; *(int*)((uintptr_t)memory + bytes - 4) = 2; void* memory1 = g_shm_ctx.mgr->Realloc(memory, bytes << 1); REQUIRE(memory1); REQUIRE(*(int*)memory1 == 1); REQUIRE(*(int*)((uintptr_t)memory1 + bytes - 4) == 2); g_shm_ctx.mgr->Free(memory1); void* memory2 = g_shm_ctx.mgr->Calloc(bytes/ 4, 4); REQUIRE(memory2); for(size_t i = 0; i < bytes / 4; ++ i) { REQUIRE(*(int*)memory2 == 0); } g_shm_ctx.mgr->Free(memory2); } bg::ShmFini(); }