1256a93a4Safresh1#!/usr/bin/perl 2256a93a4Safresh1 3256a93a4Safresh1use strict; 4256a93a4Safresh1use warnings FATAL => 'all'; 5256a93a4Safresh1use English; 6256a93a4Safresh1 7256a93a4Safresh1use Config; 8256a93a4Safresh1use Test::More; 9256a93a4Safresh1use ExtUtils::PL2Bat; 10256a93a4Safresh1use Cwd qw/cwd/; 11256a93a4Safresh1 12256a93a4Safresh1my @test_vals = ( 0, 1, 2, 3, -1, -2, 65535, 65536, 65537, 47, 100, 200, 255, 256, 257, 258, 511, 512, 513, -255, -256, -20012001 ); 13256a93a4Safresh1 14256a93a4Safresh1plan($OSNAME eq 'MSWin32' ? ( tests => (($#test_vals+1)*5)+2 ) : ( skip_all => 'Only usable on Windows' )); 15256a93a4Safresh1 16*f2a19305Safresh1# the method of execution of the test script is geared to cmd.exe so ensure 17*f2a19305Safresh1# this is used in case the user have some non-standard shell. 18*f2a19305Safresh1# E.g. TCC/4NT doesn't quite handle the invocation correctly producing errors. 19*f2a19305Safresh1$ENV{COMSPEC} = "$ENV{SystemRoot}\\System32\\cmd.exe"; 20*f2a19305Safresh1 21256a93a4Safresh1my $perl_in_fname = 'test_perl_source'; 22256a93a4Safresh1 23256a93a4Safresh1open my $out, '>', $perl_in_fname or die qq{Couldn't create source file ("$perl_in_fname"): $!}; 24256a93a4Safresh1print $out "#! perl -w\nexit \$ARGV[0];\n"; 25256a93a4Safresh1close $out; 26256a93a4Safresh1 27256a93a4Safresh1pl2bat(in => $perl_in_fname); 28256a93a4Safresh1 29256a93a4Safresh1my $batch_out_fname = $perl_in_fname.'.bat'; 30256a93a4Safresh1 31256a93a4Safresh1ok (-e "$batch_out_fname", qq{Executable file exists ("$batch_out_fname")}); 32256a93a4Safresh1 33256a93a4Safresh1my $int_max_8bit = 2**8; 34256a93a4Safresh1my $int_max_16bit = 2**16; 35256a93a4Safresh1 36256a93a4Safresh1my $path_with_cwd = construct_test_PATH(); 37256a93a4Safresh1 38256a93a4Safresh1foreach my $input_val ( @test_vals ) { 39256a93a4Safresh1 local $ENV{PATH} = $path_with_cwd; 40256a93a4Safresh1 my $qx_output = q//; 41256a93a4Safresh1 my $qx_retval = 0; 42256a93a4Safresh1 my $error_level = 0; 43256a93a4Safresh1 my $status = q//; 44256a93a4Safresh1 my $success = 1; 45256a93a4Safresh1 46256a93a4Safresh1 $success &&= eval { $qx_output = qx{"$batch_out_fname" $input_val}; $qx_retval = $CHILD_ERROR; $qx_retval != -1; }; 47256a93a4Safresh1 $qx_retval = ( $qx_retval > 0 ) ? ( $qx_retval >> 8 ) : $qx_retval; 48256a93a4Safresh1 49256a93a4Safresh1 $success &&= eval { $error_level = qx{"$batch_out_fname" $input_val & call echo ^%ERRORLEVEL^%}; 1; }; 50256a93a4Safresh1 $error_level =~ s/\r?\n$//msx; 51256a93a4Safresh1 52256a93a4Safresh1 $success &&= eval { $status = qx{"$batch_out_fname" $input_val && (echo PROCESS_SUCCESS) || (echo PROCESS_FAILURE)}; 1; }; 53256a93a4Safresh1 $status =~ s/\r?\n$//msx; 54256a93a4Safresh1 55256a93a4Safresh1 # (for qx/.../) post-call status values ($CHILD_ERROR) can be [ 0 ... 255 ]; values outside that range will be returned as `value % 256` 56256a93a4Safresh1 my $expected_qx_retval = ($input_val % $int_max_8bit); 57256a93a4Safresh1 58256a93a4Safresh1 # `exit $value` will set ERRORLEVEL to $value for values of [ -1, 0 ... 65535 ]; values outside that range will set ERRORLEVEL to `$value % 65536` 59256a93a4Safresh1 my $expected_error_level = ($input_val == -1) ? -1 : ($input_val % $int_max_16bit); 60256a93a4Safresh1 61256a93a4Safresh1 is $success, 1, qq{`"$batch_out_fname" $input_val` executed successfully}; 62256a93a4Safresh1 is $qx_output, q//, qq{qx/"$batch_out_fname" $input_val/ returns expected empty output}; # assure no extraneous output from BAT wrap 63256a93a4Safresh1 is $qx_retval, $expected_qx_retval, qq{qx/"$batch_out_fname" $input_val/ returns expected $CHILD_ERROR ($expected_qx_retval)}; 64256a93a4Safresh1 is $error_level, $expected_error_level, qq{"$batch_out_fname": `exit $input_val` set expected ERRORLEVEL ($expected_error_level)}; 65256a93a4Safresh1 is $status, (($input_val % $int_max_16bit) == 0) ? 'PROCESS_SUCCESS' : 'PROCESS_FAILURE', qq{`"$batch_out_fname" $input_val` process exit ($status) is correct}; 66256a93a4Safresh1} 67256a93a4Safresh1 68256a93a4Safresh1unlink $perl_in_fname, $batch_out_fname; 69256a93a4Safresh1 70256a93a4Safresh1# the test needs CWD in PATH to check the created .bat files, but under win2k 71256a93a4Safresh1# PATH must not be too long. so to keep any win2k smokers happy, we construct 72256a93a4Safresh1# a new PATH that contains the dirs which hold cmd.exe, perl.exe, and CWD 73256a93a4Safresh1 74256a93a4Safresh1sub construct_test_PATH { 75256a93a4Safresh1 my $perl_path = $^X; 76256a93a4Safresh1 my $cmd_path = $ENV{ComSpec} || `where cmd`; # where doesn't seem to work on all windows versions 77256a93a4Safresh1 $_ =~ s/[\\\/][^\\\/]+$// for $perl_path, $cmd_path; # strip executable names 78256a93a4Safresh1 79256a93a4Safresh1 my @path_fallbacks = grep /\Q$ENV{SystemRoot}\E|system32|winnt|windows/i, split $Config{path_sep}, $ENV{PATH}; 80256a93a4Safresh1 81256a93a4Safresh1 my $path_with_cwd = join $Config{path_sep}, @path_fallbacks, $cmd_path, $perl_path, cwd(); 82256a93a4Safresh1 83256a93a4Safresh1 my ($perl) = ( $^X =~ /[\\\/]([^\\]+)$/ ); # in case the perl executable name differs 84256a93a4Safresh1 note "using perl executable name: $perl"; 85256a93a4Safresh1 86256a93a4Safresh1 local $ENV{PATH} = $path_with_cwd; 87256a93a4Safresh1 my $test_out = `$perl -e 1 2>&1`; 88256a93a4Safresh1 is $test_out, "", "perl execution with temp path works" 89256a93a4Safresh1 or diag "make_executable.t tmp path: $path_with_cwd"; 90256a93a4Safresh1 diag "make_executable.t PATH likely did not contain cmd.exe" 91256a93a4Safresh1 if !defined $test_out; 92256a93a4Safresh1 93256a93a4Safresh1 return $path_with_cwd; 94256a93a4Safresh1} 95