1898184e3Ssthen#!perl -w 2898184e3Ssthenuse strict; 3898184e3Ssthen 4898184e3Ssthenuse Test::More; 5898184e3Ssthenuse Config; 6898184e3Ssthenuse XS::APItest; 791f110e0Safresh1no warnings 'experimental::smartmatch'; 8898184e3Ssthenuse constant TRUTH => '0 but true'; 9898184e3Ssthen 10898184e3Ssthen# Tests for grok_number. Not yet comprehensive. 11898184e3Ssthenforeach my $leader ('', ' ', ' ') { 12898184e3Ssthen foreach my $trailer ('', ' ', ' ') { 13898184e3Ssthen foreach ((map {"0" x $_} 1 .. 12), 14898184e3Ssthen (map {("0" x $_) . "1"} 0 .. 12), 15898184e3Ssthen (map {"1" . ("0" x $_)} 1 .. 9), 16898184e3Ssthen (map {1 << $_} 0 .. 31), 17898184e3Ssthen (map {1 << $_} 0 .. 31), 18898184e3Ssthen (map {0xFFFFFFFF >> $_} reverse (0 .. 31)), 19898184e3Ssthen ) { 20898184e3Ssthen foreach my $sign ('', '-', '+') { 21898184e3Ssthen my $string = $leader . $sign . $_ . $trailer; 22898184e3Ssthen my ($flags, $value) = grok_number($string); 23898184e3Ssthen is($flags & IS_NUMBER_IN_UV, IS_NUMBER_IN_UV, 24898184e3Ssthen "'$string' is a UV"); 25898184e3Ssthen is($flags & IS_NUMBER_NEG, $sign eq '-' ? IS_NUMBER_NEG : 0, 26898184e3Ssthen "'$string' sign"); 27898184e3Ssthen is($value, abs $string, "value is correct"); 28898184e3Ssthen } 29898184e3Ssthen } 30898184e3Ssthen 31898184e3Ssthen { 32898184e3Ssthen my (@UV, @NV); 339f11ffb7Safresh1 if ($Config{ivsize} == 4) { 34898184e3Ssthen @UV = qw(429496729 4294967290 4294967294 4294967295); 35898184e3Ssthen @NV = qw(4294967296 4294967297 4294967300 4294967304); 369f11ffb7Safresh1 } elsif ($Config{ivsize} == 8) { 37898184e3Ssthen @UV = qw(1844674407370955161 18446744073709551610 38898184e3Ssthen 18446744073709551614 18446744073709551615); 39898184e3Ssthen @NV = qw(18446744073709551616 18446744073709551617 40898184e3Ssthen 18446744073709551620 18446744073709551624); 419f11ffb7Safresh1 } else { die "Unknown IV size $Config{ivsize}" } 42898184e3Ssthen foreach (@UV) { 43898184e3Ssthen my $string = $leader . $_ . $trailer; 44898184e3Ssthen my ($flags, $value) = grok_number($string); 45898184e3Ssthen is($flags & IS_NUMBER_IN_UV, IS_NUMBER_IN_UV, 46898184e3Ssthen "'$string' is a UV"); 47898184e3Ssthen is($value, abs $string, "value is correct"); 48898184e3Ssthen } 49898184e3Ssthen foreach (@NV) { 50898184e3Ssthen my $string = $leader . $_ . $trailer; 51898184e3Ssthen my ($flags, $value) = grok_number($string); 52898184e3Ssthen is($flags & IS_NUMBER_IN_UV, 0, "'$string' is an NV"); 53898184e3Ssthen is($value, undef, "value is correct"); 54898184e3Ssthen } 55898184e3Ssthen } 56898184e3Ssthen 57898184e3Ssthen my $string = $leader . TRUTH . $trailer; 58898184e3Ssthen my ($flags, $value) = grok_number($string); 59898184e3Ssthen 60898184e3Ssthen if ($string eq TRUTH) { 61898184e3Ssthen is($flags & IS_NUMBER_IN_UV, IS_NUMBER_IN_UV, "'$string' is a UV"); 62898184e3Ssthen is($value, 0); 63898184e3Ssthen } else { 64898184e3Ssthen is($flags, 0, "'$string' is not a number"); 65898184e3Ssthen is($value, undef); 66898184e3Ssthen } 67898184e3Ssthen } 68898184e3Ssthen} 69898184e3Ssthen 70b8851fccSafresh1# format tests 71*eac174f2Safresh1my @groks = ( 72b8851fccSafresh1 # input, in flags, out uv, out flags 73*eac174f2Safresh1 (map { 74*eac174f2Safresh1 # Expect the same answer with or without SCAN_TRAILING 75*eac174f2Safresh1 [ $_->[0], 0, $_->[1], $_->[2] ], 76*eac174f2Safresh1 [ $_->[0], PERL_SCAN_TRAILING, $_->[1], $_->[2] ], 77*eac174f2Safresh1 } ( 78*eac174f2Safresh1 [ "1", 1, IS_NUMBER_IN_UV ], 79*eac174f2Safresh1 [ "3.1", 3, IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT ], 80*eac174f2Safresh1 [ "3e5", undef, IS_NUMBER_NOT_INT ], 81*eac174f2Safresh1 [ "Inf", undef, IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT ], 82*eac174f2Safresh1 [ "nan", undef, IS_NUMBER_NAN | IS_NUMBER_NOT_INT ], 83*eac174f2Safresh1 [ "nanq", undef, IS_NUMBER_NAN | IS_NUMBER_NOT_INT ], 84*eac174f2Safresh1 [ "nan(123)", undef, IS_NUMBER_NAN | IS_NUMBER_NOT_INT ], 85*eac174f2Safresh1 # trailing whitespace is ok though 86*eac174f2Safresh1 [ "1 ", 1, IS_NUMBER_IN_UV ], 87*eac174f2Safresh1 [ "nan(123 ) ", undef, IS_NUMBER_NAN | IS_NUMBER_NOT_INT ], 88*eac174f2Safresh1 )), 89*eac174f2Safresh1 (map { 90*eac174f2Safresh1 # Trailing stuff should cause failure unless SCAN_TRAILING 91*eac174f2Safresh1 [ $_->[0], 0, undef, 0 ], 92*eac174f2Safresh1 [ $_->[0], PERL_SCAN_TRAILING, $_->[1], $_->[2] | IS_NUMBER_TRAILING ], 93*eac174f2Safresh1 } ( 94*eac174f2Safresh1 [ "1x", 1, IS_NUMBER_IN_UV ], 95*eac174f2Safresh1 [ "3.1a", 3, IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT ], 96*eac174f2Safresh1 [ "3e", 3, IS_NUMBER_IN_UV ], 97*eac174f2Safresh1 [ "3e+", 3, IS_NUMBER_IN_UV ], 98*eac174f2Safresh1 [ "Infin", undef, IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT ], 99*eac174f2Safresh1 [ "nanx", undef, IS_NUMBER_NAN | IS_NUMBER_NOT_INT ], 100*eac174f2Safresh1 [ "nan(123 x)", undef, IS_NUMBER_NAN | IS_NUMBER_NOT_INT ], 101*eac174f2Safresh1 [ "nan(123) x", undef, IS_NUMBER_NAN | IS_NUMBER_NOT_INT ], 102*eac174f2Safresh1 # TODO: this should probably be in the preceding section, parsed 103*eac174f2Safresh1 # as invalid with or without SCAN_TRAILING. See GH #19464. 104*eac174f2Safresh1 [ "In", undef, 0 ], 105*eac174f2Safresh1 )), 106b8851fccSafresh1); 107b8851fccSafresh1 1089f11ffb7Safresh1my $non_ieee_fp = ($Config{doublekind} == 9 || 1099f11ffb7Safresh1 $Config{doublekind} == 10 || 1109f11ffb7Safresh1 $Config{doublekind} == 11); 1119f11ffb7Safresh1 1129f11ffb7Safresh1if ($non_ieee_fp) { 1139f11ffb7Safresh1 @groks = grep { $_->[0] !~ /^(?:inf|nan)/i } @groks; 1149f11ffb7Safresh1} 1159f11ffb7Safresh1 116b8851fccSafresh1for my $grok (@groks) { 117b8851fccSafresh1 my ($out_flags, $out_uv) = grok_number_flags($grok->[0], $grok->[1]); 118b8851fccSafresh1 is($out_uv, $grok->[2], "'$grok->[0]' flags $grok->[1] - check number"); 119b8851fccSafresh1 is($out_flags, $grok->[3], "'$grok->[0]' flags $grok->[1] - check flags"); 120b8851fccSafresh1} 121b8851fccSafresh1 122b8851fccSafresh1my $ATOU_MAX = ~0; 123b8851fccSafresh1 124b8851fccSafresh1# atou tests 125b8851fccSafresh1my @atous = 126b8851fccSafresh1 ( 127b8851fccSafresh1 # [ input, endsv, out uv, out len ] 128b8851fccSafresh1 129b8851fccSafresh1 # Basic cases. 130b8851fccSafresh1 [ "0", "", 0, 1 ], 131b8851fccSafresh1 [ "1", "", 1, 1 ], 132b8851fccSafresh1 [ "2", "", 2, 1 ], 133b8851fccSafresh1 [ "9", "", 9, 1 ], 134b8851fccSafresh1 [ "12", "", 12, 2 ], 135b8851fccSafresh1 [ "123", "", 123, 3 ], 136b8851fccSafresh1 137b8851fccSafresh1 # Trailing whitespace is accepted or rejected, depending on endptr. 138b8851fccSafresh1 [ "0 ", " ", 0, 1 ], 139b8851fccSafresh1 [ "1 ", " ", 1, 1 ], 140b8851fccSafresh1 [ "2 ", " ", 2, 1 ], 141b8851fccSafresh1 [ "12 ", " ", 12, 2 ], 142b8851fccSafresh1 143b8851fccSafresh1 # Trailing garbage is accepted or rejected, depending on endptr. 144b8851fccSafresh1 [ "0x", "x", 0, 1 ], 145b8851fccSafresh1 [ "1x", "x", 1, 1 ], 146b8851fccSafresh1 [ "2x", "x", 2, 1 ], 147b8851fccSafresh1 [ "12x", "x", 12, 2 ], 148b8851fccSafresh1 149b8851fccSafresh1 # Leading whitespace is failure. 150b8851fccSafresh1 [ " 0", undef, 0, 0 ], 151b8851fccSafresh1 [ " 1", undef, 0, 0 ], 152b8851fccSafresh1 [ " 12", undef, 0, 0 ], 153b8851fccSafresh1 154b8851fccSafresh1 # Leading garbage is outright failure. 155b8851fccSafresh1 [ "x0", undef, 0, 0 ], 156b8851fccSafresh1 [ "x1", undef, 0, 0 ], 157b8851fccSafresh1 [ "x12", undef, 0, 0 ], 158b8851fccSafresh1 159b8851fccSafresh1 # We do not parse decimal point. 160b8851fccSafresh1 [ "12.3", ".3", 12, 2 ], 161b8851fccSafresh1 162b8851fccSafresh1 # Leading pluses or minuses are no good. 163b8851fccSafresh1 [ "+12", undef, 0, 0 ], 164b8851fccSafresh1 [ "-12", undef, 0, 0 ], 165b8851fccSafresh1 166b8851fccSafresh1 # Extra leading zeros are no good. 167b8851fccSafresh1 [ "00", undef, $ATOU_MAX, 0 ], 168b8851fccSafresh1 [ "01", undef, $ATOU_MAX, 0 ], 169b8851fccSafresh1 [ "012", undef, $ATOU_MAX, 0 ], 170b8851fccSafresh1 ); 171b8851fccSafresh1 172b8851fccSafresh1# Values near overflow point. 173b8851fccSafresh1if ($Config{uvsize} == 8) { 174b8851fccSafresh1 push @atous, 175b8851fccSafresh1 ( 176b8851fccSafresh1 # 32-bit values no problem for 64-bit. 177b8851fccSafresh1 [ "4294967293", "", 4294967293, 10, ], 178b8851fccSafresh1 [ "4294967294", "", 4294967294, 10, ], 179b8851fccSafresh1 [ "4294967295", "", 4294967295, 10, ], 180b8851fccSafresh1 [ "4294967296", "", 4294967296, 10, ], 181b8851fccSafresh1 [ "4294967297", "", 4294967297, 10, ], 182b8851fccSafresh1 183b8851fccSafresh1 # This is well within 64-bit. 184b8851fccSafresh1 [ "9999999999", "", 9999999999, 10, ], 185b8851fccSafresh1 186b8851fccSafresh1 # Values valid up to 64-bit, failing beyond. 187b8851fccSafresh1 [ "18446744073709551613", "", 18446744073709551613, 20, ], 188b8851fccSafresh1 [ "18446744073709551614", "", 18446744073709551614, 20, ], 189b8851fccSafresh1 [ "18446744073709551615", "", $ATOU_MAX, 20, ], 190b8851fccSafresh1 [ "18446744073709551616", undef, $ATOU_MAX, 0, ], 191b8851fccSafresh1 [ "18446744073709551617", undef, $ATOU_MAX, 0, ], 192b8851fccSafresh1 ); 193b8851fccSafresh1} elsif ($Config{uvsize} == 4) { 194b8851fccSafresh1 push @atous, 195b8851fccSafresh1 ( 196b8851fccSafresh1 # Values valid up to 32-bit, failing beyond. 197b8851fccSafresh1 [ "4294967293", "", 4294967293, 10, ], 198b8851fccSafresh1 [ "4294967294", "", 4294967294, 10, ], 199b8851fccSafresh1 [ "4294967295", "", $ATOU_MAX, 10, ], 200b8851fccSafresh1 [ "4294967296", undef, $ATOU_MAX, 0, ], 201b8851fccSafresh1 [ "4294967297", undef, $ATOU_MAX, 0, ], 202b8851fccSafresh1 203b8851fccSafresh1 # Still beyond 32-bit. 204b8851fccSafresh1 [ "4999999999", undef, $ATOU_MAX, 0, ], 205b8851fccSafresh1 [ "5678901234", undef, $ATOU_MAX, 0, ], 206b8851fccSafresh1 [ "6789012345", undef, $ATOU_MAX, 0, ], 207b8851fccSafresh1 [ "7890123456", undef, $ATOU_MAX, 0, ], 208b8851fccSafresh1 [ "8901234567", undef, $ATOU_MAX, 0, ], 209b8851fccSafresh1 [ "9012345678", undef, $ATOU_MAX, 0, ], 210b8851fccSafresh1 [ "9999999999", undef, $ATOU_MAX, 0, ], 211b8851fccSafresh1 [ "10000000000", undef, $ATOU_MAX, 0, ], 212b8851fccSafresh1 [ "12345678901", undef, $ATOU_MAX, 0, ], 213b8851fccSafresh1 214b8851fccSafresh1 # 64-bit values are way beyond. 215b8851fccSafresh1 [ "18446744073709551613", undef, $ATOU_MAX, 0, ], 216b8851fccSafresh1 [ "18446744073709551614", undef, $ATOU_MAX, 0, ], 217b8851fccSafresh1 [ "18446744073709551615", undef, $ATOU_MAX, 0, ], 218b8851fccSafresh1 [ "18446744073709551616", undef, $ATOU_MAX, 0, ], 219b8851fccSafresh1 [ "18446744073709551617", undef, $ATOU_MAX, 0, ], 220b8851fccSafresh1 ); 221b8851fccSafresh1} 222b8851fccSafresh1 223b8851fccSafresh1# These will fail to fail once 128/256-bit systems arrive. 224b8851fccSafresh1push @atous, 225b8851fccSafresh1 ( 226b8851fccSafresh1 [ "23456789012345678901", undef, $ATOU_MAX, 0 ], 227b8851fccSafresh1 [ "34567890123456789012", undef, $ATOU_MAX, 0 ], 228b8851fccSafresh1 [ "98765432109876543210", undef, $ATOU_MAX, 0 ], 229b8851fccSafresh1 [ "98765432109876543211", undef, $ATOU_MAX, 0 ], 230b8851fccSafresh1 [ "99999999999999999999", undef, $ATOU_MAX, 0 ], 231b8851fccSafresh1 ); 232b8851fccSafresh1 233b8851fccSafresh1for my $grok (@atous) { 234b8851fccSafresh1 my $input = $grok->[0]; 235b8851fccSafresh1 my $endsv = $grok->[1]; 236b8851fccSafresh1 my $expect_ok = defined $endsv; 237b8851fccSafresh1 my $strict_ok = $expect_ok && $endsv eq ''; 238b8851fccSafresh1 239b8851fccSafresh1 my ($ok, $out_uv, $out_len); 240b8851fccSafresh1 241b8851fccSafresh1 # First with endsv. 242b8851fccSafresh1 ($ok, $out_uv, $out_len) = grok_atoUV($input, $endsv); 243b8851fccSafresh1 is($expect_ok, $ok, sprintf "'$input' expected %s, got %s", 244b8851fccSafresh1 ($expect_ok ? 'success' : 'failure'), 245b8851fccSafresh1 ($ok ? 'success' : 'failure'), 246b8851fccSafresh1 ); 247b8851fccSafresh1 if ($expect_ok) { 248b8851fccSafresh1 is($expect_ok, $ok, "'$input' expect success"); 249b8851fccSafresh1 is($out_uv, $grok->[2], 250b8851fccSafresh1 "'$input' $endsv - number success (got $out_uv cf $grok->[2])"); 251b8851fccSafresh1 ok($grok->[3] <= length $input, "'$input' $endsv - length sanity 1"); 252b8851fccSafresh1 unless (length $grok->[1]) { 253b8851fccSafresh1 is($out_len, $grok->[3], "'$input' $endsv - length sanity 2"); 254b8851fccSafresh1 } # else { ... } ? 255b8851fccSafresh1 if ($out_len) { 256b8851fccSafresh1 is($endsv, substr($input, $out_len), 257b8851fccSafresh1 "'$input' $endsv - length sanity 3"); 258b8851fccSafresh1 } 259b8851fccSafresh1 } else { 260b8851fccSafresh1 is($expect_ok, $ok, "'$input' expect failure"); 261b8851fccSafresh1 is(0xdeadbeef, $out_uv, "'$input' on failure expect value unchanged"); 262b8851fccSafresh1 } 263b8851fccSafresh1 264b8851fccSafresh1 # Then without endsv (undef == NULL). 265b8851fccSafresh1 ($ok, $out_uv, $out_len) = grok_atoUV($input, undef); 266b8851fccSafresh1 if ($strict_ok) { 267b8851fccSafresh1 is($strict_ok, $ok, "'$input' expect strict success"); 268b8851fccSafresh1 is($out_uv, $grok->[2], 269b8851fccSafresh1 "'$input' $endsv - strict number success (got $out_uv cf $grok->[2])"); 270b8851fccSafresh1 } else { 271b8851fccSafresh1 is($strict_ok, $ok, "'$input' expect strict failure"); 272b8851fccSafresh1 is(0xdeadbeef, $out_uv, "'$input' on strict failure expect value unchanged"); 273b8851fccSafresh1 } 274b8851fccSafresh1} 275b8851fccSafresh1 276898184e3Ssthendone_testing(); 277