feature. See also
. The project being documented here (as the example) is the Zig library itself.
ArenaAllocator.fuzzMultiThreaded
fn fuzzMultiThreaded(fuzz_init: FuzzContext.Init, smith: *std.testing.Smith) anyerror!void
File
Code
fn fuzzMultiThreaded(fuzz_init: FuzzContext.Init, smith: *std.testing.Smith) anyerror!void {
@disableInstrumentation();
const testing = std.testing;
const io = fuzz_init.threaded_instance.io();
fuzz_init.sample_instance.prepareFailures(smith);
const control_allocator = fuzz_init.control_instance.threadSafeAllocator();
const sample_child_allocator = fuzz_init.sample_instance.allocator();
var arena_instance = fuzz_init.arena_state.*.promote(sample_child_allocator);
defer fuzz_init.arena_state.* = arena_instance.state;
var ctx: FuzzContext = .init(
control_allocator,
arena_instance.allocator(),
);
defer ctx.deinit();
var group: std.Io.Group = .init;
defer group.cancel(io);
var n_allocs: usize = 0;
var n_actions: usize = 0;
while (!smith.eosWeightedSimple(99, 1) and n_actions < FuzzContext.max_action_count) {
errdefer comptime unreachable;
const weights: []const testing.Smith.Weight = if (n_allocs == FuzzContext.max_alloc_count)
&.{
.value(FuzzContext.Action, .resize, 1),
.value(FuzzContext.Action, .remap, 1),
.value(FuzzContext.Action, .free, 1),
}
else
&.{
.value(FuzzContext.Action, .resize, 1),
.value(FuzzContext.Action, .remap, 1),
.value(FuzzContext.Action, .free, 1),
.value(FuzzContext.Action, .alloc, 3),
};
switch (smith.valueWeighted(FuzzContext.Action, weights)) {
.alloc => {
const alloc_index = n_allocs;
n_allocs += 1;
ctx.allocs[alloc_index].common.len = .free;
group.concurrent(io, FuzzContext.doOneAlloc, .{
&ctx,
nextLen(smith),
smith.valueRangeAtMost(
Alignment,
.@"1",
.fromByteUnits(2 * std.heap.page_size_max),
),
@fromBackingInt(@intCast(alloc_index)),
}) catch unreachable;
},
.resize => group.concurrent(io, FuzzContext.doOneResize, .{ &ctx, nextLen(smith) }) catch unreachable,
.remap => group.concurrent(io, FuzzContext.doOneRemap, .{ &ctx, nextLen(smith) }) catch unreachable,
.free => group.concurrent(io, FuzzContext.doOneFree, .{&ctx}) catch unreachable,
}
n_actions += 1;
}
try group.await(io);
try ctx.check(n_allocs);
const old_capacity = arena_instance.queryCapacity();
const reset_mode: ResetMode = switch (smith.value(@typeInfo(ResetMode).@"union".tag_type.?)) {
.free_all => .free_all,
.retain_capacity => .retain_capacity,
.retain_with_limit => .{ .retain_with_limit = smith.value(usize) },
};
const ok = arena_instance.reset(reset_mode);
const new_capacity = arena_instance.queryCapacity();
switch (reset_mode) {
.free_all => {
try testing.expect(ok);
try testing.expectEqual(0, new_capacity);
fuzz_init.sample_instance.reset();
},
.retain_with_limit => |limit| if (ok) try testing.expect(new_capacity <= limit),
.retain_capacity => if (ok) try testing.expectEqual(old_capacity, new_capacity),
}
fuzz_init.control_instance.reset();
}