# HACK: get newline for use in strings given that "\n" and $'' do not work. NL="$(printf '\nE')" NL="${NL%E}" FAIL_SUMMARY="" # Test success marker. If END_MARKER file exists, we know that all tests # finished. If FAIL_SUMMARY_FILE exists we know that some tests failed, this # file will contain information about failed tests. Build is considered # successful if tests ended without any of them failing. END_MARKER="$BUILD_DIR/.tests_finished" FAIL_SUMMARY_FILE="$BUILD_DIR/.test_errors" ANSI_CLEAR="\033[0K" if test "$TRAVIS" = "true"; then ci_fold() { local action="$1" local name="$2" name="$(echo -n "$name" | tr '\n\0' '--' | sed 's/[^A-Za-z0-9]\{1,\}/-/g')" name="$(echo -n "$name" | sed 's/-$//')" echo -en "travis_fold:${action}:${name}\r${ANSI_CLEAR}" } elif test "$GITHUB_ACTIONS" = "true"; then ci_fold() { local action="$1" local name="$2" name="$(echo -n "$name" | tr '\n\0' '--' | sed 's/[^A-Za-z0-9]\{1,\}/-/g')" name="$(echo -n "$name" | sed 's/-$//')" case "$action" in start) echo "::group::${name}" ;; end) echo "::endgroup::" ;; *) :;; esac } else ci_fold() { return 0 } fi enter_suite() { set +x FAILED=0 rm -f "${END_MARKER}" local suite_name="$1" export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE}/$suite_name" ci_fold start "${NVIM_TEST_CURRENT_SUITE}" set -x } exit_suite() { set +x if test $FAILED -ne 0 ; then echo "Suite ${NVIM_TEST_CURRENT_SUITE} failed, summary:" echo "${FAIL_SUMMARY}" else ci_fold end "${NVIM_TEST_CURRENT_SUITE}" fi export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE%/*}" if test "$1" != "--continue" ; then exit $FAILED else local saved_failed=$FAILED FAILED=0 return $saved_failed fi } fail() { local test_name="$1" local fail_char="$2" local message="$3" : ${fail_char:=F} : ${message:=Test $test_name failed} local full_msg="$fail_char $NVIM_TEST_CURRENT_SUITE|$test_name :: $message" FAIL_SUMMARY="${FAIL_SUMMARY}${NL}${full_msg}" echo "${full_msg}" >> "${FAIL_SUMMARY_FILE}" echo "Failed: $full_msg" FAILED=1 } run_test() { local cmd="$1" test $# -gt 0 && shift local test_name="$1" : ${test_name:=$cmd} test $# -gt 0 && shift if ! eval "$cmd" ; then fail "${test_name}" "$@" fi } run_test_wd() { local hang_ok= if test "$1" = "--allow-hang" ; then hang_ok=1 shift fi local timeout="$1" test $# -gt 0 && shift local cmd="$1" test $# -gt 0 && shift local restart_cmd="$1" : ${restart_cmd:=true} test $# -gt 0 && shift local test_name="$1" : ${test_name:=$cmd} test $# -gt 0 && shift local output_file="$(mktemp)" local status_file="$(mktemp)" local sid_file="$(mktemp)" local restarts=5 local prev_tmpsize=-1 while test $restarts -gt 0 ; do : > "$status_file" : > "$sid_file" setsid \ env \ output_file="$output_file" \ status_file="$status_file" \ sid_file="$sid_file" \ cmd="$cmd" \ CI_DIR="$CI_DIR" \ sh -c ' . "${CI_DIR}/common/test.sh" ps -o sid= > "$sid_file" ( ret=0 if ! eval "$cmd" 2>&1 ; then ret=1 fi echo "$ret" > "$status_file" ) | tee -a "$output_file" ' while test "$(stat -c "%s" "$status_file")" -eq 0 ; do prev_tmpsize=$tmpsize sleep $timeout tmpsize="$(stat -c "%s" "$output_file")" if test $tempsize -eq $prev_temsize ; then # no output, assuming either hang or exit break fi done restarts=$(( restarts - 1 )) if test "$(stat -c "%s" "$status_file")" -eq 0 ; then # Status file not updated, assuming hang # SID not known, this should not ever happen if test "$(stat -c "%s" "$sid_file")" -eq 0 ; then fail "$test_name" E "Shell did not run" break fi # Kill all processes which belong to one session: should get rid of test # processes as well as sh itself. pkill -KILL -s$(cat "$sid_file") if test $restarts -eq 0 ; then if test -z "$hang_ok" ; then fail "$test_name" E "Test hang up" fi else echo "Test ${test_name} hang up, restarting" eval "$restart_cmd" fi else local new_failed="$(cat "$status_file")" if test "$new_failed" != "0" ; then fail "$test_name" F "Test failed in run_test_wd" fi break fi done rm -f "$output_file" rm -f "$status_file" rm -f "$sid_file" } ended_successfully() { if test -f "${FAIL_SUMMARY_FILE}" ; then echo 'Test failed, complete summary:' cat "${FAIL_SUMMARY_FILE}" return 1 fi if ! test -f "${END_MARKER}" ; then echo 'ended_successfully called before end marker was touched' return 1 fi return 0 } end_tests() { touch "${END_MARKER}" ended_successfully }