Commit cdda395590

Andrew Kelley <andrew@ziglang.org>
2023-03-15 18:32:32
std lib tests: avoid cwd races by using std.testing.tmpDir
1 parent 5c6adbe
Changed files (2)
lib
lib/std/os/linux/io_uring.zig
@@ -1728,10 +1728,12 @@ test "writev/fsync/readv" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const path = "test_io_uring_writev_fsync_readv";
-    const file = try std.fs.cwd().createFile(path, .{ .read = true, .truncate = true });
+    const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true });
     defer file.close();
-    defer std.fs.cwd().deleteFile(path) catch {};
     const fd = file.handle;
 
     const buffer_write = [_]u8{42} ** 128;
@@ -1796,10 +1798,11 @@ test "write/read" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
     const path = "test_io_uring_write_read";
-    const file = try std.fs.cwd().createFile(path, .{ .read = true, .truncate = true });
+    const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true });
     defer file.close();
-    defer std.fs.cwd().deleteFile(path) catch {};
     const fd = file.handle;
 
     const buffer_write = [_]u8{97} ** 20;
@@ -1842,10 +1845,12 @@ test "write_fixed/read_fixed" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const path = "test_io_uring_write_read_fixed";
-    const file = try std.fs.cwd().createFile(path, .{ .read = true, .truncate = true });
+    const file = try tmp.dir.createFile(path, .{ .read = true, .truncate = true });
     defer file.close();
-    defer std.fs.cwd().deleteFile(path) catch {};
     const fd = file.handle;
 
     var raw_buffers: [2][11]u8 = undefined;
@@ -1899,8 +1904,10 @@ test "openat" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const path = "test_io_uring_openat";
-    defer std.fs.cwd().deleteFile(path) catch {};
 
     // Workaround for LLVM bug: https://github.com/ziglang/zig/issues/12014
     const path_addr = if (builtin.zig_backend == .stage2_llvm) p: {
@@ -1910,12 +1917,12 @@ test "openat" {
 
     const flags: u32 = os.O.CLOEXEC | os.O.RDWR | os.O.CREAT;
     const mode: os.mode_t = 0o666;
-    const sqe_openat = try ring.openat(0x33333333, linux.AT.FDCWD, path, flags, mode);
+    const sqe_openat = try ring.openat(0x33333333, tmp.dir.fd, path, flags, mode);
     try testing.expectEqual(linux.io_uring_sqe{
         .opcode = .OPENAT,
         .flags = 0,
         .ioprio = 0,
-        .fd = linux.AT.FDCWD,
+        .fd = tmp.dir.fd,
         .off = 0,
         .addr = path_addr,
         .len = mode,
@@ -1931,12 +1938,6 @@ test "openat" {
     const cqe_openat = try ring.copy_cqe();
     try testing.expectEqual(@as(u64, 0x33333333), cqe_openat.user_data);
     if (cqe_openat.err() == .INVAL) return error.SkipZigTest;
-    // AT.FDCWD is not fully supported before kernel 5.6:
-    // See https://lore.kernel.org/io-uring/20200207155039.12819-1-axboe@kernel.dk/T/
-    // We use IORING_FEAT_RW_CUR_POS to know if we are pre-5.6 since that feature was added in 5.6.
-    if (cqe_openat.err() == .BADF and (ring.features & linux.IORING_FEAT_RW_CUR_POS) == 0) {
-        return error.SkipZigTest;
-    }
     if (cqe_openat.res <= 0) std.debug.print("\ncqe_openat.res={}\n", .{cqe_openat.res});
     try testing.expect(cqe_openat.res > 0);
     try testing.expectEqual(@as(u32, 0), cqe_openat.flags);
@@ -1954,10 +1955,12 @@ test "close" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const path = "test_io_uring_close";
-    const file = try std.fs.cwd().createFile(path, .{});
+    const file = try tmp.dir.createFile(path, .{});
     errdefer file.close();
-    defer std.fs.cwd().deleteFile(path) catch {};
 
     const sqe_close = try ring.close(0x44444444, file.handle);
     try testing.expectEqual(linux.IORING_OP.CLOSE, sqe_close.opcode);
@@ -2295,10 +2298,12 @@ test "fallocate" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const path = "test_io_uring_fallocate";
-    const file = try std.fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 });
+    const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 });
     defer file.close();
-    defer std.fs.cwd().deleteFile(path) catch {};
 
     try testing.expectEqual(@as(u64, 0), (try file.stat()).size);
 
@@ -2339,10 +2344,11 @@ test "statx" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
     const path = "test_io_uring_statx";
-    const file = try std.fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 });
+    const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 });
     defer file.close();
