use Carp qw/croak/;
use POSIX qw/SIGTERM/;
-use Test::More;
+use Fcntl qw/F_SETFD/;
+use Test::Builder;
use Perl::Destruct::Level level => 3;
=head1 VERSION
-Version 0.05
+Version 0.06
=cut
-our $VERSION = '0.05';
+our $VERSION = '0.06';
=head1 SYNOPSIS
=cut
+my $Test = Test::Builder->new;
+
my $run;
sub _counter {
}
sub _tester {
- is($_[0], 0, $_[1]);
+ $Test->is_num($_[0], 0, $_[1]);
_counter(@_);
}
croak 'Optional arguments must be passed as key => value pairs' if @_ % 2;
my %args = @_;
if (!defined $args{run} && !$run) {
- my ($file, $next);
+ my ($file, $pm, $next);
my $l = 0;
while ($l < 1000) {
$next = (caller $l++)[1];
last unless defined $next;
- $file = $next;
+ next unless $next ne '-e' and $next !~ /^\s*\(\s*eval\s*\d*\s*\)\s*$/
+ and -f $next;
+ if ($next =~ /\.pm$/) {
+ $pm = $next;
+ } else {
+ $file = $next;
+ }
+ }
+ unless (defined $file) {
+ $file = $pm;
+ return unless defined $pm;
}
- return if not $file or $file eq '-e';
my $callers = $args{callers};
$callers = 12 unless defined $callers;
$callers = int $callers;
}
}
if (!$vg) {
- plan skip_all => 'No valgrind executable could be found in your path';
+ $Test->skip_all('No valgrind executable could be found in your path');
return;
}
}
- pipe my $rdr, my $wtr or croak "pipe(\$rdr, \$wtr): $!";
+ pipe my $ordr, my $owtr or die "pipe(\$ordr, \$owtr): $!";
+ pipe my $vrdr, my $vwtr or die "pipe(\$vrdr, \$vwtr): $!";
my $pid = fork;
if (!defined $pid) {
- croak "fork(): $!";
+ die "fork(): $!";
} elsif ($pid == 0) {
- setpgrp 0, 0 or croak "setpgrp(0, 0): $!";
- close $rdr or croak "close(\$rdr): $!";
- open STDERR, '>&', $wtr or croak "open(STDERR, '>&', \$wtr): $!";
+ setpgrp 0, 0 or die "setpgrp(0, 0): $!";
+ close $ordr or die "close(\$ordr): $!";
+ open STDOUT, '>&=', $owtr or die "open(STDOUT, '>&=', \$owtr): $!";
+ close $vrdr or die "close(\$vrdr): $!";
+ fcntl $vwtr, F_SETFD, 0 or die "fcntl(\$vwtr, F_SETFD, 0): $!";
my @args = (
+ $vg,
'--tool=memcheck',
'--leak-check=full',
'--leak-resolution=high',
'--num-callers=' . $callers,
- '--error-limit=yes'
+ '--error-limit=yes',
+ '--log-fd=' . fileno($vwtr)
);
unless ($args{no_supp}) {
for (Test::Valgrind::Suppressions::supp_path(), $args{supp}) {
push @args, $^X;
push @args, '-I' . $_ for @INC;
push @args, '-MTest::Valgrind=run,1', $file;
- print STDERR "valgrind @args\n" if $args{diag};
+ print STDOUT "valgrind @args\n";
local $ENV{PERL_DESTRUCT_LEVEL} = 3;
local $ENV{PERL_DL_NONLAZY} = 1;
- exec $vg, @args;
+ exec { $args[0] } @args;
+ die "exec @args: $!";
}
- close $wtr or croak "close(\$wtr): $!";
local $SIG{INT} = sub { kill -(SIGTERM) => $pid };
- plan tests => 5 unless $args{no_test};
+ $Test->plan(tests => 5) unless $args{no_test} or defined $Test->has_plan;
my @tests = (
'errors',
'definitely lost', 'indirectly lost', 'possibly lost', 'still reachable'
);
my %res = map { $_ => 0 } @tests;
- while (<$rdr>) {
- diag $_ if $args{diag};
+ close $owtr or die "close(\$owtr): $!";
+ $Test->diag(do { local $/; <$ordr> }) if $args{diag};
+ close $ordr or die "close(\$ordr): $!";
+ close $vwtr or die "close(\$vwtr): $!";
+ while (<$vrdr>) {
+ $Test->diag($_) if $args{diag};
if (/^=+\d+=+\s*FATAL\s*:\s*(.*)/) {
chomp(my $err = $1);
- diag "Valgrind error: $err";
+ $Test->diag("Valgrind error: $err");
$res{$_} = undef for @tests;
}
if (/ERROR\s+SUMMARY\s*:\s+(\d+)/) {
Valgrind 3.1.0 (L<http://valgrind.org>).
-L<Carp>, L<POSIX> (core modules since perl 5) and L<Test::More> (since 5.6.2).
+L<Carp>, L<Fcntl>, L<POSIX> (core modules since perl 5) and L<Test::Builder> (since 5.6.2).
L<Perl::Destruct::Level>.