Commit 1ac46fac15

Andrew Kelley <superjoe30@gmail.com>
2017-11-10 20:02:45
add a std lib test for reading and writing files
* fix fstat wrong on darwin * move std.debug.global_allocator to std.debug.global_allocator_state and make it private * add std.debug.global_allocator as a pointer (to upgrade your zig code remove the '&')
1 parent 336d818
std/c/darwin.zig
@@ -6,26 +6,28 @@ pub const _errno = __error;
 
 /// Renamed to Stat to not conflict with the stat function.
 pub const Stat = extern struct {
-    dev: u32,
+    dev: i32,
     mode: u16,
     nlink: u16,
     ino: u64,
     uid: u32,
     gid: u32,
-    rdev: u64,
-
-    atim: timespec,
-    mtim: timespec,
-    ctim: timespec,
-
-    size: u64,
-    blocks: u64,
-    blksize: u32,
+    rdev: i32,
+    atime: usize,
+    atimensec: usize,
+    mtime: usize,
+    mtimensec: usize,
+    ctime: usize,
+    ctimensec: usize,
+    birthtime: usize,
+    birthtimensec: usize,
+    size: i64,
+    blocks: i64,
+    blksize: i32,
     flags: u32,
     gen: u32,
     lspare: i32,
-    qspare: [2]u64,
-
+    qspare: [2]i64,
 };
 
 pub const timespec = extern struct {
std/c/index.zig
@@ -14,6 +14,7 @@ pub extern "c" fn exit(code: c_int) -> noreturn;
 pub extern "c" fn isatty(fd: c_int) -> c_int;
 pub extern "c" fn close(fd: c_int) -> c_int;
 pub extern "c" fn fstat(fd: c_int, buf: &Stat) -> c_int;
+pub extern "c" fn @"fstat$INODE64"(fd: c_int, buf: &Stat) -> c_int;
 pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) -> isize;
 pub extern "c" fn open(path: &const u8, oflag: c_int, ...) -> c_int;
 pub extern "c" fn raise(sig: c_int) -> c_int;
std/os/darwin.zig
@@ -129,7 +129,7 @@ pub fn isatty(fd: i32) -> bool {
 }
 
 pub fn fstat(fd: i32, buf: &c.Stat) -> usize {
-    errnoWrap(c.fstat(fd, buf))
+    errnoWrap(c.@"fstat$INODE64"(fd, buf))
 }
 
 pub fn lseek(fd: i32, offset: isize, whence: c_int) -> usize {
std/os/index.zig
@@ -562,7 +562,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 {
 
 test "os.getCwd" {
     // at least call it so it gets compiled
-    _ = getCwd(&debug.global_allocator);
+    _ = getCwd(debug.global_allocator);
 }
 
 pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void {
@@ -1432,10 +1432,10 @@ test "windows arg parsing" {
 fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) {
     var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);
     for (expected_args) |expected_arg| {
-        const arg = %%??it.next(&debug.global_allocator);
+        const arg = %%??it.next(debug.global_allocator);
         assert(mem.eql(u8, arg, expected_arg));
     }
-    assert(it.next(&debug.global_allocator) == null);
+    assert(it.next(debug.global_allocator) == null);
 }
 
 test "std.os" {
@@ -1500,4 +1500,3 @@ pub fn isTty(handle: FileHandle) -> bool {
         }
     }
 }
-
std/os/path.zig
@@ -41,23 +41,23 @@ pub fn joinPosix(allocator: &Allocator, paths: ...) -> %[]u8 {
 }
 
 test "os.path.join" {
-    assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, "c:\\a\\b", "c"), "c:\\a\\b\\c"));
-    assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, "c:\\a\\b\\", "c"), "c:\\a\\b\\c"));
+    assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\a\\b", "c"), "c:\\a\\b\\c"));
+    assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\a\\b\\", "c"), "c:\\a\\b\\c"));
 
-    assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, "c:\\", "a", "b\\", "c"), "c:\\a\\b\\c"));
-    assert(mem.eql(u8, %%joinWindows(&debug.global_allocator, "c:\\a\\", "b\\", "c"), "c:\\a\\b\\c"));
+    assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\", "a", "b\\", "c"), "c:\\a\\b\\c"));
+    assert(mem.eql(u8, %%joinWindows(debug.global_allocator, "c:\\a\\", "b\\", "c"), "c:\\a\\b\\c"));
 
