authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2023-12-21 23:15:12-08:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-12-22 13:47:19+02:00
log70b248497ab87471997c62a515bf4bb4109899b9
tree43cebd226cfe9cfdec7134c69d0c388a1369a533
parent60982ea5bd05695a0e97205cf3de223bd9111767

fs: Add tests for deleteTree not following symlinks

In theory this is part of https://github.com/ziglang/zig/issues/18335, but these tests already pass since deleteTree does not depend on `OpenDirOptions.no_follow` behavior for these test cases: - `deleteTree` always tries to delete the initial path as a file first, which will succeed on symlinks because `deleteFile` doesn't follow symlinks - `deleteTree` when iterating a directory will get the type of symlinks as .sym_link, not as .directory (even if the symlink points to a directory), meaning it will never try to open a symlink as a directory.

1 files changed, 51 insertions(+), 0 deletions(-)

lib/std/fs/test.zig+51
...@@ -999,6 +999,57 @@ test "openSelfExe" {...@@ -999,6 +999,57 @@ test "openSelfExe" {
999 self_exe_file.close();999 self_exe_file.close();
1000}1000}
10011001
1002test "deleteTree does not follow symlinks" {
1003 var tmp = tmpDir(.{});
1004 defer tmp.cleanup();
1005
1006 try tmp.dir.makePath("b");
1007 {
1008 var a = try tmp.dir.makeOpenPath("a", .{});
1009 defer a.close();
1010
1011 a.symLink("../b", "b", .{ .is_directory = true }) catch |err| switch (err) {
1012 // Symlink requires admin privileges on windows, so this test can legitimately fail.
1013 error.AccessDenied => return error.SkipZigTest,
1014 else => return err,
1015 };
1016 }
1017
1018 try tmp.dir.deleteTree("a");
1019
1020 try testing.expectError(error.FileNotFound, tmp.dir.access("a", .{}));
1021 try tmp.dir.access("b", .{});
1022}
1023
1024test "deleteTree on a symlink" {
1025 var tmp = tmpDir(.{});
1026 defer tmp.cleanup();
1027
1028 // Symlink to a file
1029 try tmp.dir.writeFile("file", "");
1030 tmp.dir.symLink("file", "filelink", .{}) catch |err| switch (err) {
1031 // Symlink requires admin privileges on windows, so this test can legitimately fail.
1032 error.AccessDenied => return error.SkipZigTest,
1033 else => return err,
1034 };
1035
1036 try tmp.dir.deleteTree("filelink");
1037 try testing.expectError(error.FileNotFound, tmp.dir.access("filelink", .{}));
1038 try tmp.dir.access("file", .{});
1039
1040 // Symlink to a directory
1041 try tmp.dir.makePath("dir");
1042 tmp.dir.symLink("dir", "dirlink", .{ .is_directory = true }) catch |err| switch (err) {
1043 // Symlink requires admin privileges on windows, so this test can legitimately fail.
1044 error.AccessDenied => return error.SkipZigTest,
1045 else => return err,
1046 };
1047
1048 try tmp.dir.deleteTree("dirlink");
1049 try testing.expectError(error.FileNotFound, tmp.dir.access("dirlink", .{}));
1050 try tmp.dir.access("dir", .{});
1051}
1052
1002test "makePath, put some files in it, deleteTree" {1053test "makePath, put some files in it, deleteTree" {
1003 try testWithAllSupportedPathTypes(struct {1054 try testWithAllSupportedPathTypes(struct {
1004 fn impl(ctx: *TestContext) !void {1055 fn impl(ctx: *TestContext) !void {