File-Replace-Inplace

 view release on metacpan or  search on metacpan

t/25_tie_handle_argv.t  view on Meta::CPAN

#TODO Later: Why is $BE needed here, but not in the ::Inplace tests?
our $BE; # BE="buggy eof", Perl 5.14.x had several regressions regarding eof (and a few others) (gets set below)
our $CE; # CE="can't eof()", Perl <5.12 doesn't support eof() on tied filehandles (gets set below)
our $FL = undef; # FL="First Line"
# Apparently there are some versions of Perl on Win32 where the following two appear to work slightly differently.
# I've seen differing results on different systems and I'm not sure why, so I set it dynamically... not pretty, but this test isn't critical.
if ( $^O eq 'MSWin32' && $] ge '5.014' && $] lt '5.018' )
	{ $FL = $.; $FE = defined($.) }

diag "WARNING: Perl 5.16 or better is strongly recommended for Tie::Handle::Argv (see documentation)" if $] lt '5.016';

BEGIN { use_ok('Tie::Handle::Argv') }

## no critic (RequireCarping)

sub testboth {  ## no critic (RequireArgUnpacking)
	# test that both regular ARGV and our tied base class act the same
	die "bad nr of args" unless @_==2 || @_==3;
	my ($name, $sub, $args) = @_;
	my $stdin = delete $$args{stdin};
	{
		local (*ARGV, $.);  ## no critic (RequireInitializationForLocalVars)
		my $osi = defined($stdin) ? OverrideStdin->new($stdin) : undef;
		subtest "$name - untied" => $sub;
		$osi and $osi->restore;
	}
	{
		local (*ARGV, $.);  ## no critic (RequireInitializationForLocalVars)
		local $CE = $] lt '5.012';
		local $BE = $] ge '5.014' && $] lt '5.016';
		tie *ARGV, 'Tie::Handle::Argv', debug=>$DEBUG;
		my $osi = defined($stdin) ? OverrideStdin->new($stdin) : undef;
		subtest "$name - tied" => $sub;
		$osi and $osi->restore;
		untie *ARGV;
	}
	return;
}

testboth 'basic test' => sub { plan tests=>1;
	my @tf = (newtempfn("Foo\nBar\n"), newtempfn("Quz\nBaz"));
	my @states;
	@ARGV = @tf;  ## no critic (RequireLocalizedPunctuationVars)
	push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof];
	push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof, $_] while <>;
	push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof];
	is_deeply \@states, [
		[[@tf],    undef,  !!0, $FL, $FE         ],
		[[$tf[1]], $tf[0], !!1, 1,   !!0, "Foo\n"],
		[[$tf[1]], $tf[0], !!1, 2,   !!1, "Bar\n"],
		[[],       $tf[1], !!1, 3,   !!0, "Quz\n"],
		[[],       $tf[1], !!1, 4,   !!1, "Baz"  ],
		[[],       $tf[1], !!0, 4,   $BE?!!0:!!1 ],
	], 'states' or diag explain \@states;
};

testboth 'basic test with eof()' => sub {
	plan $CE ? ( skip_all=>"eof() not supported on tied handles on Perl<5.12" ) : (tests=>1);
	my @tf = (newtempfn("Foo\nBar"), newtempfn("Quz\nBaz\n"));
	my @states;
	local @ARGV = @tf; # this also tests "local"ization after constructing the object
	# WARNING: eof() modifies $ARGV (and potentially others), so don't do e.g. [$ARGV, $., eof, eof()]!!
	# See e.g. https://www.perlmonks.org/?node_id=289044 and https://www.perlmonks.org/?node_id=1076954
	# and https://www.perlmonks.org/?node_id=1164369 and probably more
	push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof], eof();
	# eof() will open the first file, so record the current state again:
	push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof], eof();
	push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof, $_], eof() while <>;
	# another call to eof() now would open and try to read STDIN (we test that in the STDIN tests)
	push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof];
	is_deeply \@states, [
		[[@tf],    undef,  !!0, $FL,       $FE         ], !!0,
		[[$tf[1]], $tf[0], !!1, $BE?$FL:0, !!0         ], !!0,
		[[$tf[1]], $tf[0], !!1, 1,         !!0, "Foo\n"], !!0,
		[[$tf[1]], $tf[0], !!1, 2,         !!1, "Bar"  ], !!0,
		[[],       $tf[1], !!1, 3,         !!0, "Quz\n"], !!0,
		[[],       $tf[1], !!1, 4,         !!1, "Baz\n"], !!1,
		[[],       $tf[1], !!0, 4,         $BE?!!0:!!1 ],
	], 'states' or diag explain \@states;
};

subtest 'custom files & filename' => sub { plan tests=>3;
	local (*ARGV, $.);  ## no critic (RequireInitializationForLocalVars)
	local $BE = $] ge '5.014' && $] lt '5.016';
	my @testfiles1;
	my $testfilename1;
	my $obj = tie *ARGV, 'Tie::Handle::Argv', debug=>$DEBUG, files=>\@testfiles1, filename=>\$testfilename1;
	my @tf = (newtempfn("Foo\nBar\n"), newtempfn("Quz\nBaz"));
	my @states;
	@ARGV = ("foo");  ## no critic (RequireLocalizedPunctuationVars)
	@testfiles1 = @tf;
	push @states, [[@ARGV], $ARGV, [@testfiles1], $testfilename1, defined(fileno ARGV), $., eof];
	push @states, [[@ARGV], $ARGV, [@testfiles1], $testfilename1, defined(fileno ARGV), $., eof, $_] while <>;
	push @states, [[@ARGV], $ARGV, [@testfiles1], $testfilename1, defined(fileno ARGV), $., eof];
	is_deeply \@states, [
		[["foo"], undef, [@tf],    undef,  !!0, $FL, $FE         ],
		[["foo"], undef, [$tf[1]], $tf[0], !!1, 1,   !!0, "Foo\n"],
		[["foo"], undef, [$tf[1]], $tf[0], !!1, 2,   !!1, "Bar\n"],
		[["foo"], undef, [],       $tf[1], !!1, 3,   !!0, "Quz\n"],
		[["foo"], undef, [],       $tf[1], !!1, 4,   !!1, "Baz"  ],
		[["foo"], undef, [],       $tf[1], !!0, 4,   $BE?!!0:!!1 ],
	], 'states' or diag explain \@states;
	{ # make code coverage happy
		is 0+@testfiles1, 0, 'testfiles empty';
		$obj->init_empty_argv;
		is_deeply \@testfiles1, ['-'], 'testfiles was populated';
	}
	untie *ARGV;
};

testboth 'readline contexts' => sub { plan tests=>2;
	# we test scalar everywhere, need to test the others too
	my @tf = (newtempfn("Alpha"), newtempfn("Bravo\nCharlie\nDelta"), newtempfn("Echo\n!!!"));
	my @states;
	@ARGV = @tf;  ## no critic (RequireLocalizedPunctuationVars)
	push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof];
	for (1..2) {
		<>; # void ctx
		push @states, [[@ARGV], $ARGV, defined(fileno ARGV), $., eof];
	}
	my @got = <>; # list ctx



( run in 1.085 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )