X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FTest-Valgrind.git;a=blobdiff_plain;f=lib%2FTest%2FValgrind.pm;h=f9b28ab6acdccf3cd52a814a6e99a82bab04c7e4;hp=3c52e85bc814416e96797d65dc13f5c0516ad042;hb=abe419ac02d109283a1fe5615f5ab9d0a9a5572f;hpb=14d9a30088d40282446f97180ac6e383fa9ababf diff --git a/lib/Test/Valgrind.pm b/lib/Test/Valgrind.pm index 3c52e85..f9b28ab 100644 --- a/lib/Test/Valgrind.pm +++ b/lib/Test/Valgrind.pm @@ -9,22 +9,25 @@ Test::Valgrind - Test Perl code through valgrind. =head1 VERSION -Version 1.00 +Version 1.01 =cut -our $VERSION = '1.00'; +our $VERSION = '1.01'; =head1 SYNOPSIS # From the command-line perl -MTest::Valgrind leaky.pl + # From the command-line, snippet style + perl -MTest::Valgrind -e 'leaky()' + # In a test file use Test::More; eval 'use Test::Valgrind'; plan skip_all => 'Test::Valgrind is required to test your distribution with valgrind' if $@; - ... + leaky(); # In all the test files of a directory prove --exec 'perl -Iblib/lib -Iblib/arch -MTest::Valgrind' t/*.t @@ -222,35 +225,68 @@ sub import { my $file = delete $args{file}; unless (defined $file) { - my ($pm, $next); - my $l = 0; - while ($l < 1000) { - $next = (caller $l++)[1]; + my ($next, $last_pm); + for (my $l = 0; 1; ++$l) { + $next = (caller $l)[1]; last unless defined $next; - next if $next eq '-e' - or $next =~ /^\s*\(\s*eval\s*\d*\s*\)\s*$/ - or !-f $next; - if ($next =~ /\.pm$/) { - $pm = $next; + next if $next =~ /^\s*\(\s*eval\s*\d*\s*\)\s*$/; + if ($next =~ /\.pmc?$/) { + $last_pm = $next; } else { $file = $next; + last; } } - unless (defined($file) or defined($file = $pm)) { - require Test::Builder; - Test::Builder->new->diag('Couldn\'t find a valid source file'); - return; - } + $file = $last_pm unless defined $file; + } + + unless (defined $file) { + require Test::Builder; + Test::Builder->new->diag('Couldn\'t find a valid source file'); + return; + } + + if ($file ne '-e') { + exit $class->analyse( + file => $file, + %args, + ); } - exit $class->analyse( - file => $file, - %args, - ); + require File::Temp; + my $tmp = File::Temp->new; + + require Filter::Util::Call; + Filter::Util::Call::filter_add(sub { + my $status = Filter::Util::Call::filter_read(); + if ($status > 0) { + print $tmp $_; + } elsif ($status == 0) { + close $tmp; + my $code = $class->analyse( + file => $tmp->filename, + %args, + ); + exit $code; + } + $status; + }); } +=head1 VARIABLES + +=head2 C<$dl_unload> + +When set to true, all dynamic extensions that were loaded during the analysis will be unloaded at C time by L. + +Since this obfuscates error stack traces, it's disabled by default. + +=cut + +our $dl_unload; + END { - if ($run and eval { require DynaLoader; 1 }) { + if ($dl_unload and $run and eval { require DynaLoader; 1 }) { my @rest; DynaLoader::dl_unload_file($_) or push @rest, $_ for @DynaLoader::dl_librefs; @DynaLoader::dl_librefs = @rest; @@ -259,8 +295,6 @@ END { =head1 CAVEATS -You can't use this module to test code given by the C<-e> command-line switch. - Perl 5.8 is notorious for leaking like there's no tomorrow, so the suppressions are very likely not to be very accurate on it. Anyhow, results will most likely be better if your perl is built with debugging enabled. Using the latest C available will also help. This module is not really secure. It's definitely not taint safe. That shouldn't be a problem for test files.