Artifact 58aeaddb3b1748889cea1e68129b7a57636737bfa27555cd0d2126a5d86ac9fd:
- File
src/fuzz_tests.zig
— part of check-in
[efaf2d3ae1]
at
2026-07-18 08:21:09
on branch storage
— feat(ยง6): pack re-deltification with chronological+wire-delta rebasing and monotonic-shrink guard
fossil-scm-clone: zit=110083984B fossil=72245248B ratio=1.5238 (packed store, exact accounting header64+zlib+delta+config==110083984: zlib 8377 frames / 84,763,872 B 77.0% avg 10118 B; delta 59122 frames / 25,319,960 B 23.0% avg 428 B; config 1 frame / 88 B; raw 0. Artifact-type: checkin/manifest 20848 / 23,816,728 B 21.6%, other 6929 / 4,706,432 B 4.3%, file-blob 39722 / 81,560,672 B 74.1%. As-cloned baseline was 117,528,088 B zlib 9647/92,073,728; delta 57852/25,454,120; ratio 1.6268.)
sqlite: zit=175246544B fossil=147709952B ratio=1.1864 (packed store, exact accounting header64+zlib+delta+config==175246544: zlib 9260 frames / 113,048,584 B 64.5% avg 12208 B; delta 121734 frames / 62,197,808 B 35.5% avg 510 B; config 1 frame / 88 B; raw 0. Artifact-type: checkin/manifest 36515 / 65,427,440 B 37.3%, other 4775 / 5,462,856 B 3.1%, file-blob 89704 / 104,356,096 B 59.5%. As-cloned baseline was 207,344,544 B zlib 10847/140,422,768; delta 120147/66,921,536; ratio 1.4037.)
vs baseline:
fossil-scm-clone: zit=117528088B fossil=72245248B ratio=1.627 (raw=0B/0f; zlib=92073728B/9647f 78.3%; delta=25454120B/57852f 21.7%; config=176B/2f. Header+padding overhead 3711845B 3.2%. Artifact-type: checkin/manifest 26721968B/20848, other 4835264B/6929, file-blob 85970616B/39722. Accounting exact.)
sqlite: zit=207344544B fossil=147709952B ratio=1.404 (raw=0B/0f; zlib=140422768B/10847f 67.7%; delta=66921536B/120147f 32.3%; config=176B/2f. Header+padding overhead 7212808B 3.5%. Artifact-type: checkin/manifest 81006048B/36515, other 5531960B/4775, file-blob 120806296B/89704. Accounting exact.) (user: dmestas, size: 5375) [annotate] [blame] [check-ins using]
//! Seeded fuzz-target runner. //! //! `zig build fuzz -- <target> [--seed N] [--rounds N]` //! //! One binary; targets are named-tuple fields dispatched through //! `std.meta.FieldEnum`, so a module registers a new target by adding one //! field to `targets` below. The seed is explicit (`--seed`, decimal or //! `0x`-prefixed) or drawn from the process's csprng; either way it is //! always printed as `reproduce with seed=0x...` before the target runs, so //! a failure replays exactly. `--rounds` bounds the run explicitly (default //! 10_000); an out-of-band runner sweeps higher counts. const std = @import("std"); const delta_fuzz = @import("delta_fuzz.zig"); const artifact_fuzz = @import("artifact_fuzz.zig"); const sync_fuzz = @import("sync_fuzz.zig"); const logstore_fuzz = @import("logstore_fuzz.zig"); /// One field per fuzz target: `pub fn(allocator, seed: u64, rounds: usize) !void`. /// The field name is the argv target name. const targets = .{ .delta_apply_garbage = delta_fuzz.applyGarbage, .delta_round_trip = delta_fuzz.roundTrip, .delta_decode_int_bounded = delta_fuzz.decodeIntBounded, .delta_target_size_garbage = delta_fuzz.targetSizeGarbage, .delta_create_large_sizes = delta_fuzz.createLargeSizes, .artifact_parse_garbage = artifact_fuzz.parseGarbage, .artifact_parse_structured = artifact_fuzz.parseStructured, .artifact_card_line = artifact_fuzz.cardLine, .artifact_escapes = artifact_fuzz.escapes, .artifact_timestamp = artifact_fuzz.timestamp, .artifact_framing = artifact_fuzz.framing, .artifact_predicates = artifact_fuzz.predicates, .artifact_create_round_trip = artifact_fuzz.createRoundTrip, .sync_container_round_trip = sync_fuzz.containerRoundTrip, .sync_signal_cookie_round_trip = sync_fuzz.signalCookieRoundTrip, .sync_parsers_adversarial = sync_fuzz.parsersAdversarial, .sync_consume_reply_adversarial = sync_fuzz.consumeReplyAdversarial, .logstore_open_garbage = logstore_fuzz.openGarbage, .logstore_zlib_round_trip = logstore_fuzz.zlibRoundTrip, .logstore_delta_round_trip = logstore_fuzz.deltaRoundTrip, .logstore_pick_base_round_trip = logstore_fuzz.pickBaseRoundTrip, .logstore_pack_round_trip = logstore_fuzz.packRoundTrip, .logstore_parse_config = logstore_fuzz.parseConfig, }; const Target = std.meta.FieldEnum(@TypeOf(targets)); const default_rounds: usize = 10_000; /// Most targets do microsecond-scale work per round and run at `default_rounds`. /// `logstore_pack_round_trip` is ~100x heavier: it builds AND repacks a full /// mixed-frame store every round (dozens of deflate/inflate cycles plus the /// best-of-N `pickBase` search over the whole store), so `default_rounds` runs a /// single seed past the 10-minute execution cap. It gets a reduced default sized /// to finish a seed with margin under that cap while still covering thousands of /// distinct stores; an explicit `--rounds` still sweeps higher out of band. const pack_round_trip_default_rounds: usize = 2_000; /// The per-target default round count applied when `--rounds` is absent. fn defaultRoundsFor(target: Target) usize { return switch (target) { .logstore_pack_round_trip => pack_round_trip_default_rounds, else => default_rounds, }; } pub fn main(init: std.process.Init) !void { const gpa = init.gpa; const args = try init.minimal.args.toSlice(init.arena.allocator()); var stderr_buffer: [1024]u8 = undefined; var stderr_writer: std.Io.File.Writer = .init(.stderr(), init.io, &stderr_buffer); const err = &stderr_writer.interface; if (args.len < 2) { try usage(err); try err.flush(); std.process.exit(2); } const target = std.meta.stringToEnum(Target, args[1]) orelse { try err.print("fuzz: unknown target '{s}'\n\n", .{args[1]}); try usage(err); try err.flush(); std.process.exit(2); }; var seed: u64 = undefined; init.io.random(std.mem.asBytes(&seed)); var rounds: usize = defaultRoundsFor(target); try parseFlags(args[2..], &seed, &rounds); try err.print("reproduce with seed=0x{x}\n", .{seed}); try err.flush(); switch (target) { inline else => |tag| try @field(targets, @tagName(tag))(gpa, seed, rounds), } } /// Parse `[--seed N] [--rounds N]` in any order, overwriting the defaults /// already in `seed`/`rounds`. Each flag consumes exactly one value; an /// unknown flag or a missing value is an explicit error, never ignored. fn parseFlags(args: []const []const u8, seed: *u64, rounds: *usize) !void { var i: usize = 0; while (i < args.len) : (i += 1) { if (std.mem.eql(u8, args[i], "--seed")) { i += 1; if (i >= args.len) return error.MissingSeedValue; seed.* = try std.fmt.parseInt(u64, args[i], 0); } else if (std.mem.eql(u8, args[i], "--rounds")) { i += 1; if (i >= args.len) return error.MissingRoundsValue; rounds.* = try std.fmt.parseInt(usize, args[i], 0); } else { return error.UnknownArgument; } } } fn usage(w: *std.Io.Writer) !void { try w.writeAll("usage: zig build fuzz -- <target> [--seed N] [--rounds N]\n\ntargets:\n"); inline for (@typeInfo(Target).@"enum".fields) |f| { try w.print(" {s}\n", .{f.name}); } }