diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-09-26 01:54:45 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-09-26 01:54:45 -0400 |
| commit | 68bb3945708c43109c48bda3664176307d45b62c (patch) | |
| tree | afb9731e10cef9d192560b52cd9ae2cf179775c4 /lib/std/os/test.zig | |
| parent | 6128bc728d1e1024a178c16c2149f5b1a167a013 (diff) | |
| parent | 4637e8f9699af9c3c6cf4df50ef5bb67c7a318a4 (diff) | |
| download | zig-68bb3945708c43109c48bda3664176307d45b62c.tar.gz zig-68bb3945708c43109c48bda3664176307d45b62c.zip | |
Merge pull request #3315 from ziglang/mv-std-lib
Move std/ to lib/std/
Diffstat (limited to 'lib/std/os/test.zig')
| -rw-r--r-- | lib/std/os/test.zig | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig new file mode 100644 index 0000000000..87d57b36c0 --- /dev/null +++ b/lib/std/os/test.zig @@ -0,0 +1,225 @@ +const std = @import("../std.zig"); +const os = std.os; +const testing = std.testing; +const expect = std.testing.expect; +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.debug.global_allocator; + +const builtin = @import("builtin"); +const AtomicRmwOp = builtin.AtomicRmwOp; +const AtomicOrder = builtin.AtomicOrder; + +test "makePath, put some files in it, deleteTree" { + try fs.makePath(a, "os_test_tmp" ++ fs.path.sep_str ++ "b" ++ fs.path.sep_str ++ "c"); + 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(a, "os_test_tmp"); + if (fs.Dir.open(a, "os_test_tmp")) |dir| { + @panic("expected error"); + } else |err| { + expect(err == error.FileNotFound); + } +} + +test "access file" { + try fs.makePath(a, "os_test_tmp"); + if (File.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt")) |ok| { + @panic("expected error"); + } else |err| { + expect(err == error.FileNotFound); + } + + try io.writeFile("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", ""); + try os.access("os_test_tmp" ++ fs.path.sep_str ++ "file.txt", os.F_OK); + try fs.deleteTree(a, "os_test_tmp"); +} + +fn testThreadIdFn(thread_id: *Thread.Id) void { + thread_id.* = Thread.getCurrentId(); +} + +test "std.Thread.getCurrentId" { + if (builtin.single_threaded) return error.SkipZigTest; + + var thread_current_id: Thread.Id = undefined; + const thread = try Thread.spawn(&thread_current_id, testThreadIdFn); + const thread_id = thread.handle(); + thread.wait(); + if (Thread.use_pthreads) { + expect(thread_current_id == thread_id); + } else if (os.windows.is_the_target) { + expect(Thread.getCurrentId() != thread_current_id); + } else { + // 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; + + 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" { + const cpu_count = try Thread.cpuCount(); + expect(cpu_count >= 1); +} + +test "AtomicFile" { + if (builtin.arch == .aarch64 and builtin.glibc_version != null) { + // TODO https://github.com/ziglang/zig/issues/3288 + return error.SkipZigTest; + } + 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 + ; + { + 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.deleteFile(test_out_file); +} + +test "thread local storage" { + if (builtin.single_threaded) return error.SkipZigTest; + 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; + _ = os.getcwd(&buf) catch undefined; +} + +test "realpath" { + var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + testing.expectError(error.FileNotFound, fs.realpath("definitely_bogus_does_not_exist1234", &buf)); +} + +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)); +} + +// 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 + counter.* += usize(1); + + // 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); +} + +test "gethostname" { + if (os.windows.is_the_target) + return error.SkipZigTest; + + var buf: [os.HOST_NAME_MAX]u8 = undefined; + const hostname = try os.gethostname(&buf); + expect(hostname.len != 0); +} |
