diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index cc211a69a1..8171ff7eea 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -1348,46 +1348,30 @@ const childstr = test "build and call child_process" { if (builtin.os.tag == .wasi) return error.SkipZigTest; const testing = std.testing; - var it = try std.process.argsWithAllocator(std.testing.allocator); - defer it.deinit(); // no-op unless WASI or Windows + const allocator = testing.allocator; + + var it = try std.process.argsWithAllocator(allocator); + defer it.deinit(); // no-op unless WASI or Windows + const testargs = try testing.getTestArgs(&it); - _ = it.next() orelse unreachable; - const zigexec = it.next() orelse unreachable; - try testing.expect(it.next() == null); - try testing.expect(!it.skip()); - const cwd_str = try process.getCwdAlloc(testing.allocator); - defer testing.allocator.free(cwd_str); var tmp = testing.tmpDir(.{ .no_follow = true }); // ie zig-cache/tmp/8DLgoSEqz593PAEE defer tmp.cleanup(); - const cache = "zig-cache"; - const tmpdir = "tmp"; + const tmpdirpath = try tmp.getFullPath(allocator); + defer allocator.free(tmpdirpath); const child_name = "child"; // no need for suffixes (.exe, .wasm) due to '-femit-bin' const suffix_zig = ".zig"; - const child_path = try fs.path.join(testing.allocator, &[_][]const u8{ cwd_str, std.fs.path.sep_str, cache, tmpdir, &tmp.sub_path, child_name }); - defer testing.allocator.free(child_path); + const child_path = try fs.path.join(allocator, &[_][]const u8{ tmpdirpath, child_name }); + defer allocator.free(child_path); + const child_zig = try mem.concat(allocator, u8, &[_][]const u8{ child_path, suffix_zig }); + defer allocator.free(child_zig); - const child_zig = try mem.concat(testing.allocator, u8, &[_][]const u8{ child_path, suffix_zig }); - defer testing.allocator.free(child_zig); - const emit_flag = "-femit-bin="; - const emit_bin = try mem.concat(testing.allocator, u8, &[_][]const u8{ emit_flag, child_path }); - defer testing.allocator.free(emit_bin); - { - // 'zigexec build-exe path/to/child.zig -femit-bin=path/to/child' expect success - try tmp.dir.writeFile("child.zig", childstr); - const args = [_][]const u8{ zigexec, "build-exe", child_zig, emit_bin }; - var procCompileChild = try ChildProcess.init(&args, testing.allocator); - defer procCompileChild.deinit(); - try procCompileChild.spawn(); - const ret_val = try procCompileChild.wait(); - try testing.expectEqual(ret_val, .{ .Exited = 0 }); - } - { - // spawn compiled file as child_process with argument 'hello world' + expect success - const args = [_][]const u8{ child_path, "hello world" }; - var child_proc = try ChildProcess.init(&args, testing.allocator); - defer child_proc.deinit(); - try child_proc.spawn(); - const ret_val = try child_proc.wait(); - try testing.expectEqual(ret_val, .{ .Exited = 0 }); - } + try tmp.dir.writeFile("child.zig", childstr); + try testing.buildExe(testargs.zigexec, child_zig, child_path); + + // spawn compiled file as child_process with argument 'hello world' + expect success + const args = [_][]const u8{ child_path, "hello world" }; + var child_proc = try ChildProcess.init(&args, allocator); + defer child_proc.deinit(); + const ret_val = try child_proc.spawnAndWait(); + try testing.expectEqual(ret_val, .{ .Exited = 0 }); } diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 5049218c90..4146e033b4 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -355,6 +355,19 @@ pub const TmpDir = struct { const random_bytes_count = 12; const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count); + /// caller owns memory + pub fn getFullPath(self: *TmpDir, alloc: std.mem.Allocator) ![]u8 { + const cwd_str = try std.process.getCwdAlloc(alloc); + defer alloc.free(cwd_str); + const path = try std.fs.path.join(alloc, &[_][]const u8{ + cwd_str, + "zig-cache", + "tmp", + &self.sub_path, + }); + return path; + } + pub fn cleanup(self: *TmpDir) void { self.dir.close(); self.parent_dir.deleteTree(&self.sub_path) catch {}; @@ -400,6 +413,43 @@ pub fn tmpDir(opts: std.fs.Dir.OpenDirOptions) TmpDir { }; } +const TestArgs = struct { + testexec: [:0]const u8 = undefined, + zigexec: [:0]const u8 = undefined, +}; + +/// Get test arguments inside test block by regular test runner ('zig test file.zig') +/// Caller must provide backing ArgIterator +pub fn getTestArgs(it: *std.process.ArgIterator) !TestArgs { + var testargs = TestArgs{}; + testargs.testexec = it.next() orelse unreachable; + testargs.zigexec = it.next() orelse unreachable; + try expect(!it.skip()); + return testargs; +} + +test "getTestArgs" { + var it = try std.process.argsWithAllocator(allocator); + const testargs = try getTestArgs(&it); + defer it.deinit(); // no-op unless WASI or Windows + try expect(testargs.testexec.len > 0); // zig compiler executable path + try expect(testargs.zigexec.len > 0); // test runner executable path +} + +/// Spawns child process with 'zigexec build-exe zigfile -femit-bin=binfile' +/// and expects success +pub fn buildExe(zigexec: []const u8, zigfile: []const u8, binfile: []const u8) !void { + const flag_emit = "-femit-bin="; + const cmd_emit = try std.mem.concat(allocator, u8, &[_][]const u8{ flag_emit, binfile }); + defer allocator.free(cmd_emit); + const args = [_][]const u8{ zigexec, "build-exe", zigfile, cmd_emit }; + var procCompileChild = try std.ChildProcess.init(&args, allocator); + defer procCompileChild.deinit(); + try procCompileChild.spawn(); + const ret_val = try procCompileChild.wait(); + try expectEqual(ret_val, .{ .Exited = 0 }); +} + test "expectEqual nested array" { const a = [2][2]f32{ [_]f32{ 1.0, 0.0 },