xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/t/op/tie.t (revision 0:68f95e015346)
1#!./perl
2
3# Add new tests to the end with format:
4# ########
5#
6# # test description
7# Test code
8# EXPECT
9# Warn or die msgs (if any) at - line 1234
10#
11
12chdir 't' if -d 't';
13@INC = '../lib';
14$ENV{PERL5LIB} = "../lib";
15
16$|=1;
17
18undef $/;
19@prgs = split /^########\n/m, <DATA>;
20
21require './test.pl';
22plan(tests => scalar @prgs);
23for (@prgs){
24    ++$i;
25    my($prog,$expected) = split(/\nEXPECT\n/, $_, 2);
26    print("not ok $i # bad test format\n"), next
27        unless defined $expected;
28    my ($testname) = $prog =~ /^# (.*)\n/m;
29    $testname ||= '';
30    $TODO = $testname =~ s/^TODO //;
31    $results =~ s/\n+$//;
32    $expected =~ s/\n+$//;
33
34    fresh_perl_is($prog, $expected, {}, $testname);
35}
36
37__END__
38
39# standard behaviour, without any extra references
40use Tie::Hash ;
41tie %h, Tie::StdHash;
42untie %h;
43EXPECT
44########
45
46# standard behaviour, without any extra references
47use Tie::Hash ;
48{package Tie::HashUntie;
49 use base 'Tie::StdHash';
50 sub UNTIE
51  {
52   warn "Untied\n";
53  }
54}
55tie %h, Tie::HashUntie;
56untie %h;
57EXPECT
58Untied
59########
60
61# standard behaviour, with 1 extra reference
62use Tie::Hash ;
63$a = tie %h, Tie::StdHash;
64untie %h;
65EXPECT
66########
67
68# standard behaviour, with 1 extra reference via tied
69use Tie::Hash ;
70tie %h, Tie::StdHash;
71$a = tied %h;
72untie %h;
73EXPECT
74########
75
76# standard behaviour, with 1 extra reference which is destroyed
77use Tie::Hash ;
78$a = tie %h, Tie::StdHash;
79$a = 0 ;
80untie %h;
81EXPECT
82########
83
84# standard behaviour, with 1 extra reference via tied which is destroyed
85use Tie::Hash ;
86tie %h, Tie::StdHash;
87$a = tied %h;
88$a = 0 ;
89untie %h;
90EXPECT
91########
92
93# strict behaviour, without any extra references
94use warnings 'untie';
95use Tie::Hash ;
96tie %h, Tie::StdHash;
97untie %h;
98EXPECT
99########
100
101# strict behaviour, with 1 extra references generating an error
102use warnings 'untie';
103use Tie::Hash ;
104$a = tie %h, Tie::StdHash;
105untie %h;
106EXPECT
107untie attempted while 1 inner references still exist at - line 6.
108########
109
110# strict behaviour, with 1 extra references via tied generating an error
111use warnings 'untie';
112use Tie::Hash ;
113tie %h, Tie::StdHash;
114$a = tied %h;
115untie %h;
116EXPECT
117untie attempted while 1 inner references still exist at - line 7.
118########
119
120# strict behaviour, with 1 extra references which are destroyed
121use warnings 'untie';
122use Tie::Hash ;
123$a = tie %h, Tie::StdHash;
124$a = 0 ;
125untie %h;
126EXPECT
127########
128
129# strict behaviour, with extra 1 references via tied which are destroyed
130use warnings 'untie';
131use Tie::Hash ;
132tie %h, Tie::StdHash;
133$a = tied %h;
134$a = 0 ;
135untie %h;
136EXPECT
137########
138
139# strict error behaviour, with 2 extra references
140use warnings 'untie';
141use Tie::Hash ;
142$a = tie %h, Tie::StdHash;
143$b = tied %h ;
144untie %h;
145EXPECT
146untie attempted while 2 inner references still exist at - line 7.
147########
148
149# strict behaviour, check scope of strictness.
150no warnings 'untie';
151use Tie::Hash ;
152$A = tie %H, Tie::StdHash;
153$C = $B = tied %H ;
154{
155    use warnings 'untie';
156    use Tie::Hash ;
157    tie %h, Tie::StdHash;
158    untie %h;
159}
160untie %H;
161EXPECT
162########
163
164# Forbidden aggregate self-ties
165sub Self::TIEHASH { bless $_[1], $_[0] }
166{
167    my %c;
168    tie %c, 'Self', \%c;
169}
170EXPECT
171Self-ties of arrays and hashes are not supported at - line 6.
172########
173
174# Allowed scalar self-ties
175my $destroyed = 0;
176sub Self::TIESCALAR { bless $_[1], $_[0] }
177sub Self::DESTROY   { $destroyed = 1; }
178{
179    my $c = 42;
180    tie $c, 'Self', \$c;
181}
182die "self-tied scalar not DESTROYed" unless $destroyed == 1;
183EXPECT
184########
185
186# Allowed glob self-ties
187my $destroyed = 0;
188my $printed   = 0;
189sub Self2::TIEHANDLE { bless $_[1], $_[0] }
190sub Self2::DESTROY   { $destroyed = 1; }
191sub Self2::PRINT     { $printed = 1; }
192{
193    use Symbol;
194    my $c = gensym;
195    tie *$c, 'Self2', $c;
196    print $c 'Hello';
197}
198die "self-tied glob not PRINTed" unless $printed == 1;
199die "self-tied glob not DESTROYed" unless $destroyed == 1;
200EXPECT
201########
202
203# Allowed IO self-ties
204my $destroyed = 0;
205sub Self3::TIEHANDLE { bless $_[1], $_[0] }
206sub Self3::DESTROY   { $destroyed = 1; }
207sub Self3::PRINT     { $printed = 1; }
208{
209    use Symbol 'geniosym';
210    my $c = geniosym;
211    tie *$c, 'Self3', $c;
212    print $c 'Hello';
213}
214die "self-tied IO not PRINTed" unless $printed == 1;
215die "self-tied IO not DESTROYed" unless $destroyed == 1;
216EXPECT
217########
218
219# TODO IO "self-tie" via TEMP glob
220my $destroyed = 0;
221sub Self3::TIEHANDLE { bless $_[1], $_[0] }
222sub Self3::DESTROY   { $destroyed = 1; }
223sub Self3::PRINT     { $printed = 1; }
224{
225    use Symbol 'geniosym';
226    my $c = geniosym;
227    tie *$c, 'Self3', \*$c;
228    print $c 'Hello';
229}
230die "IO tied to TEMP glob not PRINTed" unless $printed == 1;
231die "IO tied to TEMP glob not DESTROYed" unless $destroyed == 1;
232EXPECT
233########
234
235# Interaction of tie and vec
236
237my ($a, $b);
238use Tie::Scalar;
239tie $a,Tie::StdScalar or die;
240vec($b,1,1)=1;
241$a = $b;
242vec($a,1,1)=0;
243vec($b,1,1)=0;
244die unless $a eq $b;
245EXPECT
246########
247
248# correct unlocalisation of tied hashes (patch #16431)
249use Tie::Hash ;
250tie %tied, Tie::StdHash;
251{ local $hash{'foo'} } warn "plain hash bad unlocalize" if exists $hash{'foo'};
252{ local $tied{'foo'} } warn "tied hash bad unlocalize" if exists $tied{'foo'};
253{ local $ENV{'foo'}  } warn "%ENV bad unlocalize" if exists $ENV{'foo'};
254EXPECT
255########
256
257# An attempt at lvalueable barewords broke this
258tie FH, 'main';
259EXPECT
260Can't modify constant item in tie at - line 3, near "'main';"
261Execution of - aborted due to compilation errors.
262########
263
264# localizing tied hash slices
265$ENV{FooA} = 1;
266$ENV{FooB} = 2;
267print exists $ENV{FooA} ? 1 : 0, "\n";
268print exists $ENV{FooB} ? 2 : 0, "\n";
269print exists $ENV{FooC} ? 3 : 0, "\n";
270{
271    local @ENV{qw(FooA FooC)};
272    print exists $ENV{FooA} ? 4 : 0, "\n";
273    print exists $ENV{FooB} ? 5 : 0, "\n";
274    print exists $ENV{FooC} ? 6 : 0, "\n";
275}
276print exists $ENV{FooA} ? 7 : 0, "\n";
277print exists $ENV{FooB} ? 8 : 0, "\n";
278print exists $ENV{FooC} ? 9 : 0, "\n"; # this should not exist
279EXPECT
2801
2812
2820
2834
2845
2856
2867
2878
2880
289########
290#
291# FETCH freeing tie'd SV
292sub TIESCALAR { bless [] }
293sub FETCH { *a = \1; 1 }
294tie $a, 'main';
295print $a;
296EXPECT
297Tied variable freed while still in use at - line 6.
298########
299
300#  [20020716.007] - nested FETCHES
301
302sub F1::TIEARRAY { bless [], 'F1' }
303sub F1::FETCH { 1 }
304my @f1;
305tie @f1, 'F1';
306
307sub F2::TIEARRAY { bless [2], 'F2' }
308sub F2::FETCH { my $self = shift; my $x = $f1[3]; $self }
309my @f2;
310tie @f2, 'F2';
311
312print $f2[4][0],"\n";
313
314sub F3::TIEHASH { bless [], 'F3' }
315sub F3::FETCH { 1 }
316my %f3;
317tie %f3, 'F3';
318
319sub F4::TIEHASH { bless [3], 'F4' }
320sub F4::FETCH { my $self = shift; my $x = $f3{3}; $self }
321my %f4;
322tie %f4, 'F4';
323
324print $f4{'foo'}[0],"\n";
325
326EXPECT
3272
3283
329########
330# test untie() from within FETCH
331package Foo;
332sub TIESCALAR { my $pkg = shift; return bless [@_], $pkg; }
333sub FETCH {
334  my $self = shift;
335  my ($obj, $field) = @$self;
336  untie $obj->{$field};
337  $obj->{$field} = "Bar";
338}
339package main;
340tie $a->{foo}, "Foo", $a, "foo";
341$a->{foo}; # access once
342# the hash element should not be tied anymore
343print defined tied $a->{foo} ? "not ok" : "ok";
344EXPECT
345ok
346########
347# the tmps returned by FETCH should appear to be SCALAR
348# (even though they are now implemented using PVLVs.)
349package X;
350sub TIEHASH { bless {} }
351sub TIEARRAY { bless {} }
352sub FETCH {1}
353my (%h, @a);
354tie %h, 'X';
355tie @a, 'X';
356my $r1 = \$h{1};
357my $r2 = \$a[0];
358my $s = "$r1 ". ref($r1) . " $r2 " . ref($r2);
359$s=~ s/\(0x\w+\)//g;
360print $s, "\n";
361EXPECT
362SCALAR SCALAR SCALAR SCALAR
363########
364# [perl #23287] segfault in untie
365sub TIESCALAR { bless $_[1], $_[0] }
366my $var;
367tie $var, 'main', \$var;
368untie $var;
369EXPECT
370########
371# Test case from perlmonks by runrig
372# http://www.perlmonks.org/index.pl?node_id=273490
373# "Here is what I tried. I think its similar to what you've tried
374#  above. Its odd but convienient that after untie'ing you are left with
375#  a variable that has the same value as was last returned from
376#  FETCH. (At least on my perl v5.6.1). So you don't need to pass a
377#  reference to the variable in order to set it after the untie (here it
378#  is accessed through a closure)."
379use strict;
380use warnings;
381package MyTied;
382sub TIESCALAR {
383    my ($class,$code) = @_;
384    bless $code, $class;
385}
386sub FETCH {
387    my $self = shift;
388    print "Untie\n";
389    $self->();
390}
391package main;
392my $var;
393tie $var, 'MyTied', sub { untie $var; 4 };
394print "One\n";
395print "$var\n";
396print "Two\n";
397print "$var\n";
398print "Three\n";
399print "$var\n";
400EXPECT
401One
402Untie
4034
404Two
4054
406Three
4074
408########
409# [perl #22297] cannot untie scalar from within tied FETCH
410my $counter = 0;
411my $x = 7;
412my $ref = \$x;
413tie $x, 'Overlay', $ref, $x;
414my $y;
415$y = $x;
416$y = $x;
417$y = $x;
418$y = $x;
419#print "WILL EXTERNAL UNTIE $ref\n";
420untie $$ref;
421$y = $x;
422$y = $x;
423$y = $x;
424$y = $x;
425#print "counter = $counter\n";
426
427print (($counter == 1) ? "ok\n" : "not ok\n");
428
429package Overlay;
430
431sub TIESCALAR
432{
433        my $pkg = shift;
434        my ($ref, $val) = @_;
435        return bless [ $ref, $val ], $pkg;
436}
437
438sub FETCH
439{
440        my $self = shift;
441        my ($ref, $val) = @$self;
442        #print "WILL INTERNAL UNITE $ref\n";
443        $counter++;
444        untie $$ref;
445        return $val;
446}
447EXPECT
448ok
449########
450
451# test SCALAR method
452package TieScalar;
453
454sub TIEHASH {
455    my $pkg = shift;
456    bless { } => $pkg;
457}
458
459sub STORE {
460    $_[0]->{$_[1]} = $_[2];
461}
462
463sub FETCH {
464    $_[0]->{$_[1]}
465}
466
467sub CLEAR {
468    %{ $_[0] } = ();
469}
470
471sub SCALAR {
472    print "SCALAR\n";
473    return 0 if ! keys %{$_[0]};
474    sprintf "%i/%i", scalar keys %{$_[0]}, scalar keys %{$_[0]};
475}
476
477package main;
478tie my %h => "TieScalar";
479$h{key1} = "val1";
480$h{key2} = "val2";
481print scalar %h, "\n";
482%h = ();
483print scalar %h, "\n";
484EXPECT
485SCALAR
4862/2
487SCALAR
4880
489########
490
491# test scalar on tied hash when no SCALAR method has been given
492package TieScalar;
493
494sub TIEHASH {
495    my $pkg = shift;
496    bless { } => $pkg;
497}
498sub STORE {
499    $_[0]->{$_[1]} = $_[2];
500}
501sub FETCH {
502    $_[0]->{$_[1]}
503}
504sub CLEAR {
505    %{ $_[0] } = ();
506}
507sub FIRSTKEY {
508    my $a = keys %{ $_[0] };
509    print "FIRSTKEY\n";
510    each %{ $_[0] };
511}
512
513package main;
514tie my %h => "TieScalar";
515
516if (!%h) {
517    print "empty\n";
518} else {
519    print "not empty\n";
520}
521
522$h{key1} = "val1";
523print "not empty\n" if %h;
524print "not empty\n" if %h;
525print "-->\n";
526my ($k,$v) = each %h;
527print "<--\n";
528print "not empty\n" if %h;
529%h = ();
530print "empty\n" if ! %h;
531EXPECT
532FIRSTKEY
533empty
534FIRSTKEY
535not empty
536FIRSTKEY
537not empty
538-->
539FIRSTKEY
540<--
541not empty
542FIRSTKEY
543empty
544