#include "render_3D/detail/Render_Domain.h" #include #include #include #include #include #include #include namespace renderive::render_3d::detail { namespace { TEST(RenderDomain, SharesDomainPerGpuIndex) { auto first = Render_Domain::acquire(0x7ffffffcU); auto second = Render_Domain::acquire(0x7ffffffcU); auto other = Render_Domain::acquire(0x7ffffffbU); EXPECT_EQ(first, second); EXPECT_NE(first, other); } TEST(RenderDomain, PreparedTaskRunsAfterNoThrowHandoff) { auto domain = Render_Domain::acquire(0x7ffffffaU); std::atomic executed{}; auto prepared = domain->prepare([&] { executed.store(true, std::memory_order_release); }); ASSERT_TRUE(prepared); EXPECT_EQ(domain->post(std::move(prepared.task)), Render_Domain::Error::none); EXPECT_TRUE(domain->invoke([] {})); EXPECT_TRUE(executed.load(std::memory_order_acquire)); } TEST(RenderDomain, AbandonedPreparedTasksReleaseReservedCapacity) { auto domain = Render_Domain::acquire(0x7ffffff9U); for (std::size_t index = 0; index < 128; ++index) { auto prepared = domain->prepare([] {}); ASSERT_TRUE(prepared); } EXPECT_TRUE(domain->invoke([] {})); } TEST(RenderDomain, NestedInvokeExecutesInlineOnTheAffinityThread) { auto domain = Render_Domain::acquire(0x7ffffff8U); const auto value = domain->invoke([domain] { const auto nested = domain->invoke([] { return 42; }); if (!nested) throw std::logic_error("nested render-domain invoke unexpectedly stopped"); return *nested.value; }); ASSERT_TRUE(value); EXPECT_EQ(*value.value, 42); } TEST(RenderDomain, ReportsBoundedAdmissionStatistics) { auto domain = Render_Domain::acquire(0x7ffffff7U); const auto statistics = domain->statistics(); EXPECT_EQ(statistics.capacity, 64U); EXPECT_TRUE(statistics.admitted <= statistics.capacity); EXPECT_TRUE(statistics.queued <= statistics.capacity); } TEST(RenderDomain, ContainsUnhandledFireAndForgetExceptionsAndKeepsRunning) { auto domain = Render_Domain::acquire(0x7ffffff6U); const auto before = domain->statistics().unhandled_exception_count; EXPECT_EQ(domain->post([] { throw std::runtime_error("unexpected render-domain failure"); }), Render_Domain::Error::none); EXPECT_TRUE(domain->invoke([] {})); const auto after = domain->statistics().unhandled_exception_count; EXPECT_EQ(after, before + 1U); const auto value = domain->invoke([] { return 17; }); ASSERT_TRUE(value); EXPECT_EQ(*value.value, 17); } TEST(RenderDomain, FinalOwnerMayBeReleasedOnAffinityThread) { auto domain = Render_Domain::acquire(0x7ffffff5U); std::weak_ptr weak = domain; std::promise released; auto finished = released.get_future(); EXPECT_EQ(domain->post([owned = domain, &released]() mutable { owned.reset(); released.set_value(); }), Render_Domain::Error::none); domain.reset(); EXPECT_EQ(finished.wait_for(std::chrono::seconds(1)), std::future_status::ready); EXPECT_TRUE(weak.expired()); } } }