File Coverage

inc/Test/Exception.pm
Criterion Covered Total %
statement 51 99 51.5
branch 6 32 18.7
condition 2 9 22.2
subroutine 13 18 72.2
pod 4 4 100.0
total 76 162 46.9


line stmt bran cond sub pod time code
1 5     5   7370 #line 1
  5         9  
  5         191  
2 5     5   26 use strict;
  5         10  
  5         196  
3             use warnings;
4              
5 5     5   26 package Test::Exception;
  5         7  
  5         123  
6 5     5   5578 use Test::Builder;
  5         8395  
  5         31  
7 5     5   216 use Sub::Uplevel qw( uplevel );
  5         11  
  5         2482  
8             use base qw( Exporter );
9              
10             our $VERSION = '0.31';
11             our @EXPORT = qw(dies_ok lives_ok throws_ok lives_and);
12              
13             my $Tester = Test::Builder->new;
14              
15 5     5   31 sub import {
16 5 50       31 my $self = shift;
17 0         0 if ( @_ ) {
18 0         0 my $package = caller;
19 0         0 $Tester->exported_to( $package );
20             $Tester->plan( @_ );
21 5         1582 };
22             $self->export_to_level( 1, $self, $_ ) foreach @EXPORT;
23             }
24              
25             #line 83
26              
27             sub _quiet_caller (;$) { ## no critic Prototypes
28             my $height = $_[0];
29             $height++;
30              
31             if ( CORE::caller() eq 'DB' ) {
32             # passthrough the @DB::args trick
33             package DB;
34             if( wantarray ) {
35             if ( !@_ ) {
36             return (CORE::caller($height))[0..2];
37             }
38             else {
39             # If we got here, we are within a Test::Exception test, and
40             # something is producing a stacktrace. In case this is a full
41             # trace (i.e. confess() ), we have to make sure that the sub
42             # args are not visible. If we do not do this, and the test in
43             # question is throws_ok() with a regex, it will end up matching
44             # against itself in the args to throws_ok().
45             #
46             # While it is possible (and maybe wise), to test if we are
47             # indeed running under throws_ok (by crawling the stack right
48             # up from here), the old behavior of Test::Exception was to
49             # simply obliterate @DB::args altogether in _quiet_caller, so
50             # we are just preserving the behavior to avoid surprises
51             #
52             my @frame_info = CORE::caller($height);
53             @DB::args = ();
54             return @frame_info;
55             }
56             }
57              
58             # fallback if nothing above returns
59             return CORE::caller($height);
60             }
61             else {
62             if( wantarray and !@_ ) {
63             return (CORE::caller($height))[0..2];
64             }
65             else {
66             return CORE::caller($height);
67             }
68             }
69             }
70              
71             sub _try_as_caller {
72             my $coderef = shift;
73              
74             # local works here because Sub::Uplevel has already overridden caller
75             local *CORE::GLOBAL::caller;
76             { no warnings 'redefine'; *CORE::GLOBAL::caller = \&_quiet_caller; }
77              
78             eval { uplevel 3, $coderef };
79             return $@;
80             };
81              
82              
83             sub _is_exception {
84             my $exception = shift;
85 46     46   2545 return ref $exception || $exception ne '';
86 46         50 };
87              
88 46 100       113  
89             sub _exception_as_string {
90             my ( $prefix, $exception ) = @_;
91 5 50       16 return "$prefix normal exit" unless _is_exception( $exception );
92 5 50       19 my $class = ref $exception;
93 0         0 $exception = "$class ($exception)"
94             if $class && "$exception" !~ m/^\Q$class/;
95             chomp $exception;
96             return "$prefix $exception";
97             };
98              
99              
100             #line 206
101              
102              
103             sub throws_ok (&$;$) {
104             my ( $coderef, $expecting, $description ) = @_;
105             unless (defined $expecting) {
106             require Carp;
107             Carp::croak( "throws_ok: must pass exception class/object or regex" );
108             }
109 5         43 $description = _exception_as_string( "threw", $expecting )
110 5         12 unless defined $description;
111 5         42 my $exception = _try_as_caller( $coderef );
112             my $regex = $Tester->maybe_regex( $expecting );
113             my $ok = $regex
114             ? ( $exception =~ m/$regex/ )
115             : eval {
116 0         0 $exception->isa( ref $expecting ? ref $expecting : $expecting )
117             };
118             $Tester->ok( $ok, $description );
119 41 50 33     258 unless ( $ok ) {
120 0         0 $Tester->diag( _exception_as_string( "expecting:", $expecting ) );
121             $Tester->diag( _exception_as_string( "found:", $exception ) );
122             };
123 41         300 $@ = $exception;
124             return $ok;
125             };
126              
127              
128             #line 254
129 9     9   19  
130             sub dies_ok (&;$) {
131             my ( $coderef, $description ) = @_;
132 9         32 my $exception = _try_as_caller( $coderef );
133 5     5   32 my $ok = $Tester->ok( _is_exception($exception), $description );
  5         11  
  5         3550  
  9         16  
  9         27  
134             $@ = $exception;
135 9         28 return $ok;
  9         56  
136 9         2399 }
137              
138              
139             #line 293
140              
141 9     9   19 sub lives_ok (&;$) {
142 9   33     157 my ( $coderef, $description ) = @_;
143             my $exception = _try_as_caller( $coderef );
144             my $ok = $Tester->ok( ! _is_exception( $exception ), $description );
145             $Tester->diag( _exception_as_string( "died:", $exception ) ) unless $ok;
146             $@ = $exception;
147 0     0   0 return $ok;
148 0 0       0 }
149 0         0  
150 0 0 0     0  
151             #line 333
152 0         0  
153 0         0 sub lives_and (&;$) {
154             my ( $test, $description ) = @_;
155             {
156             local $Test::Builder::Level = $Test::Builder::Level + 1;
157             my $ok = \&Test::Builder::ok;
158             no warnings;
159             local *Test::Builder::ok = sub {
160             $_[2] = $description unless defined $_[2];
161             $ok->(@_);
162             };
163             use warnings;
164             eval { $test->() } and return 1;
165             };
166             my $exception = $@;
167             if ( _is_exception( $exception ) ) {
168             $Tester->ok( 0, $description );
169             $Tester->diag( _exception_as_string( "died:", $exception ) );
170             };
171             $@ = $exception;
172             return;
173             }
174              
175             #line 502
176              
177             1;