This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
0fd8de6455de1bacea85131592a97e24097ae25c
[perl5.git] / t / uni / overload.t
1 #!perl -w
2
3 BEGIN {
4     chdir 't';
5     @INC = '../lib';
6     require Config; import Config;
7     require './test.pl';
8 }
9
10 plan(tests => 215);
11
12 package UTF8Toggle;
13 use strict;
14
15 use overload '""' => 'stringify', fallback => 1;
16
17 sub new {
18     my $class = shift;
19     my $value = shift;
20     my $state = shift||0;
21     return bless [$value, $state], $class;
22 }
23
24 sub stringify {
25     my $self = shift;
26     $self->[1] = ! $self->[1];
27     if ($self->[1]) {
28         utf8::downgrade($self->[0]);
29     } else {
30         utf8::upgrade($self->[0]);
31     }
32     $self->[0];
33 }
34
35 package main;
36
37 # These tests are based on characters 128-255 not having latin1, and hence
38 # Unicode, semantics
39 # no feature "unicode_strings";
40
41 # Bug 34297
42 foreach my $t ("ASCII", "B\366se") {
43     my $length = length $t;
44
45     my $u = UTF8Toggle->new($t);
46     is (length $u, $length, "length of '$t'");
47     is (length $u, $length, "length of '$t'");
48     is (length $u, $length, "length of '$t'");
49     is (length $u, $length, "length of '$t'");
50 }
51
52 my $u = UTF8Toggle->new("\311");
53 my $lc = lc $u;
54 is (length $lc, 1);
55 is ($lc, "\311", "E acute -> e acute");
56 $lc = lc $u;
57 is (length $lc, 1);
58 is ($lc, "\351", "E acute -> e acute");
59 $lc = lc $u;
60 is (length $lc, 1);
61 is ($lc, "\311", "E acute -> e acute");
62
63 $u = UTF8Toggle->new("\351");
64 my $uc = uc $u;
65 is (length $uc, 1);
66 is ($uc, "\351", "e acute -> E acute");
67 $uc = uc $u;
68 is (length $uc, 1);
69 is ($uc, "\311", "e acute -> E acute");
70 $uc = uc $u;
71 is (length $uc, 1);
72 is ($uc, "\351", "e acute -> E acute");
73
74 $u = UTF8Toggle->new("\311");
75 $lc = lcfirst $u;
76 is (length $lc, 1);
77 is ($lc, "\311", "E acute -> e acute");
78 $lc = lcfirst $u;
79 is (length $lc, 1);
80 is ($lc, "\351", "E acute -> e acute");
81 $lc = lcfirst $u;
82 is (length $lc, 1);
83 is ($lc, "\311", "E acute -> e acute");
84
85 $u = UTF8Toggle->new("\351");
86 $uc = ucfirst $u;
87 is (length $uc, 1);
88 is ($uc, "\351", "e acute -> E acute");
89 $uc = ucfirst $u;
90 is (length $uc, 1);
91 is ($uc, "\311", "e acute -> E acute");
92 $uc = ucfirst $u;
93 is (length $uc, 1);
94 is ($uc, "\351", "e acute -> E acute");
95
96 my $have_setlocale = 0;
97 eval {
98     require POSIX;
99     if($Config{d_setlocale}) {
100         import POSIX ':locale_h';
101         $have_setlocale++;
102     }
103 };
104
105 SKIP: {
106     if (!$have_setlocale) {
107         skip "No setlocale", 24;
108     } elsif (!setlocale(&POSIX::LC_ALL, "en_GB.ISO8859-1")) {
109         skip "Could not setlocale to en_GB.ISO8859-1", 24;
110     } elsif ($^O eq 'dec_osf' || $^O eq 'VMS') {
111         skip "$^O has broken en_GB.ISO8859-1 locale", 24;
112     } else {
113         use locale;
114         my $u = UTF8Toggle->new("\311");
115         my $lc = lc $u;
116         is (length $lc, 1);
117         is ($lc, "\351", "E acute -> e acute");
118         $lc = lc $u;
119         is (length $lc, 1);
120         is ($lc, "\351", "E acute -> e acute");
121         $lc = lc $u;
122         is (length $lc, 1);
123         is ($lc, "\351", "E acute -> e acute");
124
125         $u = UTF8Toggle->new("\351");
126         my $uc = uc $u;
127         is (length $uc, 1);
128         is ($uc, "\311", "e acute -> E acute");
129         $uc = uc $u;
130         is (length $uc, 1);
131         is ($uc, "\311", "e acute -> E acute");
132         $uc = uc $u;
133         is (length $uc, 1);
134         is ($uc, "\311", "e acute -> E acute");
135
136         $u = UTF8Toggle->new("\311");
137         $lc = lcfirst $u;
138         is (length $lc, 1);
139         is ($lc, "\351", "E acute -> e acute");
140         $lc = lcfirst $u;
141         is (length $lc, 1);
142         is ($lc, "\351", "E acute -> e acute");
143         $lc = lcfirst $u;
144         is (length $lc, 1);
145         is ($lc, "\351", "E acute -> e acute");
146
147         $u = UTF8Toggle->new("\351");
148         $uc = ucfirst $u;
149         is (length $uc, 1);
150         is ($uc, "\311", "e acute -> E acute");
151         $uc = ucfirst $u;
152         is (length $uc, 1);
153         is ($uc, "\311", "e acute -> E acute");
154         $uc = ucfirst $u;
155         is (length $uc, 1);
156         is ($uc, "\311", "e acute -> E acute");
157     }
158 }
159
160 my $tmpfile = tempfile();
161
162 foreach my $operator ('print', 'syswrite', 'syswrite len', 'syswrite off',
163                       'syswrite len off') {
164     foreach my $layer ('', ':utf8') {
165         open my $fh, "+>$layer", $tmpfile or die $!;
166         my $pad = $operator =~ /\boff\b/ ? "\243" : "";
167         my $trail = $operator =~ /\blen\b/ ? "!" : "";
168         my $u = UTF8Toggle->new("$pad\311\n$trail");
169         my $l = UTF8Toggle->new("$pad\351\n$trail", 1);
170         if ($operator eq 'print') {
171             no warnings 'utf8';
172             print $fh $u;
173             print $fh $u;
174             print $fh $u;
175             print $fh $l;
176             print $fh $l;
177             print $fh $l;
178         } elsif ($operator eq 'syswrite') {
179             syswrite $fh, $u;
180             syswrite $fh, $u;
181             syswrite $fh, $u;
182             syswrite $fh, $l;
183             syswrite $fh, $l;
184             syswrite $fh, $l;
185         } elsif ($operator eq 'syswrite len') {
186             syswrite $fh, $u, 2;
187             syswrite $fh, $u, 2;
188             syswrite $fh, $u, 2;
189             syswrite $fh, $l, 2;
190             syswrite $fh, $l, 2;
191             syswrite $fh, $l, 2;
192         } elsif ($operator eq 'syswrite off'
193                  || $operator eq 'syswrite len off') {
194             syswrite $fh, $u, 2, 1;
195             syswrite $fh, $u, 2, 1;
196             syswrite $fh, $u, 2, 1;
197             syswrite $fh, $l, 2, 1;
198             syswrite $fh, $l, 2, 1;
199             syswrite $fh, $l, 2, 1;
200         } else {
201             die $operator;
202         }
203
204         seek $fh, 0, 0 or die $!;
205         my $line;
206         chomp ($line = <$fh>);
207         is ($line, "\311", "$operator $layer");
208         chomp ($line = <$fh>);
209         is ($line, "\311", "$operator $layer");
210         chomp ($line = <$fh>);
211         is ($line, "\311", "$operator $layer");
212         chomp ($line = <$fh>);
213         is ($line, "\351", "$operator $layer");
214         chomp ($line = <$fh>);
215         is ($line, "\351", "$operator $layer");
216         chomp ($line = <$fh>);
217         is ($line, "\351", "$operator $layer");
218
219         close $fh or die $!;
220     }
221 }
222
223 my $little = "\243\243";
224 my $big = " \243 $little ! $little ! $little \243 ";
225 my $right = rindex $big, $little;
226 my $right1 = rindex $big, $little, 11;
227 my $left = index $big, $little;
228 my $left1 = index $big, $little, 4;
229
230 cmp_ok ($right, ">", $right1, "Sanity check our rindex tests");
231 cmp_ok ($left, "<", $left1, "Sanity check our index tests");
232
233 foreach my $b ($big, UTF8Toggle->new($big)) {
234     foreach my $l ($little, UTF8Toggle->new($little),
235                    UTF8Toggle->new($little, 1)) {
236         is (rindex ($b, $l), $right, "rindex");
237         is (rindex ($b, $l), $right, "rindex");
238         is (rindex ($b, $l), $right, "rindex");
239
240         is (rindex ($b, $l, 11), $right1, "rindex 11");
241         is (rindex ($b, $l, 11), $right1, "rindex 11");
242         is (rindex ($b, $l, 11), $right1, "rindex 11");
243
244         is (index ($b, $l), $left, "index");
245         is (index ($b, $l), $left, "index");
246         is (index ($b, $l), $left, "index");
247
248         is (index ($b, $l, 4), $left1, "index 4");
249         is (index ($b, $l, 4), $left1, "index 4");
250         is (index ($b, $l, 4), $left1, "index 4");
251     }
252 }
253
254 my $bits = "\311";
255 foreach my $pieces ($bits, UTF8Toggle->new($bits)) {
256     like ($bits ^ $pieces, qr/\A\0+\z/, "something xor itself is zeros");
257     like ($bits ^ $pieces, qr/\A\0+\z/, "something xor itself is zeros");
258     like ($bits ^ $pieces, qr/\A\0+\z/, "something xor itself is zeros");
259
260     like ($pieces ^ $bits, qr/\A\0+\z/, "something xor itself is zeros");
261     like ($pieces ^ $bits, qr/\A\0+\z/, "something xor itself is zeros");
262     like ($pieces ^ $bits, qr/\A\0+\z/, "something xor itself is zeros");
263 }
264
265 foreach my $value ("\243", UTF8Toggle->new("\243")) {
266     is (pack ("A/A", $value), pack ("A/A", "\243"),
267         "pack copes with overloading");
268     is (pack ("A/A", $value), pack ("A/A", "\243"));
269     is (pack ("A/A", $value), pack ("A/A", "\243"));
270 }
271
272 foreach my $value ("\243", UTF8Toggle->new("\243")) {
273     my $v;
274     $v = substr $value, 0, 1;
275     is ($v, "\243");
276     $v = substr $value, 0, 1;
277     is ($v, "\243");
278     $v = substr $value, 0, 1;
279     is ($v, "\243");
280 }
281
282 {
283     package RT69422;
284     use overload '""' => sub { $_[0]->{data} }
285 }
286
287 {
288     my $text = bless { data => "\x{3075}" }, 'RT69422';
289     my $p = substr $text, 0, 1;
290     is ($p, "\x{3075}");
291 }