=cut
+use List::Util ();
use Env::Sanctify ();
use Test::Valgrind::Suppressions;
local $_;
while (<$fh>) {
- return 1 if /^\s*fun:Perl_/;
+ return 1 if /^\s*fun:(Perl|S|XS)_/
+ or /^\s*obj:.*perl/;
}
close $fh;
return $report if $report->is_diag
or not $report->isa('Test::Valgrind::Report::Suppressions');
- my $data = $report->data;
- $data =~ s/[^\r\n]*\bPerl_runops_(?:standard|debug)\b.*//s;
- $data = Test::Valgrind::Suppressions->strip_tail($session, $data);
+ my @frames = grep length, split /\n/, $report->data;
+
+ # If we see the runloop, match from here.
+ my $top = List::Util::first(sub {
+ $frames[$_] =~ /^\s*fun:Perl_runops_(?:standard|debug)\b/
+ }, 0 .. $#frames);
+ --$top if $top;
+
+ unless (defined $top) {
+ # Otherwise, match from the latest Perl_ symbol.
+ $top = List::Util::first(sub {
+ $frames[$_] =~ /^\s*fun:Perl_/
+ }, reverse 0 .. $#frames);
+ }
+
+ unless (defined $top) {
+ # Otherwise, match from the latest S_ symbol.
+ $top = List::Util::first(sub {
+ $frames[$_] =~ /^\s*fun:S_/
+ }, reverse 0 .. $#frames);
+ }
+
+ unless (defined $top) {
+ # Otherwise, match from the latest XS_ symbol.
+ $top = List::Util::first(sub {
+ $frames[$_] =~ /^\s*fun:XS_/
+ }, reverse 0 .. $#frames);
+ }
+
+ $#frames = $top if defined $top;
+
+ my $data = join "\n", @frames, '';
+
+ $data = Test::Valgrind::Suppressions->maybe_generalize($session, $data);
$report->new(
id => $report->id,
return $status;
}
-=head2 C<strip_tail>
+=head2 C<maybe_generalize>
- my $mangled_suppression = Test::Valgrind::Suppressions->strip_tail(
+ my $mangled_suppression = Test::Valgrind::Suppressions->maybe_generalize(
$session,
$suppression,
);
Removes all wildcard frames at the end of the suppression.
-Moreover, C<'...'> is appended when C<valgrind> C<3.4.0> or higher is used.
+It also replaces sequences of wildcard frames by C<'...'> when C<valgrind> C<3.4.0> or higher is used.
Returns the mangled suppression.
=cut
-sub strip_tail {
+sub maybe_generalize {
shift;
my ($sess, $supp) = @_;
1 while $supp =~ s/[^\r\n]*:\s*\*\s*$//;
+
# With valgrind 3.4.0, we can replace unknown series of frames by '...'
if ($sess->version ge '3.4.0') {
- 1 while $supp =~ s/[^\r\n]*\.{3}\s*$//;
$supp .= "...\n";
+ $supp =~ s/(?:^\s*(?:\.{3}|\*:\S*|obj:\*)\s*\n)+/...\n/mg;
}
$supp;