#!/usr/bin/env perl6 use Test; my %prop-data = NAME => 'name', Line_Break => 'str', General_Category => 'str' ; my %expected-loses = "extracted/DerivedGeneralCategory.txt" => { General_Category => { Cn => 21, }, }, # Many codepoints return XX instead of ID. These codepoints are undefined, but unicode # spec has specified that they should regardless be ID "LineBreak.txt" => { Line_Break => { ID => 62579, PR => 15 } } ; # Number of wins/loses for each property value my (%LOSES, %WINS); # %( Property_Name => Filename => Property_Value => Num_Wins/Loses ) my %FAILED; # %( Property_Name => Filename => [ 10, 20, 30, 44 ] ) List of failed codepoints my %WIN-NUM; # %( Property_Name => Filename => Total_Num_Win/Lose ) my %LOSE-NUM; use nqp; sub test-file (IO::Path $folder is copy, Str:D $file-name, Str:D $uniprop, :$answer-column is copy) is export { note "File: $file-name" if $*DEBUG; $answer-column = 1 if !defined $answer-column; $folder = $*CWD.child("t/3rdparty/Unicode/15.0.0") if !$folder; %LOSE-NUM{$file-name}{$uniprop} = 0 if %LOSE-NUM{$file-name}{$uniprop}:!exists; %WIN-NUM{$file-name}{$uniprop} = 0 if %WIN-NUM{$file-name}{$uniprop}:!exists; my IO::Path:D $file = $folder.child: $file-name; die $uniprop if %prop-data{$uniprop}:!exists; my Str:D $call = %prop-data{$uniprop} orelse die "Property type is not set. Please set to 'str', 'int', or 'name'"; my int $propcode = $call eq 'name' ?? 0 !! nqp::unipropcode($uniprop); for $file.lines.grep({ nqp::isne_s($_, '') && !nqp::eqat($_, '#', 0) }) -> $line { my str @array = $uniprop eq 'NAME' ?? nqp::split(';', $line) !! $line.split([';', "#"]); my str $range = @array[0].trim; my str $value = @array[$answer-column].trim; my str @ranges = nqp::split("..", $range); my int $lowest = hex(@ranges[0]); my int $highest = 1 < @ranges.elems ?? hex(@ranges[1]) !! $lowest; if $propcode { for $lowest..$highest { if $value eq ($call eq 'str' ?? nqp::getuniprop_str($_, $propcode) !! ($call eq 'int' ?? nqp::getuniprop_int($_, $propcode) !! die "\$call is set to '$call'\nIt should be either 'int', 'str' or 'name'") ) { correct($value, $_, $uniprop, $file-name); } else { if $*DEBUG { my $actual = $call eq 'str' ?? nqp::getuniprop_str($_, $propcode) !! nqp::getuniprop_int($_, $propcode); wrong($value, "cp $_ expected $value actually $actual", $uniprop, $file-name); } else { wrong($value, $_, $uniprop, $file-name); } } } } else { check-name($lowest, $value, $file-name); } CATCH { die "$_\nError: Line: $line\n\@array: @array.raku()" } } my Bool:D $has-tested = False; for %LOSES{$file-name}{$uniprop}.keys.sort -> $pvalue { $has-tested = True; %expected-loses{$file-name}{$uniprop}{$pvalue} = 0 if %expected-loses{$file-name}{$uniprop}:!exists or %expected-loses{$file-name}{$uniprop}{$pvalue}:!exists; todo "Expecting %expected-loses{$file-name}{$uniprop}{$pvalue} failures from $uniprop=$pvalue", 1 if %LOSES{$file-name}{$uniprop}{$pvalue} < %expected-loses{$file-name}{$uniprop}{$pvalue}; ok %LOSES{$file-name}{$uniprop}{$pvalue} <= %expected-loses{$file-name}{$uniprop}{$pvalue}, format-test-text($uniprop, $file-name, %WINS{$file-name}{$uniprop}{$pvalue}, %LOSES{$file-name}{$uniprop}{$pvalue}, $pvalue, %expected-loses{$file-name}{$uniprop}{$pvalue}); } for %expected-loses{$file-name}{$uniprop}.keys.sort -> $pvalue { next if %LOSES{$file-name}{$uniprop}{$pvalue}:exists; $has-tested = True; %LOSES{$file-name}{$uniprop}{$pvalue} = 0 if %LOSES{$file-name}{$uniprop}{$pvalue}:!exists; todo "Expecting %expected-loses{$file-name}{$uniprop}{$pvalue} failures from $uniprop=$pvalue", 1 if %LOSES{$file-name}{$uniprop}{$pvalue} < %expected-loses{$file-name}{$uniprop}{$pvalue}; ok(%LOSES{$file-name}{$uniprop}{$pvalue} <= %expected-loses{$file-name}{$uniprop}{$pvalue}, format-test-text($uniprop, $file-name, %WINS{$file-name}{$uniprop}{$pvalue}, %LOSES{$file-name}{$uniprop}{$pvalue}, $pvalue, %expected-loses{$file-name}{$uniprop}{$pvalue})); } if !$has-tested { ok True, format-test-text($uniprop, $file-name, %WIN-NUM{$file-name}{$uniprop}, %LOSE-NUM{$file-name}{$uniprop}); } if $*DEBUG { my @list = %FAILED{$file-name}{$uniprop}.list; my @debug-out; while @list { @debug-out.push: @list.splice(0, 10).join(', '); } note "\%FAILED\{$file-name\}\{$uniprop\}:\n", @debug-out.join("\n").indent(4); note "Property: $uniprop win %WIN-NUM{$file-name}{$uniprop} lose %LOSE-NUM{$file-name}{$uniprop} percent: " ~ (%LOSE-NUM{$file-name}{$uniprop} == 0 ?? 1 !! %LOSE-NUM{$file-name}{$uniprop}/%WIN-NUM{$file-name}{$uniprop}) * 100; } } sub format-test-text ($uniprop, $file-name, $correct, $wrong, Str:D $pvalue = "", Int $looking-for?) { "Property: $uniprop" ~ ($pvalue ?? "=$pvalue" !! "") ~ " from file: $file-name (Correct: $correct Wrong: $wrong)" ~ ($looking-for ?? ". Todo'd if < $looking-for failures." !! "") } sub ends-with (\a, \b) { nqp::eqat(a, b, nqp::chars(a) - nqp::chars(b)) } sub check-name (Int:D $code, Str:D $name, Str:D $file-name) { state %firsts; my str $expected = $name; my str $uniname = nqp::getuniname($code); if nqp::eqat($expected, '<', 0) { if nqp::eqat($expected, '') { $expected = nqp::substr($expected, 0, nqp::chars($expected) - nqp::chars(", First>")) ~ ">"; %firsts{$expected} = $code; } elsif ends-with($expected, ', Last>') { $expected = nqp::substr($expected, 0, nqp::chars($expected) - nqp::chars(", Last>")) ~ ">"; die "\%firsts{$expected} does not exist" unless %firsts{$expected}; my $ex = $expected; if nqp::eqat($expected, "') { $expected = ''; } elsif $expected.ends-with('Surrogate>') { $expected = ''; } for %firsts{$ex}..$code -> $curr-code { $uniname = nqp::getuniname($curr-code); my str $this-expected = get-hex-name($expected, $curr-code); #say "before $expected after $this-expected"; nqp::iseq_s($uniname, $this-expected) ?? correct("", $curr-code, "NAME", $file-name) !! wrong("", $curr-code, "NAME", $file-name); } } elsif nqp::iseq_s($expected, "") { $expected = get-hex-name($expected, $code); } else { die $expected; } } else { nqp::iseq_s($uniname, $expected) ?? correct("", $code, "NAME", $file-name) !! wrong($expected, $code, "NAME", $file-name); } } sub get-hex-name ($name is copy, $code is raw) { my $has-brack = nqp::eqat($name, '>', nqp::chars($name) - 1); $name = nqp::substr($name, 0, nqp::chars($name) - 1) if $has-brack; my str $base = nqp::base_I(nqp::decont($code), 16); my int $diff = nqp::sub_i(4, nqp::chars($base)); if nqp::islt_i(0, $diff) { $base = nqp::concat(nqp::x('0', $diff), $base); } nqp::concat( nqp::concat( nqp::concat($name, '-'), $base), $has-brack ?? '>' !! ''); } sub correct ($value, $code, $uniprop, $file-name) { %WINS{$file-name}{$uniprop}{$value}++; %WIN-NUM{$file-name}{$uniprop}++; } sub wrong ($value, $code, $uniprop, $file-name) { %LOSES{$file-name}{$uniprop}{$value}++; %FAILED{$file-name}{$uniprop}.push: $code; %LOSE-NUM{$file-name}{$uniprop}++; } sub hex (Str:D $string) { nqp::radix_I(16, $string, 0, 0, Int)[0] } # vim: expandtab shiftwidth=4