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
2019-06-13 06:35:32 +02:00
-m: Use --screen off
2017-08-11 01:00:27 +02:00
-h: show this help
EOF
exit " $1 "
}
2017-08-14 16:15:56 +02:00
fail_on_warning =
2019-06-13 06:35:32 +02:00
manual_screens =
2017-08-14 16:15:56 +02:00
verbose = ${ VERBOSE :- 0 }
2019-06-13 06:35:32 +02:00
while getopts vWmh 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 ; ;
2019-06-13 06:35:32 +02:00
m) manual_screens = " --screen off" ; ;
2017-08-11 01:00:27 +02:00
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
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
2019-09-13 16:02:22 +02:00
if ! $AWESOME --version; then
echo " $AWESOME cannot be run. " >& 2
2016-05-03 12:08:00 +02:00
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
2019-10-17 04:24:32 +02:00
# Enable partial maximization tests if wmctrl is found.
if command -v wmctrl >/dev/null 2>& 1; then
export HAS_WMCTRL = 1
fi
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
2019-06-13 06:35:32 +02:00
awesome_options = ( $AWESOME_OPTIONS $manual_screens --search lib --search " $this_dir " )
awesome_options += ( --screen off)
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
}
2017-11-24 05:26:54 +01:00
# Wait for DISPLAY to be available, i.e. the X server is running.
wait_until_success "X resources are ready" " DISPLAY=' $D ' xrdb -q >/dev/null 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 "
2019-06-13 06:35:32 +02:00
2018-06-12 19:16:44 +02:00
# Kill awesome after $TEST_TIMEOUT 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 " \
2019-09-13 17:55:27 +02:00
XDG_CONFIG_HOME = " $build_dir " \
2018-06-12 19:16:44 +02:00
timeout " $TEST_TIMEOUT " " $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.
2018-06-12 19:16:44 +02:00
TEST_TIMEOUT = ${ TEST_TIMEOUT :- 30 }
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
2019-01-03 13:43:54 +01:00
2017-11-18 01:52:48 +01:00
# Make the filename absolute if it is not.
2019-01-03 13:43:54 +01:00
if [ " ${ f #/ } " = " $f " ] ; then
f = " $PWD / $f "
2017-11-18 01:52:48 +01:00
fi
2015-07-18 12:33:24 +02:00
2017-11-18 01:52:48 +01:00
# Execute the test file in awesome.
2018-08-06 16:03:17 +02:00
DISPLAY = $D " $AWESOME_CLIENT " 2>& 1 " dofile(' $f ') " || echo "Error: awesome-client failed" >> " $awesome_log "
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) ; ;
2018-06-12 19:16:44 +02:00
124) echo " Awesome was killed due to timeout after $TEST_TIMEOUT seconds " ; ;
2016-09-25 06:00:15 +02:00
*) 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-21 14:51:25 +02:00
pattern = '.*[Ee]rror.*|.*assertion failed.*|^Step .* failed:|^.{19} E: awesome: .*|.*luaA_panic.*'
2017-08-11 01:00:27 +02:00
if [ [ $fail_on_warning ] ] ; then
pattern += '|^.{19} W: awesome:.*'
fi
error = " $( grep --color -o --binary-files= text -E " $pattern " " $awesome_log " || true ) "
2018-06-26 16:43:20 +02:00
# Filter out false positive errors:
error = " $( echo " $error " | grep -vE ".{19} W: awesome: (Can't read color .* from GTK)" || true ) "
2017-08-11 01:00:27 +02:00
if [ [ $fail_on_warning ] ] ; then
# Filter out ignored warnings.
2019-06-24 23:17:51 +02:00
error = " $( echo " $error " | grep -vE ".{19} W: awesome: (Removing last screen through fake_remove|a_glib_poll|Cannot reliably detect EOF|beautiful: can't get colorscheme from xrdb|Can't read color .* from GTK+3 theme|A notification|Notification)" || true ) "
2017-08-11 01:00:27 +02:00
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