| author | |
| committer | |
| log | a0af3c7a19c8f60f740e9a8c178ce19d85b26256 |
| tree | f1dca4f8c42e8fbd1a57e8a5bf991a53fcc0b02f |
| parent | 304e828088f0b03d47f7b0b3df7b1449c0a1f2d6 |
Test coverage was lacking for chdir() on WASI, allowing this to
regress.
This change makes os.chdir() compile again, and improves the test
logic to use our standard CWD support for WASI.3 files changed, 38 insertions(+), 22 deletions(-)
lib/std/os.zig+6-2| ... | @@ -2999,15 +2999,19 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void { | ... | @@ -2999,15 +2999,19 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void { |
| 2999 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2999 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 3000 | var buf: [MAX_PATH_BYTES]u8 = undefined; | 3000 | var buf: [MAX_PATH_BYTES]u8 = undefined; |
| 3001 | var alloc = std.heap.FixedBufferAllocator.init(&buf); | 3001 | var alloc = std.heap.FixedBufferAllocator.init(&buf); |
| 3002 | const path = try fs.resolve(alloc.allocator(), &.{ wasi_cwd.cwd, dir_path }); | 3002 | const path = fs.path.resolve(alloc.allocator(), &.{ wasi_cwd.cwd, dir_path }) catch |err| switch (err) { |
| 3003 | error.OutOfMemory => return error.NameTooLong, | ||
| 3004 | else => |e| return e, | ||
| 3005 | }; | ||
| 3003 | 3006 | ||
| 3004 | const dirinfo = try fstatat(AT.FDCWD, path, 0); | 3007 | const dirinfo = try fstatat(AT.FDCWD, path, 0); |
| 3005 | if (dirinfo.filetype != .DIRECTORY) { | 3008 | if (dirinfo.filetype != .DIRECTORY) { |
| 3006 | return error.NotDir; | 3009 | return error.NotDir; |
| 3007 | } | 3010 | } |
| 3008 | 3011 | ||
| 3012 | // This copy is guaranteed to succeed, since buf and path_buffer are the same size. | ||
| 3009 | var cwd_alloc = std.heap.FixedBufferAllocator.init(&wasi_cwd.path_buffer); | 3013 | var cwd_alloc = std.heap.FixedBufferAllocator.init(&wasi_cwd.path_buffer); |
| 3010 | wasi_cwd.cwd = try cwd_alloc.allocator().dupe(u8, path); | 3014 | wasi_cwd.cwd = cwd_alloc.allocator().dupe(u8, path) catch unreachable; |
| 3011 | return; | 3015 | return; |
| 3012 | } else if (builtin.os.tag == .windows) { | 3016 | } else if (builtin.os.tag == .windows) { |
| 3013 | var utf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined; | 3017 | var utf16_dir_path: [windows.PATH_MAX_WIDE]u16 = undefined; |
lib/std/os/test.zig+30-3| ... | @@ -22,7 +22,8 @@ const Dir = std.fs.Dir; | ... | @@ -22,7 +22,8 @@ const Dir = std.fs.Dir; |
| 22 | const ArenaAllocator = std.heap.ArenaAllocator; | 22 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 23 | 23 | ||
| 24 | test "chdir smoke test" { | 24 | test "chdir smoke test" { |
| 25 | if (native_os == .wasi) return error.SkipZigTest; // WASI doesn't allow navigating outside of a preopen | 25 | if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest; |
| 26 | if (native_os == .wasi and !builtin.link_libc) try os.initPreopensWasi(std.heap.page_allocator, "/preopens/cwd"); | ||
| 26 | 27 | ||
| 27 | // Get current working directory path | 28 | // Get current working directory path |
| 28 | var old_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined; | 29 | var old_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined; |
| ... | @@ -35,16 +36,42 @@ test "chdir smoke test" { | ... | @@ -35,16 +36,42 @@ test "chdir smoke test" { |
| 35 | const new_cwd = try os.getcwd(new_cwd_buf[0..]); | 36 | const new_cwd = try os.getcwd(new_cwd_buf[0..]); |
| 36 | try expect(mem.eql(u8, old_cwd, new_cwd)); | 37 | try expect(mem.eql(u8, old_cwd, new_cwd)); |
| 37 | } | 38 | } |
| 38 | { | 39 | |
| 39 | // Next, change current working directory to one level above | 40 | // Next, change current working directory to one level above |
| 41 | if (native_os != .wasi) { // WASI does not support navigating outside of Preopens | ||
| 40 | const parent = fs.path.dirname(old_cwd) orelse unreachable; // old_cwd should be absolute | 42 | const parent = fs.path.dirname(old_cwd) orelse unreachable; // old_cwd should be absolute |
| 41 | try os.chdir(parent); | 43 | try os.chdir(parent); |
| 44 | |||
| 42 | // Restore cwd because process may have other tests that do not tolerate chdir. | 45 | // Restore cwd because process may have other tests that do not tolerate chdir. |
| 43 | defer os.chdir(old_cwd) catch unreachable; | 46 | defer os.chdir(old_cwd) catch unreachable; |
| 47 | |||
| 44 | var new_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined; | 48 | var new_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined; |
| 45 | const new_cwd = try os.getcwd(new_cwd_buf[0..]); | 49 | const new_cwd = try os.getcwd(new_cwd_buf[0..]); |
| 46 | try expect(mem.eql(u8, parent, new_cwd)); | 50 | try expect(mem.eql(u8, parent, new_cwd)); |
| 47 | } | 51 | } |
| 52 | |||
| 53 | // Next, change current working directory to a temp directory one level below | ||
| 54 | { | ||
| 55 | // Create a tmp directory | ||
| 56 | var tmp_dir_buf: [fs.MAX_PATH_BYTES]u8 = undefined; | ||
| 57 | var tmp_dir_path = path: { | ||
| 58 | var allocator = std.heap.FixedBufferAllocator.init(&tmp_dir_buf); | ||
| 59 | break :path try fs.path.resolve(allocator.allocator(), &[_][]const u8{ old_cwd, "zig-test-tmp" }); | ||
| 60 | }; | ||
| 61 | var tmp_dir = try fs.cwd().makeOpenPath("zig-test-tmp", .{}); | ||
| 62 | |||
| 63 | // Change current working directory to tmp directory | ||
| 64 | try os.chdir("zig-test-tmp"); | ||
| 65 | |||
| 66 | var new_cwd_buf: [fs.MAX_PATH_BYTES]u8 = undefined; | ||
| 67 | const new_cwd = try os.getcwd(new_cwd_buf[0..]); | ||
| 68 | try expect(mem.eql(u8, tmp_dir_path, new_cwd)); | ||
| 69 | |||
| 70 | // Restore cwd because process may have other tests that do not tolerate chdir. | ||
| 71 | tmp_dir.close(); | ||
| 72 | os.chdir(old_cwd) catch unreachable; | ||
| 73 | try fs.cwd().deleteDir("zig-test-tmp"); | ||
| 74 | } | ||
| 48 | } | 75 | } |
| 49 | 76 | ||
| 50 | test "open smoke test" { | 77 | test "open smoke test" { |
lib/std/testing.zig+2-17| ... | @@ -379,28 +379,13 @@ pub const TmpIterableDir = struct { | ... | @@ -379,28 +379,13 @@ pub const TmpIterableDir = struct { |
| 379 | } | 379 | } |
| 380 | }; | 380 | }; |
| 381 | 381 | ||
| 382 | fn getCwdOrWasiPreopen() std.fs.Dir { | ||
| 383 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | ||
| 384 | var preopens = std.fs.wasi.PreopenList.init(allocator); | ||
| 385 | defer preopens.deinit(); | ||
| 386 | preopens.populate(null) catch | ||
| 387 | @panic("unable to make tmp dir for testing: unable to populate preopens"); | ||
| 388 | const preopen = preopens.find(std.fs.wasi.PreopenType{ .Dir = "." }) orelse | ||
| 389 | @panic("unable to make tmp dir for testing: didn't find '.' in the preopens"); | ||
| 390 | |||
| 391 | return std.fs.Dir{ .fd = preopen.fd }; | ||
| 392 | } else { | ||
| 393 | return std.fs.cwd(); | ||
| 394 | } | ||
| 395 | } | ||
| 396 | |||
| 397 | pub fn tmpDir(opts: std.fs.Dir.OpenDirOptions) TmpDir { | 382 | pub fn tmpDir(opts: std.fs.Dir.OpenDirOptions) TmpDir { |
| 398 | var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; | 383 | var random_bytes: [TmpDir.random_bytes_count]u8 = undefined; |
| 399 | std.crypto.random.bytes(&random_bytes); | 384 | std.crypto.random.bytes(&random_bytes); |
| 400 | var sub_path: [TmpDir.sub_path_len]u8 = undefined; | 385 | var sub_path: [TmpDir.sub_path_len]u8 = undefined; |
| 401 | _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); | 386 | _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); |
| 402 | 387 | ||
| 403 | var cwd = getCwdOrWasiPreopen(); | 388 | var cwd = std.fs.cwd(); |
| 404 | var cache_dir = cwd.makeOpenPath("zig-cache", .{}) catch | 389 | var cache_dir = cwd.makeOpenPath("zig-cache", .{}) catch |
| 405 | @panic("unable to make tmp dir for testing: unable to make and open zig-cache dir"); | 390 | @panic("unable to make tmp dir for testing: unable to make and open zig-cache dir"); |
| 406 | defer cache_dir.close(); | 391 | defer cache_dir.close(); |
| ... | @@ -422,7 +407,7 @@ pub fn tmpIterableDir(opts: std.fs.Dir.OpenDirOptions) TmpIterableDir { | ... | @@ -422,7 +407,7 @@ pub fn tmpIterableDir(opts: std.fs.Dir.OpenDirOptions) TmpIterableDir { |
| 422 | var sub_path: [TmpIterableDir.sub_path_len]u8 = undefined; | 407 | var sub_path: [TmpIterableDir.sub_path_len]u8 = undefined; |
| 423 | _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); | 408 | _ = std.fs.base64_encoder.encode(&sub_path, &random_bytes); |
| 424 | 409 | ||
| 425 | var cwd = getCwdOrWasiPreopen(); | 410 | var cwd = std.fs.cwd(); |
| 426 | var cache_dir = cwd.makeOpenPath("zig-cache", .{}) catch | 411 | var cache_dir = cwd.makeOpenPath("zig-cache", .{}) catch |
| 427 | @panic("unable to make tmp dir for testing: unable to make and open zig-cache dir"); | 412 | @panic("unable to make tmp dir for testing: unable to make and open zig-cache dir"); |
| 428 | defer cache_dir.close(); | 413 | defer cache_dir.close(); |