1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
|
#!./perl -w
# Tests for sprintf that do not fit the format of sprintf.t.
BEGIN {
chdir 't' if -d 't';
@INC = '../lib';
require './test.pl';
}
plan tests => 1370;
use strict;
use Config;
is(
sprintf("%.40g ",0.01),
sprintf("%.40g", 0.01)." ",
q(the sprintf "%.<number>g" optimization)
);
is(
sprintf("%.40f ",0.01),
sprintf("%.40f", 0.01)." ",
q(the sprintf "%.<number>f" optimization)
);
# cases of $i > 1 are against [perl #39126]
for my $i (1, 5, 10, 20, 50, 100) {
chop(my $utf8_format = "%-*s\x{100}");
my $string = "\xB4"x$i; # latin1 ACUTE or ebcdic COPYRIGHT
my $expect = $string." "x$i; # followed by 2*$i spaces
is(sprintf($utf8_format, 3*$i, $string), $expect,
"width calculation under utf8 upgrade, length=$i");
}
# check simultaneous width & precision with wide characters
for my $i (1, 3, 5, 10) {
my $string = "\x{0410}"x($i+10); # cyrillic capital A
my $expect = "\x{0410}"x$i; # cut down to exactly $i characters
my $format = "%$i.${i}s";
is(sprintf($format, $string), $expect,
"width & precision interplay with utf8 strings, length=$i");
}
# Used to mangle PL_sv_undef
fresh_perl_like(
'print sprintf "xxx%n\n"; print undef',
'Modification of a read-only value attempted at - line 1\.',
{ switches => [ '-w' ] },
q(%n should not be able to modify read-only constants),
);
# check overflows
for (int(~0/2+1), ~0, "9999999999999999999") {
is(eval {sprintf "%${_}d", 0}, undef, "no sprintf result expected %${_}d");
like($@, qr/^Integer overflow in format string for sprintf /, "overflow in sprintf");
is(eval {printf "%${_}d\n", 0}, undef, "no printf result expected %${_}d");
like($@, qr/^Integer overflow in format string for printf /, "overflow in printf");
}
# check %NNN$ for range bounds
{
my ($warn, $bad) = (0,0);
local $SIG{__WARN__} = sub {
if ($_[0] =~ /missing argument/i) {
$warn++
}
else {
$bad++
}
};
my $fmt = join('', map("%$_\$s%" . ((1 << 31)-$_) . '$s', 1..20));
my $result = sprintf $fmt, qw(a b c d);
is($result, "abcd", "only four valid values in $fmt");
is($warn, 36, "expected warnings");
is($bad, 0, "unexpected warnings");
}
{
foreach my $ord (0 .. 255) {
my $bad = 0;
local $SIG{__WARN__} = sub {
if ($_[0] !~ /^Invalid conversion in sprintf/) {
warn $_[0];
$bad++;
}
};
my $r = eval {sprintf '%v' . chr $ord};
is ($bad, 0, "pattern '%v' . chr $ord");
}
}
sub mysprintf_int_flags {
my ($fmt, $num) = @_;
die "wrong format $fmt" if $fmt !~ /^%([-+ 0]+)([1-9][0-9]*)d\z/;
my $flag = $1;
my $width = $2;
my $sign = $num < 0 ? '-' :
$flag =~ /\+/ ? '+' :
$flag =~ /\ / ? ' ' :
'';
my $abs = abs($num);
my $padlen = $width - length($sign.$abs);
return
$flag =~ /0/ && $flag !~ /-/ # do zero padding
? $sign . '0' x $padlen . $abs
: $flag =~ /-/ # left or right
? $sign . $abs . ' ' x $padlen
: ' ' x $padlen . $sign . $abs;
}
# Whole tests for "%4d" with 2 to 4 flags;
# total counts: 3 * (4**2 + 4**3 + 4**4) == 1008
my @flags = ("-", "+", " ", "0");
for my $num (0, -1, 1) {
for my $f1 (@flags) {
for my $f2 (@flags) {
for my $f3 ('', @flags) { # '' for doubled flags
my $flag = $f1.$f2.$f3;
my $width = 4;
my $fmt = '%'."${flag}${width}d";
my $result = sprintf($fmt, $num);
my $expect = mysprintf_int_flags($fmt, $num);
is($result, $expect, qq/sprintf("$fmt",$num)/);
next if $f3 eq '';
for my $f4 (@flags) { # quadrupled flags
my $flag = $f1.$f2.$f3.$f4;
my $fmt = '%'."${flag}${width}d";
my $result = sprintf($fmt, $num);
my $expect = mysprintf_int_flags($fmt, $num);
is($result, $expect, qq/sprintf("$fmt",$num)/);
}
}
}
}
}
# test that %f doesn't panic with +Inf, -Inf, NaN [perl #45383]
foreach my $n (2**1e100, -2**1e100, 2**1e100/2**1e100) { # +Inf, -Inf, NaN
eval { my $f = sprintf("%f", $n); };
is $@, "", "sprintf(\"%f\", $n)";
}
# test %ll formats with and without HAS_QUAD
eval { my $q = pack "q", 0 };
my $Q = $@ eq '';
my @tests = (
[ '%lld' => [qw( 4294967296 -100000000000000 )] ],
[ '%lli' => [qw( 4294967296 -100000000000000 )] ],
[ '%llu' => [qw( 4294967296 100000000000000 )] ],
[ '%Ld' => [qw( 4294967296 -100000000000000 )] ],
[ '%Li' => [qw( 4294967296 -100000000000000 )] ],
[ '%Lu' => [qw( 4294967296 100000000000000 )] ],
);
for my $t (@tests) {
my($fmt, $nums) = @$t;
for my $num (@$nums) {
my $w; local $SIG{__WARN__} = sub { $w = shift };
is(sprintf($fmt, $num), $Q ? $num : $fmt, "quad: $fmt -> $num");
like($w, $Q ? '' : qr/Invalid conversion in sprintf: "$fmt"/, "warning: $fmt");
}
}
# Check unicode vs byte length
for my $width (1,2,3,4,5,6,7) {
for my $precis (1,2,3,4,5,6,7) {
my $v = "\x{20ac}\x{20ac}";
my $format = "%" . $width . "." . $precis . "s";
my $chars = ($precis > 2 ? 2 : $precis);
my $space = ($width < 2 ? 0 : $width - $chars);
fresh_perl_is(
'my $v = "\x{20ac}\x{20ac}"; my $x = sprintf "'.$format.'", $v; $x =~ /^(\s*)(\S*)$/; print "$_" for map {length} $1, $2',
"$space$chars",
{},
q(sprintf ").$format.q(", "\x{20ac}\x{20ac}"),
);
}
}
# Overload count
package o { use overload '""', sub { ++our $count; $_[0][0]; } }
my $o = bless ["\x{100}"], o::;
() = sprintf "%1s", $o;
is $o::count, '1', 'sprinf %1s overload count';
$o::count = 0;
() = sprintf "%.1s", $o;
is $o::count, '1', 'sprinf %.1s overload count';
|