File Coverage

blib/lib/DB/Pluggable/Plugin/BreakOnTestNumber.pm
Criterion Covered Total %
statement 27 53 50.9
branch 0 12 0.0
condition 0 3 0.0
subroutine 9 12 75.0
pod 2 2 100.0
total 38 82 46.3


line stmt bran cond sub pod time code
1             package DB::Pluggable::Plugin::BreakOnTestNumber;
2 1     1   1094 use strict;
  1         2  
  1         43  
3 1     1   6 use warnings;
  1         3  
  1         33  
4 1     1   26 use 5.010;
  1         4  
  1         40  
5 1     1   1742 use Role::Basic;
  1         17676  
  1         9  
6 1     1   1194 use Hook::LexWrap;
  1         1315  
  1         6  
7 1     1   30 use Test::Builder; # preload so we can "safely" overwrite lock()
  1         2  
  1         190  
8             with qw(
9             DB::Pluggable::Role::Initializer
10             DB::Pluggable::Role::WatchFunction
11             );
12             our $VERSION = '1.112001';
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{$_}++ }
  0            
20 0           sort { $a <=> $b } (split(/\s*,\s*/, $1), @DB::testbreak);
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   6 no warnings 'redefine';
  1         2  
  1         31  
29 1     1   4 no strict 'refs';
  1         1  
  1         280  
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   6 no warnings 'once';
  1         2  
  1         102  
61 0           $DB::stack[ -$depth + 1 ] = 1;
62             }
63 0           return;
64             }
65             1;
66              
67             =pod
68              
69             =for stopwords watchfunction
70              
71             =for test_synopsis 1;
72             __END__