In Test::Aggregate, if a test program has a plan, I want to try to verify that it ran that number of tests. Because of how BEGIN and END blocks work, I am forced to override Test::Builder's ok() method. I've wound up with something like this:
my $ok; BEGIN { $ok = \&Test::Builder::ok } sub Test::Builder::ok { my $callpack; my $stack_level = 0; while ( my ($package, undef, undef, $subroutine) = caller($stack_level) ) { last if 'Test::Aggregate' eq $package; last if $callpack && $subroutine =~ /::(?:BEGIN|CHECK|INIT|END)\z/; $callpack = $package; $stack_level++; } $TESTS_RUN{$callpack} += 1; $ok->(@_); }
See that strange line that checks if I'm in a BEGIN/CHECK/INIT/END block? That's because this prints out that they all run in main:: (I've updated this code to show the issue better).
#!/usr/bin/env perl -l use strict; use warnings; package Bar; { package Foo; BEGIN { print 'BEGIN in ' . caller(0) . ' ' . __PACKAGE__ } CHECK { print 'CHECK in ' . caller(0) . ' ' . __PACKAGE__ } INIT { print 'INIT in ' . caller(0) . ' ' . __PACKAGE__ } END { print 'END in ' . caller(0) . ' ' . __PACKAGE__ } sub frames { my $frame = 0; while ( my $callpack = caller($frame) ) { print "Frame $frame in $callpack"; $frame++; } } } Foo->frames; __END__ BEGIN in main Foo CHECK in main Foo INIT in main Foo Frame 0 in Bar END in main Foo
I've read perlmod and perlsub, but I can't tell if this is documented. I know they're not really subs and that's why caller doesn't report what I expected, but are these blocks always in main::?
package Foo;
sub pkg {
print 'in ' . caller;
}
BEGIN { pkg }
__END__
in Foo
I might argue this is a bug.