@@ -49,7 +49,7 @@ macro_rules! defensive {
4949 ) ;
5050 debug_assert!( false , "{}" , $crate:: traits:: DEFENSIVE_OP_INTERNAL_ERROR ) ;
5151 } ;
52- ( $error: tt ) => {
52+ ( $error: expr $ ( , ) ? ) => {
5353 frame_support:: log:: error!(
5454 target: "runtime" ,
5555 "{}: {:?}" ,
@@ -58,7 +58,7 @@ macro_rules! defensive {
5858 ) ;
5959 debug_assert!( false , "{}: {:?}" , $crate:: traits:: DEFENSIVE_OP_INTERNAL_ERROR , $error) ;
6060 } ;
61- ( $error: tt , $proof: tt ) => {
61+ ( $error: expr , $proof: expr $ ( , ) ? ) => {
6262 frame_support:: log:: error!(
6363 target: "runtime" ,
6464 "{}: {:?}: {:?}" ,
@@ -70,6 +70,25 @@ macro_rules! defensive {
7070 }
7171}
7272
73+ /// Trigger a defensive failure if a condition is not met.
74+ ///
75+ /// Similar to [`assert!`] but will print an error without `debug_assertions` instead of silently
76+ /// ignoring it. Only accepts one instead of variable formatting arguments.
77+ ///
78+ /// # Example
79+ ///
80+ /// ```should_panic
81+ /// frame_support::defensive_assert!(1 == 0, "Must fail")
82+ /// ```
83+ #[ macro_export]
84+ macro_rules! defensive_assert {
85+ ( $cond: expr $( , $proof: expr ) ? $( , ) ?) => {
86+ if !( $cond) {
87+ $crate:: defensive!( :: core:: stringify!( $cond) $( , $proof ) ?) ;
88+ }
89+ } ;
90+ }
91+
7392/// Prelude module for all defensive traits to be imported at once.
7493pub mod defensive_prelude {
7594 pub use super :: { Defensive , DefensiveOption , DefensiveResult } ;
@@ -1141,6 +1160,27 @@ mod test {
11411160 use sp_core:: bounded:: { BoundedSlice , BoundedVec } ;
11421161 use sp_std:: marker:: PhantomData ;
11431162
1163+ #[ test]
1164+ fn defensive_assert_works ( ) {
1165+ defensive_assert ! ( true ) ;
1166+ defensive_assert ! ( true , ) ;
1167+ defensive_assert ! ( true , "must work" ) ;
1168+ defensive_assert ! ( true , "must work" , ) ;
1169+ }
1170+
1171+ #[ test]
1172+ #[ cfg( debug_assertions) ]
1173+ #[ should_panic( expected = "Defensive failure has been triggered!: \" 1 == 0\" : \" Must fail\" " ) ]
1174+ fn defensive_assert_panics ( ) {
1175+ defensive_assert ! ( 1 == 0 , "Must fail" ) ;
1176+ }
1177+
1178+ #[ test]
1179+ #[ cfg( not( debug_assertions) ) ]
1180+ fn defensive_assert_does_not_panic ( ) {
1181+ defensive_assert ! ( 1 == 0 , "Must fail" ) ;
1182+ }
1183+
11441184 #[ test]
11451185 #[ cfg( not( debug_assertions) ) ]
11461186 fn defensive_saturating_accrue_works ( ) {
0 commit comments