App-Test-Generator
view release on metacpan or search on metacpan
lib/Devel/App/Test/Generator/LCSAJ/Runtime.pm view on Meta::CPAN
Records a per-(file, line) hit count used later for LCSAJ coverage
analysis.
=head3 Arguments
None. Perl calls this sub directly; the current execution location is
obtained internally via C<caller(0)>.
=head3 Returns
Nothing meaningful â this is a void debugger callback.
=head3 Side effects
Increments C<%HITS{$norm}{$line}> for the normalised path and line number
of the statement about to execute. Resolves each distinct raw filename
via C<Cwd::abs_path> once, memoising the result in C<%NORM_CACHE>.
=head3 Usage example
Not called directly â activated via the Perl debugger flag:
PERL5OPT='-d:App::Test::Generator::LCSAJ::Runtime -Mblib' prove -l t
=head3 API specification
=head4 input
{ }
=head4 output
{ type => UNDEF }
=head3 Formal specification
Let H be the hits relation (file x line) â â, T be the target-file set,
and I be the internal-file predicate (true only for this module's own
source path).
â DB_DB ââââââââââââââââââââââââââââââââââââââââââ
â ÎH
â file? : FilePath
â line? : â
ââââââââââââââââââââââââââââââââââââââââââââââââââ
â norm == normalize(file?)
â ¬I(norm) â§ (T = â
⨠norm â T)
â â¹ Hâ²(norm, line?) = H(norm, line?) + 1
â I(norm) ⨠(T â â
â§ norm â T)
â â¹ Hâ² = H
ââââââââââââââââââââââââââââââââââââââââââââââââââ
=cut
sub DB::DB {
my (undef, $file, $line) = caller(0);
return unless defined $file && defined $line;
# Resolve symlinks and relative components to a stable absolute path,
# cached per raw $file to avoid a stat() on every statement
my $norm = $NORM_CACHE{$file} //= _normalize(abs_path($file) // $file);
# Never record hits inside this module itself â suffix match is used
# so it works regardless of CWD or install prefix
return if $norm =~ m{(?:^|/)Devel/App/Test/Generator/LCSAJ/Runtime\.pm$};
# If a target list was provided, skip files not in it
if(%TARGET) {
return unless $TARGET{$norm};
}
$HITS{$norm}{$line}++;
}
# --------------------------------------------------
# _write_results
#
# Purpose: Serialise %HITS to a per-process JSON
# file in the output directory.
#
# Entry: None. Reads %HITS and $OUT_DIR.
#
# Exit: Returns nothing. Writes a JSON file.
# Returns immediately if %HITS is empty.
#
# Side effects: Creates $OUT_DIR if absent.
# Writes cover_html/lcsaj_hits/hits_PID.json
#
# Notes: Called from END so it runs even when
# prove exits non-zero â mutation tests
# are expected to fail. PID is included
# in the filename so parallel test runs
# produce separate files without collision.
# --------------------------------------------------
sub _write_results {
return unless %HITS;
# Include PID in filename to support parallel test runs
my $out_file = "$OUT_DIR/hits_$$.json";
make_path($OUT_DIR) unless -d $OUT_DIR;
# autodie is disabled for this open -- under "use autodie qw(open)"
# open() never returns false on failure, it throws its own exception
# instead, which would silently make the "or croak" below dead code
no autodie qw(open);
open my $fh, '>', $out_file or croak "Cannot write $out_file: $!";
print $fh encode_json(\%HITS);
close $fh;
}
1;
__END__
=head1 OUTPUT FORMAT
C<cover_html/lcsaj_hits/hits_PID.json> is a JSON object of the form:
( run in 2.695 seconds using v1.01-cache-2.11-cpan-600a1bdf6e4 )