#                                                                    -*-perl-*-

$description = "Test jobserver.";

$details = "These tests are ones that specifically are different when the
jobserver feature is available.  Most -j tests are the same whether or not
jobserver is available, and those appear in the 'parallelism' test suite.";

exists $FEATURES{'jobserver'} or return -1;

if (!$parallel_jobs) {
  return -1;
}

# Shorthand
my $np = '--no-print-directory';
my $j1err = "warning: jobserver unavailable: using -j1.  Add '+' to parent make rule.";

# Simple test of MAKEFLAGS settings
run_make_test(q!
SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))
recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all
all:;@echo $@: "/$(SHOW)/"
!,
              "-j2 $np", "recurse: /-j2 --jobserver-auth=<auth> $np/\nall: /-j2 --jobserver-auth=<auth> $np/\n");

# Setting parallelism with the environment
# Command line should take precedence over the environment
$ENV{MAKEFLAGS} = "-j2 $np";
run_make_test(q!
SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))
recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all
all:;@echo $@: "/$(SHOW)/"
!,
              '', "recurse: /-j2 --jobserver-auth=<auth> $np/\nall: /-j2 --jobserver-auth=<auth> $np/\n");

# Test override of -jN
$ENV{MAKEFLAGS} = "-j9 $np";
run_make_test(q!
SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))
recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -j3 -f #MAKEFILE# recurse2
recurse2: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all
all:;@echo $@: "/$(SHOW)/"
!,
              "-j2 $np", "recurse: /-j2 --jobserver-auth=<auth> $np/\n#MAKE#[1]: warning: -j3 forced in submake: resetting jobserver mode.\nrecurse2: /-j3 --jobserver-auth=<auth> $np/\nall: /-j3 --jobserver-auth=<auth> $np/\n");

# Test override of -jN with -j
run_make_test(q!
SHOW = $(patsubst --jobserver-auth=%,--jobserver-auth=<auth>,$(MAKEFLAGS))
recurse: ; @echo $@: "/$(SHOW)/"; $(MAKE) -j -f #MAKEFILE# recurse2
recurse2: ; @echo $@: "/$(SHOW)/"; $(MAKE) -f #MAKEFILE# all
all:;@echo $@: "/$(SHOW)/"
!,
              "-j2 $np", "recurse: /-j2 --jobserver-auth=<auth> $np/\n#MAKE#[1]: warning: -j0 forced in submake: resetting jobserver mode.\nrecurse2: /-j $np/\nall: /-j $np/\n");

# Don't put --jobserver-auth into a re-exec'd MAKEFLAGS.
# We can't test this directly because there's no way a makefile can
# show the value of MAKEFLAGS we were re-exec'd with.  We can intuit it
# by looking for "disabling jobserver mode" warnings; we should only
# get one from the original invocation and none from the re-exec.
# See Savannah bug #18124

unlink('inc.mk');

run_make_test(q!
.RECIPEPREFIX = >
-include inc.mk
recur:
#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
> @rm -f inc.mk
> @$(MAKE) -j2 -f #MAKEFILE# all
all:
#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
> @echo $@
inc.mk:
#> @echo 'MAKEFLAGS = $(MAKEFLAGS)'
> @echo 'FOO = bar' > $@
!,
              "$np -j2", "#MAKE#[1]: warning: -j2 forced in submake: resetting jobserver mode.\nall\n");

unlink('inc.mk');

# Test recursion which is hidden from make.
# See Savannah bug #39934
# Or Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=885474
# Environments that don't use a pipe won't close access, so this won't happen.
if ($port_type ne 'W32') {
    create_file('Makefile2', "vpath %.c ../\n", "foo:\n");

    run_make_test(q!
default: ; @ #MAKEPATH# -f Makefile2
!,
              "--jobserver-style=pipe -j2 $np",
"#MAKE#[1]: $j1err
#MAKE#[1]: Nothing to be done for 'foo'.");

    rmfiles('Makefile2');
}

# For Windows and named pipes, we don't need to worry about recursion
if ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) {
  create_file('Makefile2', "vpath %.c ../\n", "foo:\n");

  run_make_test(q!
default: ; @ #MAKEPATH# -f Makefile2
!,
              "-j2 $np",
"#MAKE#[1]: Nothing to be done for 'foo'.");

  rmfiles('Makefile2');
}

# Ensure enter/leave directory messages appear before jobserver warnings

run_make_test(q!
all: ; @$(MAKE) -C . -f #MAKEFILE# recurse -j1
recurse: ; @echo hi
!,
              '-w -j2', "#MAKE#: Entering directory '#PWD#'
#MAKE#[1]: Entering directory '#PWD#'
#MAKE#[1]: warning: -j1 forced in submake: resetting jobserver mode.
hi
#MAKE#[1]: Leaving directory '#PWD#'
#MAKE#: Leaving directory '#PWD#'\n");

# Check for invalid jobserver-style options

run_make_test(q!
all: a
all a: ; @echo $@
!,
              '--jobserver-style=foo -j8',
              "#MAKE#: *** unknown jobserver auth style 'foo'.  Stop.", 512);

# Ensure the jobserver is not disabled even if only later commands are recursive

run_make_test(q!
.RECIPEPREFIX := >
all:
> @echo $@ 1
> @echo $@ 2
> @$(MAKE) -f #MAKEFILE# recurse

recurse: ; @echo $@
!,
              "$np -j8", "all 1\nall 2\nrecurse");

if ($port_type ne 'W32') {
    run_make_test(undef, "$np --jobserver-style=pipe -j8",
                  "all 1\nall 2\nrecurse");
}

# And with + instead of $(MAKE)

run_make_test(q!
.RECIPEPREFIX := >
all:
> @echo $@ 1
> @echo $@ 2
> @+#MAKEPATH# -f #MAKEFILE# recurse

recurse: ; @echo $@
!,
              "$np -j8", "all 1\nall 2\nrecurse");

if ($port_type ne 'W32') {
    run_make_test(undef, "$np --jobserver-style=pipe -j8",
                  "all 1\nall 2\nrecurse");
}

# We can't reset TMPDIR to something invalid when using valgrind
if (exists $FEATURES{'jobserver-fifo'} && !$valgrind) {
  # sv 62908.
  # Test that when mkfifo fails, make switches to pipe and succeeds.
  # Force mkfifo to fail by attempting to create a fifo in a non existent
  # directory.
  # run_make_test does not allow matching a multiline pattern, therefore run
  # the test twice.
  # First time look for /$ERR_no_such_file/ to ensure mkfifo failed.
  # Second time look for /Nothing to be done/ to ensure make succeeded.
  $ENV{TMPDIR} = "nosuchdir";
  run_make_test("all:\n", '-j2', "/$ERR_no_such_file/");

  $ENV{TMPDIR} = "nosuchdir";
  run_make_test(undef, '-j2', "/Nothing to be done/");

  # Verify that MAKE_TMPDIR is preferred if provided
  $ENV{MAKE_TMPDIR} = '.';
  $ENV{TMPDIR} = 'nosuchdir';

  run_make_test(q!
recurse: ; @$(MAKE) -f #MAKEFILE# all
all:;@echo "$$MAKEFLAGS"
!,
              "-j2 --no-print-directory", "/--jobserver-auth=fifo:\\./");

  # Verify we fall back to -j1 but continue, of the auth is bad.
  $ENV{MAKEFLAGS} = '-j2 --jobserver-auth=fifo:nosuchfile';
  run_make_test(q!all:;@echo hi!, "", "#MAKE#: cannot open jobserver nosuchfile: $ERR_no_such_file\n#MAKE#: $j1err\nhi\n");
}

1;
