safina_macros/lib.rs
1//! # safina-macros
2//! [](https://crates.io/crates/safina-macros)
3//! [](http://www.apache.org/licenses/LICENSE-2.0)
4//! [](https://github.com/rust-secure-code/safety-dance/)
5//! [](https://gitlab.com/leonhard-llc/safina-rs/-/pipelines)
6//!
7//! Procedural macros for the [safina](https://crates.io/crates/safina) crate.
8//!
9//! License: Apache-2.0
10//!
11//! # Cargo Geiger Safety Report
12#![forbid(unsafe_code)]
13
14mod async_test;
15
16/// A macro for running `async fn` tests.
17///
18/// - Runs tests with [safina::executor](https://docs.rs/safina/latest/safina/executor/)
19/// - Each test gets its own executor with 2 threads for async tasks and 1 thread for blocking tasks.
20/// - Also calls
21/// [safina::timer::start_timer_thread](https://docs.rs/safina/latest/safina/timer/fn.start_timer_thread.html)
22/// before running the test
23/// - Lightweight dependencies
24///
25/// # Examples
26/// ```rust
27/// use safina::async_test;
28/// # async fn async_work() -> Result<(), std::io::Error> { Ok(()) }
29///
30/// #[async_test]
31/// async fn test1() {
32/// async_work().await.unwrap();
33/// }
34/// ```
35///
36/// ```rust
37/// use safina::async_test;
38/// # use core::time::Duration;
39/// # fn blocking_work() -> Result<u8, std::io::Error> { Ok(3) }
40/// # async fn background_task() {}
41/// # async fn async_work() -> Result<u8, std::io::Error> { Ok(42) }
42///
43/// // Make your test an `async fn`.
44/// #[async_test]
45/// async fn test2() {
46/// // You can `await`.
47/// async_work().await.unwrap();
48///
49/// // You can spawn tasks which will run on
50/// // the executor.
51/// // These tasks stop when the test
52/// // function returns and drops the
53/// // executor.
54/// safina::executor::spawn(background_task());
55///
56/// // You can run blocking code without
57/// // stalling other async tasks.
58/// let result = safina::executor::schedule_blocking(
59/// || blocking_work()
60/// ).async_recv().await.unwrap();
61/// assert_eq!(3, result.unwrap());
62///
63/// // You can use timer functions.
64/// safina::timer::sleep_for(
65/// Duration::from_millis(10)).await;
66/// safina::timer::with_timeout(
67/// async_work(),
68/// Duration::from_millis(100)
69/// ).await.unwrap().unwrap();
70/// }
71/// ```
72///
73/// # Alternatives
74/// - [async_std::test](https://docs.rs/async-std/latest/async_std/attr.test.html)
75/// - [futures_await_test::async_test](https://docs.rs/futures-await-test)
76/// - [tokio::test](https://docs.rs/tokio/latest/tokio/attr.test.html)
77#[proc_macro_attribute]
78pub fn async_test(
79 attr: proc_macro::TokenStream,
80 item: proc_macro::TokenStream,
81) -> proc_macro::TokenStream {
82 let output2 = match async_test::implementation(
83 safe_proc_macro2::TokenStream::from(attr),
84 safe_proc_macro2::TokenStream::from(item),
85 ) {
86 Ok(output) => output,
87 Err(error_tokens) => return proc_macro::TokenStream::from(error_tokens),
88 };
89
90 // let mut token_stream_string = String::new();
91 // for tree in output {
92 // token_stream_string.push_str(format!("tree: {tree}\n").as_str());
93 // }
94 // panic!("TokenStream:\n{}", token_stream_string);
95
96 proc_macro::TokenStream::from(output2)
97}