File Coverage

inc/Test/Memory/Cycle.pm
Criterion Covered Total %
statement 34 109 31.1
branch 0 30 0.0
condition n/a
subroutine 6 15 40.0
pod 4 4 100.0
total 44 158 27.8


line stmt bran cond sub pod time code
1             #line 1
2             package Test::Memory::Cycle;
3 1     1   1890  
  1         2  
  1         37  
4 1     1   5 use strict;
  1         1  
  1         43  
5             use warnings;
6              
7             #line 14
8              
9             our $VERSION = '1.04';
10              
11             #line 46
12              
13             use Devel::Cycle qw( find_cycle find_weakened_cycle );
14             use Test::Builder;
15              
16             my $Test = Test::Builder->new;
17              
18             sub import {
19             my $self = shift;
20             my $caller = caller;
21             no strict 'refs';
22             *{$caller.'::memory_cycle_ok'} = \&memory_cycle_ok;
23             *{$caller.'::memory_cycle_exists'} = \&memory_cycle_exists;
24              
25             *{$caller.'::weakened_memory_cycle_ok'} = \&weakened_memory_cycle_ok;
26             *{$caller.'::weakened_memory_cycle_exists'} = \&weakened_memory_cycle_exists;
27             *{$caller.'::memory_cycle_exists'} = \&memory_cycle_exists;
28              
29             *{$caller.'::weakened_memory_cycle_ok'} = \&weakened_memory_cycle_ok;
30             *{$caller.'::weakened_memory_cycle_exists'} = \&weakened_memory_cycle_exists;
31              
32             $Test->exported_to($caller);
33             $Test->plan(@_);
34              
35             return;
36             }
37              
38             #line 79
39              
40             sub memory_cycle_ok {
41             my $ref = shift;
42             my $msg = shift;
43              
44             my $cycle_no = 0;
45             my @diags;
46              
47 1     1   1499 # Callback function that is called once for each memory cycle found.
  1         3966  
  1         5  
48 1     1   159 my $callback = sub {
  1         2  
  1         49  
49             my $path = shift;
50             $cycle_no++;
51             push( @diags, "Cycle #$cycle_no" );
52             foreach (@$path) {
53 1     1   9 my ($type,$index,$ref,$value) = @$_;
54 1         3  
55 1     1   6 my $str = 'Unknown! This should never happen!';
  1         2  
  1         1008  
56 1         2 my $refdisp = _ref_shortname( $ref );
  1         7  
57 1         1 my $valuedisp = _ref_shortname( $value );
  1         5  
58              
59 1         2 $str = sprintf( ' %s => %s', $refdisp, $valuedisp ) if $type eq 'SCALAR';
  1         4  
60 1         2 $str = sprintf( ' %s => %s', "${refdisp}->[$index]", $valuedisp ) if $type eq 'ARRAY';
  1         4  
61 1         2 $str = sprintf( ' %s => %s', "${refdisp}->{$index}", $valuedisp ) if $type eq 'HASH';
  1         3  
62             $str = sprintf( ' closure %s => %s', "${refdisp}, $index", $valuedisp ) if $type eq 'CODE';
63 1         2  
  1         2  
64 1         1 push( @diags, $str );
  1         2  
65             }
66 1         6 };
67 1         9  
68             find_cycle( $ref, $callback );
69 1         23 my $ok = !$cycle_no;
70             $Test->ok( $ok, $msg );
71             $Test->diag( join( "\n", @diags, '' ) ) unless $ok;
72              
73             return $ok;
74             } # memory_cycle_ok
75              
76             #line 121
77              
78             sub memory_cycle_exists {
79             my $ref = shift;
80             my $msg = shift;
81 0     0 1    
82 0           my $cycle_no = 0;
83              
84 0           # Callback function that is called once for each memory cycle found.
85 0           my $callback = sub { $cycle_no++ };
86              
87             find_cycle( $ref, $callback );
88             my $ok = $cycle_no;
89 0     0     $Test->ok( $ok, $msg );
90 0            
91 0           return $ok;
92 0           } # memory_cycle_exists
93 0            
94             #line 145
95 0            
96 0           sub weakened_memory_cycle_ok {
97 0           my $ref = shift;
98             my $msg = shift;
99 0 0          
100 0 0         my $cycle_no = 0;
101 0 0         my @diags;
102 0 0          
103             # Callback function that is called once for each memory cycle found.
104 0           my $callback = sub {
105             my $path = shift;
106 0           $cycle_no++;
107             push( @diags, "Cycle #$cycle_no" );
108 0           foreach (@$path) {
109 0           my ($type,$index,$ref,$value,$is_weakened) = @$_;
110 0            
111 0 0         my $str = "Unknown! This should never happen!";
112             my $refdisp = _ref_shortname( $ref );
113 0           my $valuedisp = _ref_shortname( $value );
114             my $weak = $is_weakened ? 'w->' : '';
115              
116             $str = sprintf( ' %s%s => %s', $weak, $refdisp, $valuedisp ) if $type eq 'SCALAR';
117             $str = sprintf( ' %s%s => %s', $weak, "${refdisp}->[$index]", $valuedisp ) if $type eq 'ARRAY';
118             $str = sprintf( ' %s%s => %s', $weak, "${refdisp}->{$index}", $valuedisp ) if $type eq 'HASH';
119              
120             push( @diags, $str );
121             }
122             };
123 0     0 1    
124 0           find_weakened_cycle( $ref, $callback );
125             my $ok = !$cycle_no;
126 0           $Test->ok( $ok, $msg );
127             $Test->diag( join( "\n", @diags, "" ) ) unless $ok;
128              
129 0     0     return $ok;
  0            
130             } # weakened_memory_cycle_ok
131 0            
132 0           #line 189
133 0            
134             sub weakened_memory_cycle_exists {
135 0           my $ref = shift;
136             my $msg = shift;
137              
138             my $cycle_no = 0;
139              
140             # Callback function that is called once for each memory cycle found.
141             my $callback = sub { $cycle_no++ };
142              
143             find_weakened_cycle( $ref, $callback );
144             my $ok = $cycle_no;
145             $Test->ok( $ok, $msg );
146              
147 0     0 1   return $ok;
148 0           } # weakened_memory_cycle_exists
149              
150 0            
151 0           my %shortnames;
152             my $new_shortname = "A";
153              
154             sub _ref_shortname {
155 0     0     my $ref = shift;
156 0           my $refstr = "$ref";
157 0           my $refdisp = $shortnames{ $refstr };
158 0           if ( !$refdisp ) {
159 0           my $sigil = ref($ref) . " ";
160             $sigil = '%' if $sigil eq "HASH ";
161 0           $sigil = '@' if $sigil eq "ARRAY ";
162 0           $sigil = '$' if $sigil eq "REF ";
163 0           $sigil = '&' if $sigil eq "CODE ";
164 0 0         $refdisp = $shortnames{ $refstr } = $sigil . $new_shortname++;
165             }
166 0 0          
167 0 0         return $refdisp;
168 0 0         }
169              
170 0           #line 278
171              
172 0           1;