| author | |
| committer | |
| log | 9e3bda5efffb12dd6491b4f7c92ccc89b9043c64 |
| tree | ccb1af8488c729172ca9727ccbbf8dd04348b546 |
| parent | a91c6dc71d42ea59ec53ce4e0ae83e4970731313 |
21 files changed, 187 insertions(+), 139 deletions(-)
lib/std/Io/File/Writer.zig+4-2| ... | ... | @@ -56,8 +56,9 @@ pub const WriteFileError = error{ |
| 56 | 56 | |
| 57 | 57 | pub const SeekError = Io.File.SeekError; |
| 58 | 58 | |
| 59 | pub fn init(file: File, buffer: []u8) Writer { | |
| 59 | pub fn init(file: File, io: Io, buffer: []u8) Writer { | |
| 60 | 60 | return .{ |
| 61 | .io = io, | |
| 61 | 62 | .file = file, |
| 62 | 63 | .interface = initInterface(buffer), |
| 63 | 64 | .mode = .positional, |
| ... | ... | @@ -67,8 +68,9 @@ pub fn init(file: File, buffer: []u8) Writer { |
| 67 | 68 | /// Positional is more threadsafe, since the global seek position is not |
| 68 | 69 | /// affected, but when such syscalls are not available, preemptively |
| 69 | 70 | /// initializing in streaming mode will skip a failed syscall. |
| 70 | pub fn initStreaming(file: File, buffer: []u8) Writer { | |
| 71 | pub fn initStreaming(file: File, io: Io, buffer: []u8) Writer { | |
| 71 | 72 | return .{ |
| 73 | .io = io, | |
| 72 | 74 | .file = file, |
| 73 | 75 | .interface = initInterface(buffer), |
| 74 | 76 | .mode = .streaming, |
lib/std/process/Child.zig+8-9| ... | ... | @@ -435,8 +435,7 @@ pub const RunError = posix.GetCwdError || posix.ReadError || SpawnError || posix |
| 435 | 435 | |
| 436 | 436 | /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. |
| 437 | 437 | /// If it succeeds, the caller owns result.stdout and result.stderr memory. |
| 438 | pub fn run(args: struct { | |
| 439 | allocator: mem.Allocator, | |
| 438 | pub fn run(allocator: Allocator, io: Io, args: struct { | |
| 440 | 439 | argv: []const []const u8, |
| 441 | 440 | cwd: ?[]const u8 = null, |
| 442 | 441 | cwd_dir: ?Io.Dir = null, |
| ... | ... | @@ -447,7 +446,7 @@ pub fn run(args: struct { |
| 447 | 446 | expand_arg0: Arg0Expand = .no_expand, |
| 448 | 447 | progress_node: std.Progress.Node = std.Progress.Node.none, |
| 449 | 448 | }) RunError!RunResult { |
| 450 | var child = ChildProcess.init(args.argv, args.allocator); | |
| 449 | var child = ChildProcess.init(args.argv, allocator); | |
| 451 | 450 | child.stdin_behavior = .Ignore; |
| 452 | 451 | child.stdout_behavior = .Pipe; |
| 453 | 452 | child.stderr_behavior = .Pipe; |
| ... | ... | @@ -458,19 +457,19 @@ pub fn run(args: struct { |
| 458 | 457 | child.progress_node = args.progress_node; |
| 459 | 458 | |
| 460 | 459 | var stdout: ArrayList(u8) = .empty; |
| 461 | defer stdout.deinit(args.allocator); | |
| 460 | defer stdout.deinit(allocator); | |
| 462 | 461 | var stderr: ArrayList(u8) = .empty; |
| 463 | defer stderr.deinit(args.allocator); | |
| 462 | defer stderr.deinit(allocator); | |
| 464 | 463 | |
| 465 | 464 | try child.spawn(); |
| 466 | 465 | errdefer { |
| 467 | _ = child.kill() catch {}; | |
| 466 | _ = child.kill(io) catch {}; | |
| 468 | 467 | } |
| 469 | try child.collectOutput(args.allocator, &stdout, &stderr, args.max_output_bytes); | |
| 468 | try child.collectOutput(allocator, &stdout, &stderr, args.max_output_bytes); | |
| 470 | 469 | |
| 471 | 470 | return .{ |
| 472 | .stdout = try stdout.toOwnedSlice(args.allocator), | |
| 473 | .stderr = try stderr.toOwnedSlice(args.allocator), | |
| 471 | .stdout = try stdout.toOwnedSlice(allocator), | |
| 472 | .stderr = try stderr.toOwnedSlice(allocator), | |
| 474 | 473 | .term = try child.wait(), |
| 475 | 474 | }; |
| 476 | 475 | } |
test/src/convert-stack-trace.zig+3-3| ... | ... | @@ -41,13 +41,13 @@ pub fn main() !void { |
| 41 | 41 | var read_buf: [1024]u8 = undefined; |
| 42 | 42 | var write_buf: [1024]u8 = undefined; |
| 43 | 43 | |
| 44 | const in_file = try std.fs.cwd().openFile(args[1], .{}); | |
| 45 | defer in_file.close(); | |
| 44 | const in_file = try std.Io.Dir.cwd().openFile(io, args[1], .{}); | |
| 45 | defer in_file.close(io); | |
| 46 | 46 | |
| 47 | 47 | const out_file: std.Io.File = .stdout(); |
| 48 | 48 | |
| 49 | 49 | var in_fr = in_file.reader(io, &read_buf); |
| 50 | var out_fw = out_file.writer(&write_buf); | |
| 50 | var out_fw = out_file.writer(io, &write_buf); | |
| 51 | 51 | |
| 52 | 52 | const w = &out_fw.interface; |
| 53 | 53 |
test/standalone/child_process/main.zig+8-7| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const Io = std.Io; | |
| 2 | 3 | |
| 3 | 4 | pub fn main() !void { |
| 4 | 5 | // make sure safety checks are enabled even in release modes |
| ... | ... | @@ -20,7 +21,7 @@ pub fn main() !void { |
| 20 | 21 | }; |
| 21 | 22 | defer if (needs_free) gpa.free(child_path); |
| 22 | 23 | |
| 23 | var threaded: std.Io.Threaded = .init(gpa); | |
| 24 | var threaded: Io.Threaded = .init(gpa); | |
| 24 | 25 | defer threaded.deinit(); |
| 25 | 26 | const io = threaded.io(); |
| 26 | 27 | |
| ... | ... | @@ -31,7 +32,7 @@ pub fn main() !void { |
| 31 | 32 | try child.spawn(); |
| 32 | 33 | const child_stdin = child.stdin.?; |
| 33 | 34 | try child_stdin.writeAll("hello from stdin"); // verified in child |
| 34 | child_stdin.close(); | |
| 35 | child_stdin.close(io); | |
| 35 | 36 | child.stdin = null; |
| 36 | 37 | |
| 37 | 38 | const hello_stdout = "hello from stdout"; |
| ... | ... | @@ -39,17 +40,17 @@ pub fn main() !void { |
| 39 | 40 | var stdout_reader = child.stdout.?.readerStreaming(io, &.{}); |
| 40 | 41 | const n = try stdout_reader.interface.readSliceShort(&buf); |
| 41 | 42 | if (!std.mem.eql(u8, buf[0..n], hello_stdout)) { |
| 42 | testError("child stdout: '{s}'; want '{s}'", .{ buf[0..n], hello_stdout }); | |
| 43 | testError(io, "child stdout: '{s}'; want '{s}'", .{ buf[0..n], hello_stdout }); | |
| 43 | 44 | } |
| 44 | 45 | |
| 45 | 46 | switch (try child.wait()) { |
| 46 | 47 | .Exited => |code| { |
| 47 | 48 | const child_ok_code = 42; // set by child if no test errors |
| 48 | 49 | if (code != child_ok_code) { |
| 49 | testError("child exit code: {d}; want {d}", .{ code, child_ok_code }); | |
| 50 | testError(io, "child exit code: {d}; want {d}", .{ code, child_ok_code }); | |
| 50 | 51 | } |
| 51 | 52 | }, |
| 52 | else => |term| testError("abnormal child exit: {}", .{term}), | |
| 53 | else => |term| testError(io, "abnormal child exit: {}", .{term}), | |
| 53 | 54 | } |
| 54 | 55 | if (parent_test_error) return error.ParentTestError; |
| 55 | 56 | |
| ... | ... | @@ -61,8 +62,8 @@ pub fn main() !void { |
| 61 | 62 | |
| 62 | 63 | var parent_test_error = false; |
| 63 | 64 | |
| 64 | fn testError(comptime fmt: []const u8, args: anytype) void { | |
| 65 | var stderr_writer = std.Io.File.stderr().writer(&.{}); | |
| 65 | fn testError(io: Io, comptime fmt: []const u8, args: anytype) void { | |
| 66 | var stderr_writer = Io.File.stderr().writer(io, &.{}); | |
| 66 | 67 | const stderr = &stderr_writer.interface; |
| 67 | 68 | stderr.print("PARENT TEST ERROR: ", .{}) catch {}; |
| 68 | 69 | stderr.print(fmt, args) catch {}; |
test/standalone/cmakedefine/check.zig+5-2| ... | ... | @@ -9,8 +9,11 @@ pub fn main() !void { |
| 9 | 9 | const actual_path = args[1]; |
| 10 | 10 | const expected_path = args[2]; |
| 11 | 11 | |
| 12 | const actual = try std.fs.cwd().readFileAlloc(actual_path, arena, .limited(1024 * 1024)); | |
| 13 | const expected = try std.fs.cwd().readFileAlloc(expected_path, arena, .limited(1024 * 1024)); | |
| 12 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 13 | const io = threaded.io(); | |
| 14 | ||
| 15 | const actual = try std.Io.Dir.cwd().readFileAlloc(io, actual_path, arena, .limited(1024 * 1024)); | |
| 16 | const expected = try std.Io.Dir.cwd().readFileAlloc(io, expected_path, arena, .limited(1024 * 1024)); | |
| 14 | 17 | |
| 15 | 18 | // The actual output starts with a comment which we should strip out before comparing. |
| 16 | 19 | const comment_str = "/* This file was generated by ConfigHeader using the Zig Build System. */\n"; |
test/standalone/dirname/build.zig+6-4| ... | ... | @@ -59,13 +59,15 @@ pub fn build(b: *std.Build) void { |
| 59 | 59 | |
| 60 | 60 | // Absolute path: |
| 61 | 61 | const abs_path = setup_abspath: { |
| 62 | // TODO this is a bad pattern, don't do this | |
| 63 | const io = b.graph.io; | |
| 62 | 64 | const temp_dir = b.makeTempPath(); |
| 63 | 65 | |
| 64 | var dir = std.fs.cwd().openDir(temp_dir, .{}) catch @panic("failed to open temp dir"); | |
| 65 | defer dir.close(); | |
| 66 | var dir = std.Io.Dir.cwd().openDir(io, temp_dir, .{}) catch @panic("failed to open temp dir"); | |
| 67 | defer dir.close(io); | |
| 66 | 68 | |
| 67 | var file = dir.createFile("foo.txt", .{}) catch @panic("failed to create file"); | |
| 68 | file.close(); | |
| 69 | var file = dir.createFile(io, "foo.txt", .{}) catch @panic("failed to create file"); | |
| 70 | file.close(io); | |
| 69 | 71 | |
| 70 | 72 | break :setup_abspath std.Build.LazyPath{ .cwd_relative = temp_dir }; |
| 71 | 73 | }; |
test/standalone/dirname/exists_in.zig+6-3| ... | ... | @@ -34,8 +34,11 @@ fn run(allocator: std.mem.Allocator) !void { |
| 34 | 34 | return error.BadUsage; |
| 35 | 35 | }; |
| 36 | 36 | |
| 37 | var dir = try std.fs.cwd().openDir(dir_path, .{}); | |
| 38 | defer dir.close(); | |
| 37 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 38 | const io = threaded.io(); | |
| 39 | 39 | |
| 40 | _ = try dir.statFile(relpath); | |
| 40 | var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); | |
| 41 | defer dir.close(io); | |
| 42 | ||
| 43 | _ = try dir.statFile(io, relpath); | |
| 41 | 44 | } |
test/standalone/dirname/touch.zig+10-7| ... | ... | @@ -26,14 +26,17 @@ fn run(allocator: std.mem.Allocator) !void { |
| 26 | 26 | return error.BadUsage; |
| 27 | 27 | }; |
| 28 | 28 | |
| 29 | const dir_path = std.fs.path.dirname(path) orelse unreachable; | |
| 30 | const basename = std.fs.path.basename(path); | |
| 29 | const dir_path = std.Io.Dir.path.dirname(path) orelse unreachable; | |
| 30 | const basename = std.Io.Dir.path.basename(path); | |
| 31 | 31 | |
| 32 | var dir = try std.fs.cwd().openDir(dir_path, .{}); | |
| 33 | defer dir.close(); | |
| 32 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 33 | const io = threaded.io(); | |
| 34 | 34 | |
| 35 | _ = dir.statFile(basename) catch { | |
| 36 | var file = try dir.createFile(basename, .{}); | |
| 37 | file.close(); | |
| 35 | var dir = try std.Io.Dir.cwd().openDir(io, dir_path, .{}); | |
| 36 | defer dir.close(io); | |
| 37 | ||
| 38 | _ = dir.statFile(io, basename) catch { | |
| 39 | var file = try dir.createFile(io, basename, .{}); | |
| 40 | file.close(io); | |
| 38 | 41 | }; |
| 39 | 42 | } |
test/standalone/entry_point/check_differ.zig+5-2| ... | ... | @@ -6,8 +6,11 @@ pub fn main() !void { |
| 6 | 6 | const args = try std.process.argsAlloc(arena); |
| 7 | 7 | if (args.len != 3) return error.BadUsage; // usage: 'check_differ <path a> <path b>' |
| 8 | 8 | |
| 9 | const contents_1 = try std.fs.cwd().readFileAlloc(args[1], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty | |
| 10 | const contents_2 = try std.fs.cwd().readFileAlloc(args[2], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty | |
| 9 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 10 | const io = threaded.io(); | |
| 11 | ||
| 12 | const contents_1 = try std.Io.Dir.cwd().readFileAlloc(io, args[1], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty | |
| 13 | const contents_2 = try std.Io.Dir.cwd().readFileAlloc(io, args[2], arena, .limited(1024 * 1024 * 64)); // 64 MiB ought to be plenty | |
| 11 | 14 | |
| 12 | 15 | if (std.mem.eql(u8, contents_1, contents_2)) { |
| 13 | 16 | return error.FilesMatch; |
test/standalone/glibc_compat/glibc_runtime_check.zig+2-2| ... | ... | @@ -28,10 +28,10 @@ extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: [*]const u8) c_int; |
| 28 | 28 | |
| 29 | 29 | // PR #17034 - fstat moved between libc_nonshared and libc |
| 30 | 30 | fn checkStat() !void { |
| 31 | const cwdFd = std.fs.cwd().fd; | |
| 31 | const cwd_fd = std.Io.Dir.cwd().handle; | |
| 32 | 32 | |
| 33 | 33 | var buf: [256]u8 = @splat(0); |
| 34 | var result = fstatat(cwdFd, "a_file_that_definitely_does_not_exist", &buf, 0); | |
| 34 | var result = fstatat(cwd_fd, "a_file_that_definitely_does_not_exist", &buf, 0); | |
| 35 | 35 | assert(result == -1); |
| 36 | 36 | assert(std.posix.errno(result) == .NOENT); |
| 37 | 37 |
test/standalone/install_headers/check_exists.zig+7-4| ... | ... | @@ -11,8 +11,11 @@ pub fn main() !void { |
| 11 | 11 | var arg_it = try std.process.argsWithAllocator(arena); |
| 12 | 12 | _ = arg_it.next(); |
| 13 | 13 | |
| 14 | const cwd = std.fs.cwd(); | |
| 15 | const cwd_realpath = try cwd.realpathAlloc(arena, "."); | |
| 14 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 15 | const io = threaded.io(); | |
| 16 | ||
| 17 | const cwd = std.Io.Dir.cwd(); | |
| 18 | const cwd_realpath = try cwd.realPathAlloc(io, arena, "."); | |
| 16 | 19 | |
| 17 | 20 | while (arg_it.next()) |file_path| { |
| 18 | 21 | if (file_path.len > 0 and file_path[0] == '!') { |
| ... | ... | @@ -20,7 +23,7 @@ pub fn main() !void { |
| 20 | 23 | "exclusive file check '{s}{c}{s}' failed", |
| 21 | 24 | .{ cwd_realpath, std.fs.path.sep, file_path[1..] }, |
| 22 | 25 | ); |
| 23 | if (std.fs.cwd().statFile(file_path[1..])) |_| { | |
| 26 | if (cwd.statFile(io, file_path[1..])) |_| { | |
| 24 | 27 | return error.FileFound; |
| 25 | 28 | } else |err| switch (err) { |
| 26 | 29 | error.FileNotFound => {}, |
| ... | ... | @@ -31,7 +34,7 @@ pub fn main() !void { |
| 31 | 34 | "inclusive file check '{s}{c}{s}' failed", |
| 32 | 35 | .{ cwd_realpath, std.fs.path.sep, file_path }, |
| 33 | 36 | ); |
| 34 | _ = try std.fs.cwd().statFile(file_path); | |
| 37 | _ = try cwd.statFile(io, file_path); | |
| 35 | 38 | } |
| 36 | 39 | } |
| 37 | 40 | } |
test/standalone/libfuzzer/main.zig+5-5| ... | ... | @@ -20,8 +20,8 @@ pub fn main() !void { |
| 20 | 20 | const io = threaded.io(); |
| 21 | 21 | |
| 22 | 22 | const cache_dir_path = args.next() orelse @panic("expected cache directory path argument"); |
| 23 | var cache_dir = try std.fs.cwd().openDir(cache_dir_path, .{}); | |
| 24 | defer cache_dir.close(); | |
| 23 | var cache_dir = try std.Io.Dir.cwd().openDir(io, cache_dir_path, .{}); | |
| 24 | defer cache_dir.close(io); | |
| 25 | 25 | |
| 26 | 26 | abi.fuzzer_init(.fromSlice(cache_dir_path)); |
| 27 | 27 | abi.fuzzer_init_test(testOne, .fromSlice("test")); |
| ... | ... | @@ -30,8 +30,8 @@ pub fn main() !void { |
| 30 | 30 | |
| 31 | 31 | const pc_digest = abi.fuzzer_coverage().id; |
| 32 | 32 | const coverage_file_path = "v/" ++ std.fmt.hex(pc_digest); |
| 33 | const coverage_file = try cache_dir.openFile(coverage_file_path, .{}); | |
| 34 | defer coverage_file.close(); | |
| 33 | const coverage_file = try cache_dir.openFile(io, coverage_file_path, .{}); | |
| 34 | defer coverage_file.close(io); | |
| 35 | 35 | |
| 36 | 36 | var read_buf: [@sizeOf(abi.SeenPcsHeader)]u8 = undefined; |
| 37 | 37 | var r = coverage_file.reader(io, &read_buf); |
| ... | ... | @@ -42,6 +42,6 @@ pub fn main() !void { |
| 42 | 42 | const expected_len = @sizeOf(abi.SeenPcsHeader) + |
| 43 | 43 | try std.math.divCeil(usize, pcs_header.pcs_len, @bitSizeOf(usize)) * @sizeOf(usize) + |
| 44 | 44 | pcs_header.pcs_len * @sizeOf(usize); |
| 45 | if (try coverage_file.getEndPos() != expected_len) | |
| 45 | if (try coverage_file.length(io) != expected_len) | |
| 46 | 46 | return error.WrongEnd; |
| 47 | 47 | } |
test/standalone/posix/relpaths.zig+15-8| ... | ... | @@ -1,9 +1,11 @@ |
| 1 | 1 | // Test relative paths through POSIX APIS. These tests have to change the cwd, so |
| 2 | 2 | // they shouldn't be Zig unit tests. |
| 3 | 3 | |
| 4 | const std = @import("std"); | |
| 5 | 4 | const builtin = @import("builtin"); |
| 6 | 5 | |
| 6 | const std = @import("std"); | |
| 7 | const Io = std.Io; | |
| 8 | ||
| 7 | 9 | pub fn main() !void { |
| 8 | 10 | if (builtin.target.os.tag == .wasi) return; // Can link, but can't change into tmpDir |
| 9 | 11 | |
| ... | ... | @@ -11,6 +13,11 @@ pub fn main() !void { |
| 11 | 13 | const a = Allocator.allocator(); |
| 12 | 14 | defer std.debug.assert(Allocator.deinit() == .ok); |
| 13 | 15 | |
| 16 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 17 | const io = threaded.io(); | |
| 18 | ||
| 19 | // TODO this API isn't supposed to be used outside of unit testing. make it compilation error if used | |
| 20 | // outside of unit testing. | |
| 14 | 21 | var tmp = std.testing.tmpDir(.{}); |
| 15 | 22 | defer tmp.cleanup(); |
| 16 | 23 | |
| ... | ... | @@ -18,7 +25,7 @@ pub fn main() !void { |
| 18 | 25 | try tmp.dir.setAsCwd(); |
| 19 | 26 | |
| 20 | 27 | try test_symlink(a, tmp); |
| 21 | try test_link(tmp); | |
| 28 | try test_link(io, tmp); | |
| 22 | 29 | } |
| 23 | 30 | |
| 24 | 31 | fn test_symlink(a: std.mem.Allocator, tmp: std.testing.TmpDir) !void { |
| ... | ... | @@ -65,7 +72,7 @@ fn getLinkInfo(fd: std.posix.fd_t) !struct { std.posix.ino_t, std.posix.nlink_t |
| 65 | 72 | return .{ st.ino, st.nlink }; |
| 66 | 73 | } |
| 67 | 74 | |
| 68 | fn test_link(tmp: std.testing.TmpDir) !void { | |
| 75 | fn test_link(io: Io, tmp: std.testing.TmpDir) !void { | |
| 69 | 76 | switch (builtin.target.os.tag) { |
| 70 | 77 | .linux, .illumos => {}, |
| 71 | 78 | else => return, |
| ... | ... | @@ -74,17 +81,17 @@ fn test_link(tmp: std.testing.TmpDir) !void { |
| 74 | 81 | const target_name = "link-target"; |
| 75 | 82 | const link_name = "newlink"; |
| 76 | 83 | |
| 77 | try tmp.dir.writeFile(.{ .sub_path = target_name, .data = "example" }); | |
| 84 | try tmp.dir.writeFile(io, .{ .sub_path = target_name, .data = "example" }); | |
| 78 | 85 | |
| 79 | 86 | // Test 1: create the relative link from inside tmp |
| 80 | 87 | try std.posix.link(target_name, link_name); |
| 81 | 88 | |
| 82 | 89 | // Verify |
| 83 | const efd = try tmp.dir.openFile(target_name, .{}); | |
| 84 | defer efd.close(); | |
| 90 | const efd = try tmp.dir.openFile(io, target_name, .{}); | |
| 91 | defer efd.close(io); | |
| 85 | 92 | |
| 86 | const nfd = try tmp.dir.openFile(link_name, .{}); | |
| 87 | defer nfd.close(); | |
| 93 | const nfd = try tmp.dir.openFile(io, link_name, .{}); | |
| 94 | defer nfd.close(io); | |
| 88 | 95 | |
| 89 | 96 | { |
| 90 | 97 | const eino, _ = try getLinkInfo(efd.handle); |
test/standalone/run_cwd/check_file_exists.zig+4-1| ... | ... | @@ -8,7 +8,10 @@ pub fn main() !void { |
| 8 | 8 | if (args.len != 2) return error.BadUsage; |
| 9 | 9 | const path = args[1]; |
| 10 | 10 | |
| 11 | std.fs.cwd().access(path, .{}) catch return error.AccessFailed; | |
| 11 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 12 | const io = threaded.io(); | |
| 13 | ||
| 14 | std.Io.Dir.cwd().access(io, path, .{}) catch return error.AccessFailed; | |
| 12 | 15 | } |
| 13 | 16 | |
| 14 | 17 | const std = @import("std"); |
test/standalone/run_output_caching/main.zig+5-3| ... | ... | @@ -1,10 +1,12 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn main() !void { |
| 4 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 5 | const io = threaded.io(); | |
| 4 | 6 | var args = try std.process.argsWithAllocator(std.heap.page_allocator); |
| 5 | 7 | _ = args.skip(); |
| 6 | 8 | const filename = args.next().?; |
| 7 | const file = try std.fs.cwd().createFile(filename, .{}); | |
| 8 | defer file.close(); | |
| 9 | try file.writeAll(filename); | |
| 9 | const file = try std.Io.Dir.cwd().createFile(io, filename, .{}); | |
| 10 | defer file.close(io); | |
| 11 | try file.writeAll(io, filename); | |
| 10 | 12 | } |
test/standalone/run_output_paths/create_file.zig+3-1| ... | ... | @@ -1,10 +1,12 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn main() !void { |
| 4 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 5 | const io = threaded.io(); | |
| 4 | 6 | var args = try std.process.argsWithAllocator(std.heap.page_allocator); |
| 5 | 7 | _ = args.skip(); |
| 6 | 8 | const dir_name = args.next().?; |
| 7 | const dir = try std.fs.cwd().openDir(if (std.mem.startsWith(u8, dir_name, "--dir=")) | |
| 9 | const dir = try std.Io.Dir.cwd().openDir(io, if (std.mem.startsWith(u8, dir_name, "--dir=")) | |
| 8 | 10 | dir_name["--dir=".len..] |
| 9 | 11 | else |
| 10 | 12 | dir_name, .{}); |
test/standalone/self_exe_symlink/create-symlink.zig+5-1| ... | ... | @@ -14,5 +14,9 @@ pub fn main() anyerror!void { |
| 14 | 14 | // If `exe_path` is relative to our cwd, we need to convert it to be relative to the dirname of `symlink_path`. |
| 15 | 15 | const exe_rel_path = try std.fs.path.relative(allocator, std.fs.path.dirname(symlink_path) orelse ".", exe_path); |
| 16 | 16 | defer allocator.free(exe_rel_path); |
| 17 | try std.fs.cwd().symLink(exe_rel_path, symlink_path, .{}); | |
| 17 | ||
| 18 | var threaded: std.Io.Threaded = .init_single_threaded; | |
| 19 | const io = threaded.io(); | |
| 20 | ||
| 21 | try std.Io.Dir.cwd().symLink(io, exe_rel_path, symlink_path, .{}); | |
| 18 | 22 | } |
test/standalone/self_exe_symlink/main.zig+10-6| ... | ... | @@ -1,15 +1,19 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | 3 | pub fn main() !void { |
| 4 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; | |
| 5 | defer std.debug.assert(gpa.deinit() == .ok); | |
| 6 | const allocator = gpa.allocator(); | |
| 4 | var debug_allocator: std.heap.DebugAllocator(.{}) = .init; | |
| 5 | defer if (debug_allocator.deinit() == .leak) @panic("found memory leaks"); | |
| 6 | const gpa = debug_allocator.allocator(); | |
| 7 | 7 | |
| 8 | const self_path = try std.fs.selfExePathAlloc(allocator); | |
| 9 | defer allocator.free(self_path); | |
| 8 | var threaded: std.Io.Threaded = .init(gpa); | |
| 9 | defer threaded.deinit(); | |
| 10 | const io = threaded.io(); | |
| 11 | ||
| 12 | const self_path = try std.fs.selfExePathAlloc(gpa); | |
| 13 | defer gpa.free(self_path); | |
| 10 | 14 | |
| 11 | 15 | var self_exe = try std.fs.openSelfExe(.{}); |
| 12 | defer self_exe.close(); | |
| 16 | defer self_exe.close(io); | |
| 13 | 17 | var buf: [std.fs.max_path_bytes]u8 = undefined; |
| 14 | 18 | const self_exe_path = try std.os.getFdPath(self_exe.handle, &buf); |
| 15 | 19 |
test/standalone/simple/cat/main.zig+3-3| ... | ... | @@ -18,7 +18,7 @@ pub fn main() !void { |
| 18 | 18 | const exe = args[0]; |
| 19 | 19 | var catted_anything = false; |
| 20 | 20 | var stdout_buffer: [4096]u8 = undefined; |
| 21 | var stdout_writer = Io.File.stdout().writerStreaming(&stdout_buffer); | |
| 21 | var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); | |
| 22 | 22 | const stdout = &stdout_writer.interface; |
| 23 | 23 | var stdin_reader = Io.File.stdin().readerStreaming(io, &.{}); |
| 24 | 24 | |
| ... | ... | @@ -32,8 +32,8 @@ pub fn main() !void { |
| 32 | 32 | } else if (mem.startsWith(u8, arg, "-")) { |
| 33 | 33 | return usage(exe); |
| 34 | 34 | } else { |
| 35 | const file = cwd.openFile(arg, .{}) catch |err| fatal("unable to open file: {t}\n", .{err}); | |
| 36 | defer file.close(); | |
| 35 | const file = cwd.openFile(io, arg, .{}) catch |err| fatal("unable to open file: {t}\n", .{err}); | |
| 36 | defer file.close(io); | |
| 37 | 37 | |
| 38 | 38 | catted_anything = true; |
| 39 | 39 | var file_reader = file.reader(io, &.{}); |
test/standalone/windows_spawn/main.zig+62-58| ... | ... | @@ -1,15 +1,20 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const Io = std.Io; |
| 3 | const Allocator = std.mem.Allocator; | |
| 3 | 4 | |
| 4 | 5 | const windows = std.os.windows; |
| 5 | 6 | const utf16Literal = std.unicode.utf8ToUtf16LeStringLiteral; |
| 6 | 7 | |
| 7 | 8 | pub fn main() anyerror!void { |
| 8 | var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; | |
| 9 | defer if (gpa.deinit() == .leak) @panic("found memory leaks"); | |
| 10 | const allocator = gpa.allocator(); | |
| 9 | var debug_allocator: std.heap.DebugAllocator(.{}) = .init; | |
| 10 | defer if (debug_allocator.deinit() == .leak) @panic("found memory leaks"); | |
| 11 | const gpa = debug_allocator.allocator(); | |
| 11 | 12 | |
| 12 | var it = try std.process.argsWithAllocator(allocator); | |
| 13 | var threaded: std.Io.Threaded = .init(gpa); | |
| 14 | defer threaded.deinit(); | |
| 15 | const io = threaded.io(); | |
| 16 | ||
| 17 | var it = try std.process.argsWithAllocator(gpa); | |
| 13 | 18 | defer it.deinit(); |
| 14 | 19 | _ = it.next() orelse unreachable; // skip binary name |
| 15 | 20 | const hello_exe_cache_path = it.next() orelse unreachable; |
| ... | ... | @@ -17,14 +22,14 @@ pub fn main() anyerror!void { |
| 17 | 22 | var tmp = std.testing.tmpDir(.{}); |
| 18 | 23 | defer tmp.cleanup(); |
| 19 | 24 | |
| 20 | const tmp_absolute_path = try tmp.dir.realpathAlloc(allocator, "."); | |
| 21 | defer allocator.free(tmp_absolute_path); | |
| 22 | const tmp_absolute_path_w = try std.unicode.utf8ToUtf16LeAllocZ(allocator, tmp_absolute_path); | |
| 23 | defer allocator.free(tmp_absolute_path_w); | |
| 24 | const cwd_absolute_path = try std.fs.cwd().realpathAlloc(allocator, "."); | |
| 25 | defer allocator.free(cwd_absolute_path); | |
| 26 | const tmp_relative_path = try std.fs.path.relative(allocator, cwd_absolute_path, tmp_absolute_path); | |
| 27 | defer allocator.free(tmp_relative_path); | |
| 25 | const tmp_absolute_path = try tmp.dir.realpathAlloc(gpa, "."); | |
| 26 | defer gpa.free(tmp_absolute_path); | |
| 27 | const tmp_absolute_path_w = try std.unicode.utf8ToUtf16LeAllocZ(gpa, tmp_absolute_path); | |
| 28 | defer gpa.free(tmp_absolute_path_w); | |
| 29 | const cwd_absolute_path = try Io.Dir.cwd().realpathAlloc(gpa, "."); | |
| 30 | defer gpa.free(cwd_absolute_path); | |
| 31 | const tmp_relative_path = try std.fs.path.relative(gpa, cwd_absolute_path, tmp_absolute_path); | |
| 32 | defer gpa.free(tmp_relative_path); | |
| 28 | 33 | |
| 29 | 34 | // Clear PATH |
| 30 | 35 | std.debug.assert(windows.kernel32.SetEnvironmentVariableW( |
| ... | ... | @@ -39,10 +44,10 @@ pub fn main() anyerror!void { |
| 39 | 44 | ) == windows.TRUE); |
| 40 | 45 | |
| 41 | 46 | // No PATH, so it should fail to find anything not in the cwd |
| 42 | try testExecError(error.FileNotFound, allocator, "something_missing"); | |
| 47 | try testExecError(error.FileNotFound, gpa, "something_missing"); | |
| 43 | 48 | |
| 44 | 49 | // make sure we don't get error.BadPath traversing out of cwd with a relative path |
| 45 | try testExecError(error.FileNotFound, allocator, "..\\.\\.\\.\\\\..\\more_missing"); | |
| 50 | try testExecError(error.FileNotFound, gpa, "..\\.\\.\\.\\\\..\\more_missing"); | |
| 46 | 51 | |
| 47 | 52 | std.debug.assert(windows.kernel32.SetEnvironmentVariableW( |
| 48 | 53 | utf16Literal("PATH"), |
| ... | ... | @@ -50,14 +55,14 @@ pub fn main() anyerror!void { |
| 50 | 55 | ) == windows.TRUE); |
| 51 | 56 | |
| 52 | 57 | // Move hello.exe into the tmp dir which is now added to the path |
| 53 | try std.fs.cwd().copyFile(hello_exe_cache_path, tmp.dir, "hello.exe", .{}); | |
| 58 | try Io.Dir.cwd().copyFile(hello_exe_cache_path, tmp.dir, "hello.exe", .{}); | |
| 54 | 59 | |
| 55 | 60 | // with extension should find the .exe (case insensitive) |
| 56 | try testExec(allocator, "HeLLo.exe", "hello from exe\n"); | |
| 61 | try testExec(gpa, "HeLLo.exe", "hello from exe\n"); | |
| 57 | 62 | // without extension should find the .exe (case insensitive) |
| 58 | try testExec(allocator, "heLLo", "hello from exe\n"); | |
| 63 | try testExec(gpa, "heLLo", "hello from exe\n"); | |
| 59 | 64 | // with invalid cwd |
| 60 | try std.testing.expectError(error.FileNotFound, testExecWithCwd(allocator, "hello.exe", "missing_dir", "")); | |
| 65 | try std.testing.expectError(error.FileNotFound, testExecWithCwd(gpa, io, "hello.exe", "missing_dir", "")); | |
| 61 | 66 | |
| 62 | 67 | // now add a .bat |
| 63 | 68 | try tmp.dir.writeFile(.{ .sub_path = "hello.bat", .data = "@echo hello from bat" }); |
| ... | ... | @@ -65,33 +70,33 @@ pub fn main() anyerror!void { |
| 65 | 70 | try tmp.dir.writeFile(.{ .sub_path = "hello.cmd", .data = "@echo hello from cmd" }); |
| 66 | 71 | |
| 67 | 72 | // with extension should find the .bat (case insensitive) |
| 68 | try testExec(allocator, "heLLo.bat", "hello from bat\r\n"); | |
| 73 | try testExec(gpa, "heLLo.bat", "hello from bat\r\n"); | |
| 69 | 74 | // with extension should find the .cmd (case insensitive) |
| 70 | try testExec(allocator, "heLLo.cmd", "hello from cmd\r\n"); | |
| 75 | try testExec(gpa, "heLLo.cmd", "hello from cmd\r\n"); | |
| 71 | 76 | // without extension should find the .exe (since its first in PATHEXT) |
| 72 | try testExec(allocator, "heLLo", "hello from exe\n"); | |
| 77 | try testExec(gpa, "heLLo", "hello from exe\n"); | |
| 73 | 78 | |
| 74 | 79 | // now rename the exe to not have an extension |
| 75 | 80 | try renameExe(tmp.dir, "hello.exe", "hello"); |
| 76 | 81 | |
| 77 | 82 | // with extension should now fail |
| 78 | try testExecError(error.FileNotFound, allocator, "hello.exe"); | |
| 83 | try testExecError(error.FileNotFound, gpa, "hello.exe"); | |
| 79 | 84 | // without extension should succeed (case insensitive) |
| 80 | try testExec(allocator, "heLLo", "hello from exe\n"); | |
| 85 | try testExec(gpa, "heLLo", "hello from exe\n"); | |
| 81 | 86 | |
| 82 | 87 | try tmp.dir.makeDir("something"); |
| 83 | 88 | try renameExe(tmp.dir, "hello", "something/hello.exe"); |
| 84 | 89 | |
| 85 | const relative_path_no_ext = try std.fs.path.join(allocator, &.{ tmp_relative_path, "something/hello" }); | |
| 86 | defer allocator.free(relative_path_no_ext); | |
| 90 | const relative_path_no_ext = try std.fs.path.join(gpa, &.{ tmp_relative_path, "something/hello" }); | |
| 91 | defer gpa.free(relative_path_no_ext); | |
| 87 | 92 | |
| 88 | 93 | // Giving a full relative path to something/hello should work |
| 89 | try testExec(allocator, relative_path_no_ext, "hello from exe\n"); | |
| 94 | try testExec(gpa, relative_path_no_ext, "hello from exe\n"); | |
| 90 | 95 | // But commands with path separators get excluded from PATH searching, so this will fail |
| 91 | try testExecError(error.FileNotFound, allocator, "something/hello"); | |
| 96 | try testExecError(error.FileNotFound, gpa, "something/hello"); | |
| 92 | 97 | |
| 93 | 98 | // Now that .BAT is the first PATHEXT that should be found, this should succeed |
| 94 | try testExec(allocator, "heLLo", "hello from bat\r\n"); | |
| 99 | try testExec(gpa, "heLLo", "hello from bat\r\n"); | |
| 95 | 100 | |
| 96 | 101 | // Add a hello.exe that is not a valid executable |
| 97 | 102 | try tmp.dir.writeFile(.{ .sub_path = "hello.exe", .data = "invalid" }); |
| ... | ... | @@ -100,18 +105,18 @@ pub fn main() anyerror!void { |
| 100 | 105 | // case for .EXE extensions, where if they ever try to get executed but they are |
| 101 | 106 | // invalid, that gets treated as a fatal error wherever they are found and InvalidExe |
| 102 | 107 | // is returned immediately. |
| 103 | try testExecError(error.InvalidExe, allocator, "hello.exe"); | |
| 108 | try testExecError(error.InvalidExe, gpa, "hello.exe"); | |
| 104 | 109 | // Same thing applies to the command with no extension--even though there is a |
| 105 | 110 | // hello.bat that could be executed, it should stop after it tries executing |
| 106 | 111 | // hello.exe and getting InvalidExe. |
| 107 | try testExecError(error.InvalidExe, allocator, "hello"); | |
| 112 | try testExecError(error.InvalidExe, gpa, "hello"); | |
| 108 | 113 | |
| 109 | 114 | // If we now rename hello.exe to have no extension, it will behave differently |
| 110 | 115 | try renameExe(tmp.dir, "hello.exe", "hello"); |
| 111 | 116 | |
| 112 | 117 | // Now, trying to execute it without an extension should treat InvalidExe as recoverable |
| 113 | 118 | // and skip over it and find hello.bat and execute that |
| 114 | try testExec(allocator, "hello", "hello from bat\r\n"); | |
| 119 | try testExec(gpa, "hello", "hello from bat\r\n"); | |
| 115 | 120 | |
| 116 | 121 | // If we rename the invalid exe to something else |
| 117 | 122 | try renameExe(tmp.dir, "hello", "goodbye"); |
| ... | ... | @@ -119,13 +124,13 @@ pub fn main() anyerror!void { |
| 119 | 124 | // since that is what the original error will be after searching for 'goodbye' |
| 120 | 125 | // in the cwd. It will try to execute 'goodbye' from the PATH but the InvalidExe error |
| 121 | 126 | // should be ignored in this case. |
| 122 | try testExecError(error.FileNotFound, allocator, "goodbye"); | |
| 127 | try testExecError(error.FileNotFound, gpa, "goodbye"); | |
| 123 | 128 | |
| 124 | 129 | // Now let's set the tmp dir as the cwd and set the path only include the "something" sub dir |
| 125 | 130 | try tmp.dir.setAsCwd(); |
| 126 | 131 | defer tmp.parent_dir.setAsCwd() catch {}; |
| 127 | const something_subdir_abs_path = try std.mem.concatWithSentinel(allocator, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0); | |
| 128 | defer allocator.free(something_subdir_abs_path); | |
| 132 | const something_subdir_abs_path = try std.mem.concatWithSentinel(gpa, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0); | |
| 133 | defer gpa.free(something_subdir_abs_path); | |
| 129 | 134 | |
| 130 | 135 | std.debug.assert(windows.kernel32.SetEnvironmentVariableW( |
| 131 | 136 | utf16Literal("PATH"), |
| ... | ... | @@ -134,37 +139,37 @@ pub fn main() anyerror!void { |
| 134 | 139 | |
| 135 | 140 | // Now trying to execute goodbye should give error.InvalidExe since it's the original |
| 136 | 141 | // error that we got when trying within the cwd |
| 137 | try testExecError(error.InvalidExe, allocator, "goodbye"); | |
| 142 | try testExecError(error.InvalidExe, gpa, "goodbye"); | |
| 138 | 143 | |
| 139 | 144 | // hello should still find the .bat |
| 140 | try testExec(allocator, "hello", "hello from bat\r\n"); | |
| 145 | try testExec(gpa, "hello", "hello from bat\r\n"); | |
| 141 | 146 | |
| 142 | 147 | // If we rename something/hello.exe to something/goodbye.exe |
| 143 | 148 | try renameExe(tmp.dir, "something/hello.exe", "something/goodbye.exe"); |
| 144 | 149 | // And try to execute goodbye, then the one in something should be found |
| 145 | 150 | // since the one in cwd is an invalid executable |
| 146 | try testExec(allocator, "goodbye", "hello from exe\n"); | |
| 151 | try testExec(gpa, "goodbye", "hello from exe\n"); | |
| 147 | 152 | |
| 148 | 153 | // If we use an absolute path to execute the invalid goodbye |
| 149 | const goodbye_abs_path = try std.mem.join(allocator, "\\", &.{ tmp_absolute_path, "goodbye" }); | |
| 150 | defer allocator.free(goodbye_abs_path); | |
| 154 | const goodbye_abs_path = try std.mem.join(gpa, "\\", &.{ tmp_absolute_path, "goodbye" }); | |
| 155 | defer gpa.free(goodbye_abs_path); | |
| 151 | 156 | // then the PATH should not be searched and we should get InvalidExe |
| 152 | try testExecError(error.InvalidExe, allocator, goodbye_abs_path); | |
| 157 | try testExecError(error.InvalidExe, gpa, goodbye_abs_path); | |
| 153 | 158 | |
| 154 | 159 | // If we try to exec but provide a cwd that is an absolute path, the PATH |
| 155 | 160 | // should still be searched and the goodbye.exe in something should be found. |
| 156 | try testExecWithCwd(allocator, "goodbye", tmp_absolute_path, "hello from exe\n"); | |
| 161 | try testExecWithCwd(gpa, "goodbye", tmp_absolute_path, "hello from exe\n"); | |
| 157 | 162 | |
| 158 | 163 | // introduce some extra path separators into the path which is dealt with inside the spawn call. |
| 159 | 164 | const denormed_something_subdir_size = std.mem.replacementSize(u16, something_subdir_abs_path, utf16Literal("\\"), utf16Literal("\\\\\\\\")); |
| 160 | 165 | |
| 161 | const denormed_something_subdir_abs_path = try allocator.allocSentinel(u16, denormed_something_subdir_size, 0); | |
| 162 | defer allocator.free(denormed_something_subdir_abs_path); | |
| 166 | const denormed_something_subdir_abs_path = try gpa.allocSentinel(u16, denormed_something_subdir_size, 0); | |
| 167 | defer gpa.free(denormed_something_subdir_abs_path); | |
| 163 | 168 | |
| 164 | 169 | _ = std.mem.replace(u16, something_subdir_abs_path, utf16Literal("\\"), utf16Literal("\\\\\\\\"), denormed_something_subdir_abs_path); |
| 165 | 170 | |
| 166 | const denormed_something_subdir_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(allocator, denormed_something_subdir_abs_path); | |
| 167 | defer allocator.free(denormed_something_subdir_wtf8); | |
| 171 | const denormed_something_subdir_wtf8 = try std.unicode.wtf16LeToWtf8Alloc(gpa, denormed_something_subdir_abs_path); | |
| 172 | defer gpa.free(denormed_something_subdir_wtf8); | |
| 168 | 173 | |
| 169 | 174 | // clear the path to ensure that the match comes from the cwd |
| 170 | 175 | std.debug.assert(windows.kernel32.SetEnvironmentVariableW( |
| ... | ... | @@ -172,18 +177,18 @@ pub fn main() anyerror!void { |
| 172 | 177 | null, |
| 173 | 178 | ) == windows.TRUE); |
| 174 | 179 | |
| 175 | try testExecWithCwd(allocator, "goodbye", denormed_something_subdir_wtf8, "hello from exe\n"); | |
| 180 | try testExecWithCwd(gpa, "goodbye", denormed_something_subdir_wtf8, "hello from exe\n"); | |
| 176 | 181 | |
| 177 | 182 | // normalization should also work if the non-normalized path is found in the PATH var. |
| 178 | 183 | std.debug.assert(windows.kernel32.SetEnvironmentVariableW( |
| 179 | 184 | utf16Literal("PATH"), |
| 180 | 185 | denormed_something_subdir_abs_path, |
| 181 | 186 | ) == windows.TRUE); |
| 182 | try testExec(allocator, "goodbye", "hello from exe\n"); | |
| 187 | try testExec(gpa, "goodbye", "hello from exe\n"); | |
| 183 | 188 | |
| 184 | 189 | // now make sure we can launch executables "outside" of the cwd |
| 185 | 190 | var subdir_cwd = try tmp.dir.openDir(denormed_something_subdir_wtf8, .{}); |
| 186 | defer subdir_cwd.close(); | |
| 191 | defer subdir_cwd.close(io); | |
| 187 | 192 | |
| 188 | 193 | try renameExe(tmp.dir, "something/goodbye.exe", "hello.exe"); |
| 189 | 194 | try subdir_cwd.setAsCwd(); |
| ... | ... | @@ -195,25 +200,24 @@ pub fn main() anyerror!void { |
| 195 | 200 | ) == windows.TRUE); |
| 196 | 201 | |
| 197 | 202 | // while we're at it make sure non-windows separators work fine |
| 198 | try testExec(allocator, "../hello", "hello from exe\n"); | |
| 203 | try testExec(gpa, "../hello", "hello from exe\n"); | |
| 199 | 204 | } |
| 200 | 205 | |
| 201 | fn testExecError(err: anyerror, allocator: std.mem.Allocator, command: []const u8) !void { | |
| 202 | return std.testing.expectError(err, testExec(allocator, command, "")); | |
| 206 | fn testExecError(err: anyerror, gpa: Allocator, command: []const u8) !void { | |
| 207 | return std.testing.expectError(err, testExec(gpa, command, "")); | |
| 203 | 208 | } |
| 204 | 209 | |
| 205 | fn testExec(allocator: std.mem.Allocator, command: []const u8, expected_stdout: []const u8) !void { | |
| 206 | return testExecWithCwd(allocator, command, null, expected_stdout); | |
| 210 | fn testExec(gpa: Allocator, command: []const u8, expected_stdout: []const u8) !void { | |
| 211 | return testExecWithCwd(gpa, command, null, expected_stdout); | |
| 207 | 212 | } |
| 208 | 213 | |
| 209 | fn testExecWithCwd(allocator: std.mem.Allocator, command: []const u8, cwd: ?[]const u8, expected_stdout: []const u8) !void { | |
| 210 | const result = try std.process.Child.run(.{ | |
| 211 | .allocator = allocator, | |
| 214 | fn testExecWithCwd(gpa: Allocator, io: Io, command: []const u8, cwd: ?[]const u8, expected_stdout: []const u8) !void { | |
| 215 | const result = try std.process.Child.run(gpa, io, .{ | |
| 212 | 216 | .argv = &[_][]const u8{command}, |
| 213 | 217 | .cwd = cwd, |
| 214 | 218 | }); |
| 215 | defer allocator.free(result.stdout); | |
| 216 | defer allocator.free(result.stderr); | |
| 219 | defer gpa.free(result.stdout); | |
| 220 | defer gpa.free(result.stderr); | |
| 217 | 221 | |
| 218 | 222 | try std.testing.expectEqualStrings("", result.stderr); |
| 219 | 223 | try std.testing.expectEqualStrings(expected_stdout, result.stdout); |
test/tests.zig+11-8| ... | ... | @@ -2024,6 +2024,7 @@ pub fn addLinkTests( |
| 2024 | 2024 | pub fn addCliTests(b: *std.Build) *Step { |
| 2025 | 2025 | const step = b.step("test-cli", "Test the command line interface"); |
| 2026 | 2026 | const s = std.fs.path.sep_str; |
| 2027 | const io = b.graph.io; | |
| 2027 | 2028 | |
| 2028 | 2029 | { |
| 2029 | 2030 | // Test `zig init`. |
| ... | ... | @@ -2132,13 +2133,13 @@ pub fn addCliTests(b: *std.Build) *Step { |
| 2132 | 2133 | const tmp_path = b.makeTempPath(); |
| 2133 | 2134 | const unformatted_code = " // no reason for indent"; |
| 2134 | 2135 | |
| 2135 | var dir = std.fs.cwd().openDir(tmp_path, .{}) catch @panic("unhandled"); | |
| 2136 | defer dir.close(); | |
| 2136 | var dir = std.Io.Dir.cwd().openDir(io, tmp_path, .{}) catch @panic("unhandled"); | |
| 2137 | defer dir.close(io); | |
| 2137 | 2138 | dir.writeFile(.{ .sub_path = "fmt1.zig", .data = unformatted_code }) catch @panic("unhandled"); |
| 2138 | 2139 | dir.writeFile(.{ .sub_path = "fmt2.zig", .data = unformatted_code }) catch @panic("unhandled"); |
| 2139 | 2140 | dir.makeDir("subdir") catch @panic("unhandled"); |
| 2140 | var subdir = dir.openDir("subdir", .{}) catch @panic("unhandled"); | |
| 2141 | defer subdir.close(); | |
| 2141 | var subdir = dir.openDir(io, "subdir", .{}) catch @panic("unhandled"); | |
| 2142 | defer subdir.close(io); | |
| 2142 | 2143 | subdir.writeFile(.{ .sub_path = "fmt3.zig", .data = unformatted_code }) catch @panic("unhandled"); |
| 2143 | 2144 | |
| 2144 | 2145 | // Test zig fmt affecting only the appropriate files. |
| ... | ... | @@ -2634,7 +2635,7 @@ pub fn addCases( |
| 2634 | 2635 | var cases = @import("src/Cases.zig").init(gpa, arena); |
| 2635 | 2636 | |
| 2636 | 2637 | var dir = try b.build_root.handle.openDir(io, "test/cases", .{ .iterate = true }); |
| 2637 | defer dir.close(); | |
| 2638 | defer dir.close(io); | |
| 2638 | 2639 | |
| 2639 | 2640 | cases.addFromDir(dir, b); |
| 2640 | 2641 | try @import("cases.zig").addCases(&cases, build_options, b); |
| ... | ... | @@ -2680,6 +2681,8 @@ pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step |
| 2680 | 2681 | } |
| 2681 | 2682 | |
| 2682 | 2683 | pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void { |
| 2684 | const io = b.graph.io; | |
| 2685 | ||
| 2683 | 2686 | const incr_check = b.addExecutable(.{ |
| 2684 | 2687 | .name = "incr-check", |
| 2685 | 2688 | .root_module = b.createModule(.{ |
| ... | ... | @@ -2689,11 +2692,11 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void { |
| 2689 | 2692 | }), |
| 2690 | 2693 | }); |
| 2691 | 2694 | |
| 2692 | var dir = try b.build_root.handle.openDir("test/incremental", .{ .iterate = true }); | |
| 2693 | defer dir.close(); | |
| 2695 | var dir = try b.build_root.handle.openDir(io, "test/incremental", .{ .iterate = true }); | |
| 2696 | defer dir.close(io); | |
| 2694 | 2697 | |
| 2695 | 2698 | var it = try dir.walk(b.graph.arena); |
| 2696 | while (try it.next()) |entry| { | |
| 2699 | while (try it.next(io)) |entry| { | |
| 2697 | 2700 | if (entry.kind != .file) continue; |
| 2698 | 2701 | |
| 2699 | 2702 | const run = b.addRunArtifact(incr_check); |