xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/utf8.t (revision 0:68f95e015346)
1*0Sstevel@tonic-gate#!./perl
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gatemy $has_perlio;
4*0Sstevel@tonic-gate
5*0Sstevel@tonic-gateBEGIN {
6*0Sstevel@tonic-gate    chdir 't' if -d 't';
7*0Sstevel@tonic-gate    @INC = '../lib';
8*0Sstevel@tonic-gate    require './test.pl';
9*0Sstevel@tonic-gate    unless ($has_perlio = find PerlIO::Layer 'perlio') {
10*0Sstevel@tonic-gate	print <<EOF;
11*0Sstevel@tonic-gate# Since you don't have perlio you might get failures with UTF-8 locales.
12*0Sstevel@tonic-gateEOF
13*0Sstevel@tonic-gate    }
14*0Sstevel@tonic-gate}
15*0Sstevel@tonic-gate
16*0Sstevel@tonic-gateno utf8; # Ironic, no?
17*0Sstevel@tonic-gate
18*0Sstevel@tonic-gate# NOTE!
19*0Sstevel@tonic-gate#
20*0Sstevel@tonic-gate# Think carefully before adding tests here.  In general this should be
21*0Sstevel@tonic-gate# used only for about three categories of tests:
22*0Sstevel@tonic-gate#
23*0Sstevel@tonic-gate# (1) tests that absolutely require 'use utf8', and since that in general
24*0Sstevel@tonic-gate#     shouldn't be needed as the utf8 is being obsoleted, this should
25*0Sstevel@tonic-gate#     have rather few tests.  If you want to test Unicode and regexes,
26*0Sstevel@tonic-gate#     you probably want to go to op/regexp or op/pat; if you want to test
27*0Sstevel@tonic-gate#     split, go to op/split; pack, op/pack; appending or joining,
28*0Sstevel@tonic-gate#     op/append or op/join, and so forth
29*0Sstevel@tonic-gate#
30*0Sstevel@tonic-gate# (2) tests that have to do with Unicode tokenizing (though it's likely
31*0Sstevel@tonic-gate#     that all the other Unicode tests sprinkled around the t/**/*.t are
32*0Sstevel@tonic-gate#     going to catch that)
33*0Sstevel@tonic-gate#
34*0Sstevel@tonic-gate# (3) complicated tests that simultaneously stress so many Unicode features
35*0Sstevel@tonic-gate#     that deciding into which other test script the tests should go to
36*0Sstevel@tonic-gate#     is hard -- maybe consider breaking up the complicated test
37*0Sstevel@tonic-gate#
38*0Sstevel@tonic-gate#
39*0Sstevel@tonic-gate
40*0Sstevel@tonic-gateplan tests => 145;
41*0Sstevel@tonic-gate
42*0Sstevel@tonic-gate{
43*0Sstevel@tonic-gate    # bug id 20001009.001
44*0Sstevel@tonic-gate
45*0Sstevel@tonic-gate    my ($a, $b);
46*0Sstevel@tonic-gate
47*0Sstevel@tonic-gate    { use bytes; $a = "\xc3\xa4" }
48*0Sstevel@tonic-gate    { use utf8;  $b = "\xe4"     }
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate    my $test = 68;
51*0Sstevel@tonic-gate
52*0Sstevel@tonic-gate    ok($a ne $b);
53*0Sstevel@tonic-gate
54*0Sstevel@tonic-gate    { use utf8; ok($a ne $b) }
55*0Sstevel@tonic-gate}
56*0Sstevel@tonic-gate
57*0Sstevel@tonic-gate
58*0Sstevel@tonic-gate{
59*0Sstevel@tonic-gate    # bug id 20000730.004
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gate    my $smiley = "\x{263a}";
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gate    for my $s ("\x{263a}",
64*0Sstevel@tonic-gate	       $smiley,
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate	       "" . $smiley,
67*0Sstevel@tonic-gate	       "" . "\x{263a}",
68*0Sstevel@tonic-gate
69*0Sstevel@tonic-gate	       $smiley    . "",
70*0Sstevel@tonic-gate	       "\x{263a}" . "",
71*0Sstevel@tonic-gate	       ) {
72*0Sstevel@tonic-gate	my $length_chars = length($s);
73*0Sstevel@tonic-gate	my $length_bytes;
74*0Sstevel@tonic-gate	{ use bytes; $length_bytes = length($s) }
75*0Sstevel@tonic-gate	my @regex_chars = $s =~ m/(.)/g;
76*0Sstevel@tonic-gate	my $regex_chars = @regex_chars;
77*0Sstevel@tonic-gate	my @split_chars = split //, $s;
78*0Sstevel@tonic-gate	my $split_chars = @split_chars;
79*0Sstevel@tonic-gate	ok("$length_chars/$regex_chars/$split_chars/$length_bytes" eq
80*0Sstevel@tonic-gate	   "1/1/1/3");
81*0Sstevel@tonic-gate    }
82*0Sstevel@tonic-gate
83*0Sstevel@tonic-gate    for my $s ("\x{263a}" . "\x{263a}",
84*0Sstevel@tonic-gate	       $smiley    . $smiley,
85*0Sstevel@tonic-gate
86*0Sstevel@tonic-gate	       "\x{263a}\x{263a}",
87*0Sstevel@tonic-gate	       "$smiley$smiley",
88*0Sstevel@tonic-gate
89*0Sstevel@tonic-gate	       "\x{263a}" x 2,
90*0Sstevel@tonic-gate	       $smiley    x 2,
91*0Sstevel@tonic-gate	       ) {
92*0Sstevel@tonic-gate	my $length_chars = length($s);
93*0Sstevel@tonic-gate	my $length_bytes;
94*0Sstevel@tonic-gate	{ use bytes; $length_bytes = length($s) }
95*0Sstevel@tonic-gate	my @regex_chars = $s =~ m/(.)/g;
96*0Sstevel@tonic-gate	my $regex_chars = @regex_chars;
97*0Sstevel@tonic-gate	my @split_chars = split //, $s;
98*0Sstevel@tonic-gate	my $split_chars = @split_chars;
99*0Sstevel@tonic-gate	ok("$length_chars/$regex_chars/$split_chars/$length_bytes" eq
100*0Sstevel@tonic-gate	   "2/2/2/6");
101*0Sstevel@tonic-gate    }
102*0Sstevel@tonic-gate}
103*0Sstevel@tonic-gate
104*0Sstevel@tonic-gate
105*0Sstevel@tonic-gate{
106*0Sstevel@tonic-gate    my $w = 0;
107*0Sstevel@tonic-gate    local $SIG{__WARN__} = sub { print "#($_[0])\n"; $w++ };
108*0Sstevel@tonic-gate    my $x = eval q/"\\/ . "\x{100}" . q/"/;;
109*0Sstevel@tonic-gate
110*0Sstevel@tonic-gate    ok($w == 0 && $x eq "\x{100}");
111*0Sstevel@tonic-gate}
112*0Sstevel@tonic-gate
113*0Sstevel@tonic-gate{
114*0Sstevel@tonic-gate    use warnings;
115*0Sstevel@tonic-gate    use strict;
116*0Sstevel@tonic-gate
117*0Sstevel@tonic-gate    my $show = q(
118*0Sstevel@tonic-gate                 sub show {
119*0Sstevel@tonic-gate                   my $result;
120*0Sstevel@tonic-gate                   $result .= '>' . join (',', map {ord} split //, $_) . '<'
121*0Sstevel@tonic-gate                     foreach @_;
122*0Sstevel@tonic-gate                   $result;
123*0Sstevel@tonic-gate                 }
124*0Sstevel@tonic-gate                 1;
125*0Sstevel@tonic-gate                );
126*0Sstevel@tonic-gate    eval $show or die $@; # We don't expect this sub definition to fail.
127*0Sstevel@tonic-gate    my $progfile = 'utf' . $$;
128*0Sstevel@tonic-gate    END {unlink_all $progfile}
129*0Sstevel@tonic-gate
130*0Sstevel@tonic-gate    # If I'm right 60 is '>' in ASCII, ' ' in EBCDIC
131*0Sstevel@tonic-gate    # 173 is not punctuation in either ASCII or EBCDIC
132*0Sstevel@tonic-gate    my (@char);
133*0Sstevel@tonic-gate    foreach (60, 173, 257, 65532) {
134*0Sstevel@tonic-gate      my $char = chr $_;
135*0Sstevel@tonic-gate      utf8::encode($char);
136*0Sstevel@tonic-gate      # I don't want to use map {ord} and I've no need to hardcode the UTF
137*0Sstevel@tonic-gate      # version
138*0Sstevel@tonic-gate      my $charsubst = $char;
139*0Sstevel@tonic-gate      $charsubst =~ s/(.)/ord ($1) . ','/ge;
140*0Sstevel@tonic-gate      chop $charsubst;
141*0Sstevel@tonic-gate      # Not testing this one against map {ord}
142*0Sstevel@tonic-gate      my $char_as_ord
143*0Sstevel@tonic-gate          = join " . ", map {sprintf 'chr (%d)', ord $_} split //, $char;
144*0Sstevel@tonic-gate      push @char, [$_, $char, $charsubst, $char_as_ord];
145*0Sstevel@tonic-gate    }
146*0Sstevel@tonic-gate    # Now we've done all the UTF8 munching hopefully we're safe
147*0Sstevel@tonic-gate    my @tests = (
148*0Sstevel@tonic-gate             ['check our detection program works',
149*0Sstevel@tonic-gate              'my @a = ("'.chr(60).'\x2A", ""); $b = show @a', qr/^>60,42<><$/],
150*0Sstevel@tonic-gate             ['check literal 8 bit input',
151*0Sstevel@tonic-gate              '$a = "' . chr (173) . '"; $b = show $a', qr/^>173<$/],
152*0Sstevel@tonic-gate             ['check no utf8; makes no change',
153*0Sstevel@tonic-gate              'no utf8; $a = "' . chr (173) . '"; $b = show $a', qr/^>173<$/],
154*0Sstevel@tonic-gate             # Now we do the real byte sequences that are valid UTF8
155*0Sstevel@tonic-gate             (map {
156*0Sstevel@tonic-gate               ["the utf8 sequence for chr $_->[0]",
157*0Sstevel@tonic-gate                qq{\$a = "$_->[1]"; \$b = show \$a}, qr/^>$_->[2]<$/],
158*0Sstevel@tonic-gate               ["no utf8; for the utf8 sequence for chr $_->[0]",
159*0Sstevel@tonic-gate                qq(no utf8; \$a = "$_->[1]"; \$b = show \$a), qr/^>$_->[2]<$/],
160*0Sstevel@tonic-gate               ["use utf8; for the utf8 sequence for chr $_->[0]",
161*0Sstevel@tonic-gate                qq(use utf8; \$a = "$_->[1]"; \$b = show \$a), qr/^>$_->[0]<$/],
162*0Sstevel@tonic-gate              } @char),
163*0Sstevel@tonic-gate             # Interpolation of hex characters needs to take place now, as we're
164*0Sstevel@tonic-gate             # testing feeding malformed utf8 into perl. Bug now fixed was an
165*0Sstevel@tonic-gate             # "out of memory" error. We really need the "" [rather than qq()
166*0Sstevel@tonic-gate             # or q()] to get the best explosion.
167*0Sstevel@tonic-gate             ["!Feed malformed utf8 into perl.", <<"BANG",
168*0Sstevel@tonic-gate    use utf8; %a = ("\xE1\xA0"=>"sterling");
169*0Sstevel@tonic-gate    print 'start'; printf '%x,', ord \$_ foreach keys %a; print "end\n";
170*0Sstevel@tonic-gateBANG
171*0Sstevel@tonic-gate	      qr/^Malformed UTF-8 character \(\d bytes?, need \d, .+\).*start\d+,end$/sm
172*0Sstevel@tonic-gate	     ],
173*0Sstevel@tonic-gate            );
174*0Sstevel@tonic-gate    foreach (@tests) {
175*0Sstevel@tonic-gate        my ($why, $prog, $expect) = @$_;
176*0Sstevel@tonic-gate        open P, ">$progfile" or die "Can't open '$progfile': $!";
177*0Sstevel@tonic-gate        binmode(P, ":bytes") if $has_perlio;
178*0Sstevel@tonic-gate	print P $show, $prog, '; print $b'
179*0Sstevel@tonic-gate            or die "Print to 'progfile' failed: $!";
180*0Sstevel@tonic-gate        close P or die "Can't close '$progfile': $!";
181*0Sstevel@tonic-gate        if ($why =~ s/^!//) {
182*0Sstevel@tonic-gate            print "# Possible delay...\n";
183*0Sstevel@tonic-gate        } else {
184*0Sstevel@tonic-gate            print "# $prog\n";
185*0Sstevel@tonic-gate        }
186*0Sstevel@tonic-gate        my $result = runperl ( stderr => 1, progfile => $progfile );
187*0Sstevel@tonic-gate        like ($result, $expect, $why);
188*0Sstevel@tonic-gate    }
189*0Sstevel@tonic-gate    print
190*0Sstevel@tonic-gate        "# Again! Again! [but this time as eval, and not the explosive one]\n";
191*0Sstevel@tonic-gate    # and now we've safely done them all as separate files, check that the
192*0Sstevel@tonic-gate    # evals do the same thing. Hopefully doing it later successfully decouples
193*0Sstevel@tonic-gate    # the previous tests from anything messy that may go wrong with the evals.
194*0Sstevel@tonic-gate    foreach (@tests) {
195*0Sstevel@tonic-gate        my ($why, $prog, $expect) = @$_;
196*0Sstevel@tonic-gate        next if $why =~ m/^!/; # Goes bang.
197*0Sstevel@tonic-gate        my $result = eval $prog;
198*0Sstevel@tonic-gate        if ($@) {
199*0Sstevel@tonic-gate            print "# prog is $prog\n";
200*0Sstevel@tonic-gate            print "# \$\@=", _qq($@), "\n";
201*0Sstevel@tonic-gate        }
202*0Sstevel@tonic-gate        like ($result, $expect, $why);
203*0Sstevel@tonic-gate    }
204*0Sstevel@tonic-gate
205*0Sstevel@tonic-gate    # See what the tokeniser does with hash keys.
206*0Sstevel@tonic-gate    print "# What does the tokeniser do with utf8 hash keys?\n";
207*0Sstevel@tonic-gate    @tests = (map {
208*0Sstevel@tonic-gate        # This is the control - I don't expect it to fail
209*0Sstevel@tonic-gate        ["assign utf8 for chr $_->[0] to a hash",
210*0Sstevel@tonic-gate         qq(my \$a = "$_->[1]"; my %h; \$h{\$a} = 1;
211*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{$_->[3]}; \$b),
212*0Sstevel@tonic-gate         qr/^>$_->[2]<$/],
213*0Sstevel@tonic-gate        ["no utf8; assign utf8 for chr $_->[0] to a hash",
214*0Sstevel@tonic-gate         qq(no utf8; my \$a = "$_->[1]"; my %h; \$h{\$a} = 1;
215*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{$_->[3]}; \$b),
216*0Sstevel@tonic-gate         qr/^>$_->[2]<$/],
217*0Sstevel@tonic-gate        ["use utf8; assign utf8 for chr $_->[0] to a hash",
218*0Sstevel@tonic-gate         qq(use utf8; my \$a = "$_->[1]"; my %h; \$h{\$a} = 1;
219*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{chr $_->[0]}; \$b),
220*0Sstevel@tonic-gate         qr/^>$_->[0]<$/],
221*0Sstevel@tonic-gate        # Now check literal $h{"x"} constructions.
222*0Sstevel@tonic-gate        ["\$h{\"x\"} construction, where x is utf8 for chr $_->[0]",
223*0Sstevel@tonic-gate         qq(my \$a = "$_->[1]"; my %h; \$h{"$_->[1]"} = 1;
224*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{$_->[3]}; \$b),
225*0Sstevel@tonic-gate         qr/^>$_->[2]<$/],
226*0Sstevel@tonic-gate        ["no utf8; \$h{\"x\"} construction, where x is utf8 for chr $_->[0]",
227*0Sstevel@tonic-gate         qq(no utf8; my \$a = "$_->[1]"; my %h; \$h{"$_->[1]"} = 1;
228*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{$_->[3]}; \$b),
229*0Sstevel@tonic-gate         qr/^>$_->[2]<$/],
230*0Sstevel@tonic-gate        ["use utf8; \$h{\"x\"} construction, where x is utf8 for chr $_->[0]",
231*0Sstevel@tonic-gate         qq(use utf8; my \$a = "$_->[1]"; my %h; \$h{"$_->[1]"} = 1;
232*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{chr $_->[0]}; \$b),
233*0Sstevel@tonic-gate         qr/^>$_->[0]<$/],
234*0Sstevel@tonic-gate        # Now check "x" => constructions.
235*0Sstevel@tonic-gate        ["assign \"x\"=>1 to a hash, where x is utf8 for chr $_->[0]",
236*0Sstevel@tonic-gate         qq(my \$a = "$_->[1]"; my %h; %h = ("$_->[1]" => 1);
237*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{$_->[3]}; \$b),
238*0Sstevel@tonic-gate         qr/^>$_->[2]<$/],
239*0Sstevel@tonic-gate        ["no utf8; assign \"x\"=>1 to a hash, where x is utf8 for chr $_->[0]",
240*0Sstevel@tonic-gate         qq(no utf8; my \$a = "$_->[1]"; my %h; %h = ("$_->[1]" => 1);
241*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{$_->[3]}; \$b),
242*0Sstevel@tonic-gate         qr/^>$_->[2]<$/],
243*0Sstevel@tonic-gate        ["use utf8; assign \"x\"=>1 to a hash, where x is utf8 for chr $_->[0]",
244*0Sstevel@tonic-gate         qq(use utf8; my \$a = "$_->[1]"; my %h; %h = ("$_->[1]" => 1);
245*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{chr $_->[0]}; \$b),
246*0Sstevel@tonic-gate         qr/^>$_->[0]<$/],
247*0Sstevel@tonic-gate        # Check copies of hashes made from literal utf8 keys
248*0Sstevel@tonic-gate        ["assign utf8 for chr $_->[0] to a hash, then copy it",
249*0Sstevel@tonic-gate         qq(my \$a = "$_->[1]"; my %i; \$i{\$a} = 1; my %h = %i;
250*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{$_->[3]}; \$b),
251*0Sstevel@tonic-gate         qr/^>$_->[2]<$/],
252*0Sstevel@tonic-gate        ["no utf8; assign utf8 for chr $_->[0] to a hash, then copy it",
253*0Sstevel@tonic-gate         qq(no utf8; my \$a = "$_->[1]"; my %i; \$i{\$a} = 1;; my %h = %i;
254*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{$_->[3]}; \$b),
255*0Sstevel@tonic-gate         qr/^>$_->[2]<$/],
256*0Sstevel@tonic-gate        ["use utf8; assign utf8 for chr $_->[0] to a hash, then copy it",
257*0Sstevel@tonic-gate         qq(use utf8; my \$a = "$_->[1]"; my %i; \$i{\$a} = 1; my %h = %i;
258*0Sstevel@tonic-gate            my \$b = show keys %h; \$b .= 'F' unless \$h{chr $_->[0]}; \$b),
259*0Sstevel@tonic-gate         qr/^>$_->[0]<$/],
260*0Sstevel@tonic-gate     } @char);
261*0Sstevel@tonic-gate    foreach (@tests) {
262*0Sstevel@tonic-gate        my ($why, $prog, $expect) = @$_;
263*0Sstevel@tonic-gate        # print "# $prog\n";
264*0Sstevel@tonic-gate        my $result = eval $prog;
265*0Sstevel@tonic-gate        like ($result, $expect, $why);
266*0Sstevel@tonic-gate    }
267*0Sstevel@tonic-gate}
268*0Sstevel@tonic-gate
269*0Sstevel@tonic-gate#
270*0Sstevel@tonic-gate# bug fixed by change #17928
271*0Sstevel@tonic-gate# separate perl used because we rely on 'strict' not yet loaded;
272*0Sstevel@tonic-gate# before the patch, the eval died with an error like:
273*0Sstevel@tonic-gate#   "my" variable $strict::VERSION can't be in a package
274*0Sstevel@tonic-gate#
275*0Sstevel@tonic-gateSKIP: {
276*0Sstevel@tonic-gate    skip("Embedded UTF-8 does not work in EBCDIC", 1) if ord("A") == 193;
277*0Sstevel@tonic-gate    ok('' eq runperl(prog => <<'CODE'), "change #17928");
278*0Sstevel@tonic-gate	my $code = qq{ my \$\xe3\x83\x95\xe3\x83\xbc = 5; };
279*0Sstevel@tonic-gate    {
280*0Sstevel@tonic-gate	use utf8;
281*0Sstevel@tonic-gate	eval $code;
282*0Sstevel@tonic-gate	print $@ if $@;
283*0Sstevel@tonic-gate    }
284*0Sstevel@tonic-gateCODE
285*0Sstevel@tonic-gate}
286*0Sstevel@tonic-gate
287*0Sstevel@tonic-gate{
288*0Sstevel@tonic-gate    use utf8;
289*0Sstevel@tonic-gate    $a = <<'END';
290*0Sstevel@tonic-gate0 ....... 1 ....... 2 ....... 3 ....... 4 ....... 5 ....... 6 ....... 7 .......
291*0Sstevel@tonic-gateEND
292*0Sstevel@tonic-gate    my (@i, $s);
293*0Sstevel@tonic-gate
294*0Sstevel@tonic-gate    @i = ();
295*0Sstevel@tonic-gate    push @i, $s = index($a, '6');     # 60
296*0Sstevel@tonic-gate    push @i, $s = index($a, '.', $s); # next . after 60 is 62
297*0Sstevel@tonic-gate    push @i, $s = index($a, '5');     # 50
298*0Sstevel@tonic-gate    push @i, $s = index($a, '.', $s); # next . after 52 is 52
299*0Sstevel@tonic-gate    push @i, $s = index($a, '7');     # 70
300*0Sstevel@tonic-gate    push @i, $s = index($a, '.', $s); # next . after 70 is 72
301*0Sstevel@tonic-gate    push @i, $s = index($a, '4');     # 40
302*0Sstevel@tonic-gate    push @i, $s = index($a, '.', $s); # next . after 40 is 42
303*0Sstevel@tonic-gate    is("@i", "60 62 50 52 70 72 40 42", "utf8 heredoc index");
304*0Sstevel@tonic-gate
305*0Sstevel@tonic-gate    @i = ();
306*0Sstevel@tonic-gate    push @i, $s = rindex($a, '6');     # 60
307*0Sstevel@tonic-gate    push @i, $s = rindex($a, '.', $s); # previous . before 60 is 58
308*0Sstevel@tonic-gate    push @i, $s = rindex($a, '5');     # 50
309*0Sstevel@tonic-gate    push @i, $s = rindex($a, '.', $s); # previous . before 52 is 48
310*0Sstevel@tonic-gate    push @i, $s = rindex($a, '7');     # 70
311*0Sstevel@tonic-gate    push @i, $s = rindex($a, '.', $s); # previous . before 70 is 68
312*0Sstevel@tonic-gate    push @i, $s = rindex($a, '4');     # 40
313*0Sstevel@tonic-gate    push @i, $s = rindex($a, '.', $s); # previous . before 40 is 38
314*0Sstevel@tonic-gate    is("@i", "60 58 50 48 70 68 40 38", "utf8 heredoc rindex");
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gate    @i = ();
317*0Sstevel@tonic-gate    push @i, $s =  index($a, '6');     # 60
318*0Sstevel@tonic-gate    push @i,  index($a, '.', $s);      # next     . after  60 is 62
319*0Sstevel@tonic-gate    push @i, rindex($a, '.', $s);      # previous . before 60 is 58
320*0Sstevel@tonic-gate    push @i, $s = rindex($a, '5');     # 60
321*0Sstevel@tonic-gate    push @i,  index($a, '.', $s);      # next     . after  50 is 52
322*0Sstevel@tonic-gate    push @i, rindex($a, '.', $s);      # previous . before 50 is 48
323*0Sstevel@tonic-gate    push @i, $s =  index($a, '7', $s); # 70
324*0Sstevel@tonic-gate    push @i,  index($a, '.', $s);      # next     . after  70 is 72
325*0Sstevel@tonic-gate    push @i, rindex($a, '.', $s);      # previous . before 70 is 68
326*0Sstevel@tonic-gate    is("@i", "60 62 58 50 52 48 70 72 68", "utf8 heredoc index and rindex");
327*0Sstevel@tonic-gate}
328*0Sstevel@tonic-gate
329*0Sstevel@tonic-gateSKIP: {
330*0Sstevel@tonic-gate    skip("Embedded UTF-8 does not work in EBCDIC", 1) if ord("A") == 193;
331*0Sstevel@tonic-gate    use utf8;
332*0Sstevel@tonic-gate    eval qq{is(q \xc3\xbc test \xc3\xbc, qq\xc2\xb7 test \xc2\xb7,
333*0Sstevel@tonic-gate	       "utf8 quote delimiters [perl #16823]");};
334*0Sstevel@tonic-gate}
335*0Sstevel@tonic-gate
336*0Sstevel@tonic-gate# Test the "internals".
337*0Sstevel@tonic-gate
338*0Sstevel@tonic-gate{
339*0Sstevel@tonic-gate    my $a = "A";
340*0Sstevel@tonic-gate    my $b = chr(0x0FF);
341*0Sstevel@tonic-gate    my $c = chr(0x100);
342*0Sstevel@tonic-gate
343*0Sstevel@tonic-gate    ok( utf8::valid($a), "utf8::valid basic");
344*0Sstevel@tonic-gate    ok( utf8::valid($b), "utf8::valid beyond");
345*0Sstevel@tonic-gate    ok( utf8::valid($c), "utf8::valid unicode");
346*0Sstevel@tonic-gate
347*0Sstevel@tonic-gate    ok(!utf8::is_utf8($a), "!utf8::is_utf8 basic");
348*0Sstevel@tonic-gate    ok(!utf8::is_utf8($b), "!utf8::is_utf8 beyond");
349*0Sstevel@tonic-gate    ok( utf8::is_utf8($c), "utf8::is_utf8 unicode");
350*0Sstevel@tonic-gate
351*0Sstevel@tonic-gate    is(utf8::upgrade($a), 1, "utf8::upgrade basic");
352*0Sstevel@tonic-gate    is(utf8::upgrade($b), 2, "utf8::upgrade beyond");
353*0Sstevel@tonic-gate    is(utf8::upgrade($c), 2, "utf8::upgrade unicode");
354*0Sstevel@tonic-gate
355*0Sstevel@tonic-gate    is($a, "A",       "basic");
356*0Sstevel@tonic-gate    is($b, "\xFF",    "beyond");
357*0Sstevel@tonic-gate    is($c, "\x{100}", "unicode");
358*0Sstevel@tonic-gate
359*0Sstevel@tonic-gate    ok( utf8::valid($a), "utf8::valid basic");
360*0Sstevel@tonic-gate    ok( utf8::valid($b), "utf8::valid beyond");
361*0Sstevel@tonic-gate    ok( utf8::valid($c), "utf8::valid unicode");
362*0Sstevel@tonic-gate
363*0Sstevel@tonic-gate    ok( utf8::is_utf8($a), "utf8::is_utf8 basic");
364*0Sstevel@tonic-gate    ok( utf8::is_utf8($b), "utf8::is_utf8 beyond");
365*0Sstevel@tonic-gate    ok( utf8::is_utf8($c), "utf8::is_utf8 unicode");
366*0Sstevel@tonic-gate
367*0Sstevel@tonic-gate    is(utf8::downgrade($a), 1, "utf8::downgrade basic");
368*0Sstevel@tonic-gate    is(utf8::downgrade($b), 1, "utf8::downgrade beyond");
369*0Sstevel@tonic-gate
370*0Sstevel@tonic-gate    is($a, "A",       "basic");
371*0Sstevel@tonic-gate    is($b, "\xFF",    "beyond");
372*0Sstevel@tonic-gate
373*0Sstevel@tonic-gate    ok( utf8::valid($a), "utf8::valid basic");
374*0Sstevel@tonic-gate    ok( utf8::valid($b), "utf8::valid beyond");
375*0Sstevel@tonic-gate
376*0Sstevel@tonic-gate    ok(!utf8::is_utf8($a), "!utf8::is_utf8 basic");
377*0Sstevel@tonic-gate    ok(!utf8::is_utf8($b), "!utf8::is_utf8 beyond");
378*0Sstevel@tonic-gate
379*0Sstevel@tonic-gate    utf8::encode($a);
380*0Sstevel@tonic-gate    utf8::encode($b);
381*0Sstevel@tonic-gate    utf8::encode($c);
382*0Sstevel@tonic-gate
383*0Sstevel@tonic-gate    is($a, "A",       "basic");
384*0Sstevel@tonic-gate    is(length($b), 2, "beyond length");
385*0Sstevel@tonic-gate    is(length($c), 2, "unicode length");
386*0Sstevel@tonic-gate
387*0Sstevel@tonic-gate    ok(utf8::valid($a), "utf8::valid basic");
388*0Sstevel@tonic-gate    ok(utf8::valid($b), "utf8::valid beyond");
389*0Sstevel@tonic-gate    ok(utf8::valid($c), "utf8::valid unicode");
390*0Sstevel@tonic-gate
391*0Sstevel@tonic-gate    # encode() clears the UTF-8 flag (unlike upgrade()).
392*0Sstevel@tonic-gate    ok(!utf8::is_utf8($a), "!utf8::is_utf8 basic");
393*0Sstevel@tonic-gate    ok(!utf8::is_utf8($b), "!utf8::is_utf8 beyond");
394*0Sstevel@tonic-gate    ok(!utf8::is_utf8($c), "!utf8::is_utf8 unicode");
395*0Sstevel@tonic-gate
396*0Sstevel@tonic-gate    utf8::decode($a);
397*0Sstevel@tonic-gate    utf8::decode($b);
398*0Sstevel@tonic-gate    utf8::decode($c);
399*0Sstevel@tonic-gate
400*0Sstevel@tonic-gate    is($a, "A",       "basic");
401*0Sstevel@tonic-gate    is($b, "\xFF",    "beyond");
402*0Sstevel@tonic-gate    is($c, "\x{100}", "unicode");
403*0Sstevel@tonic-gate
404*0Sstevel@tonic-gate    ok(utf8::valid($a), "!utf8::valid basic");
405*0Sstevel@tonic-gate    ok(utf8::valid($b), "!utf8::valid beyond");
406*0Sstevel@tonic-gate    ok(utf8::valid($c), " utf8::valid unicode");
407*0Sstevel@tonic-gate
408*0Sstevel@tonic-gate    ok(!utf8::is_utf8($a), "!utf8::is_utf8 basic");
409*0Sstevel@tonic-gate    ok( utf8::is_utf8($b), " utf8::is_utf8 beyond"); # $b stays in UTF-8.
410*0Sstevel@tonic-gate    ok( utf8::is_utf8($c), " utf8::is_utf8 unicode");
411*0Sstevel@tonic-gate}
412*0Sstevel@tonic-gate
413*0Sstevel@tonic-gate{
414*0Sstevel@tonic-gate    eval {utf8::encode("�")};
415*0Sstevel@tonic-gate    like($@, qr/^Modification of a read-only value attempted/,
416*0Sstevel@tonic-gate	 "utf8::encode should refuse to touch read-only values");
417*0Sstevel@tonic-gate}
418*0Sstevel@tonic-gate
419*0Sstevel@tonic-gate{
420*0Sstevel@tonic-gate    my $a = "456\xb6";
421*0Sstevel@tonic-gate    utf8::upgrade($a);
422*0Sstevel@tonic-gate
423*0Sstevel@tonic-gate    my $b = "123456\xb6";
424*0Sstevel@tonic-gate    $b =~ s/^...//;
425*0Sstevel@tonic-gate    utf8::upgrade($b);
426*0Sstevel@tonic-gate    is($b, $a, "utf8::upgrade OffsetOK");
427*0Sstevel@tonic-gate}
428