Skip to content

Commit 87a1127

Browse files
committed
fix: Prevent combinatorial explosion in test_parse
1 parent 52d87e6 commit 87a1127

2 files changed

Lines changed: 22 additions & 75 deletions

File tree

crates/libtest2/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub mod _private {
6060
pub use libtest2_harness::TestKind;
6161

6262
pub use crate::_main_parse as main_parse;
63+
pub use crate::_parse_ignore as parse_ignore;
6364
pub use crate::_test_parse as test_parse;
6465
pub use crate::case::DynCase;
6566
}

crates/libtest2/src/macros.rs

Lines changed: 21 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -26,72 +26,35 @@ macro_rules! _test_parse {
2626
};
2727

2828
// Recursively handle attributes
29-
(name=$name:ident body=[$($item:tt)*] unparsed_attrs=[] parsed_attrs=[$(#[$parsed_attr:meta])*] $(ignore=$state:expr)?) => {
29+
(name=$name:ident body=[$($item:tt)*] unparsed_attrs=[] parsed_attrs=[$(#[$parsed_attr:meta])*] $(ignore=$ignore:tt)?) => {
3030
$crate::_private::test_parse! {
3131
name=$name
3232
body=[$($item)*]
3333
attrs=[$(#[$parsed_attr])*]
34-
$(ignore=$state)?
34+
$(ignore=$ignore)?
3535
}
3636
};
37-
(name=$name:ident body=[$($item:tt)*] unparsed_attrs=[#[ignore] $(#[$($unparsed_attr:tt)+])*] parsed_attrs=[$(#[$parsed_attr:meta])*] $(ignore=$state:expr)?) => {
37+
(name=$name:ident body=[$($item:tt)*] unparsed_attrs=[#[ignore $(= $reason:literal)?] $(#[$($unparsed_attr:tt)+])*] parsed_attrs=[$(#[$parsed_attr:meta])*] $(ignore=$ignore:tt)?) => {
3838
$crate::_private::test_parse! {
3939
name=$name
4040
body=[$($item)*]
4141
unparsed_attrs=[$(#[$($unparsed_attr)*])*]
4242
parsed_attrs=[$(#[$parsed_attr])*]
43-
ignore=()
43+
ignore=[$($reason)?]
4444
}
4545
};
46-
(name=$name:ident body=[$($item:tt)*] unparsed_attrs=[#[ignore = $reason:literal] $(#[$($unparsed_attr:tt)+])*] parsed_attrs=[$(#[$parsed_attr:meta])*] $(ignore=$state:expr)?) => {
47-
$crate::_private::test_parse! {
48-
name=$name
49-
body=[$($item)*]
50-
unparsed_attrs=[$(#[$($unparsed_attr)*])*]
51-
parsed_attrs=[$(#[$parsed_attr])*]
52-
ignore=$reason
53-
}
54-
};
55-
(name=$name:ident body=[$($item:tt)*] unparsed_attrs=[#[$($attr:tt)+] $(#[$($unparsed_attr:tt)+])*] parsed_attrs=[$(#[$parsed_attr:meta])*] $(ignore=$state:expr)?) => {
46+
(name=$name:ident body=[$($item:tt)*] unparsed_attrs=[#[$($attr:tt)+] $(#[$($unparsed_attr:tt)+])*] parsed_attrs=[$(#[$parsed_attr:meta])*] $(ignore=$ignore:tt)?) => {
5647
$crate::_private::test_parse! {
5748
name=$name
5849
body=[$($item)*]
5950
unparsed_attrs=[$(#[$($unparsed_attr)*])*]
6051
parsed_attrs=[#[$($attr)* $(#[$($parsed_attr)*])*]]
61-
$(ignore=$state)?
52+
$(ignore=$ignore)?
6253
}
6354
};
6455

6556
// End result
66-
(name=$name:ident body=[$($item:tt)*] attrs=[$(#[$attr:meta])*]) => {
67-
#[allow(non_camel_case_types)]
68-
struct $name;
69-
70-
impl $crate::_private::Case for $name {
71-
fn name(&self) -> &str {
72-
$crate::_private::push!(crate::TESTS, _: $crate::_private::DynCase = $crate::_private::DynCase(&$name));
73-
74-
stringify!($name)
75-
}
76-
fn kind(&self) -> $crate::_private::TestKind {
77-
Default::default()
78-
}
79-
fn source(&self) -> Option<&$crate::_private::Source> {
80-
None
81-
}
82-
fn exclusive(&self, _: &$crate::TestContext) -> bool {
83-
false
84-
}
85-
86-
fn run(&self, context: &$crate::TestContext) -> $crate::RunResult {
87-
$(#[$attr])*
88-
fn run $($item)*
89-
90-
run(context)
91-
}
92-
}
93-
};
94-
(name=$name:ident body=[$($item:tt)*] attrs=[$(#[$attr:meta])*] ignore=$reason:literal) => {
57+
(name=$name:ident body=[$($item:tt)*] attrs=[$(#[$attr:meta])*] $(ignore=$ignore:tt)?) => {
9558
#[allow(non_camel_case_types)]
9659
struct $name;
9760

@@ -115,37 +78,9 @@ macro_rules! _test_parse {
11578
$(#[$attr])*
11679
fn run $($item)*
11780

118-
context.ignore_for($reason)?;
119-
120-
run(context)
121-
}
122-
}
123-
};
124-
(name=$name:ident body=[$($item:tt)*] attrs=[$(#[$attr:meta])*] ignore=$unused:expr) => {
125-
#[allow(non_camel_case_types)]
126-
struct $name;
127-
128-
impl $crate::_private::Case for $name {
129-
fn name(&self) -> &str {
130-
$crate::_private::push!(crate::TESTS, _: $crate::_private::DynCase = $crate::_private::DynCase(&$name));
131-
132-
stringify!($name)
133-
}
134-
fn kind(&self) -> $crate::_private::TestKind {
135-
Default::default()
136-
}
137-
fn source(&self) -> Option<&$crate::_private::Source> {
138-
None
139-
}
140-
fn exclusive(&self, _: &$crate::TestContext) -> bool {
141-
false
142-
}
143-
144-
fn run(&self, context: &$crate::TestContext) -> $crate::RunResult {
145-
$(#[$attr])*
146-
fn run $($item)*
147-
148-
context.ignore()?;
81+
$(
82+
$crate::_private::parse_ignore!($ignore, context)?;
83+
)?
14984

15085
use $crate::IntoRunResult;
15186
let result = run(context);
@@ -154,3 +89,14 @@ macro_rules! _test_parse {
15489
}
15590
};
15691
}
92+
93+
#[macro_export]
94+
#[doc(hidden)]
95+
macro_rules! _parse_ignore {
96+
([$reason:literal], $context:expr) => {
97+
$context.ignore_for($reason)
98+
};
99+
([], $context:expr) => {
100+
$context.ignore()
101+
};
102+
}

0 commit comments

Comments
 (0)