feature. See also
. The project being documented here (as the example) is the Zig library itself.
test_runner.fuzz
pub fn fuzz(
context: anytype,
comptime testOne: fn (context: @TypeOf(context), *std.testing.Smith) anyerror!void,
options: testing.FuzzInputOptions,
) anyerror!void
File
Code
pub fn fuzz(
context: anytype,
comptime testOne: fn (context: @TypeOf(context), *std.testing.Smith) anyerror!void,
options: testing.FuzzInputOptions,
) anyerror!void {
// coverage from being considered.
@disableInstrumentation();
// we still want CI test coverage enabled.
if (need_simple) return;
// contradict itself by making it not actually be a fuzz test when the test
// is built in fuzz mode.
is_fuzz_test = true;
if (log_err_count != 0) @panic("error logs detected");
// excluded from code coverage instrumentation. It needs a function pointer
// it can call for checking exactly one input. Inside this function we do
// our standard unit test checks such as memory leaks, and interaction with
// error logs.
const global = struct {
var ctx: @TypeOf(context) = undefined;
fn test_one() callconv(.c) bool {
@disableInstrumentation();
testing.allocator_instance = .init(std.heap.page_allocator, .{
.canary = 0xcacce5e0,
.check_write_after_free = true,
});
defer if (testing.allocator_instance.deinit() != 0) std.process.exit(1);
log_err_count = 0;
testOne(ctx, @constCast(&testing.Smith{ .in = null })) catch |err| switch (err) {
error.SkipZigTest => return true,
else => {
const stderr = std.debug.lockStderr(&.{}).terminal();
p: {
if (@errorReturnTrace()) |trace| {
std.debug.writeErrorReturnTrace(trace, stderr) catch break :p;
}
stderr.writer.print("failed with error.{t}\n", .{err}) catch break :p;
}
std.process.exit(1);
},
};
if (log_err_count != 0) {
const stderr = std.debug.lockStderr(&.{}).terminal();
stderr.writer.print("error logs detected\n", .{}) catch {};
std.process.exit(1);
}
return false;
}
};
if (builtin.fuzz) {
const prev_allocator_state = testing.allocator_instance;
defer testing.allocator_instance = prev_allocator_state;
global.ctx = context;
fuzz_abi.fuzzer_set_test(&global.test_one);
for (options.corpus) |elem|
fuzz_abi.fuzzer_new_input(.fromSlice(elem));
fuzz_abi.fuzzer_start_test();
return;
}
// provided corpus.
for (options.corpus) |input| {
var smith: testing.Smith = .{ .in = input };
try testOne(context, &smith);
}
// string as a smoke test.
var smith: testing.Smith = .{ .in = "" };
try testOne(context, &smith);
}