Skip to content

Instantly share code, notes, and snippets.

@matu3ba
Last active March 8, 2022 22:03
Show Gist options
  • Save matu3ba/2ec6abaa48806d70ee135ab5a9bd19d2 to your computer and use it in GitHub Desktop.
Save matu3ba/2ec6abaa48806d70ee135ab5a9bd19d2 to your computer and use it in GitHub Desktop.
subprocess testing
:!/usr/bin/time -v zig test %
1/1 test "build and call child_process"... cwd_str: /home/misterspoon/dev/git/zig/zig/pipe
tmpDir: vCWMmOLRT0RiWAMe
child_zig: zig-cache/tmp/vCWMmOLRT0RiWAMe/child.zig
emit_bin: -femit-bin=zig-cache/tmp/vCWMmOLRT0RiWAMe/child
child_path: zig-cache/tmp/vCWMmOLRT0RiWAMe/child
OK
All 1 tests passed.
Command being timed: "zig test tst_childprocess.zig"
User time (seconds): 2.14
Voluntary context switches: 3548
Involuntary context switches: 90
Swaps: 0
File system inputs: 0
File system outputs: 7360
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
const std = @import("std");
// child parses the stdin input and checks expected result
const childstr =
\\ const std = @import("std");
\\ const builtin = @import("builtin");
\\ const os = std.os;
\\ pub fn main() !void {
\\ var arena_inst = std.heap.ArenaAllocator.init(std.heap.page_allocator);
\\ defer arena_inst.deinit();
\\ const arena = arena_inst.allocator();
\\ var it = try std.process.argsWithAllocator(arena);
\\ defer it.deinit(); // no-op unless WASI or Windows
\\ _ = it.next() orelse unreachable; // skip binary name
\\ const input = it.next() orelse unreachable;
\\ var expect_helloworld = "hello world".*;
\\ try std.testing.expect(std.mem.eql(u8, &expect_helloworld, input));
\\ }
;
test "build and call child_process" {
var arena_inst = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena_inst.deinit();
const arena = arena_inst.allocator();
var tmp = std.testing.tmpDir(.{}); // ie zig-cache/tmp/8DLgoSEqz593PAEE
defer tmp.cleanup();
const cwd_str = try std.process.getCwdAlloc(arena);
defer arena.free(cwd_str);
std.debug.print("cwd_str: {s}\n", .{cwd_str});
std.debug.print("tmpDir: {s}\n", .{tmp.sub_path});
const exited: []const u8 = "Exited";
const cache = "zig-cache";
const tmpdir = "tmp";
const child_name = "child"; // no need for suffixes (.exe, .wasm) due to '-femit-bin'
const suffix_zig = ".zig";
const child_path = try std.fs.path.join(arena, &[_][]const u8{ cache, tmpdir, &tmp.sub_path, child_name });
defer arena.free(child_path);
const child_zig = try std.mem.concat(arena, u8, &[_][]const u8{ child_path, suffix_zig });
defer arena.free(child_zig);
std.debug.print("child_zig: {s}\n", .{child_zig});
const emit_flag = "-femit-bin=";
const emit_bin = try std.mem.concat(arena, u8, &[_][]const u8{ emit_flag, child_path });
defer arena.free(emit_bin);
std.debug.print("emit_bin: {s}\n", .{emit_bin});
{
// compile file => run 'zig build-exe path/to/child.zig -femit-bin=path/to/child' and expect success
try tmp.dir.writeFile("child.zig", childstr);
const args = [_][]const u8{ "zig", "build-exe", child_zig, emit_bin };
var procCompileChild = try std.ChildProcess.init(&args, arena);
defer procCompileChild.deinit();
try procCompileChild.spawn();
const ret_val = try procCompileChild.wait();
try std.testing.expectEqualSlices(u8, exited, std.meta.tagName(ret_val));
try std.testing.expectEqual(@as(u8, 0), ret_val.Exited);
}
{
// spawn compiled file as child_process with argument 'hello world'
std.debug.print("child_path: {s}\n", .{child_path});
const args = [_][]const u8{ child_path, "hello world" };
var child_proc = try std.ChildProcess.init(&args, arena);
defer child_proc.deinit();
try child_proc.spawn();
const ret_val = try child_proc.wait();
try std.testing.expectEqualSlices(u8, exited, std.meta.tagName(ret_val));
try std.testing.expectEqual(@as(u8, 0), ret_val.Exited);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment