xref: /openbsd-src/gnu/usr.bin/perl/t/uni/parser.t (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1#!./perl
2
3# Checks if the parser behaves correctly in edge cases
4# (including weird syntax errors)
5
6BEGIN {
7    require './test.pl';
8}
9
10plan (tests => 52);
11
12use utf8;
13use open qw( :utf8 :std );
14
15ok *tèst, "*main::tèst", "sanity check.";
16ok $::{"tèst"}, "gets the right glob in the stash.";
17
18my $glob_by_sub = sub { *main::method }->();
19
20is *main::method, "*main::method", "glob stringy works";
21is "" . *main::method, "*main::method", "glob stringify-through-concat works";
22is $glob_by_sub, "*main::method", "glob stringy works";
23is "" . $glob_by_sub, "*main::method", "";
24
25sub gimme_glob {
26    no strict 'refs';
27    is *{$_[0]}, "*main::$_[0]";
28    *{$_[0]};
29}
30
31is "" . gimme_glob("下郎"), "*main::下郎";
32$a = *下郎;
33is "" . $a, "*main::下郎";
34
35*{gimme_glob("下郎")} = sub {};
36
37{
38    ok defined *{"下郎"}{CODE};
39    ok !defined *{"\344\270\213\351\203\216"}{CODE};
40}
41
42$Lèon = 1;
43is ${*Lèon{SCALAR}}, 1, "scalar define in the right glob,";
44ok !${*{"L\303\250on"}{SCALAR}}, "..and nothing in the wrong one.";
45
46my $a = "foo" . chr(190);
47my $b = $a    . chr(256);
48chop $b; # $b is $a with utf8 on
49
50is $a, $b, '$a equals $b';
51
52*$b = sub { 5 };
53
54is eval { main->$a }, 5, q!$a can call $b's sub!;
55ok !$@, "..and there's no error.";
56
57my $c = $b;
58utf8::encode($c);
59ok $b ne $c, '$b unequal $c';
60eval { main->$c };
61ok $@, q!$c can't call $b's sub.!;
62
63# Now define another sub under the downgraded name:
64*$a = sub { 6 };
65# Call it:
66is eval { main->$a }, 6, "Adding a new sub to *a and calling it works,";
67ok !$@, "..without errors.";
68eval { main->$c };
69ok $@, "but it's still unreachable through *c";
70
71*$b = \10;
72is ${*$a{SCALAR}}, 10;
73is ${*$b{SCALAR}}, 10;
74is ${*$c{SCALAR}}, undef;
75
76opendir FÒÒ, ".";
77closedir FÒÒ;
78::ok($::{"FÒÒ"}, "Bareword generates the right glob.");
79::ok(!$::{"F\303\222\303\222"});
80
81sub участники { 1 }
82
83ok $::{"участники"}, "non-const sub declarations generate the right glob";
84ok *{$::{"участники"}}{CODE};
85is *{$::{"участники"}}{CODE}->(), 1;
86
87sub 原 () { 1 }
88
89is grep({ $_ eq "\x{539f}"     } keys %::), 1, "Constant subs generate the right glob.";
90is grep({ $_ eq "\345\216\237" } keys %::), 0;
91
92#These should probably go elsewhere.
93eval q{ sub wròng1 (_$); wròng1(1,2) };
94like( $@, qr/Malformed prototype for main::wròng1/, 'Malformed prototype croak is clean.' );
95
96eval q{ sub ча::ики ($__); ча::ики(1,2) };
97like( $@, qr/Malformed prototype for ча::ики/ );
98
99our $問 = 10;
100is $問, 10, "our works";
101is $main::問, 10, "...as does getting the same variable through the fully qualified name";
102is ${"main::\345\225\217"}, undef, "..and using the encoded form doesn't";
103
104{
105    use charnames qw( :full );
106
107    eval qq! my \$\x{30cb} \N{DROMEDARY CAMEL} !;
108    $@ =~ s/eval \d+/eval 11/;
109    is $@, 'Unrecognized character \x{1f42a}; marked by <-- HERE after  my $ニ <-- HERE near column 8 at (eval 11) line 1.
110', "'Unrecognized character' croak is UTF-8 clean";
111
112    eval "q\0foobar\0 \x{FFFF}+1";
113    $@ =~ s/eval \d+/eval 11/;
114    is(
115        $@,
116       "Unrecognized character \\x{ffff}; marked by <-- HERE after q\0foobar\0 <-- HERE near column 11 at (eval 11) line 1.\n",
117       "...and nul-clean"
118    );
119
120    {
121        use re 'eval';
122        my $f = qq{(?{\$ネ+ 1; \x{1F42A} })};
123        eval { "a" =~ /^a$f/ };
124        my $e = $@;
125        $e =~ s/eval \d+/eval 11/;
126        is(
127            $e,
128            "Unrecognized character \\x{1f42a}; marked by <-- HERE after (?{\$ネ+ 1; <-- HERE near column 13 at (eval 11) line 1.\n",
129            "Messages from a re-eval are UTF-8 clean"
130        );
131
132        $f = qq{(?{q\0foobar\0 \x{FFFF}+1 })};
133        eval { "a" =~ /^a$f/ };
134        my $e = $@;
135        $e =~ s/eval \d+/eval 11/;
136        is(
137            $e,
138            "Unrecognized character \\x{ffff}; marked by <-- HERE after q\x{0}foobar\x{0} <-- HERE near column 16 at (eval 11) line 1.\n",
139           "...and nul-clean"
140        );
141    }
142
143    {
144        eval qq{\$ネ+ 1; \x{1F42A}};
145        $@ =~ s/eval \d+/eval 11/;
146        is(
147            $@,
148            "Unrecognized character \\x{1f42a}; marked by <-- HERE after \$ネ+ 1; <-- HERE near column 8 at (eval 11) line 1.\n",
149            "Unrecognized character error doesn't cut off in the middle of characters"
150        )
151    }
152
153}
154
155{
156    use feature 'state';
157    for ( qw( my state our ) ) {
158        local $@;
159        eval "$_ Foo $x = 1;";
160        like $@, qr/No such class Foo/u, "'No such class' warning for $_ is UTF-8 clean";
161    }
162}
163
164{
165    local $@;
166    eval "our \$main::\x{30cb};";
167    like $@, qr!No package name allowed for variable \$main::\x{30cb} in "our"!, "'No such package name allowed for variable' is UTF-8 clean";
168}
169
170{
171    use feature 'state';
172    local $@;
173    for ( qw( my state ) ) {
174        eval "$_ \$::\x{30cb};";
175        like $@, qr!"$_" variable \$::\x{30cb} can't be in a package!, qq!'"$_" variable %s can't be in a package' is UTF-8 clean!;
176    }
177}
178
179{
180    local $@;
181    eval qq!print \x{30cb}, "comma""!;
182    like $@, qr/No comma allowed after filehandle/, "No comma allowed after filehandle triggers correctly for UTF-8 filehandles.";
183}
184
185# tests for "Bad name"
186eval q{ Foo::$bar };
187like( $@, qr/Bad name after Foo::/, 'Bad name after Foo::' );
188eval q{ Foo''bar };
189like( $@, qr/Bad name after Foo'/, 'Bad name after Foo\'' );
190
191{
192    no warnings 'utf8';
193    my $malformed_to_be = "\x{c0}\x{a0}";   # Overlong sequence
194    CORE::evalbytes "use charnames ':full'; use utf8; my \$x = \"\\N{abc$malformed_to_be}\"";
195    like( $@, qr/Malformed UTF-8 character immediately after '\\N\{abc' at .* within string/, 'Malformed UTF-8 input to \N{}');
196}
197