xref: /openbsd-src/gnu/usr.bin/perl/t/io/scalar.t (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
1*5486feefSafresh1#!./perl
2*5486feefSafresh1
3*5486feefSafresh1BEGIN {
4*5486feefSafresh1    chdir 't' if -d 't';
5*5486feefSafresh1    require './test.pl';
6*5486feefSafresh1    set_up_inc('../lib');
7*5486feefSafresh1	skip_all('Can\'t run under miniperl') if is_miniperl();
8*5486feefSafresh1}
9*5486feefSafresh1
10*5486feefSafresh1use strict;
11*5486feefSafresh1
12*5486feefSafresh1use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END); # Not 0, 1, 2 everywhere.
13*5486feefSafresh1use Errno qw(EACCES);
14*5486feefSafresh1
15*5486feefSafresh1plan(128);
16*5486feefSafresh1
17*5486feefSafresh1my $fh;
18*5486feefSafresh1my $var = "aaa\n";
19*5486feefSafresh1ok(open($fh,"+<",\$var));
20*5486feefSafresh1
21*5486feefSafresh1is(<$fh>, $var);
22*5486feefSafresh1
23*5486feefSafresh1ok(eof($fh));
24*5486feefSafresh1
25*5486feefSafresh1ok(seek($fh,0,SEEK_SET));
26*5486feefSafresh1ok(!eof($fh));
27*5486feefSafresh1
28*5486feefSafresh1ok(print $fh "bbb\n");
29*5486feefSafresh1is($var, "bbb\n");
30*5486feefSafresh1$var = "foo\nbar\n";
31*5486feefSafresh1ok(seek($fh,0,SEEK_SET));
32*5486feefSafresh1ok(!eof($fh));
33*5486feefSafresh1is(<$fh>, "foo\n");
34*5486feefSafresh1ok(close $fh, $!);
35*5486feefSafresh1
36*5486feefSafresh1# Test that semantics are similar to normal file-based I/O
37*5486feefSafresh1# Check that ">" clobbers the scalar
38*5486feefSafresh1$var = "Something";
39*5486feefSafresh1open $fh, ">", \$var;
40*5486feefSafresh1is($var, "");
41*5486feefSafresh1#  Check that file offset set to beginning of scalar
42*5486feefSafresh1my $off = tell($fh);
43*5486feefSafresh1is($off, 0);
44*5486feefSafresh1# Check that writes go where they should and update the offset
45*5486feefSafresh1$var = "Something";
46*5486feefSafresh1print $fh "Brea";
47*5486feefSafresh1$off = tell($fh);
48*5486feefSafresh1is($off, 4);
49*5486feefSafresh1is($var, "Breathing");
50*5486feefSafresh1close $fh;
51*5486feefSafresh1
52*5486feefSafresh1# Check that ">>" appends to the scalar
53*5486feefSafresh1$var = "Something ";
54*5486feefSafresh1open $fh, ">>", \$var;
55*5486feefSafresh1$off = tell($fh);
56*5486feefSafresh1is($off, 10);
57*5486feefSafresh1is($var, "Something ");
58*5486feefSafresh1#  Check that further writes go to the very end of the scalar
59*5486feefSafresh1$var .= "else ";
60*5486feefSafresh1is($var, "Something else ");
61*5486feefSafresh1
62*5486feefSafresh1$off = tell($fh);
63*5486feefSafresh1is($off, 10);
64*5486feefSafresh1
65*5486feefSafresh1print $fh "is here";
66*5486feefSafresh1is($var, "Something else is here");
67*5486feefSafresh1close $fh;
68*5486feefSafresh1
69*5486feefSafresh1# Check that updates to the scalar from elsewhere do not
70*5486feefSafresh1# cause problems
71*5486feefSafresh1$var = "line one\nline two\line three\n";
72*5486feefSafresh1open $fh, "<", \$var;
73*5486feefSafresh1while (<$fh>) {
74*5486feefSafresh1    $var = "foo";
75*5486feefSafresh1}
76*5486feefSafresh1close $fh;
77*5486feefSafresh1is($var, "foo");
78*5486feefSafresh1
79*5486feefSafresh1# Check that dup'ing the handle works
80*5486feefSafresh1
81*5486feefSafresh1$var = '';
82*5486feefSafresh1open $fh, "+>", \$var;
83*5486feefSafresh1print $fh "xxx\n";
84*5486feefSafresh1open my $dup,'+<&',$fh;
85*5486feefSafresh1print $dup "yyy\n";
86*5486feefSafresh1seek($dup,0,SEEK_SET);
87*5486feefSafresh1is(<$dup>, "xxx\n");
88*5486feefSafresh1is(<$dup>, "yyy\n");
89*5486feefSafresh1close($fh);
90*5486feefSafresh1close($dup);
91*5486feefSafresh1
92*5486feefSafresh1open $fh, '<', \42;
93*5486feefSafresh1is(<$fh>, "42", "reading from non-string scalars");
94*5486feefSafresh1close $fh;
95*5486feefSafresh1
96*5486feefSafresh1{ package P; sub TIESCALAR {bless{}} sub FETCH { "shazam" } sub STORE {} }
97*5486feefSafresh1tie my $p, 'P'; open $fh, '<', \$p;
98*5486feefSafresh1is(<$fh>, "shazam", "reading from magic scalars");
99*5486feefSafresh1
100*5486feefSafresh1{
101*5486feefSafresh1    use warnings;
102*5486feefSafresh1    my $warn = 0;
103*5486feefSafresh1    local $SIG{__WARN__} = sub { $warn++ };
104*5486feefSafresh1    open my $fh, '>', \my $scalar;
105*5486feefSafresh1    print $fh "foo";
106*5486feefSafresh1    close $fh;
107*5486feefSafresh1    is($warn, 0, "no warnings when writing to an undefined scalar");
108*5486feefSafresh1    undef $scalar;
109*5486feefSafresh1    open $fh, '>>', \$scalar;
110*5486feefSafresh1    print $fh "oof";
111*5486feefSafresh1    close $fh;
112*5486feefSafresh1    is($warn, 0, "no warnings when appending to an undefined scalar");
113*5486feefSafresh1}
114*5486feefSafresh1
115*5486feefSafresh1{
116*5486feefSafresh1    use warnings;
117*5486feefSafresh1    my $warn = 0;
118*5486feefSafresh1    local $SIG{__WARN__} = sub { $warn++ };
119*5486feefSafresh1    for (1..2) {
120*5486feefSafresh1        open my $fh, '>', \my $scalar;
121*5486feefSafresh1        close $fh;
122*5486feefSafresh1    }
123*5486feefSafresh1    is($warn, 0, "no warnings when reusing a lexical");
124*5486feefSafresh1}
125*5486feefSafresh1
126*5486feefSafresh1{
127*5486feefSafresh1    use warnings;
128*5486feefSafresh1    my $warn = 0;
129*5486feefSafresh1    local $SIG{__WARN__} = sub { $warn++ };
130*5486feefSafresh1
131*5486feefSafresh1    my $fetch = 0;
132*5486feefSafresh1    {
133*5486feefSafresh1        package MgUndef;
134*5486feefSafresh1        sub TIESCALAR { bless [] }
135*5486feefSafresh1        sub FETCH { $fetch++; return undef }
136*5486feefSafresh1	sub STORE {}
137*5486feefSafresh1    }
138*5486feefSafresh1    tie my $scalar, 'MgUndef';
139*5486feefSafresh1
140*5486feefSafresh1    open my $fh, '<', \$scalar;
141*5486feefSafresh1    close $fh;
142*5486feefSafresh1    is($warn, 0, "no warnings reading a magical undef scalar");
143*5486feefSafresh1    is($fetch, 1, "FETCH only called once");
144*5486feefSafresh1}
145*5486feefSafresh1
146*5486feefSafresh1{
147*5486feefSafresh1    use warnings;
148*5486feefSafresh1    my $warn = 0;
149*5486feefSafresh1    local $SIG{__WARN__} = sub { $warn++ };
150*5486feefSafresh1    my $scalar = 3;
151*5486feefSafresh1    undef $scalar;
152*5486feefSafresh1    open my $fh, '<', \$scalar;
153*5486feefSafresh1    close $fh;
154*5486feefSafresh1    is($warn, 0, "no warnings reading an undef, allocated scalar");
155*5486feefSafresh1}
156*5486feefSafresh1
157*5486feefSafresh1my $data = "a non-empty PV";
158*5486feefSafresh1$data = undef;
159*5486feefSafresh1open(MEM, '<', \$data) or die "Fail: $!\n";
160*5486feefSafresh1my $x = join '', <MEM>;
161*5486feefSafresh1is($x, '');
162*5486feefSafresh1
163*5486feefSafresh1{
164*5486feefSafresh1    # [perl #35929] verify that works with $/ (i.e. test PerlIOScalar_unread)
165*5486feefSafresh1    my $s = <<'EOF';
166*5486feefSafresh1line A
167*5486feefSafresh1line B
168*5486feefSafresh1a third line
169*5486feefSafresh1EOF
170*5486feefSafresh1    open(F, '<', \$s) or die "Could not open string as a file";
171*5486feefSafresh1    local $/ = "";
172*5486feefSafresh1    my $ln = <F>;
173*5486feefSafresh1    close F;
174*5486feefSafresh1    is($ln, $s, "[perl #35929]");
175*5486feefSafresh1}
176*5486feefSafresh1
177*5486feefSafresh1# [perl #40267] PerlIO::scalar doesn't respect readonly-ness
178*5486feefSafresh1{
179*5486feefSafresh1    my $warn;
180*5486feefSafresh1    local $SIG{__WARN__} = sub { $warn = "@_" };
181*5486feefSafresh1    ok(!(defined open(F, '>', \undef)), "[perl #40267] - $!");
182*5486feefSafresh1    is($warn, undef, "no warning with warnings off");
183*5486feefSafresh1    close F;
184*5486feefSafresh1
185*5486feefSafresh1    use warnings 'layer';
186*5486feefSafresh1    undef $warn;
187*5486feefSafresh1    my $ro = \43;
188*5486feefSafresh1    ok(!(defined open(F, '>', $ro)), $!);
189*5486feefSafresh1    is($!+0, EACCES, "check we get a read-onlyish error code");
190*5486feefSafresh1    like($warn, qr/Modification of a read-only value attempted/,
191*5486feefSafresh1         "check we did warn");
192*5486feefSafresh1    close F;
193*5486feefSafresh1    # but we can read from it
194*5486feefSafresh1    ok(open(F, '<', $ro), $!);
195*5486feefSafresh1    is(<F>, 43);
196*5486feefSafresh1    close F;
197*5486feefSafresh1}
198*5486feefSafresh1
199*5486feefSafresh1{
200*5486feefSafresh1    # Check that we zero fill when needed when seeking,
201*5486feefSafresh1    # and that seeking negative off the string does not do bad things.
202*5486feefSafresh1
203*5486feefSafresh1    my $foo;
204*5486feefSafresh1
205*5486feefSafresh1    ok(open(F, '>', \$foo));
206*5486feefSafresh1
207*5486feefSafresh1    # Seeking forward should zero fill.
208*5486feefSafresh1
209*5486feefSafresh1    ok(seek(F, 50, SEEK_SET));
210*5486feefSafresh1    print F "x";
211*5486feefSafresh1    is(length($foo), 51);
212*5486feefSafresh1    like($foo, qr/^\0{50}x$/);
213*5486feefSafresh1
214*5486feefSafresh1    is(tell(F), 51);
215*5486feefSafresh1    ok(seek(F, 0, SEEK_SET));
216*5486feefSafresh1    is(length($foo), 51);
217*5486feefSafresh1
218*5486feefSafresh1    # Seeking forward again should zero fill but only the new bytes.
219*5486feefSafresh1
220*5486feefSafresh1    ok(seek(F, 100, SEEK_SET));
221*5486feefSafresh1    print F "y";
222*5486feefSafresh1    is(length($foo), 101);
223*5486feefSafresh1    like($foo, qr/^\0{50}x\0{49}y$/);
224*5486feefSafresh1    is(tell(F), 101);
225*5486feefSafresh1
226*5486feefSafresh1    # Seeking back and writing should not zero fill.
227*5486feefSafresh1
228*5486feefSafresh1    ok(seek(F, 75, SEEK_SET));
229*5486feefSafresh1    print F "z";
230*5486feefSafresh1    is(length($foo), 101);
231*5486feefSafresh1    like($foo, qr/^\0{50}x\0{24}z\0{24}y$/);
232*5486feefSafresh1    is(tell(F), 76);
233*5486feefSafresh1
234*5486feefSafresh1    # Seeking negative should not do funny business.
235*5486feefSafresh1
236*5486feefSafresh1    ok(!seek(F,  -50, SEEK_SET), $!);
237*5486feefSafresh1    ok(seek(F, 0, SEEK_SET));
238*5486feefSafresh1    ok(!seek(F,  -50, SEEK_CUR), $!);
239*5486feefSafresh1    ok(!seek(F, -150, SEEK_END), $!);
240*5486feefSafresh1}
241*5486feefSafresh1
242*5486feefSafresh1# RT #43789: should respect tied scalar
243*5486feefSafresh1
244*5486feefSafresh1{
245*5486feefSafresh1    package TS;
246*5486feefSafresh1    my $s;
247*5486feefSafresh1    sub TIESCALAR { bless \my $x }
248*5486feefSafresh1    sub FETCH { $s .= ':F'; ${$_[0]} }
249*5486feefSafresh1    sub STORE { $s .= ":S($_[1])"; ${$_[0]} = $_[1] }
250*5486feefSafresh1
251*5486feefSafresh1    package main;
252*5486feefSafresh1
253*5486feefSafresh1    my $x;
254*5486feefSafresh1    $s = '';
255*5486feefSafresh1    tie $x, 'TS';
256*5486feefSafresh1    my $fh;
257*5486feefSafresh1
258*5486feefSafresh1    ok(open($fh, '>', \$x), 'open-write tied scalar');
259*5486feefSafresh1    $s .= ':O';
260*5486feefSafresh1    print($fh 'ABC');
261*5486feefSafresh1    $s .= ':P';
262*5486feefSafresh1    ok(seek($fh, 0, SEEK_SET));
263*5486feefSafresh1    $s .= ':SK';
264*5486feefSafresh1    print($fh 'DEF');
265*5486feefSafresh1    $s .= ':P';
266*5486feefSafresh1    ok(close($fh), 'close tied scalar - write');
267*5486feefSafresh1    is($s, ':F:S():O:F:S(ABC):P:SK:F:S(DEF):P', 'tied actions - write');
268*5486feefSafresh1    is($x, 'DEF', 'new value preserved');
269*5486feefSafresh1
270*5486feefSafresh1    $x = 'GHI';
271*5486feefSafresh1    $s = '';
272*5486feefSafresh1    ok(open($fh, '+<', \$x), 'open-read tied scalar');
273*5486feefSafresh1    $s .= ':O';
274*5486feefSafresh1    my $buf;
275*5486feefSafresh1    is(read($fh,$buf,2), 2, 'read1');
276*5486feefSafresh1    $s .= ':R';
277*5486feefSafresh1    is($buf, 'GH', 'buf1');
278*5486feefSafresh1    is(read($fh,$buf,2), 1, 'read2');
279*5486feefSafresh1    $s .= ':R';
280*5486feefSafresh1    is($buf, 'I', 'buf2');
281*5486feefSafresh1    is(read($fh,$buf,2), 0, 'read3');
282*5486feefSafresh1    $s .= ':R';
283*5486feefSafresh1    is($buf, '', 'buf3');
284*5486feefSafresh1    ok(close($fh), 'close tied scalar - read');
285*5486feefSafresh1    is($s, ':F:S(GHI):O:F:R:F:R:F:R', 'tied actions - read');
286*5486feefSafresh1}
287*5486feefSafresh1
288*5486feefSafresh1# [perl #78716] Seeking beyond the end of the string, then reading
289*5486feefSafresh1{
290*5486feefSafresh1    my $str = '1234567890';
291*5486feefSafresh1    open my $strIn, '<', \$str;
292*5486feefSafresh1    seek $strIn, 15, 1;
293*5486feefSafresh1    is read($strIn, my $buffer, 5), 0,
294*5486feefSafresh1     'seek beyond end end of string followed by read';
295*5486feefSafresh1}
296*5486feefSafresh1
297*5486feefSafresh1# Writing to COW scalars and non-PVs
298*5486feefSafresh1{
299*5486feefSafresh1    my $bovid = __PACKAGE__;
300*5486feefSafresh1    open my $handel, ">", \$bovid;
301*5486feefSafresh1    print $handel "the COW with the crumpled horn";
302*5486feefSafresh1    is $bovid, "the COW with the crumpled horn", 'writing to COW scalars';
303*5486feefSafresh1
304*5486feefSafresh1    package lrcg { use overload fallback => 1, '""'=>sub { 'chin' } }
305*5486feefSafresh1    seek $handel, 3, 0;
306*5486feefSafresh1    $bovid = bless [], lrcg::;
307*5486feefSafresh1    print $handel 'mney';
308*5486feefSafresh1    is $bovid, 'chimney', 'writing to refs';
309*5486feefSafresh1
310*5486feefSafresh1    seek $handel, 1, 0;
311*5486feefSafresh1    $bovid = 42;  # still has a PV
312*5486feefSafresh1    print $handel 5;
313*5486feefSafresh1    is $bovid, 45, 'writing to numeric scalar';
314*5486feefSafresh1
315*5486feefSafresh1    seek $handel, 1, 0;
316*5486feefSafresh1    undef $bovid;
317*5486feefSafresh1    $bovid = 42;   # just IOK
318*5486feefSafresh1    print $handel 5;
319*5486feefSafresh1    is $bovid, 45, 'writing to numeric scalar';
320*5486feefSafresh1}
321*5486feefSafresh1
322*5486feefSafresh1# [perl #92706]
323*5486feefSafresh1{
324*5486feefSafresh1    open my $fh, "<", \(my $f=*f); seek $fh, 2,1;
325*5486feefSafresh1    pass 'seeking on a glob copy';
326*5486feefSafresh1    open my $fh, "<", \(my $f=*f); seek $fh, -2,2;
327*5486feefSafresh1    pass 'seeking on a glob copy from the end';
328*5486feefSafresh1}
329*5486feefSafresh1
330*5486feefSafresh1# [perl #108398]
331*5486feefSafresh1sub has_trailing_nul(\$) {
332*5486feefSafresh1    my ($ref) = @_;
333*5486feefSafresh1    my $sv = B::svref_2object($ref);
334*5486feefSafresh1    return undef if !$sv->isa('B::PV');
335*5486feefSafresh1
336*5486feefSafresh1    my $cur = $sv->CUR;
337*5486feefSafresh1    my $len = $sv->LEN;
338*5486feefSafresh1    return 0 if $cur >= $len;
339*5486feefSafresh1
340*5486feefSafresh1    my $ptrlen = length(pack('P', ''));
341*5486feefSafresh1    my $ptrfmt
342*5486feefSafresh1	= $ptrlen == length(pack('J', 0)) ? 'J'
343*5486feefSafresh1	: $ptrlen == length(pack('I', 0)) ? 'I'
344*5486feefSafresh1	: die "Can't determine pointer format";
345*5486feefSafresh1
346*5486feefSafresh1    my $pv_addr = unpack $ptrfmt, pack 'P', $$ref;
347*5486feefSafresh1    my $trailing = unpack 'P', pack $ptrfmt, $pv_addr+$cur;
348*5486feefSafresh1    return $trailing eq "\0";
349*5486feefSafresh1}
350*5486feefSafresh1SKIP: {
351*5486feefSafresh1    if ($Config::Config{'extensions'} !~ m!\bB\b!) {
352*5486feefSafresh1	skip "no B", 4;
353*5486feefSafresh1    }
354*5486feefSafresh1    require B;
355*5486feefSafresh1
356*5486feefSafresh1    open my $fh, ">", \my $memfile or die $!;
357*5486feefSafresh1
358*5486feefSafresh1    print $fh "abc";
359*5486feefSafresh1    ok has_trailing_nul $memfile,
360*5486feefSafresh1	 'write appends trailing null when growing string';
361*5486feefSafresh1
362*5486feefSafresh1    seek $fh, 0,SEEK_SET;
363*5486feefSafresh1    print $fh "abc";
364*5486feefSafresh1    ok has_trailing_nul $memfile,
365*5486feefSafresh1	 'write appends trailing null when not growing string';
366*5486feefSafresh1
367*5486feefSafresh1    seek $fh, 200, SEEK_SET;
368*5486feefSafresh1    print $fh "abc";
369*5486feefSafresh1    ok has_trailing_nul $memfile,
370*5486feefSafresh1	 'write appends null when growing string after seek past end';
371*5486feefSafresh1
372*5486feefSafresh1    open $fh, ">", \($memfile = "hello");
373*5486feefSafresh1    ok has_trailing_nul $memfile,
374*5486feefSafresh1	 'initial truncation in ">" mode provides trailing null';
375*5486feefSafresh1}
376*5486feefSafresh1
377*5486feefSafresh1# [perl #112780] Cloning of in-memory handles
378*5486feefSafresh1SKIP: {
379*5486feefSafresh1  skip "no threads", 2 if !$Config::Config{useithreads};
380*5486feefSafresh1  require threads;
381*5486feefSafresh1  my $str = '';
382*5486feefSafresh1  open my $fh, ">", \$str;
383*5486feefSafresh1  $str = 'a';
384*5486feefSafresh1  is scalar threads::async(sub { my $foo = $str; $foo })->join, "a",
385*5486feefSafresh1    'scalars behind in-memory handles are cloned properly';
386*5486feefSafresh1  print $fh "a";
387*5486feefSafresh1  is scalar threads::async(sub { print $fh "b"; $str })->join, "ab",
388*5486feefSafresh1    'printing to a cloned in-memory handle works';
389*5486feefSafresh1}
390*5486feefSafresh1
391*5486feefSafresh1# [perl #113764] Duping via >&= (broken by the fix for #112870)
392*5486feefSafresh1{
393*5486feefSafresh1  open FILE, '>', \my $content or die "Couldn't open scalar filehandle";
394*5486feefSafresh1  open my $fh, ">&=FILE" or die "Couldn't open: $!";
395*5486feefSafresh1  print $fh "Foo-Bar\n";
396*5486feefSafresh1  close $fh;
397*5486feefSafresh1  close FILE;
398*5486feefSafresh1  is $content, "Foo-Bar\n", 'duping via >&=';
399*5486feefSafresh1}
400*5486feefSafresh1
401*5486feefSafresh1# [perl #109828] PerlIO::scalar does not handle UTF-8
402*5486feefSafresh1my $byte_warning = "Strings with code points over 0xFF may not be mapped into in-memory file handles\n";
403*5486feefSafresh1{
404*5486feefSafresh1    use Errno qw(EINVAL);
405*5486feefSafresh1    my @warnings;
406*5486feefSafresh1    local $SIG{__WARN__} = sub { push @warnings, "@_" };
407*5486feefSafresh1    my $content = "12\x{101}";
408*5486feefSafresh1    $! = 0;
409*5486feefSafresh1    ok(!open(my $fh, "<", \$content), "non-byte open should fail");
410*5486feefSafresh1    is(0+$!, EINVAL, "check \$! is updated");
411*5486feefSafresh1	is(@warnings, 0, "should be no warnings (yet)");
412*5486feefSafresh1    use warnings "utf8";
413*5486feefSafresh1    $! = 0;
414*5486feefSafresh1    ok(!open(my $fh, "<", \$content), "non byte open should fail (and warn)");
415*5486feefSafresh1    is(0+$!, EINVAL, "check \$! is updated even when we warn");
416*5486feefSafresh1    is(@warnings, 1, "should have warned");
417*5486feefSafresh1    is($warnings[0], $byte_warning, "should have warned");
418*5486feefSafresh1
419*5486feefSafresh1    @warnings = ();
420*5486feefSafresh1    $content = "12\xA1";
421*5486feefSafresh1    utf8::upgrade($content);
422*5486feefSafresh1    ok(open(my $fh, "<", \$content), "open upgraded scalar");
423*5486feefSafresh1    binmode $fh;
424*5486feefSafresh1    my $tmp;
425*5486feefSafresh1    is(read($fh, $tmp, 4), 3, "read should get the downgraded bytes");
426*5486feefSafresh1    is($tmp, "12\xA1", "check we got the expected bytes");
427*5486feefSafresh1    close $fh;
428*5486feefSafresh1    is(@warnings, 0, "should be no more warnings");
429*5486feefSafresh1}
430*5486feefSafresh1{ # changes after open
431*5486feefSafresh1    my $content = "abc";
432*5486feefSafresh1    ok(open(my $fh, "+<", \$content), "open a scalar");
433*5486feefSafresh1    binmode $fh;
434*5486feefSafresh1    my $tmp;
435*5486feefSafresh1    is(read($fh, $tmp, 1), 1, "basic read");
436*5486feefSafresh1    seek($fh, 1, SEEK_SET);
437*5486feefSafresh1    $content = "\xA1\xA2\xA3";
438*5486feefSafresh1    utf8::upgrade($content);
439*5486feefSafresh1    is(read($fh, $tmp, 1), 1, "read from post-open upgraded scalar");
440*5486feefSafresh1    is($tmp, "\xA2", "check we read the correct value");
441*5486feefSafresh1    seek($fh, 1, SEEK_SET);
442*5486feefSafresh1    $content = "\x{101}\x{102}\x{103}";
443*5486feefSafresh1
444*5486feefSafresh1    my @warnings;
445*5486feefSafresh1    local $SIG{__WARN__} = sub { push @warnings, "@_" };
446*5486feefSafresh1
447*5486feefSafresh1    $! = 0;
448*5486feefSafresh1    is(read($fh, $tmp, 1), undef, "read from scalar with >0xff chars");
449*5486feefSafresh1    is(0+$!, EINVAL, "check errno set correctly");
450*5486feefSafresh1	is(@warnings, 0, "should be no warnings (yet)");
451*5486feefSafresh1    use warnings "utf8";
452*5486feefSafresh1    seek($fh, 1, SEEK_SET);
453*5486feefSafresh1    is(read($fh, $tmp, 1), undef, "read from scalar with >0xff chars");
454*5486feefSafresh1    is(@warnings, 1, "check warnings");
455*5486feefSafresh1    is($warnings[0], $byte_warning, "check warnings");
456*5486feefSafresh1
457*5486feefSafresh1    select $fh; # make sure print fails rather tha buffers
458*5486feefSafresh1    $| = 1;
459*5486feefSafresh1    select STDERR;
460*5486feefSafresh1    no warnings "utf8";
461*5486feefSafresh1    @warnings = ();
462*5486feefSafresh1    $content = "\xA1\xA2\xA3";
463*5486feefSafresh1    utf8::upgrade($content);
464*5486feefSafresh1    seek($fh, 1, SEEK_SET);
465*5486feefSafresh1    ok((print $fh "A"), "print to an upgraded byte string");
466*5486feefSafresh1    seek($fh, 1, SEEK_SET);
467*5486feefSafresh1    is($content, "\xA1A\xA3", "check result");
468*5486feefSafresh1
469*5486feefSafresh1    $content = "\x{101}\x{102}\x{103}";
470*5486feefSafresh1    $! = 0;
471*5486feefSafresh1    ok(!(print $fh "B"), "write to an non-downgradable SV");
472*5486feefSafresh1    is(0+$!, EINVAL, "check errno set");
473*5486feefSafresh1
474*5486feefSafresh1    is(@warnings, 0, "should be no warning");
475*5486feefSafresh1
476*5486feefSafresh1    use warnings "utf8";
477*5486feefSafresh1    ok(!(print $fh "B"), "write to an non-downgradable SV (and warn)");
478*5486feefSafresh1    is(@warnings, 1, "check warnings");
479*5486feefSafresh1    is($warnings[0], $byte_warning, "check warnings");
480*5486feefSafresh1}
481*5486feefSafresh1
482*5486feefSafresh1#  RT #119529: Reading refs should not loop
483*5486feefSafresh1
484*5486feefSafresh1{
485*5486feefSafresh1    my $x = \42;
486*5486feefSafresh1    open my $fh, "<", \$x;
487*5486feefSafresh1    my $got = <$fh>; # this used to loop
488*5486feefSafresh1    like($got, qr/^SCALAR\(0x[0-9a-f]+\)$/, "ref to a ref");
489*5486feefSafresh1    is ref $x, "SCALAR", "target scalar is still a reference";
490*5486feefSafresh1}
491*5486feefSafresh1
492*5486feefSafresh1# Appending to refs
493*5486feefSafresh1{
494*5486feefSafresh1    my $x = \42;
495*5486feefSafresh1    my $as_string = "$x";
496*5486feefSafresh1    open my $refh, ">>", \$x;
497*5486feefSafresh1    is ref $x, "SCALAR", 'still a ref after opening for appending';
498*5486feefSafresh1    print $refh "boo\n";
499*5486feefSafresh1    is $x, $as_string."boo\n", 'string gets appended to ref';
500*5486feefSafresh1}
501*5486feefSafresh1
502*5486feefSafresh1SKIP:
503*5486feefSafresh1{ # [perl #123443]
504*5486feefSafresh1    skip "Can't seek over 4GB with a small off_t", 4
505*5486feefSafresh1      if $Config::Config{lseeksize} < 8;
506*5486feefSafresh1    my $buf0 = "hello";
507*5486feefSafresh1    open my $fh, "<", \$buf0 or die $!;
508*5486feefSafresh1    ok(seek($fh, 2**32, SEEK_SET), "seek to a large position");
509*5486feefSafresh1    is(read($fh, my $tmp, 1), 0, "read from a large offset");
510*5486feefSafresh1    is($tmp, "", "should have read nothing");
511*5486feefSafresh1    ok(eof($fh), "fh should be eof");
512*5486feefSafresh1}
513*5486feefSafresh1
514*5486feefSafresh1{
515*5486feefSafresh1    my $buf0 = "hello";
516*5486feefSafresh1    open my $fh, "<", \$buf0 or die $!;
517*5486feefSafresh1    ok(!seek($fh, -10, SEEK_CUR), "seek to negative position");
518*5486feefSafresh1    is(tell($fh), 0, "shouldn't change the position");
519*5486feefSafresh1}
520*5486feefSafresh1
521*5486feefSafresh1SKIP:
522*5486feefSafresh1{ # write() beyond SSize_t limit
523*5486feefSafresh1    skip "Can't overflow SSize_t with Off_t", 2
524*5486feefSafresh1      if $Config::Config{lseeksize} <= $Config::Config{sizesize};
525*5486feefSafresh1    my $buf0 = "hello";
526*5486feefSafresh1    open my $fh, "+<", \$buf0 or die $!;
527*5486feefSafresh1    ok(seek($fh, 2**32, SEEK_SET), "seek to a large position");
528*5486feefSafresh1    select((select($fh), ++$|)[0]);
529*5486feefSafresh1    ok(!(print $fh "x"), "write to a large offset");
530*5486feefSafresh1}
531