Skip to main content

test_r/
lib.rs

1pub use test_r_macro::add_test;
2pub use test_r_macro::always_capture;
3pub use test_r_macro::always_ensure_time;
4pub use test_r_macro::always_report_time;
5pub use test_r_macro::bench;
6pub use test_r_macro::define_matrix_dimension;
7pub use test_r_macro::flaky;
8pub use test_r_macro::hosted_rpc;
9pub use test_r_macro::ignore_detached_panics;
10pub use test_r_macro::inherit_test_dep;
11pub use test_r_macro::never_capture;
12pub use test_r_macro::never_ensure_time;
13pub use test_r_macro::never_report_time;
14pub use test_r_macro::non_flaky;
15pub use test_r_macro::sequential;
16pub use test_r_macro::sequential_suite;
17pub use test_r_macro::tag;
18pub use test_r_macro::tag_suite;
19pub use test_r_macro::test;
20pub use test_r_macro::test_dep;
21pub use test_r_macro::test_gen;
22pub use test_r_macro::timeout;
23pub use test_r_macro::timeout_suite;
24pub use test_r_macro::uses_test_r as enable;
25
26#[cfg(feature = "tokio")]
27pub use test_r_core::bench::AsyncBencher;
28pub use test_r_core::bench::Bencher;
29#[cfg(feature = "tokio")]
30pub use test_r_core::spawn::spawn;
31pub use test_r_core::spawn::spawn_thread;
32
33pub use test_r_core::internal::{
34    AsyncHostedDep, AsyncHostedRpcDep, CloneableDep, HostedDep, HostedRpcDep,
35};
36pub use test_r_core::worker_index;
37
38pub mod core {
39    use std::time::Duration;
40    pub use test_r_core::internal::{
41        AsyncHostedDep, AsyncHostedRpcDep, AsyncHostedRpcDispatcher, CaptureControl,
42        CloneableCodec, CloneableDep, DepScope, DependencyConstructor, DependencyView,
43        DetachedPanicPolicy, DynamicTestRegistration, FailureCause, FlakinessControl,
44        GeneratedTest, HostedBothShared, HostedDep, HostedRpcChannel, HostedRpcDep,
45        HostedRpcDispatcher, HostedRpcError, HostedRpcOwnerCell, HostedRpcTransport,
46        InProcessHostedRpcTransport, ReportTimeControl, RpcFactory, ShouldPanic, TestFunction,
47        TestGeneratorFunction, TestProperties, TestReturnValue, TestType, WorkerReconstructor,
48    };
49    pub use test_r_core::*;
50
51    #[allow(clippy::too_many_arguments)]
52    pub fn register_test(
53        name: &str,
54        module_path: &str,
55        is_ignored: bool,
56        should_panic: ShouldPanic,
57        test_type: TestType,
58        timeout: Option<Duration>,
59        flakiness_control: FlakinessControl,
60        capture_control: CaptureControl,
61        tags: Vec<String>,
62        report_time_control: ReportTimeControl,
63        ensure_time_control: ReportTimeControl,
64        detached_panic_policy: DetachedPanicPolicy,
65        run: TestFunction,
66        dependencies: Option<Vec<String>>,
67    ) {
68        let (crate_name, module_path) = split_module_path(module_path);
69
70        internal::REGISTERED_TESTS
71            .lock()
72            .unwrap()
73            .push(internal::RegisteredTest {
74                name: name.to_string(),
75                crate_name,
76                module_path,
77                run,
78                props: internal::TestProperties {
79                    should_panic,
80                    test_type,
81                    timeout,
82                    flakiness_control,
83                    capture_control,
84                    report_time_control,
85                    ensure_time_control,
86                    tags,
87                    is_ignored,
88                    detached_panic_policy,
89                },
90                dependencies,
91            });
92    }
93
94    pub fn register_dependency_constructor(
95        name: &str,
96        module_path: &str,
97        cons: DependencyConstructor,
98        dependencies: Vec<String>,
99    ) {
100        register_dependency_constructor_with_scope(
101            name,
102            module_path,
103            cons,
104            dependencies,
105            DepScope::Shared,
106            None,
107            None,
108            None,
109            None,
110        )
111    }
112
113    #[allow(clippy::too_many_arguments)]
114    pub fn register_dependency_constructor_with_scope(
115        name: &str,
116        module_path: &str,
117        cons: DependencyConstructor,
118        dependencies: Vec<String>,
119        scope: DepScope,
120        worker_fn: Option<WorkerReconstructor>,
121        cloneable_codec: Option<CloneableCodec>,
122        hosted_codec: Option<CloneableCodec>,
123        rpc_factory: Option<RpcFactory>,
124    ) {
125        register_dependency_constructor_with_scope_and_companions(
126            name,
127            module_path,
128            cons,
129            dependencies,
130            scope,
131            worker_fn,
132            cloneable_codec,
133            hosted_codec,
134            rpc_factory,
135            Vec::new(),
136        )
137    }
138
139    /// Registers a dependency constructor that must be retained
140    /// together with the listed `companions` during pruning. See
141    /// [`internal::RegisteredDependency::companions`] for the planner
142    /// semantics. All other parameters behave exactly as
143    /// [`register_dependency_constructor_with_scope`].
144    #[allow(clippy::too_many_arguments)]
145    pub fn register_dependency_constructor_with_scope_and_companions(
146        name: &str,
147        module_path: &str,
148        cons: DependencyConstructor,
149        dependencies: Vec<String>,
150        scope: DepScope,
151        worker_fn: Option<WorkerReconstructor>,
152        cloneable_codec: Option<CloneableCodec>,
153        hosted_codec: Option<CloneableCodec>,
154        rpc_factory: Option<RpcFactory>,
155        companions: Vec<String>,
156    ) {
157        let (crate_name, module_path) = split_module_path(module_path);
158
159        internal::REGISTERED_DEPENDENCY_CONSTRUCTORS
160            .lock()
161            .unwrap()
162            .push(internal::RegisteredDependency {
163                name: name.to_string(),
164                crate_name,
165                module_path,
166                constructor: cons,
167                dependencies,
168                scope,
169                worker_fn,
170                cloneable_codec,
171                hosted_codec,
172                rpc_factory,
173                companions,
174            });
175    }
176
177    pub fn register_suite_sequential(name: &str, module_path: &str) {
178        let (crate_name, module_path) = split_module_path(module_path);
179
180        internal::REGISTERED_TESTSUITE_PROPS.lock().unwrap().push(
181            internal::RegisteredTestSuiteProperty::Sequential {
182                name: name.to_string(),
183                crate_name,
184                module_path,
185            },
186        );
187    }
188
189    pub fn register_suite_timeout(name: &str, module_path: &str, timeout: Duration) {
190        let (crate_name, module_path) = split_module_path(module_path);
191
192        internal::REGISTERED_TESTSUITE_PROPS.lock().unwrap().push(
193            internal::RegisteredTestSuiteProperty::Timeout {
194                name: name.to_string(),
195                crate_name,
196                module_path,
197                timeout,
198            },
199        );
200    }
201
202    pub fn register_suite_tag(name: &str, module_path: &str, tag: String) {
203        let (crate_name, module_path) = split_module_path(module_path);
204
205        internal::REGISTERED_TESTSUITE_PROPS.lock().unwrap().push(
206            internal::RegisteredTestSuiteProperty::Tag {
207                name: name.to_string(),
208                crate_name,
209                module_path,
210                tag,
211            },
212        );
213    }
214
215    pub fn register_test_generator(
216        name: &str,
217        module_path: &str,
218        is_ignored: bool,
219        run: TestGeneratorFunction,
220    ) {
221        let (crate_name, module_path) = split_module_path(module_path);
222
223        internal::REGISTERED_TEST_GENERATORS.lock().unwrap().push(
224            internal::RegisteredTestGenerator {
225                name: name.to_string(),
226                crate_name,
227                module_path,
228                run,
229                is_ignored,
230            },
231        );
232    }
233
234    fn split_module_path(module_path: &str) -> (String, String) {
235        let (crate_name, module_path) =
236            if let Some((crate_name, module_path)) = module_path.split_once("::") {
237                (crate_name.to_string(), module_path.to_string())
238            } else {
239                (module_path.to_string(), String::new())
240            };
241        (crate_name, module_path)
242    }
243}
244
245pub use ::ctor;
246
247/// **Hidden macro-support helper.** Runtime-flavor selector for code
248/// emitted by `#[test_r::test_dep]` (specifically the
249/// `worker = both(Trait)` lowering) that needs to pick a different
250/// expression depending on whether the `test-r` crate was compiled
251/// with its `tokio` feature.
252///
253/// The proc macro itself cannot read the user crate's cargo features,
254/// so we route the runtime-flavor choice through this `macro_rules!`
255/// definition in `test-r`. Because `#[cfg(feature = "tokio")]` on a
256/// `macro_rules!` evaluates at the *defining* crate's compile time,
257/// the variant of the macro that gets exported reflects whether
258/// `test-r/tokio` was enabled — exactly the same toggle that decides
259/// which `test-r-core` helper variants are linked.
260///
261/// The expected invocation shape is:
262///
263/// ```ignore
264/// test_r::__test_r_select_runtime! {
265///     sync { /* tokens used when the sync runtime is active */ }
266///     tokio { /* tokens used when the tokio runtime is active */ }
267/// }
268/// ```
269///
270/// Each branch is a brace-delimited token group; the macro expands to
271/// the contents of the matching branch with no extra braces.
272#[cfg(feature = "tokio")]
273#[doc(hidden)]
274#[macro_export]
275macro_rules! __test_r_select_runtime {
276    ( sync { $($_sync:tt)* } tokio { $($tokio:tt)* } ) => {
277        $($tokio)*
278    };
279}
280
281/// Sync-runtime variant of [`__test_r_select_runtime`]; see that
282/// macro's doc-comment.
283#[cfg(not(feature = "tokio"))]
284#[doc(hidden)]
285#[macro_export]
286macro_rules! __test_r_select_runtime {
287    ( sync { $($sync:tt)* } tokio { $($_tokio:tt)* } ) => {
288        $($sync)*
289    };
290}