| 1 | const std = @import("std"); |
| 2 | const Io = std.Io; |
| 3 | |
| 4 | // 42 is expected by parent; other values result in test failure |
| 5 | var exit_code: u8 = 42; |
| 6 | |
| 7 | pub fn main(init: std.process.Init) !void { |
| 8 | try run(init.arena.allocator(), init.io, init.minimal.args); |
| 9 | std.process.exit(exit_code); |
| 10 | } |
| 11 | |
| 12 | fn run(arena: std.mem.Allocator, io: Io, args: std.process.Args) !void { |
| 13 | var it = try args.iterateAllocator(arena); |
| 14 | defer it.deinit(); |
| 15 | _ = it.next() orelse unreachable; // skip binary name |
| 16 | |
| 17 | // test cmd args |
| 18 | const hello_arg = "hello arg"; |
| 19 | const a1 = it.next() orelse unreachable; |
| 20 | if (!std.mem.eql(u8, a1, hello_arg)) { |
| 21 | testError(io, "first arg: '{s}'; want '{s}'", .{ a1, hello_arg }); |
| 22 | } |
| 23 | if (it.next()) |a2| { |
| 24 | testError(io, "expected only one arg; got more: {s}", .{a2}); |
| 25 | } |
| 26 | |
| 27 | // test stdout pipe; parent verifies |
| 28 | try std.Io.File.stdout().writeStreamingAll(io, "hello from stdout"); |
| 29 | |
| 30 | // test stdin pipe from parent |
| 31 | const hello_stdin = "hello from stdin"; |
| 32 | var buf: [hello_stdin.len]u8 = undefined; |
| 33 | const stdin: std.Io.File = .stdin(); |
| 34 | var reader = stdin.reader(io, &.{}); |
| 35 | const n = try reader.interface.readSliceShort(&buf); |
| 36 | if (!std.mem.eql(u8, buf[0..n], hello_stdin)) { |
| 37 | testError(io, "stdin: '{s}'; want '{s}'", .{ buf[0..n], hello_stdin }); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | fn testError(io: Io, comptime fmt: []const u8, args: anytype) void { |
| 42 | var stderr_writer = std.Io.File.stderr().writer(io, &.{}); |
| 43 | const stderr = &stderr_writer.interface; |
| 44 | stderr.print("CHILD TEST ERROR: ", .{}) catch {}; |
| 45 | stderr.print(fmt, args) catch {}; |
| 46 | if (fmt[fmt.len - 1] != '\n') { |
| 47 | stderr.writeByte('\n') catch {}; |
| 48 | } |
| 49 | exit_code = 1; |
| 50 | } |