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