This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
ce8496013a6ec5abb3cea086b7c7794526e10cce
[perl5.git] / t / re / reg_fold.t
1 #!perl
2
3 BEGIN {
4     chdir 't' if -d 't';
5     @INC = '../lib';
6     require './test.pl';
7 }
8
9 use strict;
10 use warnings;
11 my $count=1;
12 my @tests;
13
14 my %todo_pass = map { $_ => 1 }
15             qw(00DF 1E9E FB00 FB01 FB02 FB03 FB04 FB05 FB06);
16
17 my $file="../lib/unicore/CaseFolding.txt";
18 open my $fh,"<",$file or die "Failed to read '$file': $!";
19 while (<$fh>) {
20     chomp;
21     my ($line,$comment)= split/\s+#\s+/, $_;
22     my ($cp,$type,@folded)=split/[\s;]+/,$line||'';
23     next unless $type and ($type eq 'F' or $type eq 'C');
24     next if $type eq 'C';   # 'C' tests now done by fold_grind.t
25     my $fold_above_latin1 = grep { hex("0x$_") > 255 } @folded;
26     $_="\\x{$_}" for @folded;
27     my $cpv=hex("0x$cp");
28     my $chr="\\x{$cp}";
29     my @str;
30     foreach my $swap (0, 1) {   # swap lhs and rhs, or not.
31         foreach my $charclass (0) {   # Put rhs in [...], or not
32             my $lhs;
33             my $rhs;
34             if ($swap) {
35                 $lhs = join "", @folded;
36                 $rhs = $chr;
37                 $rhs = "[$rhs]" if $charclass;
38             } else {
39                 $lhs = $chr;
40                 $rhs = "";
41                 foreach my $rhs_char (@folded) {
42                     $rhs .= '[' if $charclass;
43                     $rhs .=  $rhs_char;
44                     $rhs .= ']' if $charclass;
45                 }
46             }
47             $lhs = "\"$lhs\"";
48             $rhs = "/^$rhs\$/i";
49
50             # Try both Latin1 and Unicode for code points below 256
51             foreach my $upgrade ("", 'utf8::upgrade($c); ') {
52                 if ($upgrade) {
53                     next if $swap && $fold_above_latin1;
54                     next if !$swap && $cpv > 255;
55                 }
56                 my $eval = "my \$c = $lhs; $upgrade\$c =~ $rhs";
57                 #print __LINE__, ": $eval\n";
58                 push @tests, qq[ok(eval '$eval', '$eval - $comment')];
59                 if (! $swap && ($cp eq '0390' || $cp eq '03B0')) {
60                     $tests[-1]="TODO: { local \$::TODO='[13:41] <BinGOs> cue *It is all Greek to me* joke.';\n$tests[-1] }"
61                 } elsif ($charclass && @folded > 1 && $swap && ! $upgrade && ! $fold_above_latin1) {
62                     $tests[-1]="TODO: { local \$::TODO='Multi-char, non-utf8 folded inside character class [ ] doesnt work';\n$tests[-1] }"
63                 } elsif (! $upgrade && $cpv >= 128 && $cpv <= 255 && $cpv != 0xb5) {
64                     $tests[-1]="TODO: { local \$::TODO='Most non-utf8 latin1 doesnt work';\n$tests[-1] }"
65                 } elsif (! $swap && $charclass && @folded > 1
66                     && ! $todo_pass{$cp})
67                 {
68                     # There are a few of these that pass; most fail.
69                     $tests[-1]="TODO: { local \$::TODO='Some multi-char, f8 folded inside character class [ ] doesnt work';\n$tests[-1] }"
70                 }
71                 $count++;
72             }
73         }
74     }
75 }
76
77 # Now verify the case folding tables.  First compute the mappings without
78 # resorting to the functions we're testing.
79
80 # Initialize the array so each $i maps to itself.
81 my @fold_ascii;
82 for my $i (0 .. 255) {
83     $fold_ascii[$i] = $i;
84 }
85 my @fold_latin1 = @fold_ascii;
86
87 # Override the uppercase elements to fold to their lower case equivalents,
88 # using the fact that 'A' in ASCII is 0x41, 'a' is 0x41+32, 'B' is 0x42, and
89 # so on.  The same paradigm applies for most of the Latin1 range cased
90 # characters, but in posix anything outside ASCII maps to itself, as we've
91 # already set up.
92 for my $i (0x41 .. 0x5A, 0xC0 .. 0xD6, 0xD8 .. 0xDE) {
93     my $upper_ord = ord_latin1_to_native($i);
94     my $lower_ord = ord_latin1_to_native($i + 32);
95
96     $fold_latin1[$upper_ord] = $lower_ord;
97
98     next if $i > 127;
99     $fold_ascii[$upper_ord] = $lower_ord;
100 }
101
102 # Same for folding lower to the upper equivalents
103 for my $i (0x61 .. 0x7A, 0xE0 .. 0xF6, 0xF8 .. 0xFE) {
104     my $lower_ord = ord_latin1_to_native($i);
105     my $upper_ord = ord_latin1_to_native($i - 32);
106
107     $fold_latin1[$lower_ord] = $upper_ord;
108
109     next if $i > 127;
110     $fold_ascii[$lower_ord] = $upper_ord;
111 }
112
113 # Test every latin1 character that the correct values in both /u and /d
114 for my $i (0 .. 255) {
115     my $chr = sprintf "\\x%02X", $i;
116     my $hex_fold_ascii = sprintf "0x%02X", $fold_ascii[$i];
117     my $hex_fold_latin1 = sprintf "0x%02X", $fold_latin1[$i];
118     push @tests, qq[like chr($hex_fold_ascii), qr/(?d:$chr)/i, 'chr($hex_fold_ascii) =~ qr/(?d:$chr)/i'];
119     $count++;
120     push @tests, qq[like chr($hex_fold_latin1), qr/(?u:$chr)/i, 'chr($hex_fold_latin1) =~ qr/(?u:$chr)/i'];
121     $count++;
122 }
123
124
125 push @tests, qq[like chr(0x0430), qr/[=\x{0410}-\x{0411}]/i, 'Bug #71752 Unicode /i char in a range'];
126 $count++;
127 push @tests, qq[like 'a', qr/\\p{Upper}/i, "'a' =~ /\\\\p{Upper}/i"];
128 $count++;
129 push @tests, q[my $c = "\x{212A}"; my $p = qr/(?:^[\x{004B}_]+$)/i; utf8::upgrade($p); like $c, $p, 'Bug #78994: my $c = "\x{212A}"; my $p = qr/(?:^[\x{004B}_]+$)/i; utf8::upgrade($p); $c =~ $p'];
130 $count++;
131
132 eval join ";\n","plan tests=>".($count-1),@tests,"1"
133     or die $@;
134 __DATA__