15759b3d2Safresh1#!perl -w 25759b3d2Safresh1use strict; 35759b3d2Safresh1use Storable "dclone"; 45759b3d2Safresh1use Test::More; 55759b3d2Safresh1 65759b3d2Safresh1my $version = int(($]-5)*1000); 75759b3d2Safresh1 85759b3d2Safresh1$version >= 8 95759b3d2Safresh1 or plan skip_all => "regexps not supported before 5.8"; 105759b3d2Safresh1 115759b3d2Safresh1my @tests; 125759b3d2Safresh1while (<DATA>) { 135759b3d2Safresh1 chomp; 145759b3d2Safresh1 next if /^\s*#/ || !/\S/; 155759b3d2Safresh1 my ($range, $code, $match, $name) = split /\s*;\s*/; 165759b3d2Safresh1 defined $name or die "Bad test line"; 175759b3d2Safresh1 my $ascii_only = $range =~ s/A//; 185759b3d2Safresh1 next if $ascii_only and ord("A") != 65; 195759b3d2Safresh1 if ($range =~ /^(\d+)-$/) { 205759b3d2Safresh1 next if $version < $1 215759b3d2Safresh1 } 225759b3d2Safresh1 elsif ($range =~ /^-(\d+)$/) { 235759b3d2Safresh1 next if $version > $1 245759b3d2Safresh1 } 255759b3d2Safresh1 elsif ($range =~ /^(\d+)-(\d+)$/) { 265759b3d2Safresh1 next if $version < $1 || $version > $2; 275759b3d2Safresh1 } 285759b3d2Safresh1 elsif ($range ne "-") { 295759b3d2Safresh1 die "Invalid version range $range for $name"; 305759b3d2Safresh1 } 315759b3d2Safresh1 my @match = split /\s*,\s*/, $match; 325759b3d2Safresh1 for my $m (@match) { 335759b3d2Safresh1 my $not = $m =~ s/^!//; 345759b3d2Safresh1 my $cmatch = eval $m; 355759b3d2Safresh1 die if $@; 365759b3d2Safresh1 push @tests, [ $code, $not, $cmatch, $m, $name ]; 375759b3d2Safresh1 } 385759b3d2Safresh1} 395759b3d2Safresh1 40*de8cc8edSafresh1plan tests => 10 + 3*scalar(@tests); 415759b3d2Safresh1 425759b3d2Safresh1SKIP: 435759b3d2Safresh1{ 445759b3d2Safresh1 $version >= 14 && $version < 20 455759b3d2Safresh1 or skip "p introduced in 5.14, pointless from 5.20", 4; 465759b3d2Safresh1 my $q1 = eval "qr/b/p"; 475759b3d2Safresh1 my $q2 = eval "qr/b/"; 485759b3d2Safresh1 my $c1 = dclone($q1); 495759b3d2Safresh1 my $c2 = dclone($q2); 505759b3d2Safresh1 ok("abc" =~ $c1, "abc matches $c1"); 515759b3d2Safresh1 is(${^PREMATCH}, "a", "check p worked"); 525759b3d2Safresh1 ok("cba" =~ $c2, "cba matches $c2"); 535759b3d2Safresh1 isnt(${^PREMATCH}, "c", "check no p worked"); 545759b3d2Safresh1} 555759b3d2Safresh1 565759b3d2Safresh1SKIP: 575759b3d2Safresh1{ 585759b3d2Safresh1 $version >= 24 595759b3d2Safresh1 or skip "n introduced in 5.22", 4; 605759b3d2Safresh1 my $c1 = dclone(eval "qr/(\\w)/"); 615759b3d2Safresh1 my $c2 = dclone(eval "qr/(\\w)/n"); 625759b3d2Safresh1 ok("a" =~ $c1, "a matches $c1"); 635759b3d2Safresh1 is($1, "a", "check capturing preserved"); 645759b3d2Safresh1 ok("b" =~ $c2, "b matches $c2"); 655759b3d2Safresh1 isnt($1, "b", "check non-capturing preserved"); 665759b3d2Safresh1} 675759b3d2Safresh1 685759b3d2Safresh1SKIP: 695759b3d2Safresh1{ 705759b3d2Safresh1 $version >= 8 715759b3d2Safresh1 or skip "Cannot retrieve before 5.8", 1; 725759b3d2Safresh1 my $x; 735759b3d2Safresh1 my $re = qr/a(?{ $x = 1 })/; 745759b3d2Safresh1 use re 'eval'; 755759b3d2Safresh1 ok(!eval { dclone($re) }, "should fail to clone, even with use re 'eval'"); 765759b3d2Safresh1} 775759b3d2Safresh1 78*de8cc8edSafresh1is(ref(dclone(bless qr//, "Foo")), "Foo", "check reblessed regexps"); 79*de8cc8edSafresh1 805759b3d2Safresh1for my $test (@tests) { 815759b3d2Safresh1 my ($code, $not, $match, $matchc, $name) = @$test; 825759b3d2Safresh1 my $qr = eval $code; 835759b3d2Safresh1 die "Could not compile $code: $@" if $@; 845759b3d2Safresh1 if ($not) { 855759b3d2Safresh1 unlike($match, $qr, "$name: pre(not) match $matchc"); 865759b3d2Safresh1 } 875759b3d2Safresh1 else { 885759b3d2Safresh1 like($match, $qr, "$name: prematch $matchc"); 895759b3d2Safresh1 } 905759b3d2Safresh1 my $qr2 = dclone($qr); 915759b3d2Safresh1 if ($not) { 925759b3d2Safresh1 unlike($match, $qr2, "$name: (not) match $matchc"); 935759b3d2Safresh1 } 945759b3d2Safresh1 else { 955759b3d2Safresh1 like($match, $qr2, "$name: match $matchc"); 965759b3d2Safresh1 } 975759b3d2Safresh1 985759b3d2Safresh1 # this is unlikely to be a problem, but make sure regexps are frozen sanely 995759b3d2Safresh1 # as part of a data structure 1005759b3d2Safresh1 my $a2 = dclone([ $qr ]); 1015759b3d2Safresh1 if ($not) { 1025759b3d2Safresh1 unlike($match, $a2->[0], "$name: (not) match $matchc (array)"); 1035759b3d2Safresh1 } 1045759b3d2Safresh1 else { 1055759b3d2Safresh1 like($match, $a2->[0], "$name: match $matchc (array)"); 1065759b3d2Safresh1 } 1075759b3d2Safresh1} 1085759b3d2Safresh1 1095759b3d2Safresh1__DATA__ 1105759b3d2Safresh1# semi-colon separated: 1115759b3d2Safresh1# perl version range; regexp qr; match string; name 1125759b3d2Safresh1# - version range is PERL_VERSION, ie 22 for 5.22 as from-to with both from 1135759b3d2Safresh1# and to optional (so "-" is all versions. 1145759b3d2Safresh1# - match string is , separated match strings 1155759b3d2Safresh1# - if a match string starts with ! it mustn't match, otherwise it must 1165759b3d2Safresh1# spaces around the commas ignored. 1175759b3d2Safresh1# The initial "!" is stripped and the remainder treated as perl code to define 1185759b3d2Safresh1# the string to (not) be matched 1195759b3d2Safresh1-; qr/foo/ ; "foo",!"fob" ; simple 1205759b3d2Safresh1-; qr/foo/i ; "foo","FOO",!"fob" ; simple case insensitive 1215759b3d2Safresh1-; qr/f o o/x ; "foo", !"f o o" ; /x 1225759b3d2Safresh1-; qr(a/b) ; "a/b" ; alt quotes 1235759b3d2Safresh1A-; qr(\x2E) ; ".", !"a" ; \x2E - hex meta 1245759b3d2Safresh1-; qr/\./ ; "." , !"a" ; \. - backslash meta 1255759b3d2Safresh18- ; qr/\x{100}/ ; "\x{100}" ; simple unicode 126*de8cc8edSafresh1A12- ; qr/fss/i ; "f\xDF\x{101}" ; case insensive unicode promoted 127*de8cc8edSafresh1A22-; qr/fss/ui ; "f\xDF" ; case insensitive unicode SS /iu 128*de8cc8edSafresh1A22-; qr/fss/aai ; !"f\xDF" ; case insensitive unicode SS /iaa 129*de8cc8edSafresh1A22-; qr/f\w/a ; "fo", !"f\xff" ; simple /a flag 130