From 1ebdc2c1b9a75420dd7518116a1e70b1ad6d93fc Mon Sep 17 00:00:00 2001 From: Stefano Lattarini Date: Wed, 10 Aug 2011 16:03:35 +0200 Subject: [PATCH] coverage: possible infinite recursion in the test harness Motivated by a regression in the 'test-protocols' branch. * tests/parallel-tests-fork-bomb.test: New test, checking that if $(TEST_SUITE_LOG) is in $(TEST_LOGS), we obtain a diagnosed error rather than a make hang or a fork bomb. * tests/Makefile.am (TESTS): Update. --- ChangeLog | 9 ++ tests/Makefile.am | 1 + tests/Makefile.in | 1 + tests/parallel-tests-fork-bomb.test | 142 ++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+) create mode 100755 tests/parallel-tests-fork-bomb.test diff --git a/ChangeLog b/ChangeLog index e08b7c96d..2d7e5d6ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-08-09 Stefano Lattarini + + coverage: possible infinite recursion in the test harness + Motivated by a regression in the 'test-protocols' branch. + * tests/parallel-tests-fork-bomb.test: New test, checking that + if $(TEST_SUITE_LOG) is in $(TEST_LOGS), we obtain a diagnosed + error rather than a make hang or a fork bomb. + * tests/Makefile.am (TESTS): Update. + 2011-08-09 Stefano Lattarini test defs: yet more environment cleanup diff --git a/tests/Makefile.am b/tests/Makefile.am index 82fb90606..833dc7a26 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -733,6 +733,7 @@ parallel-tests-log-override-2.test \ parallel-tests-log-override-recheck.test \ parallel-tests-cmdline-override.test \ parallel-tests-log-compiler-example.test \ +parallel-tests-fork-bomb.test \ parse.test \ percent.test \ percent2.test \ diff --git a/tests/Makefile.in b/tests/Makefile.in index d6d418ced..ede80e6eb 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -1006,6 +1006,7 @@ parallel-tests-log-override-2.test \ parallel-tests-log-override-recheck.test \ parallel-tests-cmdline-override.test \ parallel-tests-log-compiler-example.test \ +parallel-tests-fork-bomb.test \ parse.test \ percent.test \ percent2.test \ diff --git a/tests/parallel-tests-fork-bomb.test b/tests/parallel-tests-fork-bomb.test new file mode 100755 index 000000000..6a385d652 --- /dev/null +++ b/tests/parallel-tests-fork-bomb.test @@ -0,0 +1,142 @@ +#! /bin/sh +# Copyright (C) 2011 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Check parallel-tests features: +# - If $(TEST_SUITE_LOG) is in $(TEST_LOGS), we get a diagnosed +# error, not a make hang or a system freeze. + +parallel_tests=yes +. ./defs || Exit 1 + +# The tricky part of this test is to avoid that make hangs or even +# freezes the system in case infinite recursion (which is the bug we +# are testing against) is encountered. The following hacky makefile +# should minimize the probability of that happening. +cat > Makefile.am << 'END' +TEST_LOG_COMPILER = true +TESTS = + +errmsg = ::OOPS:: Recursion too deep + +if IS_GNU_MAKE + + is_too_deep := $(shell test $(MAKELEVEL) -lt 10 && echo no) + +## Indenteation here required to avoid confusing Automake. + ifeq ($(is_too_deep),no) + else + $(error $(errmsg), $(MAKELEVEL) levels) + endif + +else !IS_GNU_MAKE + +# We use mkdir to detect the level of recursion, since it is easy +# to use and assured to be portably atomical. Also use an higher +# number than with GNU make above, since the level used here can +# be incremented by tow or more per recursion. +recursion-not-too-deep: + @ok=no; \ + for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 \ + 18 19 20 21 22 23 24 25 26 27 28 29; \ + do \ + echo " mkdir rec-$$i.d"; \ + if mkdir rec-$$i.d; then \ + ok=yes; break; \ + else :; fi; \ + done; \ + test $$ok = yes || { echo '$(errmsg)' >&2; exit 1; } +.PHONY: recursion-not-too-deep +clean-local: + rmdir rec-[0-9].d + +targets = all check recheck $(TESTS) $(TEST_LOGS) $(TEST_SUITE_LOG) +$(targets): recursion-not-too-deep + +# For BSD make. +.BEGIN: recursion-not-too-deep + +endif !IS_GNU_MAKE +END + +if using_gmake; then + cond=: +else + cond=false +fi + +cat >> configure.in << END +AM_CONDITIONAL([IS_GNU_MAKE], [$cond]) +AC_OUTPUT +END + +# Another helpful idiom to avoid hanging on capable systems. The subshell +# is needed since `ulimit' might be a special shell builtin. +if (ulimit -t 8); then ulimit -t 8; fi + +$ACLOCAL +$AUTOCONF +$AUTOMAKE -a -Wno-portability + +./configure + +do_check () +{ + st=0 + log=$1; shift + env "$@" $MAKE -e check >output 2>&1 || st=$? + cat output + $FGREP '::OOPS::' output && Exit 1 # Possible infinite recursion. + # Check that at least we don't create a botched global log file. +# FIXME: GNU make currently creates it! +# test ! -f "$log" + # Look for possible error messages about circular dependencies from + # either make or our own recipes. At least one such a message must + # be present. + err_seen=no + for err_rx in \ + 'circular.* depend' \ + 'depend.* circular' \ + 'graph cycle' \ + 'infinite (loop|recursion)' \ + 'depend.* on itself' \ + ; do + $EGREP -i "$err_rx" output | $FGREP "$log" || continue + err_seen=yes + break + done + test $err_seen = yes || Exit 1 + # Some make implementations (e.g., NetBSD's), while smartly detecting + # the circular dependency early and diagnosing it, still exit with a + # successful exit status (yikes!). Relax our checks not to fail in + # this case. + using_gmake && { test $st -gt 0 || Exit 1; } + : +} + +: > test-suite.test +do_check test-suite.log TESTS=test-suite.test +rm -f *.log *.test + +: > 0.test +: > 1.test +: > 2.test +: > 3.test +: > foobar.test +do_check foobar.log TEST_LOGS='0.log 1.log foobar.log 2.log 3.log' \ + TEST_SUITE_LOG=foobar.log +rm -f *.log *.test + +: -- 2.47.2