diff --git a/test/standalone/posix/build.zig b/test/standalone/posix/build.zig index 52ec99628d..f163beea8a 100644 --- a/test/standalone/posix/build.zig +++ b/test/standalone/posix/build.zig @@ -4,11 +4,13 @@ const builtin = @import("builtin"); const Case = struct { src_path: []const u8, set_env_vars: bool = false, + make_tmp_dir: bool = false, }; const cases = [_]Case{ .{ .src_path = "cwd.zig", + .make_tmp_dir = true, }, .{ .src_path = "getenv.zig", @@ -19,6 +21,7 @@ const cases = [_]Case{ }, .{ .src_path = "relpaths.zig", + .make_tmp_dir = true, }, }; @@ -69,6 +72,9 @@ fn run_exe(b: *std.Build, optimize: std.builtin.OptimizeMode, case: *const Case, }); const run_cmd = b.addRunArtifact(exe); + if (case.make_tmp_dir) { + run_cmd.addDirectoryArg(b.tmpPath()); + } if (case.set_env_vars) { run_cmd.setEnvironmentVariable("ZIG_TEST_POSIX_1EQ", "test=variable"); diff --git a/test/standalone/posix/cwd.zig b/test/standalone/posix/cwd.zig index d437132475..7a9517b412 100644 --- a/test/standalone/posix/cwd.zig +++ b/test/standalone/posix/cwd.zig @@ -13,10 +13,15 @@ pub fn main(init: std.process.Init) !void { .windows => return, // POSIX is not implemented by Windows else => {}, } + const args = try init.minimal.args.toSlice(init.arena.allocator()); + const tmp_dir_path = args[1]; + + var tmp_dir = try Io.Dir.cwd().openDir(init.io, tmp_dir_path, .{}); + defer tmp_dir.close(init.io); try test_chdir_self(); try test_chdir_absolute(); - try test_chdir_relative(init.gpa, init.io); + try test_chdir_relative(init.gpa, init.io, tmp_dir); } // get current working directory and expect it to match given path @@ -47,23 +52,22 @@ fn test_chdir_absolute() !void { try expect_cwd(parent); } -fn test_chdir_relative(gpa: Allocator, io: Io) !void { - var tmp = tmpDir(io, .{}); - defer tmp.cleanup(io); +fn test_chdir_relative(gpa: Allocator, io: Io, tmp_dir: Io.Dir) !void { + const subdir_path = "subdir"; + try tmp_dir.createDir(io, "subdir", .default_dir); - // Use the tmpDir parent_dir as the "base" for the test. Then cd into the child - try std.process.setCurrentDir(io, tmp.parent_dir); + // Use the tmp dir as the "base" for the test. Then cd into the child + try std.process.setCurrentDir(io, tmp_dir); // Capture base working directory path, to build expected full path var base_cwd_buf: [path_max]u8 = undefined; const base_cwd = try std.posix.getcwd(base_cwd_buf[0..]); - const relative_dir_name = &tmp.sub_path; - const expected_path = try std.fs.path.resolve(gpa, &.{ base_cwd, relative_dir_name }); + const expected_path = try std.fs.path.resolve(gpa, &.{ base_cwd, subdir_path }); defer gpa.free(expected_path); // change current working directory to new test directory - try std.Io.Threaded.chdir(relative_dir_name); + try std.Io.Threaded.chdir(subdir_path); var new_cwd_buf: [path_max]u8 = undefined; const new_cwd = try std.posix.getcwd(new_cwd_buf[0..]); @@ -74,41 +78,3 @@ fn test_chdir_relative(gpa: Allocator, io: Io) !void { try std.testing.expectEqualStrings(expected_path, resolved_cwd); } - -pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir { - var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; - std.crypto.random.bytes(&random_bytes); - var sub_path: [TmpDir.sub_path_len]u8 = undefined; - _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); - - const cwd = Io.Dir.cwd(); - var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); - defer cache_dir.close(io); - const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir"); - const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch - @panic("unable to make tmp dir for testing: unable to make and open the tmp dir"); - - return .{ - .dir = dir, - .parent_dir = parent_dir, - .sub_path = sub_path, - }; -} - -pub const TmpDir = struct { - dir: Io.Dir, - parent_dir: Io.Dir, - sub_path: [sub_path_len]u8, - - const random_bytes_count = 12; - const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count); - - pub fn cleanup(self: *TmpDir, io: Io) void { - self.dir.close(io); - self.parent_dir.deleteTree(io, &self.sub_path) catch {}; - self.parent_dir.close(io); - self.* = undefined; - } -}; diff --git a/test/standalone/posix/relpaths.zig b/test/standalone/posix/relpaths.zig index e31e497875..9fe92f3cef 100644 --- a/test/standalone/posix/relpaths.zig +++ b/test/standalone/posix/relpaths.zig @@ -11,16 +11,19 @@ pub fn main(init: std.process.Init) !void { const io = init.io; - var tmp = tmpDir(io, .{}); - defer tmp.cleanup(io); + const args = try init.minimal.args.toSlice(init.arena.allocator()); + const tmp_dir_path = args[1]; + + var tmp_dir = try Io.Dir.cwd().openDir(io, tmp_dir_path, .{}); + defer tmp_dir.close(io); // Want to test relative paths, so cd into the tmpdir for these tests - try std.process.setCurrentDir(io, tmp.dir); + try std.process.setCurrentDir(io, tmp_dir); - try test_link(io, tmp); + try test_link(io, tmp_dir); } -fn test_link(io: Io, tmp: TmpDir) !void { +fn test_link(io: Io, tmp_dir: Io.Dir) !void { switch (builtin.target.os.tag) { .linux, .illumos => {}, else => return, @@ -29,16 +32,16 @@ fn test_link(io: Io, tmp: TmpDir) !void { const target_name = "link-target"; const link_name = "newlink"; - try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" }); + try tmp_dir.writeFile(io, .{ .sub_path = target_name, .data = "example" }); - // Test 1: create the relative link from inside tmp + // Test 1: create the relative link from inside tmp_dir try Io.Dir.hardLink(.cwd(), target_name, .cwd(), link_name, io, .{}); // Verify - const efd = try tmp.dir.openFile(io, target_name, .{}); + const efd = try tmp_dir.openFile(io, target_name, .{}); defer efd.close(io); - const nfd = try tmp.dir.openFile(io, link_name, .{}); + const nfd = try tmp_dir.openFile(io, link_name, .{}); defer nfd.close(io); { @@ -55,41 +58,3 @@ fn test_link(io: Io, tmp: TmpDir) !void { try std.testing.expectEqual(1, e_stat.nlink); } } - -pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir { - var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; - std.crypto.random.bytes(&random_bytes); - var sub_path: [TmpDir.sub_path_len]u8 = undefined; - _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); - - const cwd = Io.Dir.cwd(); - var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); - defer cache_dir.close(io); - const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir"); - const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch - @panic("unable to make tmp dir for testing: unable to make and open the tmp dir"); - - return .{ - .dir = dir, - .parent_dir = parent_dir, - .sub_path = sub_path, - }; -} - -pub const TmpDir = struct { - dir: Io.Dir, - parent_dir: Io.Dir, - sub_path: [sub_path_len]u8, - - const random_bytes_count = 12; - const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count); - - pub fn cleanup(self: *TmpDir, io: Io) void { - self.dir.close(io); - self.parent_dir.deleteTree(io, &self.sub_path) catch {}; - self.parent_dir.close(io); - self.* = undefined; - } -}; diff --git a/test/standalone/windows_bat_args/build.zig b/test/standalone/windows_bat_args/build.zig index b91b4fb3bb..d54b6cd48c 100644 --- a/test/standalone/windows_bat_args/build.zig +++ b/test/standalone/windows_bat_args/build.zig @@ -19,6 +19,22 @@ pub fn build(b: *std.Build) !void { }), }); + const bat_files = b.addWriteFiles(); + { + const echo_args_basename = "echo-args.exe"; + const preamble = std.fmt.allocPrint(b.allocator, + \\@echo off + \\"{s}" + , .{echo_args_basename}) catch @panic("OOM"); + // Trailing newline intentionally omitted above so we can add args. + + _ = bat_files.add("args1.bat", std.mem.concat(b.allocator, u8, &.{ preamble, " %*" }) catch @panic("OOM")); + _ = bat_files.add("args2.bat", std.mem.concat(b.allocator, u8, &.{ preamble, " %1 %2 %3 %4 %5 %6 %7 %8 %9" }) catch @panic("OOM")); + _ = bat_files.add("args3.bat", std.mem.concat(b.allocator, u8, &.{ preamble, " \"%~1\" \"%~2\" \"%~3\" \"%~4\" \"%~5\" \"%~6\" \"%~7\" \"%~8\" \"%~9\"" }) catch @panic("OOM")); + + _ = bat_files.addCopyFile(echo_args.getEmittedBin(), echo_args_basename); + } + const test_exe = b.addExecutable(.{ .name = "test", .root_module = b.createModule(.{ @@ -29,7 +45,7 @@ pub fn build(b: *std.Build) !void { }); const run = b.addRunArtifact(test_exe); - run.addArtifactArg(echo_args); + run.setCwd(bat_files.getDirectory()); run.expectExitCode(0); run.skip_foreign_checks = true; @@ -55,7 +71,7 @@ pub fn build(b: *std.Build) !void { const fuzz_seed_arg = std.fmt.allocPrint(b.allocator, "{}", .{fuzz_seed}) catch @panic("oom"); const fuzz_run = b.addRunArtifact(fuzz); - fuzz_run.addArtifactArg(echo_args); + fuzz_run.setCwd(bat_files.getDirectory()); fuzz_run.addArgs(&.{ fuzz_iterations_arg, fuzz_seed_arg }); fuzz_run.expectExitCode(0); fuzz_run.skip_foreign_checks = true; diff --git a/test/standalone/windows_bat_args/fuzz.zig b/test/standalone/windows_bat_args/fuzz.zig index b82ec8b458..f3f72ab897 100644 --- a/test/standalone/windows_bat_args/fuzz.zig +++ b/test/standalone/windows_bat_args/fuzz.zig @@ -11,7 +11,6 @@ pub fn main(init: std.process.Init) !void { var it = try init.minimal.args.iterateAllocator(gpa); defer it.deinit(); _ = it.next() orelse unreachable; // skip binary name - const child_exe_path_orig = it.next() orelse unreachable; const iterations: u64 = iterations: { const arg = it.next() orelse "0"; @@ -37,37 +36,6 @@ pub fn main(init: std.process.Init) !void { std.debug.print("rand seed: {}\n", .{seed}); } - var tmp = tmpDir(io, .{}); - defer tmp.cleanup(io); - - try std.process.setCurrentDir(io, tmp.dir); - defer std.process.setCurrentDir(io, tmp.parent_dir) catch {}; - - // `child_exe_path_orig` might be relative; make it relative to our new cwd. - const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig }); - defer gpa.free(child_exe_path); - - var buf: std.ArrayList(u8) = .empty; - defer buf.deinit(gpa); - try buf.print(gpa, - \\@echo off - \\"{s}" - , .{child_exe_path}); - // Trailing newline intentionally omitted above so we can add args. - const preamble_len = buf.items.len; - - try buf.appendSlice(gpa, " %*"); - try tmp.dir.writeFile(io, .{ .sub_path = "args1.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - - try buf.appendSlice(gpa, " %1 %2 %3 %4 %5 %6 %7 %8 %9"); - try tmp.dir.writeFile(io, .{ .sub_path = "args2.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - - try buf.appendSlice(gpa, " \"%~1\" \"%~2\" \"%~3\" \"%~4\" \"%~5\" \"%~6\" \"%~7\" \"%~8\" \"%~9\""); - try tmp.dir.writeFile(io, .{ .sub_path = "args3.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - var i: u64 = 0; while (iterations == 0 or i < iterations) { const rand_arg = try randomArg(gpa, rand); @@ -163,41 +131,3 @@ fn randomArg(gpa: Allocator, rand: std.Random) ![]const u8 { return buf.toOwnedSlice(gpa); } - -pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir { - var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; - std.crypto.random.bytes(&random_bytes); - var sub_path: [TmpDir.sub_path_len]u8 = undefined; - _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); - - const cwd = Io.Dir.cwd(); - var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); - defer cache_dir.close(io); - const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir"); - const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch - @panic("unable to make tmp dir for testing: unable to make and open the tmp dir"); - - return .{ - .dir = dir, - .parent_dir = parent_dir, - .sub_path = sub_path, - }; -} - -pub const TmpDir = struct { - dir: Io.Dir, - parent_dir: Io.Dir, - sub_path: [sub_path_len]u8, - - const random_bytes_count = 12; - const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count); - - pub fn cleanup(self: *TmpDir, io: Io) void { - self.dir.close(io); - self.parent_dir.deleteTree(io, &self.sub_path) catch {}; - self.parent_dir.close(io); - self.* = undefined; - } -}; diff --git a/test/standalone/windows_bat_args/test.zig b/test/standalone/windows_bat_args/test.zig index fde627a5fe..a923326aa1 100644 --- a/test/standalone/windows_bat_args/test.zig +++ b/test/standalone/windows_bat_args/test.zig @@ -6,42 +6,6 @@ pub fn main(init: std.process.Init) !void { const gpa = init.gpa; const io = init.io; - var it = try init.minimal.args.iterateAllocator(gpa); - defer it.deinit(); - _ = it.next() orelse unreachable; // skip binary name - const child_exe_path_orig = it.next() orelse unreachable; - - var tmp = tmpDir(io, .{}); - defer tmp.cleanup(io); - - try std.process.setCurrentDir(io, tmp.dir); - defer std.process.setCurrentDir(io, tmp.parent_dir) catch {}; - - // `child_exe_path_orig` might be relative; make it relative to our new cwd. - const child_exe_path = try std.fs.path.resolve(gpa, &.{ "..\\..\\..", child_exe_path_orig }); - defer gpa.free(child_exe_path); - - var buf: std.ArrayList(u8) = .empty; - defer buf.deinit(gpa); - try buf.print(gpa, - \\@echo off - \\"{s}" - , .{child_exe_path}); - // Trailing newline intentionally omitted above so we can add args. - const preamble_len = buf.items.len; - - try buf.appendSlice(gpa, " %*"); - try tmp.dir.writeFile(io, .{ .sub_path = "args1.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - - try buf.appendSlice(gpa, " %1 %2 %3 %4 %5 %6 %7 %8 %9"); - try tmp.dir.writeFile(io, .{ .sub_path = "args2.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - - try buf.appendSlice(gpa, " \"%~1\" \"%~2\" \"%~3\" \"%~4\" \"%~5\" \"%~6\" \"%~7\" \"%~8\" \"%~9\""); - try tmp.dir.writeFile(io, .{ .sub_path = "args3.bat", .data = buf.items }); - buf.shrinkRetainingCapacity(preamble_len); - // Test cases are from https://github.com/rust-lang/rust/blob/master/tests/ui/std/windows-bat-args.rs try testExecError(error.InvalidBatchScriptArg, gpa, io, &.{"\x00"}); try testExecError(error.InvalidBatchScriptArg, gpa, io, &.{"\n"}); @@ -119,7 +83,7 @@ pub fn main(init: std.process.Init) !void { try testExec(gpa, io, &.{"%FOO%"}, &env); // Ensure that none of the `>file.txt`s have caused file.txt to be created - try std.testing.expectError(error.FileNotFound, tmp.dir.access(io, "file.txt", .{})); + try std.testing.expectError(error.FileNotFound, Io.Dir.cwd().access(io, "file.txt", .{})); } fn testExecError(err: anyerror, gpa: Allocator, io: Io, args: []const []const u8) !void { @@ -160,41 +124,3 @@ fn testExecBat(gpa: Allocator, io: Io, bat: []const u8, args: []const []const u8 i += 1; } } - -pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir { - var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; - std.crypto.random.bytes(&random_bytes); - var sub_path: [TmpDir.sub_path_len]u8 = undefined; - _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); - - const cwd = Io.Dir.cwd(); - var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); - defer cache_dir.close(io); - const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir"); - const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch - @panic("unable to make tmp dir for testing: unable to make and open the tmp dir"); - - return .{ - .dir = dir, - .parent_dir = parent_dir, - .sub_path = sub_path, - }; -} - -pub const TmpDir = struct { - dir: Io.Dir, - parent_dir: Io.Dir, - sub_path: [sub_path_len]u8, - - const random_bytes_count = 12; - const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count); - - pub fn cleanup(self: *TmpDir, io: Io) void { - self.dir.close(io); - self.parent_dir.deleteTree(io, &self.sub_path) catch {}; - self.parent_dir.close(io); - self.* = undefined; - } -}; diff --git a/test/standalone/windows_spawn/build.zig b/test/standalone/windows_spawn/build.zig index 2b967b16d5..43b0f162bf 100644 --- a/test/standalone/windows_spawn/build.zig +++ b/test/standalone/windows_spawn/build.zig @@ -30,6 +30,7 @@ pub fn build(b: *std.Build) void { const run = b.addRunArtifact(main); run.addArtifactArg(hello); + run.addDirectoryArg(b.tmpPath()); run.expectExitCode(0); run.skip_foreign_checks = true; diff --git a/test/standalone/windows_spawn/main.zig b/test/standalone/windows_spawn/main.zig index 4a64ca48d6..e26b581f59 100644 --- a/test/standalone/windows_spawn/main.zig +++ b/test/standalone/windows_spawn/main.zig @@ -9,16 +9,19 @@ pub fn main(init: std.process.Init) !void { const gpa = init.gpa; const io = init.io; const process_cwd_path = try std.process.getCwdAlloc(init.arena.allocator()); + var initial_process_cwd = try Io.Dir.cwd().openDir(io, ".", .{}); + defer initial_process_cwd.close(io); var it = try init.minimal.args.iterateAllocator(gpa); defer it.deinit(); _ = it.next() orelse unreachable; // skip binary name const hello_exe_cache_path = it.next() orelse unreachable; + const tmp_dir_path = it.next() orelse unreachable; - var tmp = tmpDir(io, .{}); - defer tmp.cleanup(io); + var tmp_dir = try Io.Dir.cwd().openDir(io, tmp_dir_path, .{}); + defer tmp_dir.close(io); - const tmp_absolute_path = try tmp.dir.realPathFileAlloc(io, ".", gpa); + const tmp_absolute_path = try tmp_dir.realPathFileAlloc(io, ".", gpa); defer gpa.free(tmp_absolute_path); const tmp_absolute_path_w = try std.unicode.utf8ToUtf16LeAllocZ(gpa, tmp_absolute_path); defer gpa.free(tmp_absolute_path_w); @@ -51,7 +54,7 @@ pub fn main(init: std.process.Init) !void { ) == windows.TRUE); // Move hello.exe into the tmp dir which is now added to the path - try Io.Dir.cwd().copyFile(hello_exe_cache_path, tmp.dir, "hello.exe", io, .{}); + try Io.Dir.cwd().copyFile(hello_exe_cache_path, tmp_dir, "hello.exe", io, .{}); // with extension should find the .exe (case insensitive) try testExec(gpa, io, "HeLLo.exe", "hello from exe\n"); @@ -61,9 +64,9 @@ pub fn main(init: std.process.Init) !void { try std.testing.expectError(error.FileNotFound, testExecWithCwd(gpa, io, "hello.exe", "missing_dir", "")); // now add a .bat - try tmp.dir.writeFile(io, .{ .sub_path = "hello.bat", .data = "@echo hello from bat" }); + try tmp_dir.writeFile(io, .{ .sub_path = "hello.bat", .data = "@echo hello from bat" }); // and a .cmd - try tmp.dir.writeFile(io, .{ .sub_path = "hello.cmd", .data = "@echo hello from cmd" }); + try tmp_dir.writeFile(io, .{ .sub_path = "hello.cmd", .data = "@echo hello from cmd" }); // with extension should find the .bat (case insensitive) try testExec(gpa, io, "heLLo.bat", "hello from bat\r\n"); @@ -73,15 +76,15 @@ pub fn main(init: std.process.Init) !void { try testExec(gpa, io, "heLLo", "hello from exe\n"); // now rename the exe to not have an extension - try renameExe(tmp.dir, io, "hello.exe", "hello"); + try renameExe(tmp_dir, io, "hello.exe", "hello"); // with extension should now fail try testExecError(error.FileNotFound, gpa, io, "hello.exe"); // without extension should succeed (case insensitive) try testExec(gpa, io, "heLLo", "hello from exe\n"); - try tmp.dir.createDir(io, "something", .default_dir); - try renameExe(tmp.dir, io, "hello", "something/hello.exe"); + try tmp_dir.createDir(io, "something", .default_dir); + try renameExe(tmp_dir, io, "hello", "something/hello.exe"); const relative_path_no_ext = try std.fs.path.join(gpa, &.{ tmp_relative_path, "something/hello" }); defer gpa.free(relative_path_no_ext); @@ -95,7 +98,7 @@ pub fn main(init: std.process.Init) !void { try testExec(gpa, io, "heLLo", "hello from bat\r\n"); // Add a hello.exe that is not a valid executable - try tmp.dir.writeFile(io, .{ .sub_path = "hello.exe", .data = "invalid" }); + try tmp_dir.writeFile(io, .{ .sub_path = "hello.exe", .data = "invalid" }); // Trying to execute it with extension will give InvalidExe. This is a special // case for .EXE extensions, where if they ever try to get executed but they are @@ -108,14 +111,14 @@ pub fn main(init: std.process.Init) !void { try testExecError(error.InvalidExe, gpa, io, "hello"); // If we now rename hello.exe to have no extension, it will behave differently - try renameExe(tmp.dir, io, "hello.exe", "hello"); + try renameExe(tmp_dir, io, "hello.exe", "hello"); // Now, trying to execute it without an extension should treat InvalidExe as recoverable // and skip over it and find hello.bat and execute that try testExec(gpa, io, "hello", "hello from bat\r\n"); // If we rename the invalid exe to something else - try renameExe(tmp.dir, io, "hello", "goodbye"); + try renameExe(tmp_dir, io, "hello", "goodbye"); // Then we should now get FileNotFound when trying to execute 'goodbye', // since that is what the original error will be after searching for 'goodbye' // in the cwd. It will try to execute 'goodbye' from the PATH but the InvalidExe error @@ -123,8 +126,8 @@ pub fn main(init: std.process.Init) !void { try testExecError(error.FileNotFound, gpa, io, "goodbye"); // Now let's set the tmp dir as the cwd and set the path only include the "something" sub dir - try std.process.setCurrentDir(io, tmp.dir); - defer std.process.setCurrentDir(io, tmp.parent_dir) catch {}; + try std.process.setCurrentDir(io, tmp_dir); + defer std.process.setCurrentDir(io, initial_process_cwd) catch {}; const something_subdir_abs_path = try std.mem.concatWithSentinel(gpa, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0); defer gpa.free(something_subdir_abs_path); @@ -141,7 +144,7 @@ pub fn main(init: std.process.Init) !void { try testExec(gpa, io, "hello", "hello from bat\r\n"); // If we rename something/hello.exe to something/goodbye.exe - try renameExe(tmp.dir, io, "something/hello.exe", "something/goodbye.exe"); + try renameExe(tmp_dir, io, "something/hello.exe", "something/goodbye.exe"); // And try to execute goodbye, then the one in something should be found // since the one in cwd is an invalid executable try testExec(gpa, io, "goodbye", "hello from exe\n"); @@ -183,10 +186,10 @@ pub fn main(init: std.process.Init) !void { try testExec(gpa, io, "goodbye", "hello from exe\n"); // now make sure we can launch executables "outside" of the cwd - var subdir_cwd = try tmp.dir.openDir(io, denormed_something_subdir_wtf8, .{}); + var subdir_cwd = try tmp_dir.openDir(io, denormed_something_subdir_wtf8, .{}); defer subdir_cwd.close(io); - try renameExe(tmp.dir, io, "something/goodbye.exe", "hello.exe"); + try renameExe(tmp_dir, io, "something/goodbye.exe", "hello.exe"); try std.process.setCurrentDir(io, subdir_cwd); // clear the PATH again @@ -232,41 +235,3 @@ fn renameExe(dir: Io.Dir, io: Io, old_sub_path: []const u8, new_sub_path: []cons else => |e| return e, }; } - -pub fn tmpDir(io: Io, opts: Io.Dir.OpenOptions) TmpDir { - var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; - std.crypto.random.bytes(&random_bytes); - var sub_path: [TmpDir.sub_path_len]u8 = undefined; - _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); - - const cwd = Io.Dir.cwd(); - var cache_dir = cwd.createDirPathOpen(io, ".zig-cache", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache dir"); - defer cache_dir.close(io); - const parent_dir = cache_dir.createDirPathOpen(io, "tmp", .{}) catch - @panic("unable to make tmp dir for testing: unable to make and open .zig-cache/tmp dir"); - const dir = parent_dir.createDirPathOpen(io, &sub_path, .{ .open_options = opts }) catch - @panic("unable to make tmp dir for testing: unable to make and open the tmp dir"); - - return .{ - .dir = dir, - .parent_dir = parent_dir, - .sub_path = sub_path, - }; -} - -pub const TmpDir = struct { - dir: Io.Dir, - parent_dir: Io.Dir, - sub_path: [sub_path_len]u8, - - const random_bytes_count = 12; - const sub_path_len = std.fs.base64_encoder.calcSize(random_bytes_count); - - pub fn cleanup(self: *TmpDir, io: Io) void { - self.dir.close(io); - self.parent_dir.deleteTree(io, &self.sub_path) catch {}; - self.parent_dir.close(io); - self.* = undefined; - } -};