File Coverage

blib/lib/Test/LeakTrace.pm
Criterion Covered Total %
statement 62 65 95.3
branch 11 16 68.7
condition 2 3 66.6
subroutine 14 14 100.0
pod 6 6 100.0
total 95 104 91.3


line stmt bran cond sub pod time code
1             package Test::LeakTrace;
2              
3 13     13   196116 use 5.008_001;
  13         52  
4 13     13   74 use strict;
  13         29  
  13         316  
5 13     13   70 use warnings;
  13         47  
  13         665  
6              
7             our $VERSION = '0.16';
8              
9 13     13   104 use XSLoader;
  13         23  
  13         512  
10             XSLoader::load(__PACKAGE__, $VERSION);
11              
12 13     13   75 use Test::Builder::Module;
  13         36  
  13         81  
13             our @ISA = qw(Test::Builder::Module);
14              
15 13     13   577 use Exporter qw(import); # use Exporter::import for backward compatibility
  13         35  
  13         8154  
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   148 my($block, $name, $need_stateinfo, $mode) = @_;
31              
32 47 50 66     262 if(!defined($mode) && !defined wantarray){
33 0         0 warnings::warnif void => "Useless use of $name() in void context";
34             }
35              
36 47 100       168 if($name eq 'leaked_count') {
37 17         27 my $start;
38 17         3340 $start = count_sv();
39 17         64 $block->();
40 17         3151 return count_sv() - $start;
41             }
42              
43 30         170 local $SIG{__DIE__} = 'DEFAULT';
44              
45 30         86001 _start($need_stateinfo);
46 28         13457 eval{
47 28         13175 $block->();
48             };
49 28 100       555677 if($@){
50 2         2583 _finish(-silent);
51 2         34 die $@;
52             }
53              
54 26         43789 return _finish($mode);
55             }
56              
57             sub leaked_refs(&){
58 7     7 1 10660 my($block) = @_;
59 7         35 return _do_leaktrace($block, 'leaked_refs', 0);
60             }
61              
62             sub leaked_info(&){
63 8     8 1 2796 my($block) = @_;
64 8         26 return _do_leaktrace($block, 'leaked_refs', 1);
65             }
66              
67             sub leaked_count(&){
68 5     5 1 18 my($block) = @_;
69 5         13 return scalar _do_leaktrace($block, 'leaked_count', 0);
70             }
71              
72             sub leaktrace(&;$){
73 12     12 1 12352 my($block, $mode) = @_;
74 12 50       69 _do_leaktrace($block, 'leaktrace', 1, defined($mode) ? $mode : -simple);
75 7         43777 return;
76             }
77              
78              
79             sub leaks_cmp_ok(&$$;$){
80 12     12 1 903 my($block, $cmp_op, $expected, $description) = @_;
81              
82 12         80 my $Test = __PACKAGE__->builder;
83              
84 12 50       249 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         40 $block->();
91              
92 12         503 my $got = _do_leaktrace($block, 'leaked_count', 0);
93              
94 12         75 my $desc = sprintf 'leaks %s %-2s %s', $got, $cmp_op, $expected;
95 12 100       39 if(defined $description){
96 3         13 $description .= " ($desc)";
97             }
98             else{
99 9         18 $description = $desc;
100             }
101              
102 12         49 my $result = $Test->cmp_ok($got, $cmp_op, $expected, $description);
103              
104 12 100       9629 if(!$result){
105 3     3   94 open local(*STDERR), '>', \(my $content = '');
  3         25  
  3         6  
  3         17  
106 3         2099 $block->(); # calls it again because opening *STDERR changes the run-time environment
107              
108 3         82 _do_leaktrace($block, 'leaktrace', 1, -verbose);
109 3         30 $Test->diag($content);
110             }
111              
112 12         1187 return $result;
113             }
114              
115             sub no_leaks_ok(&;$){
116             # ($block, $description)
117 5     5 1 58 splice @_, 1, 0, ('<=', 0); # ($block, '<=', 0, $description);
118 5         20 goto &leaks_cmp_ok;
119             }
120              
121              
122             1;
123             __END__