@@ -268,12 +268,14 @@ mod tests {
268268 use crate :: handler:: argument:: Argument ;
269269 use crate :: handler:: registry:: { FunctionRegistration , FunctionStore , ThunkRunner } ;
270270 use crate :: runtime:: execution:: value_store:: ValueStore ;
271+ use crate :: runtime:: remote:: { RemoteExecution , RemoteRuntime } ;
271272 use crate :: types:: exit_reason:: ExitReason ;
273+ use async_trait:: async_trait;
272274 use std:: cell:: RefCell ;
273275 use std:: time:: Duration ;
274276 use tucana:: shared:: {
275- InputType , ListValue , NodeParameter , NodeValue , ReferenceValue , Struct , SubFlow ,
276- SubFlowSetting , Value , node_execution_result, node_value, reference_value,
277+ InputType , ListValue , NodeExecutionResult , NodeParameter , NodeValue , ReferenceValue ,
278+ Struct , SubFlow , SubFlowSetting , Value , node_execution_result, node_value, reference_value,
277279 sub_flow:: ExecutionReference , value:: Kind ,
278280 } ;
279281
@@ -418,6 +420,22 @@ mod tests {
418420 Signal :: Success ( null_value ( ) )
419421 }
420422
423+ #[ derive( Clone ) ]
424+ struct StubRemoteRuntime {
425+ result : NodeExecutionResult ,
426+ }
427+
428+ #[ async_trait]
429+ impl RemoteRuntime for StubRemoteRuntime {
430+ async fn execute_remote (
431+ & self ,
432+ _execution : RemoteExecution ,
433+ ) -> Result < NodeExecutionResult , crate :: types:: errors:: runtime_error:: RuntimeError >
434+ {
435+ Ok ( self . result . clone ( ) )
436+ }
437+ }
438+
421439 fn input_type_ref_param (
422440 database_id : i64 ,
423441 runtime_parameter_id : & str ,
@@ -938,6 +956,49 @@ mod tests {
938956 ) ) ;
939957 }
940958
959+ #[ test]
960+ fn remote_execution_report_converts_missing_outcome_to_node_error ( ) {
961+ let engine = ExecutionEngine :: new ( ) ;
962+ let remote = StubRemoteRuntime {
963+ result : NodeExecutionResult {
964+ node_id : 99 ,
965+ started_at : 1 ,
966+ finished_at : 2 ,
967+ parameter_results : Vec :: new ( ) ,
968+ result : None ,
969+ } ,
970+ } ;
971+ let mut remote_node = node (
972+ 1 ,
973+ "remote::missing_outcome" ,
974+ vec ! [ literal_param( 100 , "payload" , int_value( 20 ) ) ] ,
975+ None ,
976+ ) ;
977+ remote_node. definition_source = Some ( "remote-service" . to_string ( ) ) ;
978+
979+ let report =
980+ engine. execute_graph_report ( 1 , vec ! [ remote_node] , None , Some ( & remote) , None , false ) ;
981+
982+ assert_eq ! ( report. exit_reason, ExitReason :: Failure ) ;
983+ match report. signal {
984+ Signal :: Failure ( err) => assert_eq ! ( err. code, "T-CORE-000006" ) ,
985+ other => panic ! ( "expected missing-outcome failure, got {:?}" , other) ,
986+ }
987+ assert_eq ! ( report. node_execution_results. len( ) , 1 ) ;
988+
989+ let node_result = & report. node_execution_results [ 0 ] ;
990+ assert_eq ! ( node_result. node_id, 1 ) ;
991+ assert_eq ! ( node_result. parameter_results. len( ) , 1 ) ;
992+ assert_eq ! ( node_result. parameter_results[ 0 ] . value, Some ( int_value( 20 ) ) ) ;
993+ match node_result. result . as_ref ( ) {
994+ Some ( node_execution_result:: Result :: Error ( error) ) => {
995+ assert_eq ! ( error. code, "T-CORE-000006" ) ;
996+ assert_eq ! ( error. category, "NodeExecutionResultMissingOutcome" ) ;
997+ }
998+ other => panic ! ( "expected node error result, got {:?}" , other) ,
999+ }
1000+ }
1001+
9411002 #[ test]
9421003 fn node_execution_result_tracks_actual_node_duration ( ) {
9431004 let mut handlers = FunctionStore :: new ( ) ;
0 commit comments