64b6755254d1

wire refAllDecls(@This()) into main.zig so zig build test discovers test blocks in errors.zig, config.zig, exec.zig, commands.zig, and types.zig; fix leaked TranslatedError string fields in errors.zig tests and leaked config/machine-name allocations in config.zig tests that this surfaced

time
2026-07-02 13:32 UTC · 3 months ago
machine
koh2
agent
claude-sonnet-5
session
wire refAllDecls into zig build test
parent
b3f422a2f4b6
3 files src/config.zig+5 −0src/errors.zig+8 −3src/main.zig+12 −1
src/config.zig+5 −0
@@ -207,6 +207,8 @@207207     ;208208     const config = try parse(std.testing.allocator, input, "/home/test");209209     defer std.testing.allocator.free(config.machines);210+    defer std.testing.allocator.free(config.editor);211+    defer std.testing.allocator.free(config.machines[0].name);210212 211213     try std.testing.expectEqualStrings("hx", config.editor);212214     try std.testing.expectEqual(@as(u32, 3), config.generations);@@ -229,6 +231,7 @@229231     ;230232     const config = try parse(std.testing.allocator, input, "/home/test");231233     defer std.testing.allocator.free(config.machines);234+    defer std.testing.allocator.free(config.machines[0].name);232235 233236     try std.testing.expect(config.confirm);234237     try std.testing.expect(!config.teach);@@ -246,6 +249,7 @@246249     ;247250     const cfg_with = try parse(std.testing.allocator, with, "/home/test");248251     defer std.testing.allocator.free(cfg_with.machines);252+    defer std.testing.allocator.free(cfg_with.machines[0].name);249253     try std.testing.expect(cfg_with.flake);250254 251255     const without =@@ -254,6 +258,7 @@254258     ;255259     const cfg_without = try parse(std.testing.allocator, without, "/home/test");256260     defer std.testing.allocator.free(cfg_without.machines);261+    defer std.testing.allocator.free(cfg_without.machines[0].name);257262     try std.testing.expect(!cfg_without.flake);258263 }259264 

view file

src/errors.zig+8 −3
@@ -162,7 +162,7 @@162162 fn findLocationInLine(allocator: std.mem.Allocator, line: []const u8) ?[]const u8 {163163     const nix_pos = std.mem.indexOf(u8, line, ".nix:") orelse return null;164164     const before = line[0 .. nix_pos + 4]; // includes ".nix"165-    const rest = line[nix_pos + 5..]; // "47:3" or "47"165+    const rest = line[nix_pos + 5 ..]; // "47:3" or "47"166166     const colon_or_end = std.mem.indexOf(u8, rest, ":") orelse rest.len;167167     const line_num_str = rest[0..colon_or_end];168168     if (line_num_str.len == 0 or line_num_str.len > 6) return null;@@ -653,6 +653,9 @@653653 test "layer 1: undefined variable" {654654     const t = matchKnownPattern(std.testing.allocator, "error: undefined variable 'pkgs.notexist'");655655     try std.testing.expect(t != null);656+    defer std.testing.allocator.free(t.?.title);657+    defer std.testing.allocator.free(t.?.body);658+    defer std.testing.allocator.free(t.?.suggestion);656659     try std.testing.expect(std.mem.indexOf(u8, t.?.title, "notexist") != null);657660 }658661 @@ -666,6 +669,7 @@666669 test "layer 1: unfree" {667670     const t = matchKnownPattern(std.testing.allocator, "error: Package 'discord' has an unfree license");668671     try std.testing.expect(t != null);672+    defer std.testing.allocator.free(t.?.body);669673     try std.testing.expectEqualStrings("package has an unfree license", t.?.title);670674 }671675 @@ -675,10 +679,11 @@675679 }676680 677681 test "layer 1: service activation failure" {678-    const t = matchKnownPattern(std.testing.allocator,679-        "warning: the following units failed: rtorrent.service\n" ++682+    const t = matchKnownPattern(std.testing.allocator, "warning: the following units failed: rtorrent.service\n" ++680683         "Command 'systemd-run ...' returned non-zero exit status 4.");681684     try std.testing.expect(t != null);685+    defer std.testing.allocator.free(t.?.body);686+    defer std.testing.allocator.free(t.?.suggestion);682687     try std.testing.expectEqualStrings("service failed after upgrade", t.?.title);683688     try std.testing.expect(std.mem.indexOf(u8, t.?.body, "rtorrent.service") != null);684689     try std.testing.expect(std.mem.indexOf(u8, t.?.suggestion, "rtorrent.service") != null);

view file

src/main.zig+12 −1
@@ -252,7 +252,10 @@252252     if (std.mem.eql(u8, cmd, "home")) return commands.home(ctx);253253     if (std.mem.eql(u8, cmd, "goodbye")) return commands.goodbye(ctx);254254     if (std.mem.eql(u8, cmd, "hello")) return commands.hello(ctx);255-    if (std.mem.eql(u8, cmd, "help")) { output.help(); return; }255+    if (std.mem.eql(u8, cmd, "help")) {256+        output.help();257+        return;258+    }256259 257260     errors.error_info.setMessage("unknown command: {s}", .{cmd});258261     errors.error_info.setSuggestion("nina help", .{});@@ -345,6 +348,14 @@345348         if (std.mem.eql(u8, cmd, m)) return true;346349     }347350     return false;351+}352+353+// Zig 0.16's test runner only discovers `test` blocks in files it can see are354+// reachable from the root; refAllDecls forces every decl main.zig imports355+// (transitively) to be referenced, which is what pulls in test blocks living356+// in exec.zig, commands.zig, errors.zig, config.zig, etc.357+test {358+    std.testing.refAllDecls(@This());348359 }349360 350361 test "parse args basic" {

view file