@@ -331,8 +331,9 @@ fn eval_single_state_success_fires_action() {
331331fn eval_single_state_success_inactive_no_action ( ) {
332332 let id = 42 ;
333333 let version = 1 ;
334- let data = Evidence :: Numerical ( 0.88f64 ) ;
335- let causaloid = test_utils:: get_test_causaloid ( ) ; // Returns Deterministic(false) for data > 0.5
334+ // Use data that makes the state inactive (0.23 < 0.55 threshold)
335+ let data = Evidence :: Numerical ( 0.23f64 ) ;
336+ let causaloid = test_utils:: get_test_causaloid ( ) ; // Returns Deterministic(false)
336337
337338 let cs = CausalState :: new ( id, version, data, causaloid) ;
338339 // Use an action that would fail to prove it's not being called.
@@ -341,10 +342,11 @@ fn eval_single_state_success_inactive_no_action() {
341342 let csm = CSM :: new ( state_action) ;
342343
343344 // Data that makes the state inactive
344- let eval_data = test_utils:: get_test_single_data ( 0.88f64 ) ;
345+ let eval_data = test_utils:: get_test_single_data ( 0.23f64 ) ;
345346 // Use the correct ID
346347 let res = csm. eval_single_state ( id, eval_data) ;
347- assert ! ( res. is_err( ) ) ;
348+ // Should be Ok because the state is inactive, so the failing action is never fired.
349+ assert ! ( res. is_ok( ) ) ;
348350}
349351
350352// Test for the case where the state does not exist.
@@ -366,3 +368,157 @@ fn eval_single_state_error_not_found() {
366368 assert ! ( res. is_err( ) ) ;
367369 assert ! ( res. unwrap_err( ) . 0 . contains( "State 99 does not exist" ) ) ;
368370}
371+
372+ // This test covers the case where the state evaluation itself fails.
373+ // It adds coverage for the branch you identified.
374+ #[ test]
375+ fn eval_single_state_error_eval_fails ( ) {
376+ let id = 42 ;
377+ let version = 1 ;
378+ let data = Evidence :: Numerical ( 0.23f64 ) ;
379+ // This causaloid's causal_fn always returns an error.
380+ let causaloid = get_test_error_causaloid ( ) ;
381+
382+ let cs = CausalState :: new ( id, version, data, causaloid) ;
383+ let ca = get_test_action ( ) ; // Action won't be reached
384+ let state_action = & [ ( & cs, & ca) ] ;
385+ let csm = CSM :: new ( state_action) ;
386+
387+ let eval_data = test_utils:: get_test_single_data ( 0.23f64 ) ;
388+ // Use the correct ID to ensure we get past the 'not found' check.
389+ let res = csm. eval_single_state ( id, eval_data) ;
390+
391+ // The result should be an error because state.eval_with_data failed.
392+ assert ! ( res. is_err( ) ) ;
393+ let err_msg = res. unwrap_err ( ) . 0 ;
394+ assert ! ( err_msg. contains( & format!( "CSM[eval]: Error evaluating state {id}" ) ) ) ;
395+ }
396+
397+ // This test covers the case where the action fails to fire.
398+ #[ test]
399+ fn eval_single_state_error_action_fails ( ) {
400+ let id = 42 ;
401+ let version = 1 ;
402+ // Use data that makes the state active (0.60 > 0.55 threshold in test_causaloid)
403+ let data = Evidence :: Numerical ( 0.60f64 ) ;
404+ let causaloid = test_utils:: get_test_causaloid ( ) ; // Returns Deterministic(true)
405+
406+ let cs = CausalState :: new ( id, version, data, causaloid) ;
407+ // Use an action that is designed to fail.
408+ let ca = get_test_error_action ( ) ;
409+ let state_action = & [ ( & cs, & ca) ] ;
410+ let csm = CSM :: new ( state_action) ;
411+
412+ // Data that will make the state active
413+ let eval_data = test_utils:: get_test_single_data ( 0.60f64 ) ;
414+ // Use the correct ID
415+ let res = csm. eval_single_state ( id, eval_data) ;
416+
417+ assert ! ( res. is_err( ) ) ;
418+ let err_msg = res. unwrap_err ( ) . 0 ;
419+ assert ! ( err_msg. contains( & format!(
420+ "CSM[eval]: Failed to fire action for state {id}"
421+ ) ) ) ;
422+ }
423+
424+ // I've renamed the original test to be more descriptive.
425+ // It correctly tests the success path where a state is inactive.
426+ #[ test]
427+ fn eval_all_states_success_inactive_state ( ) {
428+ let id = 42 ;
429+ let version = 1 ;
430+ // Data that makes the state inactive (0.23 < 0.55 threshold)
431+ let data = test_utils:: get_test_single_data ( 0.23f64 ) ;
432+ let causaloid = test_utils:: get_test_causaloid ( ) ;
433+
434+ let cs = CausalState :: new ( id, version, data, causaloid) ;
435+ let ca = get_test_action ( ) ;
436+ let state_action = & [ ( & cs, & ca) ] ;
437+ let csm = CSM :: new ( state_action) ;
438+
439+ let res = csm. eval_all_states ( ) ;
440+ assert ! ( res. is_ok( ) )
441+ }
442+
443+ // New test for the success path where a state is active and the action fires.
444+ #[ test]
445+ fn eval_all_states_success_active_state_fires_action ( ) {
446+ let id = 42 ;
447+ let version = 1 ;
448+ // Data that makes the state active (0.6 > 0.55 threshold)
449+ let data = Evidence :: Numerical ( 0.60f64 ) ;
450+ let causaloid = test_utils:: get_test_causaloid ( ) ; // Returns Deterministic(true)
451+
452+ let cs = CausalState :: new ( id, version, data, causaloid) ;
453+ let ca = get_test_action ( ) ; // Succeeds
454+ let state_action = & [ ( & cs, & ca) ] ;
455+ let csm = CSM :: new ( state_action) ;
456+
457+ let res = csm. eval_all_states ( ) ;
458+ assert ! ( res. is_ok( ) ) ;
459+ }
460+
461+ // New test for the first error branch: state evaluation fails.
462+ #[ test]
463+ fn eval_all_states_error_eval_fails ( ) {
464+ let id = 42 ;
465+ let version = 1 ;
466+ let data = Evidence :: Numerical ( 0.23f64 ) ;
467+ // This causaloid's causal_fn always returns an error.
468+ let causaloid = get_test_error_causaloid ( ) ;
469+
470+ let cs = CausalState :: new ( id, version, data, causaloid) ;
471+ let ca = get_test_action ( ) ; // Action won't be reached
472+ let state_action = & [ ( & cs, & ca) ] ;
473+ let csm = CSM :: new ( state_action) ;
474+
475+ let res = csm. eval_all_states ( ) ;
476+
477+ assert ! ( res. is_err( ) ) ;
478+ let err_msg = res. unwrap_err ( ) . 0 ;
479+ assert ! ( err_msg. contains( & format!( "CSM[eval]: Error evaluating state {id}" ) ) ) ;
480+ }
481+
482+ // New test for the second error branch: action firing fails.
483+ #[ test]
484+ fn eval_all_states_error_action_fails ( ) {
485+ let id = 42 ;
486+ let version = 1 ;
487+ // Use data that makes the state active (0.60 > 0.55 threshold)
488+ let data = Evidence :: Numerical ( 0.60f64 ) ;
489+ let causaloid = test_utils:: get_test_causaloid ( ) ; // Returns Deterministic(true)
490+
491+ let cs = CausalState :: new ( id, version, data, causaloid) ;
492+ // Use an action that is designed to fail.
493+ let ca = get_test_error_action ( ) ;
494+ let state_action = & [ ( & cs, & ca) ] ;
495+ let csm = CSM :: new ( state_action) ;
496+
497+ let res = csm. eval_all_states ( ) ;
498+
499+ assert ! ( res. is_err( ) ) ;
500+ let err_msg = res. unwrap_err ( ) . 0 ;
501+ assert ! ( err_msg. contains( & format!(
502+ "CSM[eval]: Failed to fire action for state {id}"
503+ ) ) ) ;
504+ }
505+
506+ // New test for the third error branch: non-deterministic effect.
507+ #[ test]
508+ fn eval_all_states_error_non_deterministic ( ) {
509+ let id = 42 ;
510+ let version = 1 ;
511+ let data = Evidence :: Numerical ( 0.23f64 ) ;
512+ let causaloid = get_test_probabilistic_causaloid ( ) ;
513+
514+ let cs = CausalState :: new ( id, version, data, causaloid) ;
515+ let ca = get_test_action ( ) ;
516+ let state_action = & [ ( & cs, & ca) ] ;
517+ let csm = CSM :: new ( state_action) ;
518+
519+ let res = csm. eval_all_states ( ) ;
520+ assert ! ( res. is_err( ) ) ;
521+ let err_msg = res. unwrap_err ( ) . 0 ;
522+ assert ! ( err_msg. contains( "Invalid non-deterministic effect" ) ) ;
523+ assert ! ( err_msg. contains( & format!( "for state {id}" ) ) ) ;
524+ }
0 commit comments