File Coverage

blib/lib/Test/LeakTrace.pm
Criterion Covered Total %
statement 63 66 95.4
branch 11 16 68.7
condition 2 3 66.6
subroutine 14 14 100.0
pod 6 6 100.0
total 96 105 91.4


line stmt bran cond sub pod time code
1             package Test::LeakTrace;
2              
3 13     13   409504 use 5.008_001;
  13         58  
  13         657  
4 13     13   76 use strict;
  13         31  
  13         475  
5 13     13   147 use warnings;
  13         33  
  13         1223  
6              
7             our $VERSION = '0.14';
8              
9 13     13   76 use XSLoader;
  13         22  
  13         567  
10             XSLoader::load(__PACKAGE__, $VERSION);
11              
12 13     13   72 use Test::Builder::Module;
  13         16  
  13         103  
13             our @ISA = qw(Test::Builder::Module);
14              
15 13     13   757 use Exporter qw(import); # use Exporter::import for backward compatibility
  13         28  
  13         11371  
16             our @EXPORT = qw(
17             leaktrace leaked_refs leaked_info leaked_count
18             no_leaks_ok leaks_cmp_ok
19             count_sv
20             );
21              
22             our %EXPORT_TAGS = (
23             all => \@EXPORT,
24             test => [qw(no_leaks_ok leaks_cmp_ok)],
25             util => [qw(leaktrace leaked_refs leaked_info leaked_count count_sv)],
26             );
27              
28              
29             sub _do_leaktrace{
30 47     47   203 my($block, $name, $need_stateinfo, $mode) = @_;
31              
32 47 50 66     285 if(!defined($mode) && !defined wantarray){
33 0         0 warnings::warnif void => "Useless use of $name() in void context";
34             }
35              
36 47 100       184 if($name eq 'leaked_count') {
37 17         25 my $start;
38 17         8258 $start = count_sv();
39 17         70 $block->();
40 17         6325 return count_sv() - $start;
41             }
42              
43 30         266 local $SIG{__DIE__} = 'DEFAULT';
44              
45 30         182480 _start($need_stateinfo);
46 28         36113 eval{
47 28         31044 $block->();
48             };
49 28 100       1440657 if($@){
50 2         6641 _finish(-silent);
51 2         59 die $@;
52             }
53              
54 26         103563 return _finish($mode);
55             }
56              
57             sub leaked_refs(&){
58 7     7 1 12264 my($block) = @_;
59 7         39 return _do_leaktrace($block, 'leaked_refs', 0);
60             }
61              
62             sub leaked_info(&){
63 8     8 1 3629 my($block) = @_;
64 8         32 return _do_leaktrace($block, 'leaked_refs', 1);
65             }
66              
67             sub leaked_count(&){
68 5     5 1 17 my($block) = @_;
69 5         14 return scalar _do_leaktrace($block, 'leaked_count', 0);
70             }
71              
72             sub leaktrace(&;$){
73 12     12 1 17092 my($block, $mode) = @_;
74 12 50       72 _do_leaktrace($block, 'leaktrace', 1, defined($mode) ? $mode : -simple);
75 7         89436 return;
76             }
77              
78              
79             sub leaks_cmp_ok(&$$;$){
80 12     12 1 1395 my($block, $cmp_op, $expected, $description) = @_;
81              
82 12         97 my $Test = __PACKAGE__->builder;
83              
84 12 50       334 if(!_runops_installed()){
85 0 0       0 my $mod = exists $INC{'Devel/Cover.pm'} ? 'Devel::Cover' : 'strange runops routines';
86 0         0 return $Test->ok(1, "skipped (under $mod)");
87             }
88              
89             # calls to prepare cache in $block
90 12         37 $block->();
91              
92 12         195145 my $got = _do_leaktrace($block, 'leaked_count', 0);
93              
94 12         100 my $desc = sprintf 'leaks %s %-2s %s', $got, $cmp_op, $expected;
95 12 100       46 if(defined $description){
96 3         16 $description .= " ($desc)";
97             }
98             else{
99 9         21 $description = $desc;
100             }
101              
102 12         65 my $result = $Test->cmp_ok($got, $cmp_op, $expected, $description);
103              
104 12 100       14184 if(!$result){
105 3     3   161 open local(*STDERR), '>', \(my $content = '');
  3         34  
  3         8  
  3         23  
106 3         11729 $block->(); # calls it again because opening *STDERR changes the run-time environment
107              
108 3         295 _do_leaktrace($block, 'leaktrace', 1, -verbose);
109 3         47 $Test->diag($content);
110             }
111              
112 12         2269 return $result;
113             }
114              
115             sub no_leaks_ok(&;$){
116             # ($block, $description)
117 5     5 1 68 splice @_, 1, 0, ('<=', 0); # ($block, '<=', 0, $description);
118 5         23 goto &leaks_cmp_ok;
119             }
120              
121              
122             1;
123             __END__