5 require './test.pl'; # for fresh_perl_is() etc
6 require './loc_tools.pl'; # to find locales
12 # These tests are here instead of lib/locale.t because
13 # some bugs depend on in the internal state of the locale
14 # settings and pragma/locale messes up that state pretty badly.
15 # We need "fresh runs".
17 eval { require POSIX; POSIX->import("locale_h") };
19 skip_all("could not load the POSIX module"); # running minitest?
23 my $have_strtod = $Config{d_strtod} eq 'define';
24 my @locales = eval { find_locales( [ &LC_ALL, &LC_CTYPE, &LC_NUMERIC ] ) };
25 skip_all("no locales available") unless @locales;
30 foreach my $locale (@locales) {
31 next if $locale eq "C" || $locale eq 'POSIX';
32 $non_C_locale = $locale;
37 skip("no non-C locale available", 2 ) unless $non_C_locale;
38 setlocale(LC_NUMERIC, $non_C_locale);
39 isnt(setlocale(LC_NUMERIC), "C", "retrieving current non-C LC_NUMERIC doesn't give 'C'");
40 setlocale(LC_ALL, $non_C_locale);
41 isnt(setlocale(LC_ALL), "C", "retrieving current non-C LC_ALL doesn't give 'C'");
44 fresh_perl_is("for (qw(@locales)) {\n" . <<'EOF',
45 use POSIX qw(locale_h);
47 setlocale(LC_NUMERIC, "$_") or next;
48 my $s = sprintf "%g %g", 3.1, 3.1;
49 next if $s eq '3.1 3.1' || $s =~ /^(3.+1) \1$/;
53 "", {}, "no locales where LC_NUMERIC breaks");
56 skip("Windows stores locale defaults in the registry", 1 )
58 local $ENV{LC_NUMERIC}; # So not taken as a default
59 local $ENV{LC_ALL}; # so it never overrides LC_NUMERIC
60 local $ENV{LANG}; # So not taken as a default
61 fresh_perl_is("for (qw(@locales)) {\n" . <<'EOF',
62 use POSIX qw(locale_h);
65 my $s = sprintf "%g", $in; # avoid any constant folding bugs
70 "", {}, "LC_NUMERIC without environment nor setlocale() has no effect in any locale");
73 # try to find out a locale where LC_NUMERIC makes a difference
74 my $original_locale = setlocale(LC_NUMERIC);
76 my ($base, $different, $comma, $difference, $utf8_radix);
77 my $radix_encoded_as_utf8;
78 for ("C", @locales) { # prefer C for the base if available
80 setlocale(LC_NUMERIC, $_) or next;
81 my $in = 4.2; # avoid any constant folding bugs
82 if ((my $s = sprintf("%g", $in)) eq "4.2") {
87 my $radix = localeconv()->{decimal_point};
89 # For utf8 locales with a non-ascii radix, it should be encoded as
90 # UTF-8 with the internal flag so set.
91 if (! defined $utf8_radix
92 && $radix =~ /[[:^ascii:]]/
93 && is_locale_utf8($_))
96 $radix_encoded_as_utf8 = utf8::is_utf8($radix);
99 $comma ||= $_ if $radix eq ',';
103 last if $base && $different && $comma && $utf8_radix;
105 setlocale(LC_NUMERIC, $original_locale);
108 skip("no UTF-8 locale available where LC_NUMERIC radix isn't ASCII", 1 )
110 ok($radix_encoded_as_utf8 == 1, "UTF-8 locale '$utf8_radix' with non-ASCII"
111 . " radix is marked UTF-8");
115 skip("no locale available where LC_NUMERIC makes a difference", &last - 7 )
116 if !$different; # -7 is 5 tests before this block; 2 after
117 note("using the '$different' locale for LC_NUMERIC tests");
119 local $ENV{LC_NUMERIC} = $different;
120 local $ENV{LC_ALL}; # so it never overrides LC_NUMERIC
122 fresh_perl_is(<<'EOF', "4.2", {},
129 "format() does not look at LC_NUMERIC without 'use locale'");
132 fresh_perl_is(<<'EOF', "$difference\n", {},
141 "format() looks at LC_NUMERIC with 'use locale'");
145 fresh_perl_is(<<'EOF', ",,", {},
146 print localeconv()->{decimal_point};
149 print localeconv()->{decimal_point};
151 "localeconv() looks at LC_NUMERIC with and without 'use locale'");
155 my $categories = ":collate :characters :collate :ctype :monetary :time";
156 fresh_perl_is(<<"EOF", "4.2", {},
157 use locale qw($categories);
164 "format() does not look at LC_NUMERIC with 'use locale qw($categories)'");
168 fresh_perl_is(<<'EOF', $difference, {},
176 "format() looks at LC_NUMERIC with 'use locale'");
179 for my $category (qw(collate characters collate ctype monetary time)) {
180 for my $negation ("!", "not_") {
181 fresh_perl_is(<<"EOF", $difference, {},
182 use locale ":$negation$category";
189 "format() looks at LC_NUMERIC with 'use locale \":"
190 . "$negation$category\"'");
195 fresh_perl_is(<<'EOF', $difference, {},
196 use locale ":numeric";
203 "format() looks at LC_NUMERIC with 'use locale \":numeric\"'");
207 fresh_perl_is(<<'EOF', "4.2", {},
212 { use locale; write; }
214 "too late to look at the locale at write() time");
218 fresh_perl_is(<<'EOF', $difference, {},
224 { no locale; write; }
226 "too late to ignore the locale at write() time");
231 # do not let "use 5.000" affect the locale!
232 # this test is to prevent regression of [rt.perl.org #105784]
233 fresh_perl_is(<<"EOF",
237 POSIX::setlocale(POSIX::LC_NUMERIC(),"$different");
238 \$a = sprintf("%.2f", \$i);
240 \$b = sprintf("%.2f", \$i);
241 print ".\$a \$b" unless \$a eq \$b
243 "", {}, "version does not clobber version");
245 fresh_perl_is(<<"EOF",
249 POSIX::setlocale(POSIX::LC_NUMERIC(),"$different");
250 \$a = sprintf("%.2f", \$i);
252 \$b = sprintf("%.2f", \$i);
253 print "\$a \$b" unless \$a eq \$b
255 "", {}, "version does not clobber version (via eval)");
259 local $ENV{LC_NUMERIC} = $different;
260 local $ENV{LC_ALL}; # so it never overrides LC_NUMERIC
261 fresh_perl_is(<<'EOF', "$difference "x4, {},
263 use POSIX qw(locale_h);
265 printf("%g %g %s %s ", $in, 4.2, sprintf("%g", $in), sprintf("%g", 4.2));
267 "sprintf() and printf() look at LC_NUMERIC regardless of constant folding");
271 local $ENV{LC_NUMERIC} = $different;
272 local $ENV{LC_ALL}; # so it never overrides LC_NUMERIC
273 local $ENV{LANG}; # so on Windows gets sys default locale
274 fresh_perl_is(<<'EOF', "$difference "x4, {},
276 use POSIX qw(locale_h);
278 printf("%g %g %s %s ", $in, 4.2, sprintf("%g", $in), sprintf("%g", 4.2));
280 "Uses the above test to verify that on Windows the system default locale has lower priority than LC_NUMERIC");
284 # within this block, STDERR is closed. This is because fresh_perl_is()
285 # forks a shell, and some shells (like bash) can complain noisily when
286 #LC_ALL or similar is set to an invalid value
289 open my $saved_stderr, ">&STDERR" or die "Can't dup STDERR: $!";
293 local $ENV{LC_ALL} = "invalid";
294 local $ENV{LC_NUMERIC} = "invalid";
295 local $ENV{LANG} = $different;
297 # Can't turn off the warnings, so send them to /dev/null
298 if (! fresh_perl_is(<<"EOF", "$difference", { stderr => "devnull" },
299 if (\$ENV{LC_ALL} ne "invalid") {
300 # Make the test pass if the sh didn't accept the ENV set
301 print "$difference\n";
305 use POSIX qw(locale_h);
309 "LANG is used if LC_ALL, LC_NUMERIC are invalid"))
311 note "To see details change this .t to not close STDERR";
316 if ($^O eq 'MSWin32') {
317 skip("Win32 uses system default locale in preference to \"C\"",
321 local $ENV{LC_ALL} = "invalid";
322 local $ENV{LC_NUMERIC} = "invalid";
323 local $ENV{LANG} = "invalid";
325 # Can't turn off the warnings, so send them to /dev/null
326 if (! fresh_perl_is(<<"EOF", 4.2, { stderr => "devnull" },
327 if (\$ENV{LC_ALL} ne "invalid") {
328 print "$difference\n";
332 use POSIX qw(locale_h);
336 'C locale is used if LC_ALL, LC_NUMERIC, LANG are invalid'))
338 note "To see details change this .t to not close STDERR";
343 open STDERR, ">&", $saved_stderr or die "Can't dup \$saved_stderr: $!";
347 local $ENV{LC_NUMERIC} = $different;
348 local $ENV{LC_ALL}; # so it never overrides LC_NUMERIC
349 fresh_perl_is(<<"EOF",
350 use POSIX qw(locale_h);
352 BEGIN { setlocale(LC_NUMERIC, \"$different\"); };
353 setlocale(LC_ALL, "C");
355 print setlocale(LC_NUMERIC);
358 "No compile error on v-strings when setting the locale to non-dot radix at compile time when default environment has non-dot radix");
362 skip("no locale available where LC_NUMERIC is a comma", 3);
366 fresh_perl_is(<<"EOF",
371 POSIX::setlocale(POSIX::LC_NUMERIC(),"$comma");
376 "1,5\n1.5", {}, "Radix print properly in locale scope, and without");
378 fresh_perl_is(<<"EOF",
379 my \$i = 1.5; # Should be exactly representable as a base 2
380 # fraction, so can use 'eq' below
383 POSIX::setlocale(POSIX::LC_NUMERIC(),"$comma");
388 "1,5\n2,5", {}, "Can do math when radix is a comma"); # [perl 115800]
390 unless ($have_strtod) {
391 skip("no strtod()", 1);
394 fresh_perl_is(<<"EOF",
396 POSIX::setlocale(POSIX::LC_NUMERIC(),"$comma");
397 my \$one_point_5 = POSIX::strtod("1,5");
398 \$one_point_5 =~ s/0+\$//; # Remove any trailing zeros
399 print \$one_point_5, "\n";
401 "1.5", {}, "POSIX::strtod() uses underlying locale");
407 fresh_perl_is(<<"EOF",
410 POSIX::setlocale(POSIX::LC_CTYPE(),"C");
411 print "h" =~ /[g\\w]/i || 0;
414 1, {}, "/il matching of [bracketed] doesn't skip POSIX class if fails individ char");
418 fresh_perl_is(<<"EOF",
421 POSIX::setlocale(POSIX::LC_CTYPE(),"C");
422 print "0" =~ /[\\d[:punct:]]/l || 0;
425 1, {}, "/l matching of [bracketed] doesn't skip non-first POSIX class");
429 # IMPORTANT: When adding tests before the following line, be sure to update
431 # skip("no locale available where LC_NUMERIC makes a difference", ...)