| ... | ... | @@ -3,19 +3,23 @@ const native_os = builtin.os.tag; |
| 3 | 3 | |
| 4 | 4 | const std = @import("../std.zig"); |
| 5 | 5 | const Io = std.Io; |
| 6 | | const testing = std.testing; |
| 7 | | const expect = std.testing.expect; |
| 8 | 6 | const fs = std.fs; |
| 9 | 7 | const mem = std.mem; |
| 10 | 8 | const wasi = std.os.wasi; |
| 11 | 9 | const windows = std.os.windows; |
| 12 | | const posix = std.posix; |
| 13 | 10 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 14 | 11 | const Dir = std.Io.Dir; |
| 15 | 12 | const File = std.Io.File; |
| 16 | | const tmpDir = std.testing.tmpDir; |
| 17 | 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 | 23 | const PathType = enum { |
| 20 | 24 | relative, |
| 21 | 25 | absolute, |
| ... | ... | @@ -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 | 37 | pub const TransformFn = fn (allocator: mem.Allocator, dir: Dir, relative_path: [:0]const u8) TransformError![:0]const u8; |
| 34 | 38 | |
| 35 | 39 | pub fn getTransformFn(comptime path_type: PathType) TransformFn { |
| ... | ... | @@ -249,7 +253,7 @@ test "Dir.readLink on non-symlinks" { |
| 249 | 253 | fn testReadLink(io: Io, dir: Dir, target_path: []const u8, symlink_path: []const u8) !void { |
| 250 | 254 | var buffer: [fs.max_path_bytes]u8 = undefined; |
| 251 | 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 | 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 | 264 | const wtf16_buffer = try allocator.alloc(u16, target_path_w.len); |
| 261 | 265 | defer allocator.free(wtf16_buffer); |
| 262 | 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 | 270 | fn testReadLinkAbsolute(target_path: []const u8, symlink_path: []const u8) !void { |
| 267 | 271 | var buffer: [fs.max_path_bytes]u8 = undefined; |
| 268 | 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 | 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 | 290 | |
| 287 | 291 | try setupSymlink(io, ctx.dir, dir_target_path, "symlink", .{ .is_directory = true }); |
| 288 | 292 | |
| 289 | | var symlink: Dir = switch (builtin.target.os.tag) { |
| 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 | | }; |
| 293 | var symlink: Dir = try ctx.dir.openDir("symlink", .{ .follow_symlinks = false }); |
| 351 | 294 | defer symlink.close(io); |
| 352 | 295 | |
| 353 | 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 | 299 | }.impl); |
| 357 | 300 | } |
| ... | ... | @@ -417,7 +360,7 @@ test "openDirAbsolute" { |
| 417 | 360 | defer dir.close(io); |
| 418 | 361 | |
| 419 | 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 | 372 | defer dir.close(io); |
| 430 | 373 | |
| 431 | 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 | 384 | defer dir.close(io); |
| 442 | 385 | |
| 443 | 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 | 423 | const actual_path = try dir.realpathAlloc(testing.allocator, "."); |
| 481 | 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 | 429 | test "readLinkAbsolute" { |
| ... | ... | @@ -548,7 +491,7 @@ test "Dir.Iterator" { |
| 548 | 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 | 495 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 553 | 496 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); |
| 554 | 497 | } |
| ... | ... | @@ -619,7 +562,7 @@ test "Dir.Iterator twice" { |
| 619 | 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 | 566 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 624 | 567 | try testing.expect(contains(&entries, .{ .name = "some_dir", .kind = .directory })); |
| 625 | 568 | } |
| ... | ... | @@ -655,7 +598,7 @@ test "Dir.Iterator reset" { |
| 655 | 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 | 602 | try testing.expect(contains(&entries, .{ .name = "some_file", .kind = .file })); |
| 660 | 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 | 633 | |
| 691 | 634 | // On Linux, we can opt-in to receiving a more specific error by calling `nextLinux` |
| 692 | 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 | 660 | var buf: [fs.max_path_bytes]u8 = undefined; |
| 718 | 661 | |
| 719 | 662 | // FileNotFound if the path doesn't exist |
| 720 | | try testing.expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_file_path)); |
| 721 | | try testing.expectError(error.FileNotFound, ctx.dir.realpath(test_file_path, &buf)); |
| 722 | | try testing.expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_dir_path)); |
| 723 | | try testing.expectError(error.FileNotFound, ctx.dir.realpath(test_dir_path, &buf)); |
| 663 | try expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_file_path)); |
| 664 | try expectError(error.FileNotFound, ctx.dir.realpath(test_file_path, &buf)); |
| 665 | try expectError(error.FileNotFound, ctx.dir.realpathAlloc(allocator, test_dir_path)); |
| 666 | try expectError(error.FileNotFound, ctx.dir.realpath(test_dir_path, &buf)); |
| 724 | 667 | |
| 725 | 668 | // Now create the file and dir |
| 726 | 669 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_path, .data = "" }); |
| ... | ... | @@ -740,19 +683,19 @@ test "Dir.realpath smoke test" { |
| 740 | 683 | // First, test non-alloc version |
| 741 | 684 | { |
| 742 | 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 | 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 | 692 | // Next, test alloc version |
| 750 | 693 | { |
| 751 | 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 | 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 | 701 | }.impl); |
| ... | ... | @@ -769,7 +712,7 @@ test "readFileAlloc" { |
| 769 | 712 | |
| 770 | 713 | const buf1 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(1024)); |
| 771 | 714 | defer testing.allocator.free(buf1); |
| 772 | | try testing.expectEqualStrings("", buf1); |
| 715 | try expectEqualStrings("", buf1); |
| 773 | 716 | |
| 774 | 717 | const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n"; |
| 775 | 718 | try file.writeAll(write_buf); |
| ... | ... | @@ -778,12 +721,12 @@ test "readFileAlloc" { |
| 778 | 721 | // max_bytes > file_size |
| 779 | 722 | const buf2 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(1024)); |
| 780 | 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 | 728 | // max_bytes == file_size |
| 786 | | try testing.expectError( |
| 729 | try expectError( |
| 787 | 730 | error.StreamTooLong, |
| 788 | 731 | tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len)), |
| 789 | 732 | ); |
| ... | ... | @@ -793,11 +736,11 @@ test "readFileAlloc" { |
| 793 | 736 | // max_bytes == file_size + 1 |
| 794 | 737 | const buf2 = try tmp_dir.dir.readFileAlloc(io, "test_file", testing.allocator, .limited(write_buf.len + 1)); |
| 795 | 738 | defer testing.allocator.free(buf2); |
| 796 | | try testing.expectEqualStrings(write_buf, buf2); |
| 739 | try expectEqualStrings(write_buf, buf2); |
| 797 | 740 | } |
| 798 | 741 | |
| 799 | 742 | // max_bytes < file_size |
| 800 | | try testing.expectError( |
| 743 | try expectError( |
| 801 | 744 | error.StreamTooLong, |
| 802 | 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 | 752 | const io = ctx.io; |
| 810 | 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 | 757 | try ctx.dir.writeFile(io, .{ .sub_path = test_file_name, .data = "" }); |
| 815 | 758 | |
| 816 | 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 | 762 | }.impl); |
| 820 | 763 | } |
| ... | ... | @@ -828,7 +771,7 @@ test "statFile on dangling symlink" { |
| 828 | 771 | |
| 829 | 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 | 776 | }.impl); |
| 834 | 777 | } |
| ... | ... | @@ -843,19 +786,19 @@ test "directory operations on files" { |
| 843 | 786 | var file = try ctx.dir.createFile(io, test_file_name, .{ .read = true }); |
| 844 | 787 | file.close(io); |
| 845 | 788 | |
| 846 | | try testing.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, .{})); |
| 848 | | try testing.expectError(error.NotDir, ctx.dir.deleteDir(io, test_file_name)); |
| 789 | try expectError(error.PathAlreadyExists, ctx.dir.makeDir(io, test_file_name, .default_dir)); |
| 790 | try expectError(error.NotDir, ctx.dir.openDir(io, test_file_name, .{})); |
| 791 | try expectError(error.NotDir, ctx.dir.deleteDir(io, test_file_name)); |
| 849 | 792 | |
| 850 | 793 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { |
| 851 | | try testing.expectError(error.PathAlreadyExists, fs.makeDirAbsolute(test_file_name)); |
| 852 | | try testing.expectError(error.NotDir, fs.deleteDirAbsolute(test_file_name)); |
| 794 | try expectError(error.PathAlreadyExists, fs.makeDirAbsolute(test_file_name)); |
| 795 | try expectError(error.NotDir, fs.deleteDirAbsolute(test_file_name)); |
| 853 | 796 | } |
| 854 | 797 | |
| 855 | 798 | // ensure the file still exists and is a file as a sanity check |
| 856 | 799 | file = try ctx.dir.openFile(io, test_file_name, .{}); |
| 857 | 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 | 802 | file.close(io); |
| 860 | 803 | } |
| 861 | 804 | }.impl); |
| ... | ... | @@ -873,8 +816,8 @@ test "file operations on directories" { |
| 873 | 816 | |
| 874 | 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, .{})); |
| 877 | | try testing.expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name)); |
| 819 | try expectError(error.IsDir, ctx.dir.createFile(io, test_dir_name, .{})); |
| 820 | try expectError(error.IsDir, ctx.dir.deleteFile(io, test_dir_name)); |
| 878 | 821 | switch (native_os) { |
| 879 | 822 | .dragonfly, .netbsd => { |
| 880 | 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 | 827 | .wasi => { |
| 885 | 828 | // WASI return EBADF, which gets mapped to NotOpenForReading. |
| 886 | 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 | 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 | 841 | } else { |
| 899 | 842 | // Note: The `.mode = .read_write` is necessary to ensure the error occurs on all platforms. |
| 900 | 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 | 847 | if (ctx.path_type == .absolute and comptime PathType.absolute.isSupported(builtin.os)) { |
| 905 | | try testing.expectError(error.IsDir, fs.createFileAbsolute(test_dir_name, .{})); |
| 906 | | try testing.expectError(error.IsDir, fs.deleteFileAbsolute(test_dir_name)); |
| 848 | try expectError(error.IsDir, fs.createFileAbsolute(test_dir_name, .{})); |
| 849 | try expectError(error.IsDir, fs.deleteFileAbsolute(test_dir_name)); |
| 907 | 850 | } |
| 908 | 851 | |
| 909 | 852 | // ensure the directory still exists as a sanity check |
| ... | ... | @@ -935,12 +878,12 @@ test "deleteDir" { |
| 935 | 878 | const test_file_path = try ctx.transformPath("test_dir" ++ fs.path.sep_str ++ "test_file"); |
| 936 | 879 | |
| 937 | 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 | 883 | // deleting a non-empty directory |
| 941 | 884 | try ctx.dir.makeDir(io, test_dir_path, .default_dir); |
| 942 | 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 | 888 | // deleting an empty directory |
| 946 | 889 | try ctx.dir.deleteFile(io, test_file_path); |
| ... | ... | @@ -962,7 +905,7 @@ test "Dir.rename files" { |
| 962 | 905 | const missing_file_path = try ctx.transformPath("missing_file_name"); |
| 963 | 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 | 910 | // Renaming files |
| 968 | 911 | const test_file_name = try ctx.transformPath("test_file"); |
| ... | ... | @@ -972,7 +915,7 @@ test "Dir.rename files" { |
| 972 | 915 | try ctx.dir.rename(test_file_name, ctx.dir, renamed_test_file_name, io); |
| 973 | 916 | |
| 974 | 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 | 919 | file = try ctx.dir.openFile(io, renamed_test_file_name, .{}); |
| 977 | 920 | file.close(io); |
| 978 | 921 | |
| ... | ... | @@ -985,7 +928,7 @@ test "Dir.rename files" { |
| 985 | 928 | existing_file.close(io); |
| 986 | 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 | 932 | file = try ctx.dir.openFile(io, existing_file_path, .{}); |
| 990 | 933 | file.close(io); |
| 991 | 934 | } |
| ... | ... | @@ -1011,7 +954,7 @@ test "Dir.rename directories" { |
| 1011 | 954 | try ctx.dir.rename(test_dir_path, ctx.dir, test_dir_renamed_path, io); |
| 1012 | 955 | |
| 1013 | 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 | 958 | var dir = try ctx.dir.openDir(io, test_dir_renamed_path, .{}); |
| 1016 | 959 | |
| 1017 | 960 | // Put a file in the directory |
| ... | ... | @@ -1023,7 +966,7 @@ test "Dir.rename directories" { |
| 1023 | 966 | try ctx.dir.rename(test_dir_renamed_path, ctx.dir, test_dir_renamed_again_path, io); |
| 1024 | 967 | |
| 1025 | 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 | 970 | dir = try ctx.dir.openDir(io, test_dir_renamed_again_path, .{}); |
| 1028 | 971 | file = try dir.openFile(io, "test_file", .{}); |
| 1029 | 972 | file.close(io); |
| ... | ... | @@ -1048,7 +991,7 @@ test "Dir.rename directory onto empty dir" { |
| 1048 | 991 | try ctx.dir.rename(test_dir_path, ctx.dir, target_dir_path, io); |
| 1049 | 992 | |
| 1050 | 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 | 995 | var dir = try ctx.dir.openDir(io, target_dir_path, .{}); |
| 1053 | 996 | dir.close(io); |
| 1054 | 997 | } |
| ... | ... | @@ -1073,7 +1016,7 @@ test "Dir.rename directory onto non-empty dir" { |
| 1073 | 1016 | target_dir.close(io); |
| 1074 | 1017 | |
| 1075 | 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 | 1021 | // Ensure the directory was not renamed |
| 1079 | 1022 | var dir = try ctx.dir.openDir(io, test_dir_path, .{}); |
| ... | ... | @@ -1095,8 +1038,8 @@ test "Dir.rename file <-> dir" { |
| 1095 | 1038 | var file = try ctx.dir.createFile(io, test_file_path, .{ .read = true }); |
| 1096 | 1039 | file.close(io); |
| 1097 | 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)); |
| 1099 | | try testing.expectError(error.NotDir, ctx.dir.rename(test_dir_path, ctx.dir, test_file_path, io)); |
| 1041 | try expectError(error.IsDir, ctx.dir.rename(test_file_path, ctx.dir, test_dir_path, io)); |
| 1042 | try expectError(error.NotDir, ctx.dir.rename(test_dir_path, ctx.dir, test_file_path, io)); |
| 1100 | 1043 | } |
| 1101 | 1044 | }.impl); |
| 1102 | 1045 | } |
| ... | ... | @@ -1118,7 +1061,7 @@ test "rename" { |
| 1118 | 1061 | try Dir.rename(tmp_dir1.dir, test_file_name, tmp_dir2.dir, renamed_test_file_name, io); |
| 1119 | 1062 | |
| 1120 | 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 | 1065 | file = try tmp_dir2.dir.openFile(io, renamed_test_file_name, .{}); |
| 1123 | 1066 | file.close(io); |
| 1124 | 1067 | } |
| ... | ... | @@ -1139,7 +1082,7 @@ test "renameAbsolute" { |
| 1139 | 1082 | |
| 1140 | 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 | 1086 | try fs.path.join(allocator, &.{ base_path, "missing_file_name" }), |
| 1144 | 1087 | try fs.path.join(allocator, &.{ base_path, "something_else" }), |
| 1145 | 1088 | )); |
| ... | ... | @@ -1155,10 +1098,10 @@ test "renameAbsolute" { |
| 1155 | 1098 | ); |
| 1156 | 1099 | |
| 1157 | 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 | 1102 | file = try tmp_dir.dir.openFile(io, renamed_test_file_name, .{}); |
| 1160 | 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 | 1105 | file.close(io); |
| 1163 | 1106 | |
| 1164 | 1107 | // Renaming directories |
| ... | ... | @@ -1171,7 +1114,7 @@ test "renameAbsolute" { |
| 1171 | 1114 | ); |
| 1172 | 1115 | |
| 1173 | 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 | 1118 | var dir = try tmp_dir.dir.openDir(io, renamed_test_dir_name, .{}); |
| 1176 | 1119 | dir.close(io); |
| 1177 | 1120 | } |
| ... | ... | @@ -1193,7 +1136,7 @@ test "executablePath" { |
| 1193 | 1136 | const buf_self_exe_path = try std.process.executablePath(io, &buf); |
| 1194 | 1137 | const alloc_self_exe_path = try std.process.executablePathAlloc(io, testing.allocator); |
| 1195 | 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 | 1142 | test "deleteTree does not follow symlinks" { |
| ... | ... | @@ -1212,7 +1155,7 @@ test "deleteTree does not follow symlinks" { |
| 1212 | 1155 | |
| 1213 | 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 | 1159 | try tmp.dir.access(io, "b", .{}); |
| 1217 | 1160 | } |
| 1218 | 1161 | |
| ... | ... | @@ -1227,7 +1170,7 @@ test "deleteTree on a symlink" { |
| 1227 | 1170 | try setupSymlink(io, tmp.dir, "file", "filelink", .{}); |
| 1228 | 1171 | |
| 1229 | 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 | 1174 | try tmp.dir.access(io, "file", .{}); |
| 1232 | 1175 | |
| 1233 | 1176 | // Symlink to a directory |
| ... | ... | @@ -1235,7 +1178,7 @@ test "deleteTree on a symlink" { |
| 1235 | 1178 | try setupSymlink(io, tmp.dir, "dir", "dirlink", .{ .is_directory = true }); |
| 1236 | 1179 | |
| 1237 | 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 | 1182 | try tmp.dir.access(io, "dir", .{}); |
| 1240 | 1183 | } |
| 1241 | 1184 | |
| ... | ... | @@ -1257,7 +1200,7 @@ test "makePath, put some files in it, deleteTree" { |
| 1257 | 1200 | }); |
| 1258 | 1201 | |
| 1259 | 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 | 1205 | }.impl); |
| 1263 | 1206 | } |
| ... | ... | @@ -1280,7 +1223,7 @@ test "makePath, put some files in it, deleteTreeMinStackSize" { |
| 1280 | 1223 | }); |
| 1281 | 1224 | |
| 1282 | 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 | 1228 | }.impl); |
| 1286 | 1229 | } |
| ... | ... | @@ -1294,7 +1237,7 @@ test "makePath in a directory that no longer exists" { |
| 1294 | 1237 | defer tmp.cleanup(); |
| 1295 | 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 | 1243 | test "makePath but sub_path contains pre-existing file" { |
| ... | ... | @@ -1306,7 +1249,7 @@ test "makePath but sub_path contains pre-existing file" { |
| 1306 | 1249 | try tmp.dir.makeDir(io, "foo", .default_dir); |
| 1307 | 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 | 1255 | fn expectDir(io: Io, dir: Dir, path: []const u8) !void { |
| ... | ... | @@ -1364,8 +1307,8 @@ test "makepath relative walks" { |
| 1364 | 1307 | // On Windows, .. is resolved before passing the path to NtCreateFile, |
| 1365 | 1308 | // meaning everything except `first/C` drops out. |
| 1366 | 1309 | try expectDir(io, tmp.dir, "first" ++ fs.path.sep_str ++ "C"); |
| 1367 | | try testing.expectError(error.FileNotFound, tmp.dir.access(io, "second", .{})); |
| 1368 | | try testing.expectError(error.FileNotFound, tmp.dir.access(io, "third", .{})); |
| 1310 | try expectError(error.FileNotFound, tmp.dir.access(io, "second", .{})); |
| 1311 | try expectError(error.FileNotFound, tmp.dir.access(io, "third", .{})); |
| 1369 | 1312 | }, |
| 1370 | 1313 | else => { |
| 1371 | 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 | 1356 | |
| 1414 | 1357 | var count: usize = 0; |
| 1415 | 1358 | while (try walker.next()) |entry| { |
| 1416 | | try testing.expectEqualStrings(maxed_filename, entry.basename); |
| 1359 | try expectEqualStrings(maxed_filename, entry.basename); |
| 1417 | 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 | 1365 | // ensure that we can delete the tree |
| ... | ... | @@ -1467,14 +1410,14 @@ test "writev, readv" { |
| 1467 | 1410 | |
| 1468 | 1411 | try writer.interface.writeVecAll(&write_vecs); |
| 1469 | 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 | 1415 | var reader = writer.moveToReader(io); |
| 1473 | 1416 | try reader.seekTo(0); |
| 1474 | 1417 | try reader.interface.readVecAll(&read_vecs); |
| 1475 | | try testing.expectEqualStrings(&buf1, "line2\n"); |
| 1476 | | try testing.expectEqualStrings(&buf2, "line1\n"); |
| 1477 | | try testing.expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); |
| 1418 | try expectEqualStrings(&buf1, "line2\n"); |
| 1419 | try expectEqualStrings(&buf2, "line1\n"); |
| 1420 | try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); |
| 1478 | 1421 | } |
| 1479 | 1422 | |
| 1480 | 1423 | test "pwritev, preadv" { |
| ... | ... | @@ -1498,14 +1441,14 @@ test "pwritev, preadv" { |
| 1498 | 1441 | try writer.seekTo(16); |
| 1499 | 1442 | try writer.interface.writeVecAll(&lines); |
| 1500 | 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 | 1446 | var reader = writer.moveToReader(io); |
| 1504 | 1447 | try reader.seekTo(16); |
| 1505 | 1448 | try reader.interface.readVecAll(&read_vecs); |
| 1506 | | try testing.expectEqualStrings(&buf1, "line2\n"); |
| 1507 | | try testing.expectEqualStrings(&buf2, "line1\n"); |
| 1508 | | try testing.expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); |
| 1449 | try expectEqualStrings(&buf1, "line2\n"); |
| 1450 | try expectEqualStrings(&buf2, "line1\n"); |
| 1451 | try expectError(error.EndOfStream, reader.interface.readSliceAll(&buf1)); |
| 1509 | 1452 | } |
| 1510 | 1453 | |
| 1511 | 1454 | test "setEndPos" { |
| ... | ... | @@ -1529,34 +1472,34 @@ test "setEndPos" { |
| 1529 | 1472 | |
| 1530 | 1473 | { |
| 1531 | 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 | 1476 | try reader.seekTo(0); |
| 1534 | | try testing.expectEqual(initial_size, try reader.interface.readSliceShort(&buffer)); |
| 1535 | | try testing.expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]); |
| 1477 | try expectEqual(initial_size, try reader.interface.readSliceShort(&buffer)); |
| 1478 | try expectEqualStrings("ninebytes", buffer[0..@intCast(initial_size)]); |
| 1536 | 1479 | } |
| 1537 | 1480 | |
| 1538 | 1481 | { |
| 1539 | 1482 | const larger = initial_size + 4; |
| 1540 | 1483 | try f.setEndPos(larger); |
| 1541 | | try testing.expectEqual(larger, try f.length(io)); |
| 1484 | try expectEqual(larger, try f.length(io)); |
| 1542 | 1485 | try reader.seekTo(0); |
| 1543 | | try testing.expectEqual(larger, try reader.interface.readSliceShort(&buffer)); |
| 1544 | | try testing.expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]); |
| 1486 | try expectEqual(larger, try reader.interface.readSliceShort(&buffer)); |
| 1487 | try expectEqualStrings("ninebytes\x00\x00\x00\x00", buffer[0..@intCast(larger)]); |
| 1545 | 1488 | } |
| 1546 | 1489 | |
| 1547 | 1490 | { |
| 1548 | 1491 | const smaller = initial_size - 5; |
| 1549 | 1492 | try f.setEndPos(smaller); |
| 1550 | | try testing.expectEqual(smaller, try f.length(io)); |
| 1493 | try expectEqual(smaller, try f.length(io)); |
| 1551 | 1494 | try reader.seekTo(0); |
| 1552 | | try testing.expectEqual(smaller, try reader.interface.readSliceShort(&buffer)); |
| 1553 | | try testing.expectEqualStrings("nine", buffer[0..@intCast(smaller)]); |
| 1495 | try expectEqual(smaller, try reader.interface.readSliceShort(&buffer)); |
| 1496 | try expectEqualStrings("nine", buffer[0..@intCast(smaller)]); |
| 1554 | 1497 | } |
| 1555 | 1498 | |
| 1556 | 1499 | try f.setEndPos(0); |
| 1557 | | try testing.expectEqual(0, try f.length(io)); |
| 1500 | try expectEqual(0, try f.length(io)); |
| 1558 | 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 | 1505 | test "access file" { |
| ... | ... | @@ -1567,7 +1510,7 @@ test "access file" { |
| 1567 | 1510 | const file_path = try ctx.transformPath("os_test_tmp" ++ fs.path.sep_str ++ "file.txt"); |
| 1568 | 1511 | |
| 1569 | 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 | 1515 | try ctx.dir.writeFile(io, .{ .sub_path = file_path, .data = "" }); |
| 1573 | 1516 | try ctx.dir.access(io, file_path, .{}); |
| ... | ... | @@ -1614,13 +1557,13 @@ test "sendfile" { |
| 1614 | 1557 | var file_writer = dest_file.writer(io, &fallback_buffer); |
| 1615 | 1558 | try file_writer.interface.writeVecAll(&headers); |
| 1616 | 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 | 1561 | try file_writer.interface.writeVecAll(&trailers); |
| 1619 | 1562 | try file_writer.interface.flush(); |
| 1620 | 1563 | var fr = file_writer.moveToReader(io); |
| 1621 | 1564 | try fr.seekTo(0); |
| 1622 | 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 | 1569 | test "sendfile with buffered data" { |
| ... | ... | @@ -1651,15 +1594,15 @@ test "sendfile with buffered data" { |
| 1651 | 1594 | var fallback_buffer: [32]u8 = undefined; |
| 1652 | 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 | 1599 | var written_buf: [8]u8 = undefined; |
| 1657 | 1600 | var fr = file_writer.moveToReader(io); |
| 1658 | 1601 | try fr.seekTo(0); |
| 1659 | 1602 | const amt = try fr.interface.readSliceShort(&written_buf); |
| 1660 | 1603 | |
| 1661 | | try std.testing.expectEqual(4, amt); |
| 1662 | | try std.testing.expectEqualSlices(u8, "AAAA", written_buf[0..amt]); |
| 1604 | try expectEqual(4, amt); |
| 1605 | try expectEqualSlices(u8, "AAAA", written_buf[0..amt]); |
| 1663 | 1606 | } |
| 1664 | 1607 | |
| 1665 | 1608 | test "copyFile" { |
| ... | ... | @@ -1690,7 +1633,7 @@ fn expectFileContents(io: Io, dir: Dir, file_path: []const u8, data: []const u8) |
| 1690 | 1633 | const contents = try dir.readFileAlloc(io, file_path, testing.allocator, .limited(1000)); |
| 1691 | 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 | 1639 | test "AtomicFile" { |
| ... | ... | @@ -1712,7 +1655,7 @@ test "AtomicFile" { |
| 1712 | 1655 | try af.finish(); |
| 1713 | 1656 | } |
| 1714 | 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 | 1660 | try ctx.dir.deleteFile(io, test_out_file); |
| 1718 | 1661 | } |
| ... | ... | @@ -1731,7 +1674,7 @@ test "open file with exclusive nonblocking lock twice" { |
| 1731 | 1674 | defer file1.close(io); |
| 1732 | 1675 | |
| 1733 | 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 | 1679 | }.impl); |
| 1737 | 1680 | } |
| ... | ... | @@ -1748,7 +1691,7 @@ test "open file with shared and exclusive nonblocking lock" { |
| 1748 | 1691 | defer file1.close(io); |
| 1749 | 1692 | |
| 1750 | 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 | 1696 | }.impl); |
| 1754 | 1697 | } |
| ... | ... | @@ -1765,7 +1708,7 @@ test "open file with exclusive and shared nonblocking lock" { |
| 1765 | 1708 | defer file1.close(io); |
| 1766 | 1709 | |
| 1767 | 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 | 1713 | }.impl); |
| 1771 | 1714 | } |
| ... | ... | @@ -1805,7 +1748,7 @@ test "open file with exclusive lock twice, make sure second lock waits" { |
| 1805 | 1748 | // Wait for the spawned thread to start trying to acquire the exclusive file lock. |
| 1806 | 1749 | // Then wait a bit to make sure that can't acquire it since we currently hold the file lock. |
| 1807 | 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 | 1753 | // Release the file lock which should unlock the thread to lock it and set the locked event. |
| 1811 | 1754 | file.close(io); |
| ... | ... | @@ -1846,7 +1789,7 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { |
| 1846 | 1789 | .lock_nonblocking = true, |
| 1847 | 1790 | }); |
| 1848 | 1791 | file1.close(io); |
| 1849 | | try testing.expectError(error.WouldBlock, file2); |
| 1792 | try expectError(error.WouldBlock, file2); |
| 1850 | 1793 | } |
| 1851 | 1794 | |
| 1852 | 1795 | test "read from locked file" { |
| ... | ... | @@ -1871,9 +1814,9 @@ test "read from locked file" { |
| 1871 | 1814 | defer f2.close(io); |
| 1872 | 1815 | var buffer: [1]u8 = undefined; |
| 1873 | 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 | 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 | 1868 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1926 | 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 | 1872 | std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1930 | 1873 | return err; |
| 1931 | 1874 | }; |
| ... | ... | @@ -1934,7 +1877,7 @@ test "walker" { |
| 1934 | 1877 | defer entry_dir.close(io); |
| 1935 | 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 | 1883 | test "selective walker, skip entries that start with ." { |
| ... | ... | @@ -1992,7 +1935,7 @@ test "selective walker, skip entries that start with ." { |
| 1992 | 1935 | std.debug.print("found unexpected path: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1993 | 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 | 1939 | std.debug.print("path reported unexpected depth: {f}\n", .{std.ascii.hexEscape(entry.path, .lower)}); |
| 1997 | 1940 | return err; |
| 1998 | 1941 | }; |
| ... | ... | @@ -2002,7 +1945,7 @@ test "selective walker, skip entries that start with ." { |
| 2002 | 1945 | defer entry_dir.close(io); |
| 2003 | 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 | 1951 | test "walker without fully iterating" { |
| ... | ... | @@ -2025,7 +1968,7 @@ test "walker without fully iterating" { |
| 2025 | 1968 | num_walked += 1; |
| 2026 | 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 | 1974 | test "'.' and '..' in Io.Dir functions" { |
| ... | ... | @@ -2061,7 +2004,7 @@ test "'.' and '..' in Io.Dir functions" { |
| 2061 | 2004 | try ctx.dir.writeFile(io, .{ .sub_path = update_path, .data = "something" }); |
| 2062 | 2005 | var dir = ctx.dir; |
| 2063 | 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 | 2009 | try ctx.dir.deleteDir(io, subdir_path); |
| 2067 | 2010 | } |
| ... | ... | @@ -2106,8 +2049,7 @@ test "'.' and '..' in absolute functions" { |
| 2106 | 2049 | } |
| 2107 | 2050 | |
| 2108 | 2051 | test "chmod" { |
| 2109 | | if (native_os == .windows or native_os == .wasi) |
| 2110 | | return error.SkipZigTest; |
| 2052 | if (native_os == .windows or native_os == .wasi) return; |
| 2111 | 2053 | |
| 2112 | 2054 | const io = testing.io; |
| 2113 | 2055 | |
| ... | ... | @@ -2116,17 +2058,17 @@ test "chmod" { |
| 2116 | 2058 | |
| 2117 | 2059 | const file = try tmp.dir.createFile(io, "test_file", .{ .permissions = .fromMode(0o600) }); |
| 2118 | 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 | 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 | 2066 | try tmp.dir.makeDir(io, "test_dir", .default_dir); |
| 2125 | 2067 | var dir = try tmp.dir.openDir(io, "test_dir", .{ .iterate = true }); |
| 2126 | 2068 | defer dir.close(io); |
| 2127 | 2069 | |
| 2128 | 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 | 2074 | test "chown" { |
| ... | ... | @@ -2162,70 +2104,70 @@ test "invalid UTF-8/WTF-8 paths" { |
| 2162 | 2104 | // This is both invalid UTF-8 and WTF-8, since \xFF is an invalid start byte |
| 2163 | 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)); |
| 2172 | | try testing.expectError(expected_err, ctx.dir.makeOpenPath(invalid_path, .{})); |
| 2113 | try expectError(expected_err, ctx.dir.makePath(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 | 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 | 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{})); |
| 2193 | | try testing.expectError(expected_err, ctx.dir.readFileAlloc(invalid_path, testing.allocator, .limited(0))); |
| 2134 | try expectError(expected_err, ctx.dir.readFile(invalid_path, &[_]u8{})); |
| 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)); |
| 2196 | | try testing.expectError(expected_err, ctx.dir.deleteTreeMinStackSize(invalid_path)); |
| 2137 | try expectError(expected_err, ctx.dir.deleteTree(io, 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 | 2144 | var dir = ctx.dir; |
| 2203 | | try testing.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, .{})); |
| 2145 | try expectError(expected_err, dir.updateFile(io, invalid_path, 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 | 2150 | if (native_os != .wasi) { |
| 2209 | | try testing.expectError(expected_err, ctx.dir.realpath(invalid_path, &[_]u8{})); |
| 2210 | | try testing.expectError(expected_err, ctx.dir.realpathAlloc(testing.allocator, invalid_path)); |
| 2151 | try expectError(expected_err, ctx.dir.realpath(invalid_path, &[_]u8{})); |
| 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 | 2157 | if (native_os != .wasi and ctx.path_type != .relative) { |
| 2216 | | try testing.expectError(expected_err, Dir.copyFileAbsolute(invalid_path, invalid_path, .{})); |
| 2217 | | try testing.expectError(expected_err, Dir.makeDirAbsolute(invalid_path)); |
| 2218 | | try testing.expectError(expected_err, Dir.deleteDirAbsolute(invalid_path)); |
| 2219 | | try testing.expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path)); |
| 2220 | | try testing.expectError(expected_err, Dir.openDirAbsolute(invalid_path, .{})); |
| 2221 | | try testing.expectError(expected_err, Dir.openFileAbsolute(invalid_path, .{})); |
| 2222 | | try testing.expectError(expected_err, Dir.accessAbsolute(invalid_path, .{})); |
| 2223 | | try testing.expectError(expected_err, Dir.createFileAbsolute(invalid_path, .{})); |
| 2224 | | try testing.expectError(expected_err, Dir.deleteFileAbsolute(invalid_path)); |
| 2158 | try expectError(expected_err, Dir.copyFileAbsolute(invalid_path, invalid_path, .{})); |
| 2159 | try expectError(expected_err, Dir.makeDirAbsolute(invalid_path)); |
| 2160 | try expectError(expected_err, Dir.deleteDirAbsolute(invalid_path)); |
| 2161 | try expectError(expected_err, Dir.renameAbsolute(invalid_path, invalid_path)); |
| 2162 | try expectError(expected_err, Dir.openDirAbsolute(invalid_path, .{})); |
| 2163 | try expectError(expected_err, Dir.openFileAbsolute(invalid_path, .{})); |
| 2164 | try expectError(expected_err, Dir.accessAbsolute(invalid_path, .{})); |
| 2165 | try expectError(expected_err, Dir.createFileAbsolute(invalid_path, .{})); |
| 2166 | try expectError(expected_err, Dir.deleteFileAbsolute(invalid_path)); |
| 2225 | 2167 | var readlink_buf: [Dir.max_path_bytes]u8 = undefined; |
| 2226 | | try testing.expectError(expected_err, Dir.readLinkAbsolute(invalid_path, &readlink_buf)); |
| 2227 | | try testing.expectError(expected_err, Dir.symLinkAbsolute(invalid_path, invalid_path, .{})); |
| 2228 | | try testing.expectError(expected_err, Dir.realpathAlloc(testing.allocator, invalid_path)); |
| 2168 | try expectError(expected_err, Dir.readLinkAbsolute(invalid_path, &readlink_buf)); |
| 2169 | try expectError(expected_err, Dir.symLinkAbsolute(invalid_path, invalid_path, .{})); |
| 2170 | try expectError(expected_err, Dir.realpathAlloc(testing.allocator, invalid_path)); |
| 2229 | 2171 | } |
| 2230 | 2172 | } |
| 2231 | 2173 | }.impl); |
| ... | ... | @@ -2259,8 +2201,8 @@ test "read file non vectored" { |
| 2259 | 2201 | else => |e| return e, |
| 2260 | 2202 | }; |
| 2261 | 2203 | } |
| 2262 | | try testing.expectEqualStrings(contents, w.buffered()); |
| 2263 | | try testing.expectEqual(contents.len, i); |
| 2204 | try expectEqualStrings(contents, w.buffered()); |
| 2205 | try expectEqual(contents.len, i); |
| 2264 | 2206 | } |
| 2265 | 2207 | |
| 2266 | 2208 | test "seek keeping partial buffer" { |
| ... | ... | @@ -2282,7 +2224,7 @@ test "seek keeping partial buffer" { |
| 2282 | 2224 | var read_buffer: [3]u8 = undefined; |
| 2283 | 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 | 2229 | var buf: [4]u8 = undefined; |
| 2288 | 2230 | try file_reader.interface.readSliceAll(&buf); |
| ... | ... | @@ -2292,18 +2234,18 @@ test "seek keeping partial buffer" { |
| 2292 | 2234 | return; |
| 2293 | 2235 | } |
| 2294 | 2236 | |
| 2295 | | try testing.expectEqual(4, file_reader.logicalPos()); |
| 2296 | | try testing.expectEqual(7, file_reader.pos); |
| 2237 | try expectEqual(4, file_reader.logicalPos()); |
| 2238 | try expectEqual(7, file_reader.pos); |
| 2297 | 2239 | try file_reader.seekTo(6); |
| 2298 | | try testing.expectEqual(6, file_reader.logicalPos()); |
| 2299 | | try testing.expectEqual(7, file_reader.pos); |
| 2240 | try expectEqual(6, file_reader.logicalPos()); |
| 2241 | try expectEqual(7, file_reader.pos); |
| 2300 | 2242 | |
| 2301 | | try testing.expectEqualStrings("0123", &buf); |
| 2243 | try expectEqualStrings("0123", &buf); |
| 2302 | 2244 | |
| 2303 | 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 | 2251 | test "seekBy" { |
| ... | ... | @@ -2320,8 +2262,8 @@ test "seekBy" { |
| 2320 | 2262 | |
| 2321 | 2263 | var buffer: [20]u8 = undefined; |
| 2322 | 2264 | const n = try reader.interface.readSliceShort(&buffer); |
| 2323 | | try testing.expectEqual(15, n); |
| 2324 | | try testing.expectEqualStrings("t's test seekBy", buffer[0..15]); |
| 2265 | try expectEqual(15, n); |
| 2266 | try expectEqualStrings("t's test seekBy", buffer[0..15]); |
| 2325 | 2267 | } |
| 2326 | 2268 | |
| 2327 | 2269 | test "seekTo flushes buffered data" { |
| ... | ... | @@ -2348,7 +2290,7 @@ test "seekTo flushes buffered data" { |
| 2348 | 2290 | |
| 2349 | 2291 | var buf: [4]u8 = undefined; |
| 2350 | 2292 | try file_reader.interface.readSliceAll(&buf); |
| 2351 | | try std.testing.expectEqualStrings(contents, &buf); |
| 2293 | try expectEqualStrings(contents, &buf); |
| 2352 | 2294 | } |
| 2353 | 2295 | |
| 2354 | 2296 | test "File.Writer sendfile with buffered contents" { |
| ... | ... | @@ -2372,7 +2314,7 @@ test "File.Writer sendfile with buffered contents" { |
| 2372 | 2314 | var out_buf: [1]u8 = undefined; |
| 2373 | 2315 | var out_w = out.writerStreaming(&out_buf); |
| 2374 | 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 | 2318 | try out_w.interface.flush(); |
| 2377 | 2319 | } |
| 2378 | 2320 | |
| ... | ... | @@ -2380,8 +2322,8 @@ test "File.Writer sendfile with buffered contents" { |
| 2380 | 2322 | defer check.close(io); |
| 2381 | 2323 | var check_buf: [4]u8 = undefined; |
| 2382 | 2324 | var check_r = check.reader(io, &check_buf); |
| 2383 | | try testing.expectEqualStrings("abcd", try check_r.interface.take(4)); |
| 2384 | | try testing.expectError(error.EndOfStream, check_r.interface.takeByte()); |
| 2325 | try expectEqualStrings("abcd", try check_r.interface.take(4)); |
| 2326 | try expectError(error.EndOfStream, check_r.interface.takeByte()); |
| 2385 | 2327 | } |
| 2386 | 2328 | |
| 2387 | 2329 | test "readlink on Windows" { |
| ... | ... | @@ -2410,23 +2352,72 @@ test "readlinkat" { |
| 2410 | 2352 | try tmp.dir.writeFile(io, .{ .sub_path = "file.txt", .data = "nonsense" }); |
| 2411 | 2353 | |
| 2412 | 2354 | // create a symbolic link |
| 2413 | | if (native_os == .windows) { |
| 2414 | | std.os.windows.CreateSymbolicLink( |
| 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) { |
| 2355 | tmp.dir.symLink("file.txt", "link", .{}) catch |err| switch (err) { |
| 2356 | error.AccessDenied => { |
| 2420 | 2357 | // Symlink requires admin privileges on windows, so this test can legitimately fail. |
| 2421 | | error.AccessDenied => return error.SkipZigTest, |
| 2422 | | else => return err, |
| 2423 | | }; |
| 2424 | | } else { |
| 2425 | | try posix.symlinkat("file.txt", tmp.dir.handle, "link"); |
| 2426 | | } |
| 2358 | if (native_os == .windows) return error.SkipZigTest; |
| 2359 | }, |
| 2360 | }; |
| 2427 | 2361 | |
| 2428 | 2362 | // read the link |
| 2429 | 2363 | var buffer: [fs.max_path_bytes]u8 = undefined; |
| 2430 | 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 | } |