package Test2::Tools::Exception; use strict; use warnings; our $VERSION = '0.000111'; use Test2::API qw/context/; our @EXPORT = qw/dies lives try_ok/; use base 'Exporter'; sub dies(&) { my $code = shift; local ($@, $!, $?); my $ok = eval { $code->(); 1 }; my $err = $@; return undef if $ok; unless ($err) { my $ctx = context(); $ctx->alert("Got exception as expected, but exception is falsy (undef, '', or 0)..."); $ctx->release; } return $err; } sub lives(&) { my $code = shift; my $err; { local ($@, $!, $?); eval { $code->(); 1 } and return 1; $err = $@; } # If the eval failed we want to set $@ to the error. $@ = $err; return 0; } sub try_ok(&;$) { my ($code, $name) = @_; my $ok = &lives($code); my $err = $@; # Context should be obtained AFTER code is run so that events inside the # codeblock report inside the codeblock itself. This will also preserve $@ # as thrown inside the codeblock. my $ctx = context(); chomp(my $diag = "Exception: $err"); $ctx->ok($ok, $name, [$diag]); $ctx->release; $@ = $err unless $ok; return $ok; } 1; __END__ =pod =encoding UTF-8 =head1 NAME Test2::Tools::Exception - Test2 based tools for checking exceptions =head1 DESCRIPTION This is the L implementation of code used to test exceptions. This is similar to L, but it intentionally does much less. =head1 SYNOPSIS use Test2::Tools::Exception qw/dies lives/; like( dies { die 'xxx' }, qr/xxx/, "Got exception" ); ok(lives { ... }, "did not die") or note($@); =head1 EXPORTS All subs are exported by default. =over 4 =item $e = dies { ... } This will trap any exception the codeblock throws. If no exception is thrown the sub will return undef. If an exception is thrown it will be returned. This function preserves C<$@>, it will not be altered from its value before the sub is called. =item $bool = lives { ... } This will trap any exception thrown in the codeblock. It will return true when there is no exception, and false when there is. C<$@> is preserved from before the sub is called when there is no exception. When an exception is trapped C<$@> will have the exception so that you can look at it. =item $bool = try_ok { ... } =item $bool = try_ok { ... } "Test Description" This will run the code block trapping any exception. If there is no exception a passing event will be issued. If the test fails a failing event will be issued, and the exception will be reported as diagnostics. B This function does not preserve C<$@> on failure, it will be set to the exception the codeblock throws, this is by design so that you can obtain the exception if desired. =back =head1 DIFFERENCES FROM TEST::FATAL L sets C<$Test::Builder::Level> such that failing tests inside the exception block will report to the line where C is called. I disagree with this, and think the actual line of the failing test is more important. Ultimately, though L cannot be changed, people probably already depend on that behavior. =head1 SOURCE The source code repository for Test2-Suite can be found at F. =head1 MAINTAINERS =over 4 =item Chad Granum Eexodist@cpan.orgE =back =head1 AUTHORS =over 4 =item Chad Granum Eexodist@cpan.orgE =back =head1 COPYRIGHT Copyright 2017 Chad Granum Eexodist@cpan.orgE. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See F =cut