-    defer std.fs.cwd().deleteFile(path) catch {};
 
     try testing.expectEqual(@as(u64, 0), (try file.stat()).size);
 
@@ -2351,14 +2357,14 @@ test "statx" {
     var buf: linux.Statx = undefined;
     const sqe = try ring.statx(
         0xaaaaaaaa,
-        linux.AT.FDCWD,
+        tmp.dir.fd,
         path,
         0,
         linux.STATX_SIZE,
         &buf,
     );
     try testing.expectEqual(linux.IORING_OP.STATX, sqe.opcode);
-    try testing.expectEqual(@as(i32, linux.AT.FDCWD), sqe.fd);
+    try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd);
     try testing.expectEqual(@as(u32, 1), try ring.submit());
 
     const cqe = try ring.copy_cqe();
@@ -2371,8 +2377,6 @@ test "statx" {
         // The filesystem containing the file referred to by fd does not support this operation;
         // or the mode is not supported by the filesystem containing the file referred to by fd:
         .OPNOTSUPP => return error.SkipZigTest,
-        // The kernel is too old to support FDCWD for dir_fd
-        .BADF => return error.SkipZigTest,
         else => |errno| std.debug.panic("unhandled errno: {}", .{errno}),
     }
     try testing.expectEqual(linux.io_uring_cqe{
@@ -2606,28 +2610,28 @@ test "renameat" {
     const old_path = "test_io_uring_renameat_old";
     const new_path = "test_io_uring_renameat_new";
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     // Write old file with data
 
-    const old_file = try std.fs.cwd().createFile(old_path, .{ .truncate = true, .mode = 0o666 });
-    defer {
-        old_file.close();
-        std.fs.cwd().deleteFile(new_path) catch {};
-    }
+    const old_file = try tmp.dir.createFile(old_path, .{ .truncate = true, .mode = 0o666 });
+    defer old_file.close();
     try old_file.writeAll("hello");
 
     // Submit renameat
 
     var sqe = try ring.renameat(
         0x12121212,
-        linux.AT.FDCWD,
+        tmp.dir.fd,
         old_path,
-        linux.AT.FDCWD,
+        tmp.dir.fd,
         new_path,
         0,
     );
     try testing.expectEqual(linux.IORING_OP.RENAMEAT, sqe.opcode);
-    try testing.expectEqual(@as(i32, linux.AT.FDCWD), sqe.fd);
-    try testing.expectEqual(@as(i32, linux.AT.FDCWD), @bitCast(i32, sqe.len));
+    try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd);
+    try testing.expectEqual(@as(i32, tmp.dir.fd), @bitCast(i32, sqe.len));
     try testing.expectEqual(@as(u32, 1), try ring.submit());
 
     const cqe = try ring.copy_cqe();
@@ -2645,7 +2649,7 @@ test "renameat" {
 
     // Validate that the old file doesn't exist anymore
     {
-        _ = std.fs.cwd().openFile(old_path, .{}) catch |err| switch (err) {
+        _ = tmp.dir.openFile(old_path, .{}) catch |err| switch (err) {
             error.FileNotFound => {},
             else => std.debug.panic("unexpected error: {}", .{err}),
         };
@@ -2653,7 +2657,7 @@ test "renameat" {
 
     // Validate that the new file exists with the proper content
     {
-        const new_file = try std.fs.cwd().openFile(new_path, .{});
+        const new_file = try tmp.dir.openFile(new_path, .{});
         defer new_file.close();
 
         var new_file_data: [16]u8 = undefined;
@@ -2674,22 +2678,24 @@ test "unlinkat" {
 
     const path = "test_io_uring_unlinkat";
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     // Write old file with data
 
-    const file = try std.fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 });
+    const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 });
     defer file.close();
-    defer std.fs.cwd().deleteFile(path) catch {};
 
     // Submit unlinkat
 
     var sqe = try ring.unlinkat(
         0x12121212,
-        linux.AT.FDCWD,
+        tmp.dir.fd,
         path,
         0,
     );
     try testing.expectEqual(linux.IORING_OP.UNLINKAT, sqe.opcode);
-    try testing.expectEqual(@as(i32, linux.AT.FDCWD), sqe.fd);
+    try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd);
     try testing.expectEqual(@as(u32, 1), try ring.submit());
 
     const cqe = try ring.copy_cqe();
@@ -2706,7 +2712,7 @@ test "unlinkat" {
     }, cqe);
 
     // Validate that the file doesn't exist anymore
-    _ = std.fs.cwd().openFile(path, .{}) catch |err| switch (err) {
+    _ = tmp.dir.openFile(path, .{}) catch |err| switch (err) {
         error.FileNotFound => {},
         else => std.debug.panic("unexpected error: {}", .{err}),
     };
@@ -2722,20 +2728,21 @@ test "mkdirat" {
     };
     defer ring.deinit();
 
-    const path = "test_io_uring_mkdirat";
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
 
-    defer std.fs.cwd().deleteDir(path) catch {};
+    const path = "test_io_uring_mkdirat";
 
     // Submit mkdirat
 
     var sqe = try ring.mkdirat(
         0x12121212,
-        linux.AT.FDCWD,
+        tmp.dir.fd,
         path,
         0o0755,
     );
     try testing.expectEqual(linux.IORING_OP.MKDIRAT, sqe.opcode);
-    try testing.expectEqual(@as(i32, linux.AT.FDCWD), sqe.fd);
+    try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd);
     try testing.expectEqual(@as(u32, 1), try ring.submit());
 
     const cqe = try ring.copy_cqe();
@@ -2752,7 +2759,7 @@ test "mkdirat" {
     }, cqe);
 
     // Validate that the directory exist
-    _ = try std.fs.cwd().openDir(path, .{});
+    _ = try tmp.dir.openDir(path, .{});
 }
 
 test "symlinkat" {
@@ -2765,26 +2772,25 @@ test "symlinkat" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const path = "test_io_uring_symlinkat";
     const link_path = "test_io_uring_symlinkat_link";
 
-    const file = try std.fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 });
-    defer {
-        file.close();
-        std.fs.cwd().deleteFile(path) catch {};
-        std.fs.cwd().deleteFile(link_path) catch {};
-    }
+    const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 });
+    defer file.close();
 
     // Submit symlinkat
 
     var sqe = try ring.symlinkat(
         0x12121212,
         path,
-        linux.AT.FDCWD,
+        tmp.dir.fd,
         link_path,
     );
     try testing.expectEqual(linux.IORING_OP.SYMLINKAT, sqe.opcode);
