zig/lib/std/os/test.zig

261 lines
7.8 KiB
Zig
Raw Normal View History

2019-03-02 13:46:04 -08:00
const std = @import("../std.zig");
const os = std.os;
const testing = std.testing;
const expect = std.testing.expect;
const io = std.io;
2019-05-26 10:17:34 -07:00
const fs = std.fs;
const mem = std.mem;
2019-05-29 01:30:30 -07:00
const elf = std.elf;
2019-05-24 19:52:07 -07:00
const File = std.fs.File;
2019-05-25 10:07:44 -07:00
const Thread = std.Thread;
const a = std.debug.global_allocator;
const builtin = @import("builtin");
const AtomicRmwOp = builtin.AtomicRmwOp;
const AtomicOrder = builtin.AtomicOrder;
test "makePath, put some files in it, deleteTree" {
2019-05-26 20:35:26 -07:00
try fs.makePath(a, "os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c");
2019-05-26 10:17:34 -07:00
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c" ++ fs.path.sep_str ++ "file.txt", "nonsense");
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "file2.txt", "blah");
try fs.deleteTree("os_test_tmp");
if (fs.cwd().openDirTraverse("os_test_tmp")) |dir| {
@panic("expected error");
2018-03-29 01:23:44 -07:00
} else |err| {
expect(err == error.FileNotFound);
2018-03-29 01:23:44 -07:00
}
}
2018-04-13 02:27:09 -07:00
test "access file" {
2019-05-26 20:35:26 -07:00
try fs.makePath(a, "os_test_tmp");
2019-05-26 10:17:34 -07:00
if (File.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt")) |ok| {
@panic("expected error");
2018-04-13 02:27:09 -07:00
} else |err| {
expect(err == error.FileNotFound);
2018-04-13 02:27:09 -07:00
}
2019-05-26 10:17:34 -07:00
try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", "");
2019-05-26 20:35:26 -07:00
try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK);
try fs.deleteTree("os_test_tmp");
2018-04-13 02:27:09 -07:00
}
2019-05-25 10:07:44 -07:00
fn testThreadIdFn(thread_id: *Thread.Id) void {
thread_id.* = Thread.getCurrentId();
}
2019-05-25 10:07:44 -07:00
test "std.Thread.getCurrentId" {
if (builtin.single_threaded) return error.SkipZigTest;
2019-05-25 10:07:44 -07:00
var thread_current_id: Thread.Id = undefined;
const thread = try Thread.spawn(&thread_current_id, testThreadIdFn);
2018-08-06 14:30:55 -07:00
const thread_id = thread.handle();
thread.wait();
2019-05-25 10:07:44 -07:00
if (Thread.use_pthreads) {
expect(thread_current_id == thread_id);
} else if (builtin.os == .windows) {
2019-05-26 20:35:26 -07:00
expect(Thread.getCurrentId() != thread_current_id);
} else {
2019-05-26 20:35:26 -07:00
// If the thread completes very quickly, then thread_id can be 0. See the
// documentation comments for `std.Thread.handle`.
expect(thread_id == 0 or thread_current_id == thread_id);
}
}
test "spawn threads" {
if (builtin.single_threaded) return error.SkipZigTest;
var shared_ctx: i32 = 1;
2019-05-25 10:07:44 -07:00
const thread1 = try Thread.spawn({}, start1);
const thread2 = try Thread.spawn(&shared_ctx, start2);
const thread3 = try Thread.spawn(&shared_ctx, start2);
const thread4 = try Thread.spawn(&shared_ctx, start2);
thread1.wait();
thread2.wait();
thread3.wait();
thread4.wait();
expect(shared_ctx == 4);
}
fn start1(ctx: void) u8 {
return 0;
}
fn start2(ctx: *i32) u8 {
_ = @atomicRmw(i32, ctx, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
return 0;
}
test "cpu count" {
2019-05-26 20:35:26 -07:00
const cpu_count = try Thread.cpuCount();
expect(cpu_count >= 1);
}
test "AtomicFile" {
var buffer: [1024]u8 = undefined;
const allocator = &std.heap.FixedBufferAllocator.init(buffer[0..]).allocator;
const test_out_file = "tmp_atomic_file_test_dest.txt";
const test_content =
\\ hello!
\\ this is a test file
;
{
2019-05-26 20:35:26 -07:00
var af = try fs.AtomicFile.init(test_out_file, File.default_mode);
defer af.deinit();
try af.file.write(test_content);
try af.finish();
}
const content = try io.readFileAlloc(allocator, test_out_file);
expect(mem.eql(u8, content, test_content));
try fs.cwd().deleteFile(test_out_file);
}
test "thread local storage" {
if (builtin.single_threaded) return error.SkipZigTest;
2019-05-25 10:07:44 -07:00
const thread1 = try Thread.spawn({}, testTls);
const thread2 = try Thread.spawn({}, testTls);
testTls({});
thread1.wait();
thread2.wait();
}
threadlocal var x: i32 = 1234;
fn testTls(context: void) void {
if (x != 1234) @panic("bad start value");
x += 1;
if (x != 1235) @panic("bad end value");
}
test "getrandom" {
var buf_a: [50]u8 = undefined;
var buf_b: [50]u8 = undefined;
try os.getrandom(&buf_a);
try os.getrandom(&buf_b);
// If this test fails the chance is significantly higher that there is a bug than
// that two sets of 50 bytes were equal.
expect(!mem.eql(u8, &buf_a, &buf_b));
}
test "getcwd" {
// at least call it so it gets compiled
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
2019-05-26 20:35:26 -07:00
_ = os.getcwd(&buf) catch undefined;
}
test "realpath" {
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
2019-05-26 20:35:26 -07:00
testing.expectError(error.FileNotFound, fs.realpath("definitely_bogus_does_not_exist1234", &buf));
}
2019-05-29 00:43:39 -07:00
test "sigaltstack" {
if (builtin.os == .windows or builtin.os == .wasi) return error.SkipZigTest;
var st: os.stack_t = undefined;
try os.sigaltstack(null, &st);
// Setting a stack size less than MINSIGSTKSZ returns ENOMEM
st.ss_flags = 0;
st.ss_size = 1;
testing.expectError(error.SizeTooSmall, os.sigaltstack(&st, null));
}
2019-05-29 01:30:30 -07:00
// If the type is not available use void to avoid erroring out when `iter_fn` is
// analyzed
const dl_phdr_info = if (@hasDecl(os, "dl_phdr_info")) os.dl_phdr_info else c_void;
export fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 {
if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
return 0;
var counter = data.?;
// Count how many libraries are loaded
2019-11-06 20:25:57 -08:00
counter.* += @as(usize, 1);
2019-05-29 01:30:30 -07:00
// The image should contain at least a PT_LOAD segment
if (info.dlpi_phnum < 1) return -1;
// Quick & dirty validation of the phdr pointers, make sure we're not
// pointing to some random gibberish
var i: usize = 0;
var found_load = false;
while (i < info.dlpi_phnum) : (i += 1) {
const phdr = info.dlpi_phdr[i];
if (phdr.p_type != elf.PT_LOAD) continue;
// Find the ELF header
const elf_header = @intToPtr(*elf.Ehdr, phdr.p_vaddr - phdr.p_offset);
// Validate the magic
if (!mem.eql(u8, elf_header.e_ident[0..4], "\x7fELF")) return -1;
// Consistency check
if (elf_header.e_phnum != info.dlpi_phnum) return -1;
found_load = true;
break;
}
if (!found_load) return -1;
return 42;
}
test "dl_iterate_phdr" {
if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
return error.SkipZigTest;
var counter: usize = 0;
expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
expect(counter != 0);
}
2019-09-22 12:36:11 -07:00
test "gethostname" {
if (builtin.os == .windows)
2019-09-22 12:36:11 -07:00
return error.SkipZigTest;
var buf: [os.HOST_NAME_MAX]u8 = undefined;
const hostname = try os.gethostname(&buf);
expect(hostname.len != 0);
}
2019-10-03 06:32:47 -07:00
test "pipe" {
if (builtin.os == .windows)
2019-10-03 06:32:47 -07:00
return error.SkipZigTest;
var fds = try os.pipe();
try os.write(fds[1], "hello");
var buf: [16]u8 = undefined;
expect((try os.read(fds[0], buf[0..])) == 5);
testing.expectEqualSlices(u8, buf[0..5], "hello");
os.close(fds[1]);
os.close(fds[0]);
}
test "argsAlloc" {
var args = try std.process.argsAlloc(std.heap.page_allocator);
std.process.argsFree(std.heap.page_allocator, args);
}
test "memfd_create" {
// memfd_create is linux specific.
if (builtin.os != .linux) return error.SkipZigTest;
// Zig's CI testing infrastructure uses QEMU. Currently the version is
// qemu 2.11 from Ubuntu 18.04, which does not have memfd_create support.
// memfd_create support is introduced in qemu 4.2. To avoid
// "invalid syscall" errors from qemu, we disable the test when not linking libc.
// https://github.com/ziglang/zig/issues/4019
if (!builtin.link_libc) return error.SkipZigTest;
const fd = try std.os.memfd_create("test", 0);
defer std.os.close(fd);
try std.os.write(fd, "test");
try std.os.lseek_SET(fd, 0);
var buf: [10]u8 = undefined;
const bytes_read = try std.os.read(fd, &buf);
expect(bytes_read == 4);
expect(mem.eql(u8, buf[0..4], "test"));
}