1*0Sstevel@tonic-gate#!./perl -w 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gateBEGIN { 4*0Sstevel@tonic-gate chdir 't' if -d 't'; 5*0Sstevel@tonic-gate @INC = '../lib'; 6*0Sstevel@tonic-gate} 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gateuse strict; 9*0Sstevel@tonic-gateuse File::Spec; 10*0Sstevel@tonic-gateuse File::Path; 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gatemy $dir; 13*0Sstevel@tonic-gateBEGIN 14*0Sstevel@tonic-gate{ 15*0Sstevel@tonic-gate $dir = File::Spec->catdir( "auto-$$" ); 16*0Sstevel@tonic-gate unshift @INC, $dir; 17*0Sstevel@tonic-gate} 18*0Sstevel@tonic-gate 19*0Sstevel@tonic-gateuse Test::More tests => 17; 20*0Sstevel@tonic-gate 21*0Sstevel@tonic-gate# First we must set up some autoloader files 22*0Sstevel@tonic-gatemy $fulldir = File::Spec->catdir( $dir, 'auto', 'Foo' ); 23*0Sstevel@tonic-gatemkpath( $fulldir ) or die "Can't mkdir '$fulldir': $!"; 24*0Sstevel@tonic-gate 25*0Sstevel@tonic-gateopen(FOO, '>', File::Spec->catfile( $fulldir, 'foo.al' )) 26*0Sstevel@tonic-gate or die "Can't open foo file: $!"; 27*0Sstevel@tonic-gateprint FOO <<'EOT'; 28*0Sstevel@tonic-gatepackage Foo; 29*0Sstevel@tonic-gatesub foo { shift; shift || "foo" } 30*0Sstevel@tonic-gate1; 31*0Sstevel@tonic-gateEOT 32*0Sstevel@tonic-gateclose(FOO); 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gateopen(BAR, '>', File::Spec->catfile( $fulldir, 'bar.al' )) 35*0Sstevel@tonic-gate or die "Can't open bar file: $!"; 36*0Sstevel@tonic-gateprint BAR <<'EOT'; 37*0Sstevel@tonic-gatepackage Foo; 38*0Sstevel@tonic-gatesub bar { shift; shift || "bar" } 39*0Sstevel@tonic-gate1; 40*0Sstevel@tonic-gateEOT 41*0Sstevel@tonic-gateclose(BAR); 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gateopen(BAZ, '>', File::Spec->catfile( $fulldir, 'bazmarkhian.al' )) 44*0Sstevel@tonic-gate or die "Can't open bazmarkhian file: $!"; 45*0Sstevel@tonic-gateprint BAZ <<'EOT'; 46*0Sstevel@tonic-gatepackage Foo; 47*0Sstevel@tonic-gatesub bazmarkhianish { shift; shift || "baz" } 48*0Sstevel@tonic-gate1; 49*0Sstevel@tonic-gateEOT 50*0Sstevel@tonic-gateclose(BAZ); 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gateopen(BLECH, '>', File::Spec->catfile( $fulldir, 'blechanawilla.al' )) 53*0Sstevel@tonic-gate or die "Can't open blech file: $!"; 54*0Sstevel@tonic-gateprint BLECH <<'EOT'; 55*0Sstevel@tonic-gatepackage Foo; 56*0Sstevel@tonic-gatesub blechanawilla { compilation error ( 57*0Sstevel@tonic-gateEOT 58*0Sstevel@tonic-gateclose(BLECH); 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate# This is just to keep the old SVR3 systems happy; they may fail 61*0Sstevel@tonic-gate# to find the above file so we duplicate it where they should find it. 62*0Sstevel@tonic-gateopen(BLECH, '>', File::Spec->catfile( $fulldir, 'blechanawil.al' )) 63*0Sstevel@tonic-gate or die "Can't open blech file: $!"; 64*0Sstevel@tonic-gateprint BLECH <<'EOT'; 65*0Sstevel@tonic-gatepackage Foo; 66*0Sstevel@tonic-gatesub blechanawilla { compilation error ( 67*0Sstevel@tonic-gateEOT 68*0Sstevel@tonic-gateclose(BLECH); 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate# Let's define the package 71*0Sstevel@tonic-gatepackage Foo; 72*0Sstevel@tonic-gaterequire AutoLoader; 73*0Sstevel@tonic-gateAutoLoader->import( 'AUTOLOAD' ); 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gatesub new { bless {}, shift }; 76*0Sstevel@tonic-gatesub foo; 77*0Sstevel@tonic-gatesub bar; 78*0Sstevel@tonic-gatesub bazmarkhianish; 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gatepackage main; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gatemy $foo = new Foo; 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gatemy $result = $foo->can( 'foo' ); 85*0Sstevel@tonic-gateok( $result, 'can() first time' ); 86*0Sstevel@tonic-gateis( $foo->foo, 'foo', 'autoloaded first time' ); 87*0Sstevel@tonic-gateis( $foo->foo, 'foo', 'regular call' ); 88*0Sstevel@tonic-gateis( $result, \&Foo::foo, 'can() returns ref to regular installed sub' ); 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gateeval { 91*0Sstevel@tonic-gate $foo->will_fail; 92*0Sstevel@tonic-gate}; 93*0Sstevel@tonic-gatelike( $@, qr/^Can't locate/, 'undefined method' ); 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate$result = $foo->can( 'will_fail' ); 96*0Sstevel@tonic-gateok( ! $result, 'can() should fail on undefined methods' ); 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate# Used to be trouble with this 99*0Sstevel@tonic-gateeval { 100*0Sstevel@tonic-gate my $foo = new Foo; 101*0Sstevel@tonic-gate die "oops"; 102*0Sstevel@tonic-gate}; 103*0Sstevel@tonic-gatelike( $@, qr/oops/, 'indirect method call' ); 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate# Pass regular expression variable to autoloaded function. This used 106*0Sstevel@tonic-gate# to go wrong because AutoLoader used regular expressions to generate 107*0Sstevel@tonic-gate# autoloaded filename. 108*0Sstevel@tonic-gate'foo' =~ /(\w+)/; 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gateis( $foo->bar($1), 'foo', 'autoloaded method should not stomp match vars' ); 111*0Sstevel@tonic-gateis( $foo->bar($1), 'foo', '(again)' ); 112*0Sstevel@tonic-gateis( $foo->bazmarkhianish($1), 'foo', 'for any method call' ); 113*0Sstevel@tonic-gateis( $foo->bazmarkhianish($1), 'foo', '(again)' ); 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate# Used to retry long subnames with shorter filenames on any old 116*0Sstevel@tonic-gate# exception, including compilation error. Now AutoLoader only 117*0Sstevel@tonic-gate# tries shorter filenames if it can't find the long one. 118*0Sstevel@tonic-gateeval { 119*0Sstevel@tonic-gate $foo->blechanawilla; 120*0Sstevel@tonic-gate}; 121*0Sstevel@tonic-gatelike( $@, qr/syntax error/, 'require error propagates' ); 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate# test recursive autoloads 124*0Sstevel@tonic-gateopen(F, '>', File::Spec->catfile( $fulldir, 'a.al')) 125*0Sstevel@tonic-gate or die "Cannot make 'a' file: $!"; 126*0Sstevel@tonic-gateprint F <<'EOT'; 127*0Sstevel@tonic-gatepackage Foo; 128*0Sstevel@tonic-gateBEGIN { b() } 129*0Sstevel@tonic-gatesub a { ::ok( 1, 'adding a new autoloaded method' ); } 130*0Sstevel@tonic-gate1; 131*0Sstevel@tonic-gateEOT 132*0Sstevel@tonic-gateclose(F); 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gateopen(F, '>', File::Spec->catfile( $fulldir, 'b.al')) 135*0Sstevel@tonic-gate or die "Cannot make 'b' file: $!"; 136*0Sstevel@tonic-gateprint F <<'EOT'; 137*0Sstevel@tonic-gatepackage Foo; 138*0Sstevel@tonic-gatesub b { ::ok( 1, 'adding a new autoloaded method' ) } 139*0Sstevel@tonic-gate1; 140*0Sstevel@tonic-gateEOT 141*0Sstevel@tonic-gateclose(F); 142*0Sstevel@tonic-gateFoo::a(); 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gatepackage Bar; 145*0Sstevel@tonic-gateAutoLoader->import(); 146*0Sstevel@tonic-gate::ok( ! defined &AUTOLOAD, 'AutoLoader should not export AUTOLOAD by default' ); 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gatepackage Foo; 149*0Sstevel@tonic-gateAutoLoader->unimport(); 150*0Sstevel@tonic-gateeval { Foo->baz() }; 151*0Sstevel@tonic-gate::like( $@, qr/locate object method "baz"/, 152*0Sstevel@tonic-gate 'unimport() should remove imported AUTOLOAD()' ); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gatepackage Baz; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gatesub AUTOLOAD { 'i am here' } 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gateAutoLoader->import(); 159*0Sstevel@tonic-gateAutoLoader->unimport(); 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate::is( Baz->AUTOLOAD(), 'i am here', '... but not non-imported AUTOLOAD()' ); 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gatepackage main; 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate# cleanup 166*0Sstevel@tonic-gateEND { 167*0Sstevel@tonic-gate return unless $dir && -d $dir; 168*0Sstevel@tonic-gate rmtree $dir; 169*0Sstevel@tonic-gate} 170