-    try testing.expectEqual(@as(i32, linux.AT.FDCWD), sqe.fd);
+    try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd);
     try testing.expectEqual(@as(u32, 1), try ring.submit());
 
     const cqe = try ring.copy_cqe();
@@ -2801,7 +2807,7 @@ test "symlinkat" {
     }, cqe);
 
     // Validate that the symlink exist
-    _ = try std.fs.cwd().openFile(link_path, .{});
+    _ = try tmp.dir.openFile(link_path, .{});
 }
 
 test "linkat" {
@@ -2814,32 +2820,31 @@ test "linkat" {
     };
     defer ring.deinit();
 
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const first_path = "test_io_uring_linkat_first";
     const second_path = "test_io_uring_linkat_second";
 
     // Write file with data
 
-    const first_file = try std.fs.cwd().createFile(first_path, .{ .truncate = true, .mode = 0o666 });
-    defer {
-        first_file.close();
-        std.fs.cwd().deleteFile(first_path) catch {};
-        std.fs.cwd().deleteFile(second_path) catch {};
-    }
+    const first_file = try tmp.dir.createFile(first_path, .{ .truncate = true, .mode = 0o666 });
+    defer first_file.close();
     try first_file.writeAll("hello");
 
     // Submit linkat
 
     var sqe = try ring.linkat(
         0x12121212,
-        linux.AT.FDCWD,
+        tmp.dir.fd,
         first_path,
-        linux.AT.FDCWD,
+        tmp.dir.fd,
         second_path,
         0,
     );
     try testing.expectEqual(linux.IORING_OP.LINKAT, sqe.opcode);
-    try testing.expectEqual(@as(i32, linux.AT.FDCWD), sqe.fd);
-    try testing.expectEqual(@as(i32, linux.AT.FDCWD), @bitCast(i32, sqe.len));
+    try testing.expectEqual(@as(i32, tmp.dir.fd), sqe.fd);
+    try testing.expectEqual(@as(i32, tmp.dir.fd), @bitCast(i32, sqe.len));
     try testing.expectEqual(@as(u32, 1), try ring.submit());
 
     const cqe = try ring.copy_cqe();
@@ -2856,7 +2861,7 @@ test "linkat" {
     }, cqe);
 
     // Validate the second file
