From 09707022632295c5ad4d4186296a266735b393fd Mon Sep 17 00:00:00 2001 From: Ben Buhse Date: Wed, 11 Feb 2026 16:14:29 -0600 Subject: [PATCH] Add some unit tests for a few functions Mostly only testing the easily-testable helpers in utils and Config --- src/Config.zig | 59 ++++++++++++++++++++++ src/main.zig | 5 ++ src/utils.zig | 131 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) diff --git a/src/Config.zig b/src/Config.zig index 9be3010..cf6aadd 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -843,3 +843,62 @@ const RiverColor = utils.RiverColor; const XkbBindings = @import("XkbBindings.zig"); const log = std.log.scoped(.Config); + +const testing = std.testing; + +test "boolFromKdlStr" { + // True valid + try testing.expectEqual(@as(?bool, true), boolFromKdlStr("#true")); + try testing.expectEqual(@as(?bool, true), boolFromKdlStr("true")); + // False valid + try testing.expectEqual(@as(?bool, false), boolFromKdlStr("#false")); + try testing.expectEqual(@as(?bool, false), boolFromKdlStr("false")); + // Invalid + try testing.expectEqual(@as(?bool, null), boolFromKdlStr("yes")); + try testing.expectEqual(@as(?bool, null), boolFromKdlStr("1")); + try testing.expectEqual(@as(?bool, null), boolFromKdlStr("")); + try testing.expectEqual(@as(?bool, null), boolFromKdlStr("TRUE")); +} + +test "parseButton named buttons" { + try testing.expectEqual(@as(?u32, 0x110), parseButton("btn_left")); + try testing.expectEqual(@as(?u32, 0x110), parseButton("button1")); + try testing.expectEqual(@as(?u32, 0x111), parseButton("btn_right")); + try testing.expectEqual(@as(?u32, 0x111), parseButton("button3")); + try testing.expectEqual(@as(?u32, 0x112), parseButton("btn_middle")); + try testing.expectEqual(@as(?u32, 0x112), parseButton("button2")); +} + +test "parseButton case insensitive" { + try testing.expectEqual(@as(?u32, 0x110), parseButton("BTN_LEFT")); + try testing.expectEqual(@as(?u32, 0x110), parseButton("Btn_Left")); + try testing.expectEqual(@as(?u32, 0x110), parseButton("BUTTON1")); +} + +test "parseButton numeric decimal" { + try testing.expectEqual(@as(?u32, 272), parseButton("272")); + try testing.expectEqual(@as(?u32, 0), parseButton("0")); +} + +test "parseButton numeric hex" { + try testing.expectEqual(@as(?u32, 0x110), parseButton("0x110")); +} + +test "parseButton invalid" { + try testing.expectEqual(@as(?u32, null), parseButton("bogus")); + try testing.expectEqual(@as(?u32, null), parseButton("")); +} + +test "expandTilde with tilde" { + const result = try expandTilde("~/foo/bar"); + defer utils.allocator.free(result); + const home = std.posix.getenv("HOME") orelse return; + try testing.expect(mem.startsWith(u8, result, home)); + try testing.expect(mem.endsWith(u8, result, "/foo/bar")); +} + +test "expandTilde without tilde" { + const result = try expandTilde("/absolute/path"); + defer utils.allocator.free(result); + try testing.expectEqualStrings("/absolute/path", result); +} diff --git a/src/main.zig b/src/main.zig index b7043da..ffff12a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -255,3 +255,8 @@ const WindowManager = @import("WindowManager.zig"); const XkbBindings = @import("XkbBindings.zig"); const log = std.log.scoped(.main); + +test { + _ = @import("utils.zig"); + _ = @import("Config.zig"); +} diff --git a/src/utils.zig b/src/utils.zig index 22190d7..cde8a3c 100644 --- a/src/utils.zig +++ b/src/utils.zig @@ -142,3 +142,134 @@ const river = wayland.client.river; const utils = @import("utils.zig"); const log = std.log.scoped(.utils); + +const testing = std.testing; + +test "parseRgba 0xRRGGBB" { + const color = try parseRgba("0x89b4fa"); + try testing.expectEqual(@as(u32, 0x89 << 24), color.red); + try testing.expectEqual(@as(u32, 0xb4 << 24), color.green); + try testing.expectEqual(@as(u32, 0xfa << 24), color.blue); + try testing.expectEqual(@as(u32, 0xff << 24), color.alpha); +} + +test "parseRgba 0xRRGGBBAA" { + const color = try parseRgba("0x1e1e2eff"); + try testing.expectEqual(@as(u32, 0x1e << 24), color.red); + try testing.expectEqual(@as(u32, 0x1e << 24), color.green); + try testing.expectEqual(@as(u32, 0x2e << 24), color.blue); + try testing.expectEqual(@as(u32, 0xff << 24), color.alpha); +} + +test "parseRgba invalid length" { + try testing.expectError(error.InvalidRgba, parseRgba("0x123")); + try testing.expectError(error.InvalidRgba, parseRgba("0x12345678a")); + try testing.expectError(error.InvalidRgba, parseRgba("")); +} + +test "parseRgba missing 0x prefix" { + try testing.expectError(error.InvalidRgba, parseRgba("xx123456")); + try testing.expectError(error.InvalidRgba, parseRgba("12345678")); +} + +test "parseRgba invalid hex characters" { + try testing.expectError(error.InvalidCharacter, parseRgba("0xGGGGGG")); +} + +test "parseRgbaComptime" { + const color = parseRgbaComptime("0x89b4fa"); + try testing.expectEqual(@as(u32, 0x89 << 24), color.red); + try testing.expectEqual(@as(u32, 0xb4 << 24), color.green); + try testing.expectEqual(@as(u32, 0xfa << 24), color.blue); + try testing.expectEqual(@as(u32, 0xff << 24), color.alpha); +} + +test "parseRgbaComptime with alpha" { + const color = parseRgbaComptime("0x1e1e2eff"); + try testing.expectEqual(@as(u32, 0x1e << 24), color.red); + try testing.expectEqual(@as(u32, 0x1e << 24), color.green); + try testing.expectEqual(@as(u32, 0x2e << 24), color.blue); + try testing.expectEqual(@as(u32, 0xff << 24), color.alpha); +} + +test "stripQuotes removes surrounding quotes" { + try testing.expectEqualStrings("hello", stripQuotes("\"hello\"")); +} + +test "stripQuotes no quotes" { + try testing.expectEqualStrings("hello", stripQuotes("hello")); +} + +test "stripQuotes empty string" { + try testing.expectEqualStrings("", stripQuotes("")); +} + +test "stripQuotes single char" { + try testing.expectEqualStrings("\"", stripQuotes("\"")); +} + +test "stripQuotes only quotes" { + try testing.expectEqualStrings("", stripQuotes("\"\"")); +} + +test "stripQuotes mismatched quotes" { + try testing.expectEqualStrings("\"hello", stripQuotes("\"hello")); + try testing.expectEqualStrings("hello\"", stripQuotes("hello\"")); +} + +test "parseModifiers single modifier" { + const mods = (try parseModifiers("shift")).?; + try testing.expect(mods.shift); + try testing.expect(!mods.mod4); + try testing.expect(!mods.ctrl); + try testing.expect(!mods.mod1); +} + +test "parseModifiers combined" { + const mods = (try parseModifiers("mod4+shift+ctrl")).?; + try testing.expect(mods.mod4); + try testing.expect(mods.shift); + try testing.expect(mods.ctrl); + try testing.expect(!mods.mod1); +} + +test "parseModifiers super alias" { + const mods = (try parseModifiers("super")).?; + try testing.expect(mods.mod4); +} + +test "parseModifiers alt alias" { + const mods = (try parseModifiers("alt")).?; + try testing.expect(mods.mod1); +} + +test "parseModifiers none" { + const mods = (try parseModifiers("none")).?; + try testing.expect(!mods.shift); + try testing.expect(!mods.mod4); + try testing.expect(!mods.ctrl); + try testing.expect(!mods.mod1); +} + +test "parseModifiers case insensitive" { + const mods = (try parseModifiers("SHIFT")).?; + try testing.expect(mods.shift); + + const mods2 = (try parseModifiers("Mod4")).?; + try testing.expect(mods2.mod4); +} + +test "parseModifiers unrecognized" { + try testing.expectEqual(@as(?river.SeatV1.Modifiers, null), try parseModifiers("bogus")); +} + +test "parseModifiers invalid length" { + try testing.expectEqual(@as(?river.SeatV1.Modifiers, null), try parseModifiers("ab")); + try testing.expectEqual(@as(?river.SeatV1.Modifiers, null), try parseModifiers("toolong")); +} + +test "parseModifiers mod3 and mod5" { + const mods = (try parseModifiers("mod3+mod5")).?; + try testing.expect(mods.mod3); + try testing.expect(mods.mod5); +}