--- a/src/protocols/core/Output.hpp +++ b/src/protocols/core/Output.hpp @@ -33,0 +34 @@ + friend class COutputTest; // Test fixture advances the real removal timer deterministically. --- a/tests/protocols/Output.cpp +++ b/tests/protocols/Output.cpp @@ -75 +75,2 @@ - void releaseOutput(); + void releaseOutput(bool expireGrace = true); + void advanceRemovalGrace(); @@ -134,0 +136 @@ + g_pEventLoopManager = makeUnique(m_display.get(), g_pCompositor->m_wlEventLoop); @@ -176,0 +179 @@ + g_pEventLoopManager.reset(); @@ -276 +279,12 @@ -void COutputTest::releaseOutput() { +void COutputTest::advanceRemovalGrace() { + auto protocols = PROTO::defunctOutputs; + for (const auto& [_, protocol] : PROTO::outputs) + protocols.emplace_back(protocol); + for (const auto& protocol : protocols) { + if (protocol->m_removeTimer) + protocol->m_removeTimer->updateTimeout(std::chrono::nanoseconds(0)); + } + g_pEventLoopManager->onTimerFire(); +} + +void COutputTest::releaseOutput(bool expireGrace) { @@ -284,0 +299,2 @@ + if (expireGrace) + advanceRemovalGrace(); @@ -290,0 +307 @@ + advanceRemovalGrace(); @@ -835,0 +853,24 @@ + +TEST_F(COutputTest, RemovalGraceRetainsUnboundOutputForLateBind) { + m_protocol->remove(); + ASSERT_TRUE(m_protocol->isDefunct()); + ASSERT_FALSE(m_protocol->hasBoundResources()); + EXPECT_TRUE(PROTO::outputs.contains(m_monitor->m_name)); + g_pEventLoopManager->onTimerFire(); + EXPECT_TRUE(PROTO::outputs.contains(m_monitor->m_name)); + ASSERT_NO_FATAL_FAILURE(bindOutput()); + ASSERT_NO_FATAL_FAILURE(releaseOutput(false)); + EXPECT_TRUE(PROTO::outputs.contains(m_monitor->m_name)); + advanceRemovalGrace(); + EXPECT_TRUE(PROTO::outputs.empty()); +} + +TEST_F(COutputTest, RemovalGraceExpiryKeepsBoundOutputUntilRelease) { + m_protocol->remove(); + ASSERT_NO_FATAL_FAILURE(bindOutput()); + advanceRemovalGrace(); + EXPECT_TRUE(PROTO::outputs.contains(m_monitor->m_name)); + EXPECT_TRUE(m_protocol->hasBoundResources()); + ASSERT_NO_FATAL_FAILURE(releaseOutput()); + EXPECT_TRUE(PROTO::outputs.empty()); +} --- /dev/null +++ b/tests/config/shared/MonitorRuleVRR.cpp @@ -0,0 +1,19 @@ +#include +#include + +TEST(MonitorRuleVRR, ChangingOnlyVRRRequestsSoftRefresh) { + Config::CMonitorRule active; + active.m_vrr = 0; + auto requested = active; + requested.m_vrr = 1; + EXPECT_EQ(active.compare(requested), Config::COMPARISON_SOFT_MISMATCH); + EXPECT_EQ(requested.compare(active), Config::COMPARISON_SOFT_MISMATCH); + EXPECT_EQ(active.compare(active), Config::COMPARISON_FULL_MATCH); +} + +TEST(MonitorRuleVRR, ExplicitVRRDiffersFromInheritedDefault) { + Config::CMonitorRule inherited; + auto requested = inherited; + requested.m_vrr = 0; + EXPECT_EQ(inherited.compare(requested), Config::COMPARISON_SOFT_MISMATCH); +} --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -32 +32 @@ - static const std::string ver = std::format("{}_aq_{}_hu_{}_hg_{}_hc_{}_hlg_{}", GIT_COMMIT_HASH, stripPatch(AQUAMARINE_VERSION), stripPatch(HYPRUTILS_VERSION), + static const std::string ver = std::format("{}_omadora_912521ee8a53_aq_{}_hu_{}_hg_{}_hc_{}_hlg_{}", GIT_COMMIT_HASH, stripPatch(AQUAMARINE_VERSION), stripPatch(HYPRUTILS_VERSION), --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -404 +404 @@ - static const std::string ver = std::format("{}_aq_{}_hu_{}_hg_{}_hc_{}_hlg_{}", GIT_COMMIT_HASH, stripPatch(AQUAMARINE_VERSION), stripPatch(HYPRUTILS_VERSION), + static const std::string ver = std::format("{}_omadora_912521ee8a53_aq_{}_hu_{}_hg_{}_hc_{}_hlg_{}", GIT_COMMIT_HASH, stripPatch(AQUAMARINE_VERSION), stripPatch(HYPRUTILS_VERSION), --- /dev/null +++ b/tests/plugins/OmadoraABI.cpp @@ -0,0 +1,8 @@ +#include +#include +#include + +TEST(OmadoraABI, CandidateClientAndServerHashesMatch) { + EXPECT_STREQ(__hyprland_api_get_hash(), __hyprland_api_get_client_hash()); + EXPECT_TRUE(std::string_view(__hyprland_api_get_hash()).contains("_omadora_912521ee8a53_")); +} --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -748,0 +749,13 @@ + +# Fedora packaging: exercise the shipped release library without enabling +# coverage instrumentation or installing the interactive hyprtester harness. +option(FEDORA_UNIT_TESTS "Build unit tests against the release library" OFF) +if(FEDORA_UNIT_TESTS) + find_package(GTest CONFIG REQUIRED) + file(GLOB_RECURSE FEDORA_TESTFILES "tests/*.cpp") + add_executable(hyprland_fedora_gtests ${FEDORA_TESTFILES}) + target_include_directories(hyprland_fedora_gtests + PUBLIC "./include" + PRIVATE "./src" "./src/include" "./protocols" "${CMAKE_BINARY_DIR}") + target_link_libraries(hyprland_fedora_gtests hyprland_lib GTest::gtest_main) +endif()