Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async test function attribute #2409

Merged
merged 5 commits into from May 7, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 27 additions & 0 deletions futures-macro/src/executor.rs
@@ -0,0 +1,27 @@
use proc_macro::TokenStream;
use quote::quote;

pub(crate) fn test(_: TokenStream, item: TokenStream) -> TokenStream {
ibraheemdev marked this conversation as resolved.
Show resolved Hide resolved
let mut input = syn::parse_macro_input!(item as syn::ItemFn);
let attrs = &input.attrs;
let vis = &input.vis;
let sig = &mut input.sig;
let body = &input.block;

if sig.asyncness.is_none() {
return syn::Error::new_spanned(sig.fn_token, "Only async functions are supported")
.to_compile_error()
.into();
}

sig.asyncness = None;
ibraheemdev marked this conversation as resolved.
Show resolved Hide resolved

let gen = quote! {
#(#attrs)*
ibraheemdev marked this conversation as resolved.
Show resolved Hide resolved
#vis #sig {
::futures_test::__private::block_on(async move { #body })
ibraheemdev marked this conversation as resolved.
Show resolved Hide resolved
}
};

gen.into()
}
7 changes: 7 additions & 0 deletions futures-macro/src/lib.rs
Expand Up @@ -14,6 +14,7 @@ extern crate proc_macro;

use proc_macro::TokenStream;

mod executor;
mod join;
mod select;

Expand Down Expand Up @@ -44,3 +45,9 @@ pub fn select_internal(input: TokenStream) -> TokenStream {
pub fn select_biased_internal(input: TokenStream) -> TokenStream {
crate::select::select_biased(input)
}

/// The `test` attribute.
#[proc_macro_attribute]
pub fn test_internal(input: TokenStream, item: TokenStream) -> TokenStream {
crate::executor::test(input, item)
}
1 change: 1 addition & 0 deletions futures-test/Cargo.toml
Expand Up @@ -18,6 +18,7 @@ futures-io = { version = "0.3.14", path = "../futures-io", default-features = fa
futures-util = { version = "=0.4.0-alpha.0", path = "../futures-util", default-features = false }
futures-executor = { version = "=0.4.0-alpha.0", path = "../futures-executor", default-features = false }
futures-sink = { version = "=0.4.0-alpha.0", path = "../futures-sink", default-features = false }
futures-macro = { version = "=0.4.0-alpha.0", path = "../futures-macro", default-features = false }
pin-utils = { version = "0.1.0", default-features = false }
pin-project = "1.0.1"

Expand Down
14 changes: 14 additions & 0 deletions futures-test/src/lib.rs
Expand Up @@ -16,6 +16,7 @@ compile_error!(
#[cfg(feature = "std")]
pub mod __private {
pub use futures_core::{future, stream, task};
pub use futures_executor::block_on;
pub use std::{
option::Option::{None, Some},
pin::Pin,
Expand Down Expand Up @@ -49,3 +50,16 @@ pub mod io;
mod assert_unmoved;
mod interleave_pending;
mod track_closed;

/// Enables an `async` test function. The generated future will be run to completion with
/// [`futures_executor::block_on`](futures_executor::block_on).
///
/// ```
/// #[futures_test::test]
/// async fn my_test() {
/// let fut = async { true };
/// assert!(fut.await);
/// }
/// ```
ibraheemdev marked this conversation as resolved.
Show resolved Hide resolved
ibraheemdev marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(feature = "std")]
pub use futures_macro::test_internal as test;
2 changes: 1 addition & 1 deletion futures-util/src/sink/mod.rs
Expand Up @@ -243,7 +243,7 @@ pub trait SinkExt<Item>: Sink<Item> {
/// This future will drive the stream to keep producing items until it is
/// exhausted, sending each item to the sink. It will complete once both the
/// stream is exhausted, the sink has received all items, and the sink has
/// been flushed. Note that the sink is **not** closed. If the stream produces
/// been flushed. Note that the sink is **not** closed. If the stream produces
/// an error, that error will be returned by this future without flushing the sink.
///
/// Doing `sink.send_all(stream)` is roughly equivalent to
Expand Down