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