This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Convert utf8decode.t to test.pl
[perl5.git] / t / op / utf8decode.t
1 #!./perl
2
3 BEGIN {
4     chdir 't' if -d 't';
5     @INC = '../lib';
6     require './test.pl';
7 }
8
9 {
10     my $wide = v256;
11     use bytes;
12     my $ordwide = ord($wide);
13     printf "# under use bytes ord(v256) = 0x%02x\n", $ordwide;
14     skip_all('UTF-EBCDIC (not UTF-8) used here') if $ordwide == 140;
15
16     if ($ordwide != 196) {
17         printf "# v256 starts with 0x%02x\n", $ordwide;
18     }
19 }
20
21 no utf8;
22
23 # This table is based on Markus Kuhn's UTF-8 Decode Stress Tester,
24 # http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt,
25 # version dated 2000-09-02.
26
27 # We use the \x notation instead of raw binary bytes for \x00-\x1f\x7f-\xff
28 # because e.g. many patch programs have issues with binary data.
29
30 my @MK = split(/\n/, <<__EOMK__);
31 1       Correct UTF-8
32 1.1.1 y "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5"  -               11      ce:ba:e1:bd:b9:cf:83:ce:bc:ce:b5        5
33 2       Boundary conditions
34 2.1     First possible sequence of certain length
35 2.1.1 y "\x00"                  0               1       00      1
36 2.1.2 y "\xc2\x80"                      80              2       c2:80   1
37 2.1.3 y "\xe0\xa0\x80"          800             3       e0:a0:80        1
38 2.1.4 y "\xf0\x90\x80\x80"              10000           4       f0:90:80:80     1
39 2.1.5 y "\xf8\x88\x80\x80\x80"  200000          5       f8:88:80:80:80  1
40 2.1.6 y "\xfc\x84\x80\x80\x80\x80"      4000000         6       fc:84:80:80:80:80       1
41 2.2     Last possible sequence of certain length
42 2.2.1 y "\x7f"                  7f              1       7f      1
43 2.2.2 y "\xdf\xbf"                      7ff             2       df:bf   1
44 # The ffff is legal by default since 872c91ae155f6880
45 2.2.3 y "\xef\xbf\xbf"                  ffff            3       ef:bf:bf        1       character 0xffff
46 2.2.4 y "\xf7\xbf\xbf\xbf"                      1fffff          4       f7:bf:bf:bf     1
47 2.2.5 y "\xfb\xbf\xbf\xbf\xbf"                  3ffffff         5       fb:bf:bf:bf:bf  1
48 2.2.6 y "\xfd\xbf\xbf\xbf\xbf\xbf"              7fffffff        6       fd:bf:bf:bf:bf:bf       1
49 2.3     Other boundary conditions
50 2.3.1 y "\xed\x9f\xbf"          d7ff            3       ed:9f:bf        1
51 2.3.2 y "\xee\x80\x80"          e000            3       ee:80:80        1
52 2.3.3 y "\xef\xbf\xbd"                  fffd            3       ef:bf:bd        1
53 2.3.4 y "\xf4\x8f\xbf\xbf"              10ffff          4       f4:8f:bf:bf     1
54 2.3.5 y "\xf4\x90\x80\x80"              110000          4       f4:90:80:80     1
55 3       Malformed sequences
56 3.1     Unexpected continuation bytes
57 3.1.1 n "\x80"                  -               1       80      -       unexpected continuation byte 0x80
58 3.1.2 n "\xbf"                  -               1       bf      -       unexpected continuation byte 0xbf
59 3.1.3 n "\x80\xbf"                      -               2       80:bf   -       unexpected continuation byte 0x80
60 3.1.4 n "\x80\xbf\x80"          -               3       80:bf:80        -       unexpected continuation byte 0x80
61 3.1.5 n "\x80\xbf\x80\xbf"              -               4       80:bf:80:bf     -       unexpected continuation byte 0x80
62 3.1.6 n "\x80\xbf\x80\xbf\x80"  -               5       80:bf:80:bf:80  -       unexpected continuation byte 0x80
63 3.1.7 n "\x80\xbf\x80\xbf\x80\xbf"      -               6       80:bf:80:bf:80:bf       -       unexpected continuation byte 0x80
64 3.1.8 n "\x80\xbf\x80\xbf\x80\xbf\x80"  -               7       80:bf:80:bf:80:bf:80    -       unexpected continuation byte 0x80
65 3.1.9 n "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"                              -       64      80:81:82:83:84:85:86:87:88:89:8a:8b:8c:8d:8e:8f:90:91:92:93:94:95:96:97:98:99:9a:9b:9c:9d:9e:9f:a0:a1:a2:a3:a4:a5:a6:a7:a8:a9:aa:ab:ac:ad:ae:af:b0:b1:b2:b3:b4:b5:b6:b7:b8:b9:ba:bb:bc:bd:be:bf -       unexpected continuation byte 0x80
66 3.2     Lonely start characters
67 3.2.1 n "\xc0 \xc1 \xc2 \xc3 \xc4 \xc5 \xc6 \xc7 \xc8 \xc9 \xca \xcb \xcc \xcd \xce \xcf \xd0 \xd1 \xd2 \xd3 \xd4 \xd5 \xd6 \xd7 \xd8 \xd9 \xda \xdb \xdc \xdd \xde \xdf "      -       64      c0:20:c1:20:c2:20:c3:20:c4:20:c5:20:c6:20:c7:20:c8:20:c9:20:ca:20:cb:20:cc:20:cd:20:ce:20:cf:20:d0:20:d1:20:d2:20:d3:20:d4:20:d5:20:d6:20:d7:20:d8:20:d9:20:da:20:db:20:dc:20:dd:20:de:20:df:20 -       unexpected non-continuation byte 0x20, immediately after start byte 0xc0
68 3.2.2 n "\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef "      -       32      e0:20:e1:20:e2:20:e3:20:e4:20:e5:20:e6:20:e7:20:e8:20:e9:20:ea:20:eb:20:ec:20:ed:20:ee:20:ef:20 -       unexpected non-continuation byte 0x20, immediately after start byte 0xe0
69 3.2.3 n "\xf0 \xf1 \xf2 \xf3 \xf4 \xf5 \xf6 \xf7 "      -       16      f0:20:f1:20:f2:20:f3:20:f4:20:f5:20:f6:20:f7:20 -       unexpected non-continuation byte 0x20, immediately after start byte 0xf0
70 3.2.4 n "\xf8 \xf9 \xfa \xfb "          -       8       f8:20:f9:20:fa:20:fb:20 -       unexpected non-continuation byte 0x20, immediately after start byte 0xf8
71 3.2.5 n "\xfc \xfd "                    -       4       fc:20:fd:20     -       unexpected non-continuation byte 0x20, immediately after start byte 0xfc
72 3.3     Sequences with last continuation byte missing
73 3.3.1 n "\xc0"                  -       1       c0      -       1 byte, need 2
74 3.3.2 n "\xe0\x80"                      -       2       e0:80   -       2 bytes, need 3
75 3.3.3 n "\xf0\x80\x80"          -       3       f0:80:80        -       3 bytes, need 4
76 3.3.4 n "\xf8\x80\x80\x80"              -       4       f8:80:80:80     -       4 bytes, need 5
77 3.3.5 n "\xfc\x80\x80\x80\x80"  -       5       fc:80:80:80:80  -       5 bytes, need 6
78 3.3.6 n "\xdf"                  -       1       df      -       1 byte, need 2
79 3.3.7 n "\xef\xbf"                      -       2       ef:bf   -       2 bytes, need 3
80 3.3.8 n "\xf7\xbf\xbf"                  -       3       f7:bf:bf        -       3 bytes, need 4
81 3.3.9 n "\xfb\xbf\xbf\xbf"                      -       4       fb:bf:bf:bf     -       4 bytes, need 5
82 3.3.10 n "\xfd\xbf\xbf\xbf\xbf"         -       5       fd:bf:bf:bf:bf  -       5 bytes, need 6
83 3.4     Concatenation of incomplete sequences
84 3.4.1 n "\xc0\xe0\x80\xf0\x80\x80\xf8\x80\x80\x80\xfc\x80\x80\x80\x80\xdf\xef\xbf\xf7\xbf\xbf\xfb\xbf\xbf\xbf\xfd\xbf\xbf\xbf\xbf"      -       30      c0:e0:80:f0:80:80:f8:80:80:80:fc:80:80:80:80:df:ef:bf:f7:bf:bf:fb:bf:bf:bf:fd:bf:bf:bf:bf       -       unexpected non-continuation byte 0xe0, immediately after start byte 0xc0
85 3.5     Impossible bytes
86 3.5.1 n "\xfe"                  -       1       fe      -       byte 0xfe
87 3.5.2 n "\xff"                  -       1       ff      -       byte 0xff
88 3.5.3 n "\xfe\xfe\xff\xff"                      -       4       fe:fe:ff:ff     -       byte 0xfe
89 4       Overlong sequences
90 4.1     Examples of an overlong ASCII character
91 4.1.1 n "\xc0\xaf"                      -       2       c0:af   -       2 bytes, need 1
92 4.1.2 n "\xe0\x80\xaf"          -       3       e0:80:af        -       3 bytes, need 1
93 4.1.3 n "\xf0\x80\x80\xaf"              -       4       f0:80:80:af     -       4 bytes, need 1
94 4.1.4 n "\xf8\x80\x80\x80\xaf"  -       5       f8:80:80:80:af  -       5 bytes, need 1
95 4.1.5 n "\xfc\x80\x80\x80\x80\xaf"      -       6       fc:80:80:80:80:af       -       6 bytes, need 1
96 4.2     Maximum overlong sequences
97 4.2.1 n "\xc1\xbf"                      -       2       c1:bf   -       2 bytes, need 1
98 4.2.2 n "\xe0\x9f\xbf"          -       3       e0:9f:bf        -       3 bytes, need 2
99 4.2.3 n "\xf0\x8f\xbf\xbf"              -       4       f0:8f:bf:bf     -       4 bytes, need 3
100 4.2.4 n "\xf8\x87\xbf\xbf\xbf"          -       5       f8:87:bf:bf:bf  -       5 bytes, need 4
101 4.2.5 n "\xfc\x83\xbf\xbf\xbf\xbf"              -       6       fc:83:bf:bf:bf:bf       -       6 bytes, need 5
102 4.3     Overlong representation of the NUL character
103 4.3.1 n "\xc0\x80"                      -       2       c0:80   -       2 bytes, need 1
104 4.3.2 n "\xe0\x80\x80"          -       3       e0:80:80        -       3 bytes, need 1
105 4.3.3 n "\xf0\x80\x80\x80"              -       4       f0:80:80:80     -       4 bytes, need 1
106 4.3.4 n "\xf8\x80\x80\x80\x80"  -       5       f8:80:80:80:80  -       5 bytes, need 1
107 4.3.5 n "\xfc\x80\x80\x80\x80\x80"      -       6       fc:80:80:80:80:80       -       6 bytes, need 1
108 5       Illegal code positions
109 5.1     Single UTF-16 surrogates
110 5.1.1 y "\xed\xa0\x80"          -       3       ed:a0:80        -       UTF-16 surrogate 0xd800
111 5.1.2 y "\xed\xad\xbf"                  -       3       ed:ad:bf        -       UTF-16 surrogate 0xdb7f
112 5.1.3 y "\xed\xae\x80"          -       3       ed:ae:80        -       UTF-16 surrogate 0xdb80
113 5.1.4 y "\xed\xaf\xbf"                  -       3       ed:af:bf        -       UTF-16 surrogate 0xdbff
114 5.1.5 y "\xed\xb0\x80"          -       3       ed:b0:80        -       UTF-16 surrogate 0xdc00
115 5.1.6 y "\xed\xbe\x80"          -       3       ed:be:80        -       UTF-16 surrogate 0xdf80
116 5.1.7 y "\xed\xbf\xbf"                  -       3       ed:bf:bf        -       UTF-16 surrogate 0xdfff
117 5.2     Paired UTF-16 surrogates
118 5.2.1 y "\xed\xa0\x80\xed\xb0\x80"              -       6       ed:a0:80:ed:b0:80       -       UTF-16 surrogate 0xd800
119 5.2.2 y "\xed\xa0\x80\xed\xbf\xbf"              -       6       ed:a0:80:ed:bf:bf       -       UTF-16 surrogate 0xd800
120 5.2.3 y "\xed\xad\xbf\xed\xb0\x80"              -       6       ed:ad:bf:ed:b0:80       -       UTF-16 surrogate 0xdb7f
121 5.2.4 y "\xed\xad\xbf\xed\xbf\xbf"              -       6       ed:ad:bf:ed:bf:bf       -       UTF-16 surrogate 0xdb7f
122 5.2.5 y "\xed\xae\x80\xed\xb0\x80"              -       6       ed:ae:80:ed:b0:80       -       UTF-16 surrogate 0xdb80
123 5.2.6 y "\xed\xae\x80\xed\xbf\xbf"              -       6       ed:ae:80:ed:bf:bf       -       UTF-16 surrogate 0xdb80
124 5.2.7 y "\xed\xaf\xbf\xed\xb0\x80"              -       6       ed:af:bf:ed:b0:80       -       UTF-16 surrogate 0xdbff
125 5.2.8 y "\xed\xaf\xbf\xed\xbf\xbf"              -       6       ed:af:bf:ed:bf:bf       -       UTF-16 surrogate 0xdbff
126 5.3     Other illegal code positions
127 5.3.1 y "\xef\xbf\xbe"                  -       3       ef:bf:be        -       byte order mark 0xfffe
128 # The ffff is legal by default since 872c91ae155f6880
129 5.3.2 y "\xef\xbf\xbf"                  -       3       ef:bf:bf        -       character 0xffff
130 __EOMK__
131
132 # 104..181
133 {
134     my $id;
135
136     local $SIG{__WARN__} = sub {
137         print "# $id: @_";
138         $@ .= "@_";
139     };
140
141     sub warn_unpack_U {
142         $@ = '';
143         my @null = unpack('C0U*', $_[0]);
144         return $@;
145     }
146
147     for (@MK) {
148         if (/^(?:\d+(?:\.\d+)?)\s/ || /^#/) {
149             # print "# $_\n";
150         } elsif (/^(\d+\.\d+\.\d+[bu]?)\s+([yn])\s+"(.+)"\s+([0-9a-f]{1,8}|-)\s+(\d+)\s+([0-9a-f]{2}(?::[0-9a-f]{2})*)(?:\s+((?:\d+|-)(?:\s+(.+))?))?$/) {
151             $id = $1;
152             my ($okay, $bytes, $Unicode, $byteslen, $hex, $charslen, $experr) =
153                 ($2, $3, $4, $5, $6, $7, $8);
154             my @hex = split(/:/, $hex);
155             is(scalar @hex, $byteslen, 'Amount of hex tallies with byteslen');
156             {
157                 use bytes;
158                 my $bytesbyteslen = length($bytes);
159                 is($bytesbyteslen, $byteslen,
160                    'bytes length() tallies with byteslen');
161             }
162             my $warn = warn_unpack_U($bytes);
163             if ($okay eq 'y') {
164                 is($warn, '', "No warnings expected for $id");
165             } elsif ($okay ne 'n') {
166                 is($okay, 'n', "Confused test description for $id");
167             } elsif($experr) {
168                 like($warn, qr/$experr/, "Expected warning for $id");
169             } else {
170                 isnt($warn, '', "Expect a warning for $id");
171             }
172         } else {
173             fail("unknown format '$_'");
174         }
175     }
176 }
177
178 done_testing();