xref: /openbsd-src/gnu/usr.bin/perl/t/mro/basic_utf8.t (revision 898184e3e61f9129feb5978fad5a8c6865f00b92)
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_MRO_ɛ/;
25*898184e3Ssthen}
26*898184e3Ssthen
27*898184e3Ssthenmy @MFO__DFS = qw/MRO_MRO_MRO_MRO_ɓ MRO_MRO_ɛ/;
28*898184e3Ssthenmy @MFO__C3 = qw/MRO_MRO_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    subtf운ꜿ { 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ӓene;
90*898184e3Ssthen        sub new { bless {} => shift }
91*898184e3Ssthen        sub DESTROY { $x++ }
92*898184e3Ssthen
93*898184e3Ssthen        package DESTROY_MRO_Bӓene_χḻɖ;
94*898184e3Ssthen        our @ISA = qw/DESTROY_MRO_Bӓene/;
95*898184e3Ssthen    }
96*898184e3Ssthen
97*898184e3Ssthen    $obj = DESTROY_MRO_Bӓene->new();
98*898184e3Ssthen    undef $obj;
99*898184e3Ssthen    is($x, 1);
100*898184e3Ssthen
101*898184e3Ssthen    $obj = DESTROY_MRO_Bӓene_χḻɖ->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    package1;
237*898184e3Ssthen    sub new { bless {}, shift }
238*898184e3Ssthen
239*898184e3Ssthen    package2;
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    package1;
254*898184e3Ssthen    sub Fஓ {  }
255*898184e3Ssthen
256*898184e3Ssthen    package2;
257*898184e3Ssthen    sub ƚ { }
258*898184e3Ssthen
259*898184e3Ssthen    package3;
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