@@ -530,6 +530,11 @@ fn write_lines(writer: &mut Writer<Cursor<Vec<u8>>>, lines: &[Line]) {
530530 l. push_attribute ( ( "number" , number. to_string ( ) . as_ref ( ) ) ) ;
531531 l. push_attribute ( ( "hits" , hits. to_string ( ) . as_ref ( ) ) ) ;
532532 l. push_attribute ( ( "branch" , "true" ) ) ;
533+ l. push_attribute ( (
534+ "condition-coverage" ,
535+ format_condition_coverage ( conditions) . as_ref ( ) ,
536+ ) ) ;
537+
533538 writer. write_event ( Event :: Start ( l) ) . unwrap ( ) ;
534539
535540 let conditions_tag = "conditions" ;
@@ -562,6 +567,33 @@ fn write_lines(writer: &mut Writer<Cursor<Vec<u8>>>, lines: &[Line]) {
562567 . unwrap ( ) ;
563568}
564569
570+ fn format_condition_coverage ( conditions : & [ Condition ] ) -> String {
571+ let conditions_hit: f64 = conditions. iter ( ) . map ( |c| c. coverage ) . sum ( ) ;
572+ let num_conditions = conditions. len ( ) ;
573+ if num_conditions > 0 {
574+ format ! (
575+ "{:.0}% ({:.0}/{})" ,
576+ 100.0 * conditions_hit / num_conditions as f64 ,
577+ conditions_hit,
578+ num_conditions
579+ )
580+ } else {
581+ // It's unclear what this should be, so we set it to 100% to avoid potentially affecting results
582+ use std:: sync:: atomic:: { AtomicBool , Ordering :: SeqCst } ;
583+
584+ static HAVE_PRINTED_WARNING : AtomicBool = AtomicBool :: new ( false ) ;
585+ // Print a warning about symbolic links, but only once per grcov run.
586+ if HAVE_PRINTED_WARNING
587+ . compare_exchange ( false , true , SeqCst , SeqCst )
588+ . is_ok ( )
589+ {
590+ eprintln ! ( "Encountered a branch with zero conditions, returning 100% condition coverage as a precausion." ) ;
591+ }
592+
593+ "100% (0/0)" . to_owned ( )
594+ }
595+ }
596+
565597#[ cfg( test) ]
566598mod tests {
567599 use super :: * ;
@@ -860,4 +892,26 @@ mod tests {
860892 assert ! ( results. contains( r#"<source>src</source>"# ) ) ;
861893 assert ! ( results. contains( r#"package name="main.rs""# ) ) ;
862894 }
895+
896+ #[ test]
897+ fn test_condition_coverage ( ) {
898+ const HIT : Condition = Condition {
899+ coverage : 1.0 ,
900+ number : 0 ,
901+ cond_type : ConditionType :: Jump ,
902+ } ;
903+ const MISS : Condition = Condition {
904+ coverage : 0.0 ,
905+ number : 0 ,
906+ cond_type : ConditionType :: Jump ,
907+ } ;
908+
909+ assert_eq ! ( "100% (1/1)" , format_condition_coverage( & [ HIT ] ) ) ;
910+ assert_eq ! ( "0% (0/1)" , format_condition_coverage( & [ MISS ] ) ) ;
911+ assert_eq ! ( "50% (1/2)" , format_condition_coverage( & [ HIT , MISS ] ) ) ;
912+ assert_eq ! ( "33% (1/3)" , format_condition_coverage( & [ HIT , MISS , MISS ] ) ) ;
913+ assert_eq ! ( "67% (2/3)" , format_condition_coverage( & [ HIT , HIT , MISS ] ) ) ;
914+
915+ assert_eq ! ( "100% (0/0)" , format_condition_coverage( & [ ] ) ) ;
916+ }
863917}
0 commit comments