diff options
| author | Nikolai Nechaev <nikolay_nechaev@mail.ru> | 2026-04-30 02:32:06 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-04-29 18:32:06 +0100 |
| commit | 45ffaee09361110c018e962dbb3d93f7f1ee8e09 (patch) | |
| tree | 6dc9398eda8a147202b093a6b964e6c5a10195cd /hyprtester | |
| parent | 202cf48ecf627839c0a7433cbeb018c744214390 (diff) | |
tests: Fix more tests failing on CI (#14159)
* tests: Relax color management requirements in the colors test
This continues the work from d4dd299 (#14142):
- Fixes a missed check assuming a fixed value for `colorManagementPreset`
- Stricten checks to require that the expected keywords are present as json keys
* tests: Refactor `Tests::getAttribute` (was `Tests::getWindowAttribute`)
- Improve ergonomics by consistently handling attribute name;
- Remove 'window' from the function name, since it is compatible with
other responses too;
- Document the function.
* tests: Fix solitary test assuming it knows the complete set of blockers
The test was failing on the CI because new blockers appeared,
which were not expected by the text. Fix the test, so that it
just checks the set of expected blockers is a subset of actual
blockers
Diffstat (limited to 'hyprtester')
| -rw-r--r-- | hyprtester/src/tests/main/colors.cpp | 10 | ||||
| -rw-r--r-- | hyprtester/src/tests/main/dwindle.cpp | 2 | ||||
| -rw-r--r-- | hyprtester/src/tests/main/follow_mouse_shrink.cpp | 6 | ||||
| -rw-r--r-- | hyprtester/src/tests/main/solitary.cpp | 19 | ||||
| -rw-r--r-- | hyprtester/src/tests/main/window.cpp | 14 | ||||
| -rw-r--r-- | hyprtester/src/tests/shared.cpp | 11 | ||||
| -rw-r--r-- | hyprtester/src/tests/shared.hpp | 8 |
7 files changed, 45 insertions, 25 deletions
diff --git a/hyprtester/src/tests/main/colors.cpp b/hyprtester/src/tests/main/colors.cpp index 93dcbb65..e430145c 100644 --- a/hyprtester/src/tests/main/colors.cpp +++ b/hyprtester/src/tests/main/colors.cpp @@ -8,7 +8,7 @@ TEST_CASE(monitorsColorManagement) { std::string monitorsSpec = getFromSocket("j/monitors"); - ASSERT_CONTAINS(monitorsSpec, R"("colorManagementPreset")"); + ASSERT_CONTAINS(monitorsSpec, R"("colorManagementPreset": )"); ASSERT_CONTAINS(getFromSocket("/eval hl.monitor({ output = 'HEADLESS-2', bitdepth = 10, cm = 'wide' })"), "ok"); @@ -16,14 +16,14 @@ TEST_CASE(monitorsColorManagement) { std::this_thread::sleep_for(std::chrono::milliseconds(500)); monitorsSpec = getFromSocket("j/monitors"); - ASSERT_CONTAINS(monitorsSpec, R"("colorManagementPreset": "wide")"); + ASSERT_CONTAINS(monitorsSpec, R"("colorManagementPreset": )"); ASSERT_CONTAINS(getFromSocket("/eval hl.monitor({ output = 'HEADLESS-2', bitdepth = 10, cm = 'srgb', sdrbrightness = 1.2, sdrsaturation = 0.98 })"), "ok"); monitorsSpec = getFromSocket("j/monitors"); std::this_thread::sleep_for(std::chrono::milliseconds(500)); - ASSERT_CONTAINS(monitorsSpec, "colorManagementPreset"); - ASSERT_CONTAINS(monitorsSpec, "sdrBrightness"); - ASSERT_CONTAINS(monitorsSpec, "sdrSaturation"); + ASSERT_CONTAINS(monitorsSpec, R"("colorManagementPreset": )"); + ASSERT_CONTAINS(monitorsSpec, R"("sdrBrightness": )"); + ASSERT_CONTAINS(monitorsSpec, R"("sdrSaturation": )"); } diff --git a/hyprtester/src/tests/main/dwindle.cpp b/hyprtester/src/tests/main/dwindle.cpp index 5641f8ac..e962efd1 100644 --- a/hyprtester/src/tests/main/dwindle.cpp +++ b/hyprtester/src/tests/main/dwindle.cpp @@ -204,7 +204,7 @@ TEST_CASE(dwindleForceSplitOnMoveToWorkspace) { OK(getFromSocket("/dispatch hl.dsp.focus({ workspace = '1' })")); ASSERT(!!Tests::spawnKitty("kitty"), true); - std::string posBefore = Tests::getWindowAttribute(getFromSocket("/activewindow"), "at:"); + std::string posBefore = "at: " + Tests::getAttribute(getFromSocket("/activewindow"), "at"); OK(getFromSocket("/eval hl.config({ dwindle = { force_split = 2 } })")); OK(getFromSocket("/dispatch hl.dsp.cursor.move_to_corner({ corner = 3 })")); // top left diff --git a/hyprtester/src/tests/main/follow_mouse_shrink.cpp b/hyprtester/src/tests/main/follow_mouse_shrink.cpp index 0e12915b..600643c6 100644 --- a/hyprtester/src/tests/main/follow_mouse_shrink.cpp +++ b/hyprtester/src/tests/main/follow_mouse_shrink.cpp @@ -9,9 +9,9 @@ static bool isActiveWindow(const std::string& class_, char fullscreen = '0', bool log = true) { std::string activeWin = getFromSocket("/activewindow"); - auto winClass = Tests::getWindowAttribute(activeWin, "class:"); - auto winFullscreen = Tests::getWindowAttribute(activeWin, "fullscreen:").back(); - if (winClass.substr(strlen("class: ")) == class_ && winFullscreen == fullscreen) + auto winClass = Tests::getAttribute(activeWin, "class"); + auto winFullscreen = Tests::getAttribute(activeWin, "fullscreen").back(); + if (winClass == class_ && winFullscreen == fullscreen) return true; else { if (log) diff --git a/hyprtester/src/tests/main/solitary.cpp b/hyprtester/src/tests/main/solitary.cpp index 3e124a1e..522b7968 100644 --- a/hyprtester/src/tests/main/solitary.cpp +++ b/hyprtester/src/tests/main/solitary.cpp @@ -1,8 +1,11 @@ #include "tests.hpp" #include "../../shared.hpp" #include "../../hyprctlCompat.hpp" -#include <thread> +#include <algorithm> #include <chrono> +#include <ranges> +#include <set> +#include <thread> #include <hyprutils/os/Process.hpp> #include <hyprutils/memory/WeakPtr.hpp> #include "../shared.hpp" @@ -13,6 +16,13 @@ using namespace Hyprutils::Memory; #define UP CUniquePointer #define SP CSharedPointer +SUBTEST(expectBlockedByAll, const std::string& blockedByLine, const std::set<std::string>& expectedBlockedBy) { + const std::set<std::string> blockedBy = blockedByLine | std::ranges::views::split(',') | std::ranges::to<std::set<std::string>>(); + NLog::log("blockedBy = {}", blockedBy); + NLog::log("expectedBlockedBy = {}", expectedBlockedBy); + ASSERT(std::ranges::includes(blockedBy, expectedBlockedBy), true); +} + TEST_CASE(solitaryClients) { OK(getFromSocket("/eval hl.config({ general = { allow_tearing = false } })")); OK(getFromSocket("/eval hl.config({ render = { direct_scanout = 0 } })")); @@ -21,11 +31,12 @@ TEST_CASE(solitaryClients) { { auto str = getFromSocket("/monitors"); EXPECT_CONTAINS(str, "solitary: 0\n"); - EXPECT_CONTAINS(str, "solitaryBlockedBy: windowed mode,missing candidate"); + CALL_SUBTEST(expectBlockedByAll, Tests::getAttribute(str, "solitaryBlockedBy"), {"windowed mode", "missing candidate"}); EXPECT_CONTAINS(str, "activelyTearing: false"); - EXPECT_CONTAINS(str, "tearingBlockedBy: next frame is not torn,user settings,not supported by monitor,missing candidate"); + CALL_SUBTEST(expectBlockedByAll, Tests::getAttribute(str, "tearingBlockedBy"), + {"next frame is not torn", "user settings", "not supported by monitor", "missing candidate"}); EXPECT_CONTAINS(str, "directScanoutTo: 0\n"); - EXPECT_CONTAINS(str, "directScanoutBlockedBy: user settings,software renders/cursors,missing candidate"); + CALL_SUBTEST(expectBlockedByAll, Tests::getAttribute(str, "directScanoutBlockedBy"), {"user settings", "software renders/cursors", "missing candidate"}); } // FIXME: need a reliable client with solitary opaque surface in fullscreen. kitty doesn't work all the time diff --git a/hyprtester/src/tests/main/window.cpp b/hyprtester/src/tests/main/window.cpp index 7f36cf7b..4a4da0cc 100644 --- a/hyprtester/src/tests/main/window.cpp +++ b/hyprtester/src/tests/main/window.cpp @@ -75,7 +75,7 @@ TEST_CASE(swapWindow) { // Test swapwindow by direction { getFromSocket("/dispatch hl.dsp.focus({ window = 'class:kitty_A' })"); - auto pos = Tests::getWindowAttribute(getFromSocket("/activewindow"), "at:"); + auto pos = "at: " + Tests::getAttribute(getFromSocket("/activewindow"), "at"); NLog::log("{}Testing kitty_A {}, swapwindow with direction 'r'", Colors::YELLOW, pos); OK(getFromSocket("/dispatch hl.dsp.window.swap({ direction = 'right' })")); @@ -87,7 +87,7 @@ TEST_CASE(swapWindow) { // Test swapwindow by class { getFromSocket("/dispatch hl.dsp.focus({ window = 'class:kitty_A' })"); - auto pos = Tests::getWindowAttribute(getFromSocket("/activewindow"), "at:"); + auto pos = "at: " + Tests::getAttribute(getFromSocket("/activewindow"), "at"); NLog::log("{}Testing kitty_A {}, swapwindow with class:kitty_B", Colors::YELLOW, pos); OK(getFromSocket("/dispatch hl.dsp.window.swap({ target = 'class:kitty_B' })")); @@ -101,7 +101,7 @@ TEST_CASE(swapWindow) { getFromSocket("/dispatch hl.dsp.focus({ window = 'class:kitty_B' })"); auto addr = getWindowAddress(getFromSocket("/activewindow")); getFromSocket("/dispatch hl.dsp.focus({ window = 'class:kitty_A' })"); - auto pos = Tests::getWindowAttribute(getFromSocket("/activewindow"), "at:"); + auto pos = "at: " + Tests::getAttribute(getFromSocket("/activewindow"), "at"); NLog::log("{}Testing kitty_A {}, swapwindow with address:0x{}(kitty_B)", Colors::YELLOW, pos, addr); OK(getFromSocket(std::format("/dispatch hl.dsp.window.swap({{ target = 'address:0x{}' }})", addr))); @@ -124,7 +124,7 @@ TEST_CASE(swapWindow) { { getFromSocket("/dispatch hl.dsp.focus({ window = 'class:kitty_B' })"); auto addr = getWindowAddress(getFromSocket("/activewindow")); - auto ws = Tests::getWindowAttribute(getFromSocket("/activewindow"), "workspace:"); + auto ws = "workspace: " + Tests::getAttribute(getFromSocket("/activewindow"), "workspace"); NLog::log("{}Sending address:0x{}(kitty_B) to workspace \"swapwindow2\"", Colors::YELLOW, addr); OK(getFromSocket("/dispatch hl.dsp.window.move({ workspace = 'name:swapwindow2', follow = false })")); @@ -190,9 +190,9 @@ TEST_CASE(windowGroupRules) { static bool isActiveWindow(const std::string& class_, char fullscreen = '0', bool log = true) { std::string activeWin = getFromSocket("/activewindow"); - auto winClass = Tests::getWindowAttribute(activeWin, "class:"); - auto winFullscreen = Tests::getWindowAttribute(activeWin, "fullscreen:").back(); - if (winClass.substr(strlen("class: ")) == class_ && winFullscreen == fullscreen) + auto winClass = Tests::getAttribute(activeWin, "class"); + auto winFullscreen = Tests::getAttribute(activeWin, "fullscreen").back(); + if (winClass == class_ && winFullscreen == fullscreen) return true; else { if (log) diff --git a/hyprtester/src/tests/shared.cpp b/hyprtester/src/tests/shared.cpp index 03a64751..d08f4ea2 100644 --- a/hyprtester/src/tests/shared.cpp +++ b/hyprtester/src/tests/shared.cpp @@ -1,4 +1,5 @@ #include "shared.hpp" +#include <cassert> #include <csignal> #include <cerrno> #include <thread> @@ -186,12 +187,14 @@ bool Tests::writeFile(const std::string& name, const std::string& contents) { return true; } -std::string Tests::getWindowAttribute(const std::string& winInfo, const std::string& attr) { - auto pos = winInfo.find(attr); +std::string Tests::getAttribute(const std::string& hyprlandResponse, std::string attr) { + attr += ": "; + auto pos = hyprlandResponse.find(attr); if (pos == std::string::npos) { NLog::log("{}Window attribute not found: '{}'", Colors::RED, attr); return "Wrong window attribute"; } - auto pos2 = winInfo.find('\n', pos); - return winInfo.substr(pos, pos2 - pos); + pos += attr.size(); + auto pos2 = hyprlandResponse.find('\n', pos); + return hyprlandResponse.substr(pos, pos2 - pos); } diff --git a/hyprtester/src/tests/shared.hpp b/hyprtester/src/tests/shared.hpp index 95058e04..fbef8a0e 100644 --- a/hyprtester/src/tests/shared.hpp +++ b/hyprtester/src/tests/shared.hpp @@ -19,5 +19,11 @@ namespace Tests { bool killAllLayers(); std::string execAndGet(const std::string& cmd); bool writeFile(const std::string& name, const std::string& contents); - std::string getWindowAttribute(const std::string& winInfo, const std::string& attr); + /** + * Extracts the given attribute from Hyprland's response to requests such as `/clients`, `/workspaces`, etc. + * Automatically appends `: ` to `attr`. + * + * For example, `Tests::getAttribute(getFromSocket("/activewindow"), "at")` returns the active window's coordinates, e.g., `"2,32"` + */ + std::string getAttribute(const std::string& hyprlandResponse, std::string attr); }; |
