File Coverage

blib/lib/Test/Valgrind/Suppressions.pm
Criterion Covered Total %
statement 21 66 31.8
branch 11 36 30.5
condition 0 3 0.0
subroutine 4 6 66.6
pod 3 3 100.0
total 39 114 34.2


line stmt bran cond sub pod time code
1             package Test::Valgrind::Suppressions;
2              
3 6     6   28057 use strict;
  6         9  
  6         136  
4 6     6   20 use warnings;
  6         7  
  6         218  
5              
6             =head1 NAME
7              
8             Test::Valgrind::Suppressions - Generate suppressions for given tool and command.
9              
10             =head1 VERSION
11              
12             Version 1.19
13              
14             =cut
15              
16             our $VERSION = '1.19';
17              
18             =head1 DESCRIPTION
19              
20             This module is an helper for generating suppressions.
21              
22             =cut
23              
24 6     6   20 use base qw;
  6         12  
  6         3836  
25              
26             =head1 METHODS
27              
28             =head2 C
29              
30             Test::Valgrind::Suppressions->generate(
31             tool => $tool,
32             command => $command,
33             target => $target,
34             );
35              
36             Generates suppressions for the command C<< $command->new_trainer >> and the tool C<< $tool->new_trainer >>, and writes them in the file specified by C<$target>.
37             The action used behind the scenes is L.
38              
39             Returns the status code.
40              
41             =cut
42              
43             sub generate {
44 0     0 1 0 my $self = shift;
45              
46 0         0 my %args = @_;
47              
48 0         0 my $cmd = delete $args{command};
49 0 0       0 unless (ref $cmd) {
50 0         0 require Test::Valgrind::Command;
51 0         0 $cmd = Test::Valgrind::Command->new(
52             command => $cmd,
53             args => [ ],
54             );
55             }
56 0         0 $cmd = $cmd->new_trainer;
57 0 0       0 return unless defined $cmd;
58              
59 0         0 my $tool = delete $args{tool};
60 0 0       0 unless (ref $tool) {
61 0         0 require Test::Valgrind::Tool;
62 0         0 $tool = Test::Valgrind::Tool->new(tool => $tool);
63             }
64 0         0 $tool = $tool->new_trainer;
65 0 0       0 return unless defined $tool;
66              
67 0         0 my $target = delete $args{target};
68 0 0 0     0 $self->_croak('Invalid target') unless $target and not ref $target;
69              
70 0         0 require Test::Valgrind::Action;
71 0         0 my $action = Test::Valgrind::Action->new(
72             action => 'Suppressions',
73             target => $target,
74             name => 'PerlSuppression',
75             );
76              
77 0         0 require Test::Valgrind::Session;
78 0         0 my $sess = Test::Valgrind::Session->new(
79             min_version => $tool->requires_version,
80             );
81              
82 0         0 eval {
83 0         0 $sess->run(
84             command => $cmd,
85             tool => $tool,
86             action => $action,
87             );
88             };
89 0 0       0 $self->_croak($@) if $@;
90              
91 0         0 my $status = $sess->status;
92 0 0       0 $status = 255 unless defined $status;
93              
94 0         0 return $status;
95             }
96              
97             =head2 C
98              
99             my $mangled_suppression = Test::Valgrind::Suppressions->maybe_generalize(
100             $session,
101             $suppression,
102             );
103              
104             Removes all wildcard frames at the end of the suppression.
105             It also replaces sequences of wildcard frames by C<'...'> when C C<3.4.0> or higher is used.
106             Returns the mangled suppression.
107              
108             =cut
109              
110             sub maybe_generalize {
111 0     0 1 0 shift;
112              
113 0         0 my ($sess, $supp) = @_;
114              
115 0         0 1 while $supp =~ s/[^\r\n]*:\s*\*\s*$//;
116              
117             # With valgrind 3.4.0, we can replace unknown series of frames by '...'
118 0         0 my $can_ellipsis = $sess->version >= '3.4.0';
119              
120 0         0 my $did_length_check;
121              
122             ELLIPSIS: {
123 0 0       0 if ($can_ellipsis) {
  0         0  
124 0         0 $supp .= "...\n";
125 0         0 $supp =~ s/(?:^\s*(?:\.{3}|\*:\S*|obj:\*)\s*(?:\n|\z))+/...\n/mg;
126             }
127              
128 0 0       0 last if $did_length_check++;
129              
130 0         0 my $frames_count =()= $supp =~ m/^(?:(?:obj|fun|\*):|\.{3}\s*$)/mg;
131 0 0       0 if ($frames_count > 24) {
132             # Keep only 24 frames, and even sacrifice one more if we can do ellipsis.
133 0 0       0 my $last = $can_ellipsis ? 23 : 24;
134 0         0 my $len = length $supp;
135 0         0 $supp =~ m/^(?:(?:obj|fun|\*):\S*|\.{3})\s*\n/mg for 1 .. $last;
136 0         0 my $p = pos $supp;
137 0         0 substr $supp, $p, $len - $p, '';
138 0 0       0 redo ELLIPSIS if $can_ellipsis;
139             }
140             }
141              
142 0         0 $supp;
143             }
144              
145             =head2 C
146              
147             my $demangled_symbol = Test::Valgrind::Suppressions->maybe_z_demangle(
148             $symbol,
149             );
150              
151             If C<$symbol> is Z-encoded as described in C's F, extract and decode its function name part.
152             Otherwise, C<$symbol> is returned as is.
153              
154             This routine follows C's F.
155              
156             =cut
157              
158             my %z_escapes = (
159             a => '*',
160             c => ':',
161             d => '.',
162             h => '-',
163             p => '+',
164             s => ' ',
165             u => '_',
166             A => '@',
167             D => '$',
168             L => '(',
169             R => ')',
170             Z => 'Z',
171             );
172              
173             sub maybe_z_demangle {
174 7     7 1 98724 my ($self, $sym) = @_;
175              
176 7 100       44 $sym =~ s/^_vg[rwn]Z([ZU])_// or return $sym;
177              
178 6         15 my $fn_is_encoded = $1 eq 'Z';
179              
180 6 100       26 $sym =~ /^VG_Z_/ and $self->_croak('Symbol with a "VG_Z_" prefix is invalid');
181 5 100       24 $sym =~ s/^[^_]*_//
182             or $self->_croak('Symbol doesn\'t contain a function name');
183              
184 4 100       11 if ($fn_is_encoded) {
185 2         12 $sym =~ s/Z(.)/
186 4         10 my $c = $z_escapes{$1};
187 4 100       13 $self->_croak('Invalid escape sequence') unless defined $c;
188 3         13 $c;
189             /ge;
190             }
191              
192 3 50       8 $self->_croak('Empty symbol') unless length $sym;
193              
194 3         9 return $sym;
195             }
196              
197             =head1 SEE ALSO
198              
199             L, L, L, L.
200              
201             =head1 AUTHOR
202              
203             Vincent Pit, C<< >>, L.
204              
205             You can contact me by mail or on C (vincent).
206              
207             =head1 BUGS
208              
209             Please report any bugs or feature requests to C, or through the web interface at L.
210             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
211              
212             =head1 SUPPORT
213              
214             You can find documentation for this module with the perldoc command.
215              
216             perldoc Test::Valgrind::Suppressions
217              
218             =head1 COPYRIGHT & LICENSE
219              
220             Copyright 2008,2009,2010,2011,2013,2015,2016 Vincent Pit, all rights reserved.
221              
222             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
223              
224             =cut
225              
226             1; # End of Test::Valgrind::Suppressions