-    const second_file = try std.fs.cwd().openFile(second_path, .{});
+    const second_file = try tmp.dir.openFile(second_path, .{});
     defer second_file.close();
 
     var second_file_data: [16]u8 = undefined;
lib/std/os/linux/test.zig
@@ -8,10 +8,12 @@ const expectEqual = std.testing.expectEqual;
 const fs = std.fs;
 
 test "fallocate" {
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const path = "test_fallocate";
-    const file = try fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 });
+    const file = try tmp.dir.createFile(path, .{ .truncate = true, .mode = 0o666 });
     defer file.close();
-    defer fs.cwd().deleteFile(path) catch {};
 
     try expect((try file.stat()).size == 0);
 
@@ -67,12 +69,12 @@ test "timer" {
 }
 
 test "statx" {
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const tmp_file_name = "just_a_temporary_file.txt";
-    var file = try fs.cwd().createFile(tmp_file_name, .{});
-    defer {
-        file.close();
-        fs.cwd().deleteFile(tmp_file_name) catch {};
-    }
+    var file = try tmp.dir.createFile(tmp_file_name, .{});
+    defer file.close();
 
     var statx_buf: linux.Statx = undefined;
     switch (linux.getErrno(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
@@ -105,21 +107,16 @@ test "user and group ids" {
 }
 
 test "fadvise" {
+    var tmp = std.testing.tmpDir(.{});
+    defer tmp.cleanup();
+
     const tmp_file_name = "temp_posix_fadvise.txt";
-    var file = try fs.cwd().createFile(tmp_file_name, .{});
-    defer {
-        file.close();
-        fs.cwd().deleteFile(tmp_file_name) catch {};
-    }
+    var file = try tmp.dir.createFile(tmp_file_name, .{});
+    defer file.close();
 
     var buf: [2048]u8 = undefined;
     try file.writeAll(&buf);
 
-    const ret = linux.fadvise(
-        file.handle,
-        0,
-        0,
-        linux.POSIX_FADV.SEQUENTIAL,
-    );
+    const ret = linux.fadvise(file.handle, 0, 0, linux.POSIX_FADV.SEQUENTIAL);
     try expectEqual(@as(usize, 0), ret);
 }