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}