diff --git a/Cargo.toml b/Cargo.toml index 4f640c7..43eb218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,13 +18,14 @@ rust-version = "1.70.0" proc-macro = true [dependencies] -syn = { version = "2.0.68", features = ["visit", "full", "extra-traits"] } -quote = "1.0.36" -proc-macro2 = "1.0.86" +syn = { version = "2.0.100", features = ["visit", "full", "extra-traits"] } +quote = "1.0.40" +proc-macro2 = "1.0.94" structmeta = "0.3.0" [dev-dependencies] proptest = "1.6.0" -trybuild = "1.0.96" -tokio = { version = "1.38.0", features = ["rt-multi-thread"] } +trybuild = "1.0.104" +tokio = { version = "1.44.1", features = ["rt-multi-thread"] } anyhow = "1.0.97" +googletest = "0.14.0" diff --git a/src/proptest_fn.rs b/src/proptest_fn.rs index f275c8c..a21a7af 100644 --- a/src/proptest_fn.rs +++ b/src/proptest_fn.rs @@ -4,10 +4,41 @@ use crate::syn_utils::{Arg, Args}; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; use syn::{ - parse2, parse_quote, parse_str, spanned::Spanned, token, Block, Expr, Field, FieldMutability, - FnArg, Ident, ItemFn, LitStr, Pat, Result, ReturnType, Visibility, + parse2, parse_quote, parse_str, spanned::Spanned, token, Attribute, Block, Expr, Field, + FieldMutability, FnArg, Ident, ItemFn, LitStr, Pat, Result, ReturnType, Visibility, }; +// Check whether given attribute is a test attribute of forms: +// * `#[test]` +// * `#[core::prelude::*::test]` or `#[::core::prelude::*::test]` +// * `#[std::prelude::*::test]` or `#[::std::prelude::*::test]` +fn is_test_attribute(attr: &Attribute) -> bool { + let path = match &attr.meta { + syn::Meta::Path(path) => path, + _ => return false, + }; + const CANDIDATES_LEN: usize = 4; + + let candidates: [[&str; CANDIDATES_LEN]; 2] = [ + ["core", "prelude", "*", "test"], + ["std", "prelude", "*", "test"], + ]; + if path.leading_colon.is_none() + && path.segments.len() == 1 + && path.segments[0].arguments.is_none() + && path.segments[0].ident == "test" + { + return true; + } else if path.segments.len() != candidates[0].len() { + return false; + } + candidates.into_iter().any(|segments| { + path.segments.iter().zip(segments).all(|(segment, path)| { + segment.arguments.is_none() && (path == "*" || segment.ident == path) + }) + }) +} + pub fn build_proptest(attr: TokenStream, mut item_fn: ItemFn) -> Result { let mut attr_args = None; if !attr.is_empty() { @@ -64,6 +95,12 @@ pub fn build_proptest(attr: TokenStream, mut item_fn: ItemFn) -> Result Result anyhow::Result< yield_now().await; anyhow::bail!("error"); } + +#[proptest] +#[gtest] +fn googletest_result(#[strategy(1..10u8)] x: u8) -> googletest::Result<()> { + expect_that!(x, ge(1)); + verify_that!(x, lt(10)) +}