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.