This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
6caeb6e06386708944d591c01164ce4c4eaa6344
[perl5.git] / dist / Devel-PPPort / t / utf8.t
1 ################################################################################
2 #
3 #            !!!!!   Do NOT edit this file directly!   !!!!!
4 #
5 #            Edit mktests.PL and/or parts/inc/utf8 instead.
6 #
7 #  This file was automatically generated from the definition files in the
8 #  parts/inc/ subdirectory by mktests.PL. To learn more about how all this
9 #  works, please read the F<HACKERS> file that came with this distribution.
10 #
11 ################################################################################
12
13 BEGIN {
14   if ($ENV{'PERL_CORE'}) {
15     chdir 't' if -d 't';
16     @INC = ('../lib', '../ext/Devel-PPPort/t') if -d '../lib' && -d '../ext';
17     require Config; import Config;
18     use vars '%Config';
19     if (" $Config{'extensions'} " !~ m[ Devel/PPPort ]) {
20       print "1..0 # Skip -- Perl configured without Devel::PPPort module\n";
21       exit 0;
22     }
23   }
24   else {
25     unshift @INC, 't';
26   }
27
28   sub load {
29     eval "use Test";
30     require 'testutil.pl' if $@;
31   }
32
33   if (81) {
34     load();
35     plan(tests => 81);
36   }
37 }
38
39 use Devel::PPPort;
40 use strict;
41 BEGIN { $^W = 1; }
42
43 package Devel::PPPort;
44 use vars '@ISA';
45 require DynaLoader;
46 @ISA = qw(DynaLoader);
47 bootstrap Devel::PPPort;
48
49 package main;
50
51 BEGIN { require warnings if "$]" > '5.006' }
52
53 # skip tests on 5.6.0 and earlier, plus 7.0
54 if ("$]" <= '5.006' || "$]" == '5.007' ) {
55     for (1..81) {
56         skip 'skip: broken utf8 support', 0;
57     }
58     exit;
59 }
60
61 ok(&Devel::PPPort::UTF8_SAFE_SKIP("A", 0), 1);
62 ok(&Devel::PPPort::UTF8_SAFE_SKIP("A", -1), 0);
63
64 ok(&Devel::PPPort::isUTF8_CHAR("A", -1), 0);
65 ok(&Devel::PPPort::isUTF8_CHAR("A",  0), 1);
66 ok(&Devel::PPPort::isUTF8_CHAR("\x{100}",  -1), 0);
67 ok(&Devel::PPPort::isUTF8_CHAR("\x{100}",  0), 2);
68
69 if ("$]" < '5.008') {
70     for (1 ..3) {
71         ok(1, 1)
72     }
73 }
74 else {
75     ok(&Devel::PPPort::foldEQ_utf8("A\x{100}", 3, 1, "a\x{101}", 3, 1), 1);
76     ok(&Devel::PPPort::foldEQ_utf8("A\x{100}", 3, 1, "a\x{102}", 3, 1), 0);
77     ok(&Devel::PPPort::foldEQ_utf8("A\x{100}", 3, 1, "b\x{101}", 3, 1), 0);
78 }
79
80 my $ret = &Devel::PPPort::utf8_to_uvchr("A");
81 ok($ret->[0], ord("A"));
82 ok($ret->[1], 1);
83
84 $ret = &Devel::PPPort::utf8_to_uvchr("\0");
85 ok($ret->[0], 0);
86 ok($ret->[1], 1);
87
88 $ret = &Devel::PPPort::utf8_to_uvchr_buf("A", 0);
89 ok($ret->[0], ord("A"));
90 ok($ret->[1], 1);
91
92 $ret = &Devel::PPPort::utf8_to_uvchr_buf("\0", 0);
93 ok($ret->[0], 0);
94 ok($ret->[1], 1);
95
96 if (ord("A") != 65) {   # tests not valid for EBCDIC
97     for (1 .. (2 + 4 + (7 * 5))) {
98         ok(1, 1);
99     }
100 }
101 else {
102     $ret = &Devel::PPPort::utf8_to_uvchr_buf("\xc4\x80", 0);
103     ok($ret->[0], 0x100);
104     ok($ret->[1], 2);
105
106     my @warnings;
107     local $SIG{__WARN__} = sub { push @warnings, @_; };
108
109     {
110         BEGIN { 'warnings'->import('utf8') if "$]" > '5.006' }
111         $ret = &Devel::PPPort::utf8_to_uvchr("\xe0\0\x80");
112         ok($ret->[0], 0);
113         ok($ret->[1], -1);
114
115         BEGIN { 'warnings'->unimport() if "$]" > '5.006' }
116         $ret = &Devel::PPPort::utf8_to_uvchr("\xe0\0\x80");
117         ok($ret->[0], 0xFFFD);
118         ok($ret->[1], 1);
119     }
120
121     my @buf_tests = (
122         {
123             input      => "A",
124             adjustment => -1,
125             warning    => eval "qr/empty/",
126             no_warnings_returned_length => 0,
127         },
128         {
129             input      => "\xc4\xc5",
130             adjustment => 0,
131             warning    => eval "qr/non-continuation/",
132             no_warnings_returned_length => 1,
133         },
134         {
135             input      => "\xc4\x80",
136             adjustment => -1,
137             warning    => eval "qr/short|1 byte, need 2/",
138             no_warnings_returned_length => 1,
139         },
140         {
141             input      => "\xc0\x81",
142             adjustment => 0,
143             warning    => eval "qr/overlong|2 bytes, need 1/",
144             no_warnings_returned_length => 2,
145         },
146         {
147             input      => "\xe0\x80\x81",
148             adjustment => 0,
149             warning    => eval "qr/overlong|3 bytes, need 1/",
150             no_warnings_returned_length => 3,
151         },
152         {
153             input      => "\xf0\x80\x80\x81",
154             adjustment => 0,
155             warning    => eval "qr/overlong|4 bytes, need 1/",
156             no_warnings_returned_length => 4,
157         },
158         {                 # Old algorithm failed to detect this
159             input      => "\xff\x80\x90\x90\x90\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf",
160             adjustment => 0,
161             warning    => eval "qr/overflow/",
162             no_warnings_returned_length => 13,
163         },
164     );
165
166     # An empty input is an assertion failure on debugging builds.  It is
167     # deliberately the first test.
168     require Config; import Config;
169     use vars '%Config';
170     if ($Config{ccflags} =~ /-DDEBUGGING/) {
171         shift @buf_tests;
172         for (1..5) {
173             ok(1, 1);
174         }
175     }
176
177     my $test;
178     for $test (@buf_tests) {
179         my $input = $test->{'input'};
180         my $adjustment = $test->{'adjustment'};
181         my $display = 'utf8_to_uvchr_buf("';
182         my $i;
183         for ($i = 0; $i < length($input) + $adjustment; $i++) {
184             $display .= sprintf "\\x%02x", ord substr($input, $i, 1);
185         }
186
187         $display .= '")';
188         my $warning = $test->{'warning'};
189
190         undef @warnings;
191         BEGIN { 'warnings'->import('utf8') if "$]" > '5.006' }
192         $ret = &Devel::PPPort::utf8_to_uvchr_buf($input, $adjustment);
193         ok($ret->[0], 0,  "returned value $display; warnings enabled");
194         ok($ret->[1], -1, "returned length $display; warnings enabled");
195         my $all_warnings = join "; ", @warnings;
196         my $contains = grep { $_ =~ $warning } $all_warnings;
197         ok($contains, 1, $display
198                     . "; Got: '$all_warnings', which should contain '$warning'");
199
200         undef @warnings;
201         BEGIN { 'warnings'->unimport('utf8') if "$]" > '5.006' }
202         $ret = &Devel::PPPort::utf8_to_uvchr_buf($input, $adjustment);
203         ok($ret->[0], 0xFFFD,  "returned value $display; warnings disabled");
204         ok($ret->[1], $test->{'no_warnings_returned_length'},
205                       "returned length $display; warnings disabled");
206     }
207 }
208
209 if ("$]" ge '5.008') {
210     BEGIN { if ("$]" ge '5.008') { require utf8; "utf8"->import() } }
211
212     ok(Devel::PPPort::sv_len_utf8("aščť"), 4);
213     ok(Devel::PPPort::sv_len_utf8_nomg("aščť"), 4);
214
215     my $str = "áíé";
216     utf8::downgrade($str);
217     ok(Devel::PPPort::sv_len_utf8($str), 3);
218     utf8::downgrade($str);
219     ok(Devel::PPPort::sv_len_utf8_nomg($str), 3);
220     utf8::upgrade($str);
221     ok(Devel::PPPort::sv_len_utf8($str), 3);
222     utf8::upgrade($str);
223     ok(Devel::PPPort::sv_len_utf8_nomg($str), 3);
224
225     tie my $scalar, 'TieScalarCounter', "é";
226
227     ok(tied($scalar)->{fetch}, 0);
228     ok(tied($scalar)->{store}, 0);
229     ok(Devel::PPPort::sv_len_utf8($scalar), 2);
230     ok(tied($scalar)->{fetch}, 1);
231     ok(tied($scalar)->{store}, 0);
232     ok(Devel::PPPort::sv_len_utf8($scalar), 3);
233     ok(tied($scalar)->{fetch}, 2);
234     ok(tied($scalar)->{store}, 0);
235     ok(Devel::PPPort::sv_len_utf8($scalar), 4);
236     ok(tied($scalar)->{fetch}, 3);
237     ok(tied($scalar)->{store}, 0);
238     ok(Devel::PPPort::sv_len_utf8_nomg($scalar), 4);
239     ok(tied($scalar)->{fetch}, 3);
240     ok(tied($scalar)->{store}, 0);
241     ok(Devel::PPPort::sv_len_utf8_nomg($scalar), 4);
242     ok(tied($scalar)->{fetch}, 3);
243     ok(tied($scalar)->{store}, 0);
244 } else {
245     for (1..23) {
246         skip 'skip: no SV_NOSTEAL support', 0;
247     }
248 }
249
250 package TieScalarCounter;
251
252 sub TIESCALAR {
253     my ($class, $value) = @_;
254     return bless { fetch => 0, store => 0, value => $value }, $class;
255 }
256
257 sub FETCH {
258     BEGIN { if ("$]" ge '5.008') { require utf8; "utf8"->import() } }
259     my ($self) = @_;
260     $self->{fetch}++;
261     return $self->{value} .= "é";
262 }
263
264 sub STORE {
265     my ($self, $value) = @_;
266     $self->{store}++;
267     $self->{value} = $value;
268 }
269