2016-12-25 03:08:35 +01:00
|
|
|
#!/usr/bin/env bash
|
2015-10-03 14:54:17 +02:00
|
|
|
#
|
|
|
|
# Test runner.
|
|
|
|
#
|
|
|
|
# This can also be used to start awesome from the build directory, e.g. for
|
|
|
|
# git-bisect:
|
|
|
|
# 1. Put the file into a subdirectory, which is ignored by git, e.g.
|
|
|
|
# `tmp/run.sh`.
|
|
|
|
# 2. Run it from the source root (after `make`):
|
|
|
|
# env TEST_PAUSE_ON_ERRORS=1 sh tmp/run.sh
|
|
|
|
# It should start Xephyr and launch awesome in it, using the default config.
|
2015-07-10 13:17:50 +02:00
|
|
|
|
|
|
|
set -e
|
2015-07-14 12:49:35 +02:00
|
|
|
|
2016-12-25 03:46:28 +01:00
|
|
|
export SHELL=/bin/sh
|
|
|
|
export HOME=/dev/null
|
|
|
|
|
2017-08-11 01:00:27 +02:00
|
|
|
# Parse options.
|
|
|
|
usage() {
|
|
|
|
cat >&2 <<EOF
|
2017-08-16 11:27:32 +02:00
|
|
|
Usage: $0 [OPTION]... [FILE]...
|
|
|
|
|
|
|
|
Options:
|
2017-08-14 16:15:56 +02:00
|
|
|
-v: verbose mode
|
2017-08-11 01:00:27 +02:00
|
|
|
-W: warnings become errors
|
|
|
|
-h: show this help
|
|
|
|
EOF
|
|
|
|
exit "$1"
|
|
|
|
}
|
2017-08-14 16:15:56 +02:00
|
|
|
fail_on_warning=
|
|
|
|
verbose=${VERBOSE:-0}
|
|
|
|
while getopts vWh opt; do
|
2017-08-11 01:00:27 +02:00
|
|
|
case $opt in
|
2017-08-14 16:15:56 +02:00
|
|
|
v) verbose=1 ;;
|
2017-08-11 01:00:27 +02:00
|
|
|
W) fail_on_warning=1 ;;
|
|
|
|
h) usage 0 ;;
|
|
|
|
*) usage 64 ;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
shift $((OPTIND-1))
|
|
|
|
|
2017-08-16 11:27:32 +02:00
|
|
|
if (( verbose )); then
|
2015-07-14 12:49:35 +02:00
|
|
|
set -x
|
|
|
|
fi
|
2015-07-10 13:17:50 +02:00
|
|
|
|
2016-07-17 22:08:01 +02:00
|
|
|
# Change to file's dir (POSIXly).
|
|
|
|
cd -P -- "$(dirname -- "$0")"
|
2017-01-03 14:29:10 +01:00
|
|
|
this_dir="$PWD"
|
|
|
|
source_dir="${this_dir%/*}"
|
2016-07-17 22:08:01 +02:00
|
|
|
|
2016-06-12 23:28:32 +02:00
|
|
|
# Either the build dir is passed in $CMAKE_BINARY_DIR or we guess based on $PWD
|
2016-05-08 18:34:39 +02:00
|
|
|
build_dir="$CMAKE_BINARY_DIR"
|
|
|
|
if [ -z "$build_dir" ]; then
|
2016-07-17 22:08:01 +02:00
|
|
|
if [ -d "$source_dir/build" ]; then
|
|
|
|
build_dir="$source_dir/build"
|
2016-06-12 23:28:32 +02:00
|
|
|
else
|
2016-07-17 22:08:01 +02:00
|
|
|
build_dir="$source_dir"
|
2016-06-12 23:28:32 +02:00
|
|
|
fi
|
2016-05-08 18:34:39 +02:00
|
|
|
fi
|
2017-05-13 23:28:45 +02:00
|
|
|
export build_dir
|
2016-05-08 18:34:39 +02:00
|
|
|
|
2015-07-10 13:17:50 +02:00
|
|
|
# Get test files: test*, or the ones provided as args (relative to tests/).
|
|
|
|
if [ $# != 0 ]; then
|
2016-12-25 03:08:35 +01:00
|
|
|
tests="$*"
|
2015-07-10 13:17:50 +02:00
|
|
|
else
|
2016-12-25 03:08:35 +01:00
|
|
|
tests="$this_dir/test*.lua"
|
2015-07-10 13:17:50 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Travis.
|
|
|
|
if [ "$CI" = true ]; then
|
|
|
|
HEADLESS=1
|
|
|
|
TEST_PAUSE_ON_ERRORS=0
|
|
|
|
else
|
2016-10-31 23:22:31 +01:00
|
|
|
HEADLESS=${HEADLESS-0}
|
2015-10-03 14:54:17 +02:00
|
|
|
TEST_PAUSE_ON_ERRORS=${TEST_PAUSE_ON_ERRORS-0}
|
2015-07-10 13:17:50 +02:00
|
|
|
fi
|
2015-10-03 14:54:17 +02:00
|
|
|
export TEST_PAUSE_ON_ERRORS # Used in tests/_runner.lua.
|
2015-07-10 13:17:50 +02:00
|
|
|
|
|
|
|
XEPHYR=Xephyr
|
|
|
|
XVFB=Xvfb
|
2016-05-08 18:34:39 +02:00
|
|
|
AWESOME=$build_dir/awesome
|
2016-05-03 12:08:00 +02:00
|
|
|
if ! [ -x "$AWESOME" ]; then
|
|
|
|
echo "$AWESOME is not executable." >&2
|
|
|
|
exit 1
|
|
|
|
fi
|
2016-05-08 18:34:39 +02:00
|
|
|
AWESOME_CLIENT="$source_dir/utils/awesome-client"
|
2015-07-10 13:17:50 +02:00
|
|
|
D=:5
|
2016-05-08 20:58:19 +02:00
|
|
|
SIZE="${TESTS_SCREEN_SIZE:-1024x768}"
|
2015-07-10 13:17:50 +02:00
|
|
|
|
2016-05-08 16:46:57 +02:00
|
|
|
# Set up some env vars
|
|
|
|
# Disable GDK's screen scaling support
|
|
|
|
export GDK_SCALE=1
|
|
|
|
# No idea what this does, but it silences a warning that GTK init might print
|
|
|
|
export NO_AT_BRIDGE=1
|
|
|
|
|
2015-07-10 13:17:50 +02:00
|
|
|
if [ $HEADLESS = 1 ]; then
|
2016-12-25 03:08:35 +01:00
|
|
|
"$XVFB" $D -noreset -screen 0 "${SIZE}x24" &
|
2015-07-18 10:44:16 +02:00
|
|
|
xserver_pid=$!
|
2015-07-10 13:17:50 +02:00
|
|
|
else
|
|
|
|
# export XEPHYR_PAUSE=1000
|
2016-12-25 03:08:35 +01:00
|
|
|
"$XEPHYR" $D -ac -name xephyr_$D -noreset -screen "$SIZE" &
|
2015-07-18 10:44:16 +02:00
|
|
|
xserver_pid=$!
|
2015-07-18 15:03:43 +02:00
|
|
|
# Toggles debugging mode, using XEPHYR_PAUSE.
|
|
|
|
# ( sleep 1; kill -USR1 $xserver_pid ) &
|
2015-07-10 13:17:50 +02:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Add test dir (for _runner.lua).
|
2017-07-09 14:17:35 +02:00
|
|
|
# shellcheck disable=SC2206
|
|
|
|
awesome_options=($AWESOME_OPTIONS --search lib --search "$this_dir")
|
2016-12-25 03:08:35 +01:00
|
|
|
export XDG_CONFIG_HOME="$build_dir"
|
2015-07-10 13:17:50 +02:00
|
|
|
|
2015-08-05 17:41:26 +02:00
|
|
|
# Cleanup on errors / aborting.
|
|
|
|
cleanup() {
|
2015-07-18 10:45:03 +02:00
|
|
|
for p in $awesome_pid $xserver_pid; do
|
2016-12-25 03:08:35 +01:00
|
|
|
kill -TERM "$p" 2>/dev/null || true
|
2017-08-13 11:57:59 +02:00
|
|
|
wait "$p"
|
2015-07-10 13:17:50 +02:00
|
|
|
done
|
2016-12-25 03:08:35 +01:00
|
|
|
rm -rf "$tmp_files" || true
|
2015-07-10 13:17:50 +02:00
|
|
|
}
|
2015-08-05 17:41:26 +02:00
|
|
|
trap "cleanup" 0 2 3 15
|
|
|
|
|
|
|
|
tmp_files=$(mktemp -d)
|
|
|
|
awesome_log=$tmp_files/_awesome_test.log
|
|
|
|
echo "awesome_log: $awesome_log"
|
2015-07-10 13:17:50 +02:00
|
|
|
|
2015-08-05 17:48:09 +02:00
|
|
|
wait_until_success() {
|
2017-08-16 11:27:32 +02:00
|
|
|
if (( verbose )); then set +x; fi
|
2016-05-31 23:48:50 +02:00
|
|
|
wait_count=60 # 60*0.05s => 3s.
|
2015-08-05 17:48:09 +02:00
|
|
|
while true; do
|
|
|
|
set +e
|
|
|
|
eval reply="\$($2)"
|
|
|
|
ret=$?
|
|
|
|
set -e
|
|
|
|
if [ $ret = 0 ]; then
|
|
|
|
break
|
|
|
|
fi
|
2016-12-25 03:08:35 +01:00
|
|
|
wait_count=$((wait_count - 1))
|
2016-05-31 23:48:50 +02:00
|
|
|
if [ "$wait_count" -lt 0 ]; then
|
2016-12-25 03:08:35 +01:00
|
|
|
echo "Error: failed to $1!" >&2
|
|
|
|
# shellcheck disable=SC2154
|
|
|
|
echo "Last reply: $reply." >&2
|
2015-08-05 17:48:09 +02:00
|
|
|
if [ -f "$awesome_log" ]; then
|
2016-12-25 03:08:35 +01:00
|
|
|
echo "Log:" >&2
|
|
|
|
cat "$awesome_log" >&2
|
2015-08-05 17:48:09 +02:00
|
|
|
fi
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
sleep 0.05
|
|
|
|
done
|
2017-08-16 11:27:32 +02:00
|
|
|
if (( verbose )); then set -x; fi
|
2015-08-05 17:48:09 +02:00
|
|
|
}
|
|
|
|
|
2015-07-21 13:09:07 +02:00
|
|
|
# Wait for DISPLAY to be available, and setup xrdb,
|
|
|
|
# for awesome's xresources backend / queries.
|
2016-03-04 01:41:43 +01:00
|
|
|
wait_until_success "setup xrdb" "printf 'Xft.dpi: 96
|
|
|
|
*.background: #002b36
|
|
|
|
*.foreground: #93a1a1
|
|
|
|
*.color0: #002b36
|
|
|
|
*.color1: #dc322f
|
|
|
|
*.color10: #859900
|
|
|
|
*.color11: #b58900
|
|
|
|
*.color12: #268bd2
|
|
|
|
*.color13: #6c71c4
|
|
|
|
*.color14: #2aa198
|
|
|
|
*.color15: #fdf6e3
|
|
|
|
*.color16: #cb4b16
|
|
|
|
*.color17: #d33682
|
|
|
|
*.color18: #073642
|
|
|
|
*.color19: #586e75
|
|
|
|
*.color2: #859900
|
|
|
|
*.color20: #839496
|
|
|
|
*.color21: #eee8d5
|
|
|
|
*.color3: #b58900
|
|
|
|
*.color4: #268bd2
|
|
|
|
*.color5: #6c71c4
|
|
|
|
*.color6: #2aa198
|
|
|
|
*.color7: #93a1a1
|
|
|
|
*.color8: #657b83
|
|
|
|
*.color9: #dc322f' | DISPLAY='$D' xrdb 2>&1"
|
2015-07-21 13:09:07 +02:00
|
|
|
|
2015-08-05 17:10:56 +02:00
|
|
|
# Use a separate D-Bus session; sets $DBUS_SESSION_BUS_PID.
|
2016-12-25 03:08:35 +01:00
|
|
|
eval "$(DISPLAY="$D" dbus-launch --sh-syntax --exit-with-session)"
|
2015-08-05 17:10:56 +02:00
|
|
|
|
2017-08-10 11:56:59 +02:00
|
|
|
RC_FILE=${AWESOME_RC_FILE:-${source_dir}/awesomerc.lua}
|
|
|
|
AWESOME_THEMES_PATH="${AWESOME_THEMES_PATH:-${source_dir}/themes}"
|
|
|
|
AWESOME_ICON_PATH="${AWESOME_ICON_PATH:-${source_dir}/icons}"
|
2017-01-05 01:06:49 +01:00
|
|
|
|
2017-07-09 22:29:51 +02:00
|
|
|
# Inject coverage runner via temporary RC file.
|
2017-01-05 01:06:49 +01:00
|
|
|
if [ -n "$DO_COVERAGE" ] && [ "$DO_COVERAGE" != 0 ]; then
|
2017-07-09 22:29:51 +02:00
|
|
|
# Handle old filename of config files (useful for git-bisect).
|
|
|
|
if [ -f "${RC_FILE}.in" ]; then
|
|
|
|
RC_FILE="${RC_FILE}.in"
|
|
|
|
fi
|
|
|
|
sed "1 s~^~require('luacov.runner')('$source_dir/.luacov'); \0~" \
|
|
|
|
"$RC_FILE" > "$tmp_files/awesomerc.lua"
|
|
|
|
RC_FILE=$tmp_files/awesomerc.lua
|
2015-08-05 17:44:00 +02:00
|
|
|
fi
|
|
|
|
|
2015-07-10 13:17:50 +02:00
|
|
|
# Start awesome.
|
|
|
|
start_awesome() {
|
2016-12-25 03:08:35 +01:00
|
|
|
cd "$build_dir"
|
2016-09-24 15:56:36 +02:00
|
|
|
# Kill awesome after $timeout_stale seconds (e.g. for errors during test setup).
|
2017-01-03 14:29:10 +01:00
|
|
|
# SOURCE_DIRECTORY is used by .luacov.
|
2017-08-10 11:56:59 +02:00
|
|
|
DISPLAY="$D" SOURCE_DIRECTORY="$source_dir" \
|
|
|
|
AWESOME_THEMES_PATH="$AWESOME_THEMES_PATH" \
|
|
|
|
AWESOME_ICON_PATH="$AWESOME_ICON_PATH" \
|
|
|
|
timeout "$timeout_stale" "$AWESOME" -c "$RC_FILE" "${awesome_options[@]}" > "$awesome_log" 2>&1 &
|
2015-07-18 10:44:16 +02:00
|
|
|
awesome_pid=$!
|
|
|
|
cd - >/dev/null
|
2015-07-14 12:49:35 +02:00
|
|
|
|
|
|
|
# Wait until the interface for awesome-client is ready (D-Bus interface).
|
2016-09-25 20:28:27 +02:00
|
|
|
# Do this with dbus-send so that we can specify a low --reply-timeout
|
2016-12-21 02:03:03 +01:00
|
|
|
wait_until_success "wait for awesome startup via awesome-client" "dbus-send --reply-timeout=100 --dest=org.awesomewm.awful --print-reply / org.awesomewm.awful.Remote.Eval 'string:return 1' 2>&1"
|
2015-07-10 13:17:50 +02:00
|
|
|
}
|
|
|
|
|
2017-07-09 14:17:35 +02:00
|
|
|
if command -v tput >/dev/null; then
|
|
|
|
color_red() { tput setaf 1; }
|
|
|
|
color_reset() { tput sgr0; }
|
|
|
|
else
|
|
|
|
color_red() { :; }
|
|
|
|
color_reset() { :; }
|
|
|
|
fi
|
|
|
|
|
|
|
|
count_tests=0
|
|
|
|
errors=()
|
2016-05-31 23:46:23 +02:00
|
|
|
# Seconds after when awesome gets killed.
|
2016-12-02 01:34:46 +01:00
|
|
|
timeout_stale=180 # FIXME This should be no more than 60s
|
2015-07-10 13:17:50 +02:00
|
|
|
|
|
|
|
for f in $tests; do
|
|
|
|
echo "== Running $f =="
|
2017-07-09 14:17:35 +02:00
|
|
|
(( ++count_tests ))
|
2015-07-18 12:33:24 +02:00
|
|
|
|
2015-10-03 14:54:17 +02:00
|
|
|
start_awesome
|
|
|
|
|
2016-12-25 03:08:35 +01:00
|
|
|
if [ ! -r "$f" ]; then
|
2016-12-26 19:09:26 +01:00
|
|
|
if [ -r "${f#tests/}" ]; then
|
|
|
|
f=${f#tests/}
|
|
|
|
else
|
|
|
|
echo "===> ERROR $f is not readable! <==="
|
2017-07-09 14:17:35 +02:00
|
|
|
errors+=("$f is not readable.")
|
2016-12-26 19:09:26 +01:00
|
|
|
continue
|
|
|
|
fi
|
2015-07-18 12:33:24 +02:00
|
|
|
fi
|
|
|
|
|
2015-07-10 13:17:50 +02:00
|
|
|
# Send the test file to awesome.
|
2016-12-25 03:08:35 +01:00
|
|
|
DISPLAY=$D "$AWESOME_CLIENT" 2>&1 < "$f"
|
2015-07-10 13:17:50 +02:00
|
|
|
|
|
|
|
# Tail the log and quit, when awesome quits.
|
2017-07-09 14:17:35 +02:00
|
|
|
# Use a single `grep`, otherwise `--line-buffered` would be required.
|
|
|
|
tail -n 100000 -s 0.1 -f --pid "$awesome_pid" "$awesome_log" \
|
|
|
|
| grep -vE '^(.{19} W: awesome: a_dbus_connect:[0-9]+: Could not connect to D-Bus system bus:|Test finished successfully\.$)' || true
|
2015-07-10 13:17:50 +02:00
|
|
|
|
2016-09-24 15:55:24 +02:00
|
|
|
set +e
|
|
|
|
wait $awesome_pid
|
|
|
|
code=$?
|
|
|
|
set -e
|
2016-09-25 06:00:15 +02:00
|
|
|
case $code in
|
|
|
|
0) ;;
|
|
|
|
124) echo "Awesome was killed due to timeout after $timeout_stale seconds" ;;
|
|
|
|
*) echo "Awesome exited with status code $code" ;;
|
|
|
|
esac
|
2016-09-24 15:55:24 +02:00
|
|
|
|
2017-07-09 14:17:35 +02:00
|
|
|
# Parse any error from the log.
|
2017-08-11 01:00:27 +02:00
|
|
|
pattern='.*[Ee]rror.*|.*assertion failed.*|^Step .* failed:'
|
|
|
|
if [[ $fail_on_warning ]]; then
|
|
|
|
pattern+='|^.{19} W: awesome:.*'
|
|
|
|
fi
|
|
|
|
error="$(grep --color -o --binary-files=text -E "$pattern" "$awesome_log" || true)"
|
|
|
|
if [[ $fail_on_warning ]]; then
|
|
|
|
# Filter out ignored warnings.
|
|
|
|
error="$(echo "$error" | grep -vE '.{19} W: awesome: (a_glib_poll|Cannot reliably detect EOF)' || true)"
|
|
|
|
fi
|
2017-07-09 14:17:35 +02:00
|
|
|
if [[ -n "$error" ]]; then
|
|
|
|
color_red
|
2016-12-26 19:08:26 +01:00
|
|
|
echo "===> ERROR running $f <==="
|
2017-07-09 14:17:35 +02:00
|
|
|
echo "$error"
|
|
|
|
color_reset
|
|
|
|
errors+=("$f: $error")
|
|
|
|
elif ! grep -q -E '^Test finished successfully\.$' "$awesome_log"; then
|
|
|
|
color_red
|
|
|
|
echo "===> ERROR running $f <==="
|
|
|
|
color_reset
|
|
|
|
errors+=("$f: test did not indicate success. See the output above.")
|
2015-07-10 13:17:50 +02:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
2017-07-09 14:17:35 +02:00
|
|
|
echo "$count_tests tests finished."
|
|
|
|
|
|
|
|
if (( "${#errors[@]}" )); then
|
2015-10-03 14:54:17 +02:00
|
|
|
if [ "$TEST_PAUSE_ON_ERRORS" = 1 ]; then
|
|
|
|
echo "Pausing... press Enter to continue."
|
2016-12-25 03:08:35 +01:00
|
|
|
read -r
|
2015-10-03 14:54:17 +02:00
|
|
|
fi
|
2017-07-09 14:17:35 +02:00
|
|
|
color_red
|
|
|
|
echo "There were ${#errors[@]} errors:"
|
|
|
|
for error in "${errors[@]}"; do
|
|
|
|
echo " - $error"
|
|
|
|
done
|
|
|
|
color_reset
|
2015-10-03 14:54:17 +02:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
exit 0
|
2015-12-12 17:34:16 +01:00
|
|
|
|
|
|
|
# vim: filetype=sh:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|