@@ -36,12 +36,22 @@ pub fn with_transaction_result<R>(f: impl FnOnce() -> Result<R, DispatchError>)
3636 } )
3737}
3838
39+ /// Simulate execution of the supplied function in a new storage transaction.
40+ /// Changes to storage performed by the supplied function are always discarded.
41+ pub fn simulate_execution < R > ( f : impl FnOnce ( ) -> Result < R , DispatchError > ) -> Result < R , DispatchError > {
42+ with_transaction ( || {
43+ let res = f ( ) ;
44+ TransactionOutcome :: Rollback ( res)
45+ } )
46+ }
47+
3948#[ cfg( test) ]
4049mod tests {
4150 use super :: * ;
4251 use frame_support:: { assert_noop, assert_ok, decl_module, decl_storage} ;
4352 use sp_io:: TestExternalities ;
4453 use sp_runtime:: { DispatchError , DispatchResult } ;
54+ use sp_std:: result:: Result ;
4555
4656 pub trait Config : frame_system:: Config { }
4757
@@ -96,4 +106,36 @@ mod tests {
96106 assert_eq ! ( Map :: get( "val0" ) , 0 ) ;
97107 } ) ;
98108 }
109+
110+ #[ test]
111+ fn simulate_execution_works ( ) {
112+ TestExternalities :: default ( ) . execute_with ( || {
113+ assert_eq ! ( Value :: get( ) , 0 ) ;
114+ assert_eq ! ( Map :: get( "val0" ) , 0 ) ;
115+
116+ // Roll back on `Err`.
117+ assert_noop ! (
118+ simulate_execution( || -> DispatchResult {
119+ Value :: set( 99 ) ;
120+ Map :: insert( "val0" , 99 ) ;
121+ Err ( DispatchError :: Other ( "test" ) )
122+ } ) ,
123+ DispatchError :: Other ( "test" )
124+ ) ;
125+ assert_eq ! ( Value :: get( ) , 0 ) ;
126+ assert_eq ! ( Map :: get( "val0" ) , 0 ) ;
127+
128+ // Roll back on `Ok`, but returns `Ok` result.
129+ assert_ok ! (
130+ simulate_execution( || -> Result <u32 , DispatchError > {
131+ Value :: set( 99 ) ;
132+ Map :: insert( "val0" , 99 ) ;
133+ Ok ( 99 )
134+ } ) ,
135+ 99
136+ ) ;
137+ assert_eq ! ( Value :: get( ) , 0 ) ;
138+ assert_eq ! ( Map :: get( "val0" ) , 0 ) ;
139+ } ) ;
140+ }
99141}
0 commit comments