File Coverage

blib/lib/Test/Valgrind.pm
Criterion Covered Total %
statement 54 125 43.2
branch 16 58 27.5
condition 6 23 26.0
subroutine 7 9 77.7
pod 1 1 100.0
total 84 216 38.8


line stmt bran cond sub pod time code
1             package Test::Valgrind;
2              
3 3     3   1754 use strict;
  3         4  
  3         90  
4 3     3   12 use warnings;
  3         2  
  3         3848  
5              
6             =head1 NAME
7              
8             Test::Valgrind - Generate suppressions, analyse and test any command with valgrind.
9              
10             =head1 VERSION
11              
12             Version 1.19
13              
14             =cut
15              
16             our $VERSION = '1.19';
17              
18             =head1 SYNOPSIS
19              
20             # From the command-line
21             perl -MTest::Valgrind leaky.pl
22              
23             # From the command-line, snippet style
24             perl -MTest::Valgrind -e 'leaky()'
25              
26             # In a test file
27             use Test::More;
28             eval 'use Test::Valgrind';
29             plan skip_all => 'Test::Valgrind is required to test your distribution with valgrind' if $@;
30             leaky();
31              
32             # In all the test files of a directory
33             prove --exec 'perl -Iblib/lib -Iblib/arch -MTest::Valgrind' t/*.t
34              
35             =head1 DESCRIPTION
36              
37             This module is a front-end to the C API that lets you run Perl code through the C tool of the C memory debugger, to test for memory errors and leaks.
38             If they aren't available yet, it will first generate suppressions for the current C interpreter and store them in the portable flavour of F<~/.perl/Test-Valgrind/suppressions/$VERSION>.
39             The actual run will then take place, and tests will be passed or failed according to the result of the analysis.
40              
41             The complete API is much more versatile than this.
42             By declaring an appropriate L class, you can run any executable (that is, not only Perl scripts) under valgrind, generate the corresponding suppressions on-the-fly and convert the analysis result to TAP output so that it can be incorporated into your project's testsuite.
43             If you're not interested in producing TAP, you can output the results in whatever format you like (for example HTML pages) by defining your own L class.
44              
45             Due to the nature of perl's memory allocator, this module can't track leaks of Perl objects.
46             This includes non-mortalized scalars and memory cycles.
47             However, it can track leaks of chunks of memory allocated in XS extensions with C and friends or C.
48             As such, it's complementary to the other very good leak detectors listed in the L section.
49              
50             =head1 METHODS
51              
52             =head2 C
53              
54             Test::Valgrind->analyse(%options);
55              
56             Run a C analysis configured by C<%options> :
57              
58             =over 4
59              
60             =item *
61              
62             C<< command => $command >>
63              
64             The L object (or class name) to use.
65              
66             Defaults to L.
67              
68             =item *
69              
70             C<< tool => $tool >>
71              
72             The L object (or class name) to use.
73              
74             Defaults to L.
75              
76             =item *
77              
78             C<< action => $action >>
79              
80             The L object (or class name) to use.
81              
82             Defaults to L.
83              
84             =item *
85              
86             C<< file => $file >>
87              
88             The file name of the script to analyse.
89              
90             Ignored if you supply your own custom C, but mandatory otherwise.
91              
92             =item *
93              
94             C<< callers => $number >>
95              
96             Specify the maximum stack depth studied when valgrind encounters an error.
97             Raising this number improves granularity.
98              
99             Ignored if you supply your own custom C, otherwise defaults to C<24> (the maximum allowed by C).
100              
101             =item *
102              
103             C<< diag => $bool >>
104              
105             If true, print the output of the test script as diagnostics.
106              
107             Ignored if you supply your own custom C, otherwise defaults to false.
108              
109             =item *
110              
111             C<< regen_def_supp => $bool >>
112              
113             If true, forcefully regenerate the default suppression file.
114              
115             Defaults to false.
116              
117             =item *
118              
119             C<< no_def_supp => $bool >>
120              
121             If true, do not use the default suppression file.
122              
123             Defaults to false.
124              
125             =item *
126              
127             C<< allow_no_supp => $bool >>
128              
129             If true, force running the analysis even if the suppression files do not refer to any C-related symbol.
130              
131             Defaults to false.
132              
133             =item *
134              
135             C<< extra_supps => \@files >>
136              
137             Also use suppressions from C<@files> besides C's.
138              
139             Defaults to empty.
140              
141             =back
142              
143             =cut
144              
145             sub _croak {
146 0     0   0 require Carp;
147 0         0 Carp::croak(@_);
148             }
149              
150             my %skippable_errors = (
151             session => [
152             'Empty valgrind candidates list',
153             'No appropriate valgrind executable could be found',
154             ],
155             action => [ ],
156             tool => [ ],
157             command => [ ],
158             run => [
159             'No compatible suppressions available',
160             ],
161             );
162              
163             my %filter_errors;
164              
165             for my $obj (keys %skippable_errors) {
166             my @errors = @{$skippable_errors{$obj} || []};
167             if (@errors) {
168             my $rxp = join '|', @errors;
169             $rxp = qr/($rxp)\s+at.*/;
170             $filter_errors{$obj} = sub {
171             my ($err) = @_;
172             if ($err =~ /$rxp/) {
173             return ($1, 1);
174             } else {
175             return ($err, 0);
176             }
177             };
178             } else {
179             $filter_errors{$obj} = sub {
180             return ($_[0], 0);
181             };
182             }
183             }
184              
185             sub _default_abort {
186 3     3   7 my ($err) = @_;
187              
188 3         15 require Test::Builder;
189 3         23 my $tb = Test::Builder->new;
190 3         39 my $plan = $tb->has_plan;
191 3 50       28 if (defined $plan) {
192 0         0 $tb->BAIL_OUT($err);
193 0         0 return 255;
194             } else {
195 3         14 $tb->skip_all($err);
196 0         0 return 0;
197             }
198             }
199              
200             sub analyse {
201 3     3 1 3 shift;
202              
203 3         7 my %args = @_;
204              
205             my $instanceof = sub {
206 3     3   16 require Scalar::Util;
207 3 50       34 Scalar::Util::blessed($_[0]) && $_[0]->isa($_[1]);
208 3         10 };
209              
210 3         4 my $tool = delete $args{tool};
211 3 50       9 unless ($tool->$instanceof('Test::Valgrind::Tool')) {
212 3   50     13 my $callers = delete $args{callers} || 24;
213 3 50       8 $callers = 24 if $callers <= 0;
214 3         1170 require Test::Valgrind::Tool;
215 3         7 local $@;
216 3         4 $tool = eval {
217 3   50     26 Test::Valgrind::Tool->new(
218             tool => $tool || 'memcheck',
219             callers => $callers,
220             );
221             };
222 3 50       13 unless ($tool) {
223 0         0 my ($err, $skippable) = $filter_errors{tool}->($@);
224 0 0       0 _croak($err) unless $skippable;
225 0         0 return _default_abort($err);
226             }
227             }
228              
229 3         1275 require Test::Valgrind::Session;
230 3         10 my $sess = eval {
231             Test::Valgrind::Session->new(
232             min_version => $tool->requires_version,
233 3         22 map { $_ => delete $args{$_} } qw<
  12         38  
234             regen_def_supp
235             no_def_supp
236             allow_no_supp
237             extra_supps
238             >
239             );
240             };
241 3 50       22 unless ($sess) {
242 3         14 my ($err, $skippable) = $filter_errors{session}->($@);
243 3 50       10 _croak($err) unless $skippable;
244 3         10 return _default_abort($err);
245             }
246              
247 0         0 my $action = delete $args{action};
248 0 0       0 unless ($action->$instanceof('Test::Valgrind::Action')) {
249 0         0 require Test::Valgrind::Action;
250 0         0 local $@;
251 0         0 $action = eval {
252             Test::Valgrind::Action->new(
253             action => $action || 'Test',
254             diag => delete $args{diag},
255 0   0     0 );
256             };
257 0 0       0 unless ($action) {
258 0         0 my ($err, $skippable) = $filter_errors{action}->($@);
259 0 0       0 _croak($err) unless $skippable;
260 0         0 return _default_abort($err);
261             }
262             }
263              
264 0         0 my $cmd = delete $args{command};
265 0 0       0 unless ($cmd->$instanceof('Test::Valgrind::Command')) {
266 0         0 require Test::Valgrind::Command;
267 0         0 local $@;
268 0         0 $cmd = eval {
269             Test::Valgrind::Command->new(
270             command => $cmd || 'PerlScript',
271             file => delete $args{file},
272 0   0     0 args => [ '-MTest::Valgrind=run,1' ],
273             );
274             };
275 0 0       0 unless ($cmd) {
276 0         0 my ($err, $skippable) = $filter_errors{command}->($@);
277 0 0       0 _croak($err) unless $skippable;
278 0         0 $action->abort($sess, $err);
279 0         0 return $action->status($sess);
280             }
281             }
282              
283             {
284 0         0 local $@;
  0         0  
285             eval {
286 0         0 $sess->run(
287             command => $cmd,
288             tool => $tool,
289             action => $action,
290             );
291 0         0 1
292 0 0       0 } or do {
293 0         0 my ($err, $skippable) = $filter_errors{run}->($@);
294 0 0       0 if ($skippable) {
295 0         0 $action->abort($sess, $err);
296 0         0 return $action->status($sess);
297             } else {
298 0         0 require Test::Valgrind::Report;
299 0         0 $action->report($sess, Test::Valgrind::Report->new_diag($@));
300             }
301             }
302             }
303              
304 0         0 my $status = $sess->status;
305 0 0       0 $status = 255 unless defined $status;
306              
307 0         0 return $status;
308             }
309              
310             =head2 C
311              
312             use Test::Valgrind %options;
313              
314             In the parent process, L calls L with the arguments it received itself - except that if no C option was supplied, it tries to pick the first caller context that looks like a script.
315             When the analysis ends, it exits with the status returned by the action (for the default TAP-generator action, it's the number of failed tests).
316              
317             In the child process, it just Cs so that the calling code is actually run under C, albeit two side-effects :
318              
319             =over 4
320              
321             =item *
322              
323             L is loaded and the destruction level is set to C<3>.
324              
325             =item *
326              
327             Autoflush on C is turned on.
328              
329             =back
330              
331             =cut
332              
333             # We use as little modules as possible in run mode so that they don't pollute
334             # the analysis. Hence all the requires.
335              
336             my $run;
337              
338             sub import {
339 3     3   24 my $class = shift;
340 3   33     18 $class = ref($class) || $class;
341              
342 3 50       17 _croak('Optional arguments must be passed as key => value pairs') if @_ % 2;
343 3         9 my %args = @_;
344              
345 3 50 33     19 if (defined delete $args{run} or $run) {
346 0         0 require Perl::Destruct::Level;
347 0         0 Perl::Destruct::Level::set_destruct_level(3);
348             {
349 0         0 my $oldfh = select STDOUT;
  0         0  
350 0         0 $|++;
351 0         0 select $oldfh;
352             }
353 0         0 $run = 1;
354 0         0 return;
355             }
356              
357 3         4 my $file = delete $args{file};
358 3 50       9 unless (defined $file) {
359 3         3 my ($next, $last_pm);
360 3         5 for (my $l = 0; 1; ++$l) {
361 3         20 $next = (caller $l)[1];
362 3 50       9 last unless defined $next;
363 3 50       9 next if $next =~ /^\s*\(\s*eval\s*\d*\s*\)\s*$/;
364 3 50       9 if ($next =~ /\.pmc?$/) {
365 0         0 $last_pm = $next;
366             } else {
367 3         4 $file = $next;
368 3         4 last;
369             }
370             }
371 3 50       8 $file = $last_pm unless defined $file;
372             }
373              
374 3 50       7 unless (defined $file) {
375 0         0 require Test::Builder;
376 0         0 Test::Builder->new->diag('Couldn\'t find a valid source file');
377 0         0 return;
378             }
379              
380 3 50       7 if ($file ne '-e') {
381 3         14 exit $class->analyse(
382             file => $file,
383             %args,
384             );
385             }
386              
387 0           require File::Temp;
388 0           my $tmp = File::Temp->new;
389              
390 0           require Filter::Util::Call;
391             Filter::Util::Call::filter_add(sub {
392 0     0     my $status = Filter::Util::Call::filter_read();
393 0 0         if ($status > 0) {
    0          
394 0           print $tmp $_;
395             } elsif ($status == 0) {
396 0           close $tmp;
397 0           my $code = $class->analyse(
398             file => $tmp->filename,
399             %args,
400             );
401 0           exit $code;
402             }
403 0           $status;
404 0           });
405             }
406              
407             =head1 VARIABLES
408              
409             =head2 C<$dl_unload>
410              
411             When set to true, all dynamic extensions that were loaded during the analysis will be unloaded at C time by L.
412              
413             Since this obfuscates error stack traces, it's disabled by default.
414              
415             =cut
416              
417             our $dl_unload;
418              
419             END {
420 3 0 33 3   1500 if ($dl_unload and $run and eval { require DynaLoader; 1 }) {
  0   33     0  
  0         0  
421 0         0 my @rest;
422 0   0     0 DynaLoader::dl_unload_file($_) or push @rest, $_ for @DynaLoader::dl_librefs;
423 0         0 @DynaLoader::dl_librefs = @rest;
424             }
425             }
426              
427             =head1 CAVEATS
428              
429             Perl 5.8 is notorious for leaking like there's no tomorrow, so the suppressions are very likely not to be complete on it.
430             You also have a better chance to get more accurate results if your perl is built with debugging enabled.
431             Using the latest C available will also help.
432              
433             This module is not really secure.
434             It's definitely not taint safe.
435             That shouldn't be a problem for test files.
436              
437             What your tests output to C and C is eaten unless you pass the C option, in which case it will be reprinted as diagnostics.
438              
439             =head1 DEPENDENCIES
440              
441             L, L, L, L.
442              
443             =head1 SEE ALSO
444              
445             All the C API, including L, L, L and L.
446              
447             The C man page.
448              
449             L.
450              
451             L, L, L.
452              
453             =head1 AUTHOR
454              
455             Vincent Pit, C<< >>, L.
456              
457             You can contact me by mail or on C (vincent).
458              
459             =head1 BUGS
460              
461             Please report any bugs or feature requests to C, or through the web interface at L.
462             I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
463              
464             =head1 SUPPORT
465              
466             You can find documentation for this module with the perldoc command.
467              
468             perldoc Test::Valgrind
469              
470             =head1 ACKNOWLEDGEMENTS
471              
472             RafaEl Garcia-Suarez, for writing and instructing me about the existence of L (Elizabeth Mattijsen is a close second).
473              
474             H.Merijn Brand, for daring to test this thing.
475              
476             David Cantrell, for providing shell access to one of his smokers where the tests were failing.
477              
478             The Debian-perl team, for offering all the feedback they could regarding the build issues they met.
479              
480             All you people that showed interest in this module, which motivated me into completely rewriting it.
481              
482             =head1 COPYRIGHT & LICENSE
483              
484             Copyright 2008,2009,2010,2011,2013,2015,2016 Vincent Pit, all rights reserved.
485              
486             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
487              
488             =cut
489              
490             1; # End of Test::Valgrind