BATsh
view release on metacpan or search on metacpan
t/0005-verify_compat.t view on Meta::CPAN
######################################################################
#
# 0005-verify_compat.t cmd.exe compatibility: 6 items
#
# Verifies the 6 compatibility fixes implemented in v0.02:
# 1. Environment variable case-insensitivity
# 2. ^ escape character
# 3. I/O redirection (> >> 2> <)
# 4. SETLOCAL ENABLEDELAYEDEXPANSION / !VAR!
# 5. IF/FOR block %VAR% parse-time expansion
# 6. FOR /F (tokens= delims= skip= eol= usebackq)
#
# COMPATIBILITY: Perl 5.005_03 and later
#
######################################################################
use strict;
BEGIN { if ($] < 5.006 && !defined(&warnings::import)) {
$INC{'warnings.pm'} = 'stub'; eval 'package warnings; sub import {}' } }
use warnings; local $^W = 1;
BEGIN { pop @INC if $INC[-1] eq '.' }
use FindBin ();
use File::Spec ();
use lib "$FindBin::Bin/../lib";
eval { require BATsh } or die "Cannot load BATsh: $@";
BATsh::Env::init();
# ----------------------------------------------------------------
# Helpers (Perl 5.005 compatible: bareword FH, no //, no my-open)
# ----------------------------------------------------------------
my $TMPBASE = File::Spec->catfile(File::Spec->tmpdir(), "batsh_vc_$$");
sub _capture_cmd {
my (@lines) = @_;
for my $l (@lines) { $l .= "\n" unless $l =~ /\n\z/ }
BATsh::Env::init();
my $tmp = "${TMPBASE}_cap.tmp";
local *VCOLD; local *VCCAP;
open(VCOLD, '>&STDOUT') or return '';
open(VCCAP, "> $tmp") or do { open(STDOUT,'>&VCOLD'); return '' };
open(STDOUT, '>&VCCAP');
eval {
BATsh::CMD::exec_block('BATsh::CMD', \@lines,
_batsh => 'BATsh', _pushd_stack => []);
};
my $err = $@;
open(STDOUT, '>&VCOLD');
close(VCCAP); close(VCOLD);
my $buf = '';
if (open(VCREAD, "< $tmp")) {
local $/; $buf = <VCREAD>; close(VCREAD);
}
unlink $tmp;
$buf = '' unless defined $buf;
warn $err if $err;
return $buf;
}
sub _tmpfile {
my ($name, @lines) = @_;
my $path = "${TMPBASE}_${name}.tmp";
local *TMPWFH;
open(TMPWFH, "> $path") or die "Cannot write $path: $!";
for my $l (@lines) { print TMPWFH $l }
close(TMPWFH);
return $path;
}
# ----------------------------------------------------------------
# Test array (Perl 5.005 compatible closure style)
# ----------------------------------------------------------------
t/0005-verify_compat.t view on Meta::CPAN
'IF 1==2 (',
' ECHO then',
') ELSE (',
' SET Y=changed',
' ECHO %Y%',
')',
);
_ok($out eq "original\n", '5-2: ELSE block %VAR% is parse-time value (original)');
},
sub {
my $out = _capture_cmd(
'SET CNT=0',
'FOR %%i IN (a b c) DO (',
' SET CNT=%%i',
' ECHO %CNT%',
')',
);
_ok($out eq "0\n0\n0\n", '5-3: FOR block %CNT% locked at FOR-line parse time (0)');
},
sub {
my $out = _capture_cmd('SET Z=first', 'SET Z=second', 'ECHO %Z%');
_ok($out eq "second\n", '5-4: outside blocks %VAR% is runtime (sees latest SET)');
},
# ==============================================================
# Step 6: FOR /F
# ==============================================================
sub {
my $out = _capture_cmd(
'FOR /F "tokens=1,2 delims=," %%a IN ("hello,world") DO ECHO %%a / %%b',
);
_ok($out eq "hello / world\n", '6-1: FOR /F tokens=1,2 delims=,');
},
sub {
my $out = _capture_cmd(
'FOR /F "tokens=2" %%a IN ("alpha beta gamma") DO ECHO %%a',
);
_ok($out eq "beta\n", '6-2: FOR /F tokens=2 (default delims=space)');
},
sub {
my $tmp = _tmpfile('ff3', "skip_this\n", "use_this\n");
my $out = _capture_cmd("FOR /F \"skip=1\" %%a IN ($tmp) DO ECHO %%a");
unlink $tmp;
_ok($out eq "use_this\n", '6-3: FOR /F skip=1');
},
sub {
my $out = _capture_cmd(
'FOR /F "tokens=1*" %%a IN ("one two three") DO ECHO [%%a][%%b]',
);
_ok($out eq "[one][two three]\n", '6-4: FOR /F tokens=1* (star=remainder)');
},
sub {
my $tmp = _tmpfile('ff5', "#comment\n", "data_line\n");
my $out = _capture_cmd("FOR /F \"eol=#\" %%a IN ($tmp) DO ECHO %%a");
unlink $tmp;
_ok($out eq "data_line\n", '6-5: FOR /F eol=# skips lines');
},
sub {
my $tmp = _tmpfile('ff6', "key1:val1\n", "key2:val2\n");
my $out = _capture_cmd(
"FOR /F \"tokens=1,2 delims=:\" %%a IN ($tmp) DO ECHO %%a=%%b",
);
unlink $tmp;
_ok($out eq "key1=val1\nkey2=val2\n", '6-6: FOR /F multi-line file key:value');
},
# ==============================================================
# Additional: ERRORLEVEL / IF /I / compound / SET /A
# ==============================================================
sub {
my $out = _capture_cmd('ECHO a & ECHO b');
_ok($out eq "a\nb\n", 'A-1: & sequential execution');
},
sub {
my $out = _capture_cmd('IF /I "Hello"=="hello" ECHO match');
_ok($out eq "match\n", 'A-2: IF /I case-insensitive comparison');
},
sub {
BATsh::Env::init();
BATsh::CMD::set_errorlevel('BATsh::CMD', 5);
_capture_cmd('ECHO something');
my $el = BATsh::CMD::errorlevel('BATsh::CMD');
_ok($el != 0, 'A-3: ECHO does not reset ERRORLEVEL to 0');
},
sub {
BATsh::Env::init();
BATsh::CMD::set_errorlevel('BATsh::CMD', 2);
my $out = _capture_cmd(
'IF ERRORLEVEL 1 ECHO ge1',
'IF ERRORLEVEL 2 ECHO ge2',
'IF ERRORLEVEL 3 ECHO ge3',
);
_ok($out eq "ge1\nge2\n", 'A-4: ERRORLEVEL >= n evaluation');
},
sub {
my $out = _capture_cmd(
'SET /A X=3+4',
'ECHO %X%',
'SET /A Y=X*2',
'ECHO %Y%',
);
_ok($out eq "7\n14\n", 'A-5: SET /A arithmetic (3+4=7, 7*2=14)');
},
sub {
my $tmp = "${TMPBASE}_space test.tmp";
local *SPTMP;
open(SPTMP, "> $tmp") or do { _ok(1, 'A-6: skip (cannot create space-path)'); return };
print SPTMP "x\n";
close(SPTMP);
( run in 0.700 second using v1.01-cache-2.11-cpan-ceb78f64989 )