master
 1const std = @import("std");
 2const builtin = @import("builtin");
 3
 4const path_max = std.fs.max_path_bytes;
 5
 6pub fn main() !void {
 7    if (builtin.target.os.tag == .wasi) {
 8        // WASI doesn't support changing the working directory at all.
 9        return;
10    }
11
12    var Allocator = std.heap.DebugAllocator(.{}){};
13    const a = Allocator.allocator();
14    defer std.debug.assert(Allocator.deinit() == .ok);
15
16    try test_chdir_self();
17    try test_chdir_absolute();
18    try test_chdir_relative(a);
19}
20
21// get current working directory and expect it to match given path
22fn expect_cwd(expected_cwd: []const u8) !void {
23    var cwd_buf: [path_max]u8 = undefined;
24    const actual_cwd = try std.posix.getcwd(cwd_buf[0..]);
25    try std.testing.expectEqualStrings(actual_cwd, expected_cwd);
26}
27
28fn test_chdir_self() !void {
29    var old_cwd_buf: [path_max]u8 = undefined;
30    const old_cwd = try std.posix.getcwd(old_cwd_buf[0..]);
31
32    // Try changing to the current directory
33    try std.posix.chdir(old_cwd);
34    try expect_cwd(old_cwd);
35}
36
37fn test_chdir_absolute() !void {
38    var old_cwd_buf: [path_max]u8 = undefined;
39    const old_cwd = try std.posix.getcwd(old_cwd_buf[0..]);
40
41    const parent = std.fs.path.dirname(old_cwd) orelse unreachable; // old_cwd should be absolute
42
43    // Try changing to the parent via a full path
44    try std.posix.chdir(parent);
45
46    try expect_cwd(parent);
47}
48
49fn test_chdir_relative(a: std.mem.Allocator) !void {
50    var tmp = std.testing.tmpDir(.{});
51    defer tmp.cleanup();
52
53    // Use the tmpDir parent_dir as the "base" for the test. Then cd into the child
54    try tmp.parent_dir.setAsCwd();
55
56    // Capture base working directory path, to build expected full path
57    var base_cwd_buf: [path_max]u8 = undefined;
58    const base_cwd = try std.posix.getcwd(base_cwd_buf[0..]);
59
60    const relative_dir_name = &tmp.sub_path;
61    const expected_path = try std.fs.path.resolve(a, &.{ base_cwd, relative_dir_name });
62    defer a.free(expected_path);
63
64    // change current working directory to new test directory
65    try std.posix.chdir(relative_dir_name);
66
67    var new_cwd_buf: [path_max]u8 = undefined;
68    const new_cwd = try std.posix.getcwd(new_cwd_buf[0..]);
69
70    // On Windows, fs.path.resolve returns an uppercase drive letter, but the drive letter returned by getcwd may be lowercase
71    const resolved_cwd = try std.fs.path.resolve(a, &.{new_cwd});
72    defer a.free(resolved_cwd);
73
74    try std.testing.expectEqualStrings(expected_path, resolved_cwd);
75}