This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
In taint.t, add violates_taint(), to replace a repeated is()/like() pair.
[perl5.git] / t / op / stash.t
1 #!./perl
2
3 BEGIN {
4     chdir 't' if -d 't';
5     @INC = qw(../lib);
6 }
7
8 BEGIN { require "./test.pl"; }
9
10 plan( tests => 51 );
11
12 # Used to segfault (bug #15479)
13 fresh_perl_like(
14     '%:: = ""',
15     qr/Odd number of elements in hash assignment at - line 1\./,
16     { switches => [ '-w' ] },
17     'delete $::{STDERR} and print a warning',
18 );
19
20 # Used to segfault
21 fresh_perl_is(
22     'BEGIN { $::{"X::"} = 2 }',
23     '',
24     { switches => [ '-w' ] },
25     q(Insert a non-GV in a stash, under warnings 'once'),
26 );
27
28 {
29     no warnings 'deprecated';
30     ok( defined %oedipa::maas::, q(stashes happen to be defined if not used) );
31     ok( defined %{"oedipa::maas::"}, q(- work with hard refs too) );
32
33     ok( defined %tyrone::slothrop::, q(stashes are defined if seen at compile time) );
34     ok( defined %{"tyrone::slothrop::"}, q(- work with hard refs too) );
35
36     ok( defined %bongo::shaftsbury::, q(stashes are defined if a var is seen at compile time) );
37     ok( defined %{"bongo::shaftsbury::"}, q(- work with hard refs too) );
38 }
39
40 package tyrone::slothrop;
41 $bongo::shaftsbury::scalar = 1;
42
43 package main;
44
45 # Used to warn
46 # Unbalanced string table refcount: (1) for "A::" during global destruction.
47 # for ithreads.
48 {
49     local $ENV{PERL_DESTRUCT_LEVEL} = 2;
50     fresh_perl_is(
51                   'package A; sub a { // }; %::=""',
52                   '',
53                   '',
54                   );
55 }
56
57 # now tests in eval
58
59 ok( eval  { no warnings 'deprecated'; defined %achtfaden:: },   'works in eval{}' );
60 ok( eval q{ no warnings 'deprecated'; defined %schoenmaker:: }, 'works in eval("")' );
61
62 # now tests with strictures
63
64 {
65     use strict;
66     no warnings 'deprecated';
67     ok( defined %pig::, q(referencing a non-existent stash doesn't produce stricture errors) );
68     ok( !exists $pig::{bodine}, q(referencing a non-existent stash element doesn't produce stricture errors) );
69 }
70
71 SKIP: {
72     eval { require B; 1 } or skip "no B", 27;
73
74     *b = \&B::svref_2object;
75     my $CVf_ANON = B::CVf_ANON();
76
77     my $sub = do {
78         package one;
79         \&{"one"};
80     };
81     delete $one::{one};
82     my $gv = b($sub)->GV;
83
84     isa_ok( $gv, "B::GV", "deleted stash entry leaves CV with valid GV");
85     is( b($sub)->CvFLAGS & $CVf_ANON, $CVf_ANON, "...and CVf_ANON set");
86     is( eval { $gv->NAME }, "__ANON__", "...and an __ANON__ name");
87     is( eval { $gv->STASH->NAME }, "one", "...but leaves stash intact");
88
89     $sub = do {
90         package two;
91         \&{"two"};
92     };
93     %two:: = ();
94     $gv = b($sub)->GV;
95
96     isa_ok( $gv, "B::GV", "cleared stash leaves CV with valid GV");
97     is( b($sub)->CvFLAGS & $CVf_ANON, $CVf_ANON, "...and CVf_ANON set");
98     is( eval { $gv->NAME }, "__ANON__", "...and an __ANON__ name");
99     is( eval { $gv->STASH->NAME }, "two", "...but leaves stash intact");
100
101     $sub = do {
102         package three;
103         \&{"three"};
104     };
105     undef %three::;
106     $gv = b($sub)->GV;
107
108     isa_ok( $gv, "B::GV", "undefed stash leaves CV with valid GV");
109     is( b($sub)->CvFLAGS & $CVf_ANON, $CVf_ANON, "...and CVf_ANON set");
110     is( eval { $gv->NAME }, "__ANON__", "...and an __ANON__ name");
111     is( eval { $gv->STASH->NAME }, "__ANON__", "...and an __ANON__ stash");
112
113     my $sub = do {
114         package four;
115         sub { 1 };
116     };
117     %four:: = ();
118
119     my $gv = B::svref_2object($sub)->GV;
120     ok($gv->isa(q/B::GV/), "cleared stash leaves anon CV with valid GV");
121
122     my $st = eval { $gv->STASH->NAME };
123     is($st, q/four/, "...but leaves the stash intact");
124
125     my $sub = do {
126         package five;
127         sub { 1 };
128     };
129     undef %five::;
130
131     $gv = B::svref_2object($sub)->GV;
132     ok($gv->isa(q/B::GV/), "undefed stash leaves anon CV with valid GV");
133
134     $st = eval { $gv->STASH->NAME };
135     { local $TODO = 'STASHES not anonymized';
136         is($st, q/__ANON__/, "...and an __ANON__ stash");
137     }
138
139     # CvSTASH should be null on a named sub if the stash has been deleted
140     {
141         package FOO;
142         sub foo {}
143         my $rfoo = \&foo;
144         package main;
145         delete $::{'FOO::'};
146         my $cv = B::svref_2object($rfoo);
147         # (is there a better way of testing for NULL ?)
148         my $stash = $cv->STASH;
149         like($stash, qr/B::SPECIAL/, "NULL CvSTASH on named sub");
150     }
151
152     # on glob reassignment, orphaned CV should have anon CvGV
153
154     {
155         my $r;
156         eval q[
157             package FOO2;
158             sub f{};
159             $r = \&f;
160             *f = sub {};
161         ];
162         delete $FOO2::{f};
163         my $cv = B::svref_2object($r);
164         my $gv = $cv->GV;
165         ok($gv->isa(q/B::GV/), "orphaned CV has valid GV");
166         is($gv->NAME, '__ANON__', "orphaned CV has anon GV");
167     }
168
169     # deleting __ANON__ glob shouldn't break things
170
171     {
172         package FOO3;
173         sub named {};
174         my $anon = sub {};
175         my $named = eval q[\&named];
176         package main;
177         delete $FOO3::{named}; # make named anonymous
178
179         delete $FOO3::{__ANON__}; # whoops!
180         my ($cv,$gv);
181         $cv = B::svref_2object($named);
182         $gv = $cv->GV;
183         ok($gv->isa(q/B::GV/), "ex-named CV has valid GV");
184         is($gv->NAME, '__ANON__', "ex-named CV has anon GV");
185
186         $cv = B::svref_2object($anon);
187         $gv = $cv->GV;
188         ok($gv->isa(q/B::GV/), "anon CV has valid GV");
189         is($gv->NAME, '__ANON__', "anon CV has anon GV");
190     }
191
192     {
193         my $r;
194         {
195             package bloop;
196
197             BEGIN {
198                 $r = \&main::whack;
199             }
200         }
201
202         my $br = B::svref_2object($r);
203         is ($br->STASH->NAME, 'bloop',
204             'stub records the package it was compiled in');
205         # Arguably this shouldn't quite be here, but it's easy to add it
206         # here, and tricky to figure out a different good place for it.
207         like ($br->FILE, qr/stash/i,
208               'stub records the file it was compiled in');
209
210         # We need to take this reference "late", after the subroutine is
211         # defined.
212         $br = B::svref_2object(eval 'sub whack {}; \&whack');
213         die $@ if $@;
214
215         is ($br->STASH->NAME, 'main',
216             'definition overrides the package it was compiled in');
217         like ($br->FILE, qr/eval/,
218               'definition overrides the file it was compiled in');
219     }
220 }
221
222 # [perl #58530]
223 fresh_perl_is(
224     'sub foo { 1 }; use overload q/""/ => \&foo;' .
225         'delete $main::{foo}; bless []',
226     "",
227     {},
228     "no segfault with overload/deleted stash entry [#58530]",
229 );
230
231 # make sure having a sub called __ANON__ doesn't confuse perl.
232
233 {
234     my $c;
235     sub __ANON__ { $c = (caller(0))[3]; }
236     __ANON__();
237     is ($c, 'main::__ANON__', '__ANON__ sub called ok');
238 }
239
240
241 # Stashes that are effectively renamed
242 {
243     package rile;
244
245     use Config;
246
247     my $obj  = bless [];
248     my $globref = \*tat;
249
250     # effectively rename a stash
251     *slin:: = *rile::; *rile:: = *zor::;
252     
253     ::is *$globref, "*rile::tat",
254      'globs stringify the same way when stashes are moved';
255     ::is ref $obj, "rile",
256      'ref() returns the same thing when an object’s stash is moved';
257     ::like "$obj", qr "^rile=ARRAY\(0x[\da-f]+\)\z",
258      'objects stringify the same way when their stashes are moved';
259     {
260         local $::TODO =  $Config{useithreads} ? "fails under threads" : undef;
261         ::is eval '__PACKAGE__', 'rile',
262          '__PACKAGE__ returns the same when the current stash is moved';
263     }
264
265     # Now detach it completely from the symtab, making it effect-
266     # ively anonymous
267     my $life_raft = \%slin::;
268     *slin:: = *zor::;
269
270     ::is *$globref, "*rile::tat",
271      'globs stringify the same way when stashes are detached';
272     ::is ref $obj, "rile",
273      'ref() returns the same thing when an object’s stash is detached';
274     ::like "$obj", qr "^rile=ARRAY\(0x[\da-f]+\)\z",
275      'objects stringify the same way when their stashes are detached';
276     {
277         local $::TODO =  $Config{useithreads} ? "fails under threads" : undef;
278         ::is eval '__PACKAGE__', 'rile',
279          '__PACKAGE__ returns the same when the current stash is detached';
280     }
281 }
282
283 # Setting the name during undef %stash:: should have no effect.
284 {
285     my $glob = \*Phoo::glob;
286     sub o::DESTROY { eval '++$Phoo::bar' }
287     no strict 'refs';
288     ${"Phoo::thing1"} = bless [], "o";
289     undef %Phoo::;
290     is "$$glob", "*__ANON__::glob",
291       "setting stash name during undef has no effect";
292 }
293