diff options
author | Nicholas Clark <nick@ccl4.org> | 2009-09-26 05:55:28 +0100 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2009-09-26 05:55:28 +0100 |
commit | e853d2264b77e2bdc0758f8ab38e819629763e81 (patch) | |
tree | b3d56f32ce3c9c2cd3f92f7e91f24ef4417176c0 /ext | |
parent | ad73611d3a91f38464b3d95e2d6b43d4a57ef82f (diff) | |
download | perl-e853d2264b77e2bdc0758f8ab38e819629763e81.tar.gz |
Move autodie from ext/ to cpan/
Diffstat (limited to 'ext')
64 files changed, 0 insertions, 5773 deletions
diff --git a/ext/autodie/lib/Fatal.pm b/ext/autodie/lib/Fatal.pm deleted file mode 100755 index 18e71ed21a..0000000000 --- a/ext/autodie/lib/Fatal.pm +++ /dev/null @@ -1,1374 +0,0 @@ -package Fatal; - -use 5.008; # 5.8.x needed for autodie -use Carp; -use strict; -use warnings; -use Tie::RefHash; # To cache subroutine refs - -use constant PERL510 => ( $] >= 5.010 ); - -use constant LEXICAL_TAG => q{:lexical}; -use constant VOID_TAG => q{:void}; -use constant INSIST_TAG => q{!}; - -use constant ERROR_NOARGS => 'Cannot use lexical %s with no arguments'; -use constant ERROR_VOID_LEX => VOID_TAG.' cannot be used with lexical scope'; -use constant ERROR_LEX_FIRST => LEXICAL_TAG.' must be used as first argument'; -use constant ERROR_NO_LEX => "no %s can only start with ".LEXICAL_TAG; -use constant ERROR_BADNAME => "Bad subroutine name for %s: %s"; -use constant ERROR_NOTSUB => "%s is not a Perl subroutine"; -use constant ERROR_NOT_BUILT => "%s is neither a builtin, nor a Perl subroutine"; -use constant ERROR_NOHINTS => "No user hints defined for %s"; - -use constant ERROR_CANT_OVERRIDE => "Cannot make the non-overridable builtin %s fatal"; - -use constant ERROR_NO_IPC_SYS_SIMPLE => "IPC::System::Simple required for Fatalised/autodying system()"; - -use constant ERROR_IPC_SYS_SIMPLE_OLD => "IPC::System::Simple version %f required for Fatalised/autodying system(). We only have version %f"; - -use constant ERROR_AUTODIE_CONFLICT => q{"no autodie '%s'" is not allowed while "use Fatal '%s'" is in effect}; - -use constant ERROR_FATAL_CONFLICT => q{"use Fatal '%s'" is not allowed while "no autodie '%s'" is in effect}; - -use constant ERROR_58_HINTS => q{Non-subroutine %s hints for %s are not supported under Perl 5.8.x}; - -# Older versions of IPC::System::Simple don't support all the -# features we need. - -use constant MIN_IPC_SYS_SIMPLE_VER => 0.12; - -# All the Fatal/autodie modules share the same version number. -our $VERSION = '2.06_01'; - -our $Debug ||= 0; - -# EWOULDBLOCK values for systems that don't supply their own. -# Even though this is defined with our, that's to help our -# test code. Please don't rely upon this variable existing in -# the future. - -our %_EWOULDBLOCK = ( - MSWin32 => 33, -); - -# We have some tags that can be passed in for use with import. -# These are all assumed to be CORE:: - -my %TAGS = ( - ':io' => [qw(:dbm :file :filesys :ipc :socket - read seek sysread syswrite sysseek )], - ':dbm' => [qw(dbmopen dbmclose)], - ':file' => [qw(open close flock sysopen fcntl fileno binmode - ioctl truncate)], - ':filesys' => [qw(opendir closedir chdir link unlink rename mkdir - symlink rmdir readlink umask)], - ':ipc' => [qw(:msg :semaphore :shm pipe)], - ':msg' => [qw(msgctl msgget msgrcv msgsnd)], - ':threads' => [qw(fork)], - ':semaphore'=>[qw(semctl semget semop)], - ':shm' => [qw(shmctl shmget shmread)], - ':system' => [qw(system exec)], - - # Can we use qw(getpeername getsockname)? What do they do on failure? - # TODO - Can socket return false? - ':socket' => [qw(accept bind connect getsockopt listen recv send - setsockopt shutdown socketpair)], - - # Our defaults don't include system(), because it depends upon - # an optional module, and it breaks the exotic form. - # - # This *may* change in the future. I'd love IPC::System::Simple - # to be a dependency rather than a recommendation, and hence for - # system() to be autodying by default. - - ':default' => [qw(:io :threads)], - - # Version specific tags. These allow someone to specify - # use autodie qw(:1.994) and know exactly what they'll get. - - ':1.994' => [qw(:default)], - ':1.995' => [qw(:default)], - ':1.996' => [qw(:default)], - ':1.997' => [qw(:default)], - ':1.998' => [qw(:default)], - ':1.999' => [qw(:default)], - ':1.999_01' => [qw(:default)], - ':2.00' => [qw(:default)], - ':2.01' => [qw(:default)], - ':2.02' => [qw(:default)], - ':2.03' => [qw(:default)], - ':2.04' => [qw(:default)], - ':2.05' => [qw(:default)], - ':2.06' => [qw(:default)], - ':2.06_01' => [qw(:default)], -); - -$TAGS{':all'} = [ keys %TAGS ]; - -# This hash contains subroutines for which we should -# subroutine() // die() rather than subroutine() || die() - -my %Use_defined_or; - -# CORE::open returns undef on failure. It can legitimately return -# 0 on success, eg: open(my $fh, '-|') || exec(...); - -@Use_defined_or{qw( - CORE::fork - CORE::recv - CORE::send - CORE::open - CORE::fileno - CORE::read - CORE::readlink - CORE::sysread - CORE::syswrite - CORE::sysseek - CORE::umask -)} = (); - -# Cached_fatalised_sub caches the various versions of our -# fatalised subs as they're produced. This means we don't -# have to build our own replacement of CORE::open and friends -# for every single package that wants to use them. - -my %Cached_fatalised_sub = (); - -# Every time we're called with package scope, we record the subroutine -# (including package or CORE::) in %Package_Fatal. This allows us -# to detect illegal combinations of autodie and Fatal, and makes sure -# we don't accidently make a Fatal function autodying (which isn't -# very useful). - -my %Package_Fatal = (); - -# The first time we're called with a user-sub, we cache it here. -# In the case of a "no autodie ..." we put back the cached copy. - -my %Original_user_sub = (); - -# Is_fatalised_sub simply records a big map of fatalised subroutine -# refs. It means we can avoid repeating work, or fatalising something -# we've already processed. - -my %Is_fatalised_sub = (); -tie %Is_fatalised_sub, 'Tie::RefHash'; - -# We use our package in a few hash-keys. Having it in a scalar is -# convenient. The "guard $PACKAGE" string is used as a key when -# setting up lexical guards. - -my $PACKAGE = __PACKAGE__; -my $PACKAGE_GUARD = "guard $PACKAGE"; -my $NO_PACKAGE = "no $PACKAGE"; # Used to detect 'no autodie' - -# Here's where all the magic happens when someone write 'use Fatal' -# or 'use autodie'. - -sub import { - my $class = shift(@_); - my $void = 0; - my $lexical = 0; - my $insist_hints = 0; - - my ($pkg, $filename) = caller(); - - @_ or return; # 'use Fatal' is a no-op. - - # If we see the :lexical flag, then _all_ arguments are - # changed lexically - - if ($_[0] eq LEXICAL_TAG) { - $lexical = 1; - shift @_; - - # If we see no arguments and :lexical, we assume they - # wanted ':default'. - - if (@_ == 0) { - push(@_, ':default'); - } - - # Don't allow :lexical with :void, it's needlessly confusing. - if ( grep { $_ eq VOID_TAG } @_ ) { - croak(ERROR_VOID_LEX); - } - } - - if ( grep { $_ eq LEXICAL_TAG } @_ ) { - # If we see the lexical tag as the non-first argument, complain. - croak(ERROR_LEX_FIRST); - } - - my @fatalise_these = @_; - - # Thiese subs will get unloaded at the end of lexical scope. - my %unload_later; - - # This hash helps us track if we've alredy done work. - my %done_this; - - # NB: we're using while/shift rather than foreach, since - # we'll be modifying the array as we walk through it. - - while (my $func = shift @fatalise_these) { - - if ($func eq VOID_TAG) { - - # When we see :void, set the void flag. - $void = 1; - - } elsif ($func eq INSIST_TAG) { - - $insist_hints = 1; - - } elsif (exists $TAGS{$func}) { - - # When it's a tag, expand it. - push(@fatalise_these, @{ $TAGS{$func} }); - - } else { - - # Otherwise, fatalise it. - - # Check to see if there's an insist flag at the front. - # If so, remove it, and insist we have hints for this sub. - my $insist_this; - - if ($func =~ s/^!//) { - $insist_this = 1; - } - - # TODO: Even if we've already fatalised, we should - # check we've done it with hints (if $insist_hints). - - # If we've already made something fatal this call, - # then don't do it twice. - - next if $done_this{$func}; - - # We're going to make a subroutine fatalistic. - # However if we're being invoked with 'use Fatal qw(x)' - # and we've already been called with 'no autodie qw(x)' - # in the same scope, we consider this to be an error. - # Mixing Fatal and autodie effects was considered to be - # needlessly confusing on p5p. - - my $sub = $func; - $sub = "${pkg}::$sub" unless $sub =~ /::/; - - # If we're being called as Fatal, and we've previously - # had a 'no X' in scope for the subroutine, then complain - # bitterly. - - if (! $lexical and $^H{$NO_PACKAGE}{$sub}) { - croak(sprintf(ERROR_FATAL_CONFLICT, $func, $func)); - } - - # We're not being used in a confusing way, so make - # the sub fatal. Note that _make_fatal returns the - # old (original) version of the sub, or undef for - # built-ins. - - my $sub_ref = $class->_make_fatal( - $func, $pkg, $void, $lexical, $filename, - ( $insist_this || $insist_hints ) - ); - - $done_this{$func}++; - - $Original_user_sub{$sub} ||= $sub_ref; - - # If we're making lexical changes, we need to arrange - # for them to be cleaned at the end of our scope, so - # record them here. - - $unload_later{$func} = $sub_ref if $lexical; - } - } - - if ($lexical) { - - # Dark magic to have autodie work under 5.8 - # Copied from namespace::clean, that copied it from - # autobox, that found it on an ancient scroll written - # in blood. - - # This magic bit causes %^H to be lexically scoped. - - $^H |= 0x020000; - - # Our package guard gets invoked when we leave our lexical - # scope. - - push(@ { $^H{$PACKAGE_GUARD} }, autodie::Scope::Guard->new(sub { - $class->_install_subs($pkg, \%unload_later); - })); - - } - - return; - -} - -# The code here is originally lifted from namespace::clean, -# by Robert "phaylon" Sedlacek. -# -# It's been redesigned after feedback from ikegami on perlmonks. -# See http://perlmonks.org/?node_id=693338 . Ikegami rocks. -# -# Given a package, and hash of (subname => subref) pairs, -# we install the given subroutines into the package. If -# a subref is undef, the subroutine is removed. Otherwise -# it replaces any existing subs which were already there. - -sub _install_subs { - my ($class, $pkg, $subs_to_reinstate) = @_; - - my $pkg_sym = "${pkg}::"; - - while(my ($sub_name, $sub_ref) = each %$subs_to_reinstate) { - - my $full_path = $pkg_sym.$sub_name; - - # Copy symbols across to temp area. - - no strict 'refs'; ## no critic - - local *__tmp = *{ $full_path }; - - # Nuke the old glob. - { no strict; delete $pkg_sym->{$sub_name}; } ## no critic - - # Copy innocent bystanders back. Note that we lose - # formats; it seems that Perl versions up to 5.10.0 - # have a bug which causes copying formats to end up in - # the scalar slot. Thanks to Ben Morrow for spotting this. - - foreach my $slot (qw( SCALAR ARRAY HASH IO ) ) { - next unless defined *__tmp{ $slot }; - *{ $full_path } = *__tmp{ $slot }; - } - - # Put back the old sub (if there was one). - - if ($sub_ref) { - - no strict; ## no critic - *{ $pkg_sym . $sub_name } = $sub_ref; - } - } - - return; -} - -sub unimport { - my $class = shift; - - # Calling "no Fatal" must start with ":lexical" - if ($_[0] ne LEXICAL_TAG) { - croak(sprintf(ERROR_NO_LEX,$class)); - } - - shift @_; # Remove :lexical - - my $pkg = (caller)[0]; - - # If we've been called with arguments, then the developer - # has explicitly stated 'no autodie qw(blah)', - # in which case, we disable Fatalistic behaviour for 'blah'. - - my @unimport_these = @_ ? @_ : ':all'; - - while (my $symbol = shift @unimport_these) { - - if ($symbol =~ /^:/) { - - # Looks like a tag! Expand it! - push(@unimport_these, @{ $TAGS{$symbol} }); - - next; - } - - my $sub = $symbol; - $sub = "${pkg}::$sub" unless $sub =~ /::/; - - # If 'blah' was already enabled with Fatal (which has package - # scope) then, this is considered an error. - - if (exists $Package_Fatal{$sub}) { - croak(sprintf(ERROR_AUTODIE_CONFLICT,$symbol,$symbol)); - } - - # Record 'no autodie qw($sub)' as being in effect. - # This is to catch conflicting semantics elsewhere - # (eg, mixing Fatal with no autodie) - - $^H{$NO_PACKAGE}{$sub} = 1; - - if (my $original_sub = $Original_user_sub{$sub}) { - # Hey, we've got an original one of these, put it back. - $class->_install_subs($pkg, { $symbol => $original_sub }); - next; - } - - # We don't have an original copy of the sub, on the assumption - # it's core (or doesn't exist), we'll just nuke it. - - $class->_install_subs($pkg,{ $symbol => undef }); - - } - - return; - -} - -# TODO - This is rather terribly inefficient right now. - -# NB: Perl::Critic's dump-autodie-tag-contents depends upon this -# continuing to work. - -{ - my %tag_cache; - - sub _expand_tag { - my ($class, $tag) = @_; - - if (my $cached = $tag_cache{$tag}) { - return $cached; - } - - if (not exists $TAGS{$tag}) { - croak "Invalid exception class $tag"; - } - - my @to_process = @{$TAGS{$tag}}; - - my @taglist = (); - - while (my $item = shift @to_process) { - if ($item =~ /^:/) { - push(@to_process, @{$TAGS{$item}} ); - } else { - push(@taglist, "CORE::$item"); - } - } - - $tag_cache{$tag} = \@taglist; - - return \@taglist; - - } - -} - -# This code is from the original Fatal. It scares me. -# It is 100% compatible with the 5.10.0 Fatal module, right down -# to the scary 'XXXX' comment. ;) - -sub fill_protos { - my $proto = shift; - my ($n, $isref, @out, @out1, $seen_semi) = -1; - while ($proto =~ /\S/) { - $n++; - push(@out1,[$n,@out]) if $seen_semi; - push(@out, $1 . "{\$_[$n]}"), next if $proto =~ s/^\s*\\([\@%\$\&])//; - push(@out, "\$_[$n]"), next if $proto =~ s/^\s*([_*\$&])//; - push(@out, "\@_[$n..\$#_]"), last if $proto =~ s/^\s*(;\s*)?\@//; - $seen_semi = 1, $n--, next if $proto =~ s/^\s*;//; # XXXX ???? - die "Internal error: Unknown prototype letters: \"$proto\""; - } - push(@out1,[$n+1,@out]); - return @out1; -} - -# This is a backwards compatible version of _write_invocation. It's -# recommended you don't use it. - -sub write_invocation { - my ($core, $call, $name, $void, @args) = @_; - - return Fatal->_write_invocation( - $core, $call, $name, $void, - 0, # Lexical flag - undef, # Sub, unused in legacy mode - undef, # Subref, unused in legacy mode. - @args - ); -} - -# This version of _write_invocation is used internally. It's not -# recommended you call it from external code, as the interface WILL -# change in the future. - -sub _write_invocation { - - my ($class, $core, $call, $name, $void, $lexical, $sub, $sref, @argvs) = @_; - - if (@argvs == 1) { # No optional arguments - - my @argv = @{$argvs[0]}; - shift @argv; - - return $class->_one_invocation($core,$call,$name,$void,$sub,! $lexical, $sref, @argv); - - } else { - my $else = "\t"; - my (@out, @argv, $n); - while (@argvs) { - @argv = @{shift @argvs}; - $n = shift @argv; - - push @out, "${else}if (\@_ == $n) {\n"; - $else = "\t} els"; - - push @out, $class->_one_invocation($core,$call,$name,$void,$sub,! $lexical, $sref, @argv); - } - push @out, qq[ - } - die "Internal error: $name(\@_): Do not expect to get ", scalar(\@_), " arguments"; - ]; - - return join '', @out; - } -} - - -# This is a slim interface to ensure backward compatibility with -# anyone doing very foolish things with old versions of Fatal. - -sub one_invocation { - my ($core, $call, $name, $void, @argv) = @_; - - return Fatal->_one_invocation( - $core, $call, $name, $void, - undef, # Sub. Unused in back-compat mode. - 1, # Back-compat flag - undef, # Subref, unused in back-compat mode. - @argv - ); - -} - -# This is the internal interface that generates code. -# NOTE: This interface WILL change in the future. Please do not -# call this subroutine directly. - -# TODO: Whatever's calling this code has already looked up hints. Pass -# them in, rather than look them up a second time. - -sub _one_invocation { - my ($class, $core, $call, $name, $void, $sub, $back_compat, $sref, @argv) = @_; - - - # If someone is calling us directly (a child class perhaps?) then - # they could try to mix void without enabling backwards - # compatibility. We just don't support this at all, so we gripe - # about it rather than doing something unwise. - - if ($void and not $back_compat) { - Carp::confess("Internal error: :void mode not supported with $class"); - } - - # @argv only contains the results of the in-built prototype - # function, and is therefore safe to interpolate in the - # code generators below. - - # TODO - The following clobbers context, but that's what the - # old Fatal did. Do we care? - - if ($back_compat) { - - # Use Fatal qw(system) will never be supported. It generated - # a compile-time error with legacy Fatal, and there's no reason - # to support it when autodie does a better job. - - if ($call eq 'CORE::system') { - return q{ - croak("UNIMPLEMENTED: use Fatal qw(system) not supported."); - }; - } - - local $" = ', '; - - if ($void) { - return qq/return (defined wantarray)?$call(@argv): - $call(@argv) || croak "Can't $name(\@_)/ . - ($core ? ': $!' : ', \$! is \"$!\"') . '"' - } else { - return qq{return $call(@argv) || croak "Can't $name(\@_)} . - ($core ? ': $!' : ', \$! is \"$!\"') . '"'; - } - } - - # The name of our original function is: - # $call if the function is CORE - # $sub if our function is non-CORE - - # The reason for this is that $call is what we're actualling - # calling. For our core functions, this is always - # CORE::something. However for user-defined subs, we're about to - # replace whatever it is that we're calling; as such, we actually - # calling a subroutine ref. - - my $human_sub_name = $core ? $call : $sub; - - # Should we be testing to see if our result is defined, or - # just true? - - my $use_defined_or; - - my $hints; # All user-sub hints, including list hints. - - if ( $core ) { - - # Core hints are built into autodie. - - $use_defined_or = exists ( $Use_defined_or{$call} ); - - } - else { - - # User sub hints are looked up using autodie::hints, - # since users may wish to add their own hints. - - require autodie::hints; - - $hints = autodie::hints->get_hints_for( $sref ); - - # We'll look up the sub's fullname. This means we - # get better reports of where it came from in our - # error messages, rather than what imported it. - - $human_sub_name = autodie::hints->sub_fullname( $sref ); - - } - - # Checks for special core subs. - - if ($call eq 'CORE::system') { - - # Leverage IPC::System::Simple if we're making an autodying - # system. - - local $" = ", "; - - # We need to stash $@ into $E, rather than using - # local $@ for the whole sub. If we don't then - # any exceptions from internal errors in autodie/Fatal - # will mysteriously disappear before propogating - # upwards. - - return qq{ - my \$retval; - my \$E; - - - { - local \$@; - - eval { - \$retval = IPC::System::Simple::system(@argv); - }; - - \$E = \$@; - } - - if (\$E) { - - # TODO - This can't be overridden in child - # classes! - - die autodie::exception::system->new( - function => q{CORE::system}, args => [ @argv ], - message => "\$E", errno => \$!, - ); - } - - return \$retval; - }; - - } - - local $" = ', '; - - # If we're going to throw an exception, here's the code to use. - my $die = qq{ - die $class->throw( - function => q{$human_sub_name}, args => [ @argv ], - pragma => q{$class}, errno => \$!, - context => \$context, return => \$retval, - eval_error => \$@ - ) - }; - - if ($call eq 'CORE::flock') { - - # flock needs special treatment. When it fails with - # LOCK_UN and EWOULDBLOCK, then it's not really fatal, it just - # means we couldn't get the lock right now. - - require POSIX; # For POSIX::EWOULDBLOCK - - local $@; # Don't blat anyone else's $@. - - # Ensure that our vendor supports EWOULDBLOCK. If they - # don't (eg, Windows), then we use known values for its - # equivalent on other systems. - - my $EWOULDBLOCK = eval { POSIX::EWOULDBLOCK(); } - || $_EWOULDBLOCK{$^O} - || _autocroak("Internal error - can't overload flock - EWOULDBLOCK not defined on this system."); - - require Fcntl; # For Fcntl::LOCK_NB - - return qq{ - - my \$context = wantarray() ? "list" : "scalar"; - - # Try to flock. If successful, return it immediately. - - my \$retval = $call(@argv); - return \$retval if \$retval; - - # If we failed, but we're using LOCK_NB and - # returned EWOULDBLOCK, it's not a real error. - - if (\$_[1] & Fcntl::LOCK_NB() and \$! == $EWOULDBLOCK ) { - return \$retval; - } - - # Otherwise, we failed. Die noisily. - - $die; - - }; - } - - # AFAIK everything that can be given an unopned filehandle - # will fail if it tries to use it, so we don't really need - # the 'unopened' warning class here. Especially since they - # then report the wrong line number. - - # Other warnings are disabled because they produce excessive - # complaints from smart-match hints under 5.10.1. - - my $code = qq[ - no warnings qw(unopened uninitialized numeric); - - if (wantarray) { - my \@results = $call(@argv); - my \$retval = \\\@results; - my \$context = "list"; - - ]; - - if ( $hints and ( ref($hints->{list} ) || "" ) eq 'CODE' ) { - - # NB: Subroutine hints are passed as a full list. - # This differs from the 5.10.0 smart-match behaviour, - # but means that context unaware subroutines can use - # the same hints in both list and scalar context. - - $code .= qq{ - if ( \$hints->{list}->(\@results) ) { $die }; - }; - } - elsif ( PERL510 and $hints ) { - $code .= qq{ - if ( \@results ~~ \$hints->{list} ) { $die }; - }; - } - elsif ( $hints ) { - croak sprintf(ERROR_58_HINTS, 'list', $sub); - } - else { - $code .= qq{ - # An empty list, or a single undef is failure - if (! \@results or (\@results == 1 and ! defined \$results[0])) { - $die; - } - } - } - - # Tidy up the end of our wantarray call. - - $code .= qq[ - return \@results; - } - ]; - - - # Otherwise, we're in scalar context. - # We're never in a void context, since we have to look - # at the result. - - $code .= qq{ - my \$retval = $call(@argv); - my \$context = "scalar"; - }; - - if ( $hints and ( ref($hints->{scalar} ) || "" ) eq 'CODE' ) { - - # We always call code refs directly, since that always - # works in 5.8.x, and always works in 5.10.1 - - return $code .= qq{ - if ( \$hints->{scalar}->(\$retval) ) { $die }; - return \$retval; - }; - - } - elsif (PERL510 and $hints) { - return $code . qq{ - - if ( \$retval ~~ \$hints->{scalar} ) { $die }; - - return \$retval; - }; - } - elsif ( $hints ) { - croak sprintf(ERROR_58_HINTS, 'scalar', $sub); - } - - return $code . - ( $use_defined_or ? qq{ - - $die if not defined \$retval; - - return \$retval; - - } : qq{ - - return \$retval || $die; - - } ) ; - -} - -# This returns the old copy of the sub, so we can -# put it back at end of scope. - -# TODO : Check to make sure prototypes are restored correctly. - -# TODO: Taking a huge list of arguments is awful. Rewriting to -# take a hash would be lovely. - -# TODO - BACKCOMPAT - This is not yet compatible with 5.10.0 - -sub _make_fatal { - my($class, $sub, $pkg, $void, $lexical, $filename, $insist) = @_; - my($name, $code, $sref, $real_proto, $proto, $core, $call, $hints); - my $ini = $sub; - - $sub = "${pkg}::$sub" unless $sub =~ /::/; - - # Figure if we're using lexical or package semantics and - # twiddle the appropriate bits. - - if (not $lexical) { - $Package_Fatal{$sub} = 1; - } - - # TODO - We *should* be able to do skipping, since we know when - # we've lexicalised / unlexicalised a subroutine. - - $name = $sub; - $name =~ s/.*::// or $name =~ s/^&//; - - warn "# _make_fatal: sub=$sub pkg=$pkg name=$name void=$void\n" if $Debug; - croak(sprintf(ERROR_BADNAME, $class, $name)) unless $name =~ /^\w+$/; - - if (defined(&$sub)) { # user subroutine - - # NOTE: Previously we would localise $@ at this point, so - # the following calls to eval {} wouldn't interfere with anything - # that's already in $@. Unfortunately, it would also stop - # any of our croaks from triggering(!), which is even worse. - - # This could be something that we've fatalised that - # was in core. - - if ( $Package_Fatal{$sub} and do { local $@; eval { prototype "CORE::$name" } } ) { - - # Something we previously made Fatal that was core. - # This is safe to replace with an autodying to core - # version. - - $core = 1; - $call = "CORE::$name"; - $proto = prototype $call; - - # We return our $sref from this subroutine later - # on, indicating this subroutine should be placed - # back when we're finished. - - $sref = \&$sub; - - } else { - - # If this is something we've already fatalised or played with, - # then look-up the name of the original sub for the rest of - # our processing. - - $sub = $Is_fatalised_sub{\&$sub} || $sub; - - # A regular user sub, or a user sub wrapping a - # core sub. - - $sref = \&$sub; - $proto = prototype $sref; - $call = '&$sref'; - require autodie::hints; - - $hints = autodie::hints->get_hints_for( $sref ); - - # If we've insisted on hints, but don't have them, then - # bail out! - - if ($insist and not $hints) { - croak(sprintf(ERROR_NOHINTS, $name)); - } - - # Otherwise, use the default hints if we don't have - # any. - - $hints ||= autodie::hints::DEFAULT_HINTS(); - - } - - } elsif ($sub eq $ini && $sub !~ /^CORE::GLOBAL::/) { - # Stray user subroutine - croak(sprintf(ERROR_NOTSUB,$sub)); - - } elsif ($name eq 'system') { - - # If we're fatalising system, then we need to load - # helper code. - - # The business with $E is to avoid clobbering our caller's - # $@, and to avoid $@ being localised when we croak. - - my $E; - - { - local $@; - - eval { - require IPC::System::Simple; # Only load it if we need it. - require autodie::exception::system; - }; - $E = $@; - } - - if ($E) { croak ERROR_NO_IPC_SYS_SIMPLE; } - - # Make sure we're using a recent version of ISS that actually - # support fatalised system. - if ($IPC::System::Simple::VERSION < MIN_IPC_SYS_SIMPLE_VER) { - croak sprintf( - ERROR_IPC_SYS_SIMPLE_OLD, MIN_IPC_SYS_SIMPLE_VER, - $IPC::System::Simple::VERSION - ); - } - - $call = 'CORE::system'; - $name = 'system'; - $core = 1; - - } elsif ($name eq 'exec') { - # Exec doesn't have a prototype. We don't care. This - # breaks the exotic form with lexical scope, and gives - # the regular form a "do or die" beaviour as expected. - - $call = 'CORE::exec'; - $name = 'exec'; - $core = 1; - - } else { # CORE subroutine - my $E; - { - local $@; - $proto = eval { prototype "CORE::$name" }; - $E = $@; - } - croak(sprintf(ERROR_NOT_BUILT,$name)) if $E; - croak(sprintf(ERROR_CANT_OVERRIDE,$name)) if not defined $proto; - $core = 1; - $call = "CORE::$name"; - } - - if (defined $proto) { - $real_proto = " ($proto)"; - } else { - $real_proto = ''; - $proto = '@'; - } - - my $true_name = $core ? $call : $sub; - - # TODO: This caching works, but I don't like using $void and - # $lexical as keys. In particular, I suspect our code may end up - # wrapping already wrapped code when autodie and Fatal are used - # together. - - # NB: We must use '$sub' (the name plus package) and not - # just '$name' (the short name) here. Failing to do so - # results code that's in the wrong package, and hence has - # access to the wrong package filehandles. - - if (my $subref = $Cached_fatalised_sub{$class}{$sub}{$void}{$lexical}) { - $class->_install_subs($pkg, { $name => $subref }); - return $sref; - } - - $code = qq[ - sub$real_proto { - local(\$", \$!) = (', ', 0); # TODO - Why do we do this? - ]; - - # Don't have perl whine if exec fails, since we'll be handling - # the exception now. - $code .= "no warnings qw(exec);\n" if $call eq "CORE::exec"; - - my @protos = fill_protos($proto); - $code .= $class->_write_invocation($core, $call, $name, $void, $lexical, $sub, $sref, @protos); - $code .= "}\n"; - warn $code if $Debug; - - # I thought that changing package was a monumental waste of - # time for CORE subs, since they'll always be the same. However - # that's not the case, since they may refer to package-based - # filehandles (eg, with open). - # - # There is potential to more aggressively cache core subs - # that we know will never want to interact with package variables - # and filehandles. - - { - no strict 'refs'; ## no critic # to avoid: Can't use string (...) as a symbol ref ... - - my $E; - - { - local $@; - $code = eval("package $pkg; use Carp; $code"); ## no critic - $E = $@; - } - - if (not $code) { - croak("Internal error in autodie/Fatal processing $true_name: $E"); - - } - } - - # Now we need to wrap our fatalised sub inside an itty bitty - # closure, which can detect if we've leaked into another file. - # Luckily, we only need to do this for lexical (autodie) - # subs. Fatal subs can leak all they want, it's considered - # a "feature" (or at least backwards compatible). - - # TODO: Cache our leak guards! - - # TODO: This is pretty hairy code. A lot more tests would - # be really nice for this. - - my $leak_guard; - - if ($lexical) { - - $leak_guard = qq< - package $pkg; - - sub$real_proto { - - # If we're inside a string eval, we can end up with a - # whacky filename. The following code allows autodie - # to propagate correctly into string evals. - - my \$caller_level = 0; - - my \$caller; - - while ( (\$caller = (caller \$caller_level)[1]) =~ m{^\\(eval \\d+\\)\$} ) { - - # If our filename is actually an eval, and we - # reach it, then go to our autodying code immediatately. - - goto &\$code if (\$caller eq \$filename); - \$caller_level++; - } - - # We're now out of the eval stack. - - # If we're called from the correct file, then use the - # autodying code. - goto &\$code if ((caller \$caller_level)[1] eq \$filename); - - # Oh bother, we've leaked into another file. Call the - # original code. Note that \$sref may actually be a - # reference to a Fatalised version of a core built-in. - # That's okay, because Fatal *always* leaks between files. - - goto &\$sref if \$sref; - >; - - - # If we're here, it must have been a core subroutine called. - # Warning: The following code may disturb some viewers. - - # TODO: It should be possible to combine this with - # write_invocation(). - - foreach my $proto (@protos) { - local $" = ", "; # So @args is formatted correctly. - my ($count, @args) = @$proto; - $leak_guard .= qq< - if (\@_ == $count) { - return $call(@args); - } - >; - } - - $leak_guard .= qq< croak "Internal error in Fatal/autodie. Leak-guard failure"; } >; - - # warn "$leak_guard\n"; - - my $E; - { - local $@; - - $leak_guard = eval $leak_guard; ## no critic - - $E = $@; - } - - die "Internal error in $class: Leak-guard installation failure: $E" if $E; - } - - my $installed_sub = $leak_guard || $code; - - $class->_install_subs($pkg, { $name => $installed_sub }); - - $Cached_fatalised_sub{$class}{$sub}{$void}{$lexical} = $installed_sub; - - # Cache that we've now overriddent this sub. If we get called - # again, we may need to find that find subroutine again (eg, for hints). - - $Is_fatalised_sub{$installed_sub} = $sref; - - return $sref; - -} - -# This subroutine exists primarily so that child classes can override -# it to point to their own exception class. Doing this is significantly -# less complex than overriding throw() - -sub exception_class { return "autodie::exception" }; - -{ - my %exception_class_for; - my %class_loaded; - - sub throw { - my ($class, @args) = @_; - - # Find our exception class if we need it. - my $exception_class = - $exception_class_for{$class} ||= $class->exception_class; - - if (not $class_loaded{$exception_class}) { - if ($exception_class =~ /[^\w:']/) { - confess "Bad exception class '$exception_class'.\nThe '$class->exception_class' method wants to use $exception_class\nfor exceptions, but it contains characters which are not word-characters or colons."; - } - - # Alas, Perl does turn barewords into modules unless they're - # actually barewords. As such, we're left doing a string eval - # to make sure we load our file correctly. - - my $E; - - { - local $@; # We can't clobber $@, it's wrong! - eval "require $exception_class"; ## no critic - $E = $@; # Save $E despite ending our local. - } - - # We need quotes around $@ to make sure it's stringified - # while still in scope. Without them, we run the risk of - # $@ having been cleared by us exiting the local() block. - - confess "Failed to load '$exception_class'.\nThis may be a typo in the '$class->exception_class' method,\nor the '$exception_class' module may not exist.\n\n $E" if $E; - - $class_loaded{$exception_class}++; - - } - - return $exception_class->new(@args); - } -} - -# For some reason, dying while replacing our subs doesn't -# kill our calling program. It simply stops the loading of -# autodie and keeps going with everything else. The _autocroak -# sub allows us to die with a vegence. It should *only* ever be -# used for serious internal errors, since the results of it can't -# be captured. - -sub _autocroak { - warn Carp::longmess(@_); - exit(255); # Ugh! -} - -package autodie::Scope::Guard; - -# This code schedules the cleanup of subroutines at the end of -# scope. It's directly inspired by chocolateboy's excellent -# Scope::Guard module. - -sub new { - my ($class, $handler) = @_; - - return bless $handler, $class; -} - -sub DESTROY { - my ($self) = @_; - - $self->(); -} - -1; - -__END__ - -=head1 NAME - -Fatal - Replace functions with equivalents which succeed or die - -=head1 SYNOPSIS - - use Fatal qw(open close); - - open(my $fh, "<", $filename); # No need to check errors! - - use File::Copy qw(move); - use Fatal qw(move); - - move($file1, $file2); # No need to check errors! - - sub juggle { . . . } - Fatal->import('juggle'); - -=head1 BEST PRACTICE - -B<Fatal has been obsoleted by the new L<autodie> pragma.> Please use -L<autodie> in preference to C<Fatal>. L<autodie> supports lexical scoping, -throws real exception objects, and provides much nicer error messages. - -The use of C<:void> with Fatal is discouraged. - -=head1 DESCRIPTION - -C<Fatal> provides a way to conveniently replace -functions which normally return a false value when they fail with -equivalents which raise exceptions if they are not successful. This -lets you use these functions without having to test their return -values explicitly on each call. Exceptions can be caught using -C<eval{}>. See L<perlfunc> and L<perlvar> for details. - -The do-or-die equivalents are set up simply by calling Fatal's -C<import> routine, passing it the names of the functions to be -replaced. You may wrap both user-defined functions and overridable -CORE operators (except C<exec>, C<system>, C<print>, or any other -built-in that cannot be expressed via prototypes) in this way. - -If the symbol C<:void> appears in the import list, then functions -named later in that import list raise an exception only when -these are called in void context--that is, when their return -values are ignored. For example - - use Fatal qw/:void open close/; - - # properly checked, so no exception raised on error - if (not open(my $fh, '<', '/bogotic') { - warn "Can't open /bogotic: $!"; - } - - # not checked, so error raises an exception - close FH; - -The use of C<:void> is discouraged, as it can result in exceptions -not being thrown if you I<accidentally> call a method without -void context. Use L<autodie> instead if you need to be able to -disable autodying/Fatal behaviour for a small block of code. - -=head1 DIAGNOSTICS - -=over 4 - -=item Bad subroutine name for Fatal: %s - -You've called C<Fatal> with an argument that doesn't look like -a subroutine name, nor a switch that this version of Fatal -understands. - -=item %s is not a Perl subroutine - -You've asked C<Fatal> to try and replace a subroutine which does not -exist, or has not yet been defined. - -=item %s is neither a builtin, nor a Perl subroutine - -You've asked C<Fatal> to replace a subroutine, but it's not a Perl -built-in, and C<Fatal> couldn't find it as a regular subroutine. -It either doesn't exist or has not yet been defined. - -=item Cannot make the non-overridable %s fatal - -You've tried to use C<Fatal> on a Perl built-in that can't be -overridden, such as C<print> or C<system>, which means that -C<Fatal> can't help you, although some other modules might. -See the L</"SEE ALSO"> section of this documentation. - -=item Internal error: %s - -You've found a bug in C<Fatal>. Please report it using -the C<perlbug> command. - -=back - -=head1 BUGS - -C<Fatal> clobbers the context in which a function is called and always -makes it a scalar context, except when the C<:void> tag is used. -This problem does not exist in L<autodie>. - -"Used only once" warnings can be generated when C<autodie> or C<Fatal> -is used with package filehandles (eg, C<FILE>). It's strongly recommended -you use scalar filehandles instead. - -=head1 AUTHOR - -Original module by Lionel Cons (CERN). - -Prototype updates by Ilya Zakharevich <ilya@math.ohio-state.edu>. - -L<autodie> support, bugfixes, extended diagnostics, C<system> -support, and major overhauling by Paul Fenwick <pjf@perltraining.com.au> - -=head1 LICENSE - -This module is free software, you may distribute it under the -same terms as Perl itself. - -=head1 SEE ALSO - -L<autodie> for a nicer way to use lexical Fatal. - -L<IPC::System::Simple> for a similar idea for calls to C<system()> -and backticks. - -=cut diff --git a/ext/autodie/lib/autodie.pm b/ext/autodie/lib/autodie.pm deleted file mode 100644 index 8e8e7094c7..0000000000 --- a/ext/autodie/lib/autodie.pm +++ /dev/null @@ -1,424 +0,0 @@ -package autodie; -use 5.008; -use strict; -use warnings; - -use Fatal (); -our @ISA = qw(Fatal); -our $VERSION; - -BEGIN { - $VERSION = '2.06_01'; -} - -use constant ERROR_WRONG_FATAL => q{ -Incorrect version of Fatal.pm loaded by autodie. - -The autodie pragma uses an updated version of Fatal to do its -heavy lifting. We seem to have loaded Fatal version %s, which is -probably the version that came with your version of Perl. However -autodie needs version %s, which would have come bundled with -autodie. - -You may be able to solve this problem by adding the following -line of code to your main program, before any use of Fatal or -autodie. - - use lib "%s"; - -}; - -# We have to check we've got the right version of Fatal before we -# try to compile the rest of our code, lest we use a constant -# that doesn't exist. - -BEGIN { - - # If we have the wrong Fatal, then we've probably loaded the system - # one, not our own. Complain, and give a useful hint. ;) - - if ($Fatal::VERSION ne $VERSION) { - my $autodie_path = $INC{'autodie.pm'}; - - $autodie_path =~ s/autodie\.pm//; - - require Carp; - - Carp::croak sprintf( - ERROR_WRONG_FATAL, $Fatal::VERSION, $VERSION, $autodie_path - ); - } -} - -# When passing args to Fatal we want to keep the first arg -# (our package) in place. Hence the splice. - -sub import { - splice(@_,1,0,Fatal::LEXICAL_TAG); - goto &Fatal::import; -} - -sub unimport { - splice(@_,1,0,Fatal::LEXICAL_TAG); - goto &Fatal::unimport; -} - -1; - -__END__ - -=head1 NAME - -autodie - Replace functions with ones that succeed or die with lexical scope - -=head1 SYNOPSIS - - use autodie; # Recommended: implies 'use autodie qw(:default)' - - use autodie qw(:all); # Recommended more: defaults and system/exec. - - use autodie qw(open close); # open/close succeed or die - - open(my $fh, "<", $filename); # No need to check! - - { - no autodie qw(open); # open failures won't die - open(my $fh, "<", $filename); # Could fail silently! - no autodie; # disable all autodies - } - -=head1 DESCRIPTION - - bIlujDI' yIchegh()Qo'; yIHegh()! - - It is better to die() than to return() in failure. - - -- Klingon programming proverb. - -The C<autodie> pragma provides a convenient way to replace functions -that normally return false on failure with equivalents that throw -an exception on failure. - -The C<autodie> pragma has I<lexical scope>, meaning that functions -and subroutines altered with C<autodie> will only change their behaviour -until the end of the enclosing block, file, or C<eval>. - -If C<system> is specified as an argument to C<autodie>, then it -uses L<IPC::System::Simple> to do the heavy lifting. See the -description of that module for more information. - -=head1 EXCEPTIONS - -Exceptions produced by the C<autodie> pragma are members of the -L<autodie::exception> class. The preferred way to work with -these exceptions under Perl 5.10 is as follows: - - use feature qw(switch); - - eval { - use autodie; - - open(my $fh, '<', $some_file); - - my @records = <$fh>; - - # Do things with @records... - - close($fh); - - }; - - given ($@) { - when (undef) { say "No error"; } - when ('open') { say "Error from open"; } - when (':io') { say "Non-open, IO error."; } - when (':all') { say "All other autodie errors." } - default { say "Not an autodie error at all." } - } - -Under Perl 5.8, the C<given/when> structure is not available, so the -following structure may be used: - - eval { - use autodie; - - open(my $fh, '<', $some_file); - - my @records = <$fh>; - - # Do things with @records... - - close($fh); - }; - - if ($@ and $@->isa('autodie::exception')) { - if ($@->matches('open')) { print "Error from open\n"; } - if ($@->matches(':io' )) { print "Non-open, IO error."; } - } elsif ($@) { - # A non-autodie exception. - } - -See L<autodie::exception> for further information on interrogating -exceptions. - -=head1 CATEGORIES - -Autodie uses a simple set of categories to group together similar -built-ins. Requesting a category type (starting with a colon) will -enable autodie for all built-ins beneath that category. For example, -requesting C<:file> will enable autodie for C<close>, C<fcntl>, -C<fileno>, C<open> and C<sysopen>. - -The categories are currently: - - :all - :default - :io - read - seek - sysread - sysseek - syswrite - :dbm - dbmclose - dbmopen - :file - binmode - close - fcntl - fileno - flock - ioctl - open - sysopen - truncate - :filesys - chdir - closedir - opendir - link - mkdir - readlink - rename - rmdir - symlink - unlink - :ipc - pipe - :msg - msgctl - msgget - msgrcv - msgsnd - :semaphore - semctl - semget - semop - :shm - shmctl - shmget - shmread - :socket - accept - bind - connect - getsockopt - listen - recv - send - setsockopt - shutdown - socketpair - :threads - fork - :system - system - exec - - -Note that while the above category system is presently a strict -hierarchy, this should not be assumed. - -A plain C<use autodie> implies C<use autodie qw(:default)>. Note that -C<system> and C<exec> are not enabled by default. C<system> requires -the optional L<IPC::System::Simple> module to be installed, and enabling -C<system> or C<exec> will invalidate their exotic forms. See L</BUGS> -below for more details. - -The syntax: - - use autodie qw(:1.994); - -allows the C<:default> list from a particular version to be used. This -provides the convenience of using the default methods, but the surety -that no behavorial changes will occur if the C<autodie> module is -upgraded. - -C<autodie> can be enabled for all of Perl's built-ins, including -C<system> and C<exec> with: - - use autodie qw(:all); - -=head1 FUNCTION SPECIFIC NOTES - -=head2 flock - -It is not considered an error for C<flock> to return false if it fails -to an C<EWOULDBLOCK> (or equivalent) condition. This means one can -still use the common convention of testing the return value of -C<flock> when called with the C<LOCK_NB> option: - - use autodie; - - if ( flock($fh, LOCK_EX | LOCK_NB) ) { - # We have a lock - } - -Autodying C<flock> will generate an exception if C<flock> returns -false with any other error. - -=head2 system/exec - -The C<system> built-in is considered to have failed in the following -circumstances: - -=over 4 - -=item * - -The command does not start. - -=item * - -The command is killed by a signal. - -=item * - -The command returns a non-zero exit value (but see below). - -=back - -On success, the autodying form of C<system> returns the I<exit value> -rather than the contents of C<$?>. - -Additional allowable exit values can be supplied as an optional first -argument to autodying C<system>: - - system( [ 0, 1, 2 ], $cmd, @args); # 0,1,2 are good exit values - -C<autodie> uses the L<IPC::System::Simple> module to change C<system>. -See its documentation for further information. - -Applying C<autodie> to C<system> or C<exec> causes the exotic -forms C<system { $cmd } @args > or C<exec { $cmd } @args> -to be considered a syntax error until the end of the lexical scope. -If you really need to use the exotic form, you can call C<CORE::system> -or C<CORE::exec> instead, or use C<no autodie qw(system exec)> before -calling the exotic form. - -=head1 GOTCHAS - -Functions called in list context are assumed to have failed if they -return an empty list, or a list consisting only of a single undef -element. - -=head1 DIAGNOSTICS - -=over 4 - -=item :void cannot be used with lexical scope - -The C<:void> option is supported in L<Fatal>, but not -C<autodie>. To workaround this, C<autodie> may be explicitly disabled until -the end of the current block with C<no autodie>. -To disable autodie for only a single function (eg, open) -use C<no autodie qw(open)>. - -=item No user hints defined for %s - -You've insisted on hints for user-subroutines, either by pre-pending -a C<!> to the subroutine name itself, or earlier in the list of arguments -to C<autodie>. However the subroutine in question does not have -any hints available. - -=back - -See also L<Fatal/DIAGNOSTICS>. - -=head1 BUGS - -"Used only once" warnings can be generated when C<autodie> or C<Fatal> -is used with package filehandles (eg, C<FILE>). Scalar filehandles are -strongly recommended instead. - -When using C<autodie> or C<Fatal> with user subroutines, the -declaration of those subroutines must appear before the first use of -C<Fatal> or C<autodie>, or have been exported from a module. -Attempting to use C<Fatal> or C<autodie> on other user subroutines will -result in a compile-time error. - -Due to a bug in Perl, C<autodie> may "lose" any format which has the -same name as an autodying built-in or function. - -C<autodie> may not work correctly if used inside a file with a -name that looks like a string eval, such as F<eval (3)>. - -=head2 autodie and string eval - -Due to the current implementation of C<autodie>, unexpected results -may be seen when used near or with the string version of eval. -I<None of these bugs exist when using block eval>. - -Under Perl 5.8 only, C<autodie> I<does not> propagate into string C<eval> -statements, although it can be explicitly enabled inside a string -C<eval>. - -Under Perl 5.10 only, using a string eval when C<autodie> is in -effect can cause the autodie behaviour to leak into the surrounding -scope. This can be worked around by using a C<no autodie> at the -end of the scope to explicitly remove autodie's effects, or by -avoiding the use of string eval. - -I<None of these bugs exist when using block eval>. The use of -C<autodie> with block eval is considered good practice. - -=head2 REPORTING BUGS - -Please report bugs via the CPAN Request Tracker at -L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=autodie>. - -=head1 FEEDBACK - -If you find this module useful, please consider rating it on the -CPAN Ratings service at -L<http://cpanratings.perl.org/rate?distribution=autodie> . - -The module author loves to hear how C<autodie> has made your life -better (or worse). Feedback can be sent to -E<lt>pjf@perltraining.com.auE<gt>. - -=head1 AUTHOR - -Copyright 2008-2009, Paul Fenwick E<lt>pjf@perltraining.com.auE<gt> - -=head1 LICENSE - -This module is free software. You may distribute it under the -same terms as Perl itself. - -=head1 SEE ALSO - -L<Fatal>, L<autodie::exception>, L<autodie::hints>, L<IPC::System::Simple> - -I<Perl tips, autodie> at -L<http://perltraining.com.au/tips/2008-08-20.html> - -=head1 ACKNOWLEDGEMENTS - -Mark Reed and Roland Giersig -- Klingon translators. - -See the F<AUTHORS> file for full credits. The latest version of this -file can be found at -L<http://github.com/pfenwick/autodie/tree/master/AUTHORS> . - -=cut diff --git a/ext/autodie/lib/autodie/exception.pm b/ext/autodie/lib/autodie/exception.pm deleted file mode 100644 index 8646099c4c..0000000000 --- a/ext/autodie/lib/autodie/exception.pm +++ /dev/null @@ -1,741 +0,0 @@ -package autodie::exception; -use 5.008; -use strict; -use warnings; -use Carp qw(croak); - -our $DEBUG = 0; - -use overload - q{""} => "stringify" -; - -# Overload smart-match only if we're using 5.10 - -use if ($] >= 5.010), overload => '~~' => "matches"; - -our $VERSION = '2.06_01'; - -my $PACKAGE = __PACKAGE__; # Useful to have a scalar for hash keys. - -=head1 NAME - -autodie::exception - Exceptions from autodying functions. - -=head1 SYNOPSIS - - eval { - use autodie; - - open(my $fh, '<', 'some_file.txt'); - - ... - }; - - if (my $E = $@) { - say "Ooops! ",$E->caller," had problems: $@"; - } - - -=head1 DESCRIPTION - -When an L<autodie> enabled function fails, it generates an -C<autodie::exception> object. This can be interrogated to -determine further information about the error that occurred. - -This document is broken into two sections; those methods that -are most useful to the end-developer, and those methods for -anyone wishing to subclass or get very familiar with -C<autodie::exception>. - -=head2 Common Methods - -These methods are intended to be used in the everyday dealing -of exceptions. - -The following assume that the error has been copied into -a separate scalar: - - if ($E = $@) { - ... - } - -This is not required, but is recommended in case any code -is called which may reset or alter C<$@>. - -=cut - -=head3 args - - my $array_ref = $E->args; - -Provides a reference to the arguments passed to the subroutine -that died. - -=cut - -sub args { return $_[0]->{$PACKAGE}{args}; } - -=head3 function - - my $sub = $E->function; - -The subroutine (including package) that threw the exception. - -=cut - -sub function { return $_[0]->{$PACKAGE}{function}; } - -=head3 file - - my $file = $E->file; - -The file in which the error occurred (eg, C<myscript.pl> or -C<MyTest.pm>). - -=cut - -sub file { return $_[0]->{$PACKAGE}{file}; } - -=head3 package - - my $package = $E->package; - -The package from which the exceptional subroutine was called. - -=cut - -sub package { return $_[0]->{$PACKAGE}{package}; } - -=head3 caller - - my $caller = $E->caller; - -The subroutine that I<called> the exceptional code. - -=cut - -sub caller { return $_[0]->{$PACKAGE}{caller}; } - -=head3 line - - my $line = $E->line; - -The line in C<< $E->file >> where the exceptional code was called. - -=cut - -sub line { return $_[0]->{$PACKAGE}{line}; } - -=head3 context - - my $context = $E->context; - -The context in which the subroutine was called. This can be -'list', 'scalar', or undefined (unknown). It will never be 'void', as -C<autodie> always captures the return value in one way or another. - -=cut - -sub context { return $_[0]->{$PACKAGE}{context} } - -=head3 return - - my $return_value = $E->return; - -The value(s) returned by the failed subroutine. When the subroutine -was called in a list context, this will always be a reference to an -array containing the results. When the subroutine was called in -a scalar context, this will be the actual scalar returned. - -=cut - -sub return { return $_[0]->{$PACKAGE}{return} } - -=head3 errno - - my $errno = $E->errno; - -The value of C<$!> at the time when the exception occurred. - -B<NOTE>: This method will leave the main C<autodie::exception> class -and become part of a role in the future. You should only call -C<errno> for exceptions where C<$!> would reasonably have been -set on failure. - -=cut - -# TODO: Make errno part of a role. It doesn't make sense for -# everything. - -sub errno { return $_[0]->{$PACKAGE}{errno}; } - -=head3 eval_error - - my $old_eval_error = $E->eval_error; - -The contents of C<$@> immediately after autodie triggered an -exception. This may be useful when dealing with modules such -as L<Text::Balanced> that set (but do not throw) C<$@> on error. - -=cut - -sub eval_error { return $_[0]->{$PACKAGE}{eval_error}; } - -=head3 matches - - if ( $e->matches('open') ) { ... } - - if ( $e ~~ 'open' ) { ... } - -C<matches> is used to determine whether a -given exception matches a particular role. On Perl 5.10, -using smart-match (C<~~>) with an C<autodie::exception> object -will use C<matches> underneath. - -An exception is considered to match a string if: - -=over 4 - -=item * - -For a string not starting with a colon, the string exactly matches the -package and subroutine that threw the exception. For example, -C<MyModule::log>. If the string does not contain a package name, -C<CORE::> is assumed. - -=item * - -For a string that does start with a colon, if the subroutine -throwing the exception I<does> that behaviour. For example, the -C<CORE::open> subroutine does C<:file>, C<:io> and C<:all>. - -See L<autodie/CATEGORIES> for futher information. - -=back - -=cut - -{ - my (%cache); - - sub matches { - my ($this, $that) = @_; - - # TODO - Handle references - croak "UNIMPLEMENTED" if ref $that; - - my $sub = $this->function; - - if ($DEBUG) { - my $sub2 = $this->function; - warn "Smart-matching $that against $sub / $sub2\n"; - } - - # Direct subname match. - return 1 if $that eq $sub; - return 1 if $that !~ /:/ and "CORE::$that" eq $sub; - return 0 if $that !~ /^:/; - - # Cached match / check tags. - require Fatal; - - if (exists $cache{$sub}{$that}) { - return $cache{$sub}{$that}; - } - - # This rather awful looking line checks to see if our sub is in the - # list of expanded tags, caches it, and returns the result. - - return $cache{$sub}{$that} = grep { $_ eq $sub } @{ $this->_expand_tag($that) }; - } -} - -# This exists primarily so that child classes can override or -# augment it if they wish. - -sub _expand_tag { - my ($this, @args) = @_; - - return Fatal->_expand_tag(@args); -} - -=head2 Advanced methods - -The following methods, while usable from anywhere, are primarily -intended for developers wishing to subclass C<autodie::exception>, -write code that registers custom error messages, or otherwise -work closely with the C<autodie::exception> model. - -=cut - -# The table below records customer formatters. -# TODO - Should this be a package var instead? -# TODO - Should these be in a completely different file, or -# perhaps loaded on demand? Most formatters will never -# get used in most programs. - -my %formatter_of = ( - 'CORE::close' => \&_format_close, - 'CORE::open' => \&_format_open, - 'CORE::dbmopen' => \&_format_dbmopen, - 'CORE::flock' => \&_format_flock, -); - -# TODO: Our tests only check LOCK_EX | LOCK_NB is properly -# formatted. Try other combinations and ensure they work -# correctly. - -sub _format_flock { - my ($this) = @_; - - require Fcntl; - - my $filehandle = $this->args->[0]; - my $raw_mode = $this->args->[1]; - - my $mode_type; - my $lock_unlock; - - if ($raw_mode & Fcntl::LOCK_EX() ) { - $lock_unlock = "lock"; - $mode_type = "for exclusive access"; - } - elsif ($raw_mode & Fcntl::LOCK_SH() ) { - $lock_unlock = "lock"; - $mode_type = "for shared access"; - } - elsif ($raw_mode & Fcntl::LOCK_UN() ) { - $lock_unlock = "unlock"; - $mode_type = ""; - } - else { - # I've got no idea what they're trying to do. - $lock_unlock = "lock"; - $mode_type = "with mode $raw_mode"; - } - - my $cooked_filehandle; - - if ($filehandle and not ref $filehandle) { - - # A package filehandle with a name! - - $cooked_filehandle = " $filehandle"; - } - else { - # Otherwise we have a scalar filehandle. - - $cooked_filehandle = ''; - - } - - local $! = $this->errno; - - return "Can't $lock_unlock filehandle$cooked_filehandle $mode_type: $!"; - -} - -# Default formatter for CORE::dbmopen -sub _format_dbmopen { - my ($this) = @_; - my @args = @{$this->args}; - - # TODO: Presently, $args flattens out the (usually empty) hash - # which is passed as the first argument to dbmopen. This is - # a bug in our args handling code (taking a reference to it would - # be better), but for the moment we'll just examine the end of - # our arguments list for message formatting. - - my $mode = $args[-1]; - my $file = $args[-2]; - - # If we have a mask, then display it in octal, not decimal. - # We don't do this if it already looks octalish, or doesn't - # look like a number. - - if ($mode =~ /^[^\D0]\d+$/) { - $mode = sprintf("0%lo", $mode); - }; - - local $! = $this->errno; - - return "Can't dbmopen(%hash, '$file', $mode): '$!'"; -} - -# Default formatter for CORE::close - -sub _format_close { - my ($this) = @_; - my $close_arg = $this->args->[0]; - - local $! = $this->errno; - - # If we've got an old-style filehandle, mention it. - if ($close_arg and not ref $close_arg) { - return "Can't close filehandle '$close_arg': '$!'"; - } - - # TODO - This will probably produce an ugly error. Test and fix. - return "Can't close($close_arg) filehandle: '$!'"; - -} - -# Default formatter for CORE::open - -use constant _FORMAT_OPEN => "Can't open '%s' for %s: '%s'"; - -sub _format_open_with_mode { - my ($this, $mode, $file, $error) = @_; - - my $wordy_mode; - - if ($mode eq '<') { $wordy_mode = 'reading'; } - elsif ($mode eq '>') { $wordy_mode = 'writing'; } - elsif ($mode eq '>>') { $wordy_mode = 'appending'; } - - return sprintf _FORMAT_OPEN, $file, $wordy_mode, $error if $wordy_mode; - - Carp::confess("Internal autodie::exception error: Don't know how to format mode '$mode'."); - -} - -sub _format_open { - my ($this) = @_; - - my @open_args = @{$this->args}; - - # Use the default formatter for single-arg and many-arg open - if (@open_args <= 1 or @open_args >= 4) { - return $this->format_default; - } - - # For two arg open, we have to extract the mode - if (@open_args == 2) { - my ($fh, $file) = @open_args; - - if (ref($fh) eq "GLOB") { - $fh = '$fh'; - } - - my ($mode) = $file =~ m{ - ^\s* # Spaces before mode - ( - (?> # Non-backtracking subexp. - < # Reading - |>>? # Writing/appending - ) - ) - [^&] # Not an ampersand (which means a dup) - }x; - - if (not $mode) { - # Maybe it's a 2-arg open without any mode at all? - # Detect the most simple case for this, where our - # file consists only of word characters. - - if ( $file =~ m{^\s*\w+\s*$} ) { - $mode = '<' - } - else { - # Otherwise, we've got no idea what's going on. - # Use the default. - return $this->format_default; - } - } - - # Localising $! means perl make make it a pretty error for us. - local $! = $this->errno; - - return $this->_format_open_with_mode($mode, $file, $!); - } - - # Here we must be using three arg open. - - my $file = $open_args[2]; - - local $! = $this->errno; - - my $mode = $open_args[1]; - - local $@; - - my $msg = eval { $this->_format_open_with_mode($mode, $file, $!); }; - - return $msg if $msg; - - # Default message (for pipes and odd things) - - return "Can't open '$file' with mode '$open_args[1]': '$!'"; -} - -=head3 register - - autodie::exception->register( 'CORE::open' => \&mysub ); - -The C<register> method allows for the registration of a message -handler for a given subroutine. The full subroutine name including -the package should be used. - -Registered message handlers will receive the C<autodie::exception> -object as the first parameter. - -=cut - -sub register { - my ($class, $symbol, $handler) = @_; - - croak "Incorrect call to autodie::register" if @_ != 3; - - $formatter_of{$symbol} = $handler; - -} - -=head3 add_file_and_line - - say "Problem occurred",$@->add_file_and_line; - -Returns the string C< at %s line %d>, where C<%s> is replaced with -the filename, and C<%d> is replaced with the line number. - -Primarily intended for use by format handlers. - -=cut - -# Simply produces the file and line number; intended to be added -# to the end of error messages. - -sub add_file_and_line { - my ($this) = @_; - - return sprintf(" at %s line %d\n", $this->file, $this->line); -} - -=head3 stringify - - say "The error was: ",$@->stringify; - -Formats the error as a human readable string. Usually there's no -reason to call this directly, as it is used automatically if an -C<autodie::exception> object is ever used as a string. - -Child classes can override this method to change how they're -stringified. - -=cut - -sub stringify { - my ($this) = @_; - - my $call = $this->function; - - if ($DEBUG) { - my $dying_pkg = $this->package; - my $sub = $this->function; - my $caller = $this->caller; - warn "Stringifing exception for $dying_pkg :: $sub / $caller / $call\n"; - } - - # TODO - This isn't using inheritance. Should it? - if ( my $sub = $formatter_of{$call} ) { - return $sub->($this) . $this->add_file_and_line; - } - - return $this->format_default . $this->add_file_and_line; - -} - -=head3 format_default - - my $error_string = $E->format_default; - -This produces the default error string for the given exception, -I<without using any registered message handlers>. It is primarily -intended to be called from a message handler when they have -been passed an exception they don't want to format. - -Child classes can override this method to change how default -messages are formatted. - -=cut - -# TODO: This produces ugly errors. Is there any way we can -# dig around to find the actual variable names? I know perl 5.10 -# does some dark and terrible magicks to find them for undef warnings. - -sub format_default { - my ($this) = @_; - - my $call = $this->function; - - local $! = $this->errno; - - # TODO: This is probably a good idea for CORE, is it - # a good idea for other subs? - - # Trim package name off dying sub for error messages. - $call =~ s/.*:://; - - # Walk through all our arguments, and... - # - # * Replace undef with the word 'undef' - # * Replace globs with the string '$fh' - # * Quote all other args. - - my @args = @{ $this->args() }; - - foreach my $arg (@args) { - if (not defined($arg)) { $arg = 'undef' } - elsif (ref($arg) eq "GLOB") { $arg = '$fh' } - else { $arg = qq{'$arg'} } - } - - # Format our beautiful error. - - return "Can't $call(". join(q{, }, @args) . "): $!" ; - - # TODO - Handle user-defined errors from hash. - - # TODO - Handle default error messages. - -} - -=head3 new - - my $error = autodie::exception->new( - args => \@_, - function => "CORE::open", - errno => $!, - context => 'scalar', - return => undef, - ); - - -Creates a new C<autodie::exception> object. Normally called -directly from an autodying function. The C<function> argument -is required, its the function we were trying to call that -generated the exception. The C<args> parameter is optional. - -The C<errno> value is optional. In versions of C<autodie::exception> -1.99 and earlier the code would try to automatically use the -current value of C<$!>, but this was unreliable and is no longer -supported. - -Atrributes such as package, file, and caller are determined -automatically, and cannot be specified. - -=cut - -sub new { - my ($class, @args) = @_; - - my $this = {}; - - bless($this,$class); - - # I'd love to use EVERY here, but it causes our code to die - # because it wants to stringify our objects before they're - # initialised, causing everything to explode. - - $this->_init(@args); - - return $this; -} - -sub _init { - - my ($this, %args) = @_; - - # Capturing errno here is not necessarily reliable. - my $original_errno = $!; - - our $init_called = 1; - - my $class = ref $this; - - # We're going to walk up our call stack, looking for the - # first thing that doesn't look like our exception - # code, autodie/Fatal, or some whacky eval. - - my ($package, $file, $line, $sub); - - my $depth = 0; - - while (1) { - $depth++; - - ($package, $file, $line, $sub) = CORE::caller($depth); - - # Skip up the call stack until we find something outside - # of the Fatal/autodie/eval space. - - next if $package->isa('Fatal'); - next if $package->isa($class); - next if $package->isa(__PACKAGE__); - next if $file =~ /^\(eval\s\d+\)$/; - - last; - - } - - # We now have everything correct, *except* for our subroutine - # name. If it's __ANON__ or (eval), then we need to keep on - # digging deeper into our stack to find the real name. However we - # don't update our other information, since that will be correct - # for our current exception. - - my $first_guess_subroutine = $sub; - - while (defined $sub and $sub =~ /^\(eval\)$|::__ANON__$/) { - $depth++; - - $sub = (CORE::caller($depth))[3]; - } - - # If we end up falling out the bottom of our stack, then our - # __ANON__ guess is the best we can get. This includes situations - # where we were called from the top level of a program. - - if (not defined $sub) { - $sub = $first_guess_subroutine; - } - - $this->{$PACKAGE}{package} = $package; - $this->{$PACKAGE}{file} = $file; - $this->{$PACKAGE}{line} = $line; - $this->{$PACKAGE}{caller} = $sub; - $this->{$PACKAGE}{package} = $package; - - $this->{$PACKAGE}{errno} = $args{errno} || 0; - - $this->{$PACKAGE}{context} = $args{context}; - $this->{$PACKAGE}{return} = $args{return}; - $this->{$PACKAGE}{eval_error} = $args{eval_error}; - - $this->{$PACKAGE}{args} = $args{args} || []; - $this->{$PACKAGE}{function}= $args{function} or - croak("$class->new() called without function arg"); - - return $this; - -} - -1; - -__END__ - -=head1 SEE ALSO - -L<autodie>, L<autodie::exception::system> - -=head1 LICENSE - -Copyright (C)2008 Paul Fenwick - -This is free software. You may modify and/or redistribute this -code under the same terms as Perl 5.10 itself, or, at your option, -any later version of Perl 5. - -=head1 AUTHOR - -Paul Fenwick E<lt>pjf@perltraining.com.auE<gt> diff --git a/ext/autodie/lib/autodie/exception/system.pm b/ext/autodie/lib/autodie/exception/system.pm deleted file mode 100644 index 07cd1c9a03..0000000000 --- a/ext/autodie/lib/autodie/exception/system.pm +++ /dev/null @@ -1,81 +0,0 @@ -package autodie::exception::system; -use 5.008; -use strict; -use warnings; -use base 'autodie::exception'; -use Carp qw(croak); - -our $VERSION = '2.06_01'; - -my $PACKAGE = __PACKAGE__; - -=head1 NAME - -autodie::exception::system - Exceptions from autodying system(). - -=head1 SYNOPSIS - - eval { - use autodie qw(system); - - system($cmd, @args); - - }; - - if (my $E = $@) { - say "Ooops! ",$E->caller," had problems: $@"; - } - - -=head1 DESCRIPTION - -This is a L<autodie::exception> class for failures from the -C<system> command. - -Presently there is no way to interrogate an C<autodie::exception::system> -object for the command, exit status, and other information you'd expect -such an object to hold. The interface will be expanded to accommodate -this in the future. - -=cut - -sub _init { - my ($this, %args) = @_; - - $this->{$PACKAGE}{message} = $args{message} - || croak "'message' arg not supplied to autodie::exception::system->new"; - - return $this->SUPER::_init(%args); - -} - -=head2 stringify - -When stringified, C<autodie::exception::system> objects currently -use the message generated by L<IPC::System::Simple>. - -=cut - -sub stringify { - - my ($this) = @_; - - return $this->{$PACKAGE}{message} . $this->add_file_and_line; - -} - -1; - -__END__ - -=head1 LICENSE - -Copyright (C)2008 Paul Fenwick - -This is free software. You may modify and/or redistribute this -code under the same terms as Perl 5.10 itself, or, at your option, -any later version of Perl 5. - -=head1 AUTHOR - -Paul Fenwick E<lt>pjf@perltraining.com.auE<gt> diff --git a/ext/autodie/lib/autodie/hints.pm b/ext/autodie/lib/autodie/hints.pm deleted file mode 100644 index e7be03a047..0000000000 --- a/ext/autodie/lib/autodie/hints.pm +++ /dev/null @@ -1,598 +0,0 @@ -package autodie::hints; - -use strict; -use warnings; - -use constant PERL58 => ( $] < 5.009 ); - -our $VERSION = '2.06_01'; - -=head1 NAME - -autodie::hints - Provide hints about user subroutines to autodie - -=head1 SYNOPSIS - - package Your::Module; - - our %DOES = ( 'autodie::hints::provider' => 1 ); - - sub AUTODIE_HINTS { - return { - foo => { scalar => HINTS, list => SOME_HINTS }, - bar => { scalar => HINTS, list => MORE_HINTS }, - } - } - - # Later, in your main program... - - use Your::Module qw(foo bar); - use autodie qw(:default foo bar); - - foo(); # succeeds or dies based on scalar hints - - # Alternatively, hints can be set on subroutines we've - # imported. - - use autodie::hints; - use Some::Module qw(think_positive); - - BEGIN { - autodie::hints->set_hints_for( - \&think_positive, - { - fail => sub { $_[0] <= 0 } - } - ) - } - use autodie qw(think_positive); - - think_positive(...); # Returns positive or dies. - - -=head1 DESCRIPTION - -=head2 Introduction - -The L<autodie> pragma is very smart when it comes to working with -Perl's built-in functions. The behaviour for these functions are -fixed, and C<autodie> knows exactly how they try to signal failure. - -But what about user-defined subroutines from modules? If you use -C<autodie> on a user-defined subroutine then it assumes the following -behaviour to demonstrate failure: - -=over - -=item * - -A false value, in scalar context - -=item * - -An empty list, in list context - -=item * - -A list containing a single undef, in list context - -=back - -All other return values (including the list of the single zero, and the -list containing a single empty string) are considered successful. However, -real-world code isn't always that easy. Perhaps the code you're working -with returns a string containing the word "FAIL" upon failure, or a -two element list containing C<(undef, "human error message")>. To make -autodie work with these sorts of subroutines, we have -the I<hinting interface>. - -The hinting interface allows I<hints> to be provided to C<autodie> -on how it should detect failure from user-defined subroutines. While -these I<can> be provided by the end-user of C<autodie>, they are ideally -written into the module itself, or into a helper module or sub-class -of C<autodie> itself. - -=head2 What are hints? - -A I<hint> is a subroutine or value that is checked against the -return value of an autodying subroutine. If the match returns true, -C<autodie> considers the subroutine to have failed. - -If the hint provided is a subroutine, then C<autodie> will pass -the complete return value to that subroutine. If the hint is -any other value, then C<autodie> will smart-match against the -value provided. In Perl 5.8.x there is no smart-match operator, and as such -only subroutine hints are supported in these versions. - -Hints can be provided for both scalar and list contexts. Note -that an autodying subroutine will never see a void context, as -C<autodie> always needs to capture the return value for examination. -Autodying subroutines called in void context act as if they're called -in a scalar context, but their return value is discarded after it -has been checked. - -=head2 Example hints - -Hints may consist of scalars, array references, regular expressions and -subroutine references. You can specify different hints for how -failure should be identified in scalar and list contexts. - -These examples apply for use in the C<AUTODIE_HINTS> subroutine and when -calling C<autodie::hints->set_hints_for()>. - -The most common context-specific hints are: - - # Scalar failures always return undef: - { scalar => undef } - - # Scalar failures return any false value [default expectation]: - { scalar => sub { ! $_[0] } } - - # Scalar failures always return zero explicitly: - { scalar => '0' } - - # List failures always return an empty list: - { list => [] } - - # List failures return () or (undef) [default expectation]: - { list => sub { ! @_ || @_ == 1 && !defined $_[0] } } - - # List failures return () or a single false value: - { list => sub { ! @_ || @_ == 1 && !$_[0] } } - - # List failures return (undef, "some string") - { list => sub { @_ == 2 && !defined $_[0] } } - - # Unsuccessful foo() returns 'FAIL' or '_FAIL' in scalar context, - # returns (-1) in list context... - autodie::hints->set_hints_for( - \&foo, - { - scalar => qr/^ _? FAIL $/xms, - list => [-1], - } - ); - - # Unsuccessful foo() returns 0 in all contexts... - autodie::hints->set_hints_for( - \&foo, - { - scalar => 0, - list => [0], - } - ); - -This "in all contexts" construction is very common, and can be -abbreviated, using the 'fail' key. This sets both the C<scalar> -and C<list> hints to the same value: - - # Unsuccessful foo() returns 0 in all contexts... - autodie::hints->set_hints_for( - \&foo, - { - fail => sub { @_ == 1 and defined $_[0] and $_[0] == 0 } - } - ); - - # Unsuccessful think_positive() returns negative number on failure... - autodie::hints->set_hints_for( - \&think_positive, - { - fail => sub { $_[0] < 0 } - } - ); - - # Unsuccessful my_system() returns non-zero on failure... - autodie::hints->set_hints_for( - \&my_system, - { - fail => sub { $_[0] != 0 } - } - ); - -=head1 Manually setting hints from within your program - -If you are using a module which returns something special on failure, then -you can manually create hints for each of the desired subroutines. Once -the hints are specified, they are available for all files and modules loaded -thereafter, thus you can move this work into a module and it will still -work. - - use Some::Module qw(foo bar); - use autodie::hints; - - autodie::hints->set_hints_for( - \&foo, - { - scalar => SCALAR_HINT, - list => LIST_HINT, - } - ); - autodie::hints->set_hints_for( - \&bar, - { fail => SOME_HINT, } - ); - -It is possible to pass either a subroutine reference (recommended) or a fully -qualified subroutine name as the first argument. This means you can set hints -on modules that I<might> get loaded: - - use autodie::hints; - autodie::hints->set_hints_for( - 'Some::Module:bar', { fail => SCALAR_HINT, } - ); - -This technique is most useful when you have a project that uses a -lot of third-party modules. You can define all your possible hints -in one-place. This can even be in a sub-class of autodie. For -example: - - package my::autodie; - - use parent qw(autodie); - use autodie::hints; - - autodie::hints->set_hints_for(...); - - 1; - -You can now C<use my::autodie>, which will work just like the standard -C<autodie>, but is now aware of any hints that you've set. - -=head1 Adding hints to your module - -C<autodie> provides a passive interface to allow you to declare hints for -your module. These hints will be found and used by C<autodie> if it -is loaded, but otherwise have no effect (or dependencies) without autodie. -To set these, your module needs to declare that it I<does> the -C<autodie::hints::provider> role. This can be done by writing your -own C<DOES> method, using a system such as C<Class::DOES> to handle -the heavy-lifting for you, or declaring a C<%DOES> package variable -with a C<autodie::hints::provider> key and a corresponding true value. - -Note that checking for a C<%DOES> hash is an C<autodie>-only -short-cut. Other modules do not use this mechanism for checking -roles, although you can use the C<Class::DOES> module from the -CPAN to allow it. - -In addition, you must define a C<AUTODIE_HINTS> subroutine that returns -a hash-reference containing the hints for your subroutines: - - package Your::Module; - - # We can use the Class::DOES from the CPAN to declare adherence - # to a role. - - use Class::DOES 'autodie::hints::provider' => 1; - - # Alternatively, we can declare the role in %DOES. Note that - # this is an autodie specific optimisation, although Class::DOES - # can be used to promote this to a true role declaration. - - our %DOES = ( 'autodie::hints::provider' => 1 ); - - # Finally, we must define the hints themselves. - - sub AUTODIE_HINTS { - return { - foo => { scalar => HINTS, list => SOME_HINTS }, - bar => { scalar => HINTS, list => MORE_HINTS }, - baz => { fail => HINTS }, - } - } - -This allows your code to set hints without relying on C<autodie> and -C<autodie::hints> being loaded, or even installed. In this way your -code can do the right thing when C<autodie> is installed, but does not -need to depend upon it to function. - -=head1 Insisting on hints - -When a user-defined subroutine is wrapped by C<autodie>, it will -use hints if they are available, and otherwise reverts to the -I<default behaviour> described in the introduction of this document. -This can be problematic if we expect a hint to exist, but (for -whatever reason) it has not been loaded. - -We can ask autodie to I<insist> that a hint be used by prefixing -an exclamation mark to the start of the subroutine name. A lone -exclamation mark indicates that I<all> subroutines after it must -have hints declared. - - # foo() and bar() must have their hints defined - use autodie qw( !foo !bar baz ); - - # Everything must have hints (recommended). - use autodie qw( ! foo bar baz ); - - # bar() and baz() must have their hints defined - use autodie qw( foo ! bar baz ); - - # Enable autodie for all of Perl's supported built-ins, - # as well as for foo(), bar() and baz(). Everything must - # have hints. - use autodie qw( ! :all foo bar baz ); - -If hints are not available for the specified subroutines, this will cause a -compile-time error. Insisting on hints for Perl's built-in functions -(eg, C<open> and C<close>) is always successful. - -Insisting on hints is I<strongly> recommended. - -=cut - -# TODO: implement regular expression hints - -use constant UNDEF_ONLY => sub { not defined $_[0] }; -use constant EMPTY_OR_UNDEF => sub { - ! @_ or - @_==1 && !defined $_[0] -}; - -use constant EMPTY_ONLY => sub { @_ == 0 }; -use constant EMPTY_OR_FALSE => sub { - ! @_ or - @_==1 && !$_[0] -}; - -use constant SINGLE_TRUE => sub { @_ == 1 and not $_[0] }; - -use constant DEFAULT_HINTS => { - scalar => UNDEF_ONLY, - list => EMPTY_OR_UNDEF, -}; - - -use constant HINTS_PROVIDER => 'autodie::hints::provider'; - -use base qw(Exporter); - -our $DEBUG = 0; - -# Only ( undef ) is a strange but possible situation for very -# badly written code. It's not supported yet. - -my %Hints = ( - 'File::Copy::copy' => { scalar => SINGLE_TRUE, list => SINGLE_TRUE }, - 'File::Copy::move' => { scalar => SINGLE_TRUE, list => SINGLE_TRUE }, - 'File::Copy::cp' => { scalar => SINGLE_TRUE, list => SINGLE_TRUE }, - 'File::Copy::mv' => { scalar => SINGLE_TRUE, list => SINGLE_TRUE }, -); - -# Start by using Sub::Identify if it exists on this system. - -eval { require Sub::Identify; Sub::Identify->import('get_code_info'); }; - -# If it doesn't exist, we'll define our own. This code is directly -# taken from Rafael Garcia's Sub::Identify 0.04, used under the same -# license as Perl itself. - -if ($@) { - require B; - - no warnings 'once'; - - *get_code_info = sub ($) { - - my ($coderef) = @_; - ref $coderef or return; - my $cv = B::svref_2object($coderef); - $cv->isa('B::CV') or return; - # bail out if GV is undefined - $cv->GV->isa('B::SPECIAL') and return; - - return ($cv->GV->STASH->NAME, $cv->GV->NAME); - }; - -} - -sub sub_fullname { - return join( '::', get_code_info( $_[1] ) ); -} - -my %Hints_loaded = (); - -sub load_hints { - my ($class, $sub) = @_; - - my ($package) = ( $sub =~ /(.*)::/ ); - - if (not defined $package) { - require Carp; - Carp::croak( - "Internal error in autodie::hints::load_hints - no package found. - "); - } - - # Do nothing if we've already tried to load hints for - # this package. - return if $Hints_loaded{$package}++; - - my $hints_available = 0; - - { - no strict 'refs'; ## no critic - - if ($package->can('DOES') and $package->DOES(HINTS_PROVIDER) ) { - $hints_available = 1; - } - elsif ( PERL58 and $package->isa(HINTS_PROVIDER) ) { - $hints_available = 1; - } - elsif ( ${"${package}::DOES"}{HINTS_PROVIDER.""} ) { - $hints_available = 1; - } - } - - return if not $hints_available; - - my %package_hints = %{ $package->AUTODIE_HINTS }; - - foreach my $sub (keys %package_hints) { - - my $hint = $package_hints{$sub}; - - # Ensure we have a package name. - $sub = "${package}::$sub" if $sub !~ /::/; - - # TODO - Currently we don't check for conflicts, should we? - $Hints{$sub} = $hint; - - $class->normalise_hints(\%Hints, $sub); - } - - return; - -} - -sub normalise_hints { - my ($class, $hints, $sub) = @_; - - if ( exists $hints->{$sub}->{fail} ) { - - if ( exists $hints->{$sub}->{scalar} or - exists $hints->{$sub}->{list} - ) { - # TODO: Turn into a proper diagnostic. - require Carp; - local $Carp::CarpLevel = 1; - Carp::croak("fail hints cannot be provided with either scalar or list hints for $sub"); - } - - # Set our scalar and list hints. - - $hints->{$sub}->{scalar} = - $hints->{$sub}->{list} = delete $hints->{$sub}->{fail}; - - return; - - } - - # Check to make sure all our hints exist. - - foreach my $hint (qw(scalar list)) { - if ( not exists $hints->{$sub}->{$hint} ) { - # TODO: Turn into a proper diagnostic. - require Carp; - local $Carp::CarpLevel = 1; - Carp::croak("$hint hint missing for $sub"); - } - } - - return; -} - -sub get_hints_for { - my ($class, $sub) = @_; - - my $subname = $class->sub_fullname( $sub ); - - # If we have hints loaded for a sub, then return them. - - if ( exists $Hints{ $subname } ) { - return $Hints{ $subname }; - } - - # If not, we try to load them... - - $class->load_hints( $subname ); - - # ...and try again! - - if ( exists $Hints{ $subname } ) { - return $Hints{ $subname }; - } - - # It's the caller's responsibility to use defaults if desired. - # This allows on autodie to insist on hints if needed. - - return; - -} - -sub set_hints_for { - my ($class, $sub, $hints) = @_; - - if (ref $sub) { - $sub = $class->sub_fullname( $sub ); - - require Carp; - - $sub or Carp::croak("Attempts to set_hints_for unidentifiable subroutine"); - } - - if ($DEBUG) { - warn "autodie::hints: Setting $sub to hints: $hints\n"; - } - - $Hints{ $sub } = $hints; - - $class->normalise_hints(\%Hints, $sub); - - return; -} - -1; - -__END__ - - -=head1 Diagnostics - -=over 4 - -=item Attempts to set_hints_for unidentifiable subroutine - -You've called C<< autodie::hints->set_hints_for() >> using a subroutine -reference, but that reference could not be resolved back to a -subroutine name. It may be an anonymous subroutine (which can't -be made autodying), or may lack a name for other reasons. - -If you receive this error with a subroutine that has a real name, -then you may have found a bug in autodie. See L<autodie/BUGS> -for how to report this. - -=item fail hints cannot be provided with either scalar or list hints for %s - -When defining hints, you can either supply both C<list> and -C<scalar> keywords, I<or> you can provide a single C<fail> keyword. -You can't mix and match them. - -=item %s hint missing for %s - -You've provided either a C<scalar> hint without supplying -a C<list> hint, or vice-versa. You I<must> supply both C<scalar> -and C<list> hints, I<or> a single C<fail> hint. - -=back - -=head1 ACKNOWLEDGEMENTS - -=over - -=item * - -Dr Damian Conway for suggesting the hinting interface and providing the -example usage. - -=item * - -Jacinta Richardson for translating much of my ideas into this -documentation. - -=back - -=head1 AUTHOR - -Copyright 2009, Paul Fenwick E<lt>pjf@perltraining.com.auE<gt> - -=head1 LICENSE - -This module is free software. You may distribute it under the -same terms as Perl itself. - -=head1 SEE ALSO - -L<autodie>, L<Class::DOES> - -=cut diff --git a/ext/autodie/t/00-load.t b/ext/autodie/t/00-load.t deleted file mode 100755 index d07fcaefbe..0000000000 --- a/ext/autodie/t/00-load.t +++ /dev/null @@ -1,9 +0,0 @@ -#!perl -T - -use Test::More tests => 1; - -BEGIN { - use_ok( 'Fatal' ); -} - -# diag( "Testing Fatal $Fatal::VERSION, Perl $], $^X" ); diff --git a/ext/autodie/t/Fatal.t b/ext/autodie/t/Fatal.t deleted file mode 100755 index a291837d13..0000000000 --- a/ext/autodie/t/Fatal.t +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use constant NO_SUCH_FILE => "this_file_or_dir_had_better_not_exist_XYZZY"; - -use Test::More tests => 17; - -use Fatal qw(open close :void opendir); - -eval { open FOO, "<".NO_SUCH_FILE }; # Two arg open -like($@, qr/^Can't open/, q{Package Fatal::open}); -is(ref $@, "", "Regular fatal throws a string"); - -my $foo = 'FOO'; -for ('$foo', "'$foo'", "*$foo", "\\*$foo") { - eval qq{ open $_, '<$0' }; - - is($@,"", "Open using filehandle named - $_"); - - like(scalar(<$foo>), qr{^#!.*/perl}, "File contents using - $_"); - eval qq{ close FOO }; - - is($@,"", "Close filehandle using - $_"); -} - -eval { opendir FOO, NO_SUCH_FILE }; -like($@, qr{^Can't open}, "Package :void Fatal::opendir"); - -eval { my $a = opendir FOO, NO_SUCH_FILE }; -is($@, "", "Package :void Fatal::opendir in scalar context"); - -eval { Fatal->import(qw(print)) }; -like( - $@, qr{Cannot make the non-overridable builtin print fatal}, - "Can't override print" -); diff --git a/ext/autodie/t/autodie.t b/ext/autodie/t/autodie.t deleted file mode 100755 index c528a160a4..0000000000 --- a/ext/autodie/t/autodie.t +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use constant NO_SUCH_FILE => 'this_file_had_so_better_not_be_here'; - -use Test::More tests => 19; - -{ - - use autodie qw(open); - - eval { open(my $fh, '<', NO_SUCH_FILE); }; - like($@,qr{Can't open},"autodie qw(open) in lexical scope"); - - no autodie qw(open); - - eval { open(my $fh, '<', NO_SUCH_FILE); }; - is($@,"","no autodie qw(open) in lexical scope"); - - use autodie qw(open); - eval { open(my $fh, '<', NO_SUCH_FILE); }; - like($@,qr{Can't open},"autodie qw(open) in lexical scope 2"); - - no autodie; # Should turn off all autodying subs - eval { open(my $fh, '<', NO_SUCH_FILE); }; - is($@,"","no autodie in lexical scope 2"); - - # Turn our pragma on one last time, so we can verify that - # falling out of this block reverts it back to previous - # behaviour. - use autodie qw(open); - eval { open(my $fh, '<', NO_SUCH_FILE); }; - like($@,qr{Can't open},"autodie qw(open) in lexical scope 3"); - -} - -eval { open(my $fh, '<', NO_SUCH_FILE); }; -is($@,"","autodie open outside of lexical scope"); - -eval { - use autodie; # Should turn on everything - open(my $fh, '<', NO_SUCH_FILE); -}; - -like($@, qr{Can't open}, "vanilla use autodie turns on everything."); - -eval { open(my $fh, '<', NO_SUCH_FILE); }; -is($@,"","vanilla autodie cleans up"); - -{ - use autodie qw(:io); - - eval { open(my $fh, '<', NO_SUCH_FILE); }; - like($@,qr{Can't open},"autodie q(:io) makes autodying open"); - - no autodie qw(:io); - - eval { open(my $fh, '<', NO_SUCH_FILE); }; - is($@,"", "no autodie qw(:io) disabled autodying open"); -} - -{ - package Testing_autodie; - - use Test::More; - - use constant NO_SUCH_FILE => ::NO_SUCH_FILE(); - - use Fatal qw(open); - - eval { open(my $fh, '<', NO_SUCH_FILE); }; - - like($@, qr{Can't open}, "Package fatal working"); - is(ref $@,"","Old Fatal throws strings"); - - { - use autodie qw(open); - - ok(1,"use autodie allowed with Fatal"); - - eval { open(my $fh, '<', NO_SUCH_FILE); }; - like($@, qr{Can't open}, "autodie and Fatal works"); - isa_ok($@, "autodie::exception"); # autodie throws real exceptions - - } - - eval { open(my $fh, '<', NO_SUCH_FILE); }; - - like($@, qr{Can't open}, "Package fatal working after autodie"); - is(ref $@,"","Old Fatal throws strings after autodie"); - - eval " no autodie qw(open); "; - - ok($@,"no autodie on Fataled sub an error."); - - eval " - no autodie qw(close); - use Fatal 'close'; - "; - - like($@, qr{not allowed}, "Using fatal after autodie is an error."); -} - diff --git a/ext/autodie/t/autodie_test_module.pm b/ext/autodie/t/autodie_test_module.pm deleted file mode 100644 index e8e824c522..0000000000 --- a/ext/autodie/t/autodie_test_module.pm +++ /dev/null @@ -1,18 +0,0 @@ -package main; -use strict; -use warnings; - -# Calls open, while still in the main package. This shouldn't -# be autodying. -sub leak_test { - return open(my $fh, '<', $_[0]); -} - -package autodie_test_module; - -# This should be calling CORE::open -sub your_open { - return open(my $fh, '<', $_[0]); -} - -1; diff --git a/ext/autodie/t/backcompat.t b/ext/autodie/t/backcompat.t deleted file mode 100755 index acb81245b8..0000000000 --- a/ext/autodie/t/backcompat.t +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Fatal qw(open); -use Test::More tests => 2; -use constant NO_SUCH_FILE => "xyzzy_this_file_is_not_here"; - -eval { - open(my $fh, '<', NO_SUCH_FILE); -}; - -my $old_msg = qr{Can't open\(GLOB\(0x[0-9a-f]+\), <, xyzzy_this_file_is_not_here\): .* at \(eval \d+\)(?:\[.*?\])? line \d+\s+main::__ANON__\('GLOB\(0x[0-9a-f]+\)',\s*'<',\s*'xyzzy_this_file_is_not_here'\) called at \S+ line \d+\s+eval \Q{...}\E called at \S+ line \d+}; - -like($@,$old_msg,"Backwards compat ugly messages"); -is(ref($@),"", "Exception is a string, not an object"); diff --git a/ext/autodie/t/basic_exceptions.t b/ext/autodie/t/basic_exceptions.t deleted file mode 100755 index c732dd587d..0000000000 --- a/ext/autodie/t/basic_exceptions.t +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use Test::More tests => 19; - -use constant NO_SUCH_FILE => "this_file_had_better_not_exist"; - -my $line; - -eval { - use autodie ':io'; - $line = __LINE__; open(my $fh, '<', NO_SUCH_FILE); -}; - -like($@, qr/Can't open '\w+' for reading: /, "Prety printed open msg"); -like($@, qr{\Q$0\E}, "Our file mention in error message"); - -like($@, qr{for reading: '.+'}, "Error should be in single-quotes"); -like($@->errno,qr/./, "Errno should not be empty"); - -like($@, qr{\n$}, "Errors should end with a newline"); -is($@->file, $0, "Correct file"); -is($@->function, 'CORE::open', "Correct dying sub"); -is($@->package, __PACKAGE__, "Correct package"); -is($@->caller,__PACKAGE__."::__ANON__", "Correct caller"); -is($@->line, $line, "Correct line"); -is($@->args->[1], '<', 'Correct mode arg'); -is($@->args->[2], NO_SUCH_FILE, 'Correct filename arg'); -ok($@->matches('open'), 'Looks like an error from open'); -ok($@->matches(':io'), 'Looks like an error from :io'); -is($@->context, 'scalar', 'Open called in scalar/void context'); -is($@->return,undef,'Open should return undef on failure'); - -# Testing of caller info with a real subroutine. - -my $line2; - -sub xyzzy { - use autodie ':io'; - $line2 = __LINE__; open(my $fh, '<', NO_SUCH_FILE); - return; -}; - -eval { xyzzy(); }; - -isa_ok($@, 'autodie::exception'); -is($@->caller, __PACKAGE__."::xyzzy", "Subroutine caller test"); -is($@->line, $line2, "Subroutine line test"); diff --git a/ext/autodie/t/binmode.t b/ext/autodie/t/binmode.t deleted file mode 100755 index 317a41303c..0000000000 --- a/ext/autodie/t/binmode.t +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More 'no_plan'; - -# These are a bunch of general tests for working with files and -# filehandles. - -my $r = "default"; - -eval { - no warnings; - $r = binmode(FOO); -}; - -is($@,"","Sanity: binmode(FOO) doesn't usually throw exceptions"); -is($r,undef,"Sanity: binmode(FOO) returns undef"); - -eval { - use autodie qw(binmode); - no warnings; - binmode(FOO); -}; - -ok($@, "autodie qw(binmode) should cause failing binmode to die."); -isa_ok($@,"autodie::exception", "binmode exceptions are in autodie::exception"); - -eval { - use autodie; - no warnings; - binmode(FOO); -}; - -ok($@, "autodie (default) should cause failing binmode to die."); diff --git a/ext/autodie/t/blog_hints.t b/ext/autodie/t/blog_hints.t deleted file mode 100755 index 395cb14342..0000000000 --- a/ext/autodie/t/blog_hints.t +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use Test::More 'no_plan'; - -use FindBin; -use lib "$FindBin::Bin/lib"; - -use Some::Module qw(some_sub); -use my::autodie qw(! some_sub); - -eval { some_sub() }; - -isnt("$@", "", "some_sub should die in void/scalar context"); - -isa_ok($@, 'autodie::exception'); -is($@->context, 'scalar'); -is($@->function, 'Some::Module::some_sub'); -like("$@", qr/can't be called in scalar context/); - -my @returns = eval { some_sub(0); }; -is($@, "", "Good call to some_sub"); -is_deeply(\@returns, [1,2,3], "Returns unmolested"); - -@returns = eval { some_sub(1) }; - -isnt("$@",""); -is($@->return->[0], undef); -is($@->return->[1], 'Insufficient credit'); -like("$@", qr/Insufficient credit/); diff --git a/ext/autodie/t/caller.t b/ext/autodie/t/caller.t deleted file mode 100755 index 1874353627..0000000000 --- a/ext/autodie/t/caller.t +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use autodie; -use Test::More 'no_plan'; -use FindBin qw($Bin); -use lib "$Bin/lib"; -use Caller_helper; - -use constant NO_SUCH_FILE => "kiwifoo_is_so_much_fun"; - -eval { - foo(); -}; - -isa_ok($@, 'autodie::exception'); - -is($@->caller, 'main::foo', "Caller should be main::foo"); - -sub foo { - use autodie; - open(my $fh, '<', NO_SUCH_FILE); -} - -eval { - Caller_helper::foo(); -}; - -isa_ok($@, 'autodie::exception'); - -is($@->line, $Caller_helper::line, "External line number check"); -is($@->file, $INC{"Caller_helper.pm"}, "External filename check"); -is($@->package, "Caller_helper", "External package check"); -is($@->caller, "Caller_helper::foo", "External subname check"); diff --git a/ext/autodie/t/context.t b/ext/autodie/t/context.t deleted file mode 100755 index 39b86497c6..0000000000 --- a/ext/autodie/t/context.t +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use Test::More; - -plan 'no_plan'; - -sub list_return { - return if @_; - return qw(foo bar baz); -} - -sub list_return2 { - return if @_; - return qw(foo bar baz); -} - -# Returns a list presented to it, but also returns a single -# undef if given a list of a single undef. This mimics the -# behaviour of many user-defined subs and built-ins (eg: open) that -# always return undef regardless of context. - -sub list_mirror { - return undef if (@_ == 1 and not defined $_[0]); - return @_; - -} - -use Fatal qw(list_return); -use Fatal qw(:void list_return2); - -TODO: { - - # Clobbering context was documented as a bug in the original - # Fatal, so we'll still consider it a bug here. - - local $TODO = "Fatal clobbers context, just like it always has."; - - my @list = list_return(); - - is_deeply(\@list,[qw(foo bar baz)],'fatal sub works in list context'); -} - -eval { - my @line = list_return(1); # Should die -}; - -ok($@,"List return fatalised"); - -### Tests where we've fatalised our function with :void ### - -my @list2 = list_return2(); - -is_deeply(\@list2,[qw(foo bar baz)],'fatal sub works in list context'); - -eval { - my @line = list_return2(1); # Shouldn't die -}; - -ok(! $@,"void List return fatalised survives when non-void"); - -eval { - list_return2(1); -}; - -ok($@,"void List return fatalised"); diff --git a/ext/autodie/t/context_lexical.t b/ext/autodie/t/context_lexical.t deleted file mode 100755 index ce50b75c4b..0000000000 --- a/ext/autodie/t/context_lexical.t +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use Test::More; - -plan 'no_plan'; - -# Returns a list presented to it, but also returns a single -# undef if given a list of a single undef. This mimics the -# behaviour of many user-defined subs and built-ins (eg: open) that -# always return undef regardless of context. -# -# We also do an 'empty return' if no arguments are passed. This -# mimics the PBP guideline for returning nothing. - -sub list_mirror { - return undef if (@_ == 1 and not defined $_[0]); - return if not @_; - return @_; - -} - -### autodie clobbering tests ### - -eval { - list_mirror(); -}; - -is($@, "", "No autodie, no fatality"); - -eval { - use autodie qw(list_mirror); - list_mirror(); -}; - -ok($@, "Autodie fatality for empty return in void context"); - -eval { - list_mirror(); -}; - -is($@, "", "No autodie, no fatality (after autodie used)"); - -eval { - use autodie qw(list_mirror); - list_mirror(undef); -}; - -ok($@, "Autodie fatality for undef return in void context"); - -eval { - use autodie qw(list_mirror); - my @list = list_mirror(); -}; - -ok($@,"Autodie fatality for empty list return"); - -eval { - use autodie qw(list_mirror); - my @list = list_mirror(undef); -}; - -ok($@,"Autodie fatality for undef list return"); - -eval { - use autodie qw(list_mirror); - my @list = list_mirror("tada"); -}; - -ok(! $@,"No Autodie fatality for defined list return"); - -eval { - use autodie qw(list_mirror); - my $single = list_mirror("tada"); -}; - -ok(! $@,"No Autodie fatality for defined scalar return"); - -eval { - use autodie qw(list_mirror); - my $single = list_mirror(undef); -}; - -ok($@,"Autodie fatality for undefined scalar return"); diff --git a/ext/autodie/t/crickey.t b/ext/autodie/t/crickey.t deleted file mode 100755 index 91a7d7837a..0000000000 --- a/ext/autodie/t/crickey.t +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use FindBin; -use Test::More 'no_plan'; - -use lib "$FindBin::Bin/lib"; - -use constant NO_SUCH_FILE => "crickey_mate_this_file_isnt_here_either"; - -use autodie::test::au qw(open); - -eval { - open(my $fh, '<', NO_SUCH_FILE); -}; - -ok(my $e = $@, 'Strewth! autodie::test::au should throw an exception on failure'); - -isa_ok($e, 'autodie::test::au::exception', - 'Yeah mate, that should be our test exception.'); - -like($e, qr/time for a beer/, "Time for a beer mate?"); - -like( eval { $e->time_for_a_beer; }, - qr/time for a beer/, "It's always a good time for a beer." -); - -ok($e->matches('open'), "Should be a fair dinkum error from open"); diff --git a/ext/autodie/t/dbmopen.t b/ext/autodie/t/dbmopen.t deleted file mode 100755 index 31698e65be..0000000000 --- a/ext/autodie/t/dbmopen.t +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More qw(no_plan); - -use constant ERROR_REGEXP => qr{Can't dbmopen\(%hash, 'foo/bar/baz', 0666\):}; - -my $return = "default"; - -eval { - $return = dbmopen(my %foo, "foo/bar/baz", 0666); -}; - -ok(!$return, "Sanity: dbmopen usually returns false on failure"); -ok(!$@, "Sanity: dbmopen doesn't usually throw exceptions"); - -eval { - use autodie; - - dbmopen(my %foo, "foo/bar/baz", 0666); -}; - -ok($@, "autodie allows dbmopen to throw errors."); -isa_ok($@, "autodie::exception", "... errors are of the correct type"); - -like($@, ERROR_REGEXP, "Message should include number in octal, not decimal"); - -eval { - use autodie; - - my %bar = ( foo => 1, bar => 2 ); - - dbmopen(%bar, "foo/bar/baz", 0666); -}; - -like($@, ERROR_REGEXP, "Correct formatting even with non-empty dbmopen hash"); - diff --git a/ext/autodie/t/exception_class.t b/ext/autodie/t/exception_class.t deleted file mode 100755 index 127893bcbf..0000000000 --- a/ext/autodie/t/exception_class.t +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use FindBin; -use Test::More 'no_plan'; - -use lib "$FindBin::Bin/lib"; - -use constant NO_SUCH_FILE => "this_file_had_better_not_exist_xyzzy"; - -### Tests with non-existent exception class. - -my $open_success = eval { - use autodie::test::missing qw(open); # Uses non-existent exceptions - open(my $fh, '<', NO_SUCH_FILE); - 1; -}; - -is($open_success,undef,"Open should fail"); - -isnt($@,"",'$@ should not be empty'); - -is(ref($@),"",'$@ should not be a reference or object'); - -like($@, qr/Failed to load/, '$@ should contain bad exception class msg'); - -#### Tests with malformed exception class. - -my $open_success2 = eval { - use autodie::test::badname qw(open); - open(my $fh, '<', NO_SUCH_FILE); - 1; -}; - -is($open_success2,undef,"Open should fail"); - -isnt($@,"",'$@ should not be empty'); - -is(ref($@),"",'$@ should not be a reference or object'); - -like($@, qr/Bad exception class/, '$@ should contain bad exception class msg'); - -### Tests with well-formed exception class (in Klingon) - -my $open_success3 = eval { - use pujHa'ghach qw(open); #' <-- this makes my editor happy - open(my $fh, '<', NO_SUCH_FILE); - 1; -}; - -is($open_success3,undef,"Open should fail"); - -isnt("$@","",'$@ should not be empty'); - -isa_ok($@, "pujHa'ghach::Dotlh", '$@ should be a Klingon exception'); - -like($@, qr/lujqu'/, '$@ should contain Klingon text'); diff --git a/ext/autodie/t/exceptions.t b/ext/autodie/t/exceptions.t deleted file mode 100755 index 2f8c2382fc..0000000000 --- a/ext/autodie/t/exceptions.t +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More; - -BEGIN { plan skip_all => "Perl 5.10 only tests" if $] < 5.010; } - -# These are tests that depend upon 5.10 (eg, smart-match). -# Basic tests should go in basic_exceptions.t - -use 5.010; -use constant NO_SUCH_FILE => 'this_file_had_better_not_exist_xyzzy'; - -plan 'no_plan'; - -eval { - use autodie ':io'; - open(my $fh, '<', NO_SUCH_FILE); -}; - -ok($@, "Exception thrown" ); -ok($@ ~~ 'open', "Exception from open" ); -ok($@ ~~ ':file', "Exception from open / class :file" ); -ok($@ ~~ ':io', "Exception from open / class :io" ); -ok($@ ~~ ':all', "Exception from open / class :all" ); - -eval { - no warnings 'once'; # To prevent the following close from complaining. - close(THIS_FILEHANDLE_AINT_OPEN); -}; - -ok(! $@, "Close without autodie should fail silent"); - -eval { - use autodie ':io'; - close(THIS_FILEHANDLE_AINT_OPEN); -}; - -like($@, qr{Can't close filehandle 'THIS_FILEHANDLE_AINT_OPEN'},"Nice msg from close"); - -ok($@, "Exception thrown" ); -ok($@ ~~ 'close', "Exception from close" ); -ok($@ ~~ ':file', "Exception from close / class :file" ); -ok($@ ~~ ':io', "Exception from close / class :io" ); -ok($@ ~~ ':all', "Exception from close / class :all" ); - diff --git a/ext/autodie/t/exec.t b/ext/autodie/t/exec.t deleted file mode 100755 index 0d4439a8c1..0000000000 --- a/ext/autodie/t/exec.t +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More tests => 3; - -eval { - use autodie qw(exec); - exec("this_command_had_better_not_exist", 1); -}; - -isa_ok($@,"autodie::exception", "failed execs should die"); -ok($@->matches('exec'), "exception should match exec"); -ok($@->matches(':system'), "exception should match :system"); diff --git a/ext/autodie/t/filehandles.t b/ext/autodie/t/filehandles.t deleted file mode 100755 index 5bdf732e2c..0000000000 --- a/ext/autodie/t/filehandles.t +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/perl -w - -package main; - -use strict; -use Test::More; - -# We may see failures with package filehandles if Fatal/autodie -# incorrectly pulls out a cached subroutine from a different package. - -# We're using Fatal because package filehandles are likely to -# see more use with Fatal than autodie. - -use Fatal qw(open); - -eval { - open(FILE, '<', $0); -}; - - -if ($@) { - # Holy smokes! We couldn't even open our own file, bail out... - - plan skip_all => q{Can't open $0 for filehandle tests} -} - -plan tests => 4; - -my $line = <FILE>; - -like($line, qr{perl}, 'Looks like we opened $0 correctly'); - -close(FILE); - -package autodie::test; -use Test::More; - -use Fatal qw(open); - -eval { - open(FILE2, '<', $0); -}; - -is($@,"",'Opened $0 in autodie::test'); - -my $line2 = <FILE2>; - -like($line2, qr{perl}, '...and we can read from $0 fine'); - -close(FILE2); - -package main; - -# This shouldn't read anything, because FILE2 should be inside -# autodie::test - -no warnings; # Otherwise we see problems with FILE2 -my $wrong_line = <FILE2>; - -ok(! defined($wrong_line),q{Filehandles shouldn't leak between packages}); diff --git a/ext/autodie/t/fileno.t b/ext/autodie/t/fileno.t deleted file mode 100755 index 2b9c2598e7..0000000000 --- a/ext/autodie/t/fileno.t +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More tests => 8; - -# Basic sanity tests. -is(fileno(STDIN), 0, "STDIN fileno looks sane"); -is(fileno(STDOUT),1, "STDOUT looks sane"); - -my $dummy = "foo"; - -ok(!defined(fileno($dummy)), "Non-filehandles shouldn't be defined."); - - -my $fileno = eval { - use autodie qw(fileno); - fileno(STDIN); -}; - -is($@,"","fileno(STDIN) shouldn't die"); -is($fileno,0,"autodying fileno(STDIN) should be 0"); - -$fileno = eval { - use autodie qw(fileno); - fileno(STDOUT); -}; - -is($@,"","fileno(STDOUT) shouldn't die"); -is($fileno,1,"autodying fileno(STDOUT) should be 1"); - -$fileno = eval { - use autodie qw(fileno); - fileno($dummy); -}; - -isa_ok($@,"autodie::exception", 'autodying fileno($dummy) should die'); diff --git a/ext/autodie/t/flock.t b/ext/autodie/t/flock.t deleted file mode 100755 index a7550bad6a..0000000000 --- a/ext/autodie/t/flock.t +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More; -use Fcntl qw(:flock); -use POSIX qw(EWOULDBLOCK); - -require Fatal; - -my $EWOULDBLOCK = eval { EWOULDBLOCK() } - || $Fatal::_EWOULDBLOCK{$^O} - || plan skip_all => "EWOULDBLOCK not defined on this system"; - -my ($self_fh, $self_fh2); - -eval { - use autodie; - open($self_fh, '<', $0); - open($self_fh2, '<', $0); - open(SELF, '<', $0); -}; - -if ($@) { - plan skip_all => "Cannot lock this test on this system."; -} - -my $flock_return = eval { flock($self_fh, LOCK_EX | LOCK_NB); }; - -if (not $flock_return) { - plan skip_all => "flock on my own test not supported on this system."; -} - -my $flock_return2 = flock($self_fh2, LOCK_EX | LOCK_NB); - -if ($flock_return2) { - plan skip_all => "this test requires locking a file twice with ". - "different filehandles to fail"; -} - -$flock_return = flock($self_fh, LOCK_UN); - -if (not $flock_return) { - plan skip_all => "Odd, I can't unlock a file with flock on this system."; -} - -# If we're here, then we can lock and unlock our own file. - -plan 'no_plan'; - -ok( flock($self_fh, LOCK_EX | LOCK_NB), "Test file locked"); - -my $return; - -eval { - use autodie qw(flock); - $return = flock($self_fh2, LOCK_EX | LOCK_NB); -}; - -is($!+0, $EWOULDBLOCK, "Double-flocking should be EWOULDBLOCK"); -ok(!$return, "flocking a file twice should fail"); -is($@, "", "Non-blocking flock should not fail on EWOULDBLOCK"); - -__END__ - -# These are old tests which I'd love to resurrect, but they need -# a reliable way of getting flock to throw exceptions but with -# minimal blocking. They may turn into author tests. - -eval { - use autodie; - flock($self_fh2, LOCK_EX | LOCK_NB); -}; - -ok($@, "Locking a file twice throws an exception with vanilla autodie"); -isa_ok($@, "autodie::exception", "Exception is from autodie::exception"); - -like($@, qr/LOCK_EX/, "error message contains LOCK_EX switch"); -like($@, qr/LOCK_NB/, "error message contains LOCK_NB switch"); -unlike($@, qr/GLOB/ , "error doesn't include ugly GLOB mention"); - -eval { - use autodie; - flock(SELF, LOCK_EX | LOCK_NB); -}; - -ok($@, "Locking a package filehanlde twice throws exception with vanilla autodie"); -isa_ok($@, "autodie::exception", "Exception is from autodie::exception"); - -like($@, qr/LOCK_EX/, "error message contains LOCK_EX switch"); -like($@, qr/LOCK_NB/, "error message contains LOCK_NB switch"); -like($@, qr/SELF/ , "error mentions actual filehandle name."); diff --git a/ext/autodie/t/format-clobber.t b/ext/autodie/t/format-clobber.t deleted file mode 100755 index ee8e8bd5c8..0000000000 --- a/ext/autodie/t/format-clobber.t +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env perl -use warnings; -use strict; - -use FindBin; -use lib "$FindBin::Bin/lib"; -use Test::More tests => 21; - -our ($pvio, $pvfm); - -use_ok('OtherTypes'); - -# Since we use use_ok, this is effectively 'compile time'. - -ok( defined *OtherTypes::foo{SCALAR}, - "SCALAR slot intact at compile time" ); -ok( defined *OtherTypes::foo{ARRAY}, - "ARRAY slot intact at compile time" ); -ok( defined *OtherTypes::foo{HASH}, - "HASH slot intact at compile time" ); -ok( defined *OtherTypes::foo{IO}, - "IO slot intact at compile time" ); -ok( defined *OtherTypes::foo{FORMAT}, - "FORMAT slot intact at compile time" ); - -is( $OtherTypes::foo, 23, - "SCALAR slot correct at compile time" ); -is( $OtherTypes::foo[0], "bar", - "ARRAY slot correct at compile time" ); -is( $OtherTypes::foo{mouse}, "trap", - "HASH slot correct at compile time" ); -is( *OtherTypes::foo{IO}, $pvio, - "IO slot correct at compile time" ); -is( *OtherTypes::foo{FORMAT}, $pvfm, - "FORMAT slot correct at compile time" ); - -eval q{ - ok( defined *OtherTypes::foo{SCALAR}, - "SCALAR slot intact at run time" ); - ok( defined *OtherTypes::foo{ARRAY}, - "ARRAY slot intact at run time" ); - ok( defined *OtherTypes::foo{HASH}, - "HASH slot intact at run time" ); - ok( defined *OtherTypes::foo{IO}, - "IO slot intact at run time" ); - - TODO: { - local $TODO = "Copying formats fails due to a bug in Perl."; - ok( defined *OtherTypes::foo{FORMAT}, - "FORMAT slot intact at run time" ); - } - - is( $OtherTypes::foo, 23, - "SCALAR slot correct at run time" ); - is( $OtherTypes::foo[0], "bar", - "ARRAY slot correct at run time" ); - is( $OtherTypes::foo{mouse}, "trap", - "HASH slot correct at run time" ); - is( *OtherTypes::foo{IO}, $pvio, - "IO slot correct at run time" ); - - TODO: { - local $TODO = "Copying formats fails due to a bug in Perl."; - is( *OtherTypes::foo{FORMAT}, $pvfm, - "FORMAT slot correct at run time" ); - } -}; diff --git a/ext/autodie/t/hints.t b/ext/autodie/t/hints.t deleted file mode 100755 index b508fee235..0000000000 --- a/ext/autodie/t/hints.t +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use autodie::hints; - -use FindBin; -use lib "$FindBin::Bin/lib"; - -use File::Copy qw(copy move cp mv); - -use Test::More 'no_plan'; - -use constant NO_SUCH_FILE => "this_file_had_better_not_exist"; -use constant NO_SUCH_FILE2 => "this_file_had_better_not_exist_xyzzy"; - -use constant PERL510 => ( $] >= 5.0100 ); -use constant PERL5101 => ( $] >= 5.0101 ); -use constant PERL5102 => ( $] >= 5.0102 ); - -# File::Copy states that all subroutines return '0' on failure. -# However both Windows and VMS may return other false values -# (notably empty-string) on failure. This constant indicates -# whether we should skip some tests because the return values -# from File::Copy may not be what's in the documentation. - -use constant WEIRDO_FILE_COPY => - ( ! PERL5102 and ( $^O eq "MSWin32" or $^O eq "VMS" )); - -use Hints_test qw( - fail_on_empty fail_on_false fail_on_undef -); - -use autodie qw(fail_on_empty fail_on_false fail_on_undef); - -diag("Sub::Identify ", exists( $INC{'Sub/Identify.pm'} ) ? "is" : "is not", - " loaded") if (! $ENV{PERL_CORE}); - -my $hints = "autodie::hints"; - -# Basic hinting tests - -is( $hints->sub_fullname(\©), 'File::Copy::copy' , "Id: copy" ); -is( - $hints->sub_fullname(\&cp), - PERL5101 ? 'File::Copy::cp' : 'File::Copy::copy' , "Id: cp" -); - -is( $hints->sub_fullname(\&move), 'File::Copy::move' , "Id: move" ); -is( $hints->sub_fullname(\&mv), - PERL5101 ? 'File::Copy::mv' : 'File::Copy::move' , "Id: mv" -); - -if (PERL510) { - ok( $hints->get_hints_for(\©)->{scalar}->(0) , - "copy() hints should fail on 0 for scalars." - ); - ok( $hints->get_hints_for(\©)->{list}->(0) , - "copy() hints should fail on 0 for lists." - ); -} - -# Scalar context test - -eval { - use autodie qw(copy); - - my $scalar_context = copy(NO_SUCH_FILE, NO_SUCH_FILE2); -}; - -isnt("$@", "", "Copying in scalar context should throw an error."); -isa_ok($@, "autodie::exception"); - -is($@->function, "File::Copy::copy", "Function should be original name"); - -SKIP: { - skip("File::Copy is weird on Win32/VMS before 5.10.1", 1) - if WEIRDO_FILE_COPY; - - is($@->return, 0, "File::Copy returns zero on failure"); -} - -is($@->context, "scalar", "File::Copy called in scalar context"); - -# List context test. - -eval { - use autodie qw(copy); - - my @list_context = copy(NO_SUCH_FILE, NO_SUCH_FILE2); -}; - -isnt("$@", "", "Copying in list context should throw an error."); -isa_ok($@, "autodie::exception"); - -is($@->function, "File::Copy::copy", "Function should be original name"); - -SKIP: { - skip("File::Copy is weird on Win32/VMS before 5.10.1", 1) - if WEIRDO_FILE_COPY; - - is_deeply($@->return, [0], "File::Copy returns zero on failure"); -} -is($@->context, "list", "File::Copy called in list context"); - -# Tests on loaded funcs. - -my %tests = ( - - # Test code # Exception expected? - - 'fail_on_empty()' => 1, - 'fail_on_empty(0)' => 0, - 'fail_on_empty(undef)' => 0, - 'fail_on_empty(1)' => 0, - - 'fail_on_false()' => 1, - 'fail_on_false(0)' => 1, - 'fail_on_false(undef)' => 1, - 'fail_on_false(1)' => 0, - - 'fail_on_undef()' => 1, - 'fail_on_undef(0)' => 0, - 'fail_on_undef(undef)' => 1, - 'fail_on_undef(1)' => 0, - -); - -# On Perl 5.8, autodie doesn't correctly propagate into string evals. -# The following snippet forces the use of autodie inside the eval if -# we really really have to. For 5.10+, we don't want to include this -# fix, because the tests will act as a canary if we screw up string -# eval propagation. - -my $perl58_fix = ( - $] >= 5.010 ? - "" : - "use autodie qw(fail_on_empty fail_on_false fail_on_undef); " -); - -while (my ($test, $exception_expected) = each %tests) { - eval " - $perl58_fix - my \@array = $test; - "; - - - if ($exception_expected) { - isnt("$@", "", $test); - } - else { - is($@, "", $test); - } -} - -1; diff --git a/ext/autodie/t/hints_insist.t b/ext/autodie/t/hints_insist.t deleted file mode 100755 index ab618d2325..0000000000 --- a/ext/autodie/t/hints_insist.t +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use autodie; - -use Test::More tests => 5; - -use FindBin qw($Bin); -use lib "$Bin/lib"; - -use Hints_provider_does qw(always_pass always_fail no_hints); - -eval "use autodie qw( ! always_pass always_fail); "; -is("$@", "", "Insisting on good hints (distributed insist)"); - -is(always_pass(), "foo", "Always_pass() should still work"); -is(always_fail(), "foo", "Always_pass() should still work"); - -eval "use autodie qw(!always_pass !always_fail); "; -is("$@", "", "Insisting on good hints (individual insist)"); - -my $ret = eval "use autodie qw(!no_hints); 1;"; -isnt("$@", "", "Asking for non-existent hints"); diff --git a/ext/autodie/t/hints_pod_examples.t b/ext/autodie/t/hints_pod_examples.t deleted file mode 100755 index a3c6f0f553..0000000000 --- a/ext/autodie/t/hints_pod_examples.t +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use autodie::hints; -use Test::More; - -use constant PERL510 => ( $] >= 5.010 ); - -BEGIN { - if (not PERL510) { - plan skip_all => "Only subroutine hints supported in 5.8.x"; - } - else { - plan 'no_plan'; - } -} - -use FindBin; -use lib "$FindBin::Bin/lib"; -use Hints_pod_examples qw( - undef_scalar false_scalar zero_scalar empty_list default_list - empty_or_false_list undef_n_error_list foo re_fail bar - think_positive my_system -); -use autodie qw( ! - undef_scalar false_scalar zero_scalar empty_list default_list - empty_or_false_list undef_n_error_list foo re_fail bar - think_positive my_system -); - -my %scalar_tests = ( - - # Test code # Exception expected? - - 'undef_scalar()' => 1, - 'undef_scalar(1)', => 0, - 'undef_scalar(0)', => 0, - 'undef_scalar("")', => 0, - - 'false_scalar(0)', => 1, - 'false_scalar()', => 1, - 'false_scalar(undef)', => 1, - 'false_scalar("")', => 1, - 'false_scalar(1)', => 0, - 'false_scalar("1")', => 0, - - 'zero_scalar("0")', => 1, - 'zero_scalar(0)', => 1, - 'zero_scalar(1)', => 0, - 'zero_scalar(undef)', => 0, - 'zero_scalar("")', => 0, - - 'foo(0)', => 1, - 'foo(undef)', => 0, - 'foo(1)', => 0, - - 'bar(0)', => 1, - 'bar(undef)', => 0, - 'bar(1)', => 0, - - 're_fail(-1)', => 0, - 're_fail("FAIL")', => 1, - 're_fail("_FAIL")', => 1, - 're_fail("_fail")', => 0, - 're_fail("fail")', => 0, - - 'think_positive(-1)' => 1, - 'think_positive(-2)' => 1, - 'think_positive(0)' => 0, - 'think_positive(1)' => 0, - 'think_positive(2)' => 0, - - 'my_system(1)' => 1, - 'my_system(2)' => 1, - 'my_system(0)' => 0, - -); - -my %list_tests = ( - - 'empty_list()', => 1, - 'empty_list(())', => 1, - 'empty_list([])', => 0, - 'empty_list(0)', => 0, - 'empty_list("")', => 0, - 'empty_list(undef)', => 0, - - 'default_list()', => 1, - 'default_list(0)', => 0, - 'default_list("")', => 0, - 'default_list(undef)', => 1, - 'default_list(1)', => 0, - 'default_list("str")', => 0, - 'default_list(1, 2)', => 0, - - 'empty_or_false_list()', => 1, - 'empty_or_false_list(())', => 1, - 'empty_or_false_list(0)', => 1, - 'empty_or_false_list(undef)',=> 1, - 'empty_or_false_list("")', => 1, - 'empty_or_false_list("0")', => 1, - 'empty_or_false_list(1,2)', => 0, - 'empty_or_false_list("a")', => 0, - - 'undef_n_error_list(undef, 1)' => 1, - 'undef_n_error_list(undef, "a")' => 1, - 'undef_n_error_list()' => 0, - 'undef_n_error_list(0, 1)' => 0, - 'undef_n_error_list("", 1)' => 0, - 'undef_n_error_list(1)' => 0, - - 'foo(0)', => 1, - 'foo(undef)', => 0, - 'foo(1)', => 0, - - 'bar(0)', => 1, - 'bar(undef)', => 0, - 'bar(1)', => 0, - - 're_fail(-1)', => 1, - 're_fail("FAIL")', => 0, - 're_fail("_FAIL")', => 0, - 're_fail("_fail")', => 0, - 're_fail("fail")', => 0, - - 'think_positive(-1)' => 1, - 'think_positive(-2)' => 1, - 'think_positive(0)' => 0, - 'think_positive(1)' => 0, - 'think_positive(2)' => 0, - - 'my_system(1)' => 1, - 'my_system(2)' => 1, - 'my_system(0)' => 0, - -); - -# On Perl 5.8, autodie doesn't correctly propagate into string evals. -# The following snippet forces the use of autodie inside the eval if -# we really really have to. For 5.10+, we don't want to include this -# fix, because the tests will act as a canary if we screw up string -# eval propagation. - -my $perl58_fix = ( - PERL510 ? - q{} : - q{use autodie qw( - undef_scalar false_scalar zero_scalar empty_list default_list - empty_or_false_list undef_n_error_list foo re_fail bar - think_positive my_system bizarro_system - );} -); - -# Some of the tests provide different hints for scalar or list context - -while (my ($test, $exception_expected) = each %scalar_tests) { - eval " - $perl58_fix - my \$scalar = $test; - "; - - if ($exception_expected) { - isnt("$@", "", "scalar test - $test"); - } - else { - is($@, "", "scalar test - $test"); - } -} - -while (my ($test, $exception_expected) = each %list_tests) { - eval " - $perl58_fix - my \@array = $test; - "; - - if ($exception_expected) { - isnt("$@", "", "array test - $test"); - } - else { - is($@, "", "array test - $test"); - } -} - -1; diff --git a/ext/autodie/t/hints_provider_does.t b/ext/autodie/t/hints_provider_does.t deleted file mode 100755 index a671b73e13..0000000000 --- a/ext/autodie/t/hints_provider_does.t +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use autodie; - -use Test::More 'no_plan'; - -use FindBin qw($Bin); -use lib "$Bin/lib"; - -use Hints_provider_does qw(always_pass always_fail); -use autodie qw(always_pass always_fail); - -eval { my $x = always_pass() }; -is("$@", "", "always_pass in scalar context"); - -eval { my @x = always_pass() }; -is("$@", "", "always_pass in list context"); - -eval { my $x = always_fail() }; -isnt("$@", "", "always_fail in scalar context"); - -eval { my @x = always_fail() }; -isnt("$@", "", "always_fail in list context"); diff --git a/ext/autodie/t/hints_provider_easy_does_it.t b/ext/autodie/t/hints_provider_easy_does_it.t deleted file mode 100755 index 2606ff8cb3..0000000000 --- a/ext/autodie/t/hints_provider_easy_does_it.t +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use autodie; - -use Test::More 'no_plan'; - -use FindBin qw($Bin); -use lib "$Bin/lib"; - -use Hints_provider_easy_does_it qw(always_pass always_fail); -use autodie qw(always_pass always_fail); - -eval { my $x = always_pass() }; -is("$@", "", "always_pass in scalar context"); - -eval { my @x = always_pass() }; -is("$@", "", "always_pass in list context"); - -eval { my $x = always_fail() }; -isnt("$@", "", "always_fail in scalar context"); - -eval { my @x = always_fail() }; -isnt("$@", "", "always_fail in list context"); diff --git a/ext/autodie/t/hints_provider_isa.t b/ext/autodie/t/hints_provider_isa.t deleted file mode 100755 index 022b34f525..0000000000 --- a/ext/autodie/t/hints_provider_isa.t +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use autodie; - -use Test::More 'no_plan'; - -use FindBin qw($Bin); -use lib "$Bin/lib"; - -use Hints_provider_isa qw(always_pass always_fail); -use autodie qw(always_pass always_fail); - -eval { my $x = always_pass() }; -is("$@", "", "always_pass in scalar context"); - -eval { my @x = always_pass() }; -is("$@", "", "always_pass in list context"); - -eval { my $x = always_fail() }; -isnt("$@", "", "always_fail in scalar context"); - -eval { my @x = always_fail() }; -isnt("$@", "", "always_fail in list context"); diff --git a/ext/autodie/t/internal-backcompat.t b/ext/autodie/t/internal-backcompat.t deleted file mode 100755 index 9f7196c3c5..0000000000 --- a/ext/autodie/t/internal-backcompat.t +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use Fatal; -use Test::More 'no_plan'; - -# Tests to determine if Fatal's internal interfaces remain backwards -# compatible. -# -# WARNING: This file contains a lot of very ugly code, hard-coded -# strings, and nasty API calls. It may frighten small children. -# Viewer discretion is advised. - -# fill_protos. This hasn't been changed since the original Fatal, -# and so should always be the same. - -my %protos = ( - '$' => [ [ 1, '$_[0]' ] ], - '$$' => [ [ 2, '$_[0]', '$_[1]' ] ], - '$$@' => [ [ 3, '$_[0]', '$_[1]', '@_[2..$#_]' ] ], - '\$' => [ [ 1, '${$_[0]}' ] ], - '\%' => [ [ 1, '%{$_[0]}' ] ], - '\%;$*' => [ [ 1, '%{$_[0]}' ], [ 2, '%{$_[0]}', '$_[1]' ], - [ 3, '%{$_[0]}', '$_[1]', '$_[2]' ] ], -); - -while (my ($proto, $code) = each %protos) { - is_deeply( [ Fatal::fill_protos($proto) ], $code, $proto); -} - -# write_invocation tests -no warnings 'qw'; - -# Technically the outputted code varies from the classical Fatal. -# However the changes are mostly whitespace. Those that aren't are -# improvements to error messages. - -my @write_invocation_calls = ( - [ - # Core # Call # Name # Void # Args - [ 1, 'CORE::open', 'open', 0, [ 1, qw($_[0]) ], - [ 2, qw($_[0] $_[1]) ], - [ 3, qw($_[0] $_[1] @_[2..$#_])] - ], - q{ if (@_ == 1) { -return CORE::open($_[0]) || croak "Can't open(@_): $!" } elsif (@_ == 2) { -return CORE::open($_[0], $_[1]) || croak "Can't open(@_): $!" } elsif (@_ == 3) { -return CORE::open($_[0], $_[1], @_[2..$#_]) || croak "Can't open(@_): $!" - } - die "Internal error: open(@_): Do not expect to get ", scalar(@_), " arguments"; - } - ] -); - -foreach my $test (@write_invocation_calls) { - is(Fatal::write_invocation( @{ $test->[0] } ), $test->[1], 'write_inovcation'); -} - -# one_invocation tests. - -my @one_invocation_calls = ( - # Core # Call # Name # Void # Args - [ - [ 1, 'CORE::open', 'open', 0, qw($_[0] $_[1] @_[2..$#_]) ], - q{return CORE::open($_[0], $_[1], @_[2..$#_]) || croak "Can't open(@_): $!"}, - ], - [ - [ 1, 'CORE::open', 'open', 1, qw($_[0] $_[1] @_[2..$#_]) ], - q{return (defined wantarray)?CORE::open($_[0], $_[1], @_[2..$#_]): - CORE::open($_[0], $_[1], @_[2..$#_]) || croak "Can't open(@_): $!"}, - ], -); - -foreach my $test (@one_invocation_calls) { - is(Fatal::one_invocation( @{ $test->[0] } ), $test->[1], 'one_inovcation'); -} - -# TODO: _make_fatal -# Since this subroutine has always started with an underscore, -# I think it's pretty clear that it's internal-only. I'm not -# testing it here, and it doesn't yet have backcompat. diff --git a/ext/autodie/t/internal.t b/ext/autodie/t/internal.t deleted file mode 100755 index c1189444cb..0000000000 --- a/ext/autodie/t/internal.t +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use constant NO_SUCH_FILE => "this_file_or_dir_had_better_not_exist_XYZZY"; - -use Test::More tests => 6; - -# Lexical tests using the internal interface. - -eval { Fatal->import(qw(:lexical :void)) }; -like($@, qr{:void cannot be used with lexical}, ":void can't be used with :lexical"); - -eval { Fatal->import(qw(open close :lexical)) }; -like($@, qr{:lexical must be used as first}, ":lexical must come first"); - -{ - use Fatal qw(:lexical chdir); - - eval { chdir(NO_SUCH_FILE); }; - like ($@, qr/^Can't chdir/, "Lexical fatal chdir"); - - no Fatal qw(:lexical chdir); - - eval { chdir(NO_SUCH_FILE); }; - is ($@, "", "No lexical fatal chdir"); - -} - -eval { chdir(NO_SUCH_FILE); }; -is($@, "", "Lexical chdir becomes non-fatal out of scope."); - -eval { Fatal->import('2+2'); }; -like($@,qr{Bad subroutine name},"Can't use fatal with invalid sub names"); diff --git a/ext/autodie/t/lethal.t b/ext/autodie/t/lethal.t deleted file mode 100755 index 244d2f82b2..0000000000 --- a/ext/autodie/t/lethal.t +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use FindBin; -use Test::More tests => 4; -use lib "$FindBin::Bin/lib"; -use lethal qw(open); - -use constant NO_SUCH_FILE => "this_file_had_better_not_exist"; - -eval { - open(my $fh, '<', NO_SUCH_FILE); -}; - -ok($@, "lethal throws an exception"); -isa_ok($@, 'autodie::exception','...which is the correct class'); -ok($@->matches('open'), "...which matches open"); -is($@->file,__FILE__, "...which reports the correct file"); diff --git a/ext/autodie/t/lib/Caller_helper.pm b/ext/autodie/t/lib/Caller_helper.pm deleted file mode 100644 index 6ee9c69c07..0000000000 --- a/ext/autodie/t/lib/Caller_helper.pm +++ /dev/null @@ -1,13 +0,0 @@ -package Caller_helper; - -our $line; - -sub foo { - use autodie; - - $line = __LINE__; open(my $fh, '<', "no_such_file_here"); - - return; -} - -1; diff --git a/ext/autodie/t/lib/Hints_pod_examples.pm b/ext/autodie/t/lib/Hints_pod_examples.pm deleted file mode 100644 index d88d98e106..0000000000 --- a/ext/autodie/t/lib/Hints_pod_examples.pm +++ /dev/null @@ -1,108 +0,0 @@ -package Hints_pod_examples; -use strict; -use warnings; - -use base qw(Exporter); - -our %DOES = ( 'autodie::hints::provider' => 1 ); - -our @EXPORT_OK = qw( - undef_scalar false_scalar zero_scalar empty_list default_list - empty_or_false_list undef_n_error_list foo re_fail bar - think_positive my_system bizarro_system -); - -use autodie::hints; - -sub AUTODIE_HINTS { - return { - # Scalar failures always return undef: - undef_scalar => { fail => undef }, - - # Scalar failures return any false value [default behaviour]: - false_scalar => { fail => sub { return ! $_[0] } }, - - # Scalar failures always return zero explicitly: - zero_scalar => { fail => '0' }, - - # List failures always return empty list: - # We never want these called in a scalar context - empty_list => { scalar => sub { 1 }, list => [] }, - - # List failures return C<()> or C<(undef)> [default expectation]: - default_list => { fail => sub { ! @_ || @_ == 1 && !defined $_[0] } }, - - # List failures return C<()> or a single false value: - empty_or_false_list => { fail => sub { ! @_ || @_ == 1 && !$_[0] } }, - - # List failures return (undef, "some string") - undef_n_error_list => { fail => sub { @_ == 2 && !defined $_[0] } }, - }; -} - -# Define some subs that all just return their arguments -sub undef_scalar { return wantarray ? @_ : $_[0] } -sub false_scalar { return wantarray ? @_ : $_[0] } -sub zero_scalar { return wantarray ? @_ : $_[0] } -sub empty_list { return wantarray ? @_ : $_[0] } -sub default_list { return wantarray ? @_ : $_[0] } -sub empty_or_false_list { return wantarray ? @_ : $_[0] } -sub undef_n_error_list { return wantarray ? @_ : $_[0] } - - -# Unsuccessful foo() returns 0 in all contexts... -autodie::hints->set_hints_for( - \&foo, - { - scalar => 0, - list => [0], - } -); - -sub foo { return wantarray ? @_ : $_[0] } - -# Unsuccessful re_fail() returns 'FAIL' or '_FAIL' in scalar context, -# returns (-1) in list context... -autodie::hints->set_hints_for( - \&re_fail, - { - scalar => qr/^ _? FAIL $/xms, - list => [-1], - } -); - -sub re_fail { return wantarray ? @_ : $_[0] } - -# Unsuccessful bar() returns 0 in all contexts... -autodie::hints->set_hints_for( - \&bar, - { - scalar => 0, - list => [0], - } -); - -sub bar { return wantarray ? @_ : $_[0] } - -# Unsuccessful think_positive() returns negative number on failure... -autodie::hints->set_hints_for( - \&think_positive, - { - scalar => sub { $_[0] < 0 }, - list => sub { $_[0] < 0 }, - } -); - -sub think_positive { return wantarray ? @_ : $_[0] } - -# Unsuccessful my_system() returns non-zero on failure... -autodie::hints->set_hints_for( - \&my_system, - { - scalar => sub { $_[0] != 0 }, - list => sub { $_[0] != 0 }, - } -); -sub my_system { return wantarray ? @_ : $_[0] }; - -1; diff --git a/ext/autodie/t/lib/Hints_provider_does.pm b/ext/autodie/t/lib/Hints_provider_does.pm deleted file mode 100644 index 403e4b49f7..0000000000 --- a/ext/autodie/t/lib/Hints_provider_does.pm +++ /dev/null @@ -1,29 +0,0 @@ -package Hints_provider_does; -use strict; -use warnings; -use base qw(Exporter); - -our @EXPORT_OK = qw(always_fail always_pass no_hints); - -sub DOES { - my ($class, $arg) = @_; - - return 1 if ($arg eq 'autodie::hints::provider'); - return $class->SUPER::DOES($arg) if $class->SUPER::can('DOES'); - return $class->isa($arg); -} - -my $package = __PACKAGE__; - -sub AUTODIE_HINTS { - return { - always_fail => { list => sub { 1 }, scalar => sub { 1 } }, - always_pass => { list => sub { 0 }, scalar => sub { 0 } }, - }; -} - -sub always_fail { return "foo" }; -sub always_pass { return "foo" }; -sub no_hints { return "foo" }; - -1; diff --git a/ext/autodie/t/lib/Hints_provider_easy_does_it.pm b/ext/autodie/t/lib/Hints_provider_easy_does_it.pm deleted file mode 100644 index 27dbcb2425..0000000000 --- a/ext/autodie/t/lib/Hints_provider_easy_does_it.pm +++ /dev/null @@ -1,23 +0,0 @@ -package Hints_provider_easy_does_it; -use strict; -use warnings; -use base qw(Exporter); - -our @EXPORT_OK = qw(always_fail always_pass no_hints); - -our %DOES = ( 'autodie::hints::provider' => 1 ); - -my $package = __PACKAGE__; - -sub AUTODIE_HINTS { - return { - always_fail => { list => sub { 1 }, scalar => sub { 1 } }, - always_pass => { list => sub { 0 }, scalar => sub { 0 } }, - }; -} - -sub always_fail { return "foo" }; -sub always_pass { return "foo" }; -sub no_hints { return "foo" }; - -1; diff --git a/ext/autodie/t/lib/Hints_provider_isa.pm b/ext/autodie/t/lib/Hints_provider_isa.pm deleted file mode 100644 index ad15e3b258..0000000000 --- a/ext/autodie/t/lib/Hints_provider_isa.pm +++ /dev/null @@ -1,25 +0,0 @@ -package Hints_provider_isa; -use strict; -use warnings; -use base qw(Exporter); - -our @EXPORT_OK = qw(always_fail always_pass no_hints); - -{ package autodie::hints::provider; } - -push(our @ISA, 'autodie::hints::provider'); - -my $package = __PACKAGE__; - -sub AUTODIE_HINTS { - return { - always_fail => { list => sub { 1 }, scalar => sub { 1 } }, - always_pass => { list => sub { 0 }, scalar => sub { 0 } }, - }; -} - -sub always_fail { return "foo" }; -sub always_pass { return "foo" }; -sub no_hints { return "foo" }; - -1; diff --git a/ext/autodie/t/lib/Hints_test.pm b/ext/autodie/t/lib/Hints_test.pm deleted file mode 100644 index 40107880cd..0000000000 --- a/ext/autodie/t/lib/Hints_test.pm +++ /dev/null @@ -1,42 +0,0 @@ -package Hints_test; -use strict; -use warnings; - -use base qw(Exporter); - -our @EXPORT_OK = qw( - fail_on_empty fail_on_false fail_on_undef -); - -use autodie::hints; - -# Create some dummy subs that just return their arguments. - -sub fail_on_empty { return @_; } -sub fail_on_false { return @_; } -sub fail_on_undef { return @_; } - -# Set them to different failure modes when used with autodie. - -autodie::hints->set_hints_for( - \&fail_on_empty, { - list => autodie::hints::EMPTY_ONLY , - scalar => autodie::hints::EMPTY_ONLY - } -); - -autodie::hints->set_hints_for( - \&fail_on_false, { - list => autodie::hints::EMPTY_OR_FALSE , - scalar => autodie::hints::EMPTY_OR_FALSE - } -); - -autodie::hints->set_hints_for( - \&fail_on_undef, { - list => autodie::hints::EMPTY_OR_UNDEF , - scalar => autodie::hints::EMPTY_OR_UNDEF - } -); - -1; diff --git a/ext/autodie/t/lib/OtherTypes.pm b/ext/autodie/t/lib/OtherTypes.pm deleted file mode 100644 index 122a356d9f..0000000000 --- a/ext/autodie/t/lib/OtherTypes.pm +++ /dev/null @@ -1,22 +0,0 @@ -package OtherTypes; -no warnings; - -our $foo = 23; -our @foo = "bar"; -our %foo = (mouse => "trap"); -open foo, "<", $0; - -format foo = -foo -. - -BEGIN { - $main::pvio = *foo{IO}; - $main::pvfm = *foo{FORMAT}; -} - -sub foo { 1 } - -use autodie 'foo'; - -1; diff --git a/ext/autodie/t/lib/Some/Module.pm b/ext/autodie/t/lib/Some/Module.pm deleted file mode 100644 index a24ec93f66..0000000000 --- a/ext/autodie/t/lib/Some/Module.pm +++ /dev/null @@ -1,21 +0,0 @@ -package Some::Module; -use strict; -use warnings; -use base qw(Exporter); - -our @EXPORT_OK = qw(some_sub); - -# This is an example of a subroutine that returns (undef, $msg) -# to signal failure. - -sub some_sub { - my ($arg) = @_; - - if ($arg) { - return (undef, "Insufficient credit"); - } - - return (1,2,3); -} - -1; diff --git a/ext/autodie/t/lib/autodie/test/au.pm b/ext/autodie/t/lib/autodie/test/au.pm deleted file mode 100644 index 7a50e8f101..0000000000 --- a/ext/autodie/t/lib/autodie/test/au.pm +++ /dev/null @@ -1,14 +0,0 @@ -package autodie::test::au; -use strict; -use warnings; - -use base qw(autodie); - -use autodie::test::au::exception; - -sub throw { - my ($this, @args) = @_; - return autodie::test::au::exception->new(@args); -} - -1; diff --git a/ext/autodie/t/lib/autodie/test/au/exception.pm b/ext/autodie/t/lib/autodie/test/au/exception.pm deleted file mode 100644 index 5811fc1ea6..0000000000 --- a/ext/autodie/t/lib/autodie/test/au/exception.pm +++ /dev/null @@ -1,19 +0,0 @@ -package autodie::test::au::exception; -use strict; -use warnings; - -use base qw(autodie::exception); - -sub time_for_a_beer { - return "Now's a good time for a beer."; -} - -sub stringify { - my ($this) = @_; - - my $base_str = $this->SUPER::stringify; - - return "$base_str\n" . $this->time_for_a_beer; -} - -1; diff --git a/ext/autodie/t/lib/autodie/test/badname.pm b/ext/autodie/t/lib/autodie/test/badname.pm deleted file mode 100644 index 2a621a9112..0000000000 --- a/ext/autodie/t/lib/autodie/test/badname.pm +++ /dev/null @@ -1,8 +0,0 @@ -package autodie::test::badname; -use base qw(autodie); - -sub exception_class { - return 'autodie::test::badname::$@#%'; # Doesn't exist! -} - -1; diff --git a/ext/autodie/t/lib/autodie/test/missing.pm b/ext/autodie/t/lib/autodie/test/missing.pm deleted file mode 100644 index b6166a53a4..0000000000 --- a/ext/autodie/t/lib/autodie/test/missing.pm +++ /dev/null @@ -1,8 +0,0 @@ -package autodie::test::missing; -use base qw(autodie); - -sub exception_class { - return "autodie::test::missing::exception"; # Doesn't exist! -} - -1; diff --git a/ext/autodie/t/lib/lethal.pm b/ext/autodie/t/lib/lethal.pm deleted file mode 100644 index a49600a58a..0000000000 --- a/ext/autodie/t/lib/lethal.pm +++ /dev/null @@ -1,8 +0,0 @@ -package lethal; - -# A dummy package showing how we can trivially subclass autodie -# to our tastes. - -use base qw(autodie); - -1; diff --git a/ext/autodie/t/lib/my/autodie.pm b/ext/autodie/t/lib/my/autodie.pm deleted file mode 100644 index 1ad12505a4..0000000000 --- a/ext/autodie/t/lib/my/autodie.pm +++ /dev/null @@ -1,30 +0,0 @@ -package my::autodie; -use strict; -use warnings; - -use base qw(autodie); -use autodie::exception; -use autodie::hints; - -autodie::hints->set_hints_for( - 'Some::Module::some_sub' => { - scalar => sub { 1 }, # No calling in scalar/void context - list => sub { @_ == 2 and not defined $_[0] } - }, -); - -autodie::exception->register( - 'Some::Module::some_sub' => sub { - my ($E) = @_; - - if ($E->context eq "scalar") { - return "some_sub() can't be called in scalar context"; - } - - my $error = $E->return->[1]; - - return "some_sub() failed: $error"; - } -); - -1; diff --git a/ext/autodie/t/lib/pujHa/ghach.pm b/ext/autodie/t/lib/pujHa/ghach.pm deleted file mode 100644 index a55164b1a2..0000000000 --- a/ext/autodie/t/lib/pujHa/ghach.pm +++ /dev/null @@ -1,26 +0,0 @@ -package pujHa'ghach; - -# Translator notes: reH Hegh is Kligon for "always dying". -# It was the original name for this testing pragma, but -# it lacked an apostrophe, which better shows how Perl is -# useful in Klingon naming schemes. - -# The new name is pujHa'ghach is "thing which is not weak". -# puj -> be weak (verb) -# -Ha' -> not -# ghach -> normalise -Ha' verb into noun. -# -# I'm not use if -wI' should be used here. pujwI' is "thing which -# is weak". One could conceivably use "pujHa'wI'" for "thing which -# is not weak". - -use strict; -use warnings; - -use base qw(autodie); - -sub exception_class { - return "pujHa'ghach::Dotlh"; # Dotlh - status -} - -1; diff --git a/ext/autodie/t/lib/pujHa/ghach/Dotlh.pm b/ext/autodie/t/lib/pujHa/ghach/Dotlh.pm deleted file mode 100644 index c7bbf8b1f6..0000000000 --- a/ext/autodie/t/lib/pujHa/ghach/Dotlh.pm +++ /dev/null @@ -1,59 +0,0 @@ -package pujHa'ghach::Dotlh; - -# Translator notes: Dotlh = status - -# Ideally this should be le'wI' - Thing that is exceptional. ;) -# Unfortunately that results in a file called .pm, which may cause -# problems on some filesystems. - -use strict; -use warnings; - -use base qw(autodie::exception); - -sub stringify { - my ($this) = @_; - - my $error = $this->SUPER::stringify; - - return "QaghHommeyHeylIjmo':\n" . # Due to your apparent minor errors - "$error\n" . - "lujqu'"; # Epic fail - - -} - -1; - -__END__ - -# The following was a really neat idea, but currently autodie -# always pushes values in $! to format them, which loses the -# Klingon translation. - -use Errno qw(:POSIX); -use Scalar::Util qw(dualvar); - -my %translation_for = ( - EPERM() => q{Dachaw'be'}, # You do not have permission - ENOENT() => q{De' vItu'laHbe'}, # I cannot find this information. -); - -sub errno { - my ($this) = @_; - - my $errno = int $this->SUPER::errno; - - warn "In tlhIngan errno - $errno\n"; - - if ( my $tlhIngan = $translation_for{ $errno } ) { - return dualvar( $errno, $tlhIngan ); - } - - return $!; - -} - -1; - - diff --git a/ext/autodie/t/mkdir.t b/ext/autodie/t/mkdir.t deleted file mode 100755 index 7bd6529086..0000000000 --- a/ext/autodie/t/mkdir.t +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More; -use FindBin qw($Bin); -use constant TMPDIR => "$Bin/mkdir_test_delete_me"; - -# Delete our directory if it's there -rmdir TMPDIR; - -# See if we can create directories and remove them -mkdir TMPDIR or plan skip_all => "Failed to make test directory"; - -# Test the directory was created --d TMPDIR or plan skip_all => "Failed to make test directory"; - -# Try making it a second time (this should fail) -if(mkdir TMPDIR) { plan skip_all => "Attempt to remake a directory succeeded";} - -# See if we can remove the directory -rmdir TMPDIR or plan skip_all => "Failed to remove directory"; - -# Check that the directory was removed -if(-d TMPDIR) { plan skip_all => "Failed to delete test directory"; } - -# Try to delete second time -if(rmdir TMPDIR) { plan skip_all => "Able to rmdir directory twice"; } - -plan tests => 12; - -# Create a directory (this should succeed) -eval { - use autodie; - - mkdir TMPDIR; -}; -is($@, "", "mkdir returned success"); -ok(-d TMPDIR, "Successfully created test directory"); - -# Try to create it again (this should fail) -eval { - use autodie; - - mkdir TMPDIR; -}; -ok($@, "Re-creating directory causes failure."); -isa_ok($@, "autodie::exception", "... errors are of the correct type"); -ok($@->matches("mkdir"), "... it's also a mkdir object"); -ok($@->matches(":filesys"), "... and a filesys object"); - -# Try to delete directory (this should succeed) -eval { - use autodie; - - rmdir TMPDIR; -}; -is($@, "", "rmdir returned success"); -ok(! -d TMPDIR, "Successfully removed test directory"); - -# Try to delete directory again (this should fail) -eval { - use autodie; - - rmdir TMPDIR; -}; -ok($@, "Re-deleting directory causes failure."); -isa_ok($@, "autodie::exception", "... errors are of the correct type"); -ok($@->matches("rmdir"), "... it's also a rmdir object"); -ok($@->matches(":filesys"), "... and a filesys object"); - diff --git a/ext/autodie/t/open.t b/ext/autodie/t/open.t deleted file mode 100755 index 9964ba0350..0000000000 --- a/ext/autodie/t/open.t +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use Test::More 'no_plan'; - -use constant NO_SUCH_FILE => "this_file_had_better_not_exist"; - -use autodie; - -eval { open(my $fh, '<', NO_SUCH_FILE); }; -ok($@, "3-arg opening non-existent file fails"); -like($@, qr/for reading/, "Well-formatted 3-arg open failure"); - -eval { open(my $fh, "< ".NO_SUCH_FILE) }; -ok($@, "2-arg opening non-existent file fails"); - -like($@, qr/for reading/, "Well-formatted 2-arg open failure"); -unlike($@, qr/GLOB\(0x/, "No ugly globs in 2-arg open messsage"); - -# RT 47520. 2-argument open without mode would repeat the file -# and line number. - -eval { - use autodie; - - open(my $fh, NO_SUCH_FILE); -}; - -isa_ok($@, 'autodie::exception'); -like( $@, qr/at \S+ line \d+/, "At least one mention"); -unlike($@, qr/at \S+ line \d+\s+at \S+ line \d+/, "...but not too mentions"); - -# RT 47520-ish. 2-argument open without a mode should be marked -# as 'for reading'. -like($@, qr/for reading/, "Well formatted 2-arg open without mode"); - -# We also shouldn't get repeated messages, even if the default mode -# was used. Single-arg open always falls through to the default -# formatter. - -eval { - use autodie; - - open( NO_SUCH_FILE . "" ); -}; - -isa_ok($@, 'autodie::exception'); -like( $@, qr/at \S+ line \d+/, "At least one mention"); -unlike($@, qr/at \S+ line \d+\s+at \S+ line \d+/, "...but not too mentions"); diff --git a/ext/autodie/t/recv.t b/ext/autodie/t/recv.t deleted file mode 100755 index cfaa679144..0000000000 --- a/ext/autodie/t/recv.t +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More tests => 8; -use Socket; -use autodie qw(socketpair); - -# All of this code is based around recv returning an empty -# string when it gets data from a local machine (using AF_UNIX), -# but returning an undefined value on error. Fatal/autodie -# should be able to tell the difference. - -$SIG{PIPE} = 'IGNORE'; - -my ($sock1, $sock2); -socketpair($sock1, $sock2, AF_UNIX, SOCK_STREAM, PF_UNSPEC); - -my $buffer; -send($sock1, "xyz", 0); -my $ret = recv($sock2, $buffer, 2, 0); - -use autodie qw(recv); - -SKIP: { - - skip('recv() never returns empty string with socketpair emulation',4) - if ($ret); - - is($buffer,'xy',"recv() operational without autodie"); - - # Read the last byte from the socket. - eval { $ret = recv($sock2, $buffer, 1, 0); }; - - is($@, "", "recv should not die on returning an emtpy string."); - - is($buffer,"z","recv() operational with autodie"); - is($ret,"","recv returns undying empty string for local sockets"); - -} - -eval { - # STDIN isn't a socket, so this should fail. - recv(STDIN,$buffer,1,0); -}; - -ok($@,'recv dies on returning undef'); -isa_ok($@,'autodie::exception'); - -$buffer = "# Not an empty string\n"; - -# Terminate writing for $sock1 -shutdown($sock1, 1); - -eval { - use autodie qw(send); - # Writing to a socket terminated for writing should fail. - send($sock1,$buffer,0); -}; - -ok($@,'send dies on returning undef'); -isa_ok($@,'autodie::exception'); diff --git a/ext/autodie/t/repeat.t b/ext/autodie/t/repeat.t deleted file mode 100755 index 5f85f1218c..0000000000 --- a/ext/autodie/t/repeat.t +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More 'no_plan'; -use constant NO_SUCH_FILE => "this_file_had_better_not_exist"; - -eval { - use autodie qw(open open open); - open(my $fh, '<', NO_SUCH_FILE); -}; - -isa_ok($@,q{autodie::exception}); -ok($@->matches('open'),"Exception from open"); - -eval { - open(my $fh, '<', NO_SUCH_FILE); -}; - -is($@,"","Repeated autodie should not leak"); - diff --git a/ext/autodie/t/scope_leak.t b/ext/autodie/t/scope_leak.t deleted file mode 100755 index 529daa3ecd..0000000000 --- a/ext/autodie/t/scope_leak.t +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use FindBin; - -# Check for %^H leaking across file boundries. Many thanks -# to chocolateboy for pointing out this can be a problem. - -use lib $FindBin::Bin; - -use Test::More 'no_plan'; - -use constant NO_SUCH_FILE => 'this_file_had_better_not_exist'; -use autodie qw(open); - -eval { - open(my $fh, '<', NO_SUCH_FILE); -}; - -ok($@, "basic autodie test"); - -use autodie_test_module; - -# If things don't work as they should, then the file we've -# just loaded will still have an autodying main::open (although -# its own open should be unaffected). - -eval { - leak_test(NO_SUCH_FILE); -}; - -is($@,"","autodying main::open should not leak to other files"); - -eval { - autodie_test_module::your_open(NO_SUCH_FILE); -}; - -is($@,"","Other package open should be unaffected"); - -# Due to odd filenames reported when doing string evals, -# older versions of autodie would not propogate into string evals. - -eval q{ - open(my $fh, '<', NO_SUCH_FILE); -}; - -TODO: { - local $TODO = "No known way of propagating into string eval in 5.8" - if $] < 5.010; - - ok($@, "Failing-open string eval should throw an exception"); - isa_ok($@, 'autodie::exception'); -} - -eval q{ - no autodie; - - open(my $fh, '<', NO_SUCH_FILE); -}; - -is("$@","","disabling autodie in string context should work"); - -eval { - open(my $fh, '<', NO_SUCH_FILE); -}; - -ok($@,"...but shouldn't disable it for the calling code."); -isa_ok($@, 'autodie::exception'); - -eval q{ - no autodie; - - use autodie qw(open); - - open(my $fh, '<', NO_SUCH_FILE); -}; - -ok($@,"Wacky flipping of autodie in string eval should work too!"); -isa_ok($@, 'autodie::exception'); diff --git a/ext/autodie/t/string-eval-basic.t b/ext/autodie/t/string-eval-basic.t deleted file mode 100755 index 62e55006ea..0000000000 --- a/ext/autodie/t/string-eval-basic.t +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use Test::More tests => 3; - -use constant NO_SUCH_FILE => 'this_file_had_better_not_exist'; - -# Keep this test alone in its file as it can be hidden by using autodie outside -# the eval. - -# Just to make sure we're absolutely not encountering any weird $@ clobbering -# events, we'll capture a result from our string eval. - -my $result = eval q{ - use autodie "open"; - - open(my $fh, '<', NO_SUCH_FILE); - - 1; -}; - -ok( ! $result, "Eval should fail with autodie/no such file"); -ok($@, "enabling autodie in string eval should throw an exception"); -isa_ok($@, 'autodie::exception'); diff --git a/ext/autodie/t/string-eval-leak.t b/ext/autodie/t/string-eval-leak.t deleted file mode 100755 index 329bcfa40e..0000000000 --- a/ext/autodie/t/string-eval-leak.t +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use Test::More tests => 2; - -# Under Perl 5.10.x, a string eval can cause a copy to be taken of -# %^H, which delays stringification of our scope guard objects, -# which in turn causes autodie to leak. These tests check to see -# if we've successfully worked around this issue. - -eval { - - { - use autodie; - eval "1"; - } - - open(my $fh, '<', 'this_file_had_better_not_exist'); -}; - -TODO: { - local $TODO; - - if ( $] >= 5.010 ) { - $TODO = "Autodie can leak near string evals in 5.10.x"; - } - - is("$@","","Autodie should not leak out of scope"); -} - -# However, we can plug the leak with 'no autodie'. - -no autodie; - -eval { - open(my $fh, '<', 'this_file_had_better_not_exist'); -}; - -is("$@","",'no autodie should be able to workaround this bug'); diff --git a/ext/autodie/t/sysopen.t b/ext/autodie/t/sysopen.t deleted file mode 100755 index ab489b7830..0000000000 --- a/ext/autodie/t/sysopen.t +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More 'no_plan'; -use Fcntl; - -use autodie qw(sysopen); - -use constant NO_SUCH_FILE => "this_file_had_better_not_be_here_at_all"; - -my $fh; -eval { - sysopen($fh, $0, O_RDONLY); -}; - -is($@, "", "sysopen can open files that exist"); - -like(scalar( <$fh> ), qr/perl/, "Data in file read"); - -eval { - sysopen(my $fh2, NO_SUCH_FILE, O_RDONLY); -}; - -isa_ok($@, 'autodie::exception', 'Opening a bad file fails with sysopen'); diff --git a/ext/autodie/t/truncate.t b/ext/autodie/t/truncate.t deleted file mode 100755 index e69ee32d2e..0000000000 --- a/ext/autodie/t/truncate.t +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use Test::More; -use File::Temp qw(tempfile); -use IO::Handle; - -my $tmpfh = tempfile(); -my $truncate_status; - -eval { - $truncate_status = truncate($tmpfh, 0); -}; - -if ($@ || !defined($truncate_status)) { - plan skip_all => 'Truncate not implemented or not working on this system'; -} - -plan tests => 3; - -SKIP: { - my $can_truncate_stdout = truncate(\*STDOUT,0); - - if ($can_truncate_stdout) { - skip("This system thinks we can truncate STDOUT. Suuure!", 1); - } - - eval { - use autodie; - truncate(\*STDOUT,0); - }; - - isa_ok($@, 'autodie::exception', "Truncating STDOUT should throw an exception"); - -} - -eval { - use autodie; - no warnings 'once'; - truncate(\*FOO, 0); -}; - -isa_ok($@, 'autodie::exception', "Truncating an unopened file is wrong."); - -$tmpfh->print("Hello World"); -$tmpfh->flush; - -eval { - use autodie; - truncate($tmpfh, 0); -}; - -is($@, "", "Truncating a normal file should be fine"); diff --git a/ext/autodie/t/unlink.t b/ext/autodie/t/unlink.t deleted file mode 100755 index f301500fda..0000000000 --- a/ext/autodie/t/unlink.t +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More; -use FindBin qw($Bin); -use constant TMPFILE => "$Bin/unlink_test_delete_me"; - -# Create a file to practice unlinking -open(my $fh, ">", TMPFILE) - or plan skip_all => "Unable to create test file: $!"; -print {$fh} "Test\n"; -close $fh; - -# Check that file now exists --e TMPFILE or plan skip_all => "Failed to create test file"; - -# Check we can unlink -unlink TMPFILE; - -# Check it's gone -if(-e TMPFILE) {plan skip_all => "Failed to delete test file: $!";} - -# Re-create file -open(my $fh2, ">", TMPFILE) - or plan skip_all => "Unable to create test file: $!"; -print {$fh2} "Test\n"; -close $fh2; - -# Check that file now exists --e TMPFILE or plan skip_all => "Failed to create test file"; - -plan tests => 6; - -# Try to delete directory (this should succeed) -eval { - use autodie; - - unlink TMPFILE; -}; -is($@, "", "Unlink appears to have been successful"); -ok(! -e TMPFILE, "File does not exist"); - -# Try to delete file again (this should fail) -eval { - use autodie; - - unlink TMPFILE; -}; -ok($@, "Re-unlinking file causes failure."); -isa_ok($@, "autodie::exception", "... errors are of the correct type"); -ok($@->matches("unlink"), "... it's also a unlink object"); -ok($@->matches(":filesys"), "... and a filesys object"); - diff --git a/ext/autodie/t/user-context.t b/ext/autodie/t/user-context.t deleted file mode 100755 index 65b6a8876a..0000000000 --- a/ext/autodie/t/user-context.t +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use Test::More 'no_plan'; -use File::Copy; -use constant NO_SUCH_FILE => 'this_file_had_better_not_exist'; -use constant EXCEPTION => 'autodie::exception'; - -# http://perlmonks.org/?node_id=744246 describes a situation where -# using autodie on user-defined functions can fail, depending upon -# their context. These tests attempt to detect this bug. - -eval { - use autodie qw(copy); - copy(NO_SUCH_FILE, 'xyzzy'); -}; - -isa_ok($@,EXCEPTION,"Copying a non-existent file should throw an error"); - -eval { - use autodie qw(copy); - my $x = copy(NO_SUCH_FILE, 'xyzzy'); -}; - -isa_ok($@,EXCEPTION,"This shouldn't change with scalar context"); - -eval { - use autodie qw(copy); - my @x = copy(NO_SUCH_FILE, 'xyzzy'); -}; - -isa_ok($@,EXCEPTION,"This shouldn't change with array context"); - -# For good measure, test with built-ins. - -eval { - use autodie qw(open); - open(my $fh, '<', 'xyzzy'); -}; - -isa_ok($@,EXCEPTION,"Opening a non-existent file should throw an error"); - -eval { - use autodie qw(open); - my $x = open(my $fh, '<', 'xyzzy'); -}; - -isa_ok($@,EXCEPTION,"This shouldn't change with scalar context"); - -eval { - use autodie qw(open); - my @x = open(my $fh, '<', 'xyzzy'); -}; - -isa_ok($@,EXCEPTION,"This shouldn't change with array context"); diff --git a/ext/autodie/t/usersub.t b/ext/autodie/t/usersub.t deleted file mode 100755 index 4266804ca9..0000000000 --- a/ext/autodie/t/usersub.t +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/perl -w -use strict; - -use Test::More 'no_plan'; - -sub mytest { - return $_[0]; -} - -is(mytest(q{foo}),q{foo},"Mytest returns input"); - -my $return = eval { mytest(undef); }; - -ok(!defined($return), "mytest returns undef without autodie"); -is($@,"","Mytest doesn't throw an exception without autodie"); - -$return = eval { - use autodie qw(mytest); - - mytest('foo'); -}; - -is($return,'foo',"Mytest returns input with autodie"); -is($@,"","No error should be thrown"); - -$return = eval { - use autodie qw(mytest); - - mytest(undef); -}; - -isa_ok($@,'autodie::exception',"autodie mytest/undef throws exception"); - -# We set initial values here because we're expecting $data to be -# changed to undef later on. Having it as undef to begin with means -# we can't see mytest(undef) working correctly. - -my ($data, $data2) = (1,1); - -eval { - use autodie qw(mytest); - - { - no autodie qw(mytest); - - $data = mytest(undef); - $data2 = mytest('foo'); - } -}; - -is($@,"","no autodie can counter use autodie for user subs"); -ok(!defined($data), "mytest(undef) should return undef"); -is($data2, "foo", "mytest(foo) should return foo"); - -eval { - mytest(undef); -}; - -is($@,"","No lingering failure effects"); - -$return = eval { - mytest("bar"); -}; - -is($return,"bar","No lingering return effects"); diff --git a/ext/autodie/t/version.t b/ext/autodie/t/version.t deleted file mode 100755 index a729129e88..0000000000 --- a/ext/autodie/t/version.t +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use Test::More tests => 4; - -# For the moment, we'd like all our versions to be the same. -# In order to play nicely with some code scanners, they need to be -# hard-coded into the files, rather than just nicking the version -# from autodie::exception at run-time. - -require Fatal; -require autodie; -require autodie::hints; -require autodie::exception; -require autodie::exception::system; - -is($Fatal::VERSION, $autodie::VERSION); -is($autodie::VERSION, $autodie::exception::VERSION); -is($autodie::exception::VERSION, $autodie::exception::system::VERSION); -is($Fatal::VERSION, $autodie::hints::VERSION); diff --git a/ext/autodie/t/version_tag.t b/ext/autodie/t/version_tag.t deleted file mode 100755 index 7cb533329e..0000000000 --- a/ext/autodie/t/version_tag.t +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/perl -w -use strict; -use warnings; -use Test::More tests => 3; - -eval { - use autodie qw(:1.994); - - open(my $fh, '<', 'this_file_had_better_not_exist.txt'); -}; - -isa_ok($@, 'autodie::exception', "Basic version tags work"); - - -# Expanding :1.00 should fail, there was no autodie :1.00 -eval { my $foo = autodie->_expand_tag(":1.00"); }; - -isnt($@,"","Expanding :1.00 should fail"); - -my $version = $autodie::VERSION; - -# Expanding our current version should work! -eval { my $foo = autodie->_expand_tag(":$version"); }; - -is($@,"","Expanding :$version should succeed"); - |