c0d86a6d6972cfb96415db96af12fda3748a3912
[p5sagit/p5-mst-13.2.git] / t / op / ref.t
1 #!./perl
2
3 BEGIN {
4     chdir 't' if -d 't';
5     @INC = qw(. ../lib);
6 }
7
8 require 'test.pl';
9
10 plan (74);
11
12 # Test glob operations.
13
14 $bar = "one";
15 $foo = "two";
16 {
17     local(*foo) = *bar;
18     is($foo, 'one');
19 }
20 is ($foo, 'two');
21
22 $baz = "three";
23 $foo = "four";
24 {
25     local(*foo) = 'baz';
26     is ($foo, 'three');
27 }
28 is ($foo, 'four');
29
30 $foo = "global";
31 {
32     local(*foo);
33     is ($foo, undef);
34     $foo = "local";
35     is ($foo, 'local');
36 }
37 is ($foo, 'global');
38
39 # Test fake references.
40
41 $baz = "valid";
42 $bar = 'baz';
43 $foo = 'bar';
44 is ($$$foo, 'valid');
45
46 # Test real references.
47
48 $FOO = \$BAR;
49 $BAR = \$BAZ;
50 $BAZ = "hit";
51 is ($$$FOO, 'hit');
52
53 # Test references to real arrays.
54
55 my $test = curr_test();
56 @ary = ($test,$test+1,$test+2,$test+3);
57 $ref[0] = \@a;
58 $ref[1] = \@b;
59 $ref[2] = \@c;
60 $ref[3] = \@d;
61 for $i (3,1,2,0) {
62     push(@{$ref[$i]}, "ok $ary[$i]\n");
63 }
64 print @a;
65 print ${$ref[1]}[0];
66 print @{$ref[2]}[0];
67 print @{'d'};
68 curr_test($test+4);
69
70 # Test references to references.
71
72 $refref = \\$x;
73 $x = "Good";
74 is ($$$refref, 'Good');
75
76 # Test nested anonymous lists.
77
78 $ref = [[],2,[3,4,5,]];
79 is (scalar @$ref, 3);
80 is ($$ref[1], 2);
81 is (${$$ref[2]}[2], 5);
82 is (scalar @{$$ref[0]}, 0);
83
84 is ($ref->[1], 2);
85 is ($ref->[2]->[0], 3);
86
87 # Test references to hashes of references.
88
89 $refref = \%whatever;
90 $refref->{"key"} = $ref;
91 is ($refref->{"key"}->[2]->[0], 3);
92
93 # Test to see if anonymous subarrays spring into existence.
94
95 $spring[5]->[0] = 123;
96 $spring[5]->[1] = 456;
97 push(@{$spring[5]}, 789);
98 is (join(':',@{$spring[5]}), "123:456:789");
99
100 # Test to see if anonymous subhashes spring into existence.
101
102 @{$spring2{"foo"}} = (1,2,3);
103 $spring2{"foo"}->[3] = 4;
104 is (join(':',@{$spring2{"foo"}}), "1:2:3:4");
105
106 # Test references to subroutines.
107
108 {
109     my $called;
110     sub mysub { $called++; }
111     $subref = \&mysub;
112     &$subref;
113     is ($called, 1);
114 }
115
116 $subrefref = \\&mysub2;
117 is ($$subrefref->("GOOD"), "good");
118 sub mysub2 { lc shift }
119
120 # Test the ref operator.
121
122 is (ref $subref, 'CODE');
123 is (ref $ref, 'ARRAY');
124 is (ref $refref, 'HASH');
125
126 # Test anonymous hash syntax.
127
128 $anonhash = {};
129 is (ref $anonhash, 'HASH');
130 $anonhash2 = {FOO => BAR, ABC => XYZ,};
131 is (join('', sort values %$anonhash2), 'BARXYZ');
132
133 # Test bless operator.
134
135 package MYHASH;
136
137 $object = bless $main'anonhash2;
138 main::is (ref $object, 'MYHASH');
139 main::is ($object->{ABC}, 'XYZ');
140
141 $object2 = bless {};
142 main::is (ref $object2, 'MYHASH');
143
144 # Test ordinary call on object method.
145
146 &mymethod($object,"argument");
147
148 sub mymethod {
149     local($THIS, @ARGS) = @_;
150     die 'Got a "' . ref($THIS). '" instead of a MYHASH'
151         unless ref $THIS eq MYHASH;
152     main::is ($ARGS[0], "argument");
153     main::is ($THIS->{FOO}, 'BAR');
154 }
155
156 # Test automatic destructor call.
157
158 $string = "bad";
159 $object = "foo";
160 $string = "good";
161 $main'anonhash2 = "foo";
162 $string = "";
163
164 DESTROY {
165     return unless $string;
166     main::is ($string, 'good');
167
168     # Test that the object has not already been "cursed".
169     main::isnt (ref shift, 'HASH');
170 }
171
172 # Now test inheritance of methods.
173
174 package OBJ;
175
176 @ISA = (BASEOBJ);
177
178 $main'object = bless {FOO => foo, BAR => bar};
179
180 package main;
181
182 # Test arrow-style method invocation.
183
184 is ($object->doit("BAR"), bar);
185
186 # Test indirect-object-style method invocation.
187
188 $foo = doit $object "FOO";
189 main::is ($foo, foo);
190
191 sub BASEOBJ'doit {
192     local $ref = shift;
193     die "Not an OBJ" unless ref $ref eq OBJ;
194     $ref->{shift()};
195 }
196
197 package UNIVERSAL;
198 @ISA = 'LASTCHANCE';
199
200 package LASTCHANCE;
201 sub foo { main::is ($_[1], 'works') }
202
203 package WHATEVER;
204 foo WHATEVER "works";
205
206 #
207 # test the \(@foo) construct
208 #
209 package main;
210 @foo = \(1..3);
211 @bar = \(@foo);
212 @baz = \(1,@foo,@bar);
213 is (scalar (@bar), 3);
214 is (scalar grep(ref($_), @bar), 3);
215 is (scalar (@baz), 3);
216
217 my(@fuu) = \(1..2,3);
218 my(@baa) = \(@fuu);
219 my(@bzz) = \(1,@fuu,@baa);
220 is (scalar (@baa), 3);
221 is (scalar grep(ref($_), @baa), 3);
222 is (scalar (@bzz), 3);
223
224 # also, it can't be an lvalue
225 eval '\\($x, $y) = (1, 2);';
226 like ($@, qr/Can\'t modify.*ref.*in.*assignment/);
227
228 # test for proper destruction of lexical objects
229 $test = curr_test();
230 sub larry::DESTROY { print "# larry\nok $test\n"; }
231 sub curly::DESTROY { print "# curly\nok ", $test + 1, "\n"; }
232 sub moe::DESTROY   { print "# moe\nok ", $test + 2, "\n"; }
233
234 {
235     my ($joe, @curly, %larry);
236     my $moe = bless \$joe, 'moe';
237     my $curly = bless \@curly, 'curly';
238     my $larry = bless \%larry, 'larry';
239     print "# leaving block\n";
240 }
241
242 print "# left block\n";
243 curr_test($test + 3);
244
245 # another glob test
246
247
248 $foo = "garbage";
249 { local(*bar) = "foo" }
250 $bar = "glob 3";
251 local(*bar) = *bar;
252 is ($bar, "glob 3");
253
254 $var = "glob 4";
255 $_   = \$var;
256 is ($$_, 'glob 4');
257
258
259 # test if reblessing during destruction results in more destruction
260 $test = curr_test();
261 {
262     package A;
263     sub new { bless {}, shift }
264     DESTROY { print "# destroying 'A'\nok ", $test + 1, "\n" }
265     package _B;
266     sub new { bless {}, shift }
267     DESTROY { print "# destroying '_B'\nok $test\n"; bless shift, 'A' }
268     package main;
269     my $b = _B->new;
270 }
271 curr_test($test + 2);
272
273 # test if $_[0] is properly protected in DESTROY()
274
275 {
276     my $test = curr_test();
277     my $i = 0;
278     local $SIG{'__DIE__'} = sub {
279         my $m = shift;
280         if ($i++ > 4) {
281             print "# infinite recursion, bailing\nnot ok $test\n";
282             exit 1;
283         }
284         like ($m, qr/^Modification of a read-only/);
285     };
286     package C;
287     sub new { bless {}, shift }
288     DESTROY { $_[0] = 'foo' }
289     {
290         print "# should generate an error...\n";
291         my $c = C->new;
292     }
293     print "# good, didn't recurse\n";
294 }
295
296 # test if refgen behaves with autoviv magic
297 {
298     my @a;
299     $a[1] = "good";
300     my $got;
301     for (@a) {
302         $got .= ${\$_};
303         $got .= ';';
304     }
305     is ($got, ";good;");
306 }
307
308 # This test is the reason for postponed destruction in sv_unref
309 $a = [1,2,3];
310 $a = $a->[1];
311 is ($a, 2);
312
313 # This test used to coredump. The BEGIN block is important as it causes the
314 # op that created the constant reference to be freed. Hence the only
315 # reference to the constant string "pass" is in $a. The hack that made
316 # sure $a = $a->[1] would work didn't work with references to constants.
317
318
319 foreach my $lexical ('', 'my $a; ') {
320   my $expect = "pass\n";
321   my $result = runperl (switches => ['-wl'], stderr => 1,
322     prog => $lexical . 'BEGIN {$a = \q{pass}}; $a = $$a; print $a');
323
324   is ($?, 0);
325   is ($result, $expect);
326 }
327
328 my $test = curr_test();
329 sub x::DESTROY {print "ok ", $test + shift->[0], "\n"}
330 { my $a1 = bless [3],"x";
331   my $a2 = bless [2],"x";
332   { my $a3 = bless [1],"x";
333     my $a4 = bless [0],"x";
334     567;
335   }
336 }
337 curr_test($test+4);
338
339 is (runperl (switches=>['-l'],
340              prog=> 'print 1; print qq-*$\*-;print 1;'),
341     "1\n*\n*\n1\n");
342
343 # bug #21347
344
345 runperl(prog => 'sub UNIVERSAL::AUTOLOAD { qr// } a->p' );
346 is ($?, 0, 'UNIVERSAL::AUTOLOAD called when freeing qr//');
347
348 runperl(prog => 'sub UNIVERSAL::DESTROY { warn } bless \$a, A', stderr => 1);
349 is ($?, 0, 'warn called inside UNIVERSAL::DESTROY');
350
351
352 # bug #22719
353
354 runperl(prog => 'sub f { my $x = shift; *z = $x; } f({}); f();');
355 is ($?, 0, 'coredump on typeglob = (SvRV && !SvROK)');
356
357 # bug #27268: freeing self-referential typeglobs could trigger
358 # "Attempt to free unreferenced scalar" warnings
359
360 is (runperl(
361     prog => 'use Symbol;my $x=bless \gensym,"t"; print;*$$x=$x',
362     stderr => 1
363 ), '', 'freeing self-referential typeglob');
364
365 # using a regex in the destructor for STDOUT segfaulted because the
366 # REGEX pad had already been freed (ithreads build only). The
367 # object is required to trigger the early freeing of GV refs to to STDOUT
368
369 like (runperl(
370     prog => '$x=bless[]; sub IO::Handle::DESTROY{$_="bad";s/bad/ok/;print}',
371     stderr => 1
372       ), qr/^(ok)+$/, 'STDOUT destructor');
373
374 # Bit of a hack to make test.pl happy. There are 3 more tests after it leaves.
375 $test = curr_test();
376 curr_test($test + 3);
377 # test global destruction
378
379 my $test1 = $test + 1;
380 my $test2 = $test + 2;
381
382 package FINALE;
383
384 {
385     $ref3 = bless ["ok $test2\n"];      # package destruction
386     my $ref2 = bless ["ok $test1\n"];   # lexical destruction
387     local $ref1 = bless ["ok $test\n"]; # dynamic destruction
388     1;                                  # flush any temp values on stack
389 }
390
391 DESTROY {
392     print $_[0][0];
393 }
394