File Coverage

blib/lib/DB/Pluggable/Plugin/BreakOnTestNumber.pm
Criterion Covered Total %
statement 26 52 50.0
branch 0 12 0.0
condition 0 3 0.0
subroutine 9 12 75.0
pod 2 2 100.0
total 37 81 45.6


line stmt bran cond sub pod time code
1             package DB::Pluggable::Plugin::BreakOnTestNumber;
2 1     1   758 use strict;
  1         3  
  1         28  
3 1     1   5 use warnings;
  1         2  
  1         23  
4 1     1   17 use 5.010;
  1         3  
5 1     1   513 use Role::Basic;
  1         14171  
  1         6  
6 1     1   538 use Hook::LexWrap;
  1         1255  
  1         5  
7 1     1   43 use Test::Builder; # preload so we can "safely" overwrite lock()
  1         3  
  1         167  
8             with qw(
9             DB::Pluggable::Role::Initializer
10             DB::Pluggable::Role::WatchFunction
11             );
12             our $VERSION = '1.12';
13              
14             sub initialize {
15 0     0 1   @DB::testbreak = ();
16             our $cmd_b_wrapper = wrap 'DB::cmd_b', pre => sub {
17 0 0   0     return unless $_[1] =~ /\s*#\s*(\d+(?:\s*,\s*\d+)*)$/;
18 0           my %seen;
19 0           @DB::testbreak = grep { !$seen{$_}++ }
20 0           sort { $a <=> $b } (split(/\s*,\s*/, $1), @DB::testbreak);
  0            
21              
22             # Making use of the fact that Test::Builder calls lock() each
23             # time before accessing {Curr_Test} is a hack, but directly
24             # enabling the watchfunction here would mean everything slows
25             # down to a crawl. It also means that this plugin won't work
26             # with threads. And let's hope Test::Builder continues to use
27             # lock()... Not nice, but it works and is fast.
28 1     1   8 no warnings 'redefine';
  1         2  
  1         48  
29 1     1   6 no strict 'refs';
  1         2  
  1         323  
30             *Test::Builder::lock = sub {
31 0 0         return if (caller(1))[3] eq 'Test::Builder::current_test';
32              
33             # Enable watchfunction
34 0           $DB::trace |= 4;
35 0           };
36              
37             # short-circuit (i.e., don't call the original debugger function)
38             # if a plugin has handled it
39 0           $_[-1] = 1;
40 0           return;
41             }
42 0           }
43              
44             sub watchfunction {
45 0     0 1   my $self = shift;
46              
47             # disable the watchfunction until it is next enabled by lock()
48 0           $DB::trace &= ~4;
49 0 0         return unless @DB::testbreak;
50 0           my $next = Test::Builder->new->current_test + 1;
51 0 0         if ($next >= $DB::testbreak[0]) {
52 0   0       shift @DB::testbreak while @DB::testbreak && $next >= $DB::testbreak[0];
53 0           my $depth = 1;
54 0           while (1) {
55 0           my $package = (caller $depth)[0];
56 0 0         last unless defined $package;
57 0 0         last unless $package =~ /^(DB(::|$)|Test::)/;
58 0           $depth++;
59             }
60 1     1   7 no warnings 'once';
  1         3  
  1         97  
61 0           $DB::stack[ -$depth + 1 ] = 1;
62             }
63 0           return;
64             }
65             1;
66              
67             __END__