@@ -265,8 +265,12 @@ impl ExecutionEngine {
265265#[ cfg( test) ]
266266mod tests {
267267 use super :: * ;
268+ use crate :: handler:: argument:: Argument ;
269+ use crate :: handler:: registry:: { FunctionRegistration , FunctionStore , ThunkRunner } ;
270+ use crate :: runtime:: execution:: value_store:: ValueStore ;
268271 use crate :: types:: exit_reason:: ExitReason ;
269272 use std:: cell:: RefCell ;
273+ use std:: time:: Duration ;
270274 use tucana:: shared:: {
271275 InputType , ListValue , NodeParameter , NodeValue , ReferenceValue , Struct , SubFlow ,
272276 SubFlowSetting , Value , node_execution_result, node_value, reference_value,
@@ -405,6 +409,15 @@ mod tests {
405409 }
406410 }
407411
412+ fn sleep_handler (
413+ _args : & [ Argument ] ,
414+ _ctx : & mut ValueStore ,
415+ _run : & mut ThunkRunner < ' _ > ,
416+ ) -> Signal {
417+ std:: thread:: sleep ( Duration :: from_micros ( 2_000 ) ) ;
418+ Signal :: Success ( null_value ( ) )
419+ }
420+
408421 fn input_type_ref_param (
409422 database_id : i64 ,
410423 runtime_parameter_id : & str ,
@@ -925,6 +938,103 @@ mod tests {
925938 ) ) ;
926939 }
927940
941+ #[ test]
942+ fn node_execution_result_tracks_actual_node_duration ( ) {
943+ let mut handlers = FunctionStore :: new ( ) ;
944+ handlers. populate ( & [ FunctionRegistration :: eager ( "test::sleep" , sleep_handler, 0 ) ] ) ;
945+ let engine = ExecutionEngine { handlers } ;
946+ let sleep_node = node ( 1 , "test::sleep" , vec ! [ ] , None ) ;
947+
948+ let report = engine. execute_graph_report ( 1 , vec ! [ sleep_node] , None , None , None , false ) ;
949+
950+ assert_eq ! ( report. exit_reason, ExitReason :: Success ) ;
951+ assert_eq ! ( report. node_execution_results. len( ) , 1 ) ;
952+
953+ let node_result = & report. node_execution_results [ 0 ] ;
954+ assert_eq ! ( node_result. node_id, 1 ) ;
955+ assert ! ( node_result. started_at >= 1_000_000_000_000_000 ) ;
956+ assert ! ( node_result. finished_at > node_result. started_at) ;
957+ assert ! ( node_result. finished_at - node_result. started_at >= 1_000 ) ;
958+ }
959+
960+ #[ test]
961+ fn execution_report_keeps_every_for_each_callback_execution ( ) {
962+ let engine = ExecutionEngine :: new ( ) ;
963+ let for_each_node = node (
964+ 1 ,
965+ "std::list::for_each" ,
966+ vec ! [
967+ literal_param(
968+ 100 ,
969+ "list" ,
970+ list_value( vec![ int_value( 1 ) , int_value( 2 ) , int_value( 3 ) ] ) ,
971+ ) ,
972+ thunk_param( 101 , "consumer" , 2 ) ,
973+ ] ,
974+ None ,
975+ ) ;
976+ let callback_node = node (
977+ 2 ,
978+ "std::number::add" ,
979+ vec ! [
980+ input_type_ref_param( 200 , "first" , 1 , 1 , 0 ) ,
981+ literal_param( 201 , "second" , int_value( 2 ) ) ,
982+ ] ,
983+ None ,
984+ ) ;
985+
986+ let report = engine. execute_graph_report (
987+ 1 ,
988+ vec ! [ for_each_node, callback_node] ,
989+ None ,
990+ None ,
991+ None ,
992+ false ,
993+ ) ;
994+
995+ assert_eq ! ( report. exit_reason, ExitReason :: Success ) ;
996+ assert_eq ! ( report. node_execution_results. len( ) , 4 ) ;
997+
998+ let callback_results: Vec < _ > = report
999+ . node_execution_results
1000+ . iter ( )
1001+ . filter ( |result| result. node_id == 2 )
1002+ . collect ( ) ;
1003+ assert_eq ! ( callback_results. len( ) , 3 ) ;
1004+
1005+ let callback_values: Vec < _ > = callback_results
1006+ . iter ( )
1007+ . map ( |result| match result. result . as_ref ( ) {
1008+ Some ( node_execution_result:: Result :: Success ( value) ) => value. clone ( ) ,
1009+ other => panic ! ( "expected callback success result, got {:?}" , other) ,
1010+ } )
1011+ . collect ( ) ;
1012+
1013+ assert_eq ! (
1014+ callback_values,
1015+ vec![ int_value( 3 ) , int_value( 4 ) , int_value( 5 ) ]
1016+ ) ;
1017+ let callback_parameters: Vec < _ > = callback_results
1018+ . iter ( )
1019+ . map ( |result| {
1020+ result
1021+ . parameter_results
1022+ . iter ( )
1023+ . map ( |parameter| parameter. value . clone ( ) )
1024+ . collect :: < Vec < _ > > ( )
1025+ } )
1026+ . collect ( ) ;
1027+ assert_eq ! (
1028+ callback_parameters,
1029+ vec![
1030+ vec![ Some ( int_value( 1 ) ) , Some ( int_value( 2 ) ) ] ,
1031+ vec![ Some ( int_value( 2 ) ) , Some ( int_value( 2 ) ) ] ,
1032+ vec![ Some ( int_value( 3 ) ) , Some ( int_value( 2 ) ) ] ,
1033+ ]
1034+ ) ;
1035+ assert_eq ! ( report. node_execution_results[ 3 ] . node_id, 1 ) ;
1036+ }
1037+
9281038 #[ test]
9291039 fn emitter_emits_start_and_finish_for_successful_execution ( ) {
9301040 let engine = ExecutionEngine :: new ( ) ;
0 commit comments