@ -12,6 +12,7 @@
maybe_write_coverdata / 2 ,
format_error / 1 ] ) .
- include_lib ( " providers/include/providers.hrl " ) .
- include ( " rebar.hrl " ) .
- define ( PROVIDER , cover ) .
@ -62,6 +63,9 @@ maybe_write_coverdata(State, Task) ->
end .
- spec format_error ( any ( ) ) - > iolist ( ) .
format_error ( { min_coverage_failed , { PassRate , Total } } ) - >
io_lib : format ( " Requiring ~p % coverage to pass. Only ~p % obtained " ,
[ PassRate , Total ] ) ;
format_error ( Reason ) - >
io_lib : format ( " ~p " , [ Reason ] ) .
@ -102,13 +106,13 @@ do_analyze(State) ->
% % redirect cover output
true = redirect_cover_output ( State , CoverPid ) ,
% % analyze !
ok = case analyze ( State , CoverFiles ) of
[ ] - > ok ;
case analyze ( State , CoverFiles ) of
[ ] - > { ok , State } ;
Analysis - >
print_analysis ( Analysis , verbose ( State ) ) ,
write_index ( State , Analysis )
end ,
{ ok , State } .
write_index ( State , Analysis ) ,
maybe_fail_coverage ( Analysis , State )
end .
get_all_coverdata ( CoverDir ) - >
ok = filelib : ensure_dir ( filename : join ( [ CoverDir , " dummy.log " ] ) ) ,
@ -213,11 +217,11 @@ format_table(Stats, CoverFiles) ->
Header = header ( MaxLength ) ,
Separator = separator ( MaxLength ) ,
TotalLabel = format ( " total " , MaxLength ) ,
TotalCov = format ( calculate_total ( Stats ) , 8 ) ,
TotalCov = format ( calculate_total_string ( Stats ) , 8 ) ,
[ io_lib : format ( " ~ ts ~n ~ ts ~n ~ ts ~n " , [ Separator , Header , Separator ] ) ,
lists : map ( fun ( { Mod , Coverage , _ } ) - >
Name = format ( Mod , MaxLength ) ,
Cov = format ( percentage ( Coverage ) , 8 ) ,
Cov = format ( percentage_string ( Coverage ) , 8 ) ,
io_lib : format ( " | ~ ts | ~ ts | ~n " , [ Name , Cov ] )
end , Stats ) ,
io_lib : format ( " ~ ts ~n " , [ Separator ] ) ,
@ -239,6 +243,9 @@ separator(Width) ->
format ( String , Width ) - > io_lib : format ( " ~ *.ts " , [ Width , String ] ) .
calculate_total_string ( Stats ) - >
integer_to_list ( calculate_total ( Stats ) ) ++ " % " .
calculate_total ( Stats ) - >
percentage ( lists : foldl (
fun ( { _ Mod , { Cov , Not } , _ File } , { CovAcc , NotAcc } ) - >
@ -248,8 +255,10 @@ calculate_total(Stats) ->
Stats
) ) .
percentage ( { _ , 0 } ) - > " 100% " ;
percentage ( { Cov , Not } ) - > integer_to_list ( trunc ( ( Cov / ( Cov + Not ) ) * 100 ) ) ++ " % " .
percentage_string ( Data ) - > integer_to_list ( percentage ( Data ) ) ++ " % " .
percentage ( { _ , 0 } ) - > 100 ;
percentage ( { Cov , Not } ) - > trunc ( ( Cov / ( Cov + Not ) ) * 100 ) .
write_index ( State , Coverage ) - >
CoverDir = cover_dir ( State ) ,
@ -279,14 +288,25 @@ write_index_section(F, [{Section, DataFile, Mods}|Rest]) ->
FmtLink =
fun ( { Mod , Cov , Report } ) - >
? FMT ( " <tr><td><a href=' ~ ts'> ~ ts</a></td><td> ~ ts</td> \n " ,
[ strip_coverdir ( Report ) , Mod , percentage ( Cov ) ] )
[ strip_coverdir ( Report ) , Mod , percentage_string ( Cov ) ] )
end ,
lists : foreach ( fun ( M ) - > ok = file : write ( F , FmtLink ( M ) ) end , Mods ) ,
ok = file : write ( F , ? FMT ( " <tr><td><strong>Total</strong></td><td> ~ ts</td> \n " ,
[ calculate_total ( Mods ) ] ) ) ,
[ calculate_total_string ( Mods ) ] ) ) ,
ok = file : write ( F , " </table> \n " ) ,
write_index_section ( F , Rest ) .
maybe_fail_coverage ( Analysis , State ) - >
{ _ , _ CoverFiles , Stats } = lists : keyfind ( " aggregate " , 1 , Analysis ) ,
Total = calculate_total ( Stats ) ,
PassRate = min_coverage ( State ) ,
? DEBUG ( " Comparing ~p to pass rate ~p " , [ Total , PassRate ] ) ,
if Total > = PassRate - >
{ ok , State }
; Total < PassRate - >
? PRV_ERROR ( { min_coverage_failed , { PassRate , Total } } )
end .
% % fix for r15b which doesn ' t put the correct path in the ` source ` section
% % of ` module_info ( compile ) `
strip_coverdir ( [ ] ) - > " " ;
@ -401,12 +421,23 @@ verbose(State) ->
{ Verbose , _ } - > Verbose
end .
min_coverage ( State ) - >
Command = proplists : get_value ( min_coverage , command_line_opts ( State ) , undefined ) ,
Config = proplists : get_value ( min_coverage , config_opts ( State ) , undefined ) ,
case { Command , Config } of
{ undefined , undefined } - > 0 ;
{ undefined , Rate } - > Rate ;
{ Rate , _ } - > Rate
end .
cover_dir ( State ) - >
filename : join ( [ rebar_dir : base_dir ( State ) , " cover " ] ) .
cover_opts ( _ State ) - >
[ { reset , $r , " reset " , boolean , help ( reset ) } ,
{ verbose , $v , " verbose " , boolean , help ( verbose ) } ] .
{ verbose , $v , " verbose " , boolean , help ( verbose ) } ,
{ min_coverage , $m , " min_coverage " , integer , help ( min_coverage ) } ] .
help ( reset ) - > " Reset all coverdata. " ;
help ( verbose ) - > " Print coverage analysis. " .
help ( verbose ) - > " Print coverage analysis. " ;
help ( min_coverage ) - > " Mandate a coverage percentage required to succeed (0..100) " .