etest/
lib.rs

1#![allow(clippy::redundant_field_names)]
2
3//! Controls execution of `#[test]`
4//!
5//! Crate supports
6//!
7//! - [skipping](#conditional-execution) of tests based on dynamic conditions
8//!
9//! - [serial execution](#limiting-parallel-execution) of tests
10//!
11//! - [scheduling timeouts](#timeout) of tests
12//!
13//! See [etest-tests](../../etest_tests/) crate for more examples.
14//!
15//! ## Conditional execution
16//!
17//! Related attributes:
18//!
19//! - `skip`: an expression which when evaluates to true will skip the test.
20//!   This expression is executed at the runtime of the test
21//!
22//! - `skip_result`: allows to explicitly state the return value of the
23//!   function when it is skipped.  It should not be needed in most cases;
24//!   when not given the return type of the test function must implement
25//!   [`DefaultReturn`]
26//!
27//! ### Examples
28//!
29//! ```
30//! # use etest::etest;
31//! fn is_arch_arm() -> bool {
32//!     /* ... */
33//! # false
34//! }
35//!
36//! #[etest(skip=!is_arch_arm(), skip_result=42.into())]
37//! fn test_arm() -> ExitCode {
38//!     /* ... */
39//! # 0
40//! }
41//! ```
42//!
43//! ```
44//! # use etest::etest;
45//! #[etest(skip=true, skip_result=Err(()))]
46//! fn test() -> Result<(), ()> {
47//!     Ok(())
48//! }
49//! ```
50//!
51//! ### Limitations
52//!
53//! `etest` still uses the default `#[test]` harnish which does not support
54//! skipping of tests.  Hence there is no special indication that a test is
55//! skipped: it will be reported as "ok" or (when `skip_result` forces it) to
56//! "failed".
57//!
58//! Only the test output (`--show-output`) will tell the reason
59//!
60//! ```text
61//! ---- test::test0 stdout ----
62//! src/test.rs:26:1 (test::test0): SKIPPED
63//! ```
64//!
65//! ## Limiting parallel execution
66//!
67//! Parallel execution of tests can be prevented by consuming resources for
68//! the runtime of the test.  A "resource" can be specified by something which
69//! implements [`Into<ResourceId>`](ResourceId).
70//!
71//! Related attributes:
72//!
73//! - `uses`: a list of resources which are used; multiple tests can "use" the
74//!   same resource at the same time.  It can be compared to a shared lock.
75//!
76//! - `consumes`: a list of resources which are consumed by the test; only a
77//!   single test can own such a resource and all other ones which try to
78//!   "use" or "consume" it are blocked until the test finishes.
79//!
80//!   It can be compared to an exclusive lock.
81//!
82//! - `no_default_uses`: by default, every test uses implicitly a default
83//!   resource. This tag prevents it.  See also `notparallel` below.
84//!
85//! - `notparallel`: with this tag the default ressource (see
86//!   `no_default_uses` above) is consumed so that the test does not run with
87//!   other ones in parallel.
88//!
89//! Both the `uses` and `consumes` resources can be specified as
90//!
91//! - a single literal (e.g. `"video"`)
92//!
93//! - a bracket, comma separated list of expressions which are evaluated at
94//!   runtime of the test
95//!
96//! Resources will be allocated **after** checking whether test shall be
97//! skipped.
98//!
99//! ### Examples
100//!
101//! ```
102//! # use etest::etest;
103//! #[etest(consumes=["video", "audio"], uses="network", no_default_uses)]
104//! fn test0() { /* ... */ }
105//! ```
106//!
107//! ```
108//! # use etest::etest;
109//! # fn is_hdmi_connected() -> bool { true }
110//! fn output() -> &'static str {
111//!     if is_hdmi_connected() { "hdmi" } else { "lvds" }
112//! }
113//!
114//! #[etest(consumes=[output()])]
115//! fn test1() { /* ... */ }
116
117//! #[etest(notparallel)]
118//! fn test2() { /* ... */ }
119//! ```
120//!
121//! ```
122//! # use etest::{ etest, ResourceId };
123//! enum Output {
124//!     Hdmi,
125//!     Lvds,
126//! }
127//!
128//! impl From<Output> for ResourceId {
129//! # fn from(_: Output) -> Self { "hdmi".into() }
130//!     /* ... */
131//! }
132//!
133//! #[etest(consumes=[Output::Hdmi])]
134//! fn test2() { /* ... */ }
135//! ```
136//!
137//! ## Timeout
138//!
139//! Related attributes:
140//!
141//! - `timeout`: timeout which represents the maximum runtime of the test.
142//!   When test is still active after this time, it will be aborted by a
143//!   `panic!`.
144//!
145//!   The timeout is a value which implements [`Into<Timeout>`](Timeout);
146//!   plain numbers will mean milliseconds.
147//!
148//! Clock will start to tick **after** resources have been allocated.
149//!
150//! ### Examples
151//!
152//! ```
153//! # use etest::etest;
154//! #[etest(timeout=20_000)]
155//! fn test() { /* ... */ }
156//! ```
157
158
159// declares macros for use in crate; must be on top of file
160#[doc(hidden)]
161mod logging;
162
163pub use etest_derive::etest;
164
165mod resource;
166mod location;
167mod timeout;
168mod default_return;
169mod helpers;
170
171#[doc(hidden)]
172pub use location::Location;
173
174#[doc(inline)]
175pub use resource::ResourceId;
176
177// TODO: this is only public to allow rustdoc to generate the related
178// documentation
179pub use resource::ResourceIdImpl;
180
181#[doc(hidden)]
182pub use resource::{ ResourceBuilder, RESOURCES };
183
184#[doc(inline)]
185pub use default_return::DefaultReturn;
186
187#[doc(inline)]
188pub use timeout::Timeout;
189
190#[doc(hidden)]
191pub use helpers::*;
192
193#[doc(hidden)]
194pub mod prelude {
195    pub use crate::DefaultReturn;
196    pub use crate::ResourceId;
197    pub use crate::Timeout;
198    pub use crate::etest;
199}