std: Add more tests, fix broken code

It turns out that nothing in the test suite was exercising
preadv/pwritev and so the previous commits silently broke them.

Adding tests revealed readvAll and preadvAll were also broken and not
covered by any test.
This commit is contained in:
LemonBoy 2021-05-07 15:24:37 +02:00
parent 31f1cc9a0d
commit c065e12dbe
3 changed files with 90 additions and 5 deletions

View File

@ -482,7 +482,7 @@ pub const File = struct {
/// order to handle partial reads from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
pub fn readvAll(self: File, iovecs: []os.iovec) ReadError!usize {
if (iovecs.len == 0) return;
if (iovecs.len == 0) return 0;
var i: usize = 0;
var off: usize = 0;
@ -524,8 +524,8 @@ pub const File = struct {
/// The `iovecs` parameter is mutable because this function needs to mutate the fields in
/// order to handle partial reads from the underlying OS layer.
/// See https://github.com/ziglang/zig/issues/7699
pub fn preadvAll(self: File, iovecs: []const os.iovec, offset: u64) PReadError!void {
if (iovecs.len == 0) return;
pub fn preadvAll(self: File, iovecs: []os.iovec, offset: u64) PReadError!usize {
if (iovecs.len == 0) return 0;
var i: usize = 0;
var off: usize = 0;

View File

@ -520,6 +520,89 @@ test "makePath, put some files in it, deleteTree" {
}
}
test "writev, readv" {
var tmp = tmpDir(.{});
defer tmp.cleanup();
const line1 = "line1\n";
const line2 = "line2\n";
var buf1: [line1.len]u8 = undefined;
var buf2: [line2.len]u8 = undefined;
var write_vecs = [_]std.os.iovec_const{
.{
.iov_base = line1,
.iov_len = line1.len,
},
.{
.iov_base = line2,
.iov_len = line2.len,
},
};
var read_vecs = [_]std.os.iovec{
.{
.iov_base = &buf2,
.iov_len = buf2.len,
},
.{
.iov_base = &buf1,
.iov_len = buf1.len,
},
};
var src_file = try tmp.dir.createFile("test.txt", .{ .read = true });
defer src_file.close();
try src_file.writevAll(&write_vecs);
try testing.expectEqual(@as(u64, line1.len + line2.len), try src_file.getEndPos());
try src_file.seekTo(0);
const read = try src_file.readvAll(&read_vecs);
try testing.expectEqual(@as(usize, line1.len + line2.len), read);
try testing.expectEqualStrings(&buf1, "line2\n");
try testing.expectEqualStrings(&buf2, "line1\n");
}
test "pwritev, preadv" {
var tmp = tmpDir(.{});
defer tmp.cleanup();
const line1 = "line1\n";
const line2 = "line2\n";
var buf1: [line1.len]u8 = undefined;
var buf2: [line2.len]u8 = undefined;
var write_vecs = [_]std.os.iovec_const{
.{
.iov_base = line1,
.iov_len = line1.len,
},
.{
.iov_base = line2,
.iov_len = line2.len,
},
};
var read_vecs = [_]std.os.iovec{
.{
.iov_base = &buf2,
.iov_len = buf2.len,
},
.{
.iov_base = &buf1,
.iov_len = buf1.len,
},
};
var src_file = try tmp.dir.createFile("test.txt", .{ .read = true });
defer src_file.close();
try src_file.pwritevAll(&write_vecs, 16);
try testing.expectEqual(@as(u64, 16 + line1.len + line2.len), try src_file.getEndPos());
const read = try src_file.preadvAll(&read_vecs, 16);
try testing.expectEqual(@as(usize, line1.len + line2.len), read);
try testing.expectEqualStrings(&buf1, "line2\n");
try testing.expectEqualStrings(&buf2, "line1\n");
}
test "access file" {
if (builtin.os.tag == .wasi) return error.SkipZigTest;

View File

@ -646,8 +646,9 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
else
system.preadv;
const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned
while (true) {
const rc = preadv_sym(fd, iov.ptr, iov_count, offset);
const rc = preadv_sym(fd, iov.ptr, iov_count, ioffset);
switch (errno(rc)) {
0 => return @bitCast(usize, rc),
EINTR => continue,
@ -998,8 +999,9 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz
system.pwritev;
const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31);
const ioffset = @bitCast(i64, offset); // the OS treats this as unsigned
while (true) {
const rc = pwritev_sym(fd, iov.ptr, iov_count, offset);
const rc = pwritev_sym(fd, iov.ptr, iov_count, ioffset);
switch (errno(rc)) {
0 => return @intCast(usize, rc),
EINTR => continue,