| ... | @@ -3,19 +3,23 @@ const native_os = builtin.os.tag; | ... | @@ -3,19 +3,23 @@ const native_os = builtin.os.tag; |
| 3 | | 3 | |
| 4 | const std = @import("../std.zig"); | 4 | const std = @import("../std.zig"); |
| 5 | const Io = std.Io; | 5 | const Io = std.Io; |
| 6 | const testing = std.testing; | | |
| 7 | const expect = std.testing.expect; | | |
| 8 | const fs = std.fs; | 6 | const fs = std.fs; |
| 9 | const mem = std.mem; | 7 | const mem = std.mem; |
| 10 | const wasi = std.os.wasi; | 8 | const wasi = std.os.wasi; |
| 11 | const windows = std.os.windows; | 9 | const windows = std.os.windows; |
| 12 | const posix = std.posix; | | |
| 13 | const ArenaAllocator = std.heap.ArenaAllocator; | 10 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 14 | const Dir = std.Io.Dir; | 11 | const Dir = std.Io.Dir; |
| 15 | const File = std.Io.File; | 12 | const File = std.Io.File; |
| 16 | const tmpDir = std.testing.tmpDir; | | |
| 17 | const SymLinkFlags = std.Io.Dir.SymLinkFlags; | 13 | const SymLinkFlags = std.Io.Dir.SymLinkFlags; |
| 18 | | 14 | |
| | 15 | const testing = std.testing; |
| | 16 | const expect = std.testing.expect; |
| | 17 | const expectError = std.testing.expectError; |
| | 18 | const expectEqual = std.testing.expectEqual; |
| | 19 | const tmpDir = std.testing.tmpDir; |
| | 20 | const expectEqualStrings = std.testing.expectEqualStrings; |
| | 21 | const expectEqualSlices = std.testing.expectEqualSlices; |
| | 22 | |
| 19 | const PathType = enum { | 23 | const PathType = enum { |
| 20 | relative, | 24 | relative, |
| 21 | absolute, | 25 | absolute, |
| ... | @@ -29,7 +33,7 @@ const PathType = enum { | ... | @@ -29,7 +33,7 @@ const PathType = enum { |
| 29 | }; | 33 | }; |
| 30 | } | 34 | } |
| 31 | | 35 | |
| 32 | pub const TransformError = posix.RealPathError || error{OutOfMemory}; | 36 | pub const TransformError = Io.Dir.RealPathError || error{OutOfMemory}; |
| 33 | pub const TransformFn = fn (allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8; | 37 | pub const TransformFn = fn (allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8; |
| 34 | | 38 | |
| 35 | pub fn getTransformFn(comptime path_type: PathType) TransformFn { | 39 | pub fn getTransformFn(comptime path_type: PathType) TransformFn { |
| ... | @@ -249,7 +253,7 @@ test "Dir.readLink on non-symlinks" { | ... | @@ -249,7 +253,7 @@ test "Dir.readLink on non-symlinks" { |
| 249 | fn testReadLink(io: Io, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { | 253 | fn testReadLink(io: Io, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { |
| 250 | var buffer: [fs.max_path_bytes]u8 = undefined; | 254 | var buffer: [fs.max_path_bytes]u8 = undefined; |
| 251 | const actual = try dir.readLink(io, symlink_path, &buffer); | 255 | const actual = try dir.readLink(io, symlink_path, &buffer); |
| 252 | try testing.expectEqualStrings(target_path, actual); | 256 | try expectEqualStrings(target_path, actual); |
| 253 | } | 257 | } |
| 254 | | 258 | |
| 255 | fn testReadLinkW(allocator: mem.Allocator, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { | 259 | fn testReadLinkW(allocator: mem.Allocator, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { |
| ... | @@ -260,13 +264,13 @@ fn testReadLinkW(allocator: mem.Allocator, dir: Dir, target_path: []const u8, sy | ... | @@ -260,13 +264,13 @@ fn testReadLinkW(allocator: mem.Allocator, dir: Dir, target_path: []const u8, sy |
| 260 | const wtf16_buffer = try allocator.alloc(u16, target_path_w.len); | 264 | const wtf16_buffer = try allocator.alloc(u16, target_path_w.len); |
| 261 | defer allocator.free(wtf16_buffer); | 265 | defer allocator.free(wtf16_buffer); |
| 262 | const actual = try dir.readLinkW(symlink_path_w.span(), wtf16_buffer); | 266 | const actual = try dir.readLinkW(symlink_path_w.span(), wtf16_buffer); |
| 263 | try testing.expectEqualSlices(u16, target_path_w, actual); | 267 | try expectEqualSlices(u16, target_path_w, actual); |
| 264 | } | 268 | } |
| 265 | | 269 | |
| 266 | fn testReadLinkAbsolute(target_path: []const u8, symlink_path: []const u8) !void { | 270 | fn testReadLinkAbsolute(target_path: []const u8, symlink_path: []const u8) !void { |
| 267 | var buffer: [fs.max_path_bytes]u8 = undefined; | 271 | var buffer: [fs.max_path_bytes]u8 = undefined; |
| 268 | const given = try fs.readLinkAbsolute(symlink_path, buffer[0..]); | 272 | const given = try fs.readLinkAbsolute(symlink_path, buffer[0..]); |
| 269 | try testing.expectEqualStrings(target_path, given); | 273 | try expectEqualStrings(target_path, given); |
| 270 | } | 274 | } |
| 271 | | 275 | |
| 272 | test "File.stat on a File that is a symlink returns Kind.sym_link" { | 276 | test "File.stat on a File that is a symlink returns Kind.sym_link" { |
| ... | @@ -286,72 +290,11 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { | ... | @@ -286,72 +290,11 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { |
| 286 | | 290 | |
| 287 | try setupSymlink(io, ctx.dir, dir_target_path, "symlink", .{ .is_directory = true }); | 291 | try setupSymlink(io, ctx.dir, dir_target_path, "symlink", .{ .is_directory = true }); |
| 288 | | 292 | |
| 289 | var symlink: Dir = switch (builtin.target.os.tag) { | 293 | var symlink: Dir = try ctx.dir.openDir("symlink", .{ .follow_symlinks = false }); |
| 290 | .windows => windows_symlink: { | | |
| 291 | const sub_path_w = try windows.cStrToPrefixedFileW(ctx.dir.handle, "symlink"); | | |
| 292 | | | |
| 293 | var result: Dir = .{ | | |
| 294 | .handle = undefined, | | |
| 295 | }; | | |
| 296 | | | |
| 297 | const path_len_bytes = @as(u16, @intCast(sub_path_w.span().len * 2)); | | |
| 298 | var nt_name = windows.UNICODE_STRING{ | | |
| 299 | .Length = path_len_bytes, | | |
| 300 | .MaximumLength = path_len_bytes, | | |
| 301 | .Buffer = @constCast(&sub_path_w.data), | | |
| 302 | }; | | |
| 303 | var attr: windows.OBJECT_ATTRIBUTES = .{ | | |
| 304 | .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), | | |
| 305 | .RootDirectory = if (fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else ctx.dir.handle, | | |
| 306 | .Attributes = 0, | | |
| 307 | .ObjectName = &nt_name, | | |
| 308 | .SecurityDescriptor = null, | | |
| 309 | .SecurityQualityOfService = null, | | |
| 310 | }; | | |
| 311 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; | | |
| 312 | const rc = windows.ntdll.NtCreateFile( | | |
| 313 | &result.handle, | | |
| 314 | windows.STANDARD_RIGHTS_READ | windows.FILE_READ_ATTRIBUTES | windows.FILE_READ_EA | windows.SYNCHRONIZE | windows.FILE_TRAVERSE, | | |
| 315 | &attr, | | |
| 316 | &io_status_block, | | |
| 317 | null, | | |
| 318 | .{ .NORMAL = true }, | | |
| 319 | .VALID_FLAGS, | | |
| 320 | .OPEN, | | |
| 321 | .{ | | |
| 322 | .DIRECTORY_FILE = true, | | |
| 323 | .IO = .SYNCHRONOUS_NONALERT, | | |
| 324 | .OPEN_FOR_BACKUP_INTENT = true, | | |
| 325 | .OPEN_REPARSE_POINT = true, // the important thing here | | |
| 326 | }, | | |
| 327 | null, | | |
| 328 | 0, | | |
| 329 | ); | | |
| 330 | | | |
| 331 | switch (rc) { | | |
| 332 | .SUCCESS => break :windows_symlink .{ .fd = result.handle }, | | |
| 333 | else => return windows.unexpectedStatus(rc), | | |
| 334 | } | | |
| 335 | }, | | |
| 336 | .linux => linux_symlink: { | | |
| 337 | const sub_path_c = try posix.toPosixPath("symlink"); | | |
| 338 | // the O_NOFOLLOW | O_PATH combination can obtain a fd to a symlink | | |
| 339 | // note that if O_DIRECTORY is set, then this will error with ENOTDIR | | |
| 340 | const flags: posix.O = .{ | | |
| 341 | .NOFOLLOW = true, | | |
| 342 | .PATH = true, | | |
| 343 | .ACCMODE = .RDONLY, | | |
| 344 | .CLOEXEC = true, | | |
| 345 | }; | | |
| 346 | const fd = try posix.openatZ(ctx.dir.handle, &sub_path_c, flags, 0); | | |
| 347 | break :linux_symlink .{ .handle = fd }; | | |
| 348 | }, | | |
| 349 | else => unreachable, | | |
| 350 | }; | | |
| 351 | defer symlink.close(io); | 294 | defer symlink.close(io); |
| 352 | | 295 | |
| 353 | const stat = try symlink.stat(io); | 296 | const stat = try symlink.stat(io); |
| 354 | try testing.expectEqual(File.Kind.sym_link, stat.kind); | 297 | try expectEqual(File.Kind.sym_link, stat.kind); |
| 355 | } | 298 | } |
| 356 | }.impl); | 299 | }.impl); |
| 357 | } | 300 | } |
| ... | @@ -417,7 +360,7 @@ test "openDirAbsolute" { | ... | @@ -417,7 +360,7 @@ test "openDirAbsolute" { |
| 417 | defer dir.close(io); | 360 | defer dir.close(io); |
| 418 | | 361 | |
| 419 | const ino = (try dir.stat(io)).inode; | 362 | const ino = (try dir.stat(io)).inode; |
| 420 | try testing.expectEqual(tmp_ino, ino); | 363 | try expectEqual(tmp_ino, ino); |
| 421 | } | 364 | } |
| 422 | | 365 | |
| 423 | { | 366 | { |
| ... | @@ -429,7 +372,7 @@ test "openDirAbsolute" { | ... | @@ -429,7 +372,7 @@ test "openDirAbsolute" { |
| 429 | defer dir.close(io); | 372 | defer dir.close(io); |
| 430 | | 373 | |
| 431 | const ino = (try dir.stat(io)).inode; | 374 | const ino = (try dir.stat(io)).inode; |
| 432 | try testing.expectEqual(sub_ino, ino); | 375 | try expectEqual(sub_ino, ino); |
| 433 | } | 376 | } |
| 434 | | 377 | |
| 435 | { | 378 | { |
| ... | @@ -441,7 +384,7 @@ test "openDirAbsolute" { | ... | @@ -441,7 +384,7 @@ test "openDirAbsolute" { |
| 441 | defer dir.close(io); | 384 | defer dir.close(io); |
| 442 | | 385 | |
| 443 | const ino = (try dir.stat(io)).inode; | 386 | const ino = (try dir.stat(io)).inode; |
| 444 | try testing.expectEqual(tmp_ino, ino); | 387 | try expectEqual(tmp_ino, ino); |
| 445 | } | 388 | } |
| 446 | } | 389 | } |
| 447 | | 390 | |
| ... | @@ -480,7 +423,7 @@ test "openDir non-cwd parent '..'" { | ... | @@ -480,7 +423,7 @@ test "openDir non-cwd parent '..'" { |
| 480 | const actual_path = try dir.realpathAlloc(testing.allocator, "."); | 423 | const actual_path = try dir.realpathAlloc(testing.allocator, "."); |
| 481 | defer testing.allocator.free(actual_path); | 424 | defer testing.allocator.free(actual_path); |
| 482 | | 425 | |
| 483 | try testing.expectEqualStrings(expected_path, actual_path); | 426 | try expectEqualStrings(expected_path, actual_path); |
| 484 | } | 427 | } |
| 485 | | 428 | |
| 486 | test "readLinkAbsolute" { | 429 | test "readLinkAbsolute" { |
| ... | @@ -548,7 +491,7 @@ test "Dir.Iterator" { | ... | @@ -548,7 +491,7 @@ test "Dir.Iterator" { |
| 548 | try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); | 491 | try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); |
| 549 | } | 492 | } |
| 550 | | 493 | |
| 551 | try testing.expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' | 494 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' |
| 552 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); | 495 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 553 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); | 496 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); |
| 554 | } | 497 | } |
| ... | @@ -619,7 +562,7 @@ test "Dir.Iterator twice" { | ... | @@ -619,7 +562,7 @@ test "Dir.Iterator twice" { |
| 619 | try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); | 562 | try entries.append(Dir.Entry{ .name = name, .kind = entry.kind }); |
| 620 | } | 563 | } |
| 621 | | 564 | |
| 622 | try testing.expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' | 565 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' |
| 623 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); | 566 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 624 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); | 567 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); |
| 625 | } | 568 | } |
| ... | @@ -655,7 +598,7 @@ test "Dir.Iterator reset" { | ... | @@ -655,7 +598,7 @@ test "Dir.Iterator reset" { |
| 655 | try entries.append(.{ .name = name, .kind = entry.kind }); | 598 | try entries.append(.{ .name = name, .kind = entry.kind }); |
| 656 | } | 599 | } |
| 657 | | 600 | |
| 658 | try testing.expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' | 601 | try expectEqual(@as(usize, 2), entries.items.len); // note that the Iterator skips '.' and '..' |
| 659 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); | 602 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 660 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); | 603 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); |
| 661 | | 604 | |
| ... | @@ -690,7 +633,7 @@ test "Dir.Iterator but dir is deleted during iteration" { | ... | @@ -690,7 +633,7 @@ test "Dir.Iterator but dir is deleted during iteration" { |
| 690 | | 633 | |
| 691 | // On Linux, we can opt-in to receiving a more specific error by calling `nextLinux` | 634 | // On Linux, we can opt-in to receiving a more specific error by calling `nextLinux` |
| 692 | if (native_os == .linux) { | 635 | if (native_os == .linux) { |
| 693 | try std.testing.expectError(error.DirNotFound, iterator.nextLinux()); | 636 | try expectError(error.DirNotFound, iterator.nextLinux()); |
| 694 | } | 637 | } |
| 695 | } | 638 | } |
| 696 | | 639 | |
| ... | @@ -717,10 +660,10 @@ test "Dir.realpath smoke test" { | ... | @@ -717,10 +660,10 @@ test "Dir.realpath smoke test" { |
| 717 | var buf: [fs.max_path_bytes]u8 = undefined; | 660 | var buf: [fs.max_path_bytes]u8 = undefined; |
| 718 | | 661 | |
| 719 | // FileNotFound if the path doesn't exist | 662 | // FileNotFound if the path doesn't exist |
| 720 | try testing.expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_file_path)); | 663 | try expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_file_path)); |
| 721 | try testing.expectError(error.FileNotFound, ctx.dir.realpath(test_file_path, &buf)); | 664 | try expectError(error.FileNotFound, ctx.dir.realpath(test_file_path, &buf)); |
| 722 | try testing.expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_dir_path)); | 665 | try expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_dir_path)); |
| 723 | try testing.expectError(error.FileNotFound, ctx.dir.realpath(test_dir_path, &buf)); | 666 | try expectError(error.FileNotFound, ctx.dir.realpath(test_dir_path, &buf)); |
| 724 | | 667 | |
| 725 | // Now create the file and dir | 668 | // Now create the file and dir |
| 726 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); | 669 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); |
| ... | @@ -740,19 +683,19 @@ test "Dir.realpath smoke test" { | ... | @@ -740,19 +683,19 @@ test "Dir.realpath smoke test" { |
| 740 | // First, test non-alloc version | 683 | // First, test non-alloc version |
| 741 | { | 684 | { |
| 742 | const file_path = try ctx.dir.realpath(test_file_path, &buf); | 685 | const file_path = try ctx.dir.realpath(test_file_path, &buf); |
| 743 | try testing.expectEqualStrings(expected_file_path, file_path); | 686 | try expectEqualStrings(expected_file_path, file_path); |
| 744 | | 687 | |
| 745 | const dir_path = try ctx.dir.realpath(test_dir_path, &buf); | 688 | const dir_path = try ctx.dir.realpath(test_dir_path, &buf); |
| 746 | try testing.expectEqualStrings(expected_dir_path, dir_path); | 689 | try expectEqualStrings(expected_dir_path, dir_path); |
| 747 | } | 690 | } |
| 748 | | 691 | |
| 749 | // Next, test alloc version | 692 | // Next, test alloc version |
| 750 | { | 693 | { |
| 751 | const file_path = try ctx.dir.realpathAlloc(allocator, test_file_path); | 694 | const file_path = try ctx.dir.realpathAlloc(allocator, test_file_path); |
| 752 | try testing.expectEqualStrings(expected_file_path, file_path); | 695 | try expectEqualStrings(expected_file_path, file_path); |
| 753 | | 696 | |
| 754 | const dir_path = try ctx.dir.realpathAlloc(allocator, test_dir_path); | 697 | const dir_path = try ctx.dir.realpathAlloc(allocator, test_dir_path); |
| 755 | try testing.expectEqualStrings(expected_dir_path, dir_path); | 698 | try expectEqualStrings(expected_dir_path, dir_path); |
| 756 | } | 699 | } |
| 757 | } | 700 | } |
| 758 | }.impl); | 701 | }.impl); |
| ... | @@ -769,7 +712,7 @@ test "readFileAlloc" { | ... | @@ -769,7 +712,7 @@ test "readFileAlloc" { |
| 769 | | 712 | |
| 770 | const buf1 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(1024)); | 713 | const buf1 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(1024)); |
| 771 | defer testing.allocator.free(buf1); | 714 | defer testing.allocator.free(buf1); |
| 772 | try testing.expectEqualStrings("", buf1); | 715 | try expectEqualStrings("", buf1); |
| 773 | | 716 | |
| 774 | const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; | 717 | const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; |
| 775 | try file.writeAll(write_buf); | 718 | try file.writeAll(write_buf); |
| ... | @@ -778,12 +721,12 @@ test "readFileAlloc" { | ... | @@ -778,12 +721,12 @@ test "readFileAlloc" { |
| 778 | // max_bytes > file_size | 721 | // max_bytes > file_size |
| 779 | const buf2 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(1024)); | 722 | const buf2 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(1024)); |
| 780 | defer testing.allocator.free(buf2); | 723 | defer testing.allocator.free(buf2); |
| 781 | try testing.expectEqualStrings(write_buf, buf2); | 724 | try expectEqualStrings(write_buf, buf2); |
| 782 | } | 725 | } |
| 783 | | 726 | |
| 784 | { | 727 | { |
| 785 | // max_bytes == file_size | 728 | // max_bytes == file_size |
| 786 | try testing.expectError( | 729 | try expectError( |
| 787 | error.StreamTooLong, | 730 | error.StreamTooLong, |
| 788 | tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len)), | 731 | tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len)), |
| 789 | ); | 732 | ); |
| ... | @@ -793,11 +736,11 @@ test "readFileAlloc" { | ... | @@ -793,11 +736,11 @@ test "readFileAlloc" { |
| 793 | // max_bytes == file_size + 1 | 736 | // max_bytes == file_size + 1 |
| 794 | const buf2 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len + 1)); | 737 | const buf2 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len + 1)); |
| 795 | defer testing.allocator.free(buf2); | 738 | defer testing.allocator.free(buf2); |
| 796 | try testing.expectEqualStrings(write_buf, buf2); | 739 | try expectEqualStrings(write_buf, buf2); |
| 797 | } | 740 | } |
| 798 | | 741 | |
| 799 | // max_bytes < file_size | 742 | // max_bytes < file_size |
| 800 | try testing.expectError( | 743 | try expectError( |
| 801 | error.StreamTooLong, | 744 | error.StreamTooLong, |
| 802 | tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len - 1)), | 745 | tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len - 1)), |
| 803 | ); | 746 | ); |
| ... | @@ -809,12 +752,12 @@ test "Dir.statFile" { | ... | @@ -809,12 +752,12 @@ test "Dir.statFile" { |
| 809 | const io = ctx.io; | 752 | const io = ctx.io; |
| 810 | const test_file_name = try ctx.transformPath("test_file"); | 753 | const test_file_name = try ctx.transformPath("test_file"); |
| 811 | | 754 | |
| 812 | try testing.expectError(error.FileNotFound, ctx.dir.statFile(io, test_file_name, .{})); | 755 | try expectError(error.FileNotFound, ctx.dir.statFile(io, test_file_name, .{})); |
| 813 | | 756 | |
| 814 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_name, .data = "" }); | 757 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_name, .data = "" }); |
| 815 | | 758 | |
| 816 | const stat = try ctx.dir.statFile(io, test_file_name, .{}); | 759 | const stat = try ctx.dir.statFile(io, test_file_name, .{}); |
| 817 | try testing.expectEqual(File.Kind.file, stat.kind); | 760 | try expectEqual(File.Kind.file, stat.kind); |
| 818 | } | 761 | } |
| 819 | }.impl); | 762 | }.impl); |
| 820 | } | 763 | } |
| ... | @@ -828,7 +771,7 @@ test "statFile on dangling symlink" { | ... | @@ -828,7 +771,7 @@ test "statFile on dangling symlink" { |
| 828 | | 771 | |
| 829 | try setupSymlink(io, ctx.dir, symlink_target, symlink_name, .{}); | 772 | try setupSymlink(io, ctx.dir, symlink_target, symlink_name, .{}); |
| 830 | | 773 | |
| 831 | try std.testing.expectError(error.FileNotFound, ctx.dir.statFile(io, symlink_name, .{})); | 774 | try expectError(error.FileNotFound, ctx.dir.statFile(io, symlink_name, .{})); |
| 832 | } | 775 | } |
| 833 | }.impl); | 776 | }.impl); |
| 834 | } | 777 | } |
| ... | @@ -843,19 +786,19 @@ test "directory operations on files" { | ... | @@ -843,19 +786,19 @@ test "directory operations on files" { |
| 843 | var file = try ctx.dir.createFile(io, test_file_name, .{ .read = true }); | 786 | var file = try ctx.dir.createFile(io, test_file_name, .{ .read = true }); |
| 844 | file.close(io); | 787 | file.close(io); |
| 845 | | 788 | |
| 846 | try testing.expectError(error.PathAlreadyExists, ctx.dir.makeDir(io, test_file_name, .default_dir)); | 789 | try expectError(error.PathAlreadyExists, ctx.dir.makeDir(io, test_file_name, .default_dir)); |
| 847 | try testing.expectError(error.NotDir, ctx.dir.openDir(io, test_file_name, .{})); | 790 | try expectError(error.NotDir, ctx.dir.openDir(io, test_file_name, .{})); |
| 848 | try testing.expectError(error.NotDir, ctx.dir.deleteDir(io, test_file_name)); | 791 | try expectError(error.NotDir, ctx.dir.deleteDir(io, test_file_name)); |
| 849 | | 792 | |
| 850 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { | 793 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { |
| 851 | try testing.expectError(error.PathAlreadyExists, fs.makeDirAbsolute(test_file_name)); | 794 | try expectError(error.PathAlreadyExists, fs.makeDirAbsolute(test_file_name)); |
| 852 | try testing.expectError(error.NotDir, fs.deleteDirAbsolute(test_file_name)); | 795 | try expectError(error.NotDir, fs.deleteDirAbsolute(test_file_name)); |
| 853 | } | 796 | } |
| 854 | | 797 | |
| 855 | // ensure the file still exists and is a file as a sanity check | 798 | // ensure the file still exists and is a file as a sanity check |
| 856 | file = try ctx.dir.openFile(io, test_file_name, .{}); | 799 | file = try ctx.dir.openFile(io, test_file_name, .{}); |
| 857 | const stat = try file.stat(io); | 800 | const stat = try file.stat(io); |
| 858 | try testing.expectEqual(File.Kind.file, stat.kind); | 801 | try expectEqual(File.Kind.file, stat.kind); |
| 859 | file.close(io); | 802 | file.close(io); |
| 860 | } | 803 | } |
| 861 | }.impl); | 804 | }.impl); |
| ... | @@ -873,8 +816,8 @@ test "file operations on directories" { | ... | @@ -873,8 +816,8 @@ test "file operations on directories" { |
| 873 | | 816 | |
| 874 | try ctx.dir.makeDir(io, test_dir_name, .default_dir); | 817 | try ctx.dir.makeDir(io, test_dir_name, .default_dir); |
| 875 | | 818 | |
| 876 | try testing.expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{})); | 819 | try expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{})); |
| 877 | try testing.expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name)); | 820 | try expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name)); |
| 878 | switch (native_os) { | 821 | switch (native_os) { |
| 879 | .dragonfly, .netbsd => { | 822 | .dragonfly, .netbsd => { |
| 880 | // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732 | 823 | // no error when reading a directory. See https://github.com/ziglang/zig/issues/5732 |
| ... | @@ -884,10 +827,10 @@ test "file operations on directories" { | ... | @@ -884,10 +827,10 @@ test "file operations on directories" { |
| 884 | .wasi => { | 827 | .wasi => { |
| 885 | // WASI return EBADF, which gets mapped to NotOpenForReading. | 828 | // WASI return EBADF, which gets mapped to NotOpenForReading. |
| 886 | // See https://github.com/bytecodealliance/wasmtime/issues/1935 | 829 | // See https://github.com/bytecodealliance/wasmtime/issues/1935 |
| 887 | try testing.expectError(error.NotOpenForReading, ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited)); | 830 | try expectError(error.NotOpenForReading, ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited)); |
| 888 | }, | 831 | }, |
| 889 | else => { | 832 | else => { |
| 890 | try testing.expectError(error.IsDir, ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited)); | 833 | try expectError(error.IsDir, ctx.dir.readFileAlloc(io, test_dir_name, testing.allocator, .unlimited)); |
| 891 | }, | 834 | }, |
| 892 | } | 835 | } |
| 893 | | 836 | |
| ... | @@ -898,12 +841,12 @@ test "file operations on directories" { | ... | @@ -898,12 +841,12 @@ test "file operations on directories" { |
| 898 | } else { | 841 | } else { |
| 899 | // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms. | 842 | // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms. |
| 900 | // TODO: Add a read-only test as well, see https://github.com/ziglang/zig/issues/5732 | 843 | // TODO: Add a read-only test as well, see https://github.com/ziglang/zig/issues/5732 |
| 901 | try testing.expectError(error.IsDir, ctx.dir.openFile(io, test_dir_name, .{ .mode = .read_write })); | 844 | try expectError(error.IsDir, ctx.dir.openFile(io, test_dir_name, .{ .mode = .read_write })); |
| 902 | } | 845 | } |
| 903 | | 846 | |
| 904 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { | 847 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { |
| 905 | try testing.expectError(error.IsDir, fs.createFileAbsolute(test_dir_name, .{})); | 848 | try expectError(error.IsDir, fs.createFileAbsolute(test_dir_name, .{})); |
| 906 | try testing.expectError(error.IsDir, fs.deleteFileAbsolute(test_dir_name)); | 849 | try expectError(error.IsDir, fs.deleteFileAbsolute(test_dir_name)); |
| 907 | } | 850 | } |
| 908 | | 851 | |
| 909 | // ensure the directory still exists as a sanity check | 852 | // ensure the directory still exists as a sanity check |
| ... | @@ -935,12 +878,12 @@ test "deleteDir" { | ... | @@ -935,12 +878,12 @@ test "deleteDir" { |
| 935 | const test_file_path = try ctx.transformPath("test_dir" ++ fs.path.sep_str ++ "test_file"); | 878 | const test_file_path = try ctx.transformPath("test_dir" ++ fs.path.sep_str ++ "test_file"); |
| 936 | | 879 | |
| 937 | // deleting a non-existent directory | 880 | // deleting a non-existent directory |
| 938 | try testing.expectError(error.FileNotFound, ctx.dir.deleteDir(io, test_dir_path)); | 881 | try expectError(error.FileNotFound, ctx.dir.deleteDir(io, test_dir_path)); |
| 939 | | 882 | |
| 940 | // deleting a non-empty directory | 883 | // deleting a non-empty directory |
| 941 | try ctx.dir.makeDir(io, test_dir_path, .default_dir); | 884 | try ctx.dir.makeDir(io, test_dir_path, .default_dir); |
| 942 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); | 885 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); |
| 943 | try testing.expectError(error.DirNotEmpty, ctx.dir.deleteDir(io, test_dir_path)); | 886 | try expectError(error.DirNotEmpty, ctx.dir.deleteDir(io, test_dir_path)); |
| 944 | | 887 | |
| 945 | // deleting an empty directory | 888 | // deleting an empty directory |
| 946 | try ctx.dir.deleteFile(io, test_file_path); | 889 | try ctx.dir.deleteFile(io, test_file_path); |
| ... | @@ -962,7 +905,7 @@ test "Dir.rename files" { | ... | @@ -962,7 +905,7 @@ test "Dir.rename files" { |
| 962 | const missing_file_path = try ctx.transformPath("missing_file_name"); | 905 | const missing_file_path = try ctx.transformPath("missing_file_name"); |
| 963 | const something_else_path = try ctx.transformPath("something_else"); | 906 | const something_else_path = try ctx.transformPath("something_else"); |
| 964 | | 907 | |
| 965 | try testing.expectError(error.FileNotFound, ctx.dir.rename(missing_file_path, ctx.dir, something_else_path, io)); | 908 | try expectError(error.FileNotFound, ctx.dir.rename(missing_file_path, ctx.dir, something_else_path, io)); |
| 966 | | 909 | |
| 967 | // Renaming files | 910 | // Renaming files |
| 968 | const test_file_name = try ctx.transformPath("test_file"); | 911 | const test_file_name = try ctx.transformPath("test_file"); |
| ... | @@ -972,7 +915,7 @@ test "Dir.rename files" { | ... | @@ -972,7 +915,7 @@ test "Dir.rename files" { |
| 972 | try ctx.dir.rename(test_file_name, ctx.dir, renamed_test_file_name, io); | 915 | try ctx.dir.rename(test_file_name, ctx.dir, renamed_test_file_name, io); |
| 973 | | 916 | |
| 974 | // Ensure the file was renamed | 917 | // Ensure the file was renamed |
| 975 | try testing.expectError(error.FileNotFound, ctx.dir.openFile(io, test_file_name, .{})); | 918 | try expectError(error.FileNotFound, ctx.dir.openFile(io, test_file_name, .{})); |
| 976 | file = try ctx.dir.openFile(io, renamed_test_file_name, .{}); | 919 | file = try ctx.dir.openFile(io, renamed_test_file_name, .{}); |
| 977 | file.close(io); | 920 | file.close(io); |
| 978 | | 921 | |
| ... | @@ -985,7 +928,7 @@ test "Dir.rename files" { | ... | @@ -985,7 +928,7 @@ test "Dir.rename files" { |
| 985 | existing_file.close(io); | 928 | existing_file.close(io); |
| 986 | try ctx.dir.rename(renamed_test_file_name, ctx.dir, existing_file_path, io); | 929 | try ctx.dir.rename(renamed_test_file_name, ctx.dir, existing_file_path, io); |
| 987 | | 930 | |
| 988 | try testing.expectError(error.FileNotFound, ctx.dir.openFile(io, renamed_test_file_name, .{})); | 931 | try expectError(error.FileNotFound, ctx.dir.openFile(io, renamed_test_file_name, .{})); |
| 989 | file = try ctx.dir.openFile(io, existing_file_path, .{}); | 932 | file = try ctx.dir.openFile(io, existing_file_path, .{}); |
| 990 | file.close(io); | 933 | file.close(io); |
| 991 | } | 934 | } |
| ... | @@ -1011,7 +954,7 @@ test "Dir.rename directories" { | ... | @@ -1011,7 +954,7 @@ test "Dir.rename directories" { |
| 1011 | try ctx.dir.rename(test_dir_path, ctx.dir, test_dir_renamed_path, io); | 954 | try ctx.dir.rename(test_dir_path, ctx.dir, test_dir_renamed_path, io); |
| 1012 | | 955 | |
| 1013 | // Ensure the directory was renamed | 956 | // Ensure the directory was renamed |
| 1014 | try testing.expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_path, .{})); | 957 | try expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_path, .{})); |
| 1015 | var dir = try ctx.dir.openDir(io, test_dir_renamed_path, .{}); | 958 | var dir = try ctx.dir.openDir(io, test_dir_renamed_path, .{}); |
| 1016 | | 959 | |
| 1017 | // Put a file in the directory | 960 | // Put a file in the directory |
| ... | @@ -1023,7 +966,7 @@ test "Dir.rename directories" { | ... | @@ -1023,7 +966,7 @@ test "Dir.rename directories" { |
| 1023 | try ctx.dir.rename(test_dir_renamed_path, ctx.dir, test_dir_renamed_again_path, io); | 966 | try ctx.dir.rename(test_dir_renamed_path, ctx.dir, test_dir_renamed_again_path, io); |
| 1024 | | 967 | |
| 1025 | // Ensure the directory was renamed and the file still exists in it | 968 | // Ensure the directory was renamed and the file still exists in it |
| 1026 | try testing.expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_renamed_path, .{})); | 969 | try expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_renamed_path, .{})); |
| 1027 | dir = try ctx.dir.openDir(io, test_dir_renamed_again_path, .{}); | 970 | dir = try ctx.dir.openDir(io, test_dir_renamed_again_path, .{}); |
| 1028 | file = try dir.openFile(io, "test_file", .{}); | 971 | file = try dir.openFile(io, "test_file", .{}); |
| 1029 | file.close(io); | 972 | file.close(io); |
| ... | @@ -1048,7 +991,7 @@ test "Dir.rename directory onto empty dir" { | ... | @@ -1048,7 +991,7 @@ test "Dir.rename directory onto empty dir" { |
| 1048 | try ctx.dir.rename(test_dir_path, ctx.dir, target_dir_path, io); | 991 | try ctx.dir.rename(test_dir_path, ctx.dir, target_dir_path, io); |
| 1049 | | 992 | |
| 1050 | // Ensure the directory was renamed | 993 | // Ensure the directory was renamed |
| 1051 | try testing.expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_path, .{})); | 994 | try expectError(error.FileNotFound, ctx.dir.openDir(io, test_dir_path, .{})); |
| 1052 | var dir = try ctx.dir.openDir(io, target_dir_path, .{}); | 995 | var dir = try ctx.dir.openDir(io, target_dir_path, .{}); |
| 1053 | dir.close(io); | 996 | dir.close(io); |
| 1054 | } | 997 | } |
| ... | @@ -1073,7 +1016,7 @@ test "Dir.rename directory onto non-empty dir" { | ... | @@ -1073,7 +1016,7 @@ test "Dir.rename directory onto non-empty dir" { |
| 1073 | target_dir.close(io); | 1016 | target_dir.close(io); |
| 1074 | | 1017 | |
| 1075 | // Rename should fail with PathAlreadyExists if target_dir is non-empty | 1018 | // Rename should fail with PathAlreadyExists if target_dir is non-empty |
| 1076 | try testing.expectError(error.PathAlreadyExists, ctx.dir.rename(test_dir_path, ctx.dir, target_dir_path, io)); | 1019 | try expectError(error.PathAlreadyExists, ctx.dir.rename(test_dir_path, ctx.dir, target_dir_path, io)); |
| 1077 | | 1020 | |
| 1078 | // Ensure the directory was not renamed | 1021 | // Ensure the directory was not renamed |
| 1079 | var dir = try ctx.dir.openDir(io, test_dir_path, .{}); | 1022 | var dir = try ctx.dir.openDir(io, test_dir_path, .{}); |
| ... | @@ -1095,8 +1038,8 @@ test "Dir.rename file <-> dir" { | ... | @@ -1095,8 +1038,8 @@ test "Dir.rename file <-> dir" { |
| 1095 | var file = try ctx.dir.createFile(io, test_file_path, .{ .read = true }); | 1038 | var file = try ctx.dir.createFile(io, test_file_path, .{ .read = true }); |
| 1096 | file.close(io); | 1039 | file.close(io); |
| 1097 | try ctx.dir.makeDir(io, test_dir_path, .default_dir); | 1040 | try ctx.dir.makeDir(io, test_dir_path, .default_dir); |
| 1098 | try testing.expectError(error.IsDir, ctx.dir.rename(test_file_path, ctx.dir, test_dir_path, io)); | 1041 | try expectError(error.IsDir, ctx.dir.rename(test_file_path, ctx.dir, test_dir_path, io)); |
| 1099 | try testing.expectError(error.NotDir, ctx.dir.rename(test_dir_path, ctx.dir, test_file_path, io)); | 1042 | try expectError(error.NotDir, ctx.dir.rename(test_dir_path, ctx.dir, test_file_path, io)); |
| 1100 | } | 1043 | } |
| 1101 | }.impl); | 1044 | }.impl); |
| 1102 | } | 1045 | } |
| ... | @@ -1118,7 +1061,7 @@ test "rename" { | ... | @@ -1118,7 +1061,7 @@ test "rename" { |
| 1118 | try Dir.rename(tmp_dir1.dir, test_file_name, tmp_dir2.dir, renamed_test_file_name, io); | 1061 | try Dir.rename(tmp_dir1.dir, test_file_name, tmp_dir2.dir, renamed_test_file_name, io); |
| 1119 | | 1062 | |
| 1120 | // ensure the file was renamed | 1063 | // ensure the file was renamed |
| 1121 | try testing.expectError(error.FileNotFound, tmp_dir1.dir.openFile(io, test_file_name, .{})); | 1064 | try expectError(error.FileNotFound, tmp_dir1.dir.openFile(io, test_file_name, .{})); |
| 1122 | file = try tmp_dir2.dir.openFile(io, renamed_test_file_name, .{}); | 1065 | file = try tmp_dir2.dir.openFile(io, renamed_test_file_name, .{}); |
| 1123 | file.close(io); | 1066 | file.close(io); |
| 1124 | } | 1067 | } |
| ... | @@ -1139,7 +1082,7 @@ test "renameAbsolute" { | ... | @@ -1139,7 +1082,7 @@ test "renameAbsolute" { |
| 1139 | | 1082 | |
| 1140 | const base_path = try tmp_dir.dir.realpathAlloc(allocator, "."); | 1083 | const base_path = try tmp_dir.dir.realpathAlloc(allocator, "."); |
| 1141 | | 1084 | |
| 1142 | try testing.expectError(error.FileNotFound, fs.renameAbsolute( | 1085 | try expectError(error.FileNotFound, fs.renameAbsolute( |
| 1143 | try fs.path.join(allocator, &.{ base_path, "missing_file_name" }), | 1086 | try fs.path.join(allocator, &.{ base_path, "missing_file_name" }), |
| 1144 | try fs.path.join(allocator, &.{ base_path, "something_else" }), | 1087 | try fs.path.join(allocator, &.{ base_path, "something_else" }), |
| 1145 | )); | 1088 | )); |
| ... | @@ -1155,10 +1098,10 @@ test "renameAbsolute" { | ... | @@ -1155,10 +1098,10 @@ test "renameAbsolute" { |
| 1155 | ); | 1098 | ); |
| 1156 | | 1099 | |
| 1157 | // ensure the file was renamed | 1100 | // ensure the file was renamed |
| 1158 | try testing.expectError(error.FileNotFound, tmp_dir.dir.openFile(io, test_file_name, .{})); | 1101 | try expectError(error.FileNotFound, tmp_dir.dir.openFile(io, test_file_name, .{})); |
| 1159 | file = try tmp_dir.dir.openFile(io, renamed_test_file_name, .{}); | 1102 | file = try tmp_dir.dir.openFile(io, renamed_test_file_name, .{}); |
| 1160 | const stat = try file.stat(io); | 1103 | const stat = try file.stat(io); |
| 1161 | try testing.expectEqual(File.Kind.file, stat.kind); | 1104 | try expectEqual(File.Kind.file, stat.kind); |
| 1162 | file.close(io); | 1105 | file.close(io); |
| 1163 | | 1106 | |
| 1164 | // Renaming directories | 1107 | // Renaming directories |
| ... | @@ -1171,7 +1114,7 @@ test "renameAbsolute" { | ... | @@ -1171,7 +1114,7 @@ test "renameAbsolute" { |
| 1171 | ); | 1114 | ); |
| 1172 | | 1115 | |
| 1173 | // ensure the directory was renamed | 1116 | // ensure the directory was renamed |
| 1174 | try testing.expectError(error.FileNotFound, tmp_dir.dir.openDir(io, test_dir_name, .{})); | 1117 | try expectError(error.FileNotFound, tmp_dir.dir.openDir(io, test_dir_name, .{})); |
| 1175 | var dir = try tmp_dir.dir.openDir(io, renamed_test_dir_name, .{}); | 1118 | var dir = try tmp_dir.dir.openDir(io, renamed_test_dir_name, .{}); |
| 1176 | dir.close(io); | 1119 | dir.close(io); |
| 1177 | } | 1120 | } |
| ... | @@ -1193,7 +1136,7 @@ test "executablePath" { | ... | @@ -1193,7 +1136,7 @@ test "executablePath" { |
| 1193 | const buf_self_exe_path = try std.process.executablePath(io, &buf); | 1136 | const buf_self_exe_path = try std.process.executablePath(io, &buf); |
| 1194 | const alloc_self_exe_path = try std.process.executablePathAlloc(io, testing.allocator); | 1137 | const alloc_self_exe_path = try std.process.executablePathAlloc(io, testing.allocator); |
| 1195 | defer testing.allocator.free(alloc_self_exe_path); | 1138 | defer testing.allocator.free(alloc_self_exe_path); |
| 1196 | try testing.expectEqualSlices(u8, buf_self_exe_path, alloc_self_exe_path); | 1139 | try expectEqualSlices(u8, buf_self_exe_path, alloc_self_exe_path); |
| 1197 | } | 1140 | } |
| 1198 | | 1141 | |
| 1199 | test "deleteTree does not follow symlinks" { | 1142 | test "deleteTree does not follow symlinks" { |
| ... | @@ -1212,7 +1155,7 @@ test "deleteTree does not follow symlinks" { | ... | @@ -1212,7 +1155,7 @@ test "deleteTree does not follow symlinks" { |
| 1212 | | 1155 | |
| 1213 | try tmp.dir.deleteTree(io, "a"); | 1156 | try tmp.dir.deleteTree(io, "a"); |
| 1214 | | 1157 | |
| 1215 | try testing.expectError(error.FileNotFound, tmp.dir.access(io, "a", .{})); | 1158 | try expectError(error.FileNotFound, tmp.dir.access(io, "a", .{})); |
| 1216 | try tmp.dir.access(io, "b", .{}); | 1159 | try tmp.dir.access(io, "b", .{}); |
| 1217 | } | 1160 | } |
| 1218 | | 1161 | |
| ... | @@ -1227,7 +1170,7 @@ test "deleteTree on a symlink" { | ... | @@ -1227,7 +1170,7 @@ test "deleteTree on a symlink" { |
| 1227 | try setupSymlink(io, tmp.dir, "file", "filelink", .{}); | 1170 | try setupSymlink(io, tmp.dir, "file", "filelink", .{}); |
| 1228 | | 1171 | |
| 1229 | try tmp.dir.deleteTree(io, "filelink"); | 1172 | try tmp.dir.deleteTree(io, "filelink"); |
| 1230 | try testing.expectError(error.FileNotFound, tmp.dir.access(io, "filelink", .{})); | 1173 | try expectError(error.FileNotFound, tmp.dir.access(io, "filelink", .{})); |
| 1231 | try tmp.dir.access(io, "file", .{}); | 1174 | try tmp.dir.access(io, "file", .{}); |
| 1232 | | 1175 | |
| 1233 | // Symlink to a directory | 1176 | // Symlink to a directory |
| ... | @@ -1235,7 +1178,7 @@ test "deleteTree on a symlink" { | ... | @@ -1235,7 +1178,7 @@ test "deleteTree on a symlink" { |
| 1235 | try setupSymlink(io, tmp.dir, "dir", "dirlink", .{ .is_directory = true }); | 1178 | try setupSymlink(io, tmp.dir, "dir", "dirlink", .{ .is_directory = true }); |
| 1236 | | 1179 | |
| 1237 | try tmp.dir.deleteTree(io, "dirlink"); | 1180 | try tmp.dir.deleteTree(io, "dirlink"); |
| 1238 | try testing.expectError(error.FileNotFound, tmp.dir.access(io, "dirlink", .{})); | 1181 | try expectError(error.FileNotFound, tmp.dir.access(io, "dirlink", .{})); |
| 1239 | try tmp.dir.access(io, "dir", .{}); | 1182 | try tmp.dir.access(io, "dir", .{}); |
| 1240 | } | 1183 | } |
| 1241 | | 1184 | |
| ... | @@ -1257,7 +1200,7 @@ test "makePath, put some files in it, deleteTree" { | ... | @@ -1257,7 +1200,7 @@ test "makePath, put some files in it, deleteTree" { |
| 1257 | }); | 1200 | }); |
| 1258 | | 1201 | |
| 1259 | try ctx.dir.deleteTree(io, dir_path); | 1202 | try ctx.dir.deleteTree(io, dir_path); |
| 1260 | try testing.expectError(error.FileNotFound, ctx.dir.openDir(io, dir_path, .{})); | 1203 | try expectError(error.FileNotFound, ctx.dir.openDir(io, dir_path, .{})); |
| 1261 | } | 1204 | } |
| 1262 | }.impl); | 1205 | }.impl); |
| 1263 | } | 1206 | } |
| ... | @@ -1280,7 +1223,7 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { | ... | @@ -1280,7 +1223,7 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { |
| 1280 | }); | 1223 | }); |
| 1281 | | 1224 | |
| 1282 | try ctx.dir.deleteTreeMinStackSize(dir_path); | 1225 | try ctx.dir.deleteTreeMinStackSize(dir_path); |
| 1283 | try testing.expectError(error.FileNotFound, ctx.dir.openDir(io, dir_path, .{})); | 1226 | try expectError(error.FileNotFound, ctx.dir.openDir(io, dir_path, .{})); |
| 1284 | } | 1227 | } |
| 1285 | }.impl); | 1228 | }.impl); |
| 1286 | } | 1229 | } |
| ... | @@ -1294,7 +1237,7 @@ test "makePath in a directory that no longer exists" { | ... | @@ -1294,7 +1237,7 @@ test "makePath in a directory that no longer exists" { |
| 1294 | defer tmp.cleanup(); | 1237 | defer tmp.cleanup(); |
| 1295 | try tmp.parent_dir.deleteTree(io, &tmp.sub_path); | 1238 | try tmp.parent_dir.deleteTree(io, &tmp.sub_path); |
| 1296 | | 1239 | |
| 1297 | try testing.expectError(error.FileNotFound, tmp.dir.makePath(io, "sub-path")); | 1240 | try expectError(error.FileNotFound, tmp.dir.makePath(io, "sub-path")); |
| 1298 | } | 1241 | } |
| 1299 | | 1242 | |
| 1300 | test "makePath but sub_path contains pre-existing file" { | 1243 | test "makePath but sub_path contains pre-existing file" { |
| ... | @@ -1306,7 +1249,7 @@ test "makePath but sub_path contains pre-existing file" { | ... | @@ -1306,7 +1249,7 @@ test "makePath but sub_path contains pre-existing file" { |
| 1306 | try tmp.dir.makeDir(io, "foo", .default_dir); | 1249 | try tmp.dir.makeDir(io, "foo", .default_dir); |
| 1307 | try tmp.dir.writeFile(io, .{ .sub_path = "foo/bar", .data = "" }); | 1250 | try tmp.dir.writeFile(io, .{ .sub_path = "foo/bar", .data = "" }); |
| 1308 | | 1251 | |
| 1309 | try testing.expectError(error.NotDir, tmp.dir.makePath(io, "foo/bar/baz")); | 1252 | try expectError(error.NotDir, tmp.dir.makePath(io, "foo/bar/baz")); |
| 1310 | } | 1253 | } |
| 1311 | | 1254 | |
| 1312 | fn expectDir(io: Io, dir: Dir, path: []const u8) !void { | 1255 | fn expectDir(io: Io, dir: Dir, path: []const u8) !void { |
| ... | @@ -1364,8 +1307,8 @@ test "makepath relative walks" { | ... | @@ -1364,8 +1307,8 @@ test "makepath relative walks" { |
| 1364 | // On Windows, .. is resolved before passing the path to NtCreateFile, | 1307 | // On Windows, .. is resolved before passing the path to NtCreateFile, |
| 1365 | // meaning everything except `first/C` drops out. | 1308 | // meaning everything except `first/C` drops out. |
| 1366 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "C"); | 1309 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "C"); |
| 1367 | try testing.expectError(error.FileNotFound, tmp.dir.access(io, "second", .{})); | 1310 | try expectError(error.FileNotFound, tmp.dir.access(io, "second", .{})); |
| 1368 | try testing.expectError(error.FileNotFound, tmp.dir.access(io, "third", .{})); | 1311 | try expectError(error.FileNotFound, tmp.dir.access(io, "third", .{})); |
| 1369 | }, | 1312 | }, |
| 1370 | else => { | 1313 | else => { |
| 1371 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "A"); | 1314 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "A"); |
| ... | @@ -1413,10 +1356,10 @@ fn testFilenameLimits(io: Io, iterable_dir: Dir, maxed_filename: []const u8) !vo | ... | @@ -1413,10 +1356,10 @@ fn testFilenameLimits(io: Io, iterable_dir: Dir, maxed_filename: []const u8) !vo |
| 1413 | | 1356 | |
| 1414 | var count: usize = 0; | 1357 | var count: usize = 0; |
| 1415 | while (try walker.next()) |entry| { | 1358 | while (try walker.next()) |entry| { |
| 1416 | try testing.expectEqualStrings(maxed_filename, entry.basename); | 1359 | try expectEqualStrings(maxed_filename, entry.basename); |
| 1417 | count += 1; | 1360 | count += 1; |
| 1418 | } | 1361 | } |
| 1419 | try testing.expectEqual(@as(usize, 2), count); | 1362 | try expectEqual(@as(usize, 2), count); |
| 1420 | } | 1363 | } |
| 1421 | | 1364 | |
| 1422 | // ensure that we can delete the tree | 1365 | // ensure that we can delete the tree |
| ... | @@ -1467,14 +1410,14 @@ test "writev, readv" { | ... | @@ -1467,14 +1410,14 @@ test "writev, readv" { |
| 1467 | | 1410 | |
| 1468 | try writer.interface.writeVecAll(&write_vecs); | 1411 | try writer.interface.writeVecAll(&write_vecs); |
| 1469 | try writer.interface.flush(); | 1412 | try writer.interface.flush(); |
| 1470 | try testing.expectEqual(@as(u64, line1.len + line2.len), try src_file.length(io)); | 1413 | try expectEqual(@as(u64, line1.len + line2.len), try src_file.length(io)); |
| 1471 | | 1414 | |
| 1472 | var reader = writer.moveToReader(io); | 1415 | var reader = writer.moveToReader(io); |
| 1473 | try reader.seekTo(0); | 1416 | try reader.seekTo(0); |
| 1474 | try reader.interface.readVecAll(&read_vecs); | 1417 | try reader.interface.readVecAll(&read_vecs); |
| 1475 | try testing.expectEqualStrings(&buf1, "line2\n"); | 1418 | try expectEqualStrings(&buf1, "line2\n"); |
| 1476 | try testing.expectEqualStrings(&buf2, "line1\n"); | 1419 | try expectEqualStrings(&buf2, "line1\n"); |
| 1477 | try testing.expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); | 1420 | try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); |
| 1478 | } | 1421 | } |
| 1479 | | 1422 | |
| 1480 | test "pwritev, preadv" { | 1423 | test "pwritev, preadv" { |
| ... | @@ -1498,14 +1441,14 @@ test "pwritev, preadv" { | ... | @@ -1498,14 +1441,14 @@ test "pwritev, preadv" { |
| 1498 | try writer.seekTo(16); | 1441 | try writer.seekTo(16); |
| 1499 | try writer.interface.writeVecAll(&lines); | 1442 | try writer.interface.writeVecAll(&lines); |
| 1500 | try writer.interface.flush(); | 1443 | try writer.interface.flush(); |
| 1501 | try testing.expectEqual(@as(u64, 16 + line1.len + line2.len), try src_file.length(io)); | 1444 | try expectEqual(@as(u64, 16 + line1.len + line2.len), try src_file.length(io)); |
| 1502 | | 1445 | |
| 1503 | var reader = writer.moveToReader(io); | 1446 | var reader = writer.moveToReader(io); |
| 1504 | try reader.seekTo(16); | 1447 | try reader.seekTo(16); |
| 1505 | try reader.interface.readVecAll(&read_vecs); | 1448 | try reader.interface.readVecAll(&read_vecs); |
| 1506 | try testing.expectEqualStrings(&buf1, "line2\n"); | 1449 | try expectEqualStrings(&buf1, "line2\n"); |
| 1507 | try testing.expectEqualStrings(&buf2, "line1\n"); | 1450 | try expectEqualStrings(&buf2, "line1\n"); |
| 1508 | try testing.expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); | 1451 | try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); |
| 1509 | } | 1452 | } |
| 1510 | | 1453 | |
| 1511 | test "setEndPos" { | 1454 | test "setEndPos" { |
| ... | @@ -1529,34 +1472,34 @@ test "setEndPos" { | ... | @@ -1529,34 +1472,34 @@ test "setEndPos" { |
| 1529 | | 1472 | |
| 1530 | { | 1473 | { |
| 1531 | try f.setEndPos(initial_size); | 1474 | try f.setEndPos(initial_size); |
| 1532 | try testing.expectEqual(initial_size, try f.length(io)); | 1475 | try expectEqual(initial_size, try f.length(io)); |
| 1533 | try reader.seekTo(0); | 1476 | try reader.seekTo(0); |
| 1534 | try testing.expectEqual(initial_size, try reader.interface.readSliceShort(&buffer)); | 1477 | try expectEqual(initial_size, try reader.interface.readSliceShort(&buffer)); |
| 1535 | try testing.expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]); | 1478 | try expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]); |
| 1536 | } | 1479 | } |
| 1537 | | 1480 | |
| 1538 | { | 1481 | { |
| 1539 | const larger = initial_size + 4; | 1482 | const larger = initial_size + 4; |
| 1540 | try f.setEndPos(larger); | 1483 | try f.setEndPos(larger); |
| 1541 | try testing.expectEqual(larger, try f.length(io)); | 1484 | try expectEqual(larger, try f.length(io)); |
| 1542 | try reader.seekTo(0); | 1485 | try reader.seekTo(0); |
| 1543 | try testing.expectEqual(larger, try reader.interface.readSliceShort(&buffer)); | 1486 | try expectEqual(larger, try reader.interface.readSliceShort(&buffer)); |
| 1544 | try testing.expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]); | 1487 | try expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]); |
| 1545 | } | 1488 | } |
| 1546 | | 1489 | |
| 1547 | { | 1490 | { |
| 1548 | const smaller = initial_size - 5; | 1491 | const smaller = initial_size - 5; |
| 1549 | try f.setEndPos(smaller); | 1492 | try f.setEndPos(smaller); |
| 1550 | try testing.expectEqual(smaller, try f.length(io)); | 1493 | try expectEqual(smaller, try f.length(io)); |
| 1551 | try reader.seekTo(0); | 1494 | try reader.seekTo(0); |
| 1552 | try testing.expectEqual(smaller, try reader.interface.readSliceShort(&buffer)); | 1495 | try expectEqual(smaller, try reader.interface.readSliceShort(&buffer)); |
| 1553 | try testing.expectEqualStrings("nine", buffer[0..@intCast(smaller)]); | 1496 | try expectEqualStrings("nine", buffer[0..@intCast(smaller)]); |
| 1554 | } | 1497 | } |
| 1555 | | 1498 | |
| 1556 | try f.setEndPos(0); | 1499 | try f.setEndPos(0); |
| 1557 | try testing.expectEqual(0, try f.length(io)); | 1500 | try expectEqual(0, try f.length(io)); |
| 1558 | try reader.seekTo(0); | 1501 | try reader.seekTo(0); |
| 1559 | try testing.expectEqual(0, try reader.interface.readSliceShort(&buffer)); | 1502 | try expectEqual(0, try reader.interface.readSliceShort(&buffer)); |
| 1560 | } | 1503 | } |
| 1561 | | 1504 | |
| 1562 | test "access file" { | 1505 | test "access file" { |
| ... | @@ -1567,7 +1510,7 @@ test "access file" { | ... | @@ -1567,7 +1510,7 @@ test "access file" { |
| 1567 | const file_path = try ctx.transformPath("os_test_tmp" ++ fs.path.sep_str ++ "file.txt"); | 1510 | const file_path = try ctx.transformPath("os_test_tmp" ++ fs.path.sep_str ++ "file.txt"); |
| 1568 | | 1511 | |
| 1569 | try ctx.dir.makePath(io, dir_path); | 1512 | try ctx.dir.makePath(io, dir_path); |
| 1570 | try testing.expectError(error.FileNotFound, ctx.dir.access(io, file_path, .{})); | 1513 | try expectError(error.FileNotFound, ctx.dir.access(io, file_path, .{})); |
| 1571 | | 1514 | |
| 1572 | try ctx.dir.writeFile(io, .{ .sub_path = file_path, .data = "" }); | 1515 | try ctx.dir.writeFile(io, .{ .sub_path = file_path, .data = "" }); |
| 1573 | try ctx.dir.access(io, file_path, .{}); | 1516 | try ctx.dir.access(io, file_path, .{}); |
| ... | @@ -1614,13 +1557,13 @@ test "sendfile" { | ... | @@ -1614,13 +1557,13 @@ test "sendfile" { |
| 1614 | var file_writer = dest_file.writer(io, &fallback_buffer); | 1557 | var file_writer = dest_file.writer(io, &fallback_buffer); |
| 1615 | try file_writer.interface.writeVecAll(&headers); | 1558 | try file_writer.interface.writeVecAll(&headers); |
| 1616 | try file_reader.seekTo(1); | 1559 | try file_reader.seekTo(1); |
| 1617 | try testing.expectEqual(10, try file_writer.interface.sendFileAll(&file_reader, .limited(10))); | 1560 | try expectEqual(10, try file_writer.interface.sendFileAll(&file_reader, .limited(10))); |
| 1618 | try file_writer.interface.writeVecAll(&trailers); | 1561 | try file_writer.interface.writeVecAll(&trailers); |
| 1619 | try file_writer.interface.flush(); | 1562 | try file_writer.interface.flush(); |
| 1620 | var fr = file_writer.moveToReader(io); | 1563 | var fr = file_writer.moveToReader(io); |
| 1621 | try fr.seekTo(0); | 1564 | try fr.seekTo(0); |
| 1622 | const amt = try fr.interface.readSliceShort(&written_buf); | 1565 | const amt = try fr.interface.readSliceShort(&written_buf); |
| 1623 | try testing.expectEqualStrings("header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n", written_buf[0..amt]); | 1566 | try expectEqualStrings("header1\nsecond header\nine1\nsecontrailer1\nsecond trailer\n", written_buf[0..amt]); |
| 1624 | } | 1567 | } |
| 1625 | | 1568 | |
| 1626 | test "sendfile with buffered data" { | 1569 | test "sendfile with buffered data" { |
| ... | @@ -1651,15 +1594,15 @@ test "sendfile with buffered data" { | ... | @@ -1651,15 +1594,15 @@ test "sendfile with buffered data" { |
| 1651 | var fallback_buffer: [32]u8 = undefined; | 1594 | var fallback_buffer: [32]u8 = undefined; |
| 1652 | var file_writer = dest_file.writer(io, &fallback_buffer); | 1595 | var file_writer = dest_file.writer(io, &fallback_buffer); |
| 1653 | | 1596 | |
| 1654 | try std.testing.expectEqual(4, try file_writer.interface.sendFileAll(&file_reader, .limited(4))); | 1597 | try expectEqual(4, try file_writer.interface.sendFileAll(&file_reader, .limited(4))); |
| 1655 | | 1598 | |
| 1656 | var written_buf: [8]u8 = undefined; | 1599 | var written_buf: [8]u8 = undefined; |
| 1657 | var fr = file_writer.moveToReader(io); | 1600 | var fr = file_writer.moveToReader(io); |
| 1658 | try fr.seekTo(0); | 1601 | try fr.seekTo(0); |
| 1659 | const amt = try fr.interface.readSliceShort(&written_buf); | 1602 | const amt = try fr.interface.readSliceShort(&written_buf); |
| 1660 | | 1603 | |
| 1661 | try std.testing.expectEqual(4, amt); | 1604 | try expectEqual(4, amt); |
| 1662 | try std.testing.expectEqualSlices(u8, "AAAA", written_buf[0..amt]); | 1605 | try expectEqualSlices(u8, "AAAA", written_buf[0..amt]); |
| 1663 | } | 1606 | } |
| 1664 | | 1607 | |
| 1665 | test "copyFile" { | 1608 | test "copyFile" { |
| ... | @@ -1690,7 +1633,7 @@ fn expectFileContents(io: Io, dir: Dir, file_path: []const u8, data: []const u8) | ... | @@ -1690,7 +1633,7 @@ fn expectFileContents(io: Io, dir: Dir, file_path: []const u8, data: []const u8) |
| 1690 | const contents = try dir.readFileAlloc(io, file_path, testing.allocator, .limited(1000)); | 1633 | const contents = try dir.readFileAlloc(io, file_path, testing.allocator, .limited(1000)); |
| 1691 | defer testing.allocator.free(contents); | 1634 | defer testing.allocator.free(contents); |
| 1692 | | 1635 | |
| 1693 | try testing.expectEqualSlices(u8, data, contents); | 1636 | try expectEqualSlices(u8, data, contents); |
| 1694 | } | 1637 | } |
| 1695 | | 1638 | |
| 1696 | test "AtomicFile" { | 1639 | test "AtomicFile" { |
| ... | @@ -1712,7 +1655,7 @@ test "AtomicFile" { | ... | @@ -1712,7 +1655,7 @@ test "AtomicFile" { |
| 1712 | try af.finish(); | 1655 | try af.finish(); |
| 1713 | } | 1656 | } |
| 1714 | const content = try ctx.dir.readFileAlloc(io, test_out_file, allocator, .limited(9999)); | 1657 | const content = try ctx.dir.readFileAlloc(io, test_out_file, allocator, .limited(9999)); |
| 1715 | try testing.expectEqualStrings(test_content, content); | 1658 | try expectEqualStrings(test_content, content); |
| 1716 | | 1659 | |
| 1717 | try ctx.dir.deleteFile(io, test_out_file); | 1660 | try ctx.dir.deleteFile(io, test_out_file); |
| 1718 | } | 1661 | } |
| ... | @@ -1731,7 +1674,7 @@ test "open file with exclusive nonblocking lock twice" { | ... | @@ -1731,7 +1674,7 @@ test "open file with exclusive nonblocking lock twice" { |
| 1731 | defer file1.close(io); | 1674 | defer file1.close(io); |
| 1732 | | 1675 | |
| 1733 | const file2 = ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); | 1676 | const file2 = ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); |
| 1734 | try testing.expectError(error.WouldBlock, file2); | 1677 | try expectError(error.WouldBlock, file2); |
| 1735 | } | 1678 | } |
| 1736 | }.impl); | 1679 | }.impl); |
| 1737 | } | 1680 | } |
| ... | @@ -1748,7 +1691,7 @@ test "open file with shared and exclusive nonblocking lock" { | ... | @@ -1748,7 +1691,7 @@ test "open file with shared and exclusive nonblocking lock" { |
| 1748 | defer file1.close(io); | 1691 | defer file1.close(io); |
| 1749 | | 1692 | |
| 1750 | const file2 = ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); | 1693 | const file2 = ctx.dir.createFile(io, filename, .{ .lock = .exclusive, .lock_nonblocking = true }); |
| 1751 | try testing.expectError(error.WouldBlock, file2); | 1694 | try expectError(error.WouldBlock, file2); |
| 1752 | } | 1695 | } |
| 1753 | }.impl); | 1696 | }.impl); |
| 1754 | } | 1697 | } |
| ... | @@ -1765,7 +1708,7 @@ test "open file with exclusive and shared nonblocking lock" { | ... | @@ -1765,7 +1708,7 @@ test "open file with exclusive and shared nonblocking lock" { |
| 1765 | defer file1.close(io); | 1708 | defer file1.close(io); |
| 1766 | | 1709 | |
| 1767 | const file2 = ctx.dir.createFile(io, filename, .{ .lock = .shared, .lock_nonblocking = true }); | 1710 | const file2 = ctx.dir.createFile(io, filename, .{ .lock = .shared, .lock_nonblocking = true }); |
| 1768 | try testing.expectError(error.WouldBlock, file2); | 1711 | try expectError(error.WouldBlock, file2); |
| 1769 | } | 1712 | } |
| 1770 | }.impl); | 1713 | }.impl); |
| 1771 | } | 1714 | } |
| ... | @@ -1805,7 +1748,7 @@ test "open file with exclusive lock twice, make sure second lock waits" { | ... | @@ -1805,7 +1748,7 @@ test "open file with exclusive lock twice, make sure second lock waits" { |
| 1805 | // Wait for the spawned thread to start trying to acquire the exclusive file lock. | 1748 | // Wait for the spawned thread to start trying to acquire the exclusive file lock. |
| 1806 | // Then wait a bit to make sure that can't acquire it since we currently hold the file lock. | 1749 | // Then wait a bit to make sure that can't acquire it since we currently hold the file lock. |
| 1807 | started.wait(); | 1750 | started.wait(); |
| 1808 | try testing.expectError(error.Timeout, locked.timedWait(10 * std.time.ns_per_ms)); | 1751 | try expectError(error.Timeout, locked.timedWait(10 * std.time.ns_per_ms)); |
| 1809 | | 1752 | |
| 1810 | // Release the file lock which should unlock the thread to lock it and set the locked event. | 1753 | // Release the file lock which should unlock the thread to lock it and set the locked event. |
| 1811 | file.close(io); | 1754 | file.close(io); |
| ... | @@ -1846,7 +1789,7 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { | ... | @@ -1846,7 +1789,7 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { |
| 1846 | .lock_nonblocking = true, | 1789 | .lock_nonblocking = true, |
| 1847 | }); | 1790 | }); |
| 1848 | file1.close(io); | 1791 | file1.close(io); |
| 1849 | try testing.expectError(error.WouldBlock, file2); | 1792 | try expectError(error.WouldBlock, file2); |
| 1850 | } | 1793 | } |
| 1851 | | 1794 | |
| 1852 | test "read from locked file" { | 1795 | test "read from locked file" { |
| ... | @@ -1871,9 +1814,9 @@ test "read from locked file" { | ... | @@ -1871,9 +1814,9 @@ test "read from locked file" { |
| 1871 | defer f2.close(io); | 1814 | defer f2.close(io); |
| 1872 | var buffer: [1]u8 = undefined; | 1815 | var buffer: [1]u8 = undefined; |
| 1873 | if (builtin.os.tag == .windows) { | 1816 | if (builtin.os.tag == .windows) { |
| 1874 | try std.testing.expectError(error.LockViolation, f2.read(&buffer)); | 1817 | try expectError(error.LockViolation, f2.read(&buffer)); |
| 1875 | } else { | 1818 | } else { |
| 1876 | try std.testing.expectEqual(0, f2.read(&buffer)); | 1819 | try expectEqual(0, f2.read(&buffer)); |
| 1877 | } | 1820 | } |
| 1878 | } | 1821 | } |
| 1879 | } | 1822 | } |
| ... | @@ -1925,7 +1868,7 @@ test "walker" { | ... | @@ -1925,7 +1868,7 @@ test "walker" { |
| 1925 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); | 1868 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1926 | return err; | 1869 | return err; |
| 1927 | }; | 1870 | }; |
| 1928 | testing.expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| { | 1871 | expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| { |
| 1929 | std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); | 1872 | std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1930 | return err; | 1873 | return err; |
| 1931 | }; | 1874 | }; |
| ... | @@ -1934,7 +1877,7 @@ test "walker" { | ... | @@ -1934,7 +1877,7 @@ test "walker" { |
| 1934 | defer entry_dir.close(io); | 1877 | defer entry_dir.close(io); |
| 1935 | num_walked += 1; | 1878 | num_walked += 1; |
| 1936 | } | 1879 | } |
| 1937 | try testing.expectEqual(expected_paths.kvs.len, num_walked); | 1880 | try expectEqual(expected_paths.kvs.len, num_walked); |
| 1938 | } | 1881 | } |
| 1939 | | 1882 | |
| 1940 | test "selective walker, skip entries that start with ." { | 1883 | test "selective walker, skip entries that start with ." { |
| ... | @@ -1992,7 +1935,7 @@ test "selective walker, skip entries that start with ." { | ... | @@ -1992,7 +1935,7 @@ test "selective walker, skip entries that start with ." { |
| 1992 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); | 1935 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1993 | return err; | 1936 | return err; |
| 1994 | }; | 1937 | }; |
| 1995 | testing.expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| { | 1938 | expectEqual(expected_paths.get(entry.path).?, entry.depth()) catch |err| { |
| 1996 | std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); | 1939 | std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1997 | return err; | 1940 | return err; |
| 1998 | }; | 1941 | }; |
| ... | @@ -2002,7 +1945,7 @@ test "selective walker, skip entries that start with ." { | ... | @@ -2002,7 +1945,7 @@ test "selective walker, skip entries that start with ." { |
| 2002 | defer entry_dir.close(io); | 1945 | defer entry_dir.close(io); |
| 2003 | num_walked += 1; | 1946 | num_walked += 1; |
| 2004 | } | 1947 | } |
| 2005 | try testing.expectEqual(expected_paths.kvs.len, num_walked); | 1948 | try expectEqual(expected_paths.kvs.len, num_walked); |
| 2006 | } | 1949 | } |
| 2007 | | 1950 | |
| 2008 | test "walker without fully iterating" { | 1951 | test "walker without fully iterating" { |
| ... | @@ -2025,7 +1968,7 @@ test "walker without fully iterating" { | ... | @@ -2025,7 +1968,7 @@ test "walker without fully iterating" { |
| 2025 | num_walked += 1; | 1968 | num_walked += 1; |
| 2026 | break; | 1969 | break; |
| 2027 | } | 1970 | } |
| 2028 | try testing.expectEqual(@as(usize, 1), num_walked); | 1971 | try expectEqual(@as(usize, 1), num_walked); |
| 2029 | } | 1972 | } |
| 2030 | | 1973 | |
| 2031 | test "'.' and '..' in Io.Dir functions" { | 1974 | test "'.' and '..' in Io.Dir functions" { |
| ... | @@ -2061,7 +2004,7 @@ test "'.' and '..' in Io.Dir functions" { | ... | @@ -2061,7 +2004,7 @@ test "'.' and '..' in Io.Dir functions" { |
| 2061 | try ctx.dir.writeFile(io, .{ .sub_path = update_path, .data = "something" }); | 2004 | try ctx.dir.writeFile(io, .{ .sub_path = update_path, .data = "something" }); |
| 2062 | var dir = ctx.dir; | 2005 | var dir = ctx.dir; |
| 2063 | const prev_status = try dir.updateFile(io, file_path, dir, update_path, .{}); | 2006 | const prev_status = try dir.updateFile(io, file_path, dir, update_path, .{}); |
| 2064 | try testing.expectEqual(Io.Dir.PrevStatus.stale, prev_status); | 2007 | try expectEqual(Io.Dir.PrevStatus.stale, prev_status); |
| 2065 | | 2008 | |
| 2066 | try ctx.dir.deleteDir(io, subdir_path); | 2009 | try ctx.dir.deleteDir(io, subdir_path); |
| 2067 | } | 2010 | } |
| ... | @@ -2106,8 +2049,7 @@ test "'.' and '..' in absolute functions" { | ... | @@ -2106,8 +2049,7 @@ test "'.' and '..' in absolute functions" { |
| 2106 | } | 2049 | } |
| 2107 | | 2050 | |
| 2108 | test "chmod" { | 2051 | test "chmod" { |
| 2109 | if (native_os == .windows or native_os == .wasi) | 2052 | if (native_os == .windows or native_os == .wasi) return; |
| 2110 | return error.SkipZigTest; | | |
| 2111 | | 2053 | |
| 2112 | const io = testing.io; | 2054 | const io = testing.io; |
| 2113 | | 2055 | |
| ... | @@ -2116,17 +2058,17 @@ test "chmod" { | ... | @@ -2116,17 +2058,17 @@ test "chmod" { |
| 2116 | | 2058 | |
| 2117 | const file = try tmp.dir.createFile(io, "test_file", .{ .permissions = .fromMode(0o600) }); | 2059 | const file = try tmp.dir.createFile(io, "test_file", .{ .permissions = .fromMode(0o600) }); |
| 2118 | defer file.close(io); | 2060 | defer file.close(io); |
| 2119 | try testing.expectEqual(@as(posix.mode_t, 0o600), (try file.stat(io)).permissions.toMode() & 0o7777); | 2061 | try expectEqual(0o600, (try file.stat(io)).permissions.toMode() & 0o7777); |
| 2120 | | 2062 | |
| 2121 | try file.setPermissions(io, .fromMode(0o644)); | 2063 | try file.setPermissions(io, .fromMode(0o644)); |
| 2122 | try testing.expectEqual(@as(posix.mode_t, 0o644), (try file.stat(io)).permissions.toMode() & 0o7777); | 2064 | try expectEqual(0o644, (try file.stat(io)).permissions.toMode() & 0o7777); |
| 2123 | | 2065 | |
| 2124 | try tmp.dir.makeDir(io, "test_dir", .default_dir); | 2066 | try tmp.dir.makeDir(io, "test_dir", .default_dir); |
| 2125 | var dir = try tmp.dir.openDir(io, "test_dir", .{ .iterate = true }); | 2067 | var dir = try tmp.dir.openDir(io, "test_dir", .{ .iterate = true }); |
| 2126 | defer dir.close(io); | 2068 | defer dir.close(io); |
| 2127 | | 2069 | |
| 2128 | try dir.setPermissions(io, .fromMode(0o700)); | 2070 | try dir.setPermissions(io, .fromMode(0o700)); |
| 2129 | try testing.expectEqual(@as(posix.mode_t, 0o700), (try dir.stat(io)).permissions.toMode() & 0o7777); | 2071 | try expectEqual(0o700, (try dir.stat(io)).permissions.toMode() & 0o7777); |
| 2130 | } | 2072 | } |
| 2131 | | 2073 | |
| 2132 | test "chown" { | 2074 | test "chown" { |
| ... | @@ -2162,70 +2104,70 @@ test "invalid UTF-8/WTF-8 paths" { | ... | @@ -2162,70 +2104,70 @@ test "invalid UTF-8/WTF-8 paths" { |
| 2162 | // This is both invalid UTF-8 and WTF-8, since \xFF is an invalid start byte | 2104 | // This is both invalid UTF-8 and WTF-8, since \xFF is an invalid start byte |
| 2163 | const invalid_path = try ctx.transformPath("\xFF"); | 2105 | const invalid_path = try ctx.transformPath("\xFF"); |
| 2164 | | 2106 | |
| 2165 | try testing.expectError(expected_err, ctx.dir.openFile(invalid_path, .{})); | 2107 | try expectError(expected_err, ctx.dir.openFile(invalid_path, .{})); |
| 2166 | | 2108 | |
| 2167 | try testing.expectError(expected_err, ctx.dir.createFile(invalid_path, .{})); | 2109 | try expectError(expected_err, ctx.dir.createFile(invalid_path, .{})); |
| 2168 | | 2110 | |
| 2169 | try testing.expectError(expected_err, ctx.dir.makeDir(invalid_path, .default_dir)); | 2111 | try expectError(expected_err, ctx.dir.makeDir(invalid_path, .default_dir)); |
| 2170 | | 2112 | |
| 2171 | try testing.expectError(expected_err, ctx.dir.makePath(invalid_path)); | 2113 | try expectError(expected_err, ctx.dir.makePath(invalid_path)); |
| 2172 | try testing.expectError(expected_err, ctx.dir.makeOpenPath(invalid_path, .{})); | 2114 | try expectError(expected_err, ctx.dir.makeOpenPath(invalid_path, .{})); |
| 2173 | | 2115 | |
| 2174 | try testing.expectError(expected_err, ctx.dir.openDir(invalid_path, .{})); | 2116 | try expectError(expected_err, ctx.dir.openDir(invalid_path, .{})); |
| 2175 | | 2117 | |
| 2176 | try testing.expectError(expected_err, ctx.dir.deleteFile(invalid_path)); | 2118 | try expectError(expected_err, ctx.dir.deleteFile(invalid_path)); |
| 2177 | | 2119 | |
| 2178 | try testing.expectError(expected_err, ctx.dir.deleteDir(io, invalid_path)); | 2120 | try expectError(expected_err, ctx.dir.deleteDir(io, invalid_path)); |
| 2179 | | 2121 | |
| 2180 | try testing.expectError(expected_err, ctx.dir.rename(invalid_path, ctx.dir, invalid_path, io)); | 2122 | try expectError(expected_err, ctx.dir.rename(invalid_path, ctx.dir, invalid_path, io)); |
| 2181 | | 2123 | |
| 2182 | try testing.expectError(expected_err, ctx.dir.symLink(io, invalid_path, invalid_path, .{})); | 2124 | try expectError(expected_err, ctx.dir.symLink(io, invalid_path, invalid_path, .{})); |
| 2183 | if (native_os == .wasi) { | 2125 | if (native_os == .wasi) { |
| 2184 | try testing.expectError(expected_err, ctx.dir.symLinkWasi(invalid_path, invalid_path, .{})); | 2126 | try expectError(expected_err, ctx.dir.symLinkWasi(invalid_path, invalid_path, .{})); |
| 2185 | } | 2127 | } |
| 2186 | | 2128 | |
| 2187 | try testing.expectError(expected_err, ctx.dir.readLink(io, invalid_path, &[_]u8{})); | 2129 | try expectError(expected_err, ctx.dir.readLink(io, invalid_path, &[_]u8{})); |
| 2188 | if (native_os == .wasi) { | 2130 | if (native_os == .wasi) { |
| 2189 | try testing.expectError(expected_err, ctx.dir.readLinkWasi(invalid_path, &[_]u8{})); | 2131 | try expectError(expected_err, ctx.dir.readLinkWasi(invalid_path, &[_]u8{})); |
| 2190 | } | 2132 | } |
| 2191 | | 2133 | |
| 2192 | try testing.expectError(expected_err, ctx.dir.readFile(invalid_path, &[_]u8{})); | 2134 | try expectError(expected_err, ctx.dir.readFile(invalid_path, &[_]u8{})); |
| 2193 | try testing.expectError(expected_err, ctx.dir.readFileAlloc(invalid_path, testing.allocator, .limited(0))); | 2135 | try expectError(expected_err, ctx.dir.readFileAlloc(invalid_path, testing.allocator, .limited(0))); |
| 2194 | | 2136 | |
| 2195 | try testing.expectError(expected_err, ctx.dir.deleteTree(io, invalid_path)); | 2137 | try expectError(expected_err, ctx.dir.deleteTree(io, invalid_path)); |
| 2196 | try testing.expectError(expected_err, ctx.dir.deleteTreeMinStackSize(invalid_path)); | 2138 | try expectError(expected_err, ctx.dir.deleteTreeMinStackSize(invalid_path)); |
| 2197 | | 2139 | |
| 2198 | try testing.expectError(expected_err, ctx.dir.writeFile(io, .{ .sub_path = invalid_path, .data = "" })); | 2140 | try expectError(expected_err, ctx.dir.writeFile(io, .{ .sub_path = invalid_path, .data = "" })); |
| 2199 | | 2141 | |
| 2200 | try testing.expectError(expected_err, ctx.dir.access(invalid_path, .{})); | 2142 | try expectError(expected_err, ctx.dir.access(invalid_path, .{})); |
| 2201 | | 2143 | |
| 2202 | var dir = ctx.dir; | 2144 | var dir = ctx.dir; |
| 2203 | try testing.expectError(expected_err, dir.updateFile(io, invalid_path, dir, invalid_path, .{})); | 2145 | try expectError(expected_err, dir.updateFile(io, invalid_path, dir, invalid_path, .{})); |
| 2204 | try testing.expectError(expected_err, ctx.dir.copyFile(invalid_path, ctx.dir, invalid_path, .{})); | 2146 | try expectError(expected_err, ctx.dir.copyFile(invalid_path, ctx.dir, invalid_path, .{})); |
| 2205 | | 2147 | |
| 2206 | try testing.expectError(expected_err, ctx.dir.statFile(invalid_path)); | 2148 | try expectError(expected_err, ctx.dir.statFile(invalid_path)); |
| 2207 | | 2149 | |
| 2208 | if (native_os != .wasi) { | 2150 | if (native_os != .wasi) { |
| 2209 | try testing.expectError(expected_err, ctx.dir.realpath(invalid_path, &[_]u8{})); | 2151 | try expectError(expected_err, ctx.dir.realpath(invalid_path, &[_]u8{})); |
| 2210 | try testing.expectError(expected_err, ctx.dir.realpathAlloc(testing.allocator, invalid_path)); | 2152 | try expectError(expected_err, ctx.dir.realpathAlloc(testing.allocator, invalid_path)); |
| 2211 | } | 2153 | } |
| 2212 | | 2154 | |
| 2213 | try testing.expectError(expected_err, Dir.rename(ctx.dir, invalid_path, ctx.dir, invalid_path, io)); | 2155 | try expectError(expected_err, Dir.rename(ctx.dir, invalid_path, ctx.dir, invalid_path, io)); |
| 2214 | | 2156 | |
| 2215 | if (native_os != .wasi and ctx.path_type != .relative) { | 2157 | if (native_os != .wasi and ctx.path_type != .relative) { |
| 2216 | try testing.expectError(expected_err, Dir.copyFileAbsolute(invalid_path, invalid_path, .{})); | 2158 | try expectError(expected_err, Dir.copyFileAbsolute(invalid_path, invalid_path, .{})); |
| 2217 | try testing.expectError(expected_err, Dir.makeDirAbsolute(invalid_path)); | 2159 | try expectError(expected_err, Dir.makeDirAbsolute(invalid_path)); |
| 2218 | try testing.expectError(expected_err, Dir.deleteDirAbsolute(invalid_path)); | 2160 | try expectError(expected_err, Dir.deleteDirAbsolute(invalid_path)); |
| 2219 | try testing.expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path)); | 2161 | try expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path)); |
| 2220 | try testing.expectError(expected_err, Dir.openDirAbsolute(invalid_path, .{})); | 2162 | try expectError(expected_err, Dir.openDirAbsolute(invalid_path, .{})); |
| 2221 | try testing.expectError(expected_err, Dir.openFileAbsolute(invalid_path, .{})); | 2163 | try expectError(expected_err, Dir.openFileAbsolute(invalid_path, .{})); |
| 2222 | try testing.expectError(expected_err, Dir.accessAbsolute(invalid_path, .{})); | 2164 | try expectError(expected_err, Dir.accessAbsolute(invalid_path, .{})); |
| 2223 | try testing.expectError(expected_err, Dir.createFileAbsolute(invalid_path, .{})); | 2165 | try expectError(expected_err, Dir.createFileAbsolute(invalid_path, .{})); |
| 2224 | try testing.expectError(expected_err, Dir.deleteFileAbsolute(invalid_path)); | 2166 | try expectError(expected_err, Dir.deleteFileAbsolute(invalid_path)); |
| 2225 | var readlink_buf: [Dir.max_path_bytes]u8 = undefined; | 2167 | var readlink_buf: [Dir.max_path_bytes]u8 = undefined; |
| 2226 | try testing.expectError(expected_err, Dir.readLinkAbsolute(invalid_path, &readlink_buf)); | 2168 | try expectError(expected_err, Dir.readLinkAbsolute(invalid_path, &readlink_buf)); |
| 2227 | try testing.expectError(expected_err, Dir.symLinkAbsolute(invalid_path, invalid_path, .{})); | 2169 | try expectError(expected_err, Dir.symLinkAbsolute(invalid_path, invalid_path, .{})); |
| 2228 | try testing.expectError(expected_err, Dir.realpathAlloc(testing.allocator, invalid_path)); | 2170 | try expectError(expected_err, Dir.realpathAlloc(testing.allocator, invalid_path)); |
| 2229 | } | 2171 | } |
| 2230 | } | 2172 | } |
| 2231 | }.impl); | 2173 | }.impl); |
| ... | @@ -2259,8 +2201,8 @@ test "read file non vectored" { | ... | @@ -2259,8 +2201,8 @@ test "read file non vectored" { |
| 2259 | else => |e| return e, | 2201 | else => |e| return e, |
| 2260 | }; | 2202 | }; |
| 2261 | } | 2203 | } |
| 2262 | try testing.expectEqualStrings(contents, w.buffered()); | 2204 | try expectEqualStrings(contents, w.buffered()); |
| 2263 | try testing.expectEqual(contents.len, i); | 2205 | try expectEqual(contents.len, i); |
| 2264 | } | 2206 | } |
| 2265 | | 2207 | |
| 2266 | test "seek keeping partial buffer" { | 2208 | test "seek keeping partial buffer" { |
| ... | @@ -2282,7 +2224,7 @@ test "seek keeping partial buffer" { | ... | @@ -2282,7 +2224,7 @@ test "seek keeping partial buffer" { |
| 2282 | var read_buffer: [3]u8 = undefined; | 2224 | var read_buffer: [3]u8 = undefined; |
| 2283 | var file_reader: Io.File.Reader = .init(file, io, &read_buffer); | 2225 | var file_reader: Io.File.Reader = .init(file, io, &read_buffer); |
| 2284 | | 2226 | |
| 2285 | try testing.expectEqual(0, file_reader.logicalPos()); | 2227 | try expectEqual(0, file_reader.logicalPos()); |
| 2286 | | 2228 | |
| 2287 | var buf: [4]u8 = undefined; | 2229 | var buf: [4]u8 = undefined; |
| 2288 | try file_reader.interface.readSliceAll(&buf); | 2230 | try file_reader.interface.readSliceAll(&buf); |
| ... | @@ -2292,18 +2234,18 @@ test "seek keeping partial buffer" { | ... | @@ -2292,18 +2234,18 @@ test "seek keeping partial buffer" { |
| 2292 | return; | 2234 | return; |
| 2293 | } | 2235 | } |
| 2294 | | 2236 | |
| 2295 | try testing.expectEqual(4, file_reader.logicalPos()); | 2237 | try expectEqual(4, file_reader.logicalPos()); |
| 2296 | try testing.expectEqual(7, file_reader.pos); | 2238 | try expectEqual(7, file_reader.pos); |
| 2297 | try file_reader.seekTo(6); | 2239 | try file_reader.seekTo(6); |
| 2298 | try testing.expectEqual(6, file_reader.logicalPos()); | 2240 | try expectEqual(6, file_reader.logicalPos()); |
| 2299 | try testing.expectEqual(7, file_reader.pos); | 2241 | try expectEqual(7, file_reader.pos); |
| 2300 | | 2242 | |
| 2301 | try testing.expectEqualStrings("0123", &buf); | 2243 | try expectEqualStrings("0123", &buf); |
| 2302 | | 2244 | |
| 2303 | const n = try file_reader.interface.readSliceShort(&buf); | 2245 | const n = try file_reader.interface.readSliceShort(&buf); |
| 2304 | try testing.expectEqual(4, n); | 2246 | try expectEqual(4, n); |
| 2305 | | 2247 | |
| 2306 | try testing.expectEqualStrings("6789", &buf); | 2248 | try expectEqualStrings("6789", &buf); |
| 2307 | } | 2249 | } |
| 2308 | | 2250 | |
| 2309 | test "seekBy" { | 2251 | test "seekBy" { |
| ... | @@ -2320,8 +2262,8 @@ test "seekBy" { | ... | @@ -2320,8 +2262,8 @@ test "seekBy" { |
| 2320 | | 2262 | |
| 2321 | var buffer: [20]u8 = undefined; | 2263 | var buffer: [20]u8 = undefined; |
| 2322 | const n = try reader.interface.readSliceShort(&buffer); | 2264 | const n = try reader.interface.readSliceShort(&buffer); |
| 2323 | try testing.expectEqual(15, n); | 2265 | try expectEqual(15, n); |
| 2324 | try testing.expectEqualStrings("t's test seekBy", buffer[0..15]); | 2266 | try expectEqualStrings("t's test seekBy", buffer[0..15]); |
| 2325 | } | 2267 | } |
| 2326 | | 2268 | |
| 2327 | test "seekTo flushes buffered data" { | 2269 | test "seekTo flushes buffered data" { |
| ... | @@ -2348,7 +2290,7 @@ test "seekTo flushes buffered data" { | ... | @@ -2348,7 +2290,7 @@ test "seekTo flushes buffered data" { |
| 2348 | | 2290 | |
| 2349 | var buf: [4]u8 = undefined; | 2291 | var buf: [4]u8 = undefined; |
| 2350 | try file_reader.interface.readSliceAll(&buf); | 2292 | try file_reader.interface.readSliceAll(&buf); |
| 2351 | try std.testing.expectEqualStrings(contents, &buf); | 2293 | try expectEqualStrings(contents, &buf); |
| 2352 | } | 2294 | } |
| 2353 | | 2295 | |
| 2354 | test "File.Writer sendfile with buffered contents" { | 2296 | test "File.Writer sendfile with buffered contents" { |
| ... | @@ -2372,7 +2314,7 @@ test "File.Writer sendfile with buffered contents" { | ... | @@ -2372,7 +2314,7 @@ test "File.Writer sendfile with buffered contents" { |
| 2372 | var out_buf: [1]u8 = undefined; | 2314 | var out_buf: [1]u8 = undefined; |
| 2373 | var out_w = out.writerStreaming(&out_buf); | 2315 | var out_w = out.writerStreaming(&out_buf); |
| 2374 | try out_w.interface.writeByte('a'); | 2316 | try out_w.interface.writeByte('a'); |
| 2375 | try testing.expectEqual(3, try out_w.interface.sendFileAll(&in_r, .unlimited)); | 2317 | try expectEqual(3, try out_w.interface.sendFileAll(&in_r, .unlimited)); |
| 2376 | try out_w.interface.flush(); | 2318 | try out_w.interface.flush(); |
| 2377 | } | 2319 | } |
| 2378 | | 2320 | |
| ... | @@ -2380,8 +2322,8 @@ test "File.Writer sendfile with buffered contents" { | ... | @@ -2380,8 +2322,8 @@ test "File.Writer sendfile with buffered contents" { |
| 2380 | defer check.close(io); | 2322 | defer check.close(io); |
| 2381 | var check_buf: [4]u8 = undefined; | 2323 | var check_buf: [4]u8 = undefined; |
| 2382 | var check_r = check.reader(io, &check_buf); | 2324 | var check_r = check.reader(io, &check_buf); |
| 2383 | try testing.expectEqualStrings("abcd", try check_r.interface.take(4)); | 2325 | try expectEqualStrings("abcd", try check_r.interface.take(4)); |
| 2384 | try testing.expectError(error.EndOfStream, check_r.interface.takeByte()); | 2326 | try expectError(error.EndOfStream, check_r.interface.takeByte()); |
| 2385 | } | 2327 | } |
| 2386 | | 2328 | |
| 2387 | test "readlink on Windows" { | 2329 | test "readlink on Windows" { |
| ... | @@ -2410,23 +2352,72 @@ test "readlinkat" { | ... | @@ -2410,23 +2352,72 @@ test "readlinkat" { |
| 2410 | try tmp.dir.writeFile(io, .{ .sub_path = "file.txt", .data = "nonsense" }); | 2352 | try tmp.dir.writeFile(io, .{ .sub_path = "file.txt", .data = "nonsense" }); |
| 2411 | | 2353 | |
| 2412 | // create a symbolic link | 2354 | // create a symbolic link |
| 2413 | if (native_os == .windows) { | 2355 | tmp.dir.symLink("file.txt", "link", .{}) catch |err| switch (err) { |
| 2414 | std.os.windows.CreateSymbolicLink( | 2356 | error.AccessDenied => { |
| 2415 | tmp.dir.handle, | | |
| 2416 | &[_]u16{ 'l', 'i', 'n', 'k' }, | | |
| 2417 | &[_:0]u16{ 'f', 'i', 'l', 'e', '.', 't', 'x', 't' }, | | |
| 2418 | false, | | |
| 2419 | ) catch |err| switch (err) { | | |
| 2420 | // Symlink requires admin privileges on windows, so this test can legitimately fail. | 2357 | // Symlink requires admin privileges on windows, so this test can legitimately fail. |
| 2421 | error.AccessDenied => return error.SkipZigTest, | 2358 | if (native_os == .windows) return error.SkipZigTest; |
| 2422 | else => return err, | 2359 | }, |
| 2423 | }; | 2360 | }; |
| 2424 | } else { | | |
| 2425 | try posix.symlinkat("file.txt", tmp.dir.handle, "link"); | | |
| 2426 | } | | |
| 2427 | | 2361 | |
| 2428 | // read the link | 2362 | // read the link |
| 2429 | var buffer: [fs.max_path_bytes]u8 = undefined; | 2363 | var buffer: [fs.max_path_bytes]u8 = undefined; |
| 2430 | const read_link = try tmp.dir.readLink(io, "link", &buffer); | 2364 | const read_link = try tmp.dir.readLink(io, "link", &buffer); |
| 2431 | try expect(mem.eql(u8, "file.txt", read_link)); | 2365 | try expectEqualStrings("file.txt", read_link); |
| | 2366 | } |
| | 2367 | |
| | 2368 | test "fchmodat smoke test" { |
| | 2369 | if (!Io.File.Permissions.has_executable_bit) return error.SkipZigTest; |
| | 2370 | |
| | 2371 | if (builtin.cpu.arch.isMIPS64() and (builtin.abi == .gnuabin32 or builtin.abi == .muslabin32)) { |
| | 2372 | // https://github.com/ziglang/zig/issues/23808 |
| | 2373 | return error.SkipZigTest; |
| | 2374 | } |
| | 2375 | |
| | 2376 | const io = testing.io; |
| | 2377 | |
| | 2378 | var tmp = tmpDir(.{}); |
| | 2379 | defer tmp.cleanup(); |
| | 2380 | |
| | 2381 | try expectError(error.FileNotFound, tmp.dir.setPermissions(io, "regfile", 0o666, .{})); |
| | 2382 | const file = try tmp.dir.createFile(io, "regfile", .{ |
| | 2383 | .exclusive = true, |
| | 2384 | .permissions = .fromMode(0o644), |
| | 2385 | }); |
| | 2386 | file.close(io); |
| | 2387 | |
| | 2388 | if ((builtin.cpu.arch == .riscv32 or builtin.cpu.arch.isLoongArch()) and |
| | 2389 | builtin.os.tag == .linux and !builtin.link_libc) |
| | 2390 | { |
| | 2391 | return error.SkipZigTest; // No `fstatat()`. |
| | 2392 | } |
| | 2393 | |
| | 2394 | try tmp.dir.symLink(io, "regfile", "symlink", .{}); |
| | 2395 | const sym_mode = blk: { |
| | 2396 | const st = try tmp.dir.statFile(io, "symlink", .{ .follow_symlinks = false }); |
| | 2397 | break :blk st.permissions.toMode() & 0b111_111_111; |
| | 2398 | }; |
| | 2399 | |
| | 2400 | try tmp.dir.setFilePermissions(io, "regfile", .fromMode(0o640), .{}); |
| | 2401 | try expectMode(io, tmp.dir, "regfile", .fromMode(0o640)); |
| | 2402 | try tmp.dir.setFilePermissions(io, "regfile", .fromMode(0o600), .{ .follow_symlinks = false }); |
| | 2403 | try expectMode(io, tmp.dir, "regfile", .fromMode(0o600)); |
| | 2404 | |
| | 2405 | try tmp.dir.setFilePermissions(io, "symlink", .fromMode(0o640), .{}); |
| | 2406 | try expectMode(io, tmp.dir, "regfile", .fromMode(0o640)); |
| | 2407 | try expectMode(io, tmp.dir, "symlink", .fromMode(sym_mode)); |
| | 2408 | |
| | 2409 | var test_link = true; |
| | 2410 | tmp.dir.setFilePermissions(io, "symlink", .fromMode(0o600), .{ .follow_symlinks = false }) catch |err| switch (err) { |
| | 2411 | error.OperationNotSupported => test_link = false, |
| | 2412 | else => |e| return e, |
| | 2413 | }; |
| | 2414 | if (test_link) |
| | 2415 | try expectMode(tmp.dir.handle, "symlink", 0o600); |
| | 2416 | try expectMode(tmp.dir.handle, "regfile", 0o640); |
| | 2417 | } |
| | 2418 | |
| | 2419 | fn expectMode(io: Io, dir: Dir, file: []const u8, permissions: File.Permissions) !void { |
| | 2420 | const mode = permissions.toMode(); |
| | 2421 | const st = try dir.statFile(io, file, .{ .follow_symlinks = false }); |
| | 2422 | try expectEqual(mode, st.mode & 0b111_111_111); |
| 2432 | } | 2423 | } |