1898184e3Ssthen#!./perl -w 2898184e3Ssthen 3898184e3Ssthen# 4898184e3Ssthen# test method calls and autoloading. 5898184e3Ssthen# 6898184e3Ssthen 7898184e3SsthenBEGIN { 8898184e3Ssthen chdir 't' if -d 't'; 9eac174f2Safresh1 require "./test.pl"; 109f11ffb7Safresh1 set_up_inc( qw(. ../lib ../cpan/parent/lib) ); 11eac174f2Safresh1 require './charset_tools.pl'; 12898184e3Ssthen} 13898184e3Ssthen 14898184e3Ssthenuse strict; 15898184e3Ssthenuse utf8; 16898184e3Ssthenuse open qw( :utf8 :std ); 17898184e3Ssthenno warnings 'once'; 18898184e3Ssthen 19898184e3Ssthenplan(tests => 62); 20898184e3Ssthen 21898184e3Ssthen#Can't use bless yet, as it might not be clean 22898184e3Ssthen 23898184e3Ssthensub F::b { ::is shift, "F"; "UTF8 meth" } 24898184e3Ssthensub F::b { ::is shift, "F"; "UTF8 Stash" } 25898184e3Ssthensub F::b { ::is shift, "F"; "UTF8 Stash&meth" } 26898184e3Ssthen 27898184e3Ssthenis(F->b, "UTF8 meth", "If the method is in UTF-8, lookup works through explicitly named methods"); 28898184e3Ssthenis(F->${\"b"}, "UTF8 meth", '..as does for ->${\""}'); 29898184e3Sstheneval { F->${\"b\0nul"} }; 30898184e3Ssthenok $@, "If the method is in UTF-8, lookup is nul-clean"; 31898184e3Ssthen 32898184e3Ssthenis(F->b, "UTF8 Stash", "If the stash is in UTF-8, lookup works through explicitly named methods"); 33898184e3Ssthenis(F->${\"b"}, "UTF8 Stash", '..as does for ->${\""}'); 34898184e3Sstheneval { F->${\"b\0nul"} }; 35898184e3Ssthenok $@, "If the stash is in UTF-8, lookup is nul-clean"; 36898184e3Ssthen 37898184e3Ssthenis(F->b, "UTF8 Stash&meth", "If both stash and method are in UTF-8, lookup works through explicitly named methods"); 38898184e3Ssthenis(F->${\"b"}, "UTF8 Stash&meth", '..as does for ->${\""}'); 39898184e3Sstheneval { F->${\"b\0nul"} }; 40898184e3Ssthenok $@, "Even if both stash and method are in UTF-8, lookup is nul-clean"; 41898184e3Ssthen 42898184e3Sstheneval { my $ref = \my $var; $ref->method }; 43898184e3Ssthenlike $@, qr/Can't call method "method" on unblessed reference /u; 44898184e3Ssthen 45898184e3Ssthen{ 46898184e3Ssthen use utf8; 47898184e3Ssthen use open qw( :utf8 :std ); 48898184e3Ssthen 49898184e3Ssthen my $e; 50898184e3Ssthen 51898184e3Ssthen eval '$e = bless {}, "E::A"; E::A->foo()'; 52898184e3Ssthen like ($@, qr/^\QCan't locate object method "foo" via package "E::A" at/u); 53898184e3Ssthen eval '$e = bless {}, "E::B"; $e->foo()'; 54898184e3Ssthen like ($@, qr/^\QCan't locate object method "foo" via package "E::B" at/u); 55898184e3Ssthen eval 'E::C->foo()'; 56898184e3Ssthen like ($@, qr/^\QCan't locate object method "foo" via package "E::C" (perhaps /u); 57898184e3Ssthen 58898184e3Ssthen eval 'UNIVERSAL->E::D::foo()'; 59898184e3Ssthen like ($@, qr/^\QCan't locate object method "foo" via package "E::D" (perhaps /u); 60898184e3Ssthen eval 'my $e = bless {}, "UNIVERSAL"; $e->E::E::foo()'; 61898184e3Ssthen like ($@, qr/^\QCan't locate object method "foo" via package "E::E" (perhaps /u); 62898184e3Ssthen 63898184e3Ssthen $e = bless {}, "E::F"; # force package to exist 64898184e3Ssthen eval 'UNIVERSAL->E::F::foo()'; 65898184e3Ssthen like ($@, qr/^\QCan't locate object method "foo" via package "E::F" at/u); 66898184e3Ssthen eval '$e = bless {}, "UNIVERSAL"; $e->E::F::foo()'; 67898184e3Ssthen like ($@, qr/^\QCan't locate object method "foo" via package "E::F" at/u); 68898184e3Ssthen} 69898184e3Ssthen 70898184e3Ssthenis(do { use utf8; use open qw( :utf8 :std ); eval 'Foo->boogie()'; 71898184e3Ssthen $@ =~ /^\QCan't locate object method "boogie" via package "Foo" (perhaps /u ? 1 : $@}, 1); 72898184e3Ssthen 73898184e3Ssthen#This reimplements a bit of _fresh_perl() from test.pl, as we want to decode 74898184e3Ssthen#the output of that program before using it. 75898184e3SsthenSKIP: { 76898184e3Ssthen skip_if_miniperl('no dynamic loading on miniperl, no Encode'); 77898184e3Ssthen 78898184e3Ssthen my $prog = q!use utf8; use open qw( :utf8 :std ); sub T::DESTROY { $x = $_[0]; } bless [], "T";!; 79898184e3Ssthen utf8::decode($prog); 80898184e3Ssthen 81898184e3Ssthen my $tmpfile = tempfile(); 82898184e3Ssthen my $runperl_args = {}; 83898184e3Ssthen $runperl_args->{progfile} = $tmpfile; 84898184e3Ssthen $runperl_args->{stderr} = 1; 85898184e3Ssthen 86898184e3Ssthen open TEST, '>', $tmpfile or die "Cannot open $tmpfile: $!"; 87898184e3Ssthen 88898184e3Ssthen print TEST $prog; 89898184e3Ssthen close TEST or die "Cannot close $tmpfile: $!"; 90898184e3Ssthen 91898184e3Ssthen my $results = runperl(%$runperl_args); 92898184e3Ssthen 93898184e3Ssthen require Encode; 94898184e3Ssthen $results = Encode::decode("UTF-8", $results); 95898184e3Ssthen 96898184e3Ssthen like($results, 97898184e3Ssthen qr/DESTROY created new reference to dead object 'T' during global destruction./u, 98898184e3Ssthen "DESTROY creating a new reference to the object generates a warning in UTF-8."); 99898184e3Ssthen} 100898184e3Ssthen 101898184e3Ssthenpackage Føø::Bær { 102898184e3Ssthen sub new { bless {}, shift } 103898184e3Ssthen sub nèw { bless {}, shift } 104898184e3Ssthen} 105898184e3Ssthen 106898184e3Ssthenlike( Føø::Bær::new("Føø::Bær"), qr/Føø::Bær=HASH/u, 'Can access new directly through a UTF-8 package.' ); 107898184e3Ssthenlike( Føø::Bær->new, qr/Føø::Bær=HASH/u, 'Can access new as a method through a UTF-8 package.' ); 108898184e3Ssthenlike( Føø::Bær::nèw("Føø::Bær"), qr/Føø::Bær=HASH/u, 'Can access nèw directly through a UTF-8 package.' ); 109898184e3Ssthenlike( Føø::Bær->nèw, qr/Føø::Bær=HASH/u, 'Can access nèw as a method through a UTF-8 package.' ); 110898184e3Ssthen 111898184e3Ssthenis( ref Føø::Bær->new, 'Føø::Bær'); 112898184e3Ssthen 113898184e3Ssthenmy $new_ascii = "new"; 114898184e3Ssthenmy $new_latin = "nèw"; 115b8851fccSafresh1my $e_with_grave = byte_utf8a_to_utf8n("\303\250"); 116*e0680481Safresh1my $e_with_grave_escaped= $e_with_grave=~s/\x{a8}/\\\\x\\{a8\\}/r; 117b8851fccSafresh1my $new_utf8 = "n${e_with_grave}w"; 118b8851fccSafresh1my $newoct = "n${e_with_grave}w"; 119898184e3Ssthenutf8::decode($new_utf8); 120898184e3Ssthen 121898184e3Ssthenlike( Føø::Bær->$new_ascii, qr/Føø::Bær=HASH/u, "Can access \$new_ascii, [$new_ascii], stored in a scalar, as a method, through a UTF-8 package." ); 122898184e3Ssthenlike( Føø::Bær->$new_latin, qr/Føø::Bær=HASH/u, "Can access \$new_latin, [$new_latin], stored in a scalar, as a method, through a UTF-8 package." ); 123898184e3Ssthenlike( Føø::Bær->$new_utf8, qr/Føø::Bær=HASH/u, "Can access \$new_utf8, [$new_utf8], stored in a scalar, as a method, through a UTF-8 package." ); 124898184e3Ssthen{ 125898184e3Ssthen local $@; 126898184e3Ssthen eval { Føø::Bær->$newoct }; 127*e0680481Safresh1 like($@, qr/Can't locate object method "n${e_with_grave_escaped}w" via package "Føø::Bær"/u, 128*e0680481Safresh1 "Can't access [$newoct], stored in a scalar, as a method through a UTF-8 package." ); 129898184e3Ssthen} 130898184e3Ssthen 131898184e3Ssthen 132898184e3Ssthenlike( nèw Føø::Bær, qr/Føø::Bær=HASH/u, "Can access [nèw] as a method through a UTF-8 indirect object package."); 133898184e3Ssthen 134898184e3Ssthenmy $pkg_latin_1 = 'Føø::Bær'; 135898184e3Ssthen 136898184e3Ssthenlike( $pkg_latin_1->new, qr/Føø::Bær=HASH/u, 'Can access new as a method when the UTF-8 package name is in a scalar.'); 137898184e3Ssthenlike( $pkg_latin_1->nèw, qr/Føø::Bær=HASH/u, 'Can access nèw as a method when the UTF-8 package name is in a scalar.'); 138898184e3Ssthen 139898184e3Ssthenlike( $pkg_latin_1->$new_ascii, qr/Føø::Bær=HASH/u, "Can access \$new_ascii, [$new_ascii], stored in a scalar, as a method, when the UTF-8 package name is also in a scalar."); 140898184e3Ssthenlike( $pkg_latin_1->$new_latin, qr/Føø::Bær=HASH/u, "Can access \$new_latin, [$new_latin], stored in a scalar, as a method, when the UTF-8 package name is also in a scalar."); 141898184e3Ssthenlike( $pkg_latin_1->$new_utf8, qr/Føø::Bær=HASH/u, "Can access \$new_utf8, [$new_utf8], stored in a scalar, as a method, when the UTF-8 package name is also in a scalar." ); 142898184e3Ssthen{ 143898184e3Ssthen local $@; 144*e0680481Safresh1 145898184e3Ssthen eval { $pkg_latin_1->$newoct }; 146*e0680481Safresh1 like($@, qr/Can't locate object method "n${e_with_grave_escaped}w" via package "Føø::Bær"/u, 147*e0680481Safresh1 "Can't access [$newoct], stored in a scalar, as a method, when the UTF-8 package name is also in a scalar."); 148898184e3Ssthen} 149898184e3Ssthen 150898184e3Ssthenok !!Føø::Bær->can($new_ascii), "->can works for [$new_ascii]"; 151898184e3Ssthenok !!Føø::Bær->can($new_latin), "->can works for [$new_latin]"; 152898184e3Ssthenok((not !!Føø::Bær->can($newoct)), "->can doesn't work for [$newoct]"); 153898184e3Ssthen 154898184e3Ssthenpackage クラス { 155898184e3Ssthen sub new { bless {}, shift } 156898184e3Ssthen sub ニュー { bless {}, shift } 157898184e3Ssthen} 158898184e3Ssthen 159898184e3Ssthenlike( クラス::new("クラス"), qr/クラス=HASH/u); 160898184e3Ssthenlike( クラス->new, qr/クラス=HASH/u); 161898184e3Ssthen 162898184e3Ssthenlike( クラス::ニュー("クラス"), qr/クラス=HASH/u); 163898184e3Ssthenlike( クラス->ニュー, qr/クラス=HASH/u); 164898184e3Ssthen 165898184e3Ssthenlike( ニュー クラス, qr/クラス=HASH/u, "Indirect object is UTF-8, as is the class."); 166898184e3Ssthen 167898184e3Ssthenis( ref クラス->new, 'クラス'); 168898184e3Ssthenis( ref クラス->ニュー, 'クラス'); 169898184e3Ssthen 170898184e3Ssthenpackage Foo::Bar { 171898184e3Ssthen our @ISA = qw( Føø::Bær ); 172898184e3Ssthen} 173898184e3Ssthen 174898184e3Ssthenpackage Foo::Bàz { 175898184e3Ssthen use parent qw( -norequire Føø::Bær ); 176898184e3Ssthen} 177898184e3Ssthen 178898184e3Ssthenpackage ฟọ::バッズ { 179898184e3Ssthen use parent qw( -norequire Føø::Bær クラス ); 180898184e3Ssthen} 181898184e3Ssthen 182898184e3Ssthenok(Foo::Bar->new, 'Simple inheritance works by pushing into @ISA,'); 183898184e3Ssthenok(Foo::Bar->nèw, 'Even with UTF-8 methods'); 184898184e3Ssthen 185898184e3Ssthenok(Foo::Bàz->new, 'Simple inheritance works with parent using -norequire,'); 186898184e3Ssthenok(Foo::Bàz->nèw, 'Even with UTF-8 methods'); 187898184e3Ssthen 188898184e3Ssthenok(ฟọ::バッズ->new, 'parent using -norequire, in a UTF-8 package.'); 189898184e3Ssthenok(ฟọ::バッズ->nèw, 'Also works with UTF-8 methods'); 190898184e3Ssthenok(ฟọ::バッズ->ニュー, 'Even methods from an UTF-8 parent'); 191898184e3Ssthen 192b8851fccSafresh1BEGIN {no strict 'refs'; 193b8851fccSafresh1 ++${"\xff::foo"} if $::IS_ASCII; 194b8851fccSafresh1 ++${"\xdf::foo"} if $::IS_EBCDIC; 195b8851fccSafresh1 } # autovivify the package 196898184e3Ssthenpackage ÿ { # without UTF8 197898184e3Ssthen sub AUTOLOAD { 198b8851fccSafresh1 if ($::IS_ASCII) { 199898184e3Ssthen ::is our $AUTOLOAD, 200898184e3Ssthen "\xff::\x{100}", '$AUTOLOAD made from Latin1 package + UTF8 sub'; 201898184e3Ssthen } 202b8851fccSafresh1 else { 203b8851fccSafresh1 ::is our $AUTOLOAD, 204b8851fccSafresh1 "\xdf::\x{100}", '$AUTOLOAD made from Latin1 package + UTF8 sub'; 205b8851fccSafresh1 } 206b8851fccSafresh1 } 207898184e3Ssthen} 208898184e3Ssthenÿ->${\"\x{100}"}; 209898184e3Ssthen 210898184e3Ssthen#This test should go somewhere else. 211898184e3Ssthen#DATA was being generated in the wrong package. 212898184e3Ssthenpackage ʑ; 213898184e3Ssthenno strict 'refs'; 214898184e3Ssthen 215898184e3Ssthen::ok( *{"ʑ::DATA"}{IO}, "DATA is generated in the right glob"); 216898184e3Ssthen::ok !defined(*{"main::DATA"}{IO}); 217898184e3Ssthen::is scalar <DATA>, "Some data\n"; 218898184e3Ssthen 219898184e3Ssthen__DATA__ 220898184e3SsthenSome data 221