#![deny(unused)] #![warn(clippy::all)] #[generic_tests::define] mod simple { use std::borrow::Cow; use std::fmt::Debug; #[test] fn equates_to_str>() where S: ?Sized + PartialEq + Debug, { let s: S = "ab".into(); assert_eq!(&s, "ab"); assert_ne!(&s, "aa"); } #[instantiate_tests()] mod string {} #[instantiate_tests(>)] mod cow {} } #[generic_tests::define] mod fallible_protocol { use std::borrow::Cow; use std::fmt::Debug; use std::str::{self, Utf8Error}; trait FromUtf8<'a>: Sized + 'a { fn from_utf8(bytes: &'a [u8]) -> Result; } impl<'a> FromUtf8<'a> for &'a str { fn from_utf8(bytes: &'a [u8]) -> Result { str::from_utf8(bytes) } } impl<'a> FromUtf8<'a> for String { fn from_utf8(bytes: &'a [u8]) -> Result { String::from_utf8(bytes.to_vec()).map_err(|e| e.utf8_error()) } } impl<'a> FromUtf8<'a> for Cow<'a, str> { fn from_utf8(bytes: &'a [u8]) -> Result { str::from_utf8(bytes).map(Into::into) } } #[test] fn ok_from_valid_utf8<'a, T>() -> Result<(), Utf8Error> where T: FromUtf8<'a> + AsRef + Debug, { let v = T::from_utf8(b"Hello, world!")?; assert_eq!(v.as_ref(), "Hello, world!"); Ok(()) } #[instantiate_tests(<&'static str>)] mod str_slice {} #[instantiate_tests()] mod string {} #[instantiate_tests(>)] mod cow {} } #[generic_tests::define] mod nested { use std::fmt::{self, Display}; #[test] fn print() { let v = T::default(); println!("{}", v); } #[derive(Default)] struct Foo; impl Display for Foo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Foo") } } mod from_prelude { #[instantiate_tests()] mod string {} } mod imported { use std::borrow::Cow; #[instantiate_tests(>)] mod cow {} } mod locally_defined { use std::fmt::{self, Display}; #[derive(Default)] struct Bar; impl Display for Bar { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Bar") } } #[instantiate_tests()] mod bar {} } mod aliases_root { use super::Foo; #[instantiate_tests()] mod foo {} } mod shadows_root { use std::fmt::{self, Display}; #[derive(Default)] struct Foo; impl Display for Foo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "nested Foo") } } #[instantiate_tests()] mod foo {} } } #[generic_tests::define] mod modifier_attrs { #[test] #[ignore] fn ignore() { panic!("tests instantiated from this function should not be run") } #[test] #[ignore = "tests the macro works in presence of attribute content"] fn ignore_with_reason() { panic!("tests instantiated from this function should not be run") } #[ignore] #[test] fn ignore_above() { panic!("tests instantiated from this function should not be run") } #[test] #[should_panic] fn should_panic() { panic!("panicking as it should") } #[test] #[should_panic(expected = "panicking as it should")] fn should_panic_with_expected() { panic!("panicking as it should") } #[test] #[ignore] #[should_panic] fn ignore_should_panic() { // Does not panic, so should be ignored } #[instantiate_tests(<()>)] mod inst {} } #[generic_tests::define] mod cfg_attr { #[cfg(test)] #[test] fn enabled() {} #[cfg(not(test))] #[test] fn disabled_above() { panic!("unexpectedly enabled") } #[test] #[cfg(not(test))] fn disabled_below() { panic!("unexpectedly enabled") } // This should not be instantiated. If it is, it will trigger // the dead_code lint in the instantiation module. #[allow(dead_code)] #[cfg(test)] fn not_a_test_case() {} #[deny(dead_code)] #[instantiate_tests(<()>)] mod inst {} } // To test how custom attributes work, abuse the system by listing `allow` // as a test attribute. // A function annotated with `allow` should get instantiated, and the // `allow` attribute on the original function should get erased. This // does not trigger the dead code lint, though, because the instantiated // "test" function calls the generic one and itself sports the `allow` attribute // disabling the lint. #[generic_tests::define(attrs(allow, test, should_panic))] #[deny(dead_code)] mod custom_test_attrs { #[allow(dead_code)] fn custom_sig_with_builtin_types(input: i32) -> String { input.to_string() } struct Foo; struct Bar; #[allow(dead_code)] fn custom_sig_with_locally_defined_types(_input: Foo) -> Bar { Bar } #[test] fn test_attr_works_too_when_listed() {} #[test] #[should_panic] fn two_test_attrs_listed() { panic!("panicking as it should"); } #[instantiate_tests(<()>)] mod inst {} } #[generic_tests::define(attrs(allow))] mod custom_attrs_override_test { #[allow(dead_code)] fn foo() {} #[instantiate_tests(<()>)] mod inst {} #[test] fn test_is_not_instantiated() {} } #[generic_tests::define(copy_attrs(doc, cfg_attr))] mod custom_copy_attrs { /// This illustrates how doc comments can be copied /// onto the instantiated tests. #[test] fn copy_doc_attrs() {} /// This should not be instantiated. If it is, it will trigger /// the dead_code lint in the instantiation module. #[allow(dead_code)] fn not_a_test_case_but_has_doc() {} #[cfg_attr(test, doc = "This should not be instantiated")] #[allow(dead_code)] fn not_a_test_case_but_has_cfg_attr() {} #[test] #[cfg_attr(test, should_panic)] #[allow(unused_attributes)] fn custom_attr_gets_copied_to_instantiation() { panic!("panicking as it should"); } #[instantiate_tests(<()>)] #[deny(dead_code)] mod inst {} } mod fn_level_attr { #[generic_tests::define] mod macro_level_defaults { #[generic_test(attrs(test, cfg_attr))] #[test] #[cfg_attr(test, should_panic)] fn custom_inst_attrs() { panic!("panicking as it should"); } #[generic_test(copy_attrs(cfg_attr))] #[test] #[cfg_attr(test, should_panic)] #[allow(unused_attributes)] fn custom_copy_attrs() { panic!("panicking as it should"); } #[generic_test(copy_attrs())] #[test] #[cfg(not(test))] fn copy_attrs_overrides_default() {} #[cfg(test)] fn copy_attrs_overrides_default() {} #[instantiate_tests(<()>)] mod inst {} } #[generic_tests::define(attrs(allow), copy_attrs(cfg_attr))] mod macro_level_custom { #[generic_test(attrs(test))] #[test] fn custom_inst_attrs() {} #[generic_test(attrs(test))] #[test] #[cfg_attr(test, should_panic)] #[allow(unused_attributes)] fn custom_inst_attrs_mod_level_copy_attrs() { panic!("panicking as it should"); } #[generic_test(copy_attrs(cfg))] #[allow()] #[cfg(not(test))] fn custom_copy_attrs() { panic!("should be disabled"); } #[instantiate_tests(<()>)] mod inst {} } } #[generic_tests::define(attrs(allow))] #[allow(clippy::needless_lifetimes)] mod lifetimes_in_signature { struct Borrowed<'a> { #[allow(dead_code)] a: &'a str, } #[allow(dead_code)] fn elided_in_input(_s: &str) {} #[allow(dead_code)] fn explicit_in_input<'a, T>(_s: &'a str) {} #[allow(dead_code)] fn elided_and_explicit_type_param_in_input<'b, T>(_s: &str, _b: Borrowed<'b>) {} #[allow(dead_code)] fn two_args_sharing_a_lifetime<'b, T>(s: &'b str, mut b: Borrowed<'b>) { b.a = s; } #[allow(dead_code)] fn two_args_sharing_a_lifetime_one_also_elides<'b, T>(s: &'b str, b: &mut Borrowed<'b>) { b.a = s; } #[allow(dead_code)] fn explicit_in_input_placeholder_in_output<'a, T>(a: &'a str) -> Borrowed<'_> { Borrowed { a } } #[allow(dead_code)] fn elided_in_input_placeholder_in_output(a: &str) -> Borrowed<'_> { Borrowed { a } } #[allow(dead_code)] fn one_explicit_other_elided<'a, T>(a: &'a str, _b: &str) -> Borrowed<'a> { Borrowed { a } } #[allow(dead_code)] fn two_explicit<'a, 'b, T>(_a: &'a str, b: &'b str) -> Borrowed<'b> { Borrowed { a: b } } #[instantiate_tests(<()>)] mod inst {} } #[generic_tests::define(attrs(allow))] mod mut_in_signature { #[allow(dead_code)] fn mut_is_erased_in_instantiation(mut a: i32) { a += 1; let _ = a; } #[deny(unused_mut)] #[instantiate_tests(<()>)] mod inst {} } // Use a stand-in attribute because standard test does not allow unsafe #[generic_tests::define(attrs(inline))] mod unsafe_fn { #[inline] #[allow(dead_code)] unsafe fn unsafe_fn() {} #[instantiate_tests(<()>)] mod inst {} }