<commit_before>const std = @import("../std.zig");
const os = std.os;
const testing = std.testing;
const expect = testing.expect;
const expectEqual = testing.expectEqual;
const expectError = testing.expectError;
const io = std.io;
const fs = std.fs;
const mem = std.mem;
const elf = std.elf;
const File = std.fs.File;
const Thread = std.Thread;

const a = std.testing.allocator;

const builtin = @import("builtin");
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
const tmpDir = std.testing.tmpDir;
const Dir = std.fs.Dir;
const ArenaAllocator = std.heap.ArenaAllocator;

test "open smoke test" {
    if (builtin.os.tag == .wasi) return error.SkipZigTest;

    // TODO verify file attributes using `fstat`

    var tmp = tmpDir(.{});
    defer tmp.cleanup();

    // Get base abs path
    var arena = ArenaAllocator.init(testing.allocator);
    defer arena.deinit();

    const base_path = blk: {
        const relative_path = try fs.path.join(&arena.allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
        break :blk try fs.realpathAlloc(&arena.allocator, relative_path);
    };

    var file_path: []u8 = undefined;
    var fd: os.fd_t = undefined;
    const mode: os.mode_t = if (builtin.os.tag == .windows) 0 else 0o666;

    // Create some file using `open`.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
    fd = try os.open(file_path, os.O_RDWR | os.O_CREAT | os.O_EXCL, mode);
    os.close(fd);

    // Try this again with the same flags. This op should fail with error.PathAlreadyExists.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
    expectError(error.PathAlreadyExists, os.open(file_path, os.O_RDWR | os.O_CREAT | os.O_EXCL, mode));

    // Try opening without `O_EXCL` flag.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
    fd = try os.open(file_path, os.O_RDWR | os.O_CREAT, mode);
    os.close(fd);

    // Try opening as a directory which should fail.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
    expectError(error.NotDir, os.open(file_path, os.O_RDWR | os.O_DIRECTORY, mode));

    // Create some directory
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_dir" });
    try os.mkdir(file_path, mode);

    // Open dir using `open`
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_dir" });
    fd = try os.open(file_path, os.O_RDONLY | os.O_DIRECTORY, mode);
    os.close(fd);

    // Try opening as file which should fail.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_dir" });
    expectError(error.IsDir, os.open(file_path, os.O_RDWR, mode));
}

test "openat smoke test" {
    if (builtin.os.tag == .wasi) return error.SkipZigTest;

    // TODO verify file attributes using `fstatat`

    var tmp = tmpDir(.{});
    defer tmp.cleanup();

    var fd: os.fd_t = undefined;
    const mode: os.mode_t = if (builtin.os.tag == .windows) 0 else 0o666;

    // Create some file using `openat`.
    fd = try os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_CREAT | os.O_EXCL, mode);
    os.close(fd);

    // Try this again with the same flags. This op should fail with error.PathAlreadyExists.
    expectError(error.PathAlreadyExists, os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_CREAT | os.O_EXCL, mode));

    // Try opening without `O_EXCL` flag.
    fd = try os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_CREAT, mode);
    os.close(fd);

    // Try opening as a directory which should fail.
    expectError(error.NotDir, os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_DIRECTORY, mode));

    // Create some directory
    try os.mkdirat(tmp.dir.fd, "some_dir", mode);

    // Open dir using `open`
    fd = try os.openat(tmp.dir.fd, "some_dir", os.O_RDONLY | os.O_DIRECTORY, mode);
    os.close(fd);

    // Try opening as file which should fail.
    expectError(error.IsDir, os.openat(tmp.dir.fd, "some_dir", os.O_RDWR, mode));
}

