Skip to main content

tsoracle_failpoint/
lib.rs

1//
2//  ░▀█▀░█▀▀░█▀█░█▀▄░█▀█░█▀▀░█░░░█▀▀
3//  ░░█░░▀▀█░█░█░█▀▄░█▀█░█░░░█░░░█▀▀
4//  ░░▀░░▀▀▀░▀▀▀░▀░▀░▀░▀░▀▀▀░▀▀▀░▀▀▀
5//
6//  tsoracle — Distributed Timestamp Oracle
7//  https://www.tsoracle.rs
8//
9//  Copyright (c) 2026 Prisma Risk
10//
11//  Licensed under the Apache License, Version 2.0 (the "License");
12//  you may not use this file except in compliance with the License.
13//  You may obtain a copy of the License at
14//
15//      https://www.apache.org/licenses/LICENSE-2.0
16//
17//  Unless required by applicable law or agreed to in writing, software
18//  distributed under the License is distributed on an "AS IS" BASIS,
19//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20//  See the License for the specific language governing permissions and
21//  limitations under the License.
22//
23
24#![doc = include_str!("../README.md")]
25
26/// Re-export of the [`fail`] crate so the [`failpoint!`] expansion and any
27/// test arming the registry both reach fail-rs through this crate — consumers
28/// never name `fail` in their own dependency graph. Only present with the
29/// `failpoints` feature on.
30#[cfg(feature = "failpoints")]
31#[doc(hidden)]
32pub use fail;
33
34/// Synchronous failpoint injection site.
35///
36/// With the `failpoints` feature on, forwards to [`fail::fail_point!`] so a
37/// test can arm a `panic`, an error `return`, a `pause`, or a `sleep` at the
38/// named site. With it off, both forms expand to `()` — zero code, and `fail`
39/// is not linked. The expansion routes through `$crate::fail`, so consumers
40/// only need a dependency on this crate (with the feature forwarded), never on
41/// `fail` itself.
42///
43/// The single-argument form supports `panic`, `pause`, `sleep(ms)`, and
44/// `print`. The closure form additionally supports `return` / `return(string)`
45/// and must yield the enclosing function's exact return type — see
46/// `docs/failpoint-testing.md`.
47#[cfg(feature = "failpoints")]
48#[macro_export]
49macro_rules! failpoint {
50    ($name:expr) => {
51        $crate::fail::fail_point!($name)
52    };
53    ($name:expr, $closure:expr) => {
54        $crate::fail::fail_point!($name, $closure)
55    };
56}
57
58#[cfg(not(feature = "failpoints"))]
59#[macro_export]
60macro_rules! failpoint {
61    ($name:expr) => {
62        ()
63    };
64    ($name:expr, $closure:expr) => {
65        ()
66    };
67}
68
69#[cfg(test)]
70mod tests {
71    #[cfg(feature = "failpoints")]
72    #[test]
73    fn failpoint_is_reachable() {
74        // When the feature is enabled, the macro expands to a `fail`
75        // registry call site. The closure form needs a Result-returning
76        // context to compile (it can early-return) and is exercised in the
77        // consumers' `tests/failpoints.rs` under real storage code paths.
78        crate::failpoint!("test::point");
79    }
80
81    #[cfg(not(feature = "failpoints"))]
82    #[test]
83    fn failpoint_is_a_noop() {
84        // When the feature is disabled, the macro must compile to nothing
85        // measurable. Simply invoking it must not panic.
86        crate::failpoint!("test::point");
87    }
88}