Subject: | Make can_ok and isa_ok localize $SIG{__DIE__} |
Neither can_ok nor isa_ok localize $SIG{__DIE__} despite the fact that
failure is occasionally expected and $SIG{__DIE__} called in these cases
during an eval.
I brought this up before here:
http://beta.nntp.perl.org/group/perl.qa/2005/11/msg5027.html
but my proposed patch went about the problem the wrong way, by forcing
UNIVERSAL's isa() and can() to be used, thereby causing certain
overloads to be ignored.
This patch is more appropriate, I think - localizing $SIG{__DIE__} to
the default action for an eval() restores standard behavior, and allows
the caller's $SIG{__DIE__} to propagate independently of Test::More.
Tests are also included in the patch.
Subject: | Test-Simple-0.65.SIGDIE.patch |
diff -ur Test-Simple-0.65-orig/lib/Test/More.pm Test-Simple-0.65/lib/Test/More.pm
--- Test-Simple-0.65-orig/lib/Test/More.pm 2006-11-10 10:26:21.000000000 -0600
+++ Test-Simple-0.65/lib/Test/More.pm 2006-11-20 15:02:10.000000000 -0600
@@ -481,6 +481,7 @@
foreach my $method (@methods) {
local($!, $@); # don't interfere with caller's $@
# eval sometimes resets $!
+ local $SIG{__DIE__} = 'DEFAULT';
eval { $proto->can($method) } || push @nok, $method;
}
@@ -540,7 +541,7 @@
else {
# We can't use UNIVERSAL::isa because we want to honor isa() overrides
local($@, $!); # eval sometimes resets $!
- my $rslt = eval { $object->isa($class) };
+ my $rslt = eval { local $SIG{__DIE__} = 'DEFAULT'; $object->isa($class) };
if( $@ ) {
if( $@ =~ /^Can't call method "isa" on unblessed reference/ ) {
if( !UNIVERSAL::isa($object, $class) ) {
diff -ur Test-Simple-0.65-orig/t/More.t Test-Simple-0.65/t/More.t
--- Test-Simple-0.65-orig/t/More.t 2006-09-04 03:23:12.000000000 -0500
+++ Test-Simple-0.65/t/More.t 2006-11-20 14:56:02.000000000 -0600
@@ -7,7 +7,7 @@
}
}
-use Test::More tests => 51;
+use Test::More tests => 56;
# Make sure we don't mess with $@ or $!. Test at bottom.
my $Err = "this should not be touched";
@@ -62,6 +62,28 @@
isa_ok( $foo, 'blah');
}
+# can_ok() & isa_ok should make sure that they localize $SIG{__DIE__},
+# so the eval() doesn't call a custom handler when it shouldn't.
+{
+ my $die_counter = 0;
+ local $SIG{__DIE__} = sub { $die_counter++ };
+ TODO: {
+ local $TODO = 'Expecting can_ok() to fail';
+ can_ok( [], 'blah' );
+ }
+ cmp_ok( $die_counter, '==', 0, 'can_ok did not cause custom die to fire' );
+
+ TODO: {
+ local $TODO = 'Expecting isa_ok() to fail';
+ can_ok( [], 'blah' );
+ }
+ cmp_ok( $die_counter, '==', 0, 'isa_ok did not cause custom die to fire' );
+
+ local $@ = '';
+ eval { die 'a most violent death'; };
+ cmp_ok( $die_counter, '==', 1, 'die properly fires $SIG{__DIE__}' );
+}
+
pass('pass() passed');