From ef93479f9657814aad0af725cc2491fce844d2d1 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sat, 10 Aug 2019 17:16:16 +0200 Subject: [PATCH 01/12] Add test-cases init --- Cargo.toml | 5 ++++- lib/test-cases/Cargo.toml | 10 ++++++++++ lib/test-cases/src/lib.rs | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 lib/test-cases/Cargo.toml create mode 100644 lib/test-cases/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 7b523d8..d2af793 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,4 +22,7 @@ panic = "unwind" [lib] path = "src/lib.rs" -[dependencies] +[workspace] +members = [ + "lib/test-cases", +] \ No newline at end of file diff --git a/lib/test-cases/Cargo.toml b/lib/test-cases/Cargo.toml new file mode 100644 index 0000000..9cdcaf1 --- /dev/null +++ b/lib/test-cases/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "test-cases" +version = "0.1.0" +authors = ["Armin Becher "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] \ No newline at end of file diff --git a/lib/test-cases/src/lib.rs b/lib/test-cases/src/lib.rs new file mode 100644 index 0000000..e9cb431 --- /dev/null +++ b/lib/test-cases/src/lib.rs @@ -0,0 +1,16 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn make_answer(_item: TokenStream) -> TokenStream { + "fn answer() -> u32 { 42 }".parse().unwrap() +} + + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} -- GitLab From 5ef8e00bd7608cb1dbba5398f32db2efc54530cf Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sat, 10 Aug 2019 17:43:22 +0200 Subject: [PATCH 02/12] Package restructured --- Cargo.toml | 29 ++----------------- ntest/Cargo.toml | 29 +++++++++++++++++++ {src => ntest/src}/lib.rs | 11 ++++++- .../Cargo.toml | 4 +-- .../src/lib.rs | 0 5 files changed, 44 insertions(+), 29 deletions(-) create mode 100644 ntest/Cargo.toml rename {src => ntest/src}/lib.rs (91%) rename {lib/test-cases => ntest_test_cases}/Cargo.toml (75%) rename {lib/test-cases => ntest_test_cases}/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index d2af793..37be44b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,28 +1,5 @@ -[package] -name = "ntest" -version = "0.1.0" -authors = ["Armin Becher "] -edition = "2018" -description = "Testing framework for rust which enhances the built-in library with some useful features." -keywords = ["test", "tests", "unit", "testing"] -categories = ["development-tools", "development-tools::testing"] -readme = "README.md" -license = "MIT" -license-file = "LICENSE" -repository = "https://gitlab.com/becheran/ntest" -documentation = "https://docs.rs/ntest" - -[badges] -gitlab = { repository = "https://gitlab.com/becheran/ntest", branch = "master" } -maintenance = { status = "actively-developed" } - -[profile.dev] -panic = "unwind" - -[lib] -path = "src/lib.rs" - [workspace] members = [ - "lib/test-cases", -] \ No newline at end of file + "ntest", + "ntest_test_cases", +] diff --git a/ntest/Cargo.toml b/ntest/Cargo.toml new file mode 100644 index 0000000..f6bdaae --- /dev/null +++ b/ntest/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "ntest" +version = "0.1.0" +authors = ["Armin Becher "] +edition = "2018" +description = "Testing framework for rust which enhances the built-in library with some useful features." +keywords = ["test", "tests", "unit", "testing"] +categories = ["development-tools", "development-tools::testing"] +readme = "README.md" +license-file = "LICENSE" +repository = "https://gitlab.com/becheran/ntest" +documentation = "https://docs.rs/ntest" + +[badges] +gitlab = { repository = "https://gitlab.com/becheran/ntest", branch = "master" } +maintenance = { status = "actively-developed" } + +[profile.dev] +panic = "unwind" + +[lib] +path = "src/lib.rs" + + +[dependencies] +test_cases = { version = "1.0", path = "../ntest_test_cases" } + +[dev-dependencies] +test_cases = { version = "1.0", path = "../ntest_test_cases" } \ No newline at end of file diff --git a/src/lib.rs b/ntest/src/lib.rs similarity index 91% rename from src/lib.rs rename to ntest/src/lib.rs index 3aae96b..073a5cc 100644 --- a/src/lib.rs +++ b/ntest/src/lib.rs @@ -81,4 +81,13 @@ macro_rules! assert_panics { let result = std::panic::catch_unwind(||$x); assert!(result.is_err()); }); -} \ No newline at end of file +} +/* +#[cfg(feature = "test_cases")] +#[allow(unused_imports)] +#[macro_use] +extern crate test_cases; +#[cfg(feature = "test_cases")] +#[doc(hidden)] +pub use serde_derive::*; +*/ \ No newline at end of file diff --git a/lib/test-cases/Cargo.toml b/ntest_test_cases/Cargo.toml similarity index 75% rename from lib/test-cases/Cargo.toml rename to ntest_test_cases/Cargo.toml index 9cdcaf1..baef771 100644 --- a/lib/test-cases/Cargo.toml +++ b/ntest_test_cases/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "test-cases" -version = "0.1.0" +name = "test_cases" +version = "1.0.0" authors = ["Armin Becher "] edition = "2018" diff --git a/lib/test-cases/src/lib.rs b/ntest_test_cases/src/lib.rs similarity index 100% rename from lib/test-cases/src/lib.rs rename to ntest_test_cases/src/lib.rs -- GitLab From f65f09860a33623118a674d5c64cb8324af5a53a Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sat, 10 Aug 2019 18:19:42 +0200 Subject: [PATCH 03/12] Split library in two parts --- ntest/Cargo.toml | 6 +++--- ntest/LICENSE | 1 + ntest/README.md | 1 + ntest/src/lib.rs | 9 ++++++++- ntest_test_cases/Cargo.toml | 12 ++++++++++-- ntest_test_cases/LICENSE | 1 + ntest_test_cases/README.md | 1 + 7 files changed, 25 insertions(+), 6 deletions(-) create mode 120000 ntest/LICENSE create mode 120000 ntest/README.md create mode 120000 ntest_test_cases/LICENSE create mode 120000 ntest_test_cases/README.md diff --git a/ntest/Cargo.toml b/ntest/Cargo.toml index f6bdaae..ac6a0fa 100644 --- a/ntest/Cargo.toml +++ b/ntest/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntest" -version = "0.1.0" +version = "0.1.1" authors = ["Armin Becher "] edition = "2018" description = "Testing framework for rust which enhances the built-in library with some useful features." @@ -23,7 +23,7 @@ path = "src/lib.rs" [dependencies] -test_cases = { version = "1.0", path = "../ntest_test_cases" } +ntest_test_cases = { version = "0.1.0", path = "../ntest_test_cases" } [dev-dependencies] -test_cases = { version = "1.0", path = "../ntest_test_cases" } \ No newline at end of file +ntest_test_cases = { version = "0.1.0", path = "../ntest_test_cases" } \ No newline at end of file diff --git a/ntest/LICENSE b/ntest/LICENSE new file mode 120000 index 0000000..ea5b606 --- /dev/null +++ b/ntest/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/ntest/README.md b/ntest/README.md new file mode 120000 index 0000000..32d46ee --- /dev/null +++ b/ntest/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file diff --git a/ntest/src/lib.rs b/ntest/src/lib.rs index 073a5cc..bc79a40 100644 --- a/ntest/src/lib.rs +++ b/ntest/src/lib.rs @@ -90,4 +90,11 @@ extern crate test_cases; #[cfg(feature = "test_cases")] #[doc(hidden)] pub use serde_derive::*; -*/ \ No newline at end of file +*/ + +#[allow(unused_imports)] +#[macro_use] +extern crate ntest_test_cases; +#[cfg(feature = "serde_derive")] +#[doc(hidden)] +pub use ntest_test_cases::*; \ No newline at end of file diff --git a/ntest_test_cases/Cargo.toml b/ntest_test_cases/Cargo.toml index baef771..eb043fc 100644 --- a/ntest_test_cases/Cargo.toml +++ b/ntest_test_cases/Cargo.toml @@ -1,10 +1,18 @@ [package] -name = "test_cases" -version = "1.0.0" +name = "ntest_test_cases" +version = "0.1.0" authors = ["Armin Becher "] edition = "2018" +description = "Test cases for ntest framwork." +keywords = ["test", "tests", "unit", "testing", "test-cases"] +categories = ["development-tools", "development-tools::testing"] +readme = "README.md" +license-file = "LICENSE" +repository = "https://gitlab.com/becheran/ntest" +documentation = "https://docs.rs/ntest" [lib] +name = "ntest_test_cases" proc-macro = true [dependencies] \ No newline at end of file diff --git a/ntest_test_cases/LICENSE b/ntest_test_cases/LICENSE new file mode 120000 index 0000000..ea5b606 --- /dev/null +++ b/ntest_test_cases/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/ntest_test_cases/README.md b/ntest_test_cases/README.md new file mode 120000 index 0000000..32d46ee --- /dev/null +++ b/ntest_test_cases/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file -- GitLab From f59f2623a4403f68ee7a2d2d26bbd8684dc8ce19 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sun, 11 Aug 2019 00:08:43 +0200 Subject: [PATCH 04/12] Update reexport of procedural macro --- ntest/Cargo.toml | 4 ++-- ntest/src/lib.rs | 14 +------------- ntest_test_cases/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/ntest/Cargo.toml b/ntest/Cargo.toml index ac6a0fa..c2868c0 100644 --- a/ntest/Cargo.toml +++ b/ntest/Cargo.toml @@ -23,7 +23,7 @@ path = "src/lib.rs" [dependencies] -ntest_test_cases = { version = "0.1.0", path = "../ntest_test_cases" } +ntest_test_cases = { version = "0.1.1", path = "../ntest_test_cases" } [dev-dependencies] -ntest_test_cases = { version = "0.1.0", path = "../ntest_test_cases" } \ No newline at end of file +ntest_test_cases = { version = "0.1.1", path = "../ntest_test_cases" } \ No newline at end of file diff --git a/ntest/src/lib.rs b/ntest/src/lib.rs index bc79a40..397ba5f 100644 --- a/ntest/src/lib.rs +++ b/ntest/src/lib.rs @@ -82,19 +82,7 @@ macro_rules! assert_panics { assert!(result.is_err()); }); } -/* -#[cfg(feature = "test_cases")] -#[allow(unused_imports)] -#[macro_use] -extern crate test_cases; -#[cfg(feature = "test_cases")] -#[doc(hidden)] -pub use serde_derive::*; -*/ -#[allow(unused_imports)] -#[macro_use] +// Reexport procedural macros extern crate ntest_test_cases; -#[cfg(feature = "serde_derive")] -#[doc(hidden)] pub use ntest_test_cases::*; \ No newline at end of file diff --git a/ntest_test_cases/Cargo.toml b/ntest_test_cases/Cargo.toml index eb043fc..9f3d977 100644 --- a/ntest_test_cases/Cargo.toml +++ b/ntest_test_cases/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntest_test_cases" -version = "0.1.0" +version = "0.1.1" authors = ["Armin Becher "] edition = "2018" description = "Test cases for ntest framwork." -- GitLab From c2092a73243dcb5f0a390b916f300d3c773b043b Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sun, 11 Aug 2019 00:11:07 +0200 Subject: [PATCH 05/12] Version update --- ntest/Cargo.toml | 6 +++--- ntest_test_cases/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ntest/Cargo.toml b/ntest/Cargo.toml index c2868c0..0c89e90 100644 --- a/ntest/Cargo.toml +++ b/ntest/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntest" -version = "0.1.1" +version = "0.1.2" authors = ["Armin Becher "] edition = "2018" description = "Testing framework for rust which enhances the built-in library with some useful features." @@ -23,7 +23,7 @@ path = "src/lib.rs" [dependencies] -ntest_test_cases = { version = "0.1.1", path = "../ntest_test_cases" } +ntest_test_cases = { version = "0.1.2", path = "../ntest_test_cases" } [dev-dependencies] -ntest_test_cases = { version = "0.1.1", path = "../ntest_test_cases" } \ No newline at end of file +ntest_test_cases = { version = "0.1.2", path = "../ntest_test_cases" } \ No newline at end of file diff --git a/ntest_test_cases/Cargo.toml b/ntest_test_cases/Cargo.toml index 9f3d977..15f2d3b 100644 --- a/ntest_test_cases/Cargo.toml +++ b/ntest_test_cases/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntest_test_cases" -version = "0.1.1" +version = "0.1.2" authors = ["Armin Becher "] edition = "2018" description = "Test cases for ntest framwork." -- GitLab From ebc576c340833ca97596265bdc6899be99c1e412 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sun, 11 Aug 2019 11:08:34 +0200 Subject: [PATCH 06/12] First working proc_macros for test generation --- ntest_test_cases/Cargo.toml | 4 +- ntest_test_cases/src/lib.rs | 58 ++++++++++++++++++++++++---- ntest_test_cases/tests/test_cases.rs | 22 +++++++++++ 3 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 ntest_test_cases/tests/test_cases.rs diff --git a/ntest_test_cases/Cargo.toml b/ntest_test_cases/Cargo.toml index 15f2d3b..18fb7b4 100644 --- a/ntest_test_cases/Cargo.toml +++ b/ntest_test_cases/Cargo.toml @@ -15,4 +15,6 @@ documentation = "https://docs.rs/ntest" name = "ntest_test_cases" proc-macro = true -[dependencies] \ No newline at end of file +[dependencies] +syn = {version = "0.15.44",features = ["full"]} +quote = "0.6" \ No newline at end of file diff --git a/ntest_test_cases/src/lib.rs b/ntest_test_cases/src/lib.rs index e9cb431..b73ff40 100644 --- a/ntest_test_cases/src/lib.rs +++ b/ntest_test_cases/src/lib.rs @@ -1,16 +1,58 @@ extern crate proc_macro; +extern crate syn; +use syn::{parse_macro_input, DeriveInput}; use proc_macro::TokenStream; +use quote::quote; -#[proc_macro] -pub fn make_answer(_item: TokenStream) -> TokenStream { - "fn answer() -> u32 { 42 }".parse().unwrap() +#[proc_macro_attribute] +pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { + println!("attr: \"{}\"", attr.to_string()); + println!("item: \"{}\"", item.to_string()); + let input = syn::parse_macro_input!(item as syn::ItemFn); + let name = &input.ident; + let inputs = &input.decl.inputs; + //println!("item: \"{}\"", inputs[0].to_string()); + + // Our input function is always equivalent to returning 42, right? + let result = quote! { + #[test] + fn #name() { + assert!(true); + } + }; + result.into() } +/* +#[proc_macro_attribute] +pub fn test_case(attr: TokenStream, input: TokenStream) -> TokenStream { + let attr_string = get_attr_string(&attr); + let input_string = format!("#[test_case{}]{}", attr_string, input); + let ast = syn::parse_token_trees(&input_string); + + match ast { + Ok(token_tree) => { + let test_case_suit : TestCaseSuit = token_tree.into(); + let test_cases = + test_case_suit + .gen_test_cases() + .to_string(); -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); + TokenStream::from_str(&test_cases) + .expect(&format!("generate test cases for: {}", input_string)) + }, + Err(e) => panic!(e) + } +} + +fn get_attr_string(attr: &TokenStream) -> String { + let result = format!("{}", attr); + + if result.starts_with("(") { + result + } + else { + format!("({})", result) } } +*/ \ No newline at end of file diff --git a/ntest_test_cases/tests/test_cases.rs b/ntest_test_cases/tests/test_cases.rs new file mode 100644 index 0000000..3fccdbf --- /dev/null +++ b/ntest_test_cases/tests/test_cases.rs @@ -0,0 +1,22 @@ +#[macro_use] +extern crate ntest_test_cases; +#[doc(hidden)] +pub use ntest_test_cases::test_case; + +#[test_case(42)] +fn one_arg(x: u32) { + assert_eq!(x, 42) +} + + +#[test_case(13)] +fn one_arg_fail(x: u32) { + assert_eq!(x, 42) +} + + +#[test_case(13, 42)] +fn two_args(x: u32, y: u32) { + assert_eq!(x, 13); + assert_eq!(y, 42); +} \ No newline at end of file -- GitLab From d4ecdb60277145840e84684dfb29fcd5942d01a6 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Sun, 11 Aug 2019 13:05:59 +0200 Subject: [PATCH 07/12] Testcase names working --- ntest_test_cases/Cargo.toml | 3 +- ntest_test_cases/src/lib.rs | 72 +++++++++++++++------------- ntest_test_cases/tests/test_cases.rs | 3 +- 3 files changed, 44 insertions(+), 34 deletions(-) diff --git a/ntest_test_cases/Cargo.toml b/ntest_test_cases/Cargo.toml index 18fb7b4..ad359fe 100644 --- a/ntest_test_cases/Cargo.toml +++ b/ntest_test_cases/Cargo.toml @@ -17,4 +17,5 @@ proc-macro = true [dependencies] syn = {version = "0.15.44",features = ["full"]} -quote = "0.6" \ No newline at end of file +quote = "0.6" +proc-macro2 = "0.4" \ No newline at end of file diff --git a/ntest_test_cases/src/lib.rs b/ntest_test_cases/src/lib.rs index b73ff40..af40b48 100644 --- a/ntest_test_cases/src/lib.rs +++ b/ntest_test_cases/src/lib.rs @@ -1,5 +1,7 @@ extern crate proc_macro; extern crate syn; + +use proc_macro2::{Ident, Span}; use syn::{parse_macro_input, DeriveInput}; use proc_macro::TokenStream; use quote::quote; @@ -8,51 +10,57 @@ use quote::quote; pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { println!("attr: \"{}\"", attr.to_string()); println!("item: \"{}\"", item.to_string()); + let attr = parse_macro_input!(attr as syn::AttributeArgs); let input = syn::parse_macro_input!(item as syn::ItemFn); - let name = &input.ident; + let test_case_settings = parse_test_case_attributes(&attr); + + let test_case_name = syn::Ident::new( + &format!("{}{}", &input.ident.to_string(), &test_case_settings.name), + Span::call_site()); + let inputs = &input.decl.inputs; - //println!("item: \"{}\"", inputs[0].to_string()); - // Our input function is always equivalent to returning 42, right? let result = quote! { #[test] - fn #name() { + fn #test_case_name() { assert!(true); } }; result.into() } -/* -#[proc_macro_attribute] -pub fn test_case(attr: TokenStream, input: TokenStream) -> TokenStream { - let attr_string = get_attr_string(&attr); - let input_string = format!("#[test_case{}]{}", attr_string, input); - let ast = syn::parse_token_trees(&input_string); - - match ast { - Ok(token_tree) => { - let test_case_suit : TestCaseSuit = token_tree.into(); - let test_cases = - test_case_suit - .gen_test_cases() - .to_string(); - - TokenStream::from_str(&test_cases) - .expect(&format!("generate test cases for: {}", input_string)) - }, - Err(e) => panic!(e) - } -} -fn get_attr_string(attr: &TokenStream) -> String { - let result = format!("{}", attr); +struct TestCaseAttributes { + literals: Vec, + name: String, + // TODO add Meta attributes test_name and expected_result +} - if result.starts_with("(") { - result +fn parse_test_case_attributes(attr: &syn::AttributeArgs) -> TestCaseAttributes { + let mut literals: Vec = vec![]; + let mut name = "".to_string();; + for a in attr { + match a { + syn::NestedMeta::Meta(m) => println!("meta"), + syn::NestedMeta::Literal(lit) => { + literals.push((*lit).clone()); + name.push_str(&format!("_{}",lit_to_str(lit))); + }, + } } - else { - format!("({})", result) + println!("{}", name); + + TestCaseAttributes { + literals, + name, } } -*/ \ No newline at end of file + +fn lit_to_str(lit: &syn::Lit) -> String{ + match lit { + syn::Lit::Bool(s) => s.value.to_string(), + syn::Lit::Str(s) => s.value().to_string(), + syn::Lit::Int(s) => s.value().to_string(), + _ => unimplemented!(), + } +} \ No newline at end of file diff --git a/ntest_test_cases/tests/test_cases.rs b/ntest_test_cases/tests/test_cases.rs index 3fccdbf..5d03363 100644 --- a/ntest_test_cases/tests/test_cases.rs +++ b/ntest_test_cases/tests/test_cases.rs @@ -3,6 +3,7 @@ extern crate ntest_test_cases; #[doc(hidden)] pub use ntest_test_cases::test_case; +#[test_case(18)] #[test_case(42)] fn one_arg(x: u32) { assert_eq!(x, 42) @@ -15,7 +16,7 @@ fn one_arg_fail(x: u32) { } -#[test_case(13, 42)] +#[test_case(m=21,13, 42)] fn two_args(x: u32, y: u32) { assert_eq!(x, 13); assert_eq!(y, 42); -- GitLab From 6d63c8a020d016ccc64c9bf5d0f67a2e50932279 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Mon, 12 Aug 2019 00:02:41 +0200 Subject: [PATCH 08/12] Add parse test cases --- ntest_test_cases/src/lib.rs | 60 +++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/ntest_test_cases/src/lib.rs b/ntest_test_cases/src/lib.rs index af40b48..d09bcd5 100644 --- a/ntest_test_cases/src/lib.rs +++ b/ntest_test_cases/src/lib.rs @@ -5,24 +5,57 @@ use proc_macro2::{Ident, Span}; use syn::{parse_macro_input, DeriveInput}; use proc_macro::TokenStream; use quote::quote; +use syn::token::Token; +use syn::export::TokenStream2; #[proc_macro_attribute] pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { println!("attr: \"{}\"", attr.to_string()); println!("item: \"{}\"", item.to_string()); + let mut test_case_descriptions: Vec = vec![]; let attr = parse_macro_input!(attr as syn::AttributeArgs); - let input = syn::parse_macro_input!(item as syn::ItemFn); - let test_case_settings = parse_test_case_attributes(&attr); + let input = parse_macro_input!(item as syn::ItemFn); + + // Collect test case descriptions + test_case_descriptions.push(parse_test_case_attributes(&attr)); + for at in &input.attrs { + let meta = at.parse_meta(); + match meta { + Ok(m) => { + match m { + syn::Meta::List(ml) => { + if ml.ident != "test_case" { + panic!("Only test_case attributes expected, but found {:?}", ml.ident); + } + let argument_args : syn::AttributeArgs = ml.nested.into_iter().collect(); + test_case_descriptions.push(parse_test_case_attributes(&argument_args)); + } + syn::Meta::Word(i) => { + panic!("Wrong input {:?} for test cases", i) + } + syn::Meta::NameValue(l) => { + // TODO check for named values + unimplemented!() + } + } + } + Err(e) => panic!("Could not determine meta data. Error {}", e) + } + } + + let test_double: Vec = vec!["hello".to_string(), "world".to_string()]; let test_case_name = syn::Ident::new( - &format!("{}{}", &input.ident.to_string(), &test_case_settings.name), + &format!("{}{}", &input.ident.to_string(), &test_case_descriptions[0].name), Span::call_site()); - let inputs = &input.decl.inputs; - let result = quote! { + let function_arguments = &input.decl.inputs; + + let mut result = quote! { #[test] fn #test_case_name() { + #(println!(#test_double);)* assert!(true); } }; @@ -30,33 +63,34 @@ pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { } -struct TestCaseAttributes { +struct TestCaseDescription { literals: Vec, name: String, - // TODO add Meta attributes test_name and expected_result + // TODO add Meta attributes expected_result } -fn parse_test_case_attributes(attr: &syn::AttributeArgs) -> TestCaseAttributes { +fn parse_test_case_attributes(attr: &syn::AttributeArgs) -> TestCaseDescription { let mut literals: Vec = vec![]; - let mut name = "".to_string();; + let mut name = "".to_string(); + for a in attr { match a { syn::NestedMeta::Meta(m) => println!("meta"), syn::NestedMeta::Literal(lit) => { literals.push((*lit).clone()); - name.push_str(&format!("_{}",lit_to_str(lit))); - }, + name.push_str(&format!("_{}", lit_to_str(lit))); + } } } println!("{}", name); - TestCaseAttributes { + TestCaseDescription { literals, name, } } -fn lit_to_str(lit: &syn::Lit) -> String{ +fn lit_to_str(lit: &syn::Lit) -> String { match lit { syn::Lit::Bool(s) => s.value.to_string(), syn::Lit::Str(s) => s.value().to_string(), -- GitLab From f103ef548c89db9104774e12e3e72849d33333bf Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Mon, 12 Aug 2019 00:25:19 +0200 Subject: [PATCH 09/12] Working for multiple annotations --- ntest_test_cases/src/lib.rs | 47 ++++++++++++++-------------- ntest_test_cases/tests/test_cases.rs | 16 +++++----- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/ntest_test_cases/src/lib.rs b/ntest_test_cases/src/lib.rs index d09bcd5..e50229a 100644 --- a/ntest_test_cases/src/lib.rs +++ b/ntest_test_cases/src/lib.rs @@ -1,11 +1,10 @@ extern crate proc_macro; extern crate syn; -use proc_macro2::{Ident, Span}; -use syn::{parse_macro_input, DeriveInput}; +use proc_macro2::Span; +use syn::parse_macro_input; use proc_macro::TokenStream; use quote::quote; -use syn::token::Token; use syn::export::TokenStream2; #[proc_macro_attribute] @@ -27,15 +26,14 @@ pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { if ml.ident != "test_case" { panic!("Only test_case attributes expected, but found {:?}", ml.ident); } - let argument_args : syn::AttributeArgs = ml.nested.into_iter().collect(); + let argument_args: syn::AttributeArgs = ml.nested.into_iter().collect(); test_case_descriptions.push(parse_test_case_attributes(&argument_args)); } syn::Meta::Word(i) => { panic!("Wrong input {:?} for test cases", i) } - syn::Meta::NameValue(l) => { - // TODO check for named values - unimplemented!() + syn::Meta::NameValue(_) => { + unimplemented!("Need to check for named values"); } } } @@ -43,22 +41,24 @@ pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { } } - let test_double: Vec = vec!["hello".to_string(), "world".to_string()]; - - let test_case_name = syn::Ident::new( - &format!("{}{}", &input.ident.to_string(), &test_case_descriptions[0].name), - Span::call_site()); - - let function_arguments = &input.decl.inputs; + - let mut result = quote! { - #[test] - fn #test_case_name() { - #(println!(#test_double);)* - assert!(true); - } - }; + let mut result = TokenStream2::new(); + for test_case_description in test_case_descriptions { + let test_case_name = syn::Ident::new( + &format!("{}{}", &input.ident.to_string(), &test_case_description.name), + Span::call_site(), + ); + + let test_case_quote = quote! { + #[test] + fn #test_case_name() { + assert!(true); + } + }; + result.extend(test_case_quote); + } result.into() } @@ -75,14 +75,15 @@ fn parse_test_case_attributes(attr: &syn::AttributeArgs) -> TestCaseDescription for a in attr { match a { - syn::NestedMeta::Meta(m) => println!("meta"), + syn::NestedMeta::Meta(_) => { + unimplemented!("Need to check for named values"); + } syn::NestedMeta::Literal(lit) => { literals.push((*lit).clone()); name.push_str(&format!("_{}", lit_to_str(lit))); } } } - println!("{}", name); TestCaseDescription { literals, diff --git a/ntest_test_cases/tests/test_cases.rs b/ntest_test_cases/tests/test_cases.rs index 5d03363..d305b8c 100644 --- a/ntest_test_cases/tests/test_cases.rs +++ b/ntest_test_cases/tests/test_cases.rs @@ -1,9 +1,10 @@ -#[macro_use] extern crate ntest_test_cases; #[doc(hidden)] pub use ntest_test_cases::test_case; -#[test_case(18)] +#[test_case(1)] +#[test_case(2)] +#[test_case(3)] #[test_case(42)] fn one_arg(x: u32) { assert_eq!(x, 42) @@ -15,9 +16,8 @@ fn one_arg_fail(x: u32) { assert_eq!(x, 42) } - -#[test_case(m=21,13, 42)] -fn two_args(x: u32, y: u32) { - assert_eq!(x, 13); - assert_eq!(y, 42); -} \ No newline at end of file +//#[test_case(m=21,13, 42)] +//fn two_args(x: u32, y: u32) { +// assert_eq!(x, 13); +// assert_eq!(y, 42); +//} -- GitLab From 99dbe15677e0d296c8dce0fdd70083d82103637b Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Mon, 12 Aug 2019 01:25:15 +0200 Subject: [PATCH 10/12] Working arguments from input --- ntest_test_cases/src/lib.rs | 28 +++++++++++++++++++++++++--- ntest_test_cases/tests/test_cases.rs | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ntest_test_cases/src/lib.rs b/ntest_test_cases/src/lib.rs index e50229a..d828491 100644 --- a/ntest_test_cases/src/lib.rs +++ b/ntest_test_cases/src/lib.rs @@ -41,8 +41,24 @@ pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { } } - let function_arguments = &input.decl.inputs; - + let fn_args = &input.decl.inputs; + let fn_body = &input.block; + let mut fn_args_idents: Vec = vec![]; + + for i in fn_args { + match i { + syn::FnArg::Captured(c) => { + match &c.pat { + syn::Pat::Ident(ident) => { + println!("Function argument identifier {:?}", ident.ident); + fn_args_idents.push(ident.ident.clone()); + } + _ => panic!("Unexpected function identifier.") + } + } + _ => panic!("Unexpected function identifier.") + } + } let mut result = TokenStream2::new(); for test_case_description in test_case_descriptions { @@ -50,11 +66,17 @@ pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { &format!("{}{}", &input.ident.to_string(), &test_case_description.name), Span::call_site(), ); + let literals = test_case_description.literals; + if &literals.len() != &fn_args_idents.len() { + panic!("Test case arguments and function input signature do not match"); + } let test_case_quote = quote! { #[test] fn #test_case_name() { - assert!(true); + let x = 42; + #(let x = #literals;)* + #fn_body } }; result.extend(test_case_quote); diff --git a/ntest_test_cases/tests/test_cases.rs b/ntest_test_cases/tests/test_cases.rs index d305b8c..931e0f1 100644 --- a/ntest_test_cases/tests/test_cases.rs +++ b/ntest_test_cases/tests/test_cases.rs @@ -13,7 +13,7 @@ fn one_arg(x: u32) { #[test_case(13)] fn one_arg_fail(x: u32) { - assert_eq!(x, 42) + assert_eq!(x, 13) } //#[test_case(m=21,13, 42)] -- GitLab From ea24721c66a37824a7f2a0d354268ef009aabbf2 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Mon, 12 Aug 2019 01:33:13 +0200 Subject: [PATCH 11/12] Working code for multiple test cases --- ntest_test_cases/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ntest_test_cases/src/lib.rs b/ntest_test_cases/src/lib.rs index d828491..0fb1173 100644 --- a/ntest_test_cases/src/lib.rs +++ b/ntest_test_cases/src/lib.rs @@ -9,8 +9,6 @@ use syn::export::TokenStream2; #[proc_macro_attribute] pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { - println!("attr: \"{}\"", attr.to_string()); - println!("item: \"{}\"", item.to_string()); let mut test_case_descriptions: Vec = vec![]; let attr = parse_macro_input!(attr as syn::AttributeArgs); let input = parse_macro_input!(item as syn::ItemFn); @@ -50,7 +48,6 @@ pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { syn::FnArg::Captured(c) => { match &c.pat { syn::Pat::Ident(ident) => { - println!("Function argument identifier {:?}", ident.ident); fn_args_idents.push(ident.ident.clone()); } _ => panic!("Unexpected function identifier.") @@ -71,11 +68,14 @@ pub fn test_case(attr: TokenStream, item: TokenStream) -> TokenStream { panic!("Test case arguments and function input signature do not match"); } + // Needs to be immutable + let fn_args_idents = fn_args_idents.clone(); + let test_case_quote = quote! { #[test] fn #test_case_name() { let x = 42; - #(let x = #literals;)* + #(let #fn_args_idents = #literals;)* #fn_body } }; -- GitLab From 710f71d64a534f2bea0e8883a1036e0c97ef6252 Mon Sep 17 00:00:00 2001 From: Armin Becher Date: Mon, 12 Aug 2019 01:36:32 +0200 Subject: [PATCH 12/12] Version update --- ntest/Cargo.toml | 6 +++--- ntest_test_cases/Cargo.toml | 2 +- ntest_test_cases/tests/test_cases.rs | 16 ++++------------ 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/ntest/Cargo.toml b/ntest/Cargo.toml index 0c89e90..76b3207 100644 --- a/ntest/Cargo.toml +++ b/ntest/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntest" -version = "0.1.2" +version = "0.1.3" authors = ["Armin Becher "] edition = "2018" description = "Testing framework for rust which enhances the built-in library with some useful features." @@ -23,7 +23,7 @@ path = "src/lib.rs" [dependencies] -ntest_test_cases = { version = "0.1.2", path = "../ntest_test_cases" } +ntest_test_cases = { version = "0.1.3", path = "../ntest_test_cases" } [dev-dependencies] -ntest_test_cases = { version = "0.1.2", path = "../ntest_test_cases" } \ No newline at end of file +ntest_test_cases = { version = "0.1.3", path = "../ntest_test_cases" } \ No newline at end of file diff --git a/ntest_test_cases/Cargo.toml b/ntest_test_cases/Cargo.toml index ad359fe..6ce5496 100644 --- a/ntest_test_cases/Cargo.toml +++ b/ntest_test_cases/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntest_test_cases" -version = "0.1.2" +version = "0.1.3" authors = ["Armin Becher "] edition = "2018" description = "Test cases for ntest framwork." diff --git a/ntest_test_cases/tests/test_cases.rs b/ntest_test_cases/tests/test_cases.rs index 931e0f1..73b36ae 100644 --- a/ntest_test_cases/tests/test_cases.rs +++ b/ntest_test_cases/tests/test_cases.rs @@ -2,22 +2,14 @@ extern crate ntest_test_cases; #[doc(hidden)] pub use ntest_test_cases::test_case; -#[test_case(1)] -#[test_case(2)] -#[test_case(3)] #[test_case(42)] fn one_arg(x: u32) { assert_eq!(x, 42) } -#[test_case(13)] -fn one_arg_fail(x: u32) { - assert_eq!(x, 13) +#[test_case(13, 42)] +fn two_args(x: u32, y: u32) { + assert_eq!(x, 13); + assert_eq!(y, 42); } - -//#[test_case(m=21,13, 42)] -//fn two_args(x: u32, y: u32) { -// assert_eq!(x, 13); -// assert_eq!(y, 42); -//} -- GitLab