File Coverage

inc/Test/LeakTrace.pm
Criterion Covered Total %
statement 18 63 28.5
branch 0 16 0.0
condition 0 3 0.0
subroutine 6 13 46.1
pod 6 6 100.0
total 30 101 29.7


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