1*898184e3Ssthen#!./perl 2*898184e3Ssthen 3*898184e3Ssthenuse utf8; 4*898184e3Ssthenuse open qw( :utf8 :std ); 5*898184e3Ssthenuse strict; 6*898184e3Ssthenuse warnings; 7*898184e3Ssthen 8*898184e3SsthenBEGIN { require q(./test.pl); } plan(tests => 53); 9*898184e3Ssthen 10*898184e3Ssthenrequire mro; 11*898184e3Ssthen 12*898184e3Ssthen{ 13*898184e3Ssthen package MRO_அ; 14*898184e3Ssthen our @ISA = qw//; 15*898184e3Ssthen package MRO_ɓ; 16*898184e3Ssthen our @ISA = qw//; 17*898184e3Ssthen package MRO_ᶝ; 18*898184e3Ssthen our @ISA = qw//; 19*898184e3Ssthen package MRO_d; 20*898184e3Ssthen our @ISA = qw/MRO_அ MRO_ɓ MRO_ᶝ/; 21*898184e3Ssthen package MRO_ɛ; 22*898184e3Ssthen our @ISA = qw/MRO_அ MRO_ɓ MRO_ᶝ/; 23*898184e3Ssthen package MRO_ᚠ; 24*898184e3Ssthen our @ISA = qw/MRO_d MRO_ɛ/; 25*898184e3Ssthen} 26*898184e3Ssthen 27*898184e3Ssthenmy @MFO_ᚠ_DFS = qw/MRO_ᚠ MRO_d MRO_அ MRO_ɓ MRO_ᶝ MRO_ɛ/; 28*898184e3Ssthenmy @MFO_ᚠ_C3 = qw/MRO_ᚠ MRO_d MRO_ɛ MRO_அ MRO_ɓ MRO_ᶝ/; 29*898184e3Ssthenis(mro::get_mro('MRO_ᚠ'), 'dfs'); 30*898184e3Ssthenok(eq_array( 31*898184e3Ssthen mro::get_linear_isa('MRO_ᚠ'), \@MFO_ᚠ_DFS 32*898184e3Ssthen)); 33*898184e3Ssthen 34*898184e3Ssthenok(eq_array(mro::get_linear_isa('MRO_ᚠ', 'dfs'), \@MFO_ᚠ_DFS)); 35*898184e3Ssthenok(eq_array(mro::get_linear_isa('MRO_ᚠ', 'c3'), \@MFO_ᚠ_C3)); 36*898184e3Sstheneval{mro::get_linear_isa('MRO_ᚠ', 'C3')}; 37*898184e3Ssthenlike($@, qr/^Invalid mro name: 'C3'/); 38*898184e3Ssthen 39*898184e3Ssthenmro::set_mro('MRO_ᚠ', 'c3'); 40*898184e3Ssthenis(mro::get_mro('MRO_ᚠ'), 'c3'); 41*898184e3Ssthenok(eq_array( 42*898184e3Ssthen mro::get_linear_isa('MRO_ᚠ'), \@MFO_ᚠ_C3 43*898184e3Ssthen)); 44*898184e3Ssthen 45*898184e3Ssthenok(eq_array(mro::get_linear_isa('MRO_ᚠ', 'dfs'), \@MFO_ᚠ_DFS)); 46*898184e3Ssthenok(eq_array(mro::get_linear_isa('MRO_ᚠ', 'c3'), \@MFO_ᚠ_C3)); 47*898184e3Sstheneval{mro::get_linear_isa('MRO_ᚠ', 'C3')}; 48*898184e3Ssthenlike($@, qr/^Invalid mro name: 'C3'/); 49*898184e3Ssthen 50*898184e3Ssthenok(!mro::is_universal('MRO_ɓ')); 51*898184e3Ssthen 52*898184e3Ssthen@UNIVERSAL::ISA = qw/MRO_ᚠ/; 53*898184e3Ssthenok(mro::is_universal('MRO_ɓ')); 54*898184e3Ssthen 55*898184e3Ssthen@UNIVERSAL::ISA = (); 56*898184e3Ssthenok(!mro::is_universal('MRO_ᚠ')); 57*898184e3Ssthenok(!mro::is_universal('MRO_ɓ')); 58*898184e3Ssthen 59*898184e3Ssthen# is_universal, get_mro, and get_linear_isa should 60*898184e3Ssthen# handle non-existent packages sanely 61*898184e3Ssthenok(!mro::is_universal('Does_Not_Exist')); 62*898184e3Ssthenis(mro::get_mro('Also_Does_Not_Exist'), 'dfs'); 63*898184e3Ssthenok(eq_array( 64*898184e3Ssthen mro::get_linear_isa('Does_Not_Exist_Three'), 65*898184e3Ssthen [qw/Does_Not_Exist_Three/] 66*898184e3Ssthen)); 67*898184e3Ssthen 68*898184e3Ssthen# Assigning @ISA via globref 69*898184e3Ssthen{ 70*898184e3Ssthen package MRO_ҭṣṱबꗻ; 71*898184e3Ssthen sub 텟tf운ꜿ { return 123 } 72*898184e3Ssthen package MRO_Test옽ḦРꤷsӭ; 73*898184e3Ssthen sub 텟ₜꖢᶯcƧ { return 321 } 74*898184e3Ssthen package MRO_Ɯ; our @ISA = qw/MRO_ҭṣṱबꗻ/; 75*898184e3Ssthen} 76*898184e3Ssthen*MRO_ᕡ::ISA = *MRO_Ɯ::ISA; 77*898184e3Ssthenis(eval { MRO_ᕡ->텟tf운ꜿ() }, 123); 78*898184e3Ssthen 79*898184e3Ssthen# XXX TODO (when there's a way to backtrack through a glob's aliases) 80*898184e3Ssthen# push(@MRO_M::ISA, 'MRO_TestOtherBase'); 81*898184e3Ssthen# is(eval { MRO_N->testfunctwo() }, 321); 82*898184e3Ssthen 83*898184e3Ssthen# Simple DESTROY Baseline 84*898184e3Ssthen{ 85*898184e3Ssthen my $x = 0; 86*898184e3Ssthen my $obj; 87*898184e3Ssthen 88*898184e3Ssthen { 89*898184e3Ssthen package DESTROY_MRO_Bӓeᓕne; 90*898184e3Ssthen sub new { bless {} => shift } 91*898184e3Ssthen sub DESTROY { $x++ } 92*898184e3Ssthen 93*898184e3Ssthen package DESTROY_MRO_Bӓeᓕne_χḻɖ; 94*898184e3Ssthen our @ISA = qw/DESTROY_MRO_Bӓeᓕne/; 95*898184e3Ssthen } 96*898184e3Ssthen 97*898184e3Ssthen $obj = DESTROY_MRO_Bӓeᓕne->new(); 98*898184e3Ssthen undef $obj; 99*898184e3Ssthen is($x, 1); 100*898184e3Ssthen 101*898184e3Ssthen $obj = DESTROY_MRO_Bӓeᓕne_χḻɖ->new(); 102*898184e3Ssthen undef $obj; 103*898184e3Ssthen is($x, 2); 104*898184e3Ssthen} 105*898184e3Ssthen 106*898184e3Ssthen# Dynamic DESTROY 107*898184e3Ssthen{ 108*898184e3Ssthen my $x = 0; 109*898184e3Ssthen my $obj; 110*898184e3Ssthen 111*898184e3Ssthen { 112*898184e3Ssthen package DESTROY_MRO_Dჷ및; 113*898184e3Ssthen sub new { bless {} => shift } 114*898184e3Ssthen 115*898184e3Ssthen package DESTROY_MRO_Dჷ및_χḻɖ; 116*898184e3Ssthen our @ISA = qw/DESTROY_MRO_Dჷ및/; 117*898184e3Ssthen } 118*898184e3Ssthen 119*898184e3Ssthen $obj = DESTROY_MRO_Dჷ및->new(); 120*898184e3Ssthen undef $obj; 121*898184e3Ssthen is($x, 0); 122*898184e3Ssthen 123*898184e3Ssthen $obj = DESTROY_MRO_Dჷ및_χḻɖ->new(); 124*898184e3Ssthen undef $obj; 125*898184e3Ssthen is($x, 0); 126*898184e3Ssthen 127*898184e3Ssthen no warnings 'once'; 128*898184e3Ssthen *DESTROY_MRO_Dჷ및::DESTROY = sub { $x++ }; 129*898184e3Ssthen 130*898184e3Ssthen $obj = DESTROY_MRO_Dჷ및->new(); 131*898184e3Ssthen undef $obj; 132*898184e3Ssthen is($x, 1); 133*898184e3Ssthen 134*898184e3Ssthen $obj = DESTROY_MRO_Dჷ및_χḻɖ->new(); 135*898184e3Ssthen undef $obj; 136*898184e3Ssthen is($x, 2); 137*898184e3Ssthen} 138*898184e3Ssthen 139*898184e3Ssthen# clearing @ISA in different ways 140*898184e3Ssthen# some are destructive to the package, hence the new 141*898184e3Ssthen# package name each time 142*898184e3Ssthen{ 143*898184e3Ssthen no warnings 'uninitialized'; 144*898184e3Ssthen { 145*898184e3Ssthen package ᛁ앛ଌᛠ; 146*898184e3Ssthen our @ISA = qw/xx ƳƳ ƶƶ/; 147*898184e3Ssthen } 148*898184e3Ssthen # baseline 149*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ'),[qw/ᛁ앛ଌᛠ xx ƳƳ ƶƶ/])); 150*898184e3Ssthen 151*898184e3Ssthen # this looks dumb, but it preserves existing behavior for compatibility 152*898184e3Ssthen # (undefined @ISA elements treated as "main") 153*898184e3Ssthen $ᛁ앛ଌᛠ::ISA[1] = undef; 154*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ'),[qw/ᛁ앛ଌᛠ xx main ƶƶ/])); 155*898184e3Ssthen 156*898184e3Ssthen # undef the array itself 157*898184e3Ssthen undef @ᛁ앛ଌᛠ::ISA; 158*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ'),[qw/ᛁ앛ଌᛠ/])); 159*898184e3Ssthen 160*898184e3Ssthen # Now, clear more than one package's @ISA at once 161*898184e3Ssthen { 162*898184e3Ssthen package ᛁ앛ଌᛠ1; 163*898184e3Ssthen our @ISA = qw/WẆ xx/; 164*898184e3Ssthen 165*898184e3Ssthen package ᛁ앛ଌᛠ2; 166*898184e3Ssthen our @ISA = qw/ƳƳ ƶƶ/; 167*898184e3Ssthen } 168*898184e3Ssthen # baseline 169*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ1'),[qw/ᛁ앛ଌᛠ1 WẆ xx/])); 170*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ2'),[qw/ᛁ앛ଌᛠ2 ƳƳ ƶƶ/])); 171*898184e3Ssthen (@ᛁ앛ଌᛠ1::ISA, @ᛁ앛ଌᛠ2::ISA) = (); 172*898184e3Ssthen 173*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ1'),[qw/ᛁ앛ଌᛠ1/])); 174*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ2'),[qw/ᛁ앛ଌᛠ2/])); 175*898184e3Ssthen 176*898184e3Ssthen # [perl #49564] This is a pretty obscure way of clearing @ISA but 177*898184e3Ssthen # it tests a regression that affects XS code calling av_clear too. 178*898184e3Ssthen { 179*898184e3Ssthen package ᛁ앛ଌᛠ3; 180*898184e3Ssthen our @ISA = qw/WẆ xx/; 181*898184e3Ssthen } 182*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ3'),[qw/ᛁ앛ଌᛠ3 WẆ xx/])); 183*898184e3Ssthen { 184*898184e3Ssthen package ᛁ앛ଌᛠ3; 185*898184e3Ssthen reset 'I'; 186*898184e3Ssthen } 187*898184e3Ssthen ok(eq_array(mro::get_linear_isa('ᛁ앛ଌᛠ3'),[qw/ᛁ앛ଌᛠ3/])); 188*898184e3Ssthen} 189*898184e3Ssthen 190*898184e3Ssthen# Check that recursion bails out "cleanly" in a variety of cases 191*898184e3Ssthen# (as opposed to say, bombing the interpreter or something) 192*898184e3Ssthen{ 193*898184e3Ssthen my @recurse_codes = ( 194*898184e3Ssthen '@MRO_ഋ1::ISA = "MRO_ഋ2"; @MRO_ഋ2::ISA = "MRO_ഋ1";', 195*898184e3Ssthen '@MRO_ഋ3::ISA = "MRO_ഋ4"; push(@MRO_ഋ4::ISA, "MRO_ഋ3");', 196*898184e3Ssthen '@MRO_ഋ5::ISA = "MRO_ഋ6"; @MRO_ഋ6::ISA = qw/xx MRO_ഋ5 ƳƳ/;', 197*898184e3Ssthen '@MRO_ഋ7::ISA = "MRO_ഋ8"; push(@MRO_ഋ8::ISA, qw/xx MRO_ഋ7 ƳƳ/)', 198*898184e3Ssthen ); 199*898184e3Ssthen foreach my $code (@recurse_codes) { 200*898184e3Ssthen eval $code; 201*898184e3Ssthen ok($@ =~ /Recursive inheritance detected/); 202*898184e3Ssthen } 203*898184e3Ssthen} 204*898184e3Ssthen 205*898184e3Ssthen# Check that SUPER caches get invalidated correctly 206*898184e3Ssthen{ 207*898184e3Ssthen { 208*898184e3Ssthen package スṔઍR텟ʇ; 209*898184e3Ssthen sub new { bless {} => shift } 210*898184e3Ssthen sub ຟઓ { $_[1]+1 } 211*898184e3Ssthen 212*898184e3Ssthen package スṔઍR텟ʇ::MᶤƉ; 213*898184e3Ssthen our @ISA = 'スṔઍR텟ʇ'; 214*898184e3Ssthen 215*898184e3Ssthen package スṔઍR텟ʇ::킫; 216*898184e3Ssthen our @ISA = 'スṔઍR텟ʇ::MᶤƉ'; 217*898184e3Ssthen sub ຟઓ { my $s = shift; $s->SUPER::ຟઓ(@_) } 218*898184e3Ssthen 219*898184e3Ssthen package スṔઍR텟ʇ::렙ﷰए; 220*898184e3Ssthen sub ຟઓ { $_[1]+3 } 221*898184e3Ssthen } 222*898184e3Ssthen 223*898184e3Ssthen my $stk_obj = スṔઍR텟ʇ::킫->new(); 224*898184e3Ssthen is($stk_obj->ຟઓ(1), 2); 225*898184e3Ssthen { no warnings 'redefine'; 226*898184e3Ssthen *スṔઍR텟ʇ::ຟઓ = sub { $_[1]+2 }; 227*898184e3Ssthen } 228*898184e3Ssthen is($stk_obj->ຟઓ(2), 4); 229*898184e3Ssthen @スṔઍR텟ʇ::MᶤƉ::ISA = 'スṔઍR텟ʇ::렙ﷰए'; 230*898184e3Ssthen is($stk_obj->ຟઓ(3), 6); 231*898184e3Ssthen} 232*898184e3Ssthen 233*898184e3Ssthen{ 234*898184e3Ssthen { 235*898184e3Ssthen # assigning @ISA via arrayref to globref RT 60220 236*898184e3Ssthen package ᛔ1; 237*898184e3Ssthen sub new { bless {}, shift } 238*898184e3Ssthen 239*898184e3Ssthen package ᛔ2; 240*898184e3Ssthen } 241*898184e3Ssthen *{ᛔ2::ISA} = [ 'ᛔ1' ]; 242*898184e3Ssthen my $foo = ᛔ2->new; 243*898184e3Ssthen ok(!eval { $foo->ɓᛅƘ }, "no ɓᛅƘ method"); 244*898184e3Ssthen no warnings 'once'; # otherwise it'll bark about ᛔ1::ɓᛅƘ used only once 245*898184e3Ssthen *{ᛔ1::ɓᛅƘ} = sub { "[ɓᛅƘ]" }; 246*898184e3Ssthen is(scalar eval { $foo->ɓᛅƘ }, "[ɓᛅƘ]", "can ɓᛅƘ now"); 247*898184e3Ssthen is $@, ''; 248*898184e3Ssthen} 249*898184e3Ssthen 250*898184e3Ssthen{ 251*898184e3Ssthen # assigning @ISA via arrayref then modifying it RT 72866 252*898184e3Ssthen { 253*898184e3Ssthen package ㄑ1; 254*898184e3Ssthen sub Fஓ { } 255*898184e3Ssthen 256*898184e3Ssthen package ㄑ2; 257*898184e3Ssthen sub ƚ { } 258*898184e3Ssthen 259*898184e3Ssthen package ㄑ3; 260*898184e3Ssthen } 261*898184e3Ssthen push @ㄑ3::ISA, "ㄑ1"; 262*898184e3Ssthen can_ok("ㄑ3", "Fஓ"); 263*898184e3Ssthen *ㄑ3::ISA = []; 264*898184e3Ssthen push @ㄑ3::ISA, "ㄑ1"; 265*898184e3Ssthen can_ok("ㄑ3", "Fஓ"); 266*898184e3Ssthen *ㄑ3::ISA = []; 267*898184e3Ssthen push @ㄑ3::ISA, "ㄑ2"; 268*898184e3Ssthen can_ok("ㄑ3", "ƚ"); 269*898184e3Ssthen ok(!ㄑ3->can("Fஓ"), "can't call Fஓ method any longer"); 270*898184e3Ssthen} 271*898184e3Ssthen 272*898184e3Ssthen{ 273*898184e3Ssthen # test mro::method_changed_in 274*898184e3Ssthen my $count = mro::get_pkg_gen("MRO_அ"); 275*898184e3Ssthen mro::method_changed_in("MRO_அ"); 276*898184e3Ssthen my $count_new = mro::get_pkg_gen("MRO_அ"); 277*898184e3Ssthen 278*898184e3Ssthen is($count_new, $count + 1); 279*898184e3Ssthen} 280*898184e3Ssthen 281*898184e3Ssthen{ 282*898184e3Ssthen # test if we can call mro::invalidate_all_method_caches; 283*898184e3Ssthen eval { 284*898184e3Ssthen mro::invalidate_all_method_caches(); 285*898184e3Ssthen }; 286*898184e3Ssthen is($@, ""); 287*898184e3Ssthen} 288*898184e3Ssthen 289*898184e3Ssthen{ 290*898184e3Ssthen # @main::ISA 291*898184e3Ssthen no warnings 'once'; 292*898184e3Ssthen @main::ISA = 'პᛅeȵᛏ'; 293*898184e3Ssthen my $output = ''; 294*898184e3Ssthen *პᛅeȵᛏ::ど = sub { $output .= 'პᛅeȵᛏ' }; 295*898184e3Ssthen *პᛅeȵᛏ2::ど = sub { $output .= 'პᛅeȵᛏ2' }; 296*898184e3Ssthen main->ど; 297*898184e3Ssthen @main::ISA = 'პᛅeȵᛏ2'; 298*898184e3Ssthen main->ど; 299*898184e3Ssthen is $output, 'პᛅeȵᛏპᛅeȵᛏ2', '@main::ISA is magical'; 300*898184e3Ssthen} 301*898184e3Ssthen 302*898184e3Ssthen{ 303*898184e3Ssthen # Undefining *ISA, then modifying @ISA 304*898184e3Ssthen # This broke Class::Trait. See [perl #79024]. 305*898184e3Ssthen {package Class::Trait::Base} 306*898184e3Ssthen no strict 'refs'; 307*898184e3Ssthen undef *{"एxṰர::ʦፖㄡsȨ::ISA"}; 308*898184e3Ssthen 'एxṰர::ʦፖㄡsȨ'->isa('Class::Trait::Base'); # cache the mro 309*898184e3Ssthen unshift @{"एxṰர::ʦፖㄡsȨ::ISA"}, 'Class::Trait::Base'; 310*898184e3Ssthen ok 'एxṰர::ʦፖㄡsȨ'->isa('Class::Trait::Base'), 311*898184e3Ssthen 'a isa b after undef *a::ISA and @a::ISA modification'; 312*898184e3Ssthen} 313*898184e3Ssthen 314*898184e3Ssthen{ 315*898184e3Ssthen # Deleting $package::{ISA} 316*898184e3Ssthen # Broken in 5.10.0; fixed in 5.13.7 317*898184e3Ssthen @BḼᵑth::ISA = 'Bલdḏ'; 318*898184e3Ssthen delete $BḼᵑth::{ISA}; 319*898184e3Ssthen ok !BḼᵑth->isa("Bલdḏ"), 'delete $package::{ISA}'; 320*898184e3Ssthen} 321*898184e3Ssthen 322*898184e3Ssthen{ 323*898184e3Ssthen # Undefining stashes 324*898184e3Ssthen @ᖫᕃㄒṭ::ISA = "ᖮw잍"; 325*898184e3Ssthen @ᖮw잍::ISA = "ሲঌએ"; 326*898184e3Ssthen undef %ᖮw잍::; 327*898184e3Ssthen ok !ᖫᕃㄒṭ->isa('ሲঌએ'), 'undef %package:: updates subclasses'; 328*898184e3Ssthen} 329