summaryrefslogtreecommitdiff
path: root/test/e2e_harness.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-07-06 18:00:54 -0300
committerGabriel Schneider <[email protected]>2026-08-01 15:02:07 -0300
commit7a83d1548493b043e2e77022c1c87d348377ac7b (patch)
tree75bcac77800b13695a953a3398b5bb8a95e017dd /test/e2e_harness.zig
parentde4def3548a6729b0dfd2120495a61beef8c8c2c (diff)
downloadpardes-7a83d1548493b043e2e77022c1c87d348377ac7b.tar.gz
pardes-7a83d1548493b043e2e77022c1c87d348377ac7b.zip
posix portability: linux syscalls -> libc (std.c) in one shared path. All raw std.os.linux.* call sites converted with the errno-convention flip (libc returns -1 + thread-local errno, not -errno): open/close/read/write/rename in tty.zig, gui.zig, look.zig; harness too (snapshot.zig: getcwd/mkdir/chdir/fork+waitpid/getdents64->opendir-readdir, e2e_harness.zig: clock_gettime/write/close), so the parity suite itself is POSIX-portable. Per-OS branches kept only where platforms genuinely diverge: shellCwd in look.zig (linux /proc/<pid>/cwd readlink; darwin libproc proc_pidinfo PROC_PIDVNODEPATHINFO with a hand-declared extern; other POSIX degrades to null), bash path (/usr/bin/bash on linux, /bin/bash elsewhere), TIOCSWINSZ constant (absent from std.c.T on darwin). forkpty/execv/chdir externs were already libc and are portable (fork-safety preserved: absolute-path execv, no malloc between fork and exec, initial spawns before worker threads). build.zig: forward target/optimize to the ghostty dep for native/cross (web keeps its no-target fetch), disable ghostty simd for darwin cross-builds (apple_sdk needs xcrun; scalar fallback = web config), link libutil on the BSDs. Pinned ghostty needs two one-line zig-0.16 darwin fixes, applied in the zig-pkg cache and documented in build.zig. Verified: aarch64-macos + x86_64-macos + x86_64-freebsd cross-compiles green; linux native tty + gui + web green; snapshot suite 18/18 with goldens untouched. Out of scope: gui-on-macos needs Metal shaders (SDL GPU rejects our SPIR-V there).
Diffstat (limited to 'test/e2e_harness.zig')
-rw-r--r--test/e2e_harness.zig37
1 files changed, 18 insertions, 19 deletions
diff --git a/test/e2e_harness.zig b/test/e2e_harness.zig
index 6354aa4b..9099f13e 100644
--- a/test/e2e_harness.zig
+++ b/test/e2e_harness.zig
@@ -1,8 +1,11 @@
const std = @import("std");
const posix = std.posix;
-const linux = std.os.linux;
+const libc = std.c;
const ghostty_vt = @import("ghostty-vt");
+// TIOCSWINSZ: absent from std.c.T on darwin — _IOW('t', 103, winsize)
+const TIOCSWINSZ: c_int = @bitCast(@as(u32, if (@hasDecl(posix.T, "IOCSWINSZ")) posix.T.IOCSWINSZ else 0x80087467));
+
extern "c" fn forkpty(
amaster: *c_int,
name: ?[*:0]u8,
@@ -13,9 +16,9 @@ extern "c" fn execvp(file: [*:0]const u8, argv: [*:null]const ?[*:0]const u8) c_
extern "c" fn _exit(status: c_int) noreturn;
fn nowMs() i64 {
- var ts: linux.timespec = undefined;
- _ = linux.clock_gettime(linux.CLOCK.MONOTONIC, &ts);
- return ts.sec * 1000 + @divFloor(@as(i64, ts.nsec), 1_000_000);
+ var ts: libc.timespec = undefined;
+ _ = libc.clock_gettime(.MONOTONIC, &ts);
+ return @as(i64, @intCast(ts.sec)) * 1000 + @divFloor(@as(i64, @intCast(ts.nsec)), 1_000_000);
}
/// E2E test harness: forks the app in a pty and parses its output with a
@@ -92,7 +95,7 @@ pub const Harness = struct {
pub fn deinit(self: *Harness) void {
posix.kill(self.pid, posix.SIG.KILL) catch {};
- _ = linux.close(self.master);
+ _ = libc.close(self.master);
self.stream.deinit();
self.raw.deinit(self.gpa);
self.term.deinit(self.gpa);
@@ -103,10 +106,9 @@ pub const Harness = struct {
pub fn send(self: *Harness, bytes: []const u8) !void {
var off: usize = 0;
while (off < bytes.len) {
- const rc = linux.write(self.master, bytes[off..].ptr, bytes.len - off);
- const n: isize = @bitCast(rc);
+ const n = libc.write(self.master, bytes[off..].ptr, bytes.len - off);
if (n < 0) {
- if (n == -@as(isize, @intFromEnum(linux.E.INTR))) continue;
+ if (libc.errno(n) == .INTR) continue;
return error.WriteFailed;
}
off += @intCast(n);
@@ -139,7 +141,7 @@ pub const Harness = struct {
self.cols = cols;
self.term.resize(self.gpa, cols, rows) catch {};
const ws = posix.winsize{ .row = rows, .col = cols, .xpixel = 0, .ypixel = 0 };
- _ = posix.system.ioctl(self.master, posix.T.IOCSWINSZ, @intFromPtr(&ws));
+ _ = posix.system.ioctl(self.master, TIOCSWINSZ, @intFromPtr(&ws));
}
/// The full viewport text (plainString), newline-joined rows. Caller frees.
@@ -261,18 +263,15 @@ pub const Harness = struct {
}
};
-/// Write a file (helper for test setup, raw linux syscalls).
+/// Write a file (helper for test setup, raw libc).
pub fn writeFile(path: [*:0]const u8, data: []const u8) !void {
- const rc = linux.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, 0o644);
- const sfd: isize = @bitCast(rc);
- if (sfd < 0) return error.OpenFailed;
- const fd: c_int = @intCast(sfd);
- defer _ = linux.close(fd);
+ const fd = libc.open(path, .{ .ACCMODE = .WRONLY, .CREAT = true, .TRUNC = true }, @as(libc.mode_t, 0o644));
+ if (fd < 0) return error.OpenFailed;
+ defer _ = libc.close(fd);
var off: usize = 0;
while (off < data.len) {
- const w = linux.write(fd, data[off..].ptr, data.len - off);
- const sw: isize = @bitCast(w);
- if (sw <= 0) break;
- off += @intCast(sw);
+ const w = libc.write(fd, data[off..].ptr, data.len - off);
+ if (w <= 0) break;
+ off += @intCast(w);
}
}