test "symlink with relative paths" {
    if (builtin.os.tag == .wasi) return error.SkipZigTest;

    // First, try relative paths in cwd
    var cwd = fs.cwd();
    try cwd.writeFile("file.txt", "nonsense");

    if (builtin.os.tag == .windows) {
        try os.windows.CreateSymbolicLink(cwd.fd, &[_]u16{ 's', 'y', 'm', 'l', 'i', 'n', 'k', 'e', 'd' }, &[_]u16{ 'f', 'i', 'l', 'e', '.', 't', 'x', 't' }, false);
    } else {
        try os.symlink("file.txt", "symlinked");
    }
<commit_msg>std.os tests: improve robustness of "symlink with relative paths"<commit_after>const std = @import("../std.zig");
const os = std.os;
const testing = std.testing;
const expect = testing.expect;
const expectEqual = testing.expectEqual;
const expectError = testing.expectError;
const io = std.io;
const fs = std.fs;
const mem = std.mem;
const elf = std.elf;
const File = std.fs.File;
const Thread = std.Thread;

const a = std.testing.allocator;

const builtin = @import("builtin");
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
const tmpDir = std.testing.tmpDir;
const Dir = std.fs.Dir;
const ArenaAllocator = std.heap.ArenaAllocator;

test "open smoke test" {
    if (builtin.os.tag == .wasi) return error.SkipZigTest;

    // TODO verify file attributes using `fstat`

    var tmp = tmpDir(.{});
    defer tmp.cleanup();

    // Get base abs path
    var arena = ArenaAllocator.init(testing.allocator);
    defer arena.deinit();

    const base_path = blk: {
        const relative_path = try fs.path.join(&arena.allocator, &[_][]const u8{ "zig-cache", "tmp", tmp.sub_path[0..] });
        break :blk try fs.realpathAlloc(&arena.allocator, relative_path);
    };

    var file_path: []u8 = undefined;
    var fd: os.fd_t = undefined;
    const mode: os.mode_t = if (builtin.os.tag == .windows) 0 else 0o666;

    // Create some file using `open`.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
    fd = try os.open(file_path, os.O_RDWR | os.O_CREAT | os.O_EXCL, mode);
    os.close(fd);

    // Try this again with the same flags. This op should fail with error.PathAlreadyExists.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
    expectError(error.PathAlreadyExists, os.open(file_path, os.O_RDWR | os.O_CREAT | os.O_EXCL, mode));

    // Try opening without `O_EXCL` flag.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
    fd = try os.open(file_path, os.O_RDWR | os.O_CREAT, mode);
    os.close(fd);

    // Try opening as a directory which should fail.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_file" });
    expectError(error.NotDir, os.open(file_path, os.O_RDWR | os.O_DIRECTORY, mode));

    // Create some directory
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_dir" });
    try os.mkdir(file_path, mode);

    // Open dir using `open`
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_dir" });
    fd = try os.open(file_path, os.O_RDONLY | os.O_DIRECTORY, mode);
    os.close(fd);

    // Try opening as file which should fail.
    file_path = try fs.path.join(&arena.allocator, &[_][]const u8{ base_path, "some_dir" });
    expectError(error.IsDir, os.open(file_path, os.O_RDWR, mode));
}

test "openat smoke test" {
    if (builtin.os.tag == .wasi) return error.SkipZigTest;

    // TODO verify file attributes using `fstatat`

    var tmp = tmpDir(.{});
    defer tmp.cleanup();

    var fd: os.fd_t = undefined;
    const mode: os.mode_t = if (builtin.os.tag == .windows) 0 else 0o666;

    // Create some file using `openat`.
    fd = try os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_CREAT | os.O_EXCL, mode);
    os.close(fd);

    // Try this again with the same flags. This op should fail with error.PathAlreadyExists.
    expectError(error.PathAlreadyExists, os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_CREAT | os.O_EXCL, mode));

    // Try opening without `O_EXCL` flag.
    fd = try os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_CREAT, mode);
    os.close(fd);

    // Try opening as a directory which should fail.
    expectError(error.NotDir, os.openat(tmp.dir.fd, "some_file", os.O_RDWR | os.O_DIRECTORY, mode));

    // Create some directory
    try os.mkdirat(tmp.dir.fd, "some_dir", mode);

    // Open dir using `open`
    fd = try os.openat(tmp.dir.fd, "some_dir", os.O_RDONLY | os.O_DIRECTORY, mode);
    os.close(fd);

    // Try opening as file which should fail.
    expectError(error.IsDir, os.openat(tmp.dir.fd, "some_dir", os.O_RDWR, mode));
}

test "symlink with relative paths" {
    if (builtin.os.tag == .wasi) return error.SkipZigTest;

    const cwd = fs.cwd();
    cwd.deleteFile("file.txt") catch {};
    cwd.deleteFile("symlinked") catch {};

    // First, try relative paths in cwd
    try cwd.writeFile("file.txt", "nonsense");

    if (builtin.os.tag == .windows) {
        try os.windows.CreateSymbolicLink(cwd.fd, &[_]u16{ 's', 'y', 'm', 'l', 'i', 'n', 'k', 'e', 'd' }, &[_]u16{ 'f', 'i', 'l', 'e', '.', 't', 'x', 't' }, false);
    } else {
        try os.symlink("file.txt", "symlinked");
    }

{'fraction_non_alphanumeric': 0.1598421838345063, 'fraction_numerical': 0.005118362124120281, 'mean_word_length': 3.3261070110701105, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6844629', 'n_tokens_mistral': 3506, 'n_tokens_neox': 3419, 'n_words': 870}