1*0Sstevel@tonic-gate#!./perl -w 2*0Sstevel@tonic-gate 3*0Sstevel@tonic-gate# Tests for the coderef-in-@INC feature 4*0Sstevel@tonic-gate 5*0Sstevel@tonic-gateBEGIN { 6*0Sstevel@tonic-gate chdir 't' if -d 't'; 7*0Sstevel@tonic-gate @INC = qw(. ../lib); 8*0Sstevel@tonic-gate} 9*0Sstevel@tonic-gate 10*0Sstevel@tonic-gateuse File::Spec; 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gaterequire "test.pl"; 13*0Sstevel@tonic-gateplan(tests => 45); 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gatemy @tempfiles = (); 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gatesub get_temp_fh { 18*0Sstevel@tonic-gate my $f = "DummyModule0000"; 19*0Sstevel@tonic-gate 1 while -e ++$f; 20*0Sstevel@tonic-gate push @tempfiles, $f; 21*0Sstevel@tonic-gate open my $fh, ">$f" or die "Can't create $f: $!"; 22*0Sstevel@tonic-gate print $fh "package ".substr($_[0],0,-3).";\n1;\n"; 23*0Sstevel@tonic-gate print $fh $_[1] if @_ > 1; 24*0Sstevel@tonic-gate close $fh or die "Couldn't close: $!"; 25*0Sstevel@tonic-gate open $fh, $f or die "Can't open $f: $!"; 26*0Sstevel@tonic-gate return $fh; 27*0Sstevel@tonic-gate} 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gateEND { 1 while unlink @tempfiles } 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gatesub fooinc { 32*0Sstevel@tonic-gate my ($self, $filename) = @_; 33*0Sstevel@tonic-gate if (substr($filename,0,3) eq 'Foo') { 34*0Sstevel@tonic-gate return get_temp_fh($filename); 35*0Sstevel@tonic-gate } 36*0Sstevel@tonic-gate else { 37*0Sstevel@tonic-gate return undef; 38*0Sstevel@tonic-gate } 39*0Sstevel@tonic-gate} 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gatepush @INC, \&fooinc; 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gatemy $evalret = eval { require Bar; 1 }; 44*0Sstevel@tonic-gateok( !$evalret, 'Trying non-magic package' ); 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate$evalret = eval { require Foo; 1 }; 47*0Sstevel@tonic-gatedie $@ if $@; 48*0Sstevel@tonic-gateok( $evalret, 'require Foo; magic via code ref' ); 49*0Sstevel@tonic-gateok( exists $INC{'Foo.pm'}, ' %INC sees Foo.pm' ); 50*0Sstevel@tonic-gateis( ref $INC{'Foo.pm'}, 'CODE', ' val Foo.pm is a coderef in %INC' ); 51*0Sstevel@tonic-gateis( $INC{'Foo.pm'}, \&fooinc, ' val Foo.pm is correct in %INC' ); 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate$evalret = eval "use Foo1; 1;"; 54*0Sstevel@tonic-gatedie $@ if $@; 55*0Sstevel@tonic-gateok( $evalret, 'use Foo1' ); 56*0Sstevel@tonic-gateok( exists $INC{'Foo1.pm'}, ' %INC sees Foo1.pm' ); 57*0Sstevel@tonic-gateis( ref $INC{'Foo1.pm'}, 'CODE', ' val Foo1.pm is a coderef in %INC' ); 58*0Sstevel@tonic-gateis( $INC{'Foo1.pm'}, \&fooinc, ' val Foo1.pm is correct in %INC' ); 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate$evalret = eval { do 'Foo2.pl'; 1 }; 61*0Sstevel@tonic-gatedie $@ if $@; 62*0Sstevel@tonic-gateok( $evalret, 'do "Foo2.pl"' ); 63*0Sstevel@tonic-gateok( exists $INC{'Foo2.pl'}, ' %INC sees Foo2.pl' ); 64*0Sstevel@tonic-gateis( ref $INC{'Foo2.pl'}, 'CODE', ' val Foo2.pl is a coderef in %INC' ); 65*0Sstevel@tonic-gateis( $INC{'Foo2.pl'}, \&fooinc, ' val Foo2.pl is correct in %INC' ); 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gatepop @INC; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gatesub fooinc2 { 71*0Sstevel@tonic-gate my ($self, $filename) = @_; 72*0Sstevel@tonic-gate if (substr($filename, 0, length($self->[1])) eq $self->[1]) { 73*0Sstevel@tonic-gate return get_temp_fh($filename); 74*0Sstevel@tonic-gate } 75*0Sstevel@tonic-gate else { 76*0Sstevel@tonic-gate return undef; 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate} 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gatemy $arrayref = [ \&fooinc2, 'Bar' ]; 81*0Sstevel@tonic-gatepush @INC, $arrayref; 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate$evalret = eval { require Foo; 1; }; 84*0Sstevel@tonic-gatedie $@ if $@; 85*0Sstevel@tonic-gateok( $evalret, 'Originally loaded packages preserved' ); 86*0Sstevel@tonic-gate$evalret = eval { require Foo3; 1; }; 87*0Sstevel@tonic-gateok( !$evalret, 'Original magic INC purged' ); 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate$evalret = eval { require Bar; 1 }; 90*0Sstevel@tonic-gatedie $@ if $@; 91*0Sstevel@tonic-gateok( $evalret, 'require Bar; magic via array ref' ); 92*0Sstevel@tonic-gateok( exists $INC{'Bar.pm'}, ' %INC sees Bar.pm' ); 93*0Sstevel@tonic-gateis( ref $INC{'Bar.pm'}, 'ARRAY', ' val Bar.pm is an arrayref in %INC' ); 94*0Sstevel@tonic-gateis( $INC{'Bar.pm'}, $arrayref, ' val Bar.pm is correct in %INC' ); 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gateok( eval "use Bar1; 1;", 'use Bar1' ); 97*0Sstevel@tonic-gateok( exists $INC{'Bar1.pm'}, ' %INC sees Bar1.pm' ); 98*0Sstevel@tonic-gateis( ref $INC{'Bar1.pm'}, 'ARRAY', ' val Bar1.pm is an arrayref in %INC' ); 99*0Sstevel@tonic-gateis( $INC{'Bar1.pm'}, $arrayref, ' val Bar1.pm is correct in %INC' ); 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gateok( eval { do 'Bar2.pl'; 1 }, 'do "Bar2.pl"' ); 102*0Sstevel@tonic-gateok( exists $INC{'Bar2.pl'}, ' %INC sees Bar2.pl' ); 103*0Sstevel@tonic-gateis( ref $INC{'Bar2.pl'}, 'ARRAY', ' val Bar2.pl is an arrayref in %INC' ); 104*0Sstevel@tonic-gateis( $INC{'Bar2.pl'}, $arrayref, ' val Bar2.pl is correct in %INC' ); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gatepop @INC; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gatesub FooLoader::INC { 109*0Sstevel@tonic-gate my ($self, $filename) = @_; 110*0Sstevel@tonic-gate if (substr($filename,0,4) eq 'Quux') { 111*0Sstevel@tonic-gate return get_temp_fh($filename); 112*0Sstevel@tonic-gate } 113*0Sstevel@tonic-gate else { 114*0Sstevel@tonic-gate return undef; 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate} 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gatemy $href = bless( {}, 'FooLoader' ); 119*0Sstevel@tonic-gatepush @INC, $href; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate$evalret = eval { require Quux; 1 }; 122*0Sstevel@tonic-gatedie $@ if $@; 123*0Sstevel@tonic-gateok( $evalret, 'require Quux; magic via hash object' ); 124*0Sstevel@tonic-gateok( exists $INC{'Quux.pm'}, ' %INC sees Quux.pm' ); 125*0Sstevel@tonic-gateis( ref $INC{'Quux.pm'}, 'FooLoader', 126*0Sstevel@tonic-gate ' val Quux.pm is an object in %INC' ); 127*0Sstevel@tonic-gateis( $INC{'Quux.pm'}, $href, ' val Quux.pm is correct in %INC' ); 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gatepop @INC; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gatemy $aref = bless( [], 'FooLoader' ); 132*0Sstevel@tonic-gatepush @INC, $aref; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate$evalret = eval { require Quux1; 1 }; 135*0Sstevel@tonic-gatedie $@ if $@; 136*0Sstevel@tonic-gateok( $evalret, 'require Quux1; magic via array object' ); 137*0Sstevel@tonic-gateok( exists $INC{'Quux1.pm'}, ' %INC sees Quux1.pm' ); 138*0Sstevel@tonic-gateis( ref $INC{'Quux1.pm'}, 'FooLoader', 139*0Sstevel@tonic-gate ' val Quux1.pm is an object in %INC' ); 140*0Sstevel@tonic-gateis( $INC{'Quux1.pm'}, $aref, ' val Quux1.pm is correct in %INC' ); 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gatepop @INC; 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gatemy $sref = bless( \(my $x = 1), 'FooLoader' ); 145*0Sstevel@tonic-gatepush @INC, $sref; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate$evalret = eval { require Quux2; 1 }; 148*0Sstevel@tonic-gatedie $@ if $@; 149*0Sstevel@tonic-gateok( $evalret, 'require Quux2; magic via scalar object' ); 150*0Sstevel@tonic-gateok( exists $INC{'Quux2.pm'}, ' %INC sees Quux2.pm' ); 151*0Sstevel@tonic-gateis( ref $INC{'Quux2.pm'}, 'FooLoader', 152*0Sstevel@tonic-gate ' val Quux2.pm is an object in %INC' ); 153*0Sstevel@tonic-gateis( $INC{'Quux2.pm'}, $sref, ' val Quux2.pm is correct in %INC' ); 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gatepop @INC; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gatepush @INC, sub { 158*0Sstevel@tonic-gate my ($self, $filename) = @_; 159*0Sstevel@tonic-gate if (substr($filename,0,4) eq 'Toto') { 160*0Sstevel@tonic-gate $INC{$filename} = 'xyz'; 161*0Sstevel@tonic-gate return get_temp_fh($filename); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate else { 164*0Sstevel@tonic-gate return undef; 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate}; 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate$evalret = eval { require Toto; 1 }; 169*0Sstevel@tonic-gatedie $@ if $@; 170*0Sstevel@tonic-gateok( $evalret, 'require Toto; magic via anonymous code ref' ); 171*0Sstevel@tonic-gateok( exists $INC{'Toto.pm'}, ' %INC sees Toto.pm' ); 172*0Sstevel@tonic-gateok( ! ref $INC{'Toto.pm'}, q/ val Toto.pm isn't a ref in %INC/ ); 173*0Sstevel@tonic-gateis( $INC{'Toto.pm'}, 'xyz', ' val Toto.pm is correct in %INC' ); 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gatepop @INC; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gatepush @INC, sub { 178*0Sstevel@tonic-gate my ($self, $filename) = @_; 179*0Sstevel@tonic-gate if ($filename eq 'abc.pl') { 180*0Sstevel@tonic-gate return get_temp_fh($filename, qq(return "abc";\n)); 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate else { 183*0Sstevel@tonic-gate return undef; 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate}; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate$ret = ""; 188*0Sstevel@tonic-gate$ret ||= do 'abc.pl'; 189*0Sstevel@tonic-gateis( $ret, 'abc', 'do "abc.pl" sees return value' ); 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gatepop @INC; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gatemy $filename = $^O eq 'MacOS' ? ':Foo:Foo.pm' : './Foo.pm'; 194*0Sstevel@tonic-gate{ 195*0Sstevel@tonic-gate local @INC; 196*0Sstevel@tonic-gate @INC = sub { $filename = 'seen'; return undef; }; 197*0Sstevel@tonic-gate eval { require $filename; }; 198*0Sstevel@tonic-gate is( $filename, 'seen', 'the coderef sees fully-qualified pathnames' ); 199*0Sstevel@tonic-gate} 200