| 1 | const std = @import("std"); |
| 2 | const assert = std.debug.assert; |
| 3 | const abi = std.Build.abi.fuzz; |
| 4 | const native_endian = @import("builtin").cpu.arch.endian(); |
| 5 | |
| 6 | fn testOne() callconv(.c) bool { |
| 7 | return false; |
| 8 | } |
| 9 | |
| 10 | export fn runner_test_run(i: u32) void { |
| 11 | assert(i == 0); |
| 12 | abi.fuzzer_set_test(testOne); |
| 13 | abi.fuzzer_new_input(.fromSlice("")); |
| 14 | abi.fuzzer_new_input(.fromSlice("hello")); |
| 15 | abi.fuzzer_start_test(); |
| 16 | } |
| 17 | |
| 18 | export fn runner_test_name(i: u32) abi.Slice { |
| 19 | assert(i == 0); |
| 20 | return .fromSlice("test"); |
| 21 | } |
| 22 | |
| 23 | export fn runner_start_input_poller() void {} |
| 24 | export fn runner_stop_input_poller() void {} |
| 25 | |
| 26 | export fn runner_futex_wait(ptr: *const u32, expected: u32) bool { |
| 27 | assert(ptr.* == expected); // single-threaded |
| 28 | return false; |
| 29 | } |
| 30 | |
| 31 | export fn runner_futex_wake(ptr: *const u32, waiters: u32) void { |
| 32 | _ = ptr; |
| 33 | _ = waiters; |
| 34 | } |
| 35 | |
| 36 | export fn runner_broadcast_input(test_i: u32, bytes: abi.Slice) void { |
| 37 | _ = test_i; |
| 38 | _ = bytes; |
| 39 | } |
| 40 | |
| 41 | pub fn main(init: std.process.Init) !void { |
| 42 | const gpa = init.gpa; |
| 43 | const io = init.io; |
| 44 | |
| 45 | var args = try init.minimal.args.iterateAllocator(gpa); |
| 46 | defer args.deinit(); |
| 47 | _ = args.skip(); // executable name |
| 48 | |
| 49 | const cache_dir_path = args.next() orelse @panic("expected cache directory path argument"); |
| 50 | var cache_dir = try std.Io.Dir.cwd().openDir(io, cache_dir_path, .{}); |
| 51 | defer cache_dir.close(io); |
| 52 | |
| 53 | abi.fuzzer_init(.fromSlice(cache_dir_path)); |
| 54 | abi.fuzzer_main(1, 0, .iterations, 100); |
| 55 | |
| 56 | const pc_digest = abi.fuzzer_coverage().id; |
| 57 | const coverage_file_path = "v/" ++ std.fmt.hex(pc_digest); |
| 58 | const coverage_file = try cache_dir.openFile(io, coverage_file_path, .{}); |
| 59 | defer coverage_file.close(io); |
| 60 | |
| 61 | var read_buf: [@sizeOf(abi.SeenPcsHeader)]u8 = undefined; |
| 62 | var r = coverage_file.reader(io, &read_buf); |
| 63 | const pcs_header = r.interface.takeStruct(abi.SeenPcsHeader, native_endian) catch return r.err.?; |
| 64 | |
| 65 | if (pcs_header.pcs_len == 0) |
| 66 | return error.ZeroPcs; |
| 67 | const expected_len = @sizeOf(abi.SeenPcsHeader) + |
| 68 | try std.math.divCeil(usize, pcs_header.pcs_len, @bitSizeOf(usize)) * @sizeOf(usize) + |
| 69 | pcs_header.pcs_len * @sizeOf(usize); |
| 70 | if (try coverage_file.length(io) != expected_len) |
| 71 | return error.WrongEnd; |
| 72 | } |