Files
Alvin/tests/test_core.cpp
T
Aeth3randClaude Opus 5.5 ca7e62ac8d Add Alvin library: input, capture, windows and vision
A cross-platform C++23 library with a platform-neutral public API and
runtime-selected backends:

- Input: Wayland virtual pointer/keyboard (Hyprland, wlroots), libei via
  the RemoteDesktop portal (GNOME, KDE), uinput, and Win32 SendInput
- Capture: ScreenCast portal + PipeWire, and Win32 GDI
- Windows: Hyprland IPC and Win32 enumeration
- Monitors via wl_output/xdg-output and EnumDisplayMonitors
- Optional OpenCV template matching (alvin::vision)

Also adds the `alvin` CLI, Catch2 unit tests, install rules with
find_package(Alvin) support, API docs (docs/API.md and the Obsidian
vault), and README instructions for both ways of consuming the library.

Windows backends are written but not yet compiled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:58:20 -04:00

67 lines
2.1 KiB
C++

#include <catch2/catch_test_macros.hpp>
#include "alvin/frame.hpp"
#include "alvin/keys.hpp"
#include "alvin/types.hpp"
using namespace alvin;
TEST_CASE("key names round-trip and aliases resolve") {
CHECK(keyFromName("A") == Key::A);
CHECK(keyFromName("ctrl") == Key::LeftCtrl);
CHECK(keyFromName("Control") == Key::LeftCtrl);
CHECK(keyFromName("esc") == Key::Escape);
CHECK(keyFromName("F12") == Key::F12);
CHECK_FALSE(keyFromName("nope"));
for (int k = 1; k < static_cast<int>(Key::Count_); ++k) {
auto key = static_cast<Key>(k);
INFO("key index " << k);
CHECK(keyFromName(keyName(key)) == key);
}
}
TEST_CASE("chords parse in order") {
auto c = parseChord("ctrl+shift+t");
REQUIRE(c);
CHECK(*c == std::vector{Key::LeftCtrl, Key::LeftShift, Key::T});
CHECK(parseChord(" super + enter ") == std::vector{Key::LeftSuper, Key::Enter});
CHECK(parseChord("ctrl++") == std::vector{Key::LeftCtrl, Key::Equal});
CHECK_FALSE(parseChord("ctrl+"));
CHECK_FALSE(parseChord(""));
CHECK_FALSE(parseChord("ctrl+bogus"));
}
TEST_CASE("rect union ignores empty rects") {
Rect a{0, 0, 10, 10}, b{20, -5, 5, 5};
CHECK(a.united(b) == Rect{0, -5, 25, 15});
CHECK(Rect{}.united(a) == a);
CHECK(a.united(Rect{}) == a);
CHECK(a.contains({9, 9}));
CHECK_FALSE(a.contains({10, 0}));
}
TEST_CASE("frame maps between pixels and desktop coordinates") {
// A 1.5x scaled monitor: 300x150 pixels covering 200x100 logical at (1000, 50).
Frame f(300, 150);
f.setDesktopRect({1000, 50, 200, 100});
CHECK(f.toDesktop({0, 0}) == Point{1000, 50});
CHECK(f.toDesktop({150, 75}) == Point{1100, 100});
CHECK(f.fromDesktop({1100, 100}) == Point{150, 75});
Frame c = f.crop({150, 0, 1000, 75}); // clipped to the frame
CHECK(c.width() == 150);
CHECK(c.height() == 75);
CHECK(c.desktopRect() == Rect{1100, 50, 100, 50});
}
TEST_CASE("frame pixel reads BGRA") {
Frame f(2, 1);
f.data()[4] = 1; // B
f.data()[5] = 2; // G
f.data()[6] = 3; // R
f.data()[7] = 4; // A
CHECK(f.pixel(1, 0) == Color{3, 2, 1, 4});
CHECK(f.pixel(5, 5) == Color{});
}