#                                                                    -*-perl-*-

$description = 'Test the $(shell ...) function.';

$details = '';

# Test standard shell
run_make_test('.PHONY: all
OUT := $(shell echo hi)
all: ; @echo $(OUT)
              ','','hi');

# Test shells inside rules.
run_make_test('.PHONY: all
all: ; @echo $(shell echo hi)
              ','','hi');

# Verify .SHELLSTATUS
run_make_test('.PHONY: all
PRE := $(.SHELLSTATUS)
$(shell exit 0)
OK := $(.SHELLSTATUS)
$(shell exit 1)
BAD := $(.SHELLSTATUS)
all: ; @echo PRE=$(PRE) OK=$(OK) BAD=$(BAD)
              ','','PRE= OK=0 BAD=1');

# Test unescaped comment characters in shells.  Savannah bug #20513
run_make_test(q!
FOO := $(shell echo '#')
foo: ; echo '$(FOO)'
!,
              '', "echo '#'\n#\n");

# Test that exported variables are passed to $(shell ...)
$ENV{FOO} = 'baz';
run_make_test(q!
OUT = $(shell echo $$FOO)
foo: ; @echo '$(OUT)'
!,
              '', 'baz');

$ENV{FOO} = 'baz';
run_make_test(q!
FOO = bar
OUT = $(shell echo $$FOO)
foo: ; @echo '$(OUT)'
!,
              '', 'bar');

run_make_test(q!
export FOO = bar
OUT = $(shell echo $$FOO)
foo: ; @echo '$(OUT)'
!,
              '', 'bar');

# Test shells inside exported environment variables, simply expanded.
run_make_test('
export HI := $(shell echo hi)
.PHONY: all
all: ; @echo $$HI
',
              '','hi');

# Test shells inside exported environment variables.  See SV 10593
run_make_test('
export HI = $(shell echo hi)
.PHONY: all
all: ; @echo $$HI
',
              '',"hi");

$ENV{HI} = 'foo';
run_make_test('
HI = $(shell echo hi)
.PHONY: all
all: ; @echo $$HI
',
              '',"hi");

$ENV{HI} = 'foo';
run_make_test('
HI = $(shell echo hi)
bad := $(HI)
.PHONY: all
all: ; @echo $$HI $(bad)
',
              '',"hi hi");

# SV 63016: Exported variable that contains a variable containing $(shell...)

run_make_test('
HI = $(shell echo hi)
export bad = $(HI)
.PHONY: all
all:; : $(HI)
',
              '',": hi");

$ENV{HI} = 'outer';
run_make_test('
export HI = $(shell echo $$HI)
.PHONY: all
all:; @echo $$HI
',
              '',"outer");

$ENV{HI} = 'outer';
run_make_test('
export HI = $(shell echo $$HI)
.PHONY: all
all:; : $(HI)
',
              '',": outer");

if ($port_type ne 'W32') {
    # Test shell errors in recipes including offset
    # This needs to be ported to Windows, or else Windows error messages
    # need to converted to look like more normal make errors.
    run_make_test('
.RECIPEPREFIX = >
all:
>@echo hi
>$(shell ./basdfdfsed there)
>@echo $(.SHELLSTATUS)
',
                  '', "#MAKE#: ./basdfdfsed: $ERR_no_such_file\nhi\n127\n");

    run_make_test('
$(shell ./basdfdfsed where)
all: ; @echo $(.SHELLSTATUS)
',
                  '', "#MAKE#: ./basdfdfsed: $ERR_no_such_file\n127\n");

    # Test SHELLSTATUS for kill.
    # This test could be ported to Windows, using taskkill ... ?

    # Figure out the exit code for SIGINT
    my $pid = fork();
    if (! $pid) {
        exec('kill -2 $$') or die "exec: Cannot execute sleep\n";
    }
    waitpid($pid, 0);
    # .SHELLSTATUS for a signal gives 128 + the signal number
    my $ret = $?;
    if ($ret > 255) {
       # Solaris 10 perl 5.8.4 puts signal number + 128 into the high 8 bits.
       $ret >>= 8;
    }
    $ret |= 128;

    run_make_test('.PHONY: all
$(shell kill -2 $$$$)
STAT := $(.SHELLSTATUS)
all: ; @echo STAT=$(STAT)
              ','',"STAT=$ret\n");

    # Test that not-found errors can be redirected
    if ($ERR_command_not_found) {
        $_ = $ERR_command_not_found;
        s/#CMDNAME#/bad-command/g;
        run_make_test(q!
out := $(shell bad-command 2>&1)
all: ; @echo '$(.SHELLSTATUS): $(out)'
!,
                      '', "127: $_\n");
    }

    # If we're using pipes for jobserver, then we will close them and not
    # allow them to be available to sub-makes invoked via $(shell ...)
    if (exists $FEATURES{'jobserver'}) {
        run_make_test(q!
ifeq ($(ELT),)
default:; @$(MAKE) -f #MAKEFILE# ELT=1
else ifeq ($(ELT),1)
OUTPUT := $(shell $(MAKE) -f #MAKEFILE# ELT=2)
$(info $(OUTPUT))
default:;: $(ELT)
else
default:;: $(ELT)
endif
!,
                      '--no-print-directory -j2 --jobserver-style=pipe', "#MAKE#[2]: warning: jobserver unavailable: using -j1.  Add '+' to parent make rule.\n: 2\n: 1");
    }

    # This crashes if we use vfork and don't reset environ properly
    run_make_test(q!
export PATH = $(shell echo "tests:$$PATH")
foo = $(shell echo yes)

all:;echo $(foo)
!,
                  '', "echo yes\nyes\n");
}

# If we're not using pipes for jobserver, then they are available in sub-makes
# invoked by $(shell ...)
if ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) {
    run_make_test(q!
ifeq ($(ELT),)
default:; @$(MAKE) -f #MAKEFILE# ELT=1
else ifeq ($(ELT),1)
OUTPUT := $(shell $(MAKE) -f #MAKEFILE# ELT=2)
$(info $(OUTPUT))
default:;: $(ELT)
else
default:;: $(ELT)
endif
!,
                  '--no-print-directory -j2', ": 2\n: 1");
}

1;
