xref: /openbsd/gnu/usr.bin/perl/t/io/argv.t (revision 9f11ffb7)
1#!./perl
2
3BEGIN {
4    chdir 't' if -d 't';
5    require "./test.pl";
6    set_up_inc('../lib');
7}
8
9plan(tests => 37);
10
11my ($devnull, $no_devnull);
12
13if (is_miniperl()) {
14    $no_devnull = "no dynamic loading on miniperl, File::Spec not built, so can't determine /dev/null";
15} else {
16    require File::Spec;
17    $devnull = File::Spec->devnull;
18}
19
20open(TRY, '>tmpIo_argv1.tmp') || (die "Can't open temp file: $!");
21print TRY "a line\n";
22close TRY or die "Could not close: $!";
23open(TRY, '>tmpIo_argv2.tmp') || (die "Can't open temp file: $!");
24print TRY "another line\n";
25close TRY or die "Could not close: $!";
26
27$x = runperl(
28    prog	=> 'while (<>) { print $., $_; }',
29    args	=> [ 'tmpIo_argv1.tmp', 'tmpIo_argv1.tmp' ],
30);
31is($x, "1a line\n2a line\n", '<> from two files');
32
33{
34    $x = runperl(
35	prog	=> 'while (<>) { print $_; }',
36	stdin	=> "foo\n",
37	args	=> [ 'tmpIo_argv1.tmp', '-' ],
38    );
39    is($x, "a line\nfoo\n", '<> from a file and STDIN');
40
41    # readline should behave as <>, not <<>>
42    $x = runperl(
43        prog	=> 'while (readline) { print $_; }',
44        stdin	=> "foo\n",
45        stderr 	=> 1,
46        args	=> [ '-' ],
47    );
48    is($x, "foo\n", 'readline() from STDIN');
49
50    $x = runperl(
51	prog	=> 'while (<>) { print $_; }',
52	stdin	=> "foo\n",
53    );
54    is($x, "foo\n", '<> from just STDIN');
55
56    $x = runperl(
57	prog	=> 'while (<>) { print $ARGV.q/,/.$_ }',
58	args	=> [ 'tmpIo_argv1.tmp', 'tmpIo_argv2.tmp' ],
59    );
60    is($x, "tmpIo_argv1.tmp,a line\ntmpIo_argv2.tmp,another line\n", '$ARGV is the file name');
61
62TODO: {
63        local $::TODO = "unrelated bug in redirection implementation" if $^O eq 'VMS';
64        $x = runperl(
65            prog	=> 'print $ARGV while <>',
66            stdin	=> "foo\nbar\n",
67            args   	=> [ '-' ],
68        );
69        is($x, "--", '$ARGV is - for explicit STDIN');
70
71        $x = runperl(
72            prog	=> 'print $ARGV while <>',
73            stdin	=> "foo\nbar\n",
74        );
75        is($x, "--", '$ARGV is - for implicit STDIN');
76    }
77}
78
79{
80    # 5.10 stopped autovivifying scalars in globs leading to a
81    # segfault when $ARGV is written to.
82    runperl( prog => 'eof()', stdin => "nothing\n" );
83    is( 0+$?, 0, q(eof() doesn't segfault) );
84}
85
86@ARGV = is_miniperl() ? ('tmpIo_argv1.tmp', 'tmpIo_argv1.tmp', 'tmpIo_argv1.tmp')
87    : ('tmpIo_argv1.tmp', 'tmpIo_argv1.tmp', $devnull, 'tmpIo_argv1.tmp');
88while (<>) {
89    $y .= $. . $_;
90    if (eof()) {
91	is($., 3, '$. counts <>');
92    }
93}
94
95is($y, "1a line\n2a line\n3a line\n", '<> from @ARGV');
96
97
98open(TRY, '>tmpIo_argv1.tmp') or die "Can't open temp file: $!";
99close TRY or die "Could not close: $!";
100open(TRY, '>tmpIo_argv2.tmp') or die "Can't open temp file: $!";
101close TRY or die "Could not close: $!";
102@ARGV = ('tmpIo_argv1.tmp', 'tmpIo_argv2.tmp');
103$^I = '_bak';   # not .bak which confuses VMS
104$/ = undef;
105my $i = 11;
106while (<>) {
107    s/^/ok $i\n/;
108    ++$i;
109    print;
110    next_test();
111}
112open(TRY, '<tmpIo_argv1.tmp') or die "Can't open temp file: $!";
113print while <TRY>;
114open(TRY, '<tmpIo_argv2.tmp') or die "Can't open temp file: $!";
115print while <TRY>;
116close TRY or die "Could not close: $!";
117undef $^I;
118
119ok( eof TRY );
120
121{
122    no warnings 'once';
123    ok( eof NEVEROPENED,    'eof() true on unopened filehandle' );
124}
125
126open STDIN, 'tmpIo_argv1.tmp' or die $!;
127@ARGV = ();
128ok( !eof(),     'STDIN has something' );
129
130is( <>, "ok 11\n" );
131
132SKIP: {
133    skip_if_miniperl($no_devnull, 4);
134    open STDIN, $devnull or die $!;
135    @ARGV = ();
136    ok( eof(),      'eof() true with empty @ARGV' );
137
138    @ARGV = ('tmpIo_argv1.tmp');
139    ok( !eof() );
140
141    @ARGV = ($devnull, $devnull);
142    ok( !eof() );
143
144    close ARGV or die $!;
145    ok( eof(),      'eof() true after closing ARGV' );
146}
147
148SKIP: {
149    local $/;
150    open my $fh, 'tmpIo_argv1.tmp' or die "Could not open tmpIo_argv1.tmp: $!";
151    <$fh>;	# set $. = 1
152    is( <$fh>, undef );
153
154    skip_if_miniperl($no_devnull, 5);
155
156    open $fh, $devnull or die;
157    ok( defined(<$fh>) );
158
159    is( <$fh>, undef );
160    is( <$fh>, undef );
161
162    open $fh, $devnull or die;	# restart cycle again
163    ok( defined(<$fh>) );
164    is( <$fh>, undef );
165    close $fh or die "Could not close: $!";
166}
167
168open(TRY, '>tmpIo_argv1.tmp') || (die "Can't open temp file: $!");
169print TRY "one\n\nthree\n";
170close TRY or die "Could not close: $!";
171
172$x = runperl(
173    prog	=> 'print $..$ARGV.$_ while <<>>',
174    args	=> [ 'tmpIo_argv1.tmp' ],
175);
176is($x, "1tmpIo_argv1.tmpone\n2tmpIo_argv1.tmp\n3tmpIo_argv1.tmpthree\n", '<<>>');
177
178$x = runperl(
179    prog	=> '$w=q/b/;$w.=<<>>;print $w',
180    args	=> [ 'tmpIo_argv1.tmp' ],
181);
182is($x, "bone\n", '<<>> and rcatline');
183
184$x = runperl(
185    prog	=> 'while (<<>>) { print }',
186    stdin	=> "foo\n",
187);
188is($x, "foo\n", '<<>> from just STDIN (no argument)');
189
190TODO: {
191    local $::TODO = "unrelated bug in redirection implementation" if $^O eq 'VMS';
192    $x = runperl(
193        prog	=> 'print $ARGV.q/,/ for <<>>',
194        stdin	=> "foo\nbar\n",
195    );
196    is($x, "-,-,", '$ARGV is - for STDIN with <<>>');
197}
198
199$x = runperl(
200    prog	=> 'while (<<>>) { print $_; }',
201    stdin	=> "foo\n",
202    stderr	=> 1,
203    args	=> [ '-' ],
204);
205like($x, qr/^Can't open -: .* at -e line 1/, '<<>> does not treat - as STDIN');
206
207{
208    # tests for an empty string in @ARGV
209    $x = runperl(
210        prog	=> 'push @ARGV,q//;print while <>',
211        stderr	=> 1,
212    );
213    like($x, qr/^Can't open : .* at -e line 1/, '<> does not open empty string in ARGV');
214
215    $x = runperl(
216        prog	=> 'push @ARGV,q//;print while <<>>',
217        stderr	=> 1,
218    );
219    like($x, qr/^Can't open : .* at -e line 1/, '<<>> does not open empty string in ARGV');
220}
221
222SKIP: {
223    skip('no echo', 2) unless -x '/bin/echo';
224
225    $x = runperl(
226        prog	=> 'while (<<>>) { print $_; }',
227        stderr	=> 1,
228        args	=> [ '"echo foo |"' ],
229    );
230    like($x, qr/^Can't open echo foo \|: .* at -e line 1/, '<<>> does not treat ...| as fork');
231
232    $x = runperl(
233        prog	=> 'while (<<>>) { }',
234        stderr	=> 1,
235        args	=> [ 'tmpIo_argv1.tmp', '"echo foo |"' ],
236    );
237    like($x, qr/^Can't open echo foo \|: .* at -e line 1, <> line 3/, '<<>> does not treat ...| as fork after eof');
238}
239
240# This used to dump core
241fresh_perl_is( <<'**PROG**', "foobar", {}, "ARGV aliasing and eof()" );
242open OUT, ">tmpIo_argv3.tmp" or die "Can't open temp file: $!";
243print OUT "foo";
244close OUT;
245open IN, "tmpIo_argv3.tmp" or die "Can't open temp file: $!";
246*ARGV = *IN;
247while (<>) {
248    print;
249    print "bar" if eof();
250}
251close IN;
252unlink "tmpIo_argv3.tmp";
253**PROG**
254
255# This used to fail an assertion.
256# The tricks with *x and $x are to make PL_argvgv point to a freed SV when
257# the readline op does SvREFCNT_inc on it.  undef *x clears the scalar slot
258# ++$x vivifies it, reusing the just-deleted GV that PL_argvgv still points
259# to.  The BEGIN block ensures it is freed late enough that nothing else
260# has reused it yet.
261is runperl(prog => 'undef *x; delete $::{ARGV}; $x++;'
262                  .'eval q-BEGIN{undef *x} readline-; print qq-ok\n-'),
263  "ok\n", 'deleting $::{ARGV}';
264
265END {
266    unlink_all 'tmpIo_argv1.tmp', 'tmpIo_argv1.tmp_bak',
267	'tmpIo_argv2.tmp', 'tmpIo_argv2.tmp_bak', 'tmpIo_argv3.tmp';
268}
269