xref: /openbsd/gnu/usr.bin/perl/ext/XS-APItest/t/grok.t (revision eac174f2)
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