aboutsummaryrefslogtreecommitdiff
path: root/.vim/contrib/run-tests-watch
diff options
context:
space:
mode:
Diffstat (limited to '.vim/contrib/run-tests-watch')
-rwxr-xr-x.vim/contrib/run-tests-watch127
1 files changed, 127 insertions, 0 deletions
diff --git a/.vim/contrib/run-tests-watch b/.vim/contrib/run-tests-watch
new file mode 100755
index 0000000..11edbdf
--- /dev/null
+++ b/.vim/contrib/run-tests-watch
@@ -0,0 +1,127 @@
+#!/bin/sh -x
+#
+# Wrapper around inotifywait to run tests on file changes.
+# If a test file changes, only this file is run (first), while the whole test
+# suite is run afterwards (and initially).
+#
+# The recommended way to run it is via `make testwatch`, or `make testwatchx`
+# (to exit on first failure).
+#
+# # Internal documentation:
+# The default run command is "make %s" (where %s gets replaced with the test
+# file(s)), and can be given as first argument.
+#
+# You can specify VADER_OPTIONS=-x to exit on the first test failure:
+# VADER_OPTIONS=-x contrib/run-tests-watch
+# or use the following:
+# contrib/run-tests-watch 'make %s VADER_OPTIONS=-x'
+#
+# VADER_ARGS gets used to focus on a specific test file initially, until
+# another test file gets changed.
+
+watch="autoload plugin tests"
+echo "Watching: $watch"
+
+if [ -n "$1" ]; then
+ cmdpattern="$1"
+else
+ cmdpattern="make %s VADER_OPTIONS='$VADER_OPTIONS'"
+fi
+
+title() {
+ printf '\e]1;%s\a' "$*"
+ printf '\e]2;%s\a' "$*"
+}
+
+status_file=$(mktemp)
+handle_cmd_result() {
+ if [ "$1" = 0 ]; then
+ last_test_succeeded=1
+ title "✔ $2"
+ if [ "${2#*${alltestsfile}*}" != "$2" ]; then
+ alltests_succeeded=1
+ fi
+ else
+ last_test_succeeded=0
+ title "✘ $2"
+ if [ "${2#*${alltestsfile}*}" != "$2" ]; then
+ alltests_succeeded=0
+ fi
+ fi
+ echo "$last_test_succeeded $alltests_succeeded" > "$status_file"
+}
+
+# Recursively kill childs - required to get out of a running pdb.
+kill_with_childs() {
+ for p in $(pgrep -P "$1"); do
+ kill_with_childs "$p"
+ done
+ if kill -0 "$1" 2>/dev/null; then
+ kill "$1" || true
+ fi
+}
+
+alltestsfile='tests/all.vader'
+alltests_succeeded=0
+pid=
+changed_files=
+set -e
+last_changed_testsfile="${VADER_ARGS:-$alltestsfile}"
+
+while true; do
+ testfiles="$last_changed_testsfile"
+ if [ -n "$changed_files" ]; then
+ # There was a previous run
+ echo "================================================================="
+ echo "changed file: $changed_files"
+
+ read -r last_test_succeeded alltests_succeeded < "$status_file" || alltests_succeeded=0
+
+ if [ "${changed_files#tests/}" != "$changed_files" ] \
+ && [ "${changed_files#tests/include/}" = "$changed_files" ]; then
+ # A test file was changed (but not an include file).
+ last_changed_testsfile="$changed_files"
+ testfiles="$last_changed_testsfile"
+
+ # Run full tests afterwards (if not successful before).
+ if [ "$testfiles" != "$alltestsfile" ] && [ "$alltests_succeeded" = 0 ]; then
+ testfiles="$testfiles $alltestsfile"
+ fi
+
+ elif [ "$last_test_succeeded" = 1 ]; then
+ # Run all tests.
+ alltests_succeeded=0
+ testfiles="$alltestsfile"
+
+ if [ "${VADER_OPTIONS#*-x*}" != "$VADER_OPTIONS" ]; then
+ # Run tests matching the changed file first, e.g. tests/config.vader for
+ # autoload/neomake/config.vim.
+ test_file_for_changed_file="tests/${changed_files#autoload/neomake/}"
+ test_file_for_changed_file="${test_file_for_changed_file%.vim}.vader"
+ declare -p test_file_for_changed_file
+ if [ -f "$test_file_for_changed_file" ]; then
+ testfiles="$test_file_for_changed_file $testfiles"
+ fi
+ fi
+ fi
+
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
+ echo 'Killing previous run…'
+ kill_with_childs "$pid"
+ fi
+ fi
+
+ # shellcheck disable=SC2059
+ cmd="$(printf "$cmdpattern" "$testfiles")"
+ echo "Running $cmd"
+ title "… $testfiles"
+ # shellcheck disable=SC2015
+ (set +e; eval "$cmd"; handle_cmd_result "$?" "$testfiles") </dev/tty &
+ pid=$!
+
+ sleep 1
+ # shellcheck disable=SC2086
+ changed_files="$(inotifywait -q -r -e close_write \
+ --exclude '/(__pycache__/|\.)|.*\@neomake_.*' \
+ --format '%w%f' $watch)"
+done