diff options
Diffstat (limited to 't')
-rwxr-xr-x | t/buildsystems/buildsystem_tests | 275 | ||||
-rw-r--r-- | t/buildsystems/parallel.mk | 21 |
2 files changed, 288 insertions, 8 deletions
diff --git a/t/buildsystems/buildsystem_tests b/t/buildsystems/buildsystem_tests index 8f7a275a..41c0f977 100755 --- a/t/buildsystems/buildsystem_tests +++ b/t/buildsystems/buildsystem_tests @@ -1,6 +1,6 @@ #!/usr/bin/perl -use Test::More tests => 228; +use Test::More tests => 273; use strict; use warnings; @@ -49,12 +49,32 @@ sub process_stdout { my ($cmdline, $stdin) = @_; my ($reader, $writer); - open2($reader, $writer, $cmdline) or die "Unable to exec $cmdline"; + my $pid = open2($reader, $writer, $cmdline) or die "Unable to exec $cmdline"; print $writer $stdin if $stdin; close $writer; + waitpid($pid, 0); + $? = $? >> 8; # exit status return readlines($reader); } +sub write_debian_rules { + my $contents=shift; + my $backup; + + if (-f "debian/rules") { + (undef, $backup) = tempfile(DIR => ".", OPEN => 0); + rename "debian/rules", $backup; + } + # Write debian/rules if requested + if ($contents) { + open(my $f, ">", "debian/rules"); + print $f $contents;; + close($f); + chmod 0755, "debian/rules"; + } + return $backup; +} + ### Test Buildsystem class API methods is( $BS_CLASS->canonpath("path/to/the/./nowhere/../../somewhere"), "path/to/somewhere", "canonpath no1" ); @@ -384,17 +404,19 @@ EOF } $tmp = Cwd::getcwd(); -is_deeply( process_stdout("$^X -- - --builddirectory='autoconf/bld dir' --sourcedirectory autoconf", +# NOTE: disabling parallel building explicitly (it might get automatically +# enabled if run under dpkg-buildpackage -jX) to make output deterministic. +is_deeply( process_stdout("$^X -- - --builddirectory='autoconf/bld dir' --sourcedirectory autoconf --parallel=1", get_load_bs_source(undef, "configure")), - [ 'NAME=autoconf', 'builddir=autoconf/bld dir', "cwd=$tmp", 'makecmd=make', 'sourcedir=autoconf' ], + [ 'NAME=autoconf', 'builddir=autoconf/bld dir', "cwd=$tmp", 'makecmd=make', 'parallel=1', 'sourcedir=autoconf' ], "autoconf autoselection and sourcedir/builddir" ); -is_deeply( process_stdout("$^X -- - -Sautoconf -D autoconf", get_load_bs_source("autoconf", "build")), - [ 'NAME=autoconf', 'builddir=undef', "cwd=$tmp", 'makecmd=make', 'sourcedir=autoconf' ], +is_deeply( process_stdout("$^X -- - -Sautoconf -D autoconf --parallel=1", get_load_bs_source("autoconf", "build")), + [ 'NAME=autoconf', 'builddir=undef', "cwd=$tmp", 'makecmd=make', 'parallel=1', 'sourcedir=autoconf' ], "forced autoconf and sourcedir" ); -is_deeply( process_stdout("$^X -- - -B -Sautoconf", get_load_bs_source("autoconf", "build")), - [ 'NAME=autoconf', "builddir=$default_builddir", "cwd=$tmp", 'makecmd=make', 'sourcedir=.' ], +is_deeply( process_stdout("$^X -- - -B -Sautoconf --parallel=1", get_load_bs_source("autoconf", "build")), + [ 'NAME=autoconf', "builddir=$default_builddir", "cwd=$tmp", 'makecmd=make', 'parallel=1', 'sourcedir=.' ], "forced autoconf and default build directory" ); # Build the autoconf test package @@ -459,6 +481,243 @@ dh_auto_do_autoconf('autoconf'); dh_auto_do_autoconf('autoconf', 'bld/dir', configure_args => [ "--extra-autoconf-configure-arg" ]); ok ( ! -e 'bld', "bld got deleted too" ); +#### Test parallel building and related options / routines +@tmp = ( $ENV{MAKEFLAGS}, $ENV{DEB_BUILD_OPTIONS} ); + +# Test get_make_jobserver_status() sub + +$ENV{MAKEFLAGS} = "--jobserver-fds=103,104 -j"; +is_deeply( [ get_make_jobserver_status() ], [ "jobserver-unavailable", undef ], + "get_make_jobserver_status(): unavailable jobserver, unset makeflags" ); + +$ENV{MAKEFLAGS} = "-a --jobserver-fds=103,104 -j -b"; +is_deeply( [ get_make_jobserver_status() ], [ "jobserver-unavailable", "-a -b" ], + "get_make_jobserver_status(): unavailable jobserver, clean makeflags" ); + +$ENV{MAKEFLAGS} = " --jobserver-fds=1,2 -j "; +is_deeply( [ get_make_jobserver_status() ], [ "jobserver", undef ], + "get_make_jobserver_status(): jobserver (available), clean makeflags" ); + +$ENV{MAKEFLAGS} = "-a -j -b"; +is_deeply( [ get_make_jobserver_status() ], [ "jobs-0", "-a -b" ], + "get_make_jobserver_status(): -j" ); + +$ENV{MAKEFLAGS} = "-a --jobs -b"; +is_deeply( [ get_make_jobserver_status() ], [ "jobs-0", "-a -b" ], + "get_make_jobserver_status(): --jobs" ); + +$ENV{MAKEFLAGS} = "-j6"; +is_deeply( [ get_make_jobserver_status() ], [ "jobs-6", undef ], + "get_make_jobserver_status(): -j6" ); + +$ENV{MAKEFLAGS} = "-a -j6 --jobs=7"; +is_deeply( [ get_make_jobserver_status() ], [ "jobs-7", "-a" ], + "get_make_jobserver_status(): -j6 --jobs=7" ); + +$ENV{MAKEFLAGS} = "-j6 --jobserver-fds=5,6 --jobs=8"; +is_deeply( [ get_make_jobserver_status() ], [ "jobserver-unavailable", "-j6 --jobs=8" ], + "get_make_jobserver_status(): mixed jobserver and -j/--jobs" ); + +# Test parallel building with makefile build system. +$ENV{MAKEFLAGS} = ""; +$ENV{DEB_BUILD_OPTIONS} = ""; + +sub do_parallel_mk { + my $dh_opts=shift || ""; + my $make_opts=shift || ""; + return process_stdout( + "LANG=C LC_ALL=C LC_MESSAGES=C $TOPDIR/dh_auto_build -Smakefile $dh_opts " . + "-- -s -f parallel.mk $make_opts 2>&1 >/dev/null", ""); +} + +sub test_isnt_parallel { + my ($got, $desc) = @_; + my @makemsgs = grep /^make[\d\[\]]*:/, @$got; + if (@makemsgs) { + like( $makemsgs[0], qr/Error 10/, $desc ); + } + else { + ok( scalar(@makemsgs) > 0, $desc ); + } +} + +sub test_is_parallel { + my ($got, $desc) = @_; + is_deeply( $got, [] , $desc ); + is( $?, 0, "(exit status=0) $desc"); +} + +test_isnt_parallel( do_parallel_mk(), + "No parallel by default" ); +test_isnt_parallel( do_parallel_mk("--parallel"), + "No parallel by default with --parallel" ); + +$ENV{DEB_BUILD_OPTIONS}="parallel=5"; +test_isnt_parallel( do_parallel_mk(), + "DEB_BUILD_OPTIONS=parallel=5 without --parallel" ); +test_is_parallel( do_parallel_mk("--parallel"), + "DEB_BUILD_OPTIONS=parallel=5 with --parallel" ); +test_is_parallel( do_parallel_mk("--parallel=2"), + "DEB_BUILD_OPTIONS=parallel=5 with --parallel=2" ); +test_isnt_parallel( do_parallel_mk("--parallel=1"), + "DEB_BUILD_OPTIONS=parallel=5 with --parallel=1 (off)" ); + +$ENV{MAKEFLAGS} = "--jobserver-fds=105,106 -j"; +$ENV{DEB_BUILD_OPTIONS}=""; +test_isnt_parallel( do_parallel_mk(), + "makefile.pm (no parallel): no make warnings about unavailable jobserver" ); +$ENV{DEB_BUILD_OPTIONS}="parallel=5"; +test_is_parallel( do_parallel_mk("--parallel"), + "DEB_BUILD_OPTIONS=parallel=5 with --parallel: no make warnings about unavail parent jobserver" ); + +$ENV{MAKEFLAGS} = "-j2"; +$ENV{DEB_BUILD_OPTIONS}=""; +test_is_parallel( do_parallel_mk(), + "MAKEFLAGS=-j2 without --parallel: dh_auto_build honours MAKEFLAGS" ); +test_isnt_parallel( do_parallel_mk("--parallel=1"), + "MAKEFLAGS=-j2 with --parallel=1: dh_auto_build enforces -j1" ); + +# Test dh dpkg-buildpackage -jX detection +sub do_rules_for_parallel { + my $cmdline=shift || ""; + my $stdin=shift || ""; + return process_stdout("LANG=C LC_ALL=C LC_MESSAGES=C PATH=$TOPDIR:\$PATH " . + "make -f - $cmdline 2>&1 >/dev/null", $stdin); +} + +# Simulate dpkg-buildpackage -j5 +doit("ln", "-s", "parallel.mk", "Makefile"); + +sub test_dh_parallel { + my $extra_dsc=shift || ""; + my $debian_rules=shift || ""; + my $rules; + my $tmpfile; + + $ENV{MAKEFLAGS} = "-j5"; + $ENV{DEB_BUILD_OPTIONS} = "parallel=5"; + + # Write debian/rules if requested + $tmpfile = write_debian_rules($debian_rules); + + $rules = <<'EOF'; +%: + @dh_clean > /dev/null 2>&1 + @dh --buildsystem=makefile --after=dh_auto_configure --until=dh_auto_build $@ + @dh_clean > /dev/null 2>&1 +EOF + test_is_parallel( do_rules_for_parallel("build", $rules), + "dh adds --parallel implicitly under dpkg-buildpackage -j5 $extra_dsc"); + + $ENV{MAKEFLAGS} = ""; + test_isnt_parallel( do_rules_for_parallel("build", $rules), + "DEB_BUILD_OPTIONS=parallel=5 without MAKEFLAGS=-jX via dh $extra_dsc" ); + + $ENV{MAKEFLAGS} = "-j5"; + $rules = <<'EOF'; +%: + @dh_clean > /dev/null 2>&1 + @dh -j1 --buildsystem=makefile --after=dh_auto_configure --until=dh_auto_build $@ + @dh_clean > /dev/null 2>&1 +EOF + test_isnt_parallel( do_rules_for_parallel("build", $rules), + "dh -j1 disables implicit parallel under dpkg-buildpackage -j5 $extra_dsc"); + + $rules = <<'EOF'; +%: + @dh_clean > /dev/null 2>&1 + @dh -j --buildsystem=makefile --after=dh_auto_configure --until=dh_auto_build $@ + @dh_clean > /dev/null 2>&1 +EOF + test_is_parallel( do_rules_for_parallel("build", $rules), + "dh -j under dpkg-buildpackage -j5 is parallel $extra_dsc"); + $ENV{MAKEFLAGS} = ""; + test_is_parallel( do_rules_for_parallel("build", $rules), + "dh -j is parallel only with DEB_BUILD_OPTIONS=parallel=5 $extra_dsc"); + + if (defined $tmpfile) { + rename($tmpfile, "debian/rules"); + } + elsif ($debian_rules) { + unlink("debian/rules"); + } +} + +# dh should pass the same tests with and without overrides +test_dh_parallel(); +test_dh_parallel("(with overrides)", <<'EOF'); +#!/usr/bin/make -f +override_dh_auto_build: + @dh_auto_build -- -f parallel.mk +EOF + +# Test if legacy punctuation hacks (+) work as before +$ENV{MAKEFLAGS} = "-j5"; +$ENV{DEB_BUILD_OPTIONS} = "parallel=5"; +$tmp = write_debian_rules(<<'EOF'); +#!/usr/bin/make -f +%: + @dh_clean > /dev/null 2>&1 + @+dh --buildsystem=makefile --after=dh_auto_configure --until=dh_auto_build $@ + @dh_clean > /dev/null 2>&1 +EOF +test_is_parallel( do_rules_for_parallel("build", "include debian/rules"), + "legacy punctuation hacks: +dh, no override" ); +unlink "debian/rules"; + +write_debian_rules(<<'EOF'); +#!/usr/bin/make -f +override_dh_auto_build: + dh_auto_build +%: + @dh_clean > /dev/null 2>&1 + @+dh --buildsystem=makefile --after=dh_auto_configure --until=dh_auto_build $@ + @dh_clean > /dev/null 2>&1 +EOF +test_isnt_parallel( do_rules_for_parallel("build", "include debian/rules"), + "legacy punctuation hacks: +dh, override without +, no parallel, no make warnings" ); +unlink "debian/rules"; + +write_debian_rules(<<'EOF'); +#!/usr/bin/make -f +override_dh_auto_build: + +dh_auto_build +%: + @dh_clean > /dev/null 2>&1 + @+dh --buildsystem=makefile --after=dh_auto_configure --until=dh_auto_build $@ + @dh_clean > /dev/null 2>&1 +EOF +test_is_parallel( do_rules_for_parallel("build", "include debian/rules"), + "legacy punctuation hacks: +dh, override with +" ); +unlink "debian/rules"; + +write_debian_rules(<<'EOF'); +#!/usr/bin/make -f +override_dh_auto_build: + $(MAKE) +%: + @dh_clean > /dev/null 2>&1 + @+dh --buildsystem=makefile --after=dh_auto_configure --until=dh_auto_build $@ + @dh_clean > /dev/null 2>&1 +EOF +test_is_parallel( do_rules_for_parallel("build", "include debian/rules"), + "legacy punctuation hacks: +dh, override with \$(MAKE)" ); +unlink "debian/rules"; + +if (defined $tmp) { + rename($tmp, "debian/rules"); +} +else { + unlink("debian/rules"); +} + +# Clean up after parallel testing +END { + system("rm", "-f", "Makefile"); +} +$ENV{MAKEFLAGS} = $tmp[0] if defined $tmp[0]; +$ENV{DEB_BUILD_OPTIONS} = $tmp[1] if defined $tmp[1]; + END { system("rm", "-rf", $tmpdir); system("$TOPDIR/dh_clean"); diff --git a/t/buildsystems/parallel.mk b/t/buildsystems/parallel.mk new file mode 100644 index 00000000..3e0d201d --- /dev/null +++ b/t/buildsystems/parallel.mk @@ -0,0 +1,21 @@ +all: FIRST SECOND + +TMPFILE ?= $(CURDIR)/parallel.mk.lock + +rmtmpfile: + @rm -f "$(TMPFILE)" + +FIRST: rmtmpfile + @c=0; \ + while [ $$c -le 5 ] && \ + ([ ! -e "$(TMPFILE)" ] || [ "`cat "$(TMPFILE)"`" != "SECOND" ]); do \ + c=$$(($$c+1)); \ + sleep 0.1; \ + done; \ + rm -f "$(TMPFILE)"; \ + if [ $$c -gt 5 ]; then exit 10; else exit 0; fi + +SECOND: rmtmpfile + @echo $@ > "$(TMPFILE)" + +.PHONY: all FIRST SECOND rmtmpfile |