App-Prove-Plugin-Metrics
view release on metacpan or search on metacpan
lib/TAP/Harness/Metrics.pm view on Meta::CPAN
package TAP::Harness::Metrics;
use parent qw/TAP::Harness/;
use strict;
use warnings;
our $VERSION='0.0.4';
use Carp qw/confess/;
use Fcntl qw/:flock/;
my %options=(
prefix =>'PREFIX',
sep =>'.',
subdepth =>1,
label =>0,
allowed =>'-._/A-Za-z0-9',
rollup =>0,
bubble =>1,
#
type =>'file',
append =>1,
outfile=>'/tmp/metrics-tests.txt',
# format =>'tsv',
#
module=>undef,
f =>'save',
);
my @configurable=(qw/prefix sep subdepth label allowed rollup/); # not fully "enforced"
sub verifyCallback {
my ($module,$f)=@_;
if(!$module) { confess("'module' must be provided") }
if(!$f) { confess("'f' must be non-empty") }
eval "require $module;";
if($@) { confess($@) }
my $cb=$module->can($f);
if(!$cb) { confess("${module}::${f} not available") }
return $cb;
}
sub new {
my ($ref,@opt)=@_;
my $class=ref($ref)||$ref;
my $self=$class->SUPER::new(@opt);
while(my ($k,$v)=each(%options)) { $$self{$k}=$v }
if($$self{type} eq 'module') {
$$self{modulef}=verifyCallback($$self{module},$$self{f});
if(my $cfg=$$self{module}->can('configureHarness')) {
my %config=&$cfg();
foreach my $k (grep {exists($config{$_})} @configurable) { $options{$k}=$$self{$k}=$config{$k} }
}
}
$$self{parser_class}='TAP::Parser::Metrics';
return $self;
}
sub make_parser {
my ($self,@args)=@_;
my ($parser,$session)=$self->SUPER::make_parser(@args);
$parser->configure(callback=>sub { $self->save(@_) });
return ($parser,$session);
}
sub import {
my ($class,$type,@opt)=@_;
$type//='file';
if($type eq 'module') { unshift(@opt,'module') }
%options=(%options,@opt,type=>$type);
return 1;
}
sub name {
my ($self,%event)=@_;
my @path=@{$event{path}};
if(defined($$self{subdepth})&&($$self{subdepth}>=0)) { splice(@path,$$self{subdepth}) }
my @name=map {s/[^$$self{allowed}]//sgr} (($$self{prefix}?$$self{prefix}:()),$event{file},@path,($$self{label}&&defined($event{label})?$event{label}:()));
return join($$self{sep},@name);
}
sub bubbled {
my ($self,%event)=@_;
if(!@{$event{path}}) { return }
$event{label}=pop(@{$event{path}});
return $self->name(%event);
}
sub collateRollup {
my ($self,@metrics)=@_;
my (%res,%count);
foreach my $event (@metrics) {
if(defined($$event{label})) {
foreach my $name ($self->name(%$event), ($$self{label}?$self->bubbled(%$event):())) {
$count{$name}++; $res{$name}+=$$event{pass} } }
else {
local($$self{label})=0;
foreach my $name ($self->bubbled(%$event)) {
$count{$name}++; $res{$name}+=$$event{pass} } }
}
foreach my $k (keys %res) { $res{$k}/=$count{$k} }
return %res;
}
sub collate {
my ($self,@metrics)=@_;
my (%res,%count);
if($$self{rollup}) { return $self->collateRollup(@metrics) }
foreach my $event (@metrics) {
foreach my $name ($self->name(%$event), ($$self{bubble}?$self->bubbled(%$event):())) {
$count{$name}++; $res{$name}//=1; $res{$name}&&=$$event{pass} } }
return %res;
}
sub save {
my ($self,@metrics)=@_;
my %metrics=$self->collate(@metrics);
if($$self{type} eq 'file') { $self->saveFile(%metrics) }
if($$self{type} eq 'module') { &{$$self{modulef}}(%metrics) }
if($$self{type} eq 'stderr') { $self->printMetrics(%metrics) }
return;
( run in 0.795 second using v1.01-cache-2.11-cpan-5a3173703d6 )