std.Io: add unit tests for Group and concurrent

This commit is contained in:
Andrew Kelley 2025-10-28 18:04:55 -07:00
parent 03fd132b1c
commit c40204a3e5
3 changed files with 97 additions and 1 deletions

View file

@ -6114,3 +6114,7 @@ fn initializeWsa(t: *Threaded) error{NetworkDown}!void {
}
return error.NetworkDown;
}
test {
_ = @import("Threaded/test.zig");
}

View file

@ -0,0 +1,46 @@
const std = @import("std");
const Io = std.Io;
const testing = std.testing;
const assert = std.debug.assert;
test "concurrent vs main prevents deadlock via oversubscription" {
var threaded: Io.Threaded = .init(std.testing.allocator);
defer threaded.deinit();
const io = threaded.io();
threaded.cpu_count = 1;
var queue: Io.Queue(u8) = .init(&.{});
var putter = try io.concurrent(put, .{ io, &queue });
defer putter.cancel(io);
try testing.expectEqual(42, queue.getOneUncancelable(io));
}
fn put(io: Io, queue: *Io.Queue(u8)) void {
queue.putOneUncancelable(io, 42);
}
fn get(io: Io, queue: *Io.Queue(u8)) void {
assert(queue.getOneUncancelable(io) == 42);
}
test "concurrent vs concurrent prevents deadlock via oversubscription" {
var threaded: Io.Threaded = .init(std.testing.allocator);
defer threaded.deinit();
const io = threaded.io();
threaded.cpu_count = 1;
var queue: Io.Queue(u8) = .init(&.{});
var putter = try io.concurrent(put, .{ io, &queue });
defer putter.cancel(io);
var getter = try io.concurrent(get, .{ io, &queue });
defer getter.cancel(io);
getter.await(io);
putter.await(io);
}

View file

@ -1,4 +1,8 @@
const builtin = @import("builtin");
const native_endian = builtin.cpu.arch.endian();
const std = @import("std");
const Io = std.Io;
const DefaultPrng = std.Random.DefaultPrng;
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
@ -6,7 +10,6 @@ const expectError = std.testing.expectError;
const mem = std.mem;
const fs = std.fs;
const File = std.fs.File;
const native_endian = @import("builtin").target.cpu.arch.endian();
const tmpDir = std.testing.tmpDir;
@ -123,3 +126,46 @@ test "updateTimes" {
try expect(stat_new.atime.nanoseconds < stat_old.atime.nanoseconds);
try expect(stat_new.mtime.nanoseconds < stat_old.mtime.nanoseconds);
}
test "Group" {
const io = std.testing.io;
var group: Io.Group = .init;
var results: [2]usize = undefined;
group.async(io, count, .{ 1, 10, &results[0] });
group.async(io, count, .{ 20, 30, &results[1] });
group.wait(io);
try std.testing.expectEqualSlices(usize, &.{ 45, 245 }, &results);
}
fn count(a: usize, b: usize, result: *usize) void {
var sum: usize = 0;
for (a..b) |i| {
sum += i;
}
result.* = sum;
}
test "Group cancellation" {
const io = std.testing.io;
var group: Io.Group = .init;
var results: [2]usize = undefined;
group.async(io, sleep, .{ io, &results[0] });
group.async(io, sleep, .{ io, &results[1] });
group.cancel(io);
try std.testing.expectEqualSlices(usize, &.{ 1, 1 }, &results);
}
fn sleep(io: Io, result: *usize) void {
// TODO when cancellation race bug is fixed, make this timeout much longer so that
// it causes the unit test to be failed if not cancelled.
io.sleep(.fromMilliseconds(1), .awake) catch {};
result.* = 1;
}