tiny.tripwire.module
Defined in failpoint.
Creates a failpoint module at compile time for the failpoint enum P and the error specification E: the namespace that holds one group of named check sites.
Source
Source: lib/tripwire/src/failpoint.zig:30
zig
/// Creates a failpoint module at compile time for the failpoint enum `P` and/// the error specification `E`: the namespace that holds one group of named/// check sites.////// - `P` is an enum whose fields name the check sites./// - `E` is one of four things: an error set type such as `anyerror` or/// `error{...}`, an error union type such as `E!T`, a function type whose/// return is an error union such as `fn (...) E!T`, or a function value that/// declares such a return. An error value such as `error.OutOfMemory` does/// not work as `E`, because the error set case hands `E` straight back and/// the result has to be a type.////// Every caller naming the same `P` and `E` shares one state map, which belongs/// to the returned type, so no instance of the returned type carries the state./// Nothing synchronizes the state across threads.pub fn module( comptime P: type, comptime E: anytype,) type { return struct { /// The enum type whose tags name the check sites of this failpoint /// module, named here so a caller can write out the type that other /// functions take. pub const FailPoint: type = P; /// The error set read out of the error specification at compile time, /// which `check` returns so a caller can match an enclosing function's /// error set against it. pub const Error: type = err: { const T = if (@TypeOf(E) == type) E else @TypeOf(E); break :err switch (@typeInfo(T)) { .error_set => E, .error_union => |info| info.error_set, .@"fn" => |info| @typeInfo(info.return_type.?).error_union.error_set, else => @compileError("E must be an error set or function type"), }; }; /// The compile-time flag that turns the checks on, true in a test build /// and false everywhere else. pub const enabled = builtin.is_test; comptime { assert(@typeInfo(FailPoint) == .@"enum"); assert(@typeInfo(Error) == .error_set); } var tripwires: TripwireMap = .{}; const TripwireMap: type = std.EnumMap(FailPoint, Tripwire); const Tripwire: type = TripwireType(Error); /// Evaluates the check site named by `point` inside an operation where /// a simulated error should arrive, so a test can drive the error path /// that a successful run leaves alone. /// /// - Where `enabled` is false, meaning `builtin.is_test == false`, the /// call is an inlined no-op that returns `void`. /// - In a test build, the call returns `void` when `point` has no /// configuration or while the visit count stands at or below the /// threshold. Once the visit count passes the threshold, the site is /// marked tripped and the configured error is returned. The error /// comes back on every later visit as well, as long as the visit /// count stays inside `usize` range. pub fn check(point: FailPoint) callconv(callingConvention()) Error!void { if (comptime !enabled) return; return checkConstrained(point, Error); } /// Evaluates the check site named by `point` and returns an error typed /// as `ConstrainedError`, letting the check sit inside a function whose /// declared error set is wider than the module's own. /// /// - Where `enabled` is false, the call is an inlined no-op that /// returns `void`. /// - In a test build, it follows the same visit count and threshold /// rules as `check`. /// - The typing requirement in a test build comes from the body: it /// runs `return tripwire.err;`, and that value has type `Error`. Zig /// coerces an error set only into a set that holds it, so /// `ConstrainedError` has to be `Error` or a superset of `Error`. pub fn checkConstrained( point: FailPoint, comptime ConstrainedError: type, ) callconv(callingConvention()) ConstrainedError!void { if (comptime !enabled) return; const tripwire = tripwires.getPtr(point) orelse return; tripwire.reached += 1; if (tripwire.reached <= tripwire.min) return; tripwire.tripped = true; return tripwire.err; } /// Provides the one-line setup for a test that wants the site to fail /// the first time an operation reaches it, configuring `point` to /// deliver `err` on its first visit, which is a threshold of 0. The /// call replaces whatever configuration `point` already had, putting /// the visit count back to 0 and the trip flag back to false. In a test /// build, later calls to `check(point)` follow the visit count rules /// written on `check`. pub fn errorAlways(point: FailPoint, err: Error) void { errorAfter(point, err, 0); } /// Lets earlier visits through when an operation reaches the same site /// more than once before reaching the state the test targets, for /// example while parsing earlier records or running earlier loop /// iterations. The function configures `point` to pass its first `min` /// visits and to deliver `err` on visit `min + 1` and on every visit /// after that. This registration replaces whatever configuration /// `point` already had, putting the visit count back to 0 and the trip /// flag back to false. In a test build, later calls to `check(point)` /// follow the visit count rules written on `check`. pub fn errorAfter(point: FailPoint, err: Error, min: usize) void { tripwires.put(point, .{ .err = err, .min = min }); } /// Settles whether a test reached its configured sites, because a /// passing test proves its error path only once the site is known to /// have been reached. The function verifies that every configured site /// in the failpoint module was visited past its threshold and tripped. /// /// - With no site configured, it succeeds at once. /// - With any configured site still untripped, it returns /// `error.UntrippedError`. /// - Under `.reset`, it clears every configured site, including on the /// run that returns the error. /// - Under `.retain`, it keeps the registrations and the counters, so /// the trip flags stay set and a later call passes with no further /// visits in between. /// /// The call proves that the configured error was delivered at the check /// site. Whether the caller caught the error, ran its cleanup, or held /// its domain invariants is left to the test's own assertions. pub fn end(reset_mode: enum { reset, retain }) error{UntrippedError}!void { var untripped = false; var iter = tripwires.iterator(); while (iter.next()) |entry| { if (!entry.value.tripped) { untripped = true; } } switch (reset_mode) { .reset => reset(), .retain => {}, } if (untripped) return error.UntrippedError; } /// Clears every failpoint registration and the counters behind them. A /// test calls it before it starts and again on the way out, because /// that state belongs to the type and outlives any one test. pub fn reset() void { tripwires = .{}; } fn callingConvention() std.builtin.CallingConvention { return if (!enabled) .@"inline" else .auto; } };}Source: lib/tripwire/src/root.zig:312
zig
/// Creates a failpoint module at compile time for a given failpoint enum and/// error specification.pub const module = failpoint.module;Audit
| Definitions | 1 |
|---|---|
| Public names | 2 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |