xref: /openbsd/gnu/usr.bin/perl/t/op/tiehandle.t (revision 8932bfb7)
1#!./perl -w
2
3BEGIN {
4    chdir 't' if -d 't';
5    @INC = '../lib';
6}
7
8my @expect;
9my $data = "";
10my @data = ();
11
12require './test.pl';
13plan(tests => 63);
14
15sub compare {
16    local $Level = $Level + 1;
17
18    return unless @expect;
19    return ::fail() unless(@_ == @expect);
20
21    for my $i (0..$#_) {
22	next if $_[$i] eq $expect[$i];
23	return ::fail();
24    }
25
26    ::pass();
27}
28
29
30package Implement;
31
32sub TIEHANDLE {
33    ::compare(TIEHANDLE => @_);
34    my ($class,@val) = @_;
35    return bless \@val,$class;
36}
37
38sub PRINT {
39    ::compare(PRINT => @_);
40    1;
41}
42
43sub PRINTF {
44    ::compare(PRINTF => @_);
45    2;
46}
47
48sub READLINE {
49    ::compare(READLINE => @_);
50    wantarray ? @data : shift @data;
51}
52
53sub GETC {
54    ::compare(GETC => @_);
55    substr($data,0,1);
56}
57
58sub READ {
59    ::compare(READ => @_);
60    substr($_[1],$_[3] || 0) = substr($data,0,$_[2]);
61    3;
62}
63
64sub EOF {
65    ::compare(EOF => @_);
66    @data ? '' : 1;
67}
68
69sub WRITE {
70    ::compare(WRITE => @_);
71    $data = substr($_[1],$_[3] || 0, $_[2]);
72    length($data);
73}
74
75sub CLOSE {
76    ::compare(CLOSE => @_);
77    5;
78}
79
80package main;
81
82use Symbol;
83
84my $fh = gensym;
85
86@expect = (TIEHANDLE => 'Implement');
87my $ob = tie *$fh,'Implement';
88is(ref($ob),  'Implement');
89is(tied(*$fh), $ob);
90
91@expect = (PRINT => $ob,"some","text");
92$r = print $fh @expect[2,3];
93is($r, 1);
94
95@expect = (PRINTF => $ob,"%s","text");
96$r = printf $fh @expect[2,3];
97is($r, 2);
98
99@data = ("the line\n");
100@expect = (EOF => $ob, 1);
101is(eof($fh), '');
102
103$text = $data[0];
104@expect = (READLINE => $ob);
105$ln = <$fh>;
106is($ln, $text);
107
108@expect = (EOF => $ob, 0);
109is(eof, 1);
110
111@expect = ();
112@in = @data = qw(a line at a time);
113@line = <$fh>;
114@expect = @in;
115compare(@line);
116
117@expect = (GETC => $ob);
118$data = "abc";
119$ch = getc $fh;
120is($ch, "a");
121
122$buf = "xyz";
123@expect = (READ => $ob, $buf, 3);
124$data = "abc";
125$r = read $fh,$buf,3;
126is($r, 3);
127is($buf, "abc");
128
129
130$buf = "xyzasd";
131@expect = (READ => $ob, $buf, 3,3);
132$data = "abc";
133$r = sysread $fh,$buf,3,3;
134is($r, 3);
135is($buf, "xyzabc");
136
137$buf = "qwerty";
138@expect = (WRITE => $ob, $buf, 4,1);
139$data = "";
140$r = syswrite $fh,$buf,4,1;
141is($r, 4);
142is($data, "wert");
143
144$buf = "qwerty";
145@expect = (WRITE => $ob, $buf, 4);
146$data = "";
147$r = syswrite $fh,$buf,4;
148is($r, 4);
149is($data, "qwer");
150
151$buf = "qwerty";
152@expect = (WRITE => $ob, $buf, 6);
153$data = "";
154$r = syswrite $fh,$buf;
155is($r, 6);
156is($data, "qwerty");
157
158@expect = (CLOSE => $ob);
159$r = close $fh;
160is($r, 5);
161
162# Does aliasing work with tied FHs?
163*ALIAS = *$fh;
164@expect = (PRINT => $ob,"some","text");
165$r = print ALIAS @expect[2,3];
166is($r, 1);
167
168{
169    use warnings;
170    # Special case of aliasing STDERR, which used
171    # to dump core when warnings were enabled
172    local *STDERR = *$fh;
173    @expect = (PRINT => $ob,"some","text");
174    $r = print STDERR @expect[2,3];
175    is($r, 1);
176}
177
178{
179    package Bar::Say;
180    use feature 'say';
181    use base qw(Implement);
182
183    my $ors;
184    sub PRINT     {
185        $ors = $\;
186        my $self = shift;
187        return $self->SUPER::PRINT(@_);
188    }
189
190    my $fh = Symbol::gensym;
191    @expect = (TIEHANDLE => 'Bar::Say');
192    ::ok( my $obj = tie *$fh, 'Bar::Say' );
193
194    local $\ = 'something';
195    @expect = (PRINT => $obj, "stuff", "and", "things");
196    ::ok( print $fh @expect[2..4] );
197    ::is( $ors, 'something' );
198
199    ::ok( say $fh @expect[2..4] );
200    ::is( $ors, "\n",        'say sets $\ to \n in PRINT' );
201    ::is( $\,   "something", "  and it's localized" );
202}
203
204{
205    # Test for change #11536
206    package Foo;
207    use strict;
208    sub TIEHANDLE { bless {} }
209    my $cnt = 'a';
210    sub READ {
211	$_[1] = $cnt++;
212	1;
213    }
214    sub do_read {
215	my $fh = shift;
216	read $fh, my $buff, 1;
217	::pass();
218    }
219    $|=1;
220    tie *STDIN, 'Foo';
221    read STDIN, my $buff, 1;
222    ::pass();
223    do_read(\*STDIN);
224    untie *STDIN;
225}
226
227
228{
229    # test for change 11639: Can't localize *FH, then tie it
230    {
231	local *foo;
232	tie %foo, 'Blah';
233    }
234    ok(!tied %foo);
235
236    {
237	local *bar;
238	tie @bar, 'Blah';
239    }
240    ok(!tied @bar);
241
242    {
243	local *BAZ;
244	tie *BAZ, 'Blah';
245    }
246    ok(!tied *BAZ);
247
248    package Blah;
249
250    sub TIEHANDLE {bless {}}
251    sub TIEHASH   {bless {}}
252    sub TIEARRAY  {bless {}}
253}
254
255{
256    # warnings should pass to the PRINT method of tied STDERR
257    my @received;
258
259    local *STDERR = *$fh;
260    no warnings 'redefine';
261    local *Implement::PRINT = sub { @received = @_ };
262
263    $r = warn("some", "text", "\n");
264    @expect = (PRINT => $ob,"sometext\n");
265
266    compare(PRINT => @received);
267
268    use warnings;
269    print undef;
270
271    like($received[1], qr/Use of uninitialized value/);
272}
273
274{
275    # [ID 20020713.001] chomp($data=<tied_fh>)
276    local *TEST;
277    tie *TEST, 'CHOMP';
278    my $data;
279    chomp($data = <TEST>);
280    is($data, 'foobar');
281
282    package CHOMP;
283    sub TIEHANDLE { bless {}, $_[0] }
284    sub READLINE { "foobar\n" }
285}
286
287{
288    # make sure the new eof() features work with @ARGV magic
289    local *ARGV;
290    @ARGV = ('haha');
291
292    @expect = (TIEHANDLE => 'Implement');
293    $ob = tie *ARGV, 'Implement';
294    is(ref($ob),  'Implement');
295    is(tied(*ARGV), $ob);
296
297    @data = ("stuff\n");
298    @expect = (EOF => $ob, 1);
299    is(eof(ARGV), '');
300    @expect = (EOF => $ob, 2);
301    is(eof(), '');
302    shift @data;
303    @expect = (EOF => $ob, 0);
304    is(eof, 1);
305}
306