#!perl -w
BEGIN {
- if ($ENV{'PERL_CORE'}){
- chdir 't';
- @INC = '../lib';
- }
+ chdir 't' if -d 't';
+ require Config; import Config;
+ require './test.pl';
+ require './charset_tools.pl';
+ require './loc_tools.pl';
+ set_up_inc( '../lib' );
}
-use Test::More tests => 56;
+plan(tests => 217);
package UTF8Toggle;
use strict;
-use overload '""' => 'stringify';
+use overload '""' => 'stringify', fallback => 1;
sub new {
my $class = shift;
- return bless [shift, 0], $class;
+ my $value = shift;
+ my $state = shift||0;
+ return bless [$value, $state], $class;
}
sub stringify {
package main;
+# These tests are based on characters 128-255 not having latin1, and hence
+# Unicode, semantics
+# no feature "unicode_strings";
+
# Bug 34297
-foreach my $t ("ASCII", "B\366se") {
+foreach my $t ("ASCII", "B" . uni_to_native("\366") . "se") {
my $length = length $t;
my $u = UTF8Toggle->new($t);
is (length $u, $length, "length of '$t'");
}
-my $u = UTF8Toggle->new("\311");
+my $E_acute = uni_to_native("\311");
+my $e_acute = uni_to_native("\351");
+my $u = UTF8Toggle->new($E_acute);
my $lc = lc $u;
is (length $lc, 1);
-is ($lc, "\311", "E accute -> e accute");
+is ($lc, $E_acute, "E acute -> e acute");
$lc = lc $u;
is (length $lc, 1);
-is ($lc, "\351", "E accute -> e accute");
+is ($lc, $e_acute, "E acute -> e acute");
$lc = lc $u;
is (length $lc, 1);
-is ($lc, "\311", "E accute -> e accute");
+is ($lc, $E_acute, "E acute -> e acute");
-$u = UTF8Toggle->new("\351");
+$u = UTF8Toggle->new($e_acute);
my $uc = uc $u;
is (length $uc, 1);
-is ($uc, "\351", "e accute -> E accute");
+is ($uc, $e_acute, "e acute -> E acute");
$uc = uc $u;
is (length $uc, 1);
-is ($uc, "\311", "e accute -> E accute");
+is ($uc, $E_acute, "e acute -> E acute");
$uc = uc $u;
is (length $uc, 1);
-is ($uc, "\351", "e accute -> E accute");
+is ($uc, $e_acute, "e acute -> E acute");
-$u = UTF8Toggle->new("\311");
+$u = UTF8Toggle->new($E_acute);
$lc = lcfirst $u;
is (length $lc, 1);
-is ($lc, "\311", "E accute -> e accute");
+is ($lc, $E_acute, "E acute -> e acute");
$lc = lcfirst $u;
is (length $lc, 1);
-is ($lc, "\351", "E accute -> e accute");
+is ($lc, $e_acute, "E acute -> e acute");
$lc = lcfirst $u;
is (length $lc, 1);
-is ($lc, "\311", "E accute -> e accute");
+is ($lc, $E_acute, "E acute -> e acute");
-$u = UTF8Toggle->new("\351");
+$u = UTF8Toggle->new($e_acute);
$uc = ucfirst $u;
is (length $uc, 1);
-is ($uc, "\351", "e accute -> E accute");
+is ($uc, $e_acute, "e acute -> E acute");
$uc = ucfirst $u;
is (length $uc, 1);
-is ($uc, "\311", "e accute -> E accute");
+is ($uc, $E_acute, "e acute -> E acute");
$uc = ucfirst $u;
is (length $uc, 1);
-is ($uc, "\351", "e accute -> E accute");
+is ($uc, $e_acute, "e acute -> E acute");
-my $have_setlocale = 0;
-eval {
- require POSIX;
- import POSIX ':locale_h';
- $have_setlocale++;
-};
+my $have_setlocale = locales_enabled('LC_ALL');
SKIP: {
if (!$have_setlocale) {
skip "No setlocale", 24;
} elsif (!setlocale(&POSIX::LC_ALL, "en_GB.ISO8859-1")) {
skip "Could not setlocale to en_GB.ISO8859-1", 24;
+ } elsif ($^O eq 'dec_osf' || $^O eq 'VMS') {
+ skip "$^O has broken en_GB.ISO8859-1 locale", 24;
} else {
- use locale;
- my $u = UTF8Toggle->new("\311");
+ use locale;
+ my $u = UTF8Toggle->new($E_acute);
my $lc = lc $u;
is (length $lc, 1);
- is ($lc, "\351", "E accute -> e accute");
+ is ($lc, $e_acute, "E acute -> e acute");
$lc = lc $u;
is (length $lc, 1);
- is ($lc, "\351", "E accute -> e accute");
+ is ($lc, $e_acute, "E acute -> e acute");
$lc = lc $u;
is (length $lc, 1);
- is ($lc, "\351", "E accute -> e accute");
+ is ($lc, $e_acute, "E acute -> e acute");
- $u = UTF8Toggle->new("\351");
+ $u = UTF8Toggle->new($e_acute);
my $uc = uc $u;
is (length $uc, 1);
- is ($uc, "\311", "e accute -> E accute");
+ is ($uc, $E_acute, "e acute -> E acute");
$uc = uc $u;
is (length $uc, 1);
- is ($uc, "\311", "e accute -> E accute");
+ is ($uc, $E_acute, "e acute -> E acute");
$uc = uc $u;
is (length $uc, 1);
- is ($uc, "\311", "e accute -> E accute");
+ is ($uc, $E_acute, "e acute -> E acute");
- $u = UTF8Toggle->new("\311");
+ $u = UTF8Toggle->new($E_acute);
$lc = lcfirst $u;
is (length $lc, 1);
- is ($lc, "\351", "E accute -> e accute");
+ is ($lc, $e_acute, "E acute -> e acute");
$lc = lcfirst $u;
is (length $lc, 1);
- is ($lc, "\351", "E accute -> e accute");
+ is ($lc, $e_acute, "E acute -> e acute");
$lc = lcfirst $u;
is (length $lc, 1);
- is ($lc, "\351", "E accute -> e accute");
+ is ($lc, $e_acute, "E acute -> e acute");
- $u = UTF8Toggle->new("\351");
+ $u = UTF8Toggle->new($e_acute);
$uc = ucfirst $u;
is (length $uc, 1);
- is ($uc, "\311", "e accute -> E accute");
+ is ($uc, $E_acute, "e acute -> E acute");
$uc = ucfirst $u;
is (length $uc, 1);
- is ($uc, "\311", "e accute -> E accute");
+ is ($uc, $E_acute, "e acute -> E acute");
$uc = ucfirst $u;
is (length $uc, 1);
- is ($uc, "\311", "e accute -> E accute");
+ is ($uc, $E_acute, "e acute -> E acute");
+ }
+}
+
+my $tmpfile = tempfile();
+
+foreach my $operator ('print', 'syswrite', 'syswrite len', 'syswrite off',
+ 'syswrite len off') {
+ foreach my $layer ('', ':utf8') {
+ open my $fh, "+>$layer", $tmpfile or die $!;
+ my $pad = $operator =~ /\boff\b/ ? "\243" : "";
+ my $trail = $operator =~ /\blen\b/ ? "!" : "";
+ my $u = UTF8Toggle->new("$pad$E_acute\n$trail");
+ my $l = UTF8Toggle->new("$pad$e_acute\n$trail", 1);
+ no warnings 'deprecated';
+ if ($operator eq 'print') {
+ no warnings 'utf8';
+ print $fh $u;
+ print $fh $u;
+ print $fh $u;
+ print $fh $l;
+ print $fh $l;
+ print $fh $l;
+ } elsif ($operator eq 'syswrite') {
+ syswrite $fh, $u;
+ syswrite $fh, $u;
+ syswrite $fh, $u;
+ syswrite $fh, $l;
+ syswrite $fh, $l;
+ syswrite $fh, $l;
+ } elsif ($operator eq 'syswrite len') {
+ syswrite $fh, $u, 2;
+ syswrite $fh, $u, 2;
+ syswrite $fh, $u, 2;
+ syswrite $fh, $l, 2;
+ syswrite $fh, $l, 2;
+ syswrite $fh, $l, 2;
+ } elsif ($operator eq 'syswrite off'
+ || $operator eq 'syswrite len off') {
+ syswrite $fh, $u, 2, 1;
+ syswrite $fh, $u, 2, 1;
+ syswrite $fh, $u, 2, 1;
+ syswrite $fh, $l, 2, 1;
+ syswrite $fh, $l, 2, 1;
+ syswrite $fh, $l, 2, 1;
+ } else {
+ die $operator;
+ }
+
+ seek $fh, 0, 0 or die $!;
+ my $line;
+ chomp ($line = <$fh>);
+ is ($line, $E_acute, "$operator $layer");
+ chomp ($line = <$fh>);
+ is ($line, $E_acute, "$operator $layer");
+ chomp ($line = <$fh>);
+ is ($line, $E_acute, "$operator $layer");
+ chomp ($line = <$fh>);
+ is ($line, $e_acute, "$operator $layer");
+ chomp ($line = <$fh>);
+ is ($line, $e_acute, "$operator $layer");
+ chomp ($line = <$fh>);
+ is ($line, $e_acute, "$operator $layer");
+
+ close $fh or die $!;
+ }
+}
+
+my $little = "\243\243";
+my $big = " \243 $little ! $little ! $little \243 ";
+my $right = rindex $big, $little;
+my $right1 = rindex $big, $little, 11;
+my $left = index $big, $little;
+my $left1 = index $big, $little, 4;
+
+cmp_ok ($right, ">", $right1, "Sanity check our rindex tests");
+cmp_ok ($left, "<", $left1, "Sanity check our index tests");
+
+foreach my $b ($big, UTF8Toggle->new($big)) {
+ foreach my $l ($little, UTF8Toggle->new($little),
+ UTF8Toggle->new($little, 1)) {
+ is (rindex ($b, $l), $right, "rindex");
+ is (rindex ($b, $l), $right, "rindex");
+ is (rindex ($b, $l), $right, "rindex");
+
+ is (rindex ($b, $l, 11), $right1, "rindex 11");
+ is (rindex ($b, $l, 11), $right1, "rindex 11");
+ is (rindex ($b, $l, 11), $right1, "rindex 11");
+
+ is (index ($b, $l), $left, "index");
+ is (index ($b, $l), $left, "index");
+ is (index ($b, $l), $left, "index");
+
+ is (index ($b, $l, 4), $left1, "index 4");
+ is (index ($b, $l, 4), $left1, "index 4");
+ is (index ($b, $l, 4), $left1, "index 4");
}
}
+
+my $bits = $E_acute;
+foreach my $pieces ($bits, UTF8Toggle->new($bits)) {
+ like ($bits ^ $pieces, qr/\A\0+\z/, "something xor itself is zeros");
+ like ($bits ^ $pieces, qr/\A\0+\z/, "something xor itself is zeros");
+ like ($bits ^ $pieces, qr/\A\0+\z/, "something xor itself is zeros");
+
+ like ($pieces ^ $bits, qr/\A\0+\z/, "something xor itself is zeros");
+ like ($pieces ^ $bits, qr/\A\0+\z/, "something xor itself is zeros");
+ like ($pieces ^ $bits, qr/\A\0+\z/, "something xor itself is zeros");
+}
+
+foreach my $value ("\243", UTF8Toggle->new("\243")) {
+ is (pack ("A/A", $value), pack ("A/A", "\243"),
+ "pack copes with overloading");
+ is (pack ("A/A", $value), pack ("A/A", "\243"));
+ is (pack ("A/A", $value), pack ("A/A", "\243"));
+}
+
+foreach my $value ("\243", UTF8Toggle->new("\243")) {
+ my $v;
+ $v = substr $value, 0, 1;
+ is ($v, "\243");
+ $v = substr $value, 0, 1;
+ is ($v, "\243");
+ $v = substr $value, 0, 1;
+ is ($v, "\243");
+}
+
+{
+ package RT69422;
+ use overload '""' => sub { $_[0]->{data} }
+}
+
+{
+ my $text = bless { data => "\x{3075}" }, 'RT69422';
+ my $p = substr $text, 0, 1;
+ is ($p, "\x{3075}");
+}
+
+TODO: {
+ local $::TODO = 'RT #3054: Recursive operator overloading overflows the C stack';
+ fresh_perl_is(<<'EOP', "ok\n", {}, 'RT #3054: Recursive operator overloading should not crash the interpreter');
+ use overload '""' => sub { "$_[0]" };
+ print bless {}, __PACKAGE__;
+ print "ok\n";
+EOP
+}
+
+TODO: {
+ local $::TODO = 'RT #3270: Overloaded operators can not be treated as lvalues';
+ fresh_perl_is(<<'EOP', '', {stderr => 1}, 'RT #3270: Overloaded operator that returns an lvalue can be used as an lvalue');
+ use overload '.' => \˙
+ sub dot : lvalue {my ($obj, $method) = @_; $obj -> {$method};}
+ my $o = bless {} => "main";
+ $o.foo = "bar";
+EOP
+}