#!perl
#
# that the private _command function and public command function are at
# least not horribly buggy

use File::Spec::Functions qw(catdir splitdir);
use Test2::V0 -no_srand => 1;
use Test2::Tools::Command;

$ENV{FOO} = "bar$$";

my ( $pid, $in, $out, $err ) =
  Test2::Tools::Command::_command { args => [ $^X, '-E', 'say $ENV{FOO}' ] };
waitpid $pid, 0;
is( $?, 0 ) or bail_out "cannot even run perl??";
my $stdout = readline $out;
is $stdout, "bar$$\n";

# NOTE with chdir a relative command (e.g. "./bin/foo") may need to be
# fully qualified with something like rel2abs of File::Spec::Functions.
# perl scripts may need to be called via $^X, '--', './bin/foo' to use
# the correct perl and to turn off perl's command line switches
@Test2::Tools::Command::command = ( $^X, '-E' );

( $pid, $in, $out, $err ) = Test2::Tools::Command::_command {
    args    => ['say $ENV{FOO};use Cwd;say getcwd;print readline'],
    binmode => ':encoding(UTF-8)',
    chdir   => catdir(qw{t unsupercilious}),
    env     => { FOO => 'ZZZ' },
    stdin   => "$$\n",
};
waitpid $pid, 0;
$stdout = readline $out;             # custom ENV
is $stdout,   "ZZZ\n";
is $ENV{FOO}, "bar$$";
chomp( my $cwd = readline $out );    # where are we?
my @dirs = splitdir $cwd;
is $dirs[-1], 'unsupercilious';
my $mypid = readline $out;           # {stdin}
is $mypid, "$$\n";

# look ma, no args
{
    local @Test2::Tools::Command::command = ( $^X, '-e', 'sleep 99' );
    like dies { command { timeout => 1 } }, qr/timeout/;
}

# scope mostly so that variable names from above are not tripped over
{
    my $rand_status = 42 + int rand 42;
    my ( $out, $err, $status ) = command {
        args         => ["say q{out$$}; warn qq{err\n}; exit $rand_status"],
        munge_status => 1,
        status       => 1,
        stdout       => "out$$\n",
        stderr       => "err\n"
    };
    # the original exit status word is returned, not the hashref form
    is $status >> 8, $rand_status;
    is $$out,        "out$$\n";
    is $$err,        "err\n";

    my ( $out_fh, $err_fh, $nstatus ) = command {
        args    => ["say q{out$$}; warn qq{err\n}"],
        status  => undef,                              # same as 0
        want_fh => 1
    };
    is $nstatus,          0;
    is readline($out_fh), "out$$\n";
    is readline($err_fh), "err\n";
}

# PORTABILITY signal may vary here; this is for OpenBSD 7.2 (if so may
# need a "munge_signal" or to make this an author-only test)
command {
    args   => ['CORE::dump'],
    status => { code => 0, iscore => 1, signal => 6 },
    timeout => 0,
};
unlink 'perl.core';

# mostly for test coverage
command {
    args         => ['exit 0'],
    munge_status => 1,
    timeout      => 3,
};

like dies {
    command {
        args  => ['exit 0'],
        chdir => "no/such/dir/$$/unless/someone/mkdir/this",
    }
}, qr/chdir failed/;
# TODO failing on chdir back to $orig_dir that no longer exists
# might be tricky; would need to chdir this test program to a
# temporary dir, then remove that directory... eh...

done_testing;
