@@ -14,7 +14,7 @@ macro_rules! _main_parse {
1414}
1515
1616#[ macro_export]
17- #[ allow( clippy:: crate_in_macro_def) ] // accessing item defined by `_main_parse`/`_parse_ignore`, and recursively calling the macro itself
17+ #[ allow( clippy:: crate_in_macro_def) ] // accessing item defined by `_main_parse`/`_parse_ignore`/`_run_test` , and recursively calling the macro itself
1818macro_rules! _test_parse {
1919 // Entry point
2020 ( #[ test] $( #[ $( $attr: tt) +] ) * fn $name: ident $( $item: tt) * ) => {
@@ -28,20 +28,22 @@ macro_rules! _test_parse {
2828 // Recursively handle attributes:
2929
3030 // Edge condition (no more attributes to parse)
31- ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ ] $( ignore=$ignore: tt) ?) => {
31+ ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ ] $( ignore=$ignore: tt) ? $ ( should_panic=$should_panic : tt ) ? ) => {
3232 $crate:: _private:: test_parse!( break :
3333 name=$name
3434 body=[ $( $item) * ]
3535 $( ignore=$ignore) ?
36+ $( should_panic=$should_panic) ?
3637 ) ;
3738 } ;
3839 // Process `#[ignore]`/`#[ignore = ".."]` (NOTE: This will only match if an ignore macro has not already been parsed)
39- ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ #[ ignore $( = $reason: literal) ?] $( #[ $( $attr: tt) +] ) * ] ) => {
40+ ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ #[ ignore $( = $reason: literal) ?] $( #[ $( $attr: tt) +] ) * ] $ ( should_panic=$should_panic : tt ) ? ) => {
4041 $crate:: _private:: test_parse!( continue :
4142 name=$name
4243 body=[ $( $item) * ]
4344 attrs=[ $( #[ $( $attr) * ] ) * ]
4445 ignore=[ $( $reason) ?]
46+ $( should_panic=$should_panic) ?
4547 ) ;
4648 } ;
4749 // Ignore subsequent calls to `#[ignore]`/`#[ignore = ".."]`
@@ -53,19 +55,51 @@ macro_rules! _test_parse {
5355 ignore=$ignore
5456 ) ;
5557 } ;
58+ // Process `#[should_panic]`/`#[should_panic = ".."]` (NOTE: This will only match if a should_panic macro has not already been parsed)
59+ ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ #[ should_panic $( = $expected: literal) ?] $( #[ $( $attr: tt) +] ) * ] $( ignore=$ignore: tt) ?) => {
60+ $crate:: _private:: test_parse!( continue :
61+ name=$name
62+ body=[ $( $item) * ]
63+ attrs=[ $( #[ $( $attr) * ] ) * ]
64+ $( ignore=$ignore) ?
65+ should_panic=[ $( $expected) ?]
66+ ) ;
67+ } ;
68+ // Process `#[should_panic(expected = "..")]` (NOTE: Same as branch above)
69+ ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ #[ should_panic( expected = $expected: literal) ] $( #[ $( $attr: tt) +] ) * ] $( ignore=$ignore: tt) ?) => {
70+ $crate:: _private:: test_parse!( continue :
71+ name=$name
72+ body=[ $( $item) * ]
73+ attrs=[ $( #[ $( $attr) * ] ) * ]
74+ $( ignore=$ignore) ?
75+ should_panic=[ $expected]
76+ ) ;
77+ } ;
78+ // Emit an error for subsequent calls to `#[should_panic]`/`#[should_panic = ".."]`/`#[should_panic(expected = "..")]` (but continue parsing)
79+ ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ #[ should_panic $( $unused: tt) * ] $( #[ $( $attr: tt) +] ) * ] $( ignore=$ignore: tt) ? should_panic=$should_panic: tt) => {
80+ compile_error!( "annotating a test with multiple 'should_panic' attributes is not allowed" ) ;
81+ $crate:: _private:: test_parse!( continue :
82+ name=$name
83+ body=[ $( $item) * ]
84+ attrs=[ $( #[ $( $attr) * ] ) * ]
85+ $( ignore=$ignore) ?
86+ should_panic=$should_panic
87+ ) ;
88+ } ;
5689 // Emit error on unknown attributes (but continue parsing)
57- ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ #[ $( $unknown_attr: tt) +] $( #[ $( $attr: tt) +] ) * ] $( ignore=$ignore: tt) ?) => {
90+ ( continue : name=$name: ident body=[ $( $item: tt) * ] attrs=[ #[ $( $unknown_attr: tt) +] $( #[ $( $attr: tt) +] ) * ] $( ignore=$ignore: tt) ? $ ( should_panic=$should_panic : tt ) ? ) => {
5891 compile_error!( concat!( "unknown attribute '" , stringify!( $( $unknown_attr) +) , "'" ) ) ;
5992 $crate:: _private:: test_parse!( continue :
6093 name=$name
6194 body=[ $( $item) * ]
6295 attrs=[ $( #[ $( $attr) * ] ) * ]
6396 $( ignore=$ignore) ?
97+ $( should_panic=$should_panic) ?
6498 ) ;
6599 } ;
66100
67101 // End result
68- ( break : name=$name: ident body=[ $( $item: tt) * ] $( ignore=$ignore: tt) ?) => {
102+ ( break : name=$name: ident body=[ $( $item: tt) * ] $( ignore=$ignore: tt) ? $ ( should_panic=$should_panic : tt ) ? ) => {
69103 #[ allow( non_camel_case_types) ]
70104 struct $name;
71105
@@ -91,7 +125,7 @@ macro_rules! _test_parse {
91125 $crate:: _private:: parse_ignore!( context, $( $ignore) ?) ;
92126
93127 use $crate:: IntoRunResult ;
94- let result = run ( context) ;
128+ let result = $crate :: _private :: run_test! ( context, $ ( $should_panic ) ? ) ;
95129 IntoRunResult :: into_run_result( result)
96130 }
97131 }
@@ -108,3 +142,16 @@ macro_rules! _parse_ignore {
108142 } ;
109143 ( $context: expr $( , ) ?) => { } ;
110144}
145+
146+ #[ macro_export]
147+ macro_rules! _run_test {
148+ ( $context: expr, [ $expected: literal] ) => {
149+ $crate:: panic:: assert_panic_contains( || run( $context) , $expected)
150+ } ;
151+ ( $context: expr, [ ] ) => {
152+ $crate:: panic:: assert_panic( || run( $context) )
153+ } ;
154+ ( $context: expr $( , ) ?) => { {
155+ run( $context)
156+ } } ;
157+ }
0 commit comments