Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Test-Simple CPAN distribution.

Report information
The Basics
Id: 16355
Status: resolved
Priority: 0/
Queue: Test-Simple

People
Owner: Nobody in particular
Requestors: LGODDARD [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Subject: AUTOLOADed methods fail 'can' test
Important to me, perhaps trivial to others. If you run the attached script, you will probably see better than I can explain. I use &AUTOLOAD to catch calls to subroutine/methods that are defined, and in certain circumstances call other subroutines/methods. As in perltoot (I think). Anyway, such is not caught by the 'can' test, and I presume it can't be unless it is passed a correctly instantiated object (which I guess is the subject of the test). Anyway, hth. perl -V is just the latest on Win32 and RedHat. If it turns out to be relevant I'll pass it on.
use strict; use warnings; package Example; our $AUTOLOAD; sub new { return bless {}, ref($_[0]) || __PACKAGE__; } sub call_hardcoded_sub_as_method { return 1; } sub never_called_directly { warn '>> This is never_called_directly called by '.join(' ', caller),"\n"; return 1; } sub AUTOLOAD { warn '>> This was autoloaded as '.$AUTOLOAD."\n"; if ($AUTOLOAD eq 'redirect_to_never_called_directly'){ goto &never_called_directly; } } #warn '>> Test calling GOOD autoload method "coltrane" ...'."\n"; #warn '>> ...' . (Example->call_hardcoded_sub_as_method? 'ok':'not ok')."\n"; #warn '>> Test calling BAD autoload method "coltrane" ...'."\n"; #warn '>> ...' . (Example->apriocts? 'not ok':'ok')."\n"; 1; use Test::More tests => 1; my $eg = Example->new; isa_ok($eg, 'Example'); can_ok($eg, 'call_hardcoded_sub_as_method'); can_ok($eg->redirect_to_never_called_directly, 'redirect_to_never_called_directly'); # Fake it $Example::AUTOLOAD = 'redirect_to_never_called_directly'; is(&Example::AUTOLOAD, 1, 'Direct call to AUTOLOAD works'); exit;
[LGODDARD - Thu Dec 8 08:48:30 2005]: Show quoted text
> Important to me, perhaps trivial to others. If you run the attached > script, you will probably see better than I can explain. I use > &AUTOLOAD to catch calls to subroutine/methods that are defined, > and in certain circumstances call other subroutines/methods. As in > perltoot (I think). > > Anyway, such is not caught by the 'can' test, and I presume it can't > be unless it is passed a correctly instantiated object (which I > guess is the subject of the test).
There's two things wrong here. First, you're calling can_ok() wrong. The first argument is the class or object you want to call can() on. You've instead got: can_ok($eg->redirect_to_never_called_directly, 'redirect_to_never_called_directly'); Which is equivalent to: my $thing = $eg->redirect_to_never_called_directly; can_ok( $thing, 'redirect_to_never_called_directly' ); and likely not what you meant. redirect_to_never_called_directly() returns nothing. So you've just asked if nothing has a function called 'redirect_to_never_called_directly'. I admit can_ok() probably should have warned you about this. The proper way to call it is: can_ok($eg, 'redirect_to_never_called_directly'); but that won't work either. As mentioned in the docs, can_ok() is just a thin wrapper around can(). $obj->can('autoloaded_method') can not work unless you forward declare autoloaded_method() (documented in the UNIVERSAL man page). To understand why, consider this AUTOLOAD routine: sub AUTOLOAD { goto &foo if int rand 2; die; } So can_ok() is working properly. No bug. If I may give some advice I heard from someone else. If you have a problem and think "I'll solve that with an AUTOLOAD" you now have two problems. Consider instead generating methods at load-time. This technique does not have the pitfalls of autoloading. for my $method (qw(foo bar baz)) { my $code = sub { print "$method called!\n"; }; no strict 'refs'; *{$method} = $code; }