This will allow us to run the Automake testsuite forcing all the make invocations in the test cases to run in parallel mode [1], but without hitting the spurious failure reported in automake bug#11413.
See also: <http://lists.gnu.org/archive/html/bug-make/2013-05/msg00135.html> The make invocations in the test cases can be forced to run in parallel mode by, e.g., invoking "make check" like this: make check AM_TESTSUITE_MAKE="make -j16" The possible spurious failures hinted above are due to the fact that the redirected output of parallel make can racily lose lines. For example, if GNU make (3.82) is run with -j10 on a Makefile like this: all = 0 1 2 3 4 5 6 7 8 9 default: $(all) $(all): @sleep 0.$$(($RANDOM % 10)); echo $@ and has its standard output redirected in overwrite-mode to a regular file, it looses a line of that output every 15 runs or so on a Fedora 17 system with 64 ppc64 cores. Redirection in append mode does not suffer of this problem, as explained here: <http://lists.gnu.org/archive/html/automake-patches/2009-03/msg00073.html> See also previous commits v1.12-63-g45c1fcd of 2012-05-05 (tests: use append mode to capture parallel make output) and Release-1-10-280-g6426999 of 2009-03-10 (Use append mode to capture parallel test output). * t/ax/am-test-lib.sh (run_make): Adjust and enhance. * t/lisp8.sh: Take advantage of the enhancement, nd stop doing output redirection for $MAKE by hand. * t/tap-more.sh: Likewise. * t/parallel-tests-concurrency.sh: Likewise. Signed-off-by: Stefano Lattarini <stefano.lattar...@gmail.com> --- t/ax/am-test-lib.sh | 55 ++++++++++++++++++++++++++++++----------- t/lisp8.sh | 17 +++---------- t/parallel-tests-concurrency.sh | 8 ++---- t/tap-more.sh | 20 ++++++--------- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/t/ax/am-test-lib.sh b/t/ax/am-test-lib.sh index 8072ce0..7aed3ee 100644 --- a/t/ax/am-test-lib.sh +++ b/t/ax/am-test-lib.sh @@ -184,7 +184,9 @@ is_valid_varname () # run_make () { - am__make_redirect= + am__make_redirect_stdout=no + am__make_redirect_stderr=no + am__make_redirect_stdall=no am__make_flags= # Follow-up code might want to analyse these, so don't make them as # private, nor unset them later. @@ -194,15 +196,16 @@ run_make () while test $# -gt 0; do case $1 in -e) am_make_rc_exp=$2; shift;; - -O) am__make_redirect="$am__make_redirect >stdout";; - -E) am__make_redirect="$am__make_redirect 2>stderr";; - -M) am__make_redirect=">output 2>&1";; + -O) am__make_redirect_stdout=yes;; + -E) am__make_redirect_stderr=yes;; + -M) am__make_redirect_stdall=yes;; --) shift; break;; *) break;; esac shift done + # Use append mode here to avoid dropping output. See automake bug#11413 if using_gmake; then # We can trust GNU make to correctly pass macro definitions given # on the command line down to sub-make invocations, and this allow @@ -247,16 +250,41 @@ run_make () unset am__make_flags fi - eval "\$MAKE${am__make_redirect}"' ${1+"$@"}' || am_make_rc_got=$? + # In redirecting make output below, use append mode, to avoid + # dropping output. See automake bug#11413 for details. + # The exit status of 253 is a more-or-less random choice, to + # help us catch possible errors in redirections and error out + # accordingly. + ( + : exec $MAKE ${1+"$@"} # Display traces for future command. + set +x # We need to remove them now, not to pollute redirected stderr. + if test $am__make_redirect_stdall = yes; then + : > output && exec 1>>output 2>&1 || exit 253 + else + if test $am__make_redirect_stdout = yes; then + : > stdout && exec 1>>stdout || exit 253 + fi + if test $am__make_redirect_stderr = yes; then + : > stderr && exec 2>>stderr || exit 253 + fi + fi + exec $MAKE ${1+"$@"} + ) || am_make_rc_got=$? - case $am__make_redirect in - *output*) cat output;; - *stderr*stdout*) cat stdout && cat stderr >&2;; - *stdout*stderr*) cat stdout && cat stderr >&2;; - *stdout*) cat stdout;; - *stderr*) cat stderr >&2;; - esac \ - || fatal_ "displaying make output" + if test $am_make_rc_got -eq 253; then + fatal_ "run_make: problems in redirecting make output" + fi + + if test $am__make_redirect_stdall = yes; then + cat output || fatal_ "displaying make output" + else + if test $am__make_redirect_stdout = yes; then + cat stdout || fatal_ "displaying make output" + fi + if test $am__make_redirect_stderr = yes; then + cat stderr >&2 || fatal_ "displaying make output" + fi + fi case $am_make_rc_exp in IGNORE) @@ -271,7 +299,6 @@ run_make () test $am_make_rc_exp -eq $am_make_rc_got || return 1 ;; esac - unset am__make_redirect } # AUTOMAKE_run [-e STATUS] [-d DESCRIPTION] [--] [AUTOMAKE-ARGS...] diff --git a/t/lisp8.sh b/t/lisp8.sh index efb785c..c424886 100644 --- a/t/lisp8.sh +++ b/t/lisp8.sh @@ -37,26 +37,17 @@ $AUTOCONF $AUTOMAKE --add-missing ./configure -# Use append mode here to avoid dropping output. See automake bug#11413. -# TODO: port this to to run_make(), and rewrite this hunk to use that -# function ... -: >stdout -$MAKE -j >>stdout || { cat stdout; exit 1; } -cat stdout +run_make -O -- -j test -f am-one.elc test -f am-two.elc test -f am-three.elc +# Delete ... rm -f am-*.elc -# Use append mode here to avoid dropping output. See automake bug#11413. -# TODO: port this to to run_make(), and rewrite this hunk to use that -# function ... -: >stdout -$MAKE -j >>stdout || { cat stdout; exit 1; } -cat stdout - +# ... and recover. +run_make -O -- -j test -f am-one.elc test -f am-two.elc test -f am-three.elc diff --git a/t/parallel-tests-concurrency.sh b/t/parallel-tests-concurrency.sh index dd51225..7fbd20e 100644 --- a/t/parallel-tests-concurrency.sh +++ b/t/parallel-tests-concurrency.sh @@ -40,7 +40,7 @@ END if test x"$j" = xNONE; then skip_ "can't run make in parallel mode" fi - $MAKE ${j}2 all >output 2>&1 || continue + run_make -M -- ${j}2 all || continue $EGREP -i "(warning|error):|-j[\"\'\` ]" output && continue break done @@ -92,11 +92,7 @@ cd serial $MAKE ${j}1 check & cd ../parallel $sleep -# Use append mode here to avoid dropping output. See automake bug#11413. -# TODO: port this to to run_make(), and rewrite this hunk to use that -# function ... -: > stdout -$MAKE ${j}4 check >> stdout +run_make -O -- ${j}4 check cd .. # Ensure the tests are really being run in parallel mode: if this is # the case, the serial run of the dummy testsuite started above should diff --git a/t/tap-more.sh b/t/tap-more.sh index 14a7918..19d2e61 100644 --- a/t/tap-more.sh +++ b/t/tap-more.sh @@ -85,7 +85,7 @@ for try in 0 1; do mkdir build cd build srcdir=.. - run_make=$MAKE + am_make=$MAKE elif test $try -eq 1; then # In-tree parallel build. srcdir=. @@ -93,7 +93,7 @@ for try in 0 1; do *\ -j*) # Degree of parallelism already specified by the user: do # not override it. - run_make=$MAKE + : ;; *) # Some make implementations (e.g., HP-UX) don't grok '-j', @@ -102,10 +102,12 @@ for try in 0 1; do # space between '-j' and the number of jobs (e.g., Solaris # dmake). We need a runtime test to see what works. echo 'all:' > Makefile - for run_make in "$MAKE -j3" "$MAKE -j 3" "$MAKE"; do - $run_make && break + for am_make in "$MAKE -j3" "$MAKE -j 3" "$MAKE"; do + $am_make && break done rm -f Makefile + MAKE=$am_make + unset am_make ;; esac else @@ -117,10 +119,7 @@ for try in 0 1; do # Success. - # Use append mode here to avoid dropping output. See automake bug#11413. - : >stdout - $run_make check >>stdout || { cat stdout; exit 1; } - cat stdout + run_make -O check count_test_results total=6 pass=4 fail=0 xpass=0 xfail=1 skip=1 error=0 grep '^PASS: 1\.test 1 - mu$' stdout grep '^SKIP: 1\.test 2 zardoz # SKIP$' stdout @@ -137,10 +136,7 @@ for try in 0 1; do : > not-skip : > bail-out - # Use append mode here to avoid dropping output. See automake bug#11413. - : >stdout - $run_make check >>stdout && { cat stdout; exit 1; } - cat stdout + run_make -e FAIL -O check count_test_results total=7 pass=4 fail=1 xpass=0 xfail=1 skip=0 error=1 grep '^PASS: 1\.test 1 - mu$' stdout grep '^FAIL: 1\.test 2 zardoz$' stdout -- 1.8.3.rc2