Strange BEGIN behavior?

Ovid on 2008-03-26T14:58:04

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::?


It's more bizarre than that...

mauzo on 2008-03-26T21:35:55

package Foo;
sub pkg {
    print 'in ' . caller;
}
BEGIN { pkg }
__END__
in Foo

I might argue this is a bug.