1
     ˆ0ÃÂÁ  G   	ˆl–Ü4ý(ÈT¾R( J7ÆÝS�ÿ¿„l¶ß_‹uÐb&=LV[(a–Ým_J	µ5*q@9p\må1hßÄ ;û    	use strict;
use warnings;
package Test::Fatal;
# ABSTRACT: incredibly simple helpers for testing code with exceptions
$Test::Fatal::VERSION = '0.017';
#pod =head1 SYNOPSIS
#pod
#pod   use Test::More;
#pod   use Test::Fatal;
#pod
#pod   use System::Under::Test qw(might_die);
#pod
#pod   is(
#pod     exception { might_die; },
#pod     undef,
#pod     "the code lived",
#pod   );
#pod
#pod   like(
#pod     exception { might_die; },
#pod     qr/turns out it died/,
#pod     "the code died as expected",
#pod   );
#pod
#pod   isa_ok(
#pod     exception { might_die; },
#pod     'Exception::Whatever',
#pod     'the thrown exception',
#pod   );
#pod
#pod =head1 DESCRIPTION
#pod
#pod Test::Fatal is an alternative to the popular L<Test::Exception>.  It does much
#pod less, but should allow greater flexibility in testing exception-throwing code
#pod with about the same amount of typing.
#pod
#pod It exports one routine by default: C<exception>.
#pod
#pod B<Achtung!>  C<exception> intentionally does not manipulate the call stack.
#pod User-written test functions that use C<exception> must be careful to avoid
#pod false positives if exceptions use stack traces that show arguments.  For a more
#pod magical approach involving globally overriding C<caller>, see
#pod L<Test::Exception>.
#pod
#pod =cut

use Carp ();
use Try::Tiny 0.07;

use Exporter 5.57 'import';

our @EXPORT    = qw(exception);
our @EXPORT_OK = qw(exception success dies_ok lives_ok);

#pod =func exception
#pod
#pod   my $exception = exception { ... };
#pod
#pod C<exception> takes a bare block of code and returns the exception thrown by
#pod that block.  If no exception was thrown, it returns undef.
#pod
#pod B<Achtung!>  If the block results in a I<false> exception, such as 0 or the
#pod empty string, Test::Fatal itself will die.  Since either of these cases
#pod indicates a serious problem with the system under testing, this behavior is
#pod considered a I<feature>.  If you must test for these conditions, you should use
#pod L<Try::Tiny>'s try/catch mechanism.  (Try::Tiny is the underlying exception
#pod handling system of Test::Fatal.)
#pod
#pod Note that there is no TAP assert being performed.  In other words, no "ok" or
#pod "not ok" line is emitted.  It's up to you to use the rest of C<exception> in an
#pod existing test like C<ok>, C<isa_ok>, C<is>, et cetera.  Or you may wish to use
#pod the C<dies_ok> and C<lives_ok> wrappers, which do provide TAP output.
#pod
#pod C<exception> does I<not> alter the stack presented to the called block, meaning
#pod that if the exception returned has a stack trace, it will include some frames
#pod between the code calling C<exception> and the thing throwing the exception.
#pod This is considered a I<feature> because it avoids the occasionally twitchy
#pod C<Sub::Uplevel> mechanism.
#pod
#pod B<Achtung!>  This is not a great idea:
#pod
#pod   sub exception_like(&$;$) {
#pod       my ($code, $pattern, $name) = @_;
#pod       like( &exception($code), $pattern, $name );
#pod   }
#pod
#pod   exception_like(sub { }, qr/foo/, 'foo appears in the exception');
#pod
#pod If the code in the C<...> is going to throw a stack trace with the arguments to
#pod each subroutine in its call stack (for example via C<Carp::confess>,
#pod the test name, "foo appears in the exception" will itself be matched by the
#pod regex.  Instead, write this:
#pod
#pod   like( exception { ... }, qr/foo/, 'foo appears in the exception' );
#pod
#pod If you really want a test function that passes the test name, wrap the
#pod arguments in an array reference to hide the literal text from a stack trace:
#pod
#pod   sub exception_like(&$) {
#pod       my ($code, $args) = @_;
#pod       my ($pattern, $name) = @$args;
#pod       like( &exception($code), $pattern, $name );
#pod   }
#pod
#pod   exception_like(sub { }, [ qr/foo/, 'foo appears in the exception' ] );
#pod
#pod To aid in avoiding the problem where the pattern is seen in the exception
#pod because of the call 