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   198169 use 5.008_001;
  13         39  
  13         422  
4 13     13   55 use strict;
  13         13  
  13         369  
5 13     13   51 use warnings;
  13         23  
  13         567  
6              
7             our $VERSION = '0.15';
8              
9 13     13   56 use XSLoader;
  13         14  
  13         458  
10             XSLoader::load(__PACKAGE__, $VERSION);
11              
12 13     13   55 use Test::Builder::Module;
  13         14  
  13         68  
13             our @ISA = qw(Test::Builder::Module);
14              
15 13     13   603 use Exporter qw(import); # use Exporter::import for backward compatibility
  13         22  
  13         7891  
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   90 my($block, $name, $need_stateinfo, $mode) = @_;
31              
32 47 50 66     212 if(!defined($mode) && !defined wantarray){
33 0         0 warnings::warnif void => "Useless use of $name() in void context";
34             }
35              
36 47 100       136 if($name eq 'leaked_count') {
37 17         21 my $start;
38 17         4875 $start = count_sv();
39 17         56 $block->();
40 17         4442 return count_sv() - $start;
41             }
42              
43 30         139 local $SIG{__DIE__} = 'DEFAULT';
44              
45 30         107798 _start($need_stateinfo);
46 28         20338 eval{
47 28         20146 $block->();
48             };
49 28 100       799327 if($@){
50 2         3402 _finish(-silent);
51 2         27 die $@;
52             }
53              
54 26         63846 return _finish($mode);
55             }
56              
57             sub leaked_refs(&){
58 7     7 1 10255 my($block) = @_;
59 7         23 return _do_leaktrace($block, 'leaked_refs', 0);
60             }
61              
62             sub leaked_info(&){
63 8     8 1 2077 my($block) = @_;
64 8         25 return _do_leaktrace($block, 'leaked_refs', 1);
65             }
66              
67             sub leaked_count(&){
68 5     5 1 23 my($block) = @_;
69 5         15 return scalar _do_leaktrace($block, 'leaked_count', 0);
70             }
71              
72             sub leaktrace(&;$){
73 12     12 1 12082 my($block, $mode) = @_;
74 12 50       53 _do_leaktrace($block, 'leaktrace', 1, defined($mode) ? $mode : -simple);
75 7         30514 return;
76             }
77              
78              
79             sub leaks_cmp_ok(&$$;$){
80 12     12 1 469 my($block, $cmp_op, $expected, $description) = @_;
81              
82 12         81 my $Test = __PACKAGE__->builder;
83              
84 12 50       124 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         25 $block->();
91              
92 12         638 my $got = _do_leaktrace($block, 'leaked_count', 0);
93              
94 12         73 my $desc = sprintf 'leaks %s %-2s %s', $got, $cmp_op, $expected;
95 12 100       33 if(defined $description){
96 3         10 $description .= " ($desc)";
97             }
98             else{
99 9         13 $description = $desc;
100             }
101              
102 12         47 my $result = $Test->cmp_ok($got, $cmp_op, $expected, $description);
103              
104 12 100       7678 if(!$result){
105 3     3   102 open local(*STDERR), '>', \(my $content = '');
  3         20  
  3         4  
  3         17  
106 3         2685 $block->(); # calls it again because opening *STDERR changes the run-time environment
107              
108 3         210 _do_leaktrace($block, 'leaktrace', 1, -verbose);
109 3         29 $Test->diag($content);
110             }
111              
112 12         1366 return $result;
113             }
114              
115             sub no_leaks_ok(&;$){
116             # ($block, $description)
117 5     5 1 63 splice @_, 1, 0, ('<=', 0); # ($block, '<=', 0, $description);
118 5         17 goto &leaks_cmp_ok;
119             }
120              
121              
122             1;
123             __END__