feat(tfut): add run support for non-interactive run
This patch adds support for non-interactive runs (i.e.: when flag
test_run=0, logging the results of the tests in a directory and
allowing the tests to run in parallel, waiting for the completion
of all of them.
Signed-off-by: Juan Pablo Conde <juanpablo.conde@arm.com>
Signed-off-by: Edward Potapov <edward.potapov@arm.com>
Change-Id: Ieec4abcb330a563383d6317e664ab53141714efa
diff --git a/script/run_unit_tests.sh b/script/run_unit_tests.sh
index 937bb88..8847cbc 100644
--- a/script/run_unit_tests.sh
+++ b/script/run_unit_tests.sh
@@ -13,16 +13,62 @@
source "$ci_root/script/run_common.sh"
source "$ci_root/utils.sh"
+export -f launch
+
artefacts="${artefacts-$workspace/artefacts}"
run_root="$workspace/unit_tests/run"
+pid_dir="$workspace/unit_tests/pids"
mkdir -p "$run_root"
+mkdir -p "$pid_dir"
export run_root
+export pid_dir
export tfut_root="${tfut_root:-$workspace/tfut}"
+kill_and_reap() {
+ local gid
+ # Kill an active process. Ignore errors
+ [ "$1" ] || return 0
+ kill -0 "$1" &>/dev/null || return 0
+
+ # Kill the children
+ kill -- "-$1" &>/dev/null || true
+ # Kill the group
+ { gid="$(awk '{print $5}' < /proc/$1/stat)";} 2>/dev/null || return
+ kill -SIGTERM -- "-$gid" &>/dev/null || true
+ wait "$gid" &>/dev/null || true
+}
+
+# Perform clean up and ignore errors
+cleanup() {
+ local pid
+ local sig
+
+ pushd "$pid_dir"
+ set +e
+
+ sig=${1:-SIGINT}
+ echo "signal received: $sig"
+
+ if [ "$sig" != "EXIT" ]; then
+ # Kill all background processes so far and wait for them
+ while read pid; do
+ pid="$(cat $pid)"
+ echo $pid
+
+ kill_and_reap "$pid"
+
+ done < <(find -name '*.pid')
+ fi
+
+ popd
+}
+
+# Cleanup actions
+trap_with_sig cleanup SIGINT SIGHUP SIGTERM EXIT
run_test() {
test="${1:?}"
@@ -50,6 +96,9 @@
cat "tfut_artefacts.txt" | while read test; do
if upon "$test_run"; then
echo "run_test $test \$@" >> "$run_sh"
+ else
+ echo "name=\"$test\" launch run_test $test \$@ " \
+ "&> \"$run_root/${test}_output.txt\" &" >> "$run_sh"
fi
done
chmod +x "$run_sh"
@@ -60,3 +109,91 @@
"$run_sh" "$@" -v -c
exit 0
fi
+
+# For an automated run, export a known variable so that we can identify stale
+# processes spawned by Trusted Firmware CI by inspecting its environment.
+export TRUSTED_FIRMWARE_CI="1"
+
+# Otherwise, run tests in background and monitor them.
+if upon "$jenkins_run"; then
+ "$run_sh" "$@" -ojunit -v
+else
+ "$run_sh" "$@" -c -v
+fi
+batch_pid=$!
+
+# Wait for all children. Note that the wait below is *not* a timed wait.
+result=0
+
+set +e
+pushd "$pid_dir"
+
+timeout=3600
+
+echo
+
+while :; do
+ readarray -d '' all < <(find "${pid_dir}" -name '*.pid' -print0)
+ readarray -d '' succeeded < <(find "${pid_dir}" -name '*.success' -print0)
+ readarray -d '' failed < <(find "${pid_dir}" -name '*.fail' -print0)
+
+ all=("${all[@]##${pid_dir}/}")
+ all=("${all[@]%%.pid}")
+
+ succeeded=("${succeeded[@]##${pid_dir}/}")
+ succeeded=("${succeeded[@]%%.success}")
+
+ failed=("${failed[@]##${pid_dir}/}")
+ failed=("${failed[@]%%.fail}")
+
+ completed=("${succeeded[@]}" "${failed[@]}")
+
+ readarray -t remaining < <( \
+ comm -23 \
+ <(printf '%s\n' "${all[@]}" | sort) \
+ <(printf '%s\n' "${completed[@]}" | sort) \
+ )
+
+ if [ ${#remaining[@]} = 0 ]; then
+ break
+ fi
+
+ if [ ${timeout} = 0 ]; then
+ echo "- Timeout exceeded! Killing all processes..."
+
+ cleanup
+ fi
+
+ timeout=$((${timeout} - 5)) && sleep 5
+done
+
+echo
+
+if [ ${#failed[@]} != 0 ]; then
+ echo "${#failed[@]} tests failed:"
+ echo
+
+ for test in "${failed[@]}"; do
+ echo " - Test ${test}: ${test}_output.txt"
+ done
+
+ echo
+
+ result=1
+fi
+
+popd
+
+if [ "$result" -eq 0 ]; then
+ echo "Unit testing success!"
+else
+ echo "Unit testing failed!"
+fi
+
+if upon "$jenkins_run"; then
+ echo
+ echo "Artefacts location: $BUILD_URL."
+ echo
+fi
+
+exit "$result"