This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
re-implement OPpASSIGN_COMMON mechanism
[perl5.git] / t / op / utf8cache.t
CommitLineData
c45bec60 1#!./perl -w
fa421ef9
CS
2# Test for malfunctions of utf8 cache
3
4BEGIN {
5 chdir 't' if -d 't';
6 @INC = '../lib';
c45bec60 7 require './test.pl';
fa421ef9
CS
8}
9
c45bec60 10use strict;
beee7526 11use Config ();
c45bec60 12
17571deb 13plan(tests => 16);
fa421ef9 14
4785469e 15SKIP: {
afa691d5 16skip_without_dynamic_extension("Devel::Peek", 2);
4785469e 17
17571deb
TC
18my $out = runperl(stderr => 1,
19 progs => [ split /\n/, <<'EOS' ]);
20 require Devel::Peek;
21 $a = qq(hello \x{1234});
fa421ef9
CS
22 for (1..2) {
23 bar(substr($a, $_, 1));
24 }
25 sub bar {
17571deb 26 $_[0] = qq(\x{4321});
fa421ef9
CS
27 Devel::Peek::Dump($_[0]);
28 }
17571deb 29EOS
fa421ef9 30
beee7526
RU
31$out =~ s/^ALLOCATED at .*\n//m
32 if $Config::Config{ccflags} =~ /-DDEBUG_LEAKING_SCALARS/;
17571deb 33like($out, qr/\ASV =/, "check we got dump output"); # [perl #121337]
fa421ef9
CS
34
35my $utf8magic = qr{ ^ \s+ MAGIC \s = .* \n
36 \s+ MG_VIRTUAL \s = .* \n
37 \s+ MG_TYPE \s = \s PERL_MAGIC_utf8 .* \n
38 \s+ MG_LEN \s = .* \n }xm;
39
17571deb
TC
40unlike($out, qr{ $utf8magic $utf8magic }x,
41 "no duplicate utf8 magic");
88621eaf 42
4785469e
FC
43} # SKIP
44
88621eaf
DM
45# With bad caching, this code used to go quadratic and take 10s of minutes.
46# The 'test' in this case is simply that it doesn't hang.
47
48{
49 local ${^UTF8CACHE} = 1; # enable cache, disable debugging
50 my $x = "\x{100}" x 1000000;
51 while ($x =~ /./g) {
52 my $p = pos($x);
53 }
54 pass("quadratic pos");
55}
7d1328bb
FC
56
57# Get-magic can reallocate the PV. Check that the cache is reset in
58# such cases.
59
60# Regexp vars
61"\x{100}" =~ /(.+)/;
62() = substr $1, 0, 1;
63"a\x{100}" =~ /(.+)/;
64is ord substr($1, 1, 1), 0x100, 'get-magic resets utf8cache on match vars';
65
66# Substr lvalues
67my $x = "a\x{100}";
68my $l = \substr $x, 0;
69() = substr $$l, 1, 1;
70substr $x, 0, 1, = "\x{100}";
71is ord substr($$l, 1, 1), 0x100, 'get-magic resets utf8cache on LVALUEs';
72
73# defelem magic
74my %h;
75sub {
76 $_[0] = "a\x{100}";
77 () = ord substr $_[0], 1, 1;
78 $h{k} = "\x{100}"x2;
79 is ord substr($_[0], 1, 1), 0x100,
80 'get-magic resets uf8cache on defelems';
81}->($h{k});
aec43834
FC
82
83
84# Overloading can also reallocate the PV.
85
86package UTF8Toggle {
87 use overload '""' => 'stringify', fallback => 1;
88
89 sub new {
90 my $class = shift;
91 my $value = shift;
92 my $state = shift||0;
93 return bless [$value, $state], $class;
94 }
95
96 sub stringify {
97 my $self = shift;
98 $self->[1] = ! $self->[1];
99 if ($self->[1]) {
100 utf8::downgrade($self->[0]);
101 } else {
102 utf8::upgrade($self->[0]);
103 }
104 $self->[0];
105 }
106}
107my $u = UTF8Toggle->new(" \x{c2}7 ");
108
109pos $u = 2;
110is pos $u, 2, 'pos on overloaded utf8 toggler';
111() = "$u"; # flip flag
112pos $u = 2;
4ddea69a
FC
113is pos $u, 2, 'pos on overloaded utf8 toggler (again)';
114
115() = ord ${\substr $u, 1};
116is ord ${\substr($u, 1)}, 0xc2,
117 'utf8 cache + overloading does not confuse substr lvalues';
118() = "$u"; # flip flag
119() = ord substr $u, 1;
120is ord substr($u, 1), 0xc2,
121 'utf8 cache + overloading does not confuse substr lvalues (again)';
d91e94e1 122
fc061ed8
FC
123$u = UTF8Toggle->new(" \x{c2}7 ");
124() = ord ${\substr $u, 2};
125{ no warnings; ${\substr($u, 2, 1)} = 0; }
126is $u, " \x{c2}0 ",
127 'utf8 cache + overloading does not confuse substr lvalue assignment';
128$u = UTF8Toggle->new(" \x{c2}7 ");
129() = "$u"; # flip flag
130() = ord ${\substr $u, 2};
131{ no warnings; ${\substr($u, 2, 1)} = 0; }
132is $u, " \x{c2}0 ",
133 'utf8 cache + overload does not confuse substr lv assignment (again)';
134
d91e94e1
FC
135
136# Typeglobs and references should not get a cache
137use utf8;
138
139#substr
140my $globref = \*αabcdefg_::_;
141() = substr($$globref, 2, 3);
142*_abcdefgα:: = \%αabcdefg_::;
143undef %αabcdefg_::;
144{ no strict; () = *{"_abcdefgα::_"} }
145is substr($$globref, 2, 3), "abc", 'no utf8 pos cache on globs';
146
147my $ref = bless [], "αabcd_";
148() = substr($ref, 1, 3);
149bless $ref, "_abcdα";
150is substr($ref, 1, 3), "abc", 'no utf8 pos cache on references';
151
152#length
153$globref = \*αabcdefg_::_;
154() = "$$globref"; # turn utf8 flag on
155() = length($$globref);
156*_abcdefgα:: = \%αabcdefg_::;
157undef %αabcdefg_::;
158{ no strict; () = *{"_abcdefgα::_"} }
159is length($$globref), length("$$globref"), 'no utf8 length cache on globs';
160
161$ref = bless [], "αabcd_";
162() = "$ref"; # turn utf8 flag on
163() = length $ref;
164bless $ref, "α";
165is length $ref, length "$ref", 'no utf8 length cache on references';