File Coverage

lib/Devel/Trepan/BrkptMgr.pm
Criterion Covered Total %
statement 55 98 56.1
branch 9 22 40.9
condition n/a
subroutine 14 22 63.6
pod 0 14 0.0
total 78 156 50.0


line stmt bran cond sub pod time code
1             # -*- coding: utf-8 -*-
2             # Copyright (C) 2011-2013 Rocky Bernstein <rocky@cpan.org>
3 12     12   80 use strict; use warnings; no warnings 'redefine';
  12     12   29  
  12     12   303  
  12         67  
  12         27  
  12         296  
  12         62  
  12         24  
  12         362  
4 12     12   63 use English qw( -no_match_vars );
  12         27  
  12         90  
5              
6             BEGIN {
7 12     12   90 my @OLD_INC = @INC;
8 12     12   3709 use rlib '../..';
  12         30  
  12         77  
9 12     12   7162 use Devel::Trepan::DB::Breakpoint;
  12         39  
  12         407  
10 12         11813 @INC = @OLD_INC;
11             }
12              
13             package Devel::Trepan::BrkptMgr;
14              
15              
16             sub new($$)
17             {
18 27     27 0 129 my ($class,$dbgr) = @_;
19 27         70 my $self = {};
20 27         109 $self->{dbgr} = $dbgr;
21 27         83 bless $self, $class;
22 27         149 $self->clear();
23 27         232 $self;
24             }
25              
26             sub clear($)
27             {
28 27     27 0 74 my $self = shift;
29 27         196 $self->{list} = [];
30 27         109 $self->{next_id} = 1;
31             }
32              
33             sub inspect($)
34             {
35 0     0 0 0 my $self = shift;
36 0         0 my $str = '';
37 0         0 for my $brkpt ($self->list) {
38 0 0       0 next unless defined $brkpt;
39 0         0 $str .= $brkpt->inspect . "\n";
40             }
41 0         0 $str;
42             }
43              
44             sub ids($)
45             {
46 0     0 0 0 my $self = shift;
47 0         0 map $_->id, @{$self->compact()};
  0         0  
48             }
49              
50             sub list($)
51             {
52 1     1 0 4 my $self = shift;
53 1 50       2 map defined($_) ? $_ : (), @{$self->{list}}
  1         11  
54             }
55              
56             # Remove all breakpoints that we have recorded
57             sub DESTROY() {
58 1     1   344 my $self = shift;
59 1         6 for my $bp ($self->list) {
60 1         7 $self->delete_by_brkpt($bp);
61             }
62 1         58 $self->{clear};
63             }
64              
65             sub find($$)
66             {
67 3     3 0 12 my ($self, $index) = @_;
68 3 100       24 return undef unless $index =~ /^\d+$/;
69 2         6 for my $bp (@{$self->{list}}) {
  2         8  
70 2 50       11 next unless $bp;
71 2 100       51 return $bp if $bp->id eq $index;
72             }
73 1         17 return undef;
74             }
75              
76             sub delete($$)
77             {
78 0     0 0 0 my ($self, $index) = @_;
79 0         0 my $bp = $self->find($index);
80 0 0       0 if (defined ($bp)) {
81 0         0 $self->delete_by_brkpt($bp);
82 0         0 return $bp;
83             } else {
84 0         0 return undef;
85             }
86             }
87              
88             sub delete_by_brkpt($$)
89             {
90 1     1 0 4 my ($self, $delete_bp) = @_;
91 1         2 for my $candidate (@{$self->{list}}) {
  1         6  
92 1 50       5 next unless defined $candidate;
93 1 50       5 if ($candidate eq $delete_bp) {
94 1         3 $candidate = undef;
95 1 50       18 $self->{dbgr} && $self->{dbgr}->delete_bp($delete_bp);
96 1         4 return $delete_bp;
97             }
98             }
99 0         0 return undef;
100             }
101              
102             sub add($$)
103             {
104 1     1 0 1439 my ($self, $brkpt) = @_;
105 1         3 push @{$self->{list}}, $brkpt;
  1         4  
106 1         5 return $brkpt;
107             }
108              
109             sub compact($)
110             {
111 0     0 0   my $self = shift;
112 0           my @new_list = ();
113 0           for my $brkpt (@{$self->{list}}) {
  0            
114 0 0         next unless defined $brkpt;
115 0           push @new_list, $brkpt;
116             }
117 0           $self->{list} = \@new_list;
118 0           return $self->{list};
119             }
120              
121             sub is_empty($)
122             {
123 0     0 0   my $self = shift;
124 0           $self->compact();
125 0           return scalar(0 == @{$self->{list}});
  0            
126             }
127              
128             sub max($)
129             {
130 0     0 0   my $self = shift;
131 0           my $max = 0;
132 0           for my $brkpt (@{$self->{list}}) {
  0            
133 0 0         $max = $brkpt->id if $brkpt->id > $max;
134             }
135 0           return $max;
136             }
137              
138             sub size($)
139             {
140 0     0 0   my $self = shift;
141 0           $self->compact();
142 0           return scalar @{$self->{list}};
  0            
143             }
144              
145             sub reset($)
146             {
147 0     0 0   my $self = shift;
148 0           for my $bp (@{$self->{list}}) {
  0            
149 0           $self->{dbgr}->delete_bp($bp);
150             }
151 0           $self->{list} = [];
152             }
153              
154              
155             unless (caller) {
156              
157             eval <<'EOE';
158             sub bp_status($$)
159             {
160             my ($brkpts, $i) = @_;
161             printf "list size: %s\n", $brkpts->size();
162             printf "max: %d\n", $brkpts->max() // -1;
163             print $brkpts->inspect();
164             print "--- ${i} ---\n";
165             }
166             EOE
167              
168             require Devel::Trepan::Core;
169             my $dbgr = Devel::Trepan::Core->new;
170             my $brkpts = Devel::Trepan::BrkptMgr->new($dbgr);
171             bp_status($brkpts, 0);
172             my $brkpt1 = DBBreak->new(
173             type=>'brkpt', condition=>'1', id=>1, hits => 0, enabled => 1,
174             negate => 0, filename => __FILE__, line_num => __LINE__
175             );
176              
177             $brkpts->add($brkpt1);
178             bp_status($brkpts, 1);
179              
180             my $brkpt2 = DBBreak->new(
181             type=>'brkpt', condition=>'x>5', id=>2, hits => 0, enabled => 0,
182             Negate => 0, filename => __FILE__, line_num => __LINE__
183             );
184             $brkpts->add($brkpt2);
185             bp_status($brkpts, 2);
186              
187             $brkpts->delete_by_brkpt($brkpt1);
188             bp_status($brkpts, 3);
189              
190             my $brkpt3 = DBBreak->new(
191             type=>'brkpt', condition=>'y eq x', id=>3, hits => 0, enabled => 1,
192             negate => 1, filename => __FILE__, line_num => __LINE__
193             );
194             $brkpts->add($brkpt3);
195             bp_status($brkpts, 4);
196             print "id 3 found is", $brkpts->find(3), "\n";
197             print "id 4 is undef\n" unless defined $brkpts->find(4);
198             print "id 'a' is undef\n" unless defined $brkpts->find('a');
199              
200             # p brkpts.delete(2)
201             # p brkpts[2]
202             # bp_status(brkpts, 3)
203              
204             # # Two of the same breakpoints but delete 1 and see that the
205             # # other still stays
206             # offset = frame.pc_offset
207             # b2 = Trepan::Breakpoint.new(iseq, offset)
208             # brkpts << b2
209             # bp_status(brkpts, 4)
210             # b3 = Trepan::Breakpoint.new(iseq, offset)
211             # brkpts << b3
212             # bp_status(brkpts, 5)
213             # brkpts.delete_by_brkpt(b2)
214             # bp_status(brkpts, 6)
215             # brkpts.delete_by_brkpt(b3)
216             # bp_status(brkpts, 7)
217             }
218              
219             1;