From 8bc8bc2289e3e33903f9008b3513d0bd9c3f7311 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 09:58:17 -0300 Subject: A bad event record says what is wrong with it `bad event syntax` said nothing of which: now it says a report record (I D i d) is not written back, a range ends before it starts, or what a record looks like when the line is not one. Co-Authored-By: Claude Opus 5.5 --- src/ninep/ctl.zig | 18 ++++++++++++++++++ src/ninep/events.zig | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index c0695c76..5f26a181 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -2061,6 +2061,24 @@ test "a malformed address is bad address syntax, on a terminal as on a text" { } } +test "a bad event record says what is wrong with it" { + const p = try withFile(testing.allocator, "one\n"); + defer p.deinit(); + const event = Node.of(serialOf(p), .event); + const h = call(p, .{ .tag = 1, .op = .open, .node = event, .omode = 2 }).reply.handle; + for ([_][2][]const u8{ + .{ "MI0 1 0 1 x\n", "only a look or exec" }, + .{ "MX3 1 0 0 \n", "ends before it starts" }, + .{ "MX9 9 0 0 \n", "range past end" }, + .{ "garbage\n", "a record is" }, + }) |c| { + const refused = call(p, .{ .tag = 2, .op = .write, .node = event, .handle = h, .data = c[0] }); + try testing.expectEqual(E.INVAL, refused.errno()); + try testing.expect(std.mem.indexOf(u8, refused.reply.ename, c[1]) != null); + } + _ = call(p, .{ .tag = 3, .op = .release, .node = event, .handle = h }); +} + test "size is monotonic: growing is never refused, and a size once taken is taken again" { const p = try Pardes.init(testing.allocator, .{ .tty_only = true, .cols = 160, .rows = 60 }); defer p.deinit(); diff --git a/src/ninep/events.zig b/src/ninep/events.zig index 8b8f8637..868364a6 100644 --- a/src/ninep/events.zig +++ b/src/ninep/events.zig @@ -726,14 +726,14 @@ pub fn writeEvent(p: *Pardes, req: Req, id: usize) Reply { while (check.next()) |r| { switch (r.action) { .body_look, .tag_look, .body_exec, .tag_exec => {}, - else => return tree.failText(req.tag, E.INVAL, tree.e_bad_event), + else => return tree.failText(req.tag, E.INVAL, tree.e_bad_event ++ ": only a look or exec (L l X x) is written back"), } const n = if (r.action.onTag()) tag.len else body.len; - if (r.q0 > r.q1) return tree.failText(req.tag, E.INVAL, tree.e_bad_event); + if (r.q0 > r.q1) return tree.failText(req.tag, E.INVAL, tree.e_bad_event ++ ": its range ends before it starts"); // Well formed, but not a range of this text: say which. if (r.q1 > n) return tree.failText(req.tag, E.INVAL, if (r.action.onTag()) "range past end of tag" else "range past end of body"); } - if (check.i != req.data.len) return tree.failText(req.tag, E.INVAL, tree.e_bad_event); + if (check.i != req.data.len) return tree.failText(req.tag, E.INVAL, tree.e_bad_event ++ ": a record is , a line each"); } var run: EventReader = .{ .data = req.data }; while (run.next()) |r| { -- cgit v1.3