This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
test for #127855 - Slowdown in m//g on COW strings of certain lengths
[perl5.git] / t / re / fold_grind.t
1 # Grind out a lot of combinatoric tests for folding.
2
3 binmode STDOUT, ":utf8";
4
5 BEGIN {
6     chdir 't' if -d 't';
7     @INC = '../lib';
8     require './test.pl';
9     require Config; import Config;
10     skip_all_if_miniperl("no dynamic loading on miniperl, no Encode nor POSIX");
11     if ($^O eq 'dec_osf') {
12       skip_all("$^O cannot handle this test");
13     }
14     require './loc_tools.pl';
15 }
16
17 use charnames ":full";
18
19 my $DEBUG = 0;  # Outputs extra information for debugging this .t
20
21 use strict;
22 use warnings;
23 no warnings 'locale';   # Plenty of these would otherwise get generated
24 use Encode;
25 use POSIX;
26
27 # Special-cased characters in the .c's that we want to make sure get tested.
28 my %be_sure_to_test = (
29         chr utf8::unicode_to_native(0xDF) => 1, # LATIN_SMALL_LETTER_SHARP_S
30         "\x{1E9E}" => 1, # LATIN_CAPITAL_LETTER_SHARP_S
31         "\x{390}" => 1, # GREEK_SMALL_LETTER_IOTA_WITH_DIALYTIKA_AND_TONOS
32         "\x{3B0}" => 1, # GREEK_SMALL_LETTER_UPSILON_WITH_DIALYTIKA_AND_TONOS
33         "\x{1FD3}" => 1, # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
34         "\x{1FE3}" => 1, # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
35     );
36
37
38 # Tests both unicode and not, so make sure not implicitly testing unicode
39 no feature 'unicode_strings';
40
41 # Case-insensitive matching is a large and complicated issue.  Perl does not
42 # implement it fully, properly.  For example, it doesn't include normalization
43 # as part of the equation.  To test every conceivable combination is clearly
44 # impossible; these tests are mostly drawn from visual inspection of the code
45 # and experience, trying to exercise all areas.
46
47 # There are three basic ranges of characters that Perl may treat differently:
48 # 1) Invariants under utf8 which on ASCII-ish machines are ASCII, and are
49 #    referred to here as ASCII.  On EBCDIC machines, the non-ASCII invariants
50 #    are all controls that fold to themselves.
51 my $ASCII = 1;
52
53 # 2) Other characters that fit into a byte but are different in utf8 than not;
54 #    here referred to, taking some liberties, as Latin1.
55 my $Latin1 = 2;
56
57 # 3) Characters that won't fit in a byte; here referred to as Unicode
58 my $Unicode = 3;
59
60 # Within these basic groups are equivalence classes that testing any character
61 # in is likely to lead to the same results as any other character.  This is
62 # used to cut down the number of tests needed, unless PERL_RUN_SLOW_TESTS is
63 # set.
64 my $skip_apparently_redundant = ! $ENV{PERL_RUN_SLOW_TESTS};
65
66 # Additionally parts of this test run a lot of subtests, outputting the
67 # resulting TAP can be expensive so the tests are summarised internally. The
68 # PERL_DEBUG_FULL_TEST environment variable can be set to produce the full
69 # output for debugging purposes.
70
71 sub range_type {
72     my $ord = ord shift;
73
74     return $ASCII if utf8::native_to_unicode($ord) < 128;
75     return $Latin1 if $ord < 256;
76     return $Unicode;
77 }
78
79 sub numerically {
80     return $a <=> $b
81 }
82
83 my $list_all_tests = $ENV{PERL_DEBUG_FULL_TEST} || $DEBUG;
84 $| = 1 if $list_all_tests;
85
86 # Significant time is saved by not outputting each test but grouping the
87 # output into subtests
88 my $okays;          # Number of ok's in current subtest
89 my $this_iteration; # Number of possible tests in current subtest
90 my $count = 0;      # Number of subtests = number of total tests
91
92 sub run_test($$$$) {
93     my ($test, $todo, $do_we_output_locale_name, $debug) = @_;
94
95     $debug = "" unless $DEBUG;
96     my $res = eval $test;
97
98     if ($do_we_output_locale_name) {
99         $do_we_output_locale_name = 'setlocale(LC_CTYPE, "'
100                          .  POSIX::setlocale(&POSIX::LC_CTYPE)
101                          . '"); ';
102     }
103     if (!$res || $list_all_tests) {
104       # Failed or debug; output the result
105       $count++;
106       ok($res, "$do_we_output_locale_name$test; $debug");
107     } else {
108       # Just count the test as passed
109       $okays++;
110     }
111     $this_iteration++;
112 }
113
114 my %has_test_by_participants;   # Makes sure has tests for each range and each
115                                 # number of characters that fold to the same
116                                 # thing
117 my %has_test_by_byte_count; # Makes sure has tests for each combination of
118                             # n bytes folds to m bytes
119
120 my %tests; # The set of tests.
121 # Each key is a code point that folds to something else.
122 # Each value is a list of things that the key folds to.  If the 'thing' is a
123 # single code point, it is that ordinal.  If it is a multi-char fold, it is an
124 # ordered list of the code points in that fold.  Here's an example for 'S':
125 #  '83' => [ 115, 383 ]
126 #
127 # And one for a multi-char fold: \xDF
128 #  223 => [
129 #            [  # 'ss'
130 #                83,
131 #                83
132 #            ],
133 #            [  # 'SS'
134 #                115,
135 #                115
136 #            ],
137 #            [  # LATIN SMALL LETTER LONG S
138 #                383,
139 #                383
140 #            ],
141 #          7838 # LATIN_CAPITAL_LETTER_SHARP_S
142 #        ],
143
144 my %folds;          # keys are code points that fold;
145                     # values are each a list of code points the key folds to
146 my %inverse_folds;  # keys are strings of the folded-to;
147                     # values are lists of characters that fold to them
148
149 sub add_test($@) {
150     my ($to, @from) = @_;
151
152     # Called to cause the input to be tested by adding to %tests.  @from is
153     # the list of characters that fold to the string $to.  @from should be
154     # sorted so the lowest code point is first....
155     # The input is in string form; %tests uses code points, so have to
156     # convert.
157
158     my $to_chars = length $to;
159     my @test_to;        # List of tests for $to
160
161     if ($to_chars == 1) {
162         @test_to = ord $to;
163     }
164     else {
165         push @test_to, [ map { ord $_ } split "", $to ];
166
167         # For multi-char folds, we also test that things that can fold to each
168         # individual character in the fold also work.  If we were testing
169         # comprehensively, we would try every combination of upper and lower
170         # case in the fold, but it will have to suffice to avoid running
171         # forever to make sure that each thing that folds to these is tested
172         # at least once.  Because of complement matching ([^...]), we need to
173         # do both the folded, and the folded-from.
174         # We first look at each character in the multi-char fold, and save how
175         # many characters fold to it; and also the maximum number of such
176         # folds
177         my @folds_to_count;     # 0th char in fold is index 0 ...
178         my $max_folds_to = 0;
179
180         for (my $i = 0; $i < $to_chars; $i++) {
181             my $to_char = substr($to, $i, 1);
182             if (exists $inverse_folds{$to_char}) {
183                 $folds_to_count[$i] = scalar @{$inverse_folds{$to_char}};
184                 $max_folds_to = $folds_to_count[$i] if $max_folds_to < $folds_to_count[$i];
185             }
186             else {
187                 $folds_to_count[$i] = 0;
188             }
189         }
190
191         # We will need to generate as many tests as the maximum number of
192         # folds, so that each fold will have at least one test.
193         # For example, consider character X which folds to the three character
194         # string 'xyz'.  If 2 things fold to x (X and x), 4 to y (Y, Y'
195         # (Y-prime), Y'' (Y-prime-prime), and y), and 1 thing to z (itself), 4
196         # tests will be generated:
197         #   xyz
198         #   XYz
199         #   xY'z
200         #   xY''z
201         for (my $i = 0; $i < $max_folds_to; $i++) {
202             my @this_test_to;   # Assemble a single test
203
204             # For each character in the multi-char fold ...
205             for (my $j = 0; $j < $to_chars; $j++) {
206                 my $this_char = substr($to, $j, 1);
207
208                 # Use its corresponding inverse fold, if available.
209                 if ($i < $folds_to_count[$j]) {
210                     push @this_test_to, ord $inverse_folds{$this_char}[$i];
211                 }
212                 else {  # Or else itself.
213                     push @this_test_to, ord $this_char;
214                 }
215             }
216
217             # Add this test to the list
218             push @test_to, [ @this_test_to ];
219         }
220
221         # Here, have assembled all the tests for the multi-char fold.  Sort so
222         # lowest code points are first for consistency and aesthetics in
223         # output.  We know there are at least two characters in the fold, but
224         # I haven't bothered to worry about sorting on an optional third
225         # character if the first two are identical.
226         @test_to = sort { ($a->[0] == $b->[0])
227                            ? $a->[1] <=> $b->[1]
228                            : $a->[0] <=> $b->[0]
229                         } @test_to;
230     }
231
232
233     # This test is from n bytes to m bytes.  Record that so won't try to add
234     # another test that does the same.
235     use bytes;
236     my $to_bytes = length $to;
237     foreach my $from_map (@from) {
238         $has_test_by_byte_count{length $from_map}{$to_bytes} = $to;
239     }
240     no bytes;
241
242     my $ord_smallest_from = ord shift @from;
243     if (exists $tests{$ord_smallest_from}) {
244         die "There are already tests for $ord_smallest_from"
245     };
246
247     # Add in the fold tests,
248     push @{$tests{$ord_smallest_from}}, @test_to;
249
250     # Then any remaining froms in the equivalence class.
251     push @{$tests{$ord_smallest_from}}, map { ord $_ } @from;
252 }
253
254 # Get the Unicode rules and construct inverse mappings from them
255
256 use Unicode::UCD;
257 my $file="../lib/unicore/CaseFolding.txt";
258
259 # Use the Unicode data file if we are on an ASCII platform (which its data is
260 # for), and it is in the modern format (starting in Unicode 3.1.0) and it is
261 # available.  This avoids being affected by potential bugs introduced by other
262 # layers of Perl
263 if ($::IS_ASCII
264     && pack("C*", split /\./, Unicode::UCD::UnicodeVersion()) ge v3.1.0
265     && open my $fh, "<", $file)
266 {
267     while (<$fh>) {
268         chomp;
269
270         # Lines look like (though without the initial '#')
271         #0130; F; 0069 0307; # LATIN CAPITAL LETTER I WITH DOT ABOVE
272
273         # Get rid of comments, ignore blank or comment-only lines
274         my $line = $_ =~ s/ (?: \s* \# .* )? $ //rx;
275         next unless length $line;
276         my ($hex_from, $fold_type, @hex_folded) = split /[\s;]+/, $line;
277
278         next if $fold_type =~ / ^ [IT] $/x; # Perl doesn't do Turkish folding
279         next if $fold_type eq 'S';  # If Unicode's tables are correct, the F
280                                     # should be a superset of S
281
282         my $from = hex $hex_from;
283         my @to = map { hex $_ } @hex_folded;
284         @{$folds{$from}} = @to;
285         my $folded_str = pack ("U0U*", @to);
286         push @{$inverse_folds{$folded_str}}, chr $from;
287     }
288 }
289 else {  # Here, can't use the .txt file: read the Unicode rules file and
290         # construct inverse mappings from it
291
292     my ($invlist_ref, $invmap_ref, undef, $default)
293                                     = Unicode::UCD::prop_invmap('Case_Folding');
294     for my $i (0 .. @$invlist_ref - 1 - 1) {
295         next if $invmap_ref->[$i] == $default;
296
297         # Make into an array if not so already, so can treat uniformly below
298         $invmap_ref->[$i] = [ $invmap_ref->[$i] ] if ! ref $invmap_ref->[$i];
299
300         # Each subsequent element of the range requires adjustment of +1 from
301         # the previous element
302         my $adjust = -1;
303         for my $j ($invlist_ref->[$i] .. $invlist_ref->[$i+1] -1) {
304             $adjust++;
305             my @to = map { $_ + $adjust } @{$invmap_ref->[$i]};
306             push @{$folds{$j}}, @to;
307             my $folded_str = join "", map { chr } @to;
308             utf8::upgrade($folded_str);
309             #note (sprintf "%d: %04X: %s", __LINE__, $j, join " ",
310             #    map { sprintf "%04X", $_  + $adjust } @{$invmap_ref->[$i]});
311             push @{$inverse_folds{$folded_str}}, chr $j;
312         }
313     }
314 }
315
316 # Analyze the data and generate tests to get adequate test coverage.  We sort
317 # things so that smallest code points are done first.
318 TO:
319 foreach my $to (sort { (length $a == length $b)
320                         ? $a cmp $b
321                         : length $a <=> length $b
322                     } keys %inverse_folds)
323 {
324
325     # Within each fold, sort so that the smallest code points are done first
326     @{$inverse_folds{$to}} = sort { $a cmp $b } @{$inverse_folds{$to}};
327     my @from = @{$inverse_folds{$to}};
328
329     # Just add it to the tests if doing complete coverage
330     if (! $skip_apparently_redundant) {
331         add_test($to, @from);
332         next TO;
333     }
334
335     my $to_chars = length $to;
336     my $to_range_type = range_type(substr($to, 0, 1));
337
338     # If this is required to be tested, do so.  We check for these first, as
339     # they will take up slots of byte-to-byte combinations that we otherwise
340     # would have to have other tests to get.
341     foreach my $from_map (@from) {
342         if (exists $be_sure_to_test{$from_map}) {
343             add_test($to, @from);
344             next TO;
345         }
346     }
347
348     # If the fold contains heterogeneous range types, is suspect and should be
349     # tested.
350     if ($to_chars > 1) {
351         foreach my $char (split "", $to) {
352             if (range_type($char) != $to_range_type) {
353                 add_test($to, @from);
354                 next TO;
355             }
356         }
357     }
358
359     # If the mapping crosses range types, is suspect and should be tested
360     foreach my $from_map (@from) {
361         if (range_type($from_map) != $to_range_type) {
362             add_test($to, @from);
363             next TO;
364         }
365     }
366
367     # Here, all components of the mapping are in the same range type.  For
368     # single character folds, we test one case in each range type that has 2
369     # particpants, 3 particpants, etc.
370     if ($to_chars == 1) {
371         if (! exists $has_test_by_participants{scalar @from}{$to_range_type}) {
372             add_test($to, @from);
373             $has_test_by_participants{scalar @from}{$to_range_type} = $to;
374             next TO;
375         }
376     }
377
378     # We also test all combinations of mappings from m to n bytes.  This is
379     # because the regex optimizer cares.  (Don't bother worrying about that
380     # Latin1 chars will occupy a different number of bytes under utf8, as
381     # there are plenty of other cases that catch these byte numbers.)
382     use bytes;
383     my $to_bytes = length $to;
384     foreach my $from_map (@from) {
385         if (! exists $has_test_by_byte_count{length $from_map}{$to_bytes}) {
386             add_test($to, @from);
387             next TO;
388         }
389     }
390 }
391
392 # For each range type, test additionally a character that folds to itself
393 add_test(":", ":");
394 add_test(chr utf8::unicode_to_native(0xF7), chr utf8::unicode_to_native(0xF7));
395 add_test(chr 0x2C7, chr 0x2C7);
396
397 # To cut down on the number of tests
398 my $has_tested_aa_above_latin1;
399 my $has_tested_latin1_aa;
400 my $has_tested_ascii_aa;
401 my $has_tested_l_above_latin1;
402 my $has_tested_above_latin1_l;
403 my $has_tested_ascii_l;
404 my $has_tested_above_latin1_d;
405 my $has_tested_ascii_d;
406 my $has_tested_non_latin1_d;
407 my $has_tested_above_latin1_a;
408 my $has_tested_ascii_a;
409 my $has_tested_non_latin1_a;
410
411 # For use by pairs() in generating combinations
412 sub prefix {
413     my $p = shift;
414     map [ $p, $_ ], @_
415 }
416
417 # Returns all ordered combinations of pairs of elements from the input array.
418 # It doesn't return pairs like (a, a), (b, b).  Change the slice to an array
419 # to do that.  This was just to have fewer tests.
420 sub pairs (@) {
421     #print STDERR __LINE__, ": ", join(" XXX ", map { sprintf "%04X", $_ } @_), "\n";
422     map { prefix $_[$_], @_[0..$_-1, $_+1..$#_] } 0..$#_
423 }
424
425 my $utf8_locale;
426
427 my @charsets = qw(d u a aa);
428 if (locales_enabled('LC_CTYPE')) {
429     my $current_locale = POSIX::setlocale( &POSIX::LC_CTYPE, "C") // "";
430     if ($current_locale eq 'C') {
431         use locale;
432
433         # Some implementations don't have the 128-255 range characters all
434         # mean nothing under the C locale (an example being VMS).  This is
435         # legal, but since we don't know what the right answers should be,
436         # skip the locale tests in that situation.
437         for my $i (128 .. 255) {
438             my $char = chr(utf8::unicode_to_native($i));
439             goto skip_C_locale_tests if uc($char) ne $char || lc($char) ne $char;
440         }
441         push @charsets, 'l';
442
443       skip_C_locale_tests:
444
445         # Look for utf8 locale.  We use the pseudo-modifier 'L' to indicate
446         # that we really want /l, but change to a UTF-8 locale.
447         $utf8_locale = find_utf8_ctype_locale();
448         push @charsets, 'L' if defined $utf8_locale;
449     }
450 }
451
452 # Finally ready to do the tests
453 foreach my $test (sort { numerically } keys %tests) {
454
455   my $previous_target;
456   my $previous_pattern;
457   my @pairs = pairs(sort numerically $test, @{$tests{$test}});
458
459   # Each fold can be viewed as a closure of all the characters that
460   # participate in it.  Look at each possible pairing from a closure, with the
461   # first member of the pair the target string to match against, and the
462   # second member forming the pattern.  Thus each fold member gets tested as
463   # the string, and the pattern with every other member in the opposite role.
464   while (my $pair = shift @pairs) {
465     my ($target, $pattern) = @$pair;
466
467     # When testing a char that doesn't fold, we can get the same
468     # permutation twice; so skip all but the first.
469     next if $previous_target
470             && $previous_target == $target
471             && $previous_pattern == $pattern;
472     ($previous_target, $previous_pattern) = ($target, $pattern);
473
474     # Each side may be either a single char or a string.  Extract each into an
475     # array (perhaps of length 1)
476     my @target, my @pattern;
477     @target = (ref $target) ? @$target : $target;
478     @pattern = (ref $pattern) ? @$pattern : $pattern;
479
480     # We are testing just folds to/from a single character.  If our pairs
481     # happens to generate multi/multi, skip.
482     next if @target > 1 && @pattern > 1;
483
484     # Get in hex form.
485     my @x_target = map { sprintf "\\x{%04X}", $_ } @target;
486     my @x_pattern = map { sprintf "\\x{%04X}", $_ } @pattern;
487
488     my $target_above_latin1 = grep { $_ > 255 } @target;
489     my $pattern_above_latin1 = grep { $_ > 255 } @pattern;
490     my $target_has_ascii = grep { utf8::native_to_unicode($_) < 128 } @target;
491     my $pattern_has_ascii = grep { utf8::native_to_unicode($_) < 128 } @pattern;
492     my $target_only_ascii = ! grep { utf8::native_to_unicode($_) > 127 } @target;
493     my $pattern_only_ascii = ! grep { utf8::native_to_unicode($_) > 127 } @pattern;
494     my $target_has_latin1 = grep { $_ < 256 } @target;
495     my $target_has_upper_latin1
496                 = grep { $_ < 256 && utf8::native_to_unicode($_) > 127 } @target;
497     my $pattern_has_upper_latin1
498                 = grep { $_ < 256 && utf8::native_to_unicode($_) > 127 } @pattern;
499     my $pattern_has_latin1 = grep { $_ < 256 } @pattern;
500     my $is_self = @target == 1 && @pattern == 1 && $target[0] == $pattern[0];
501
502     # We don't test multi-char folding into other multi-chars.  We are testing
503     # a code point that folds to or from other characters.  Find the single
504     # code point for diagnostic purposes.  (If both are single, choose the
505     # target string)
506     my $ord = @target == 1 ? $target[0] : $pattern[0];
507     my $progress = sprintf "%04X: \"%s\" and /%s/",
508                             $test,
509                             join("", @x_target),
510                             join("", @x_pattern);
511     #note $progress;
512
513     # Now grind out tests, using various combinations.
514     foreach my $charset (@charsets) {
515       my $charset_mod = lc $charset;
516       my $current_locale = "";
517       if ($charset_mod eq 'l') {
518         $current_locale = POSIX::setlocale(&POSIX::LC_CTYPE,
519                           ($charset eq 'L')
520                            ? $utf8_locale
521                            : 'C');
522         $current_locale = 'C locale' if $current_locale eq 'C';
523       }
524       $okays = 0;
525       $this_iteration = 0;
526
527       # To cut down somewhat on the enormous quantity of tests this currently
528       # runs, skip some for some of the character sets whose results aren't
529       # likely to differ from others.  But run all tests on the code points
530       # that don't fold, plus one other set in each range group.
531       if (! $is_self) {
532
533         # /aa should only affect things with folds in the ASCII range.  But, try
534         # it on one set in the other ranges just to make sure it doesn't break
535         # them.
536         if ($charset eq 'aa') {
537
538           # It may be that this $pair of code points to test are both
539           # non-ascii, but if either of them actually fold to ascii, that is
540           # suspect and should be tested.  So for /aa, use whether their folds
541           # are ascii or not
542           my $target_has_ascii = $target_has_ascii;
543           my $pattern_has_ascii = $pattern_has_ascii;
544           if (! $target_has_ascii) {
545             foreach my $cp (@target) {
546               if (exists $folds{$cp}
547                   && grep { utf8::native_to_unicode($_) < 128 } @{$folds{$cp}} )
548               {
549                   $target_has_ascii = 1;
550                   last;
551               }
552             }
553           }
554           if (! $pattern_has_ascii) {
555             foreach my $cp (@pattern) {
556               if (exists $folds{$cp}
557                   && grep { utf8::native_to_unicode($_) < 128 } @{$folds{$cp}} )
558               {
559                   $pattern_has_ascii = 1;
560                   last;
561               }
562             }
563           }
564
565           if (! $target_has_ascii && ! $pattern_has_ascii) {
566             if ($target_above_latin1 || $pattern_above_latin1) {
567               next if defined $has_tested_aa_above_latin1
568                       && $has_tested_aa_above_latin1 != $test;
569               $has_tested_aa_above_latin1 = $test;
570             }
571             next if defined $has_tested_latin1_aa
572                     && $has_tested_latin1_aa != $test;
573             $has_tested_latin1_aa = $test;
574           }
575           elsif ($target_only_ascii && $pattern_only_ascii) {
576
577               # And, except for one set just to make sure, skip tests
578               # where both elements in the pair are ASCII.  If one works for
579               # aa, the others are likely too.  This skips tests where the
580               # fold is from non-ASCII to ASCII, but this part of the test
581               # is just about the ASCII components.
582               next if defined $has_tested_ascii_l
583                       && $has_tested_ascii_l != $test;
584               $has_tested_ascii_l = $test;
585           }
586         }
587         elsif ($charset eq 'l') {
588
589           # For l, don't need to test beyond one set those things that are
590           # all above latin1, because unlikely to have different successes
591           # than /u.  But, for the same reason as described in the /aa above,
592           # it is suspect and should be tested, if either of the folds are to
593           # latin1.
594           my $target_has_latin1 = $target_has_latin1;
595           my $pattern_has_latin1 = $pattern_has_latin1;
596           if (! $target_has_latin1) {
597             foreach my $cp (@target) {
598               if (exists $folds{$cp}
599                   && grep { $_ < 256 } @{$folds{$cp}} )
600               {
601                 $target_has_latin1 = 1;
602                 last;
603               }
604             }
605           }
606           if (! $pattern_has_latin1) {
607             foreach my $cp (@pattern) {
608               if (exists $folds{$cp}
609                   && grep { $_ < 256 } @{$folds{$cp}} )
610               {
611                 $pattern_has_latin1 = 1;
612                 last;
613               }
614             }
615           }
616           if (! $target_has_latin1 && ! $pattern_has_latin1) {
617             next if defined $has_tested_above_latin1_l
618                     && $has_tested_above_latin1_l != $test;
619             $has_tested_above_latin1_l = $test;
620           }
621           elsif ($target_only_ascii && $pattern_only_ascii) {
622
623               # And, except for one set just to make sure, skip tests
624               # where both elements in the pair are ASCII.  This is
625               # essentially the same reasoning as above for /aa.
626               next if defined $has_tested_ascii_l
627                       && $has_tested_ascii_l != $test;
628               $has_tested_ascii_l = $test;
629           }
630         }
631         elsif ($charset eq 'd') {
632           # Similarly for d.  Beyond one test (besides self) each, we  don't
633           # test pairs that are both ascii; or both above latin1, or are
634           # combinations of ascii and above latin1.
635           if (! $target_has_upper_latin1 && ! $pattern_has_upper_latin1) {
636             if ($target_has_ascii && $pattern_has_ascii) {
637               next if defined $has_tested_ascii_d
638                       && $has_tested_ascii_d != $test;
639               $has_tested_ascii_d = $test
640             }
641             elsif (! $target_has_latin1 && ! $pattern_has_latin1) {
642               next if defined $has_tested_above_latin1_d
643                       && $has_tested_above_latin1_d != $test;
644               $has_tested_above_latin1_d = $test;
645             }
646             else {
647               next if defined $has_tested_non_latin1_d
648                       && $has_tested_non_latin1_d != $test;
649               $has_tested_non_latin1_d = $test;
650             }
651           }
652         }
653         elsif ($charset eq 'a') {
654           # Similarly for a.  This should match identically to /u, so wasn't
655           # tested at all until a bug was found that was thereby missed.
656           # As a compromise, beyond one test (besides self) each, we  don't
657           # test pairs that are both ascii; or both above latin1, or are
658           # combinations of ascii and above latin1.
659           if (! $target_has_upper_latin1 && ! $pattern_has_upper_latin1) {
660             if ($target_has_ascii && $pattern_has_ascii) {
661               next if defined $has_tested_ascii_a
662                       && $has_tested_ascii_a != $test;
663               $has_tested_ascii_a = $test
664             }
665             elsif (! $target_has_latin1 && ! $pattern_has_latin1) {
666               next if defined $has_tested_above_latin1_a
667                       && $has_tested_above_latin1_a != $test;
668               $has_tested_above_latin1_a = $test;
669             }
670             else {
671               next if defined $has_tested_non_latin1_a
672                       && $has_tested_non_latin1_a != $test;
673               $has_tested_non_latin1_a = $test;
674             }
675           }
676         }
677       }
678
679       foreach my $utf8_target (0, 1) {    # Both utf8 and not, for
680                                           # code points < 256
681         my $upgrade_target = "";
682
683         # These must already be in utf8 because the string to match has
684         # something above latin1.  So impossible to test if to not to be in
685         # utf8; and otherwise, no upgrade is needed.
686         next if $target_above_latin1 && ! $utf8_target;
687         $upgrade_target = ' utf8::upgrade($c);' if ! $target_above_latin1 && $utf8_target;
688
689         foreach my $utf8_pattern (0, 1) {
690           next if $pattern_above_latin1 && ! $utf8_pattern;
691
692           # Our testing of 'l' uses the POSIX locale, which is ASCII-only
693           my $uni_semantics = $charset ne 'l' && ($utf8_target || $charset eq 'u' || $charset eq 'L' || ($charset eq 'd' && $utf8_pattern) || $charset =~ /a/);
694           my $upgrade_pattern = "";
695           $upgrade_pattern = ' utf8::upgrade($p);' if ! $pattern_above_latin1 && $utf8_pattern;
696
697           my $lhs = join "", @x_target;
698           my $lhs_str = eval qq{"$lhs"}; fail($@) if $@;
699           my @rhs = @x_pattern;
700           my $rhs = join "", @rhs;
701           my $should_fail = (! $uni_semantics && $ord < 256 && ! $is_self && utf8::native_to_unicode($ord) >= 128)
702                             || ($charset eq 'aa' && $target_has_ascii != $pattern_has_ascii)
703                             || ($charset eq 'l' && $target_has_latin1 != $pattern_has_latin1);
704
705           # Do simple tests of referencing capture buffers, named and
706           # numbered.
707           my $op = '=~';
708           $op = '!~' if $should_fail;
709
710           my $todo = 0;  # No longer any todo's
711           my $eval = "my \$c = \"$lhs$rhs\"; my \$p = qr/(?$charset_mod:^($rhs)\\1\$)/i;$upgrade_target$upgrade_pattern \$c $op \$p";
712           run_test($eval, $todo, ($charset_mod eq 'l'), "");
713
714           $eval = "my \$c = \"$lhs$rhs\"; my \$p = qr/(?$charset_mod:^(?<grind>$rhs)\\k<grind>\$)/i;$upgrade_target$upgrade_pattern \$c $op \$p";
715           run_test($eval, $todo, ($charset_mod eq 'l'), "");
716
717           if ($lhs ne $rhs) {
718             $eval = "my \$c = \"$rhs$lhs\"; my \$p = qr/(?$charset_mod:^($rhs)\\1\$)/i;$upgrade_target$upgrade_pattern \$c $op \$p";
719             run_test($eval, "", ($charset_mod eq 'l'), "");
720
721             $eval = "my \$c = \"$rhs$lhs\"; my \$p = qr/(?$charset_mod:^(?<grind>$rhs)\\k<grind>\$)/i;$upgrade_target$upgrade_pattern \$c $op \$p";
722             run_test($eval, "", ($charset_mod eq 'l'), "");
723           }
724
725           # See if works on what could be a simple trie.
726           my $alternate;
727           {
728             # Keep the alternate | branch the same length as the tested one so
729             # that it's length doesn't influence things
730             my $evaled = eval "\"$rhs\"";   # Convert e.g. \x{foo} into its
731                                             # chr equivalent
732             use bytes;
733             $alternate = 'q' x length $evaled;
734           }
735           $eval = "my \$c = \"$lhs\"; my \$p = qr/$rhs|$alternate/i$charset_mod;$upgrade_target$upgrade_pattern \$c $op \$p";
736           run_test($eval, "", ($charset_mod eq 'l'), "");
737
738           # Check that works when the folded character follows something that
739           # is quantified.  This test knows the regex code internals to the
740           # extent that it knows this is a potential problem, and that there
741           # are three different types of quantifiers generated: 1) The thing
742           # being quantified matches a single character; 2) it matches more
743           # than one character, but is fixed width; 3) it can match a variable
744           # number of characters.  (It doesn't know that case 3 shouldn't
745           # matter, since it doesn't do anything special for the character
746           # following the quantifier; nor that some of the different
747           # quantifiers execute the same underlying code, as these tests are
748           # quick, and this insulates these tests from changes in the
749           # implementation.)
750           for my $quantifier ('?', '??', '*', '*?', '+', '+?', '{1,2}', '{1,2}?') {
751             $eval = "my \$c = \"_$lhs\"; my \$p = qr/(?$charset_mod:.$quantifier$rhs)/i;$upgrade_target$upgrade_pattern \$c $op \$p";
752             run_test($eval, "", ($charset_mod eq 'l'), "");
753             $eval = "my \$c = \"__$lhs\"; my \$p = qr/(?$charset_mod:(?:..)$quantifier$rhs)/i;$upgrade_target$upgrade_pattern \$c $op \$p";
754             run_test($eval, "", ($charset_mod eq 'l'), "");
755             $eval = "my \$c = \"__$lhs\"; my \$p = qr/(?$charset_mod:(?:.|\\R)$quantifier$rhs)/i;$upgrade_target$upgrade_pattern \$c $op \$p";
756             run_test($eval, "", ($charset_mod eq 'l'), "");
757           }
758
759           foreach my $bracketed (0, 1) {   # Put rhs in [...], or not
760             next if $bracketed && @pattern != 1;    # bracketed makes these
761                                                     # or's instead of a sequence
762             foreach my $optimize_bracketed (0, 1) {
763               next if $optimize_bracketed && ! $bracketed;
764               foreach my $inverted (0,1) {
765                   next if $inverted && ! $bracketed;  # inversion only valid
766                                                       # in [^...]
767                   next if $inverted && @target != 1;  # [perl #89750] multi-char
768                                                       # not valid in [^...]
769
770                 # In some cases, add an extra character that doesn't fold, and
771                 # looks ok in the output.
772                 my $extra_char = "_";
773                 foreach my $prepend ("", $extra_char) {
774                   foreach my $append ("", $extra_char) {
775
776                     # Assemble the rhs.  Put each character in a separate
777                     # bracketed if using charclasses.  This creates a stress on
778                     # the code to span a match across multiple elements
779                     my $rhs = "";
780                     foreach my $rhs_char (@rhs) {
781                         $rhs .= '[' if $bracketed;
782                         $rhs .= '^' if $inverted;
783                         $rhs .=  $rhs_char;
784
785                         # Add a character to the class, so class doesn't get
786                         # optimized out, unless we are testing that optimization
787                         $rhs .= '_' if $optimize_bracketed;
788                         $rhs .= ']' if $bracketed;
789                     }
790
791                     # Add one of: no capturing parens
792                     #             a single set
793                     #             a nested set
794                     # Use quantifiers and extra variable width matches inside
795                     # them to keep some optimizations from happening
796                     foreach my $parend (0, 1, 2) {
797                       my $interior = (! $parend)
798                                       ? $rhs
799                                       : ($parend == 1)
800                                           ? "(${rhs},?)"
801                                           : "((${rhs})+,?)";
802                       foreach my $quantifier ("", '?', '*', '+', '{1,3}') {
803
804                         # Perhaps should be TODOs, as are unimplemented, but
805                         # maybe will never be implemented
806                         next if @pattern != 1 && $quantifier;
807
808                         # A ? or * quantifier normally causes the thing to be
809                         # able to match a null string
810                         my $quantifier_can_match_null = $quantifier eq '?'
811                                                      || $quantifier eq '*';
812
813                         # But since we only quantify the last character in a
814                         # multiple fold, the other characters will have width,
815                         # except if we are quantifying the whole rhs
816                         my $can_match_null = $quantifier_can_match_null
817                                              && (@rhs == 1 || $parend);
818
819                         foreach my $l_anchor ("", '^') { # '\A' didn't change
820                                                          # result)
821                           foreach my $r_anchor ("", '$') { # '\Z', '\z' didn't
822                                                            # change result)
823                             # The folded part can match the null string if it
824                             # isn't required to have width, and there's not
825                             # something on one or both sides that force it to.
826                             my $both_sides = ($l_anchor && $r_anchor)
827                                               || ($l_anchor && $append)
828                                               || ($r_anchor && $prepend)
829                                               || ($prepend && $append);
830                             my $must_match = ! $can_match_null || $both_sides;
831                             # for performance, but doing this missed many failures
832                             #next unless $must_match;
833                             my $quantified = "(?$charset_mod:$l_anchor$prepend$interior${quantifier}$append$r_anchor)";
834                             my $op;
835                             if ($must_match && $should_fail)  {
836                                 $op = 0;
837                             } else {
838                                 $op = 1;
839                             }
840                             $op = ! $op if $must_match && $inverted;
841
842                             if ($inverted && @target > 1) {
843                               # When doing an inverted match against a
844                               # multi-char target, and there is not something on
845                               # the left to anchor the match, if it shouldn't
846                               # succeed, skip, as what will happen (when working
847                               # correctly) is that it will match the first
848                               # position correctly, and then be inverted to not
849                               # match; then it will go to the second position
850                               # where it won't match, but get inverted to match,
851                               # and hence succeeding.
852                               next if ! ($l_anchor || $prepend) && ! $op;
853
854                               # Can't ever match for latin1 code points non-uni
855                               # semantics that have a inverted multi-char fold
856                               # when there is something on both sides and the
857                               # quantifier isn't such as to span the required
858                               # width, which is 2 or 3.
859                               $op = 0 if $ord < 255
860                                         && ! $uni_semantics
861                                         && $both_sides
862                                         && ( ! $quantifier || $quantifier eq '?')
863                                         && $parend < 2;
864
865                               # Similarly can't ever match when inverting a
866                               # multi-char fold for /aa and the quantifier
867                               # isn't sufficient to allow it to span to both
868                               # sides.
869                               $op = 0 if $target_has_ascii
870                                          && $charset eq 'aa'
871                                          && $both_sides
872                                          && ( ! $quantifier || $quantifier eq '?')
873                                          && $parend < 2;
874
875                               # Or for /l
876                               $op = 0 if $target_has_latin1 && $charset eq 'l'
877                                       && $both_sides
878                                       && ( ! $quantifier || $quantifier eq '?')
879                                       && $parend < 2;
880                             }
881
882
883                             my $desc = "";
884                             if ($charset_mod eq 'l') {
885                                 $desc .= 'setlocale(LC_CTYPE, "'
886                                         . POSIX::setlocale(&POSIX::LC_CTYPE)
887                                         . '"); '
888                             }
889                             $desc .= "my \$c = \"$prepend$lhs$append\"; "
890                                     . "my \$p = qr/$quantified/i;"
891                                     . "$upgrade_target$upgrade_pattern "
892                                     . "\$c " . ($op ? "=~" : "!~") . " \$p; ";
893                             if ($DEBUG) {
894                               $desc .= (
895                               "; uni_semantics=$uni_semantics, "
896                               . "should_fail=$should_fail, "
897                               . "bracketed=$bracketed, "
898                               . "prepend=$prepend, "
899                               . "append=$append, "
900                               . "parend=$parend, "
901                               . "quantifier=$quantifier, "
902                               . "l_anchor=$l_anchor, "
903                               . "r_anchor=$r_anchor; "
904                               . "pattern_above_latin1=$pattern_above_latin1; "
905                               . "utf8_pattern=$utf8_pattern"
906                               );
907                             }
908
909                             my $c = "$prepend$lhs_str$append";
910                             my $p = qr/$quantified/i;
911                             utf8::upgrade($c) if length($upgrade_target);
912                             utf8::upgrade($p) if length($upgrade_pattern);
913                             my $res = $op ? ($c =~ $p): ($c !~ $p);
914
915                             if (!$res || $list_all_tests) {
916                               # Failed or debug; output the result
917                               $count++;
918                               ok($res, "test $count - $desc");
919                             } else {
920                               # Just count the test as passed
921                               $okays++;
922                             }
923                             $this_iteration++;
924                           }
925                         }
926                       }
927                     }
928                   }
929                 }
930               }
931             }
932           }
933         }
934       }
935       unless($list_all_tests) {
936         $count++;
937         is $okays, $this_iteration, "$okays subtests ok for"
938           . " /$charset_mod"
939           . (($charset_mod eq 'l') ? " ($current_locale)" : "")
940           . ', target="' . join("", @x_target) . '",'
941           . ' pat="' . join("", @x_pattern) . '"';
942       }
943     }
944   }
945 }
946
947 plan($count);
948
949 1