Commit 020eb622ee

Pat Tullmann <pat.github@tullmann.org>
2025-09-09 06:31:51
standalone posix test for current working directory
1 parent c614d8d
Changed files (2)
lib
std
posix
test
standalone
posix
lib/std/posix/test.zig
@@ -17,6 +17,9 @@ const AtomicOrder = std.builtin.AtomicOrder;
 const native_os = builtin.target.os.tag;
 const tmpDir = std.testing.tmpDir;
 
+// NOTE: several additional tests are in test/standalone/posix/.  Any tests that mutate
+// process-wide POSIX state (cwd, signals, etc) cannot be Zig unit tests and should be over there.
+
 // https://github.com/ziglang/zig/issues/20288
 test "WTF-8 to WTF-16 conversion buffer overflows" {
     if (native_os != .windows) return error.SkipZigTest;
@@ -39,68 +42,6 @@ test "check WASI CWD" {
     }
 }
 
-test "chdir absolute parent" {
-    if (native_os == .wasi) return error.SkipZigTest;
-
-    // Restore default CWD at end of test.
-    const orig_cwd = try fs.cwd().openDir(".", .{});
-    defer orig_cwd.setAsCwd() catch unreachable;
-
-    // Get current working directory path
-    var old_cwd_buf: [fs.max_path_bytes]u8 = undefined;
-    const old_cwd = try posix.getcwd(old_cwd_buf[0..]);
-
-    {
-        // Firstly, changing to itself should have no effect
-        try posix.chdir(old_cwd);
-        var new_cwd_buf: [fs.max_path_bytes]u8 = undefined;
-        const new_cwd = try posix.getcwd(new_cwd_buf[0..]);
-        try expect(mem.eql(u8, old_cwd, new_cwd));
-    }
-
-    // Next, change current working directory to one level above
-    const parent = fs.path.dirname(old_cwd) orelse unreachable; // old_cwd should be absolute
-    try posix.chdir(parent);
-
-    var new_cwd_buf: [fs.max_path_bytes]u8 = undefined;
-    const new_cwd = try posix.getcwd(new_cwd_buf[0..]);
-    try expect(mem.eql(u8, parent, new_cwd));
-}
-
-test "chdir relative" {
-    if (native_os == .wasi) return error.SkipZigTest;
-
-    var tmp = tmpDir(.{});
-    defer tmp.cleanup();
-
-    // Restore default CWD at end of test.
-    const orig_cwd = try fs.cwd().openDir(".", .{});
-    defer orig_cwd.setAsCwd() catch unreachable;
-
-    // Use the tmpDir parent_dir as the "base" for the test. Then cd into the child
-    try tmp.parent_dir.setAsCwd();
-
-    // Capture base working directory path, to build expected full path
-    var base_cwd_buf: [fs.max_path_bytes]u8 = undefined;
-    const base_cwd = try posix.getcwd(base_cwd_buf[0..]);
-
-    const dir_name = &tmp.sub_path;
-    const expected_path = try fs.path.resolve(a, &.{ base_cwd, dir_name });
-    defer a.free(expected_path);
-
-    // change current working directory to new directory
-    try posix.chdir(dir_name);
-
-    var new_cwd_buf: [fs.max_path_bytes]u8 = undefined;
-    const new_cwd = try posix.getcwd(new_cwd_buf[0..]);
-
-    // On Windows, fs.path.resolve returns an uppercase drive letter, but the drive letter returned by getcwd may be lowercase
-    const resolved_cwd = try fs.path.resolve(a, &.{new_cwd});
-    defer a.free(resolved_cwd);
-
-    try expect(mem.eql(u8, expected_path, resolved_cwd));
-}
-
 test "open smoke test" {
     if (native_os == .wasi) return error.SkipZigTest;
     if (native_os == .windows) return error.SkipZigTest;
@@ -455,12 +396,6 @@ test "getrandom" {
     try expect(!mem.eql(u8, &buf_a, &buf_b));
 }
 
-test "getcwd" {
-    // at least call it so it gets compiled
-    var buf: [std.fs.max_path_bytes]u8 = undefined;
-    _ = posix.getcwd(&buf) catch undefined;
-}
-
 test "getuid" {
     if (native_os == .windows or native_os == .wasi) return error.SkipZigTest;
     _ = posix.getuid();
test/standalone/posix/cwd.zig
@@ -1,1 +1,75 @@
-pub fn main() !void {}
+const std = @import("std");
+const builtin = @import("builtin");
+
+const path_max = std.fs.max_path_bytes;
+
+pub fn main() !void {
+    if (builtin.target.os.tag == .wasi) {
+        // WASI doesn't support changing the working directory at all.
+        return;
+    }
+
+    var Allocator = std.heap.DebugAllocator(.{}){};
+    const a = Allocator.allocator();
+    defer std.debug.assert(Allocator.deinit() == .ok);
+
+    try test_chdir_self();
+    try test_chdir_absolute();
+    try test_chdir_relative(a);
+}
+
+// get current working directory and expect it to match given path
+fn expect_cwd(expected_cwd: []const u8) !void {
+    var cwd_buf: [path_max]u8 = undefined;
+    const actual_cwd = try std.posix.getcwd(cwd_buf[0..]);
+    try std.testing.expectEqualStrings(actual_cwd, expected_cwd);
+}
+
+fn test_chdir_self() !void {
+    var old_cwd_buf: [path_max]u8 = undefined;
+    const old_cwd = try std.posix.getcwd(old_cwd_buf[0..]);
+
+    // Try changing to the current directory
+    try std.posix.chdir(old_cwd);
+    try expect_cwd(old_cwd);
+}
+
+fn test_chdir_absolute() !void {
+    var old_cwd_buf: [path_max]u8 = undefined;
+    const old_cwd = try std.posix.getcwd(old_cwd_buf[0..]);
+
+    const parent = std.fs.path.dirname(old_cwd) orelse unreachable; // old_cwd should be absolute
+
+    // Try changing to the parent via a full path
+    try std.posix.chdir(parent);
+
+    try expect_cwd(parent);
+}
+
+fn test_chdir_relative(a: std.mem.Allocator) !void {
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
+    // Use the tmpDir parent_dir as the "base" for the test. Then cd into the child
+    try tmp.parent_dir.setAsCwd();
+
+    // Capture base working directory path, to build expected full path
+    var base_cwd_buf: [path_max]u8 = undefined;
+    const base_cwd = try std.posix.getcwd(base_cwd_buf[0..]);
+
+    const relative_dir_name = &tmp.sub_path;
+    const expected_path = try std.fs.path.resolve(a, &.{ base_cwd, relative_dir_name });
+    defer a.free(expected_path);
+
+    // change current working directory to new test directory
+    try std.posix.chdir(relative_dir_name);
+
+    var new_cwd_buf: [path_max]u8 = undefined;
+    const new_cwd = try std.posix.getcwd(new_cwd_buf[0..]);
+
+    // On Windows, fs.path.resolve returns an uppercase drive letter, but the drive letter returned by getcwd may be lowercase
+    const resolved_cwd = try std.fs.path.resolve(a, &.{new_cwd});
+    defer a.free(resolved_cwd);
+
+    try std.testing.expectEqualStrings(expected_path, resolved_cwd);
+}