-    assert(mem.eql(u8, %%joinWindows(&debug.global_allocator,
+    assert(mem.eql(u8, %%joinWindows(debug.global_allocator,
         "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig"),
         "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig"));
 
-    assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/a/b", "c"), "/a/b/c"));
-    assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/a/b/", "c"), "/a/b/c"));
+    assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/a/b", "c"), "/a/b/c"));
+    assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/a/b/", "c"), "/a/b/c"));
 
-    assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c"));
-    assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/a/", "b/", "c"), "/a/b/c"));
+    assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c"));
+    assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/a/", "b/", "c"), "/a/b/c"));
 
-    assert(mem.eql(u8, %%joinPosix(&debug.global_allocator, "/home/andy/dev/zig/build/lib/zig/std", "io.zig"),
+    assert(mem.eql(u8, %%joinPosix(debug.global_allocator, "/home/andy/dev/zig/build/lib/zig/std", "io.zig"),
         "/home/andy/dev/zig/build/lib/zig/std/io.zig"));
 }
 
@@ -453,7 +453,7 @@ pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) -> %[]u8 {
 }
 
 test "os.path.resolve" {
-    const cwd = %%os.getCwd(&debug.global_allocator);
+    const cwd = %%os.getCwd(debug.global_allocator);
     if (is_windows) {
         assert(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
     } else {
@@ -492,11 +492,11 @@ test "os.path.resolvePosix" {
 }
 
 fn testResolveWindows(paths: []const []const u8) -> []u8 {
-    return %%resolveWindows(&debug.global_allocator, paths);
+    return %%resolveWindows(debug.global_allocator, paths);
 }
 
 fn testResolvePosix(paths: []const []const u8) -> []u8 {
-    return %%resolvePosix(&debug.global_allocator, paths);
+    return %%resolvePosix(debug.global_allocator, paths);
 }
 
 pub fn dirname(path: []const u8) -> []const u8 {
@@ -899,12 +899,12 @@ test "os.path.relative" {
 }
 
 fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) {
-    const result = %%relativePosix(&debug.global_allocator, from, to);
+    const result = %%relativePosix(debug.global_allocator, from, to);
     assert(mem.eql(u8, result, expected_output));
 }
 
 fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) {
-    const result = %%relativeWindows(&debug.global_allocator, from, to);
+    const result = %%relativeWindows(debug.global_allocator, from, to);
     assert(mem.eql(u8, result, expected_output));
 }
 
@@ -1022,5 +1022,5 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
 
 test "os.path.real" {
     // at least call it so it gets compiled
-    _ = real(&debug.global_allocator, "some_path");
+    _ = real(debug.global_allocator, "some_path");
 }
std/array_list.zig
@@ -101,7 +101,7 @@ pub fn ArrayList(comptime T: type) -> type{
 }
 
 test "basic ArrayList test" {
-    var list = ArrayList(i32).init(&debug.global_allocator);
+    var list = ArrayList(i32).init(debug.global_allocator);
     defer list.deinit();
 
     {var i: usize = 0; while (i < 10) : (i += 1) {
std/buffer.zig
@@ -135,7 +135,7 @@ pub const Buffer = struct {
 test "simple Buffer" {
     const cstr = @import("cstr.zig");
 
-    var buf = %%Buffer.init(&debug.global_allocator, "");
+    var buf = %%Buffer.init(debug.global_allocator, "");
     assert(buf.len() == 0);
     %%buf.append("hello");
     %%buf.appendByte(' ');
std/debug.zig
@@ -38,7 +38,7 @@ fn getStderrStream() -> %&io.OutStream {
 /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
 pub fn dumpStackTrace() {
     const stderr = getStderrStream() %% return;
-    writeStackTrace(stderr, &global_allocator, stderr_file.isTty(), 1) %% return;
+    writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% return;
 }
 
 /// This function invokes undefined behavior when `ok` is `false`.
@@ -86,7 +86,7 @@ pub fn panic(comptime format: []const u8, args: ...) -> noreturn {
 
     const stderr = getStderrStream() %% os.abort();
     stderr.print(format ++ "\n", args) %% os.abort();
-    writeStackTrace(stderr, &global_allocator, stderr_file.isTty(), 1) %% os.abort();
+    writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% os.abort();
 
     os.abort();
 }
@@ -967,7 +967,8 @@ fn readILeb128(in_stream: &io.InStream) -> %i64 {
     }
 }
 
-pub var global_allocator = mem.Allocator {
+pub const global_allocator = &global_allocator_state;
+var global_allocator_state = mem.Allocator {
     .allocFn = globalAlloc,
     .reallocFn = globalRealloc,
     .freeFn = globalFree,
std/hash_map.zig
@@ -232,7 +232,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
 }
 
 test "basicHashMapTest" {
-    var map = HashMap(i32, i32, hash_i32, eql_i32).init(&debug.global_allocator);
+    var map = HashMap(i32, i32, hash_i32, eql_i32).init(debug.global_allocator);
     defer map.deinit();
 
     assert(%%map.put(1, 11) == null);
std/io.zig
@@ -20,6 +20,12 @@ const fmt = std.fmt;
 const is_posix = builtin.os != builtin.Os.windows;
 const is_windows = builtin.os == builtin.Os.windows;
 
+test "import io tests" {
+    comptime {
+        _ = @import("io_test.zig");
+    }
+}
+
 /// The function received invalid input at runtime. An Invalid error means a
 /// bug in the program that called the function.
 error Invalid;
std/io_test.zig
@@ -0,0 +1,45 @@
+const std = @import("index.zig");
+const io = std.io;
+const allocator = std.debug.global_allocator;
+const Rand = std.rand.Rand;
+const assert = std.debug.assert;
+const mem = std.mem;
+const os = std.os;
+
+test "write a file, read it, then delete it" {
+    var data: [1024]u8 = undefined;
+    var rng = Rand.init(1234);
+    rng.fillBytes(data[0..]);
+    const tmp_file_name = "temp_test_file.txt";
+    {
+        var file = %%io.File.openWrite(tmp_file_name, allocator);
+        defer file.close();
+
+        var file_out_stream = io.FileOutStream.init(&file);
+        var buf_stream = io.BufferedOutStream.init(&file_out_stream.stream);
+        const st = &buf_stream.stream;
+        %%st.print("begin");
+        %%st.write(data[0..]);
+        %%st.print("end");
+        %%buf_stream.flush();
+    }
+    {
+        var file = %%io.File.openRead(tmp_file_name, allocator);
+        defer file.close();
+
+        const file_size = %%file.getEndPos();
+        const expected_file_size = "begin".len + data.len + "end".len;
+        assert(file_size == expected_file_size);
+
+        var file_in_stream = io.FileInStream.init(&file);
+        var buf_stream = io.BufferedInStream.init(&file_in_stream.stream);
+        const st = &buf_stream.stream;
+        const contents = %%st.readAllAlloc(allocator, 2 * 1024);
+        defer allocator.free(contents);
+
+        assert(mem.eql(u8, contents[0.."begin".len], "begin"));
+        assert(mem.eql(u8, contents["begin".len..contents.len - "end".len], data));
+        assert(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
+    }
+    %%os.deleteFile(allocator, tmp_file_name);
+}
std/linked_list.zig
@@ -195,7 +195,7 @@ pub fn LinkedList(comptime T: type) -> type {
 }
 
 test "basic linked list test" {
-    const allocator = &debug.global_allocator;
+    const allocator = debug.global_allocator;
     var list = LinkedList(u32).init();
 
     var one   = %%list.createNode(1, allocator);
std/mem.zig
@@ -331,8 +331,8 @@ pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 {
 }
 
 test "mem.join" {
-    assert(eql(u8, %%join(&debug.global_allocator, ',', "a", "b", "c"), "a,b,c"));
-    assert(eql(u8, %%join(&debug.global_allocator, ',', "a"), "a"));
+    assert(eql(u8, %%join(debug.global_allocator, ',', "a", "b", "c"), "a,b,c"));
+    assert(eql(u8, %%join(debug.global_allocator, ',', "a"), "a"));
 }
 
 test "testStringEquality" {