X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=lib%2FTest%2FValgrind%2FTool%2Fmemcheck.pm;h=542ff9ddff7a3d5adb9526ad151e05ae940f6e7a;hb=b34179155630f5f4cbea1749af4054a746ded9a4;hp=a9da30bc40aa162afe039495baa0fa8d8b587fd3;hpb=abe419ac02d109283a1fe5615f5ab9d0a9a5572f;p=perl%2Fmodules%2FTest-Valgrind.git diff --git a/lib/Test/Valgrind/Tool/memcheck.pm b/lib/Test/Valgrind/Tool/memcheck.pm index a9da30b..542ff9d 100644 --- a/lib/Test/Valgrind/Tool/memcheck.pm +++ b/lib/Test/Valgrind/Tool/memcheck.pm @@ -9,33 +9,40 @@ Test::Valgrind::Tool::memcheck - Run an analysis through the memcheck tool. =head1 VERSION -Version 1.01 +Version 1.17 =cut -our $VERSION = '1.01'; +our $VERSION = '1.17'; =head1 DESCRIPTION -This tool parses the XML output of a C run with L. +This class contains the information required by the session for running the C tool. =cut -use base qw/Test::Valgrind::Tool::SuppressionsParser Test::Valgrind::Tool/; +use base qw; =head1 METHODS -This class inherits L and L. +This class inherits L. =head2 C + my $required_version = $tvt->requires_version; + This tool requires C C<3.1.0>. =cut sub requires_version { '3.1.0' } -=head2 C<< new callers => $callers, ... >> +=head2 C + + my $tvtm = Test::Valgrind::Tool::memcheck->new( + callers => $callers, + %extra_args, + ); Your usual constructor. @@ -51,15 +58,13 @@ sub new { my %args = @_; - my $callers = delete $args{callers} || 12; + my $callers = delete $args{callers} || 50; $callers =~ s/\D//g; my $self = bless $class->Test::Valgrind::Tool::new(%args), $class; $self->{callers} = $callers; - $self->{twig} = Test::Valgrind::Tool::memcheck::Twig->new(tool => $self); - $self; } @@ -67,32 +72,61 @@ sub new_trainer { shift->new(callers => 50) } =head2 C + my $callers = $tvtm->callers; + Read-only accessor for the C option. =cut sub callers { $_[0]->{callers} } -=head2 C +sub suppressions_tag { 'memcheck-' . $_[1]->version } + +=head2 C + + my $parser_class = $tvtm->parser_class($session); -Read-only accessor for the underlying L parser. +This tool uses a L parser in analysis mode, and a L parser in suppressions mode. =cut -sub twig { $_[0]->{twig} } +sub parser_class { + my ($self, $session) = @_; -sub suppressions_tag { 'memcheck-' . $_[1]->version } + my $class = $session->do_suppressions + ? 'Test::Valgrind::Parser::Suppressions::Text' + : 'Test::Valgrind::Parser::XML::Twig'; -=head2 C + { + local $@; + eval "require $class; 1" or die $@; + } -This tool emits C object reports in analysis mode. + return $class; +} + +=head2 C + + my $report_class = $tvtm->report_class($session); + +This tool emits C object reports in analysis mode, and C object reports in suppressions mode. =cut -sub report_class_analysis { 'Test::Valgrind::Tool::memcheck::Report' } +sub report_class { + my ($self, $session) = @_; + + if ($session->do_suppressions) { + require Test::Valgrind::Parser::Suppressions::Text; + return 'Test::Valgrind::Report::Suppressions'; + } else { + return 'Test::Valgrind::Tool::memcheck::Report'; + } +} sub args { - my ($self, $sess) = @_; + my $self = shift; + my ($sess) = @_; my @args = ( '--tool=memcheck', @@ -103,57 +137,17 @@ sub args { '--error-limit=yes', ); - unless ($sess->do_suppressions) { - push @args, '--track-origins=yes' if $sess->version ge '3.4.0'; - push @args, '--xml=yes'; - } + push @args, '--track-origins=yes' if $sess->version ge '3.4.0' + and not $sess->do_suppressions; - push @args, $self->SUPER::args(); + push @args, $self->SUPER::args(@_); return @args; } -# We must store the session in ourselves because it's only possible to pass -# arguments to XML::Twig objects by a global stash. - -sub _session { @_ <= 1 ? $_[0]->{_session} : ($_[0]->{_session} = $_[1]) } - -sub start { - my ($self, $sess) = @_; - - $self->_croak('This memcheck tool can\'t be run in two sessions at once') - if $self->_session; - - $self->SUPER::start($sess); - $self->_session($sess); - - return; -} - -sub parse_analysis { - my ($self, $sess, $fh) = @_; - - my $twig = $self->twig; - $twig->parse($fh); - $twig->purge; - - return; -} - -sub finish { - my ($self, $sess) = @_; - - $self->_session(undef); - $self->SUPER::start($sess); - - return; -} - =head1 SEE ALSO -L, L, L. - -L. +L, L. =head1 AUTHOR @@ -174,7 +168,7 @@ You can find documentation for this module with the perldoc command. =head1 COPYRIGHT & LICENSE -Copyright 2009 Vincent Pit, all rights reserved. +Copyright 2009,2010,2011,2013,2015 Vincent Pit, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. @@ -184,13 +178,11 @@ This program is free software; you can redistribute it and/or modify it under th package Test::Valgrind::Tool::memcheck::Report; -use base qw/Test::Valgrind::Report/; - -use Config qw/%Config/; +use base qw; -our $VERSION = '1.01'; +our $VERSION = '1.17'; -my @kinds = qw/ +my @kinds = qw< InvalidFree MismatchedFree InvalidRead @@ -206,7 +198,7 @@ my @kinds = qw/ Leak_IndirectlyLost Leak_PossiblyLost Leak_StillReachable -/; +>; push @kinds, __PACKAGE__->SUPER::kinds(); my %kinds_hashed = map { $_ => 1 } @kinds; @@ -217,7 +209,11 @@ sub valid_kind { exists $kinds_hashed{$_[1]} } sub is_leak { $_[0]->kind =~ /^Leak_/ ? 1 : '' } -my $pad = 2 * ($Config{ptrsize} || 4); +my $pad; +BEGIN { + require Config; + $pad = 2 * ($Config::Config{ptrsize} || 4); +} sub dump { my ($self) = @_; @@ -239,9 +235,9 @@ sub dump { my ($ip, $obj, $fn, $dir, $file, $line) = map { (defined) ? $_ : '?' } @$_; my $frame; if ($fn eq '?' and $obj eq '?') { - $ip =~ s/^0x//g; - $ip = hex $ip; - $frame = sprintf "0x%0${pad}X", $ip; + $ip =~ s/^0x//gi; + my $l = length $ip; + $frame = '0x' . ($l < $pad ? ('0' x ($pad - $l)) : '') . uc($ip); } else { $frame = sprintf '%s (%s) [%s:%s]', $fn, $obj, $file, $line; } @@ -254,112 +250,3 @@ sub dump { # End of Test::Valgrind::Tool::memcheck::Report -package Test::Valgrind::Tool::memcheck::Twig; - -our $VERSION = '1.01'; - -use Scalar::Util; - -use base qw/XML::Twig Test::Valgrind::Carp/; - -BEGIN { XML::Twig->add_options('Stash'); } - -my %handlers = ( - '/valgrindoutput/error' => \&handle_error, -); - -sub new { - my $class = shift; - $class = ref($class) || $class; - - my %args = @_; - my $stash = delete $args{stash} || { }; - - my $tool = delete $args{tool}; - $class->_croak('Invalid tool') unless Scalar::Util::blessed($tool) - and $tool->isa('Test::Valgrind::Tool'); - $stash->{tool} = $tool; - - bless $class->XML::Twig::new( - elt_class => __PACKAGE__ . '::Elt', - stash => $stash, - twig_roots => { map { $_ => 1 } keys %handlers }, - twig_handlers => { map { $_ => $handlers{$_} } keys %handlers }, - ), $class; -} - -sub stash { shift->{Stash} } - -sub handle_error { - my ($twig, $node) = @_; - - my $id = $node->kid('unique')->text; - my $kind = $node->kid('kind')->text; - - my $data; - - $data->{what} = $node->kid('what')->text; - $data->{stack} = [ map $_->listify_frame, - $node->kid('stack')->children('frame') ]; - - for (qw/leakedbytes leakedblocks/) { - my $kid = $node->first_child($_); - next unless $kid; - $data->{$_} = int $kid->text; - } - - if (my $auxwhat = $node->first_child('auxwhat')) { - if (my $stack = $auxwhat->next_sibling('stack')) { - $data->{auxstack} = [ map $_->listify_frame, $stack->children('frame') ]; - } - $data->{auxwhat} = $auxwhat->text; - } - - if (my $origin = $node->first_child('origin')) { - $data->{origwhat} = $origin->kid('what')->text; - $data->{origstack} = [ map $_->listify_frame, - $origin->kid('stack')->children('frame') ]; - } - - my $report = Test::Valgrind::Tool::memcheck::Report->new( - kind => $kind, - id => $id, - data => $data, - ); - - $twig->stash->{tool}->_session->report($report); - - $twig->purge; -} - -# End of Test::Valgrind::Tool::memcheck::Twig - -package Test::Valgrind::Tool::memcheck::Twig::Elt; - -our $VERSION = '1.01'; - -BEGIN { require XML::Twig; } - -use base qw/XML::Twig::Elt Test::Valgrind::Carp/; - -sub kid { - my ($self, $what) = @_; - my $node = $self->first_child($what); - $self->_croak("Couldn't get first $what child node") unless $node; - return $node; -} - -sub listify_frame { - my ($frame) = @_; - - return unless $frame->tag eq 'frame'; - - return [ - map { - my $x = $frame->first_child($_); - $x ? $x->text : undef - } qw/ip obj fn dir file line/ - ]; -} - -1; # End of Test::Valgrind::Tool::memcheck::Twig::Elt