std lib tests: avoid cwd races by using std.testing.tmpDir

This commit is contained in:
Andrew Kelley 2023-03-15 10:32:32 -07:00
parent 5c6adbeb39
commit cdda395590
2 changed files with 86 additions and 84 deletions

View File

@ -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;

View File

@ -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);
}