Core: Add a test suite (#9297)
Adds a test suite for testing hyprland's features with a runtime tester --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
parent
9a67e0421b
commit
3d6476c902
29 changed files with 2096 additions and 15 deletions
177
hyprtester/src/tests/main/groups.cpp
Normal file
177
hyprtester/src/tests/main/groups.cpp
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#include "tests.hpp"
|
||||
#include "../../shared.hpp"
|
||||
#include "../../hyprctlCompat.hpp"
|
||||
#include <print>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
#include <csignal>
|
||||
#include <cerrno>
|
||||
#include "../shared.hpp"
|
||||
|
||||
static int ret = 0;
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
using namespace Hyprutils::Memory;
|
||||
|
||||
#define UP CUniquePointer
|
||||
#define SP CSharedPointer
|
||||
|
||||
bool testGroups() {
|
||||
NLog::log("{}Testing groups", Colors::GREEN);
|
||||
|
||||
// test on workspace "window"
|
||||
NLog::log("{}Dispatching workspace `groups`", Colors::YELLOW);
|
||||
getFromSocket("/dispatch workspace name:groups");
|
||||
|
||||
NLog::log("{}Spawning kittyProcA", Colors::YELLOW);
|
||||
auto kittyProcA = Tests::spawnKitty();
|
||||
if (!kittyProcA) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Expecting 1 window", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 1);
|
||||
|
||||
// check kitty properties. One kitty should take the entire screen, minus the gaps.
|
||||
NLog::log("{}Check kitty dimensions", Colors::YELLOW);
|
||||
{
|
||||
auto str = getFromSocket("/clients");
|
||||
EXPECT_COUNT_STRING(str, "at: 22,22", 1);
|
||||
EXPECT_COUNT_STRING(str, "size: 1876,1036", 1);
|
||||
EXPECT_COUNT_STRING(str, "fullscreen: 0", 1);
|
||||
}
|
||||
|
||||
// group the kitty
|
||||
NLog::log("{}Enable group and groupbar", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch togglegroup"));
|
||||
OK(getFromSocket("/keyword group:groupbar:enabled 1"));
|
||||
|
||||
// check the height of the window now
|
||||
NLog::log("{}Recheck kitty dimensions", Colors::YELLOW);
|
||||
{
|
||||
auto str = getFromSocket("/clients");
|
||||
EXPECT_CONTAINS(str, "at: 22,43");
|
||||
EXPECT_CONTAINS(str, "size: 1876,1015");
|
||||
}
|
||||
|
||||
// disable the groupbar for ease of testing for now
|
||||
NLog::log("{}Disable groupbar", Colors::YELLOW);
|
||||
OK(getFromSocket("r/keyword group:groupbar:enabled 0"));
|
||||
|
||||
// kill all
|
||||
NLog::log("{}Kill windows", Colors::YELLOW);
|
||||
Tests::killAllWindows();
|
||||
|
||||
NLog::log("{}Spawn kitty again", Colors::YELLOW);
|
||||
kittyProcA = Tests::spawnKitty();
|
||||
if (!kittyProcA) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Group kitty", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch togglegroup"));
|
||||
|
||||
// check the height of the window now
|
||||
NLog::log("{}Check kitty dimensions 2", Colors::YELLOW);
|
||||
{
|
||||
auto str = getFromSocket("/clients");
|
||||
EXPECT_CONTAINS(str, "at: 22,22");
|
||||
EXPECT_CONTAINS(str, "size: 1876,1036");
|
||||
}
|
||||
|
||||
NLog::log("{}Spawn kittyProcB", Colors::YELLOW);
|
||||
auto kittyProcB = Tests::spawnKitty();
|
||||
if (!kittyProcB) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Expecting 2 windows", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 2);
|
||||
|
||||
size_t lastActiveKittyIdx = 0;
|
||||
|
||||
NLog::log("{}Get last active kitty id", Colors::YELLOW);
|
||||
try {
|
||||
auto str = getFromSocket("/activewindow");
|
||||
lastActiveKittyIdx = std::stoull(str.substr(7, str.find(" -> ") - 7), nullptr, 16);
|
||||
} catch (...) {
|
||||
NLog::log("{}Fail at getting prop", Colors::RED);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
// test cycling through
|
||||
|
||||
NLog::log("{}Test cycling through grouped windows", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch changegroupactive f"));
|
||||
|
||||
try {
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT(lastActiveKittyIdx != std::stoull(str.substr(7, str.find(" -> ") - 7), nullptr, 16), true);
|
||||
} catch (...) {
|
||||
NLog::log("{}Fail at getting prop", Colors::RED);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
getFromSocket("/dispatch changegroupactive f");
|
||||
|
||||
try {
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT(lastActiveKittyIdx, std::stoull(str.substr(7, str.find(" -> ") - 7), nullptr, 16));
|
||||
} catch (...) {
|
||||
NLog::log("{}Fail at getting prop", Colors::RED);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
NLog::log("{}Disable autogrouping", Colors::YELLOW);
|
||||
OK(getFromSocket("/keyword group:auto_group false"));
|
||||
|
||||
NLog::log("{}Spawn kittyProcC", Colors::YELLOW);
|
||||
auto kittyProcC = Tests::spawnKitty();
|
||||
if (!kittyProcC) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Expecting 3 windows 2", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 3);
|
||||
{
|
||||
auto str = getFromSocket("/clients");
|
||||
EXPECT_COUNT_STRING(str, "at: 22,22", 2);
|
||||
}
|
||||
|
||||
OK(getFromSocket("/dispatch movefocus l"));
|
||||
OK(getFromSocket("/dispatch changegroupactive 1"));
|
||||
OK(getFromSocket("/keyword group:auto_group true"));
|
||||
OK(getFromSocket("/keyword group:insert_after_current false"));
|
||||
|
||||
NLog::log("{}Spawn kittyProcD", Colors::YELLOW);
|
||||
auto kittyProcD = Tests::spawnKitty();
|
||||
if (!kittyProcD) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Expecting 4 windows", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 4);
|
||||
|
||||
OK(getFromSocket("/dispatch changegroupactive 3"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, std::format("pid: {}", kittyProcD->pid()));
|
||||
}
|
||||
|
||||
// kill all
|
||||
NLog::log("{}Kill windows", Colors::YELLOW);
|
||||
Tests::killAllWindows();
|
||||
|
||||
NLog::log("{}Expecting 0 windows", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 0);
|
||||
|
||||
return !ret;
|
||||
}
|
||||
142
hyprtester/src/tests/main/misc.cpp
Normal file
142
hyprtester/src/tests/main/misc.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#include "tests.hpp"
|
||||
#include "../../shared.hpp"
|
||||
#include "../../hyprctlCompat.hpp"
|
||||
#include <print>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
#include <csignal>
|
||||
#include <cerrno>
|
||||
#include "../shared.hpp"
|
||||
|
||||
static int ret = 0;
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
using namespace Hyprutils::Memory;
|
||||
|
||||
#define UP CUniquePointer
|
||||
#define SP CSharedPointer
|
||||
|
||||
bool testMisc() {
|
||||
NLog::log("{}Testing config: misc:", Colors::GREEN);
|
||||
|
||||
NLog::log("{}Testing close_special_on_empty", Colors::YELLOW);
|
||||
|
||||
OK(getFromSocket("/keyword misc:close_special_on_empty false"));
|
||||
OK(getFromSocket("/dispatch workspace special:test"));
|
||||
|
||||
Tests::spawnKitty();
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/monitors");
|
||||
EXPECT_CONTAINS(str, "special workspace: -");
|
||||
}
|
||||
|
||||
Tests::killAllWindows();
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/monitors");
|
||||
EXPECT_CONTAINS(str, "special workspace: -");
|
||||
}
|
||||
|
||||
Tests::spawnKitty();
|
||||
|
||||
OK(getFromSocket("/keyword misc:close_special_on_empty true"));
|
||||
|
||||
Tests::killAllWindows();
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/monitors");
|
||||
EXPECT_NOT_CONTAINS(str, "special workspace: -");
|
||||
}
|
||||
|
||||
NLog::log("{}Testing new_window_takes_over_fullscreen", Colors::YELLOW);
|
||||
|
||||
OK(getFromSocket("/keyword misc:new_window_takes_over_fullscreen 0"));
|
||||
|
||||
Tests::spawnKitty("kitty_A");
|
||||
|
||||
OK(getFromSocket("/dispatch fullscreen 0"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 2");
|
||||
EXPECT_CONTAINS(str, "kitty_A");
|
||||
}
|
||||
|
||||
Tests::spawnKitty("kitty_B");
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 2");
|
||||
EXPECT_CONTAINS(str, "kitty_A");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/keyword misc:new_window_takes_over_fullscreen 1"));
|
||||
|
||||
Tests::spawnKitty("kitty_C");
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 2");
|
||||
EXPECT_CONTAINS(str, "kitty_C");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/keyword misc:new_window_takes_over_fullscreen 2"));
|
||||
|
||||
Tests::spawnKitty("kitty_D");
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 0");
|
||||
EXPECT_CONTAINS(str, "kitty_D");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/keyword misc:new_window_takes_over_fullscreen 0"));
|
||||
|
||||
Tests::killAllWindows();
|
||||
|
||||
NLog::log("{}Testing exit_window_retains_fullscreen", Colors::YELLOW);
|
||||
|
||||
OK(getFromSocket("/keyword misc:exit_window_retains_fullscreen false"));
|
||||
|
||||
Tests::spawnKitty("kitty_A");
|
||||
Tests::spawnKitty("kitty_B");
|
||||
|
||||
OK(getFromSocket("/dispatch fullscreen 0"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 2");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/dispatch killwindow activewindow"));
|
||||
Tests::waitUntilWindowsN(1);
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 0");
|
||||
}
|
||||
|
||||
Tests::spawnKitty("kitty_B");
|
||||
OK(getFromSocket("/dispatch fullscreen 0"));
|
||||
OK(getFromSocket("/keyword misc:exit_window_retains_fullscreen true"));
|
||||
|
||||
OK(getFromSocket("/dispatch killwindow activewindow"));
|
||||
Tests::waitUntilWindowsN(1);
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "fullscreen: 2");
|
||||
}
|
||||
|
||||
// kill all
|
||||
NLog::log("{}Killing all windows", Colors::YELLOW);
|
||||
Tests::killAllWindows();
|
||||
|
||||
NLog::log("{}Expecting 0 windows", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 0);
|
||||
|
||||
return !ret;
|
||||
}
|
||||
6
hyprtester/src/tests/main/tests.hpp
Normal file
6
hyprtester/src/tests/main/tests.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
bool testGroups();
|
||||
bool testWindows();
|
||||
bool testWorkspaces();
|
||||
bool testMisc();
|
||||
96
hyprtester/src/tests/main/window.cpp
Normal file
96
hyprtester/src/tests/main/window.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#include "tests.hpp"
|
||||
#include "../../shared.hpp"
|
||||
#include "../../hyprctlCompat.hpp"
|
||||
#include <print>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
#include <csignal>
|
||||
#include <cerrno>
|
||||
#include "../shared.hpp"
|
||||
|
||||
static int ret = 0;
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
using namespace Hyprutils::Memory;
|
||||
|
||||
#define UP CUniquePointer
|
||||
#define SP CSharedPointer
|
||||
|
||||
bool testWindows() {
|
||||
NLog::log("{}Testing windows", Colors::GREEN);
|
||||
|
||||
// test on workspace "window"
|
||||
NLog::log("{}Switching to workspace `window`", Colors::YELLOW);
|
||||
getFromSocket("/dispatch workspace name:window");
|
||||
|
||||
NLog::log("{}Spawning kittyProcA", Colors::YELLOW);
|
||||
auto kittyProcA = Tests::spawnKitty();
|
||||
|
||||
if (!kittyProcA) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Expecting 1 window", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 1);
|
||||
|
||||
// check kitty properties. One kitty should take the entire screen, as this is smart gaps
|
||||
NLog::log("{}Expecting kitty to take up the whole screen", Colors::YELLOW);
|
||||
{
|
||||
auto str = getFromSocket("/clients");
|
||||
EXPECT(str.contains("at: 0,0"), true);
|
||||
EXPECT(str.contains("size: 1920,1080"), true);
|
||||
EXPECT(str.contains("fullscreen: 0"), true);
|
||||
}
|
||||
|
||||
NLog::log("{}Spawning kittyProcB", Colors::YELLOW);
|
||||
auto kittyProcB = Tests::spawnKitty();
|
||||
if (!kittyProcB) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Expecting 2 windows", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 2);
|
||||
|
||||
// open xeyes
|
||||
NLog::log("{}Spawning xeyes", Colors::YELLOW);
|
||||
getFromSocket("/dispatch exec xeyes");
|
||||
|
||||
NLog::log("{}Keep checking if xeyes spawned", Colors::YELLOW);
|
||||
int counter = 0;
|
||||
while (Tests::windowCount() != 3) {
|
||||
counter++;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
if (counter > 50) {
|
||||
EXPECT(Tests::windowCount(), 3);
|
||||
return !ret;
|
||||
}
|
||||
}
|
||||
|
||||
NLog::log("{}Expecting 3 windows", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 3);
|
||||
|
||||
NLog::log("{}Checking props of xeyes", Colors::YELLOW);
|
||||
// check some window props of xeyes, try to tile them
|
||||
{
|
||||
auto str = getFromSocket("/clients");
|
||||
EXPECT_CONTAINS(str, "floating: 1");
|
||||
getFromSocket("/dispatch settiled class:XEyes");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
str = getFromSocket("/clients");
|
||||
EXPECT_NOT_CONTAINS(str, "floating: 1");
|
||||
}
|
||||
|
||||
// kill all
|
||||
NLog::log("{}Killing all windows", Colors::YELLOW);
|
||||
Tests::killAllWindows();
|
||||
|
||||
NLog::log("{}Expecting 0 windows", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 0);
|
||||
|
||||
return !ret;
|
||||
}
|
||||
349
hyprtester/src/tests/main/workspaces.cpp
Normal file
349
hyprtester/src/tests/main/workspaces.cpp
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
#include "tests.hpp"
|
||||
#include "../../shared.hpp"
|
||||
#include "../../hyprctlCompat.hpp"
|
||||
#include <print>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
#include <csignal>
|
||||
#include <cerrno>
|
||||
#include "../shared.hpp"
|
||||
|
||||
static int ret = 0;
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
using namespace Hyprutils::Memory;
|
||||
|
||||
#define UP CUniquePointer
|
||||
#define SP CSharedPointer
|
||||
|
||||
bool testWorkspaces() {
|
||||
NLog::log("{}Testing workspaces", Colors::GREEN);
|
||||
|
||||
// test on workspace "window"
|
||||
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
|
||||
NLog::log("{}Spawning kittyProc on ws 1", Colors::YELLOW);
|
||||
auto kittyProcA = Tests::spawnKitty();
|
||||
|
||||
if (!kittyProcA) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace 3", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 3"));
|
||||
|
||||
NLog::log("{}Spawning kittyProc on ws 3", Colors::YELLOW);
|
||||
auto kittyProcB = Tests::spawnKitty();
|
||||
|
||||
if (!kittyProcB) {
|
||||
NLog::log("{}Error: kitty did not spawn", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
|
||||
NLog::log("{}Switching to workspace +1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace +1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 2 (2)");
|
||||
}
|
||||
|
||||
// check if the other workspaces are alive
|
||||
{
|
||||
auto str = getFromSocket("/workspaces");
|
||||
EXPECT_CONTAINS(str, "workspace ID 3 (3)");
|
||||
EXPECT_CONTAINS(str, "workspace ID 1 (1)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
|
||||
NLog::log("{}Switching to workspace m+1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace m+1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 3 (3)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace -1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace -1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 2 (2)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
|
||||
NLog::log("{}Switching to workspace r+1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace r+1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 2 (2)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace r+1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace r+1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 3 (3)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace r~1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace r~1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 1 (1)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace empty", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace empty"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 2 (2)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace previous", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace previous"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 1 (1)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace name:TEST_WORKSPACE_NULL", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace name:TEST_WORKSPACE_NULL"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID -1337 (TEST_WORKSPACE_NULL)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
|
||||
// add a new monitor
|
||||
NLog::log("{}Adding a new monitor", Colors::YELLOW);
|
||||
EXPECT(getFromSocket("/output create headless"), "ok")
|
||||
|
||||
// should take workspace 2
|
||||
{
|
||||
auto str = getFromSocket("/monitors");
|
||||
EXPECT_CONTAINS(str, "active workspace: 2 (2)");
|
||||
EXPECT_CONTAINS(str, "active workspace: 1 (1)");
|
||||
EXPECT_CONTAINS(str, "HEADLESS-3");
|
||||
}
|
||||
|
||||
// focus the first monitor
|
||||
OK(getFromSocket("/dispatch focusmonitor 0"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 1 (1)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace r+1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace r+1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 3 (3)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace r~2", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
OK(getFromSocket("/dispatch workspace r~2"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 3 (3)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace m+1", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch workspace m+1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 1 (1)");
|
||||
}
|
||||
|
||||
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
||||
// no OK: this will throw an error as it should
|
||||
getFromSocket("/dispatch workspace 1");
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 1 (1)");
|
||||
}
|
||||
|
||||
NLog::log("{}Testing back_and_forth", Colors::YELLOW);
|
||||
OK(getFromSocket("/keyword binds:workspace_back_and_forth true"));
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 3 (3)");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/keyword binds:workspace_back_and_forth false"));
|
||||
|
||||
NLog::log("{}Testing hide_special_on_workspace_change", Colors::YELLOW);
|
||||
OK(getFromSocket("/keyword binds:hide_special_on_workspace_change true"));
|
||||
OK(getFromSocket("/dispatch workspace special:HELLO"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/monitors");
|
||||
EXPECT_CONTAINS(str, "special workspace: -");
|
||||
EXPECT_CONTAINS(str, "special:HELLO");
|
||||
}
|
||||
|
||||
// no OK: will err (it shouldnt prolly but oh well)
|
||||
getFromSocket("/dispatch workspace 3");
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/monitors");
|
||||
EXPECT_COUNT_STRING(str, "special workspace: 0 ()", 2);
|
||||
}
|
||||
|
||||
OK(getFromSocket("/keyword binds:hide_special_on_workspace_change false"));
|
||||
|
||||
NLog::log("{}Testing allow_workspace_cycles", Colors::YELLOW);
|
||||
OK(getFromSocket("/keyword binds:allow_workspace_cycles true"));
|
||||
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
OK(getFromSocket("/dispatch workspace 3"));
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
|
||||
OK(getFromSocket("/dispatch workspace previous"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 3 (3)");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/dispatch workspace previous"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 1 (1)");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/dispatch workspace previous"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activeworkspace");
|
||||
EXPECT_STARTS_WITH(str, "workspace ID 3 (3)");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/keyword binds:allow_workspace_cycles false"));
|
||||
|
||||
OK(getFromSocket("/dispatch workspace 1"));
|
||||
|
||||
NLog::log("{}Killing all windows", Colors::YELLOW);
|
||||
Tests::killAllWindows();
|
||||
|
||||
// spawn 3 kitties
|
||||
NLog::log("{}Testing focus_preferred_method", Colors::YELLOW);
|
||||
OK(getFromSocket("/keyword dwindle:force_split 2"));
|
||||
Tests::spawnKitty("kitty_A");
|
||||
Tests::spawnKitty("kitty_B");
|
||||
Tests::spawnKitty("kitty_C");
|
||||
OK(getFromSocket("/keyword dwindle:force_split 0"));
|
||||
|
||||
// focus kitty 2: will be top right (dwindle)
|
||||
OK(getFromSocket("/dispatch focuswindow class:kitty_B"));
|
||||
|
||||
// resize it to be a bit taller
|
||||
OK(getFromSocket("/dispatch resizeactive +20 +20"));
|
||||
|
||||
// now we test focus methods.
|
||||
OK(getFromSocket("/keyword binds:focus_preferred_method 0"));
|
||||
|
||||
OK(getFromSocket("/dispatch focuswindow class:kitty_C"));
|
||||
OK(getFromSocket("/dispatch focuswindow class:kitty_A"));
|
||||
|
||||
OK(getFromSocket("/dispatch movefocus r"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitty_C");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/dispatch focuswindow class:kitty_A"));
|
||||
|
||||
OK(getFromSocket("/keyword binds:focus_preferred_method 1"));
|
||||
|
||||
OK(getFromSocket("/dispatch movefocus r"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitty_B");
|
||||
}
|
||||
|
||||
NLog::log("{}Testing movefocus_cycles_fullscreen", Colors::YELLOW);
|
||||
OK(getFromSocket("/dispatch focuswindow class:kitty_A"));
|
||||
OK(getFromSocket("/dispatch focusmonitor HEADLESS-3"));
|
||||
Tests::spawnKitty("kitty_D");
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitty_D");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/dispatch focusmonitor l"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitty_A");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/keyword binds:movefocus_cycles_fullscreen false"));
|
||||
OK(getFromSocket("/dispatch fullscreen 0"));
|
||||
|
||||
OK(getFromSocket("/dispatch movefocus r"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitty_D");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/dispatch focusmonitor l"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitty_A");
|
||||
}
|
||||
|
||||
OK(getFromSocket("/keyword binds:movefocus_cycles_fullscreen true"));
|
||||
|
||||
OK(getFromSocket("/dispatch movefocus r"));
|
||||
|
||||
{
|
||||
auto str = getFromSocket("/activewindow");
|
||||
EXPECT_CONTAINS(str, "class: kitty_B");
|
||||
}
|
||||
|
||||
// destroy the headless output
|
||||
OK(getFromSocket("/output remove HEADLESS-3"));
|
||||
|
||||
// kill all
|
||||
NLog::log("{}Killing all windows", Colors::YELLOW);
|
||||
Tests::killAllWindows();
|
||||
|
||||
NLog::log("{}Expecting 0 windows", Colors::YELLOW);
|
||||
EXPECT(Tests::windowCount(), 0);
|
||||
|
||||
return !ret;
|
||||
}
|
||||
21
hyprtester/src/tests/plugin/plugin.cpp
Normal file
21
hyprtester/src/tests/plugin/plugin.cpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include "plugin.hpp"
|
||||
#include "../../shared.hpp"
|
||||
#include "../../hyprctlCompat.hpp"
|
||||
#include <print>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
#include <csignal>
|
||||
#include <cerrno>
|
||||
#include "../shared.hpp"
|
||||
|
||||
bool testPlugin() {
|
||||
const auto RESPONSE = getFromSocket("/dispatch plugin:test:test");
|
||||
|
||||
if (RESPONSE != "ok") {
|
||||
NLog::log("{}Plugin tests failed, plugin returned:\n{}{}", Colors::RED, Colors::RESET, RESPONSE);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
3
hyprtester/src/tests/plugin/plugin.hpp
Normal file
3
hyprtester/src/tests/plugin/plugin.hpp
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
bool testPlugin();
|
||||
92
hyprtester/src/tests/shared.cpp
Normal file
92
hyprtester/src/tests/shared.cpp
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#include "shared.hpp"
|
||||
#include <csignal>
|
||||
#include <cerrno>
|
||||
#include <thread>
|
||||
#include <print>
|
||||
#include "../shared.hpp"
|
||||
#include "../hyprctlCompat.hpp"
|
||||
|
||||
using namespace Hyprutils::OS;
|
||||
using namespace Hyprutils::Memory;
|
||||
|
||||
CUniquePointer<CProcess> Tests::spawnKitty(const std::string& class_) {
|
||||
const auto COUNT_BEFORE = windowCount();
|
||||
|
||||
CUniquePointer<CProcess> kitty = makeUnique<CProcess>("kitty", class_.empty() ? std::vector<std::string>{} : std::vector<std::string>{"--class", class_});
|
||||
kitty->addEnv("WAYLAND_DISPLAY", WLDISPLAY);
|
||||
kitty->runAsync();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
|
||||
// wait while kitty spawns
|
||||
int counter = 0;
|
||||
while (processAlive(kitty->pid()) && windowCount() == COUNT_BEFORE) {
|
||||
counter++;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
if (counter > 50)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!processAlive(kitty->pid()))
|
||||
return nullptr;
|
||||
|
||||
return kitty;
|
||||
}
|
||||
|
||||
bool Tests::processAlive(pid_t pid) {
|
||||
errno = 0;
|
||||
int ret = kill(pid, 0);
|
||||
return ret != -1 || errno != ESRCH;
|
||||
}
|
||||
|
||||
int Tests::windowCount() {
|
||||
return countOccurrences(getFromSocket("/clients"), "focusHistoryID: ");
|
||||
}
|
||||
|
||||
int Tests::countOccurrences(const std::string& in, const std::string& what) {
|
||||
int cnt = 0;
|
||||
auto pos = in.find(what);
|
||||
while (pos != std::string::npos) {
|
||||
cnt++;
|
||||
pos = in.find(what, pos + what.length() - 1);
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
bool Tests::killAllWindows() {
|
||||
auto str = getFromSocket("/clients");
|
||||
auto pos = str.find("Window ");
|
||||
while (pos != std::string::npos) {
|
||||
auto pos2 = str.find(" -> ", pos);
|
||||
getFromSocket("/dispatch killwindow address:0x" + str.substr(pos + 7, pos2 - pos - 7));
|
||||
pos = str.find("Window ", pos + 5);
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
while (Tests::windowCount() != 0) {
|
||||
counter++;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
if (counter > 50) {
|
||||
std::println("{}Timed out waiting for windows to close", Colors::RED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tests::waitUntilWindowsN(int n) {
|
||||
int counter = 0;
|
||||
while (Tests::windowCount() != n) {
|
||||
counter++;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
if (counter > 50) {
|
||||
std::println("{}Timed out waiting for windows", Colors::RED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
hyprtester/src/tests/shared.hpp
Normal file
17
hyprtester/src/tests/shared.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "../Log.hpp"
|
||||
|
||||
//NOLINTNEXTLINE
|
||||
namespace Tests {
|
||||
Hyprutils::Memory::CUniquePointer<Hyprutils::OS::CProcess> spawnKitty(const std::string& class_ = "");
|
||||
bool processAlive(pid_t pid);
|
||||
int windowCount();
|
||||
int countOccurrences(const std::string& in, const std::string& what);
|
||||
bool killAllWindows();
|
||||
void waitUntilWindowsN(int n);
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue