diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2025-12-05 14:16:22 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-05 14:16:22 +0000 |
| commit | 9264436f35e2c4e94adfdf2a8ea23a346ace3a65 (patch) | |
| tree | 9fe48ff4728060445e655d8a3b528999fd124ff8 /hyprtester | |
| parent | d5c52ef58e57b371a9df8fd4404c5d55a1b26f34 (diff) | |
desktop: rewrite reserved area handling + improve tests (#12383)
Diffstat (limited to 'hyprtester')
| -rw-r--r-- | hyprtester/plugin/src/main.cpp | 8 | ||||
| -rw-r--r-- | hyprtester/src/shared.hpp | 11 | ||||
| -rw-r--r-- | hyprtester/src/tests/main/keybinds.cpp | 46 | ||||
| -rw-r--r-- | hyprtester/src/tests/main/window.cpp | 75 | ||||
| -rw-r--r-- | hyprtester/src/tests/main/workspaces.cpp | 92 |
5 files changed, 192 insertions, 40 deletions
diff --git a/hyprtester/plugin/src/main.cpp b/hyprtester/plugin/src/main.cpp index cbc06723..b8706f52 100644 --- a/hyprtester/plugin/src/main.cpp +++ b/hyprtester/plugin/src/main.cpp @@ -225,7 +225,7 @@ static SDispatchResult scroll(std::string in) { } static SDispatchResult keybind(std::string in) { - CVarList data(in); + CVarList2 data(std::move(in)); // 0 = release, 1 = press bool press; // See src/devices/IKeyboard.hpp : eKeyboardModifiers for modifier bitmasks @@ -234,9 +234,9 @@ static SDispatchResult keybind(std::string in) { // keycode uint32_t key; try { - press = std::stoul(data[0]) == 1; - modifier = std::stoul(data[1]); - key = std::stoul(data[2]) - 8; // xkb offset + press = std::stoul(std::string{data[0]}) == 1; + modifier = std::stoul(std::string{data[1]}); + key = std::stoul(std::string{data[2]}) - 8; // xkb offset } catch (...) { return {.success = false, .error = "invalid input"}; } uint32_t modifierMask = 0; diff --git a/hyprtester/src/shared.hpp b/hyprtester/src/shared.hpp index 43944c3c..1090aa9a 100644 --- a/hyprtester/src/shared.hpp +++ b/hyprtester/src/shared.hpp @@ -18,6 +18,17 @@ namespace Colors { constexpr const char* RESET = "\x1b[0m"; }; +#define EXPECT_MAX_DELTA(expr, desired, delta) \ + if (const auto RESULT = expr; std::abs(RESULT - (desired)) > delta) { \ + NLog::log("{}Failed: {}{}, expected max delta of {}, got delta {} ({} - {}). Source: {}@{}.", Colors::RED, Colors::RESET, #expr, delta, (RESULT - (desired)), RESULT, \ + desired, __FILE__, __LINE__); \ + ret = 1; \ + TESTS_FAILED++; \ + } else { \ + NLog::log("{}Passed: {}{}. Got {}", Colors::GREEN, Colors::RESET, #expr, (RESULT - (desired))); \ + TESTS_PASSED++; \ + } + #define EXPECT(expr, val) \ if (const auto RESULT = expr; RESULT != (val)) { \ NLog::log("{}Failed: {}{}, expected {}, got {}. Source: {}@{}.", Colors::RED, Colors::RESET, #expr, val, RESULT, __FILE__, __LINE__); \ diff --git a/hyprtester/src/tests/main/keybinds.cpp b/hyprtester/src/tests/main/keybinds.cpp index a2fe2f37..23f17abf 100644 --- a/hyprtester/src/tests/main/keybinds.cpp +++ b/hyprtester/src/tests/main/keybinds.cpp @@ -86,8 +86,7 @@ static void testBind() { // press keybind OK(getFromSocket("/dispatch plugin:test:keybind 1,7,29")); // await flag - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - EXPECT(checkFlag(), true); + EXPECT(attemptCheckFlag(20, 50), true); // release keybind OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); EXPECT(getFromSocket("/keyword unbind SUPER,Y"), "ok"); @@ -99,8 +98,7 @@ static void testBindKey() { // press keybind OK(getFromSocket("/dispatch plugin:test:keybind 1,0,29")); // await flag - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - EXPECT(checkFlag(), true); + EXPECT(attemptCheckFlag(20, 50), true); // release keybind OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); EXPECT(getFromSocket("/keyword unbind ,Y"), "ok"); @@ -116,7 +114,7 @@ static void testLongPress() { std::this_thread::sleep_for(std::chrono::milliseconds(50)); EXPECT(checkFlag(), false); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), true); // release keybind OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); @@ -133,7 +131,7 @@ static void testKeyLongPress() { std::this_thread::sleep_for(std::chrono::milliseconds(50)); EXPECT(checkFlag(), false); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), true); // release keybind OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); @@ -152,7 +150,7 @@ static void testLongPressRelease() { // release keybind OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), false); EXPECT(getFromSocket("/keyword unbind SUPER,Y"), "ok"); } @@ -169,7 +167,7 @@ static void testLongPressOnlyKeyRelease() { // release key, keep modifier OK(getFromSocket("/dispatch plugin:test:keybind 0,7,29")); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), false); OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); EXPECT(getFromSocket("/keyword unbind SUPER,Y"), "ok"); @@ -182,13 +180,13 @@ static void testRepeat() { // press keybind OK(getFromSocket("/dispatch plugin:test:keybind 1,7,29")); // await flag - std::this_thread::sleep_for(std::chrono::milliseconds(50)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), true); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), true); // check that it continues repeating - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), true); // release keybind OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); @@ -205,10 +203,10 @@ static void testKeyRepeat() { std::this_thread::sleep_for(std::chrono::milliseconds(50)); EXPECT(checkFlag(), true); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), true); // check that it continues repeating - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), true); // release keybind OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); @@ -227,10 +225,12 @@ static void testRepeatRelease() { // release keybind OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + clearFlag(); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), false); // check that it is not repeating - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), false); EXPECT(getFromSocket("/keyword unbind SUPER,Y"), "ok"); } @@ -242,15 +242,17 @@ static void testRepeatOnlyKeyRelease() { // press keybind OK(getFromSocket("/dispatch plugin:test:keybind 1,7,29")); // await flag - std::this_thread::sleep_for(std::chrono::milliseconds(50)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), true); // release key, keep modifier OK(getFromSocket("/dispatch plugin:test:keybind 0,7,29")); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + clearFlag(); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), false); // check that it is not repeating - std::this_thread::sleep_for(std::chrono::milliseconds(100)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); EXPECT(checkFlag(), false); OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); EXPECT(getFromSocket("/keyword unbind SUPER,Y"), "ok"); @@ -315,9 +317,9 @@ static void testShortcutLongPress() { // press keybind OK(getFromSocket("/dispatch plugin:test:keybind 1,7,29")); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); OK(getFromSocket("/dispatch plugin:test:keybind 0,0,29")); - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); const std::string output = readKittyOutput(); int yCount = Tests::countOccurrences(output, "y"); // sometimes 1, sometimes 2, not sure why @@ -347,7 +349,7 @@ static void testShortcutLongPressKeyRelease() { // release key, keep modifier OK(getFromSocket("/dispatch plugin:test:keybind 0,7,29")); // await repeat delay - std::this_thread::sleep_for(std::chrono::milliseconds(150)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); const std::string output = readKittyOutput(); // disabled: doesn't work on CI // EXPECT_COUNT_STRING(output, "y", 1); @@ -485,6 +487,8 @@ static void testSubmapUniversal() { static bool test() { NLog::log("{}Testing keybinds", Colors::GREEN); + clearFlag(); + testBind(); testBindKey(); testLongPress(); diff --git a/hyprtester/src/tests/main/window.cpp b/hyprtester/src/tests/main/window.cpp index 3265bf72..5fa8b58f 100644 --- a/hyprtester/src/tests/main/window.cpp +++ b/hyprtester/src/tests/main/window.cpp @@ -6,6 +6,7 @@ #include <thread> #include <hyprutils/os/Process.hpp> #include <hyprutils/memory/WeakPtr.hpp> +#include <hyprutils/string/VarList2.hpp> #include "../../shared.hpp" #include "../../hyprctlCompat.hpp" @@ -364,22 +365,40 @@ static bool test() { NLog::log("{}Testing window split ratios", Colors::YELLOW); { - const double RATIO = 1.25; - const double PERCENT = RATIO / 2.0 * 100.0; - const int GAPSIN = 5; - const int GAPSOUT = 20; - const int BORDERS = 2 * 2; - const int WTRIM = BORDERS + GAPSIN + GAPSOUT; - const int HEIGHT = 1080 - (BORDERS + (GAPSOUT * 2)); - const int WIDTH1 = std::round(1920.0 / 2.0 * (2 - RATIO)) - WTRIM; - const int WIDTH2 = std::round(1920.0 / 2.0 * RATIO) - WTRIM; + const double INITIAL_RATIO = 1.25; + const int GAPSIN = 5; + const int GAPSOUT = 20; + const int BORDERSIZE = 2; + const int BORDERS = BORDERSIZE * 2; + const int MONITOR_W = 1920; + const int MONITOR_H = 1080; + + const float totalAvailableHeight = MONITOR_H - (GAPSOUT * 2); + const int HEIGHT = std::floor(totalAvailableHeight) - BORDERS; + const float availableWidthForSplit = MONITOR_W - (GAPSOUT * 2) - GAPSIN; + + auto calculateFinalWidth = [&](double boxWidth, bool isLeftWindow) { + double gapLeft = isLeftWindow ? GAPSOUT : GAPSIN; + double gapRight = isLeftWindow ? GAPSIN : GAPSOUT; + return std::floor(boxWidth - gapLeft - gapRight - BORDERS); + }; + + double geomBoxWidthA_R1 = (availableWidthForSplit * INITIAL_RATIO / 2.0) + GAPSOUT + (GAPSIN / 2.0); + double geomBoxWidthB_R1 = MONITOR_W - geomBoxWidthA_R1; + const int WIDTH1 = calculateFinalWidth(geomBoxWidthB_R1, false); + + const double INVERTED_RATIO = 0.75; + double geomBoxWidthA_R2 = (availableWidthForSplit * INVERTED_RATIO / 2.0) + GAPSOUT + (GAPSIN / 2.0); + double geomBoxWidthB_R2 = MONITOR_W - geomBoxWidthA_R2; + const int WIDTH2 = calculateFinalWidth(geomBoxWidthB_R2, false); + const int WIDTH_A_FINAL = calculateFinalWidth(geomBoxWidthA_R2, true); OK(getFromSocket("/keyword dwindle:default_split_ratio 1.25")); if (!spawnKitty("kitty_B")) return false; - NLog::log("{}Expecting kitty_B to take up roughly {}% of screen width", Colors::YELLOW, 100 - PERCENT); + NLog::log("{}Expecting kitty_B size: {},{}", Colors::YELLOW, WIDTH1, HEIGHT); EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH1, HEIGHT)); OK(getFromSocket("/dispatch killwindow activewindow")); @@ -391,12 +410,38 @@ static bool test() { if (!spawnKitty("kitty_B")) return false; - NLog::log("{}Expecting kitty_B to take up roughly {}% of screen width", Colors::YELLOW, PERCENT); - EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH2, HEIGHT)); + try { + NLog::log("{}Expecting kitty_B size: {},{}", Colors::YELLOW, WIDTH2, HEIGHT); - OK(getFromSocket("/dispatch focuswindow class:kitty_A")); - NLog::log("{}Expecting kitty_A to have the same width as the previous kitty_B", Colors::YELLOW); - EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH1, HEIGHT)); + { + auto data = getFromSocket("/activewindow"); + data = data.substr(data.find("size:") + 5); + data = data.substr(0, data.find('\n')); + + Hyprutils::String::CVarList2 sizes(std::move(data), 0, ','); + + EXPECT_MAX_DELTA(std::stoi(std::string{sizes[0]}), WIDTH2, 2); + EXPECT_MAX_DELTA(std::stoi(std::string{sizes[1]}), HEIGHT, 2); + } + + OK(getFromSocket("/dispatch focuswindow class:kitty_A")); + NLog::log("{}Expecting kitty_A size: {},{}", Colors::YELLOW, WIDTH_A_FINAL, HEIGHT); + + { + auto data = getFromSocket("/activewindow"); + data = data.substr(data.find("size:") + 5); + data = data.substr(0, data.find('\n')); + + Hyprutils::String::CVarList2 sizes(std::move(data), 0, ','); + + EXPECT_MAX_DELTA(std::stoi(std::string{sizes[0]}), WIDTH_A_FINAL, 2); + EXPECT_MAX_DELTA(std::stoi(std::string{sizes[1]}), HEIGHT, 2); + } + + } catch (...) { + NLog::log("{}Exception thrown", Colors::RED); + EXPECT(false, true); + } OK(getFromSocket("/keyword dwindle:default_split_ratio 1")); } diff --git a/hyprtester/src/tests/main/workspaces.cpp b/hyprtester/src/tests/main/workspaces.cpp index 622236dc..c1b9690a 100644 --- a/hyprtester/src/tests/main/workspaces.cpp +++ b/hyprtester/src/tests/main/workspaces.cpp @@ -6,6 +6,7 @@ #include <chrono> #include <hyprutils/os/Process.hpp> #include <hyprutils/memory/WeakPtr.hpp> +#include <hyprutils/utils/ScopeGuard.hpp> #include <csignal> #include <cerrno> #include "../shared.hpp" @@ -14,10 +15,99 @@ static int ret = 0; using namespace Hyprutils::OS; using namespace Hyprutils::Memory; +using namespace Hyprutils::Utils; #define UP CUniquePointer #define SP CSharedPointer +static bool testAsymmetricGaps() { + NLog::log("{}Testing asymmetric gap splits", Colors::YELLOW); + { + + CScopeGuard guard = {[&]() { + NLog::log("{}Cleaning up asymmetric gap test", Colors::YELLOW); + Tests::killAllWindows(); + OK(getFromSocket("/reload")); + }}; + + OK(getFromSocket("/dispatch workspace name:gap_split_test")); + OK(getFromSocket("r/keyword general:gaps_in 0")); + OK(getFromSocket("r/keyword general:border_size 0")); + OK(getFromSocket("r/keyword dwindle:split_width_multiplier 1.0")); + OK(getFromSocket("r/keyword workspace name:gap_split_test,gapsout:0 1000 0 0")); + + NLog::log("{}Testing default split (force_split = 0)", Colors::YELLOW); + OK(getFromSocket("r/keyword dwindle:force_split 0")); + + if (!Tests::spawnKitty("gaps_kitty_A") || !Tests::spawnKitty("gaps_kitty_B")) + return false; + + NLog::log("{}Expecting vertical split (B below A)", Colors::YELLOW); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0"); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,540"); + + Tests::killAllWindows(); + EXPECT(Tests::windowCount(), 0); + + NLog::log("{}Testing force_split = 1", Colors::YELLOW); + OK(getFromSocket("r/keyword dwindle:force_split 1")); + + if (!Tests::spawnKitty("gaps_kitty_A") || !Tests::spawnKitty("gaps_kitty_B")) + return false; + + NLog::log("{}Expecting vertical split (B above A)", Colors::YELLOW); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0"); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,540"); + + NLog::log("{}Expecting horizontal split (C left of B)", Colors::YELLOW); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B")); + + if (!Tests::spawnKitty("gaps_kitty_C")) + return false; + + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_C")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0"); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 460,0"); + + Tests::killAllWindows(); + EXPECT(Tests::windowCount(), 0); + + NLog::log("{}Testing force_split = 2", Colors::YELLOW); + OK(getFromSocket("r/keyword dwindle:force_split 2")); + + if (!Tests::spawnKitty("gaps_kitty_A") || !Tests::spawnKitty("gaps_kitty_B")) + return false; + + NLog::log("{}Expecting vertical split (B below A)", Colors::YELLOW); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0"); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,540"); + + NLog::log("{}Expecting horizontal split (C right of A)", Colors::YELLOW); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A")); + + if (!Tests::spawnKitty("gaps_kitty_C")) + return false; + + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0"); + OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_C")); + EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 460,0"); + } + + // kill all + NLog::log("{}Killing all windows", Colors::YELLOW); + Tests::killAllWindows(); + + return true; +} + static bool test() { NLog::log("{}Testing workspaces", Colors::GREEN); @@ -359,6 +449,8 @@ static bool test() { NLog::log("{}Killing all windows", Colors::YELLOW); Tests::killAllWindows(); + testAsymmetricGaps(); + NLog::log("{}Expecting 0 windows", Colors::YELLOW); EXPECT(Tests::windowCount(), 0); |
