mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-06 08:55:34 +00:00
452 lines
14 KiB
Bash
Executable file
452 lines
14 KiB
Bash
Executable file
# shellcheck shell=bash
|
|
|
|
function can_run_wayland() {
|
|
local MUTTER_VERSION
|
|
MUTTER_VERSION=$(mutter --version | head -1 | cut -f2 -d' ' | cut -f1 -d'.')
|
|
if (( MUTTER_VERSION < 40 )); then
|
|
return 1
|
|
else
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
function _generate_kmpjson() {
|
|
local TESTDIR
|
|
TESTDIR="$1"
|
|
pushd "${TESTDIR}" > /dev/null || exit
|
|
KMPFILE="${TESTDIR}/kmp.json"
|
|
cat <<-EOF > "${KMPFILE}"
|
|
{
|
|
"system": {
|
|
"keymanDeveloperVersion": "10.0.1099.0",
|
|
"fileVersion": "7.0"
|
|
},
|
|
"info": {
|
|
"name": {
|
|
"description": "Test Keyboards"
|
|
},
|
|
"version": {
|
|
"description": "0.0"
|
|
}
|
|
},
|
|
"files": [
|
|
{
|
|
"name": "kmp.json",
|
|
"description": "Package information (JSON)"
|
|
}
|
|
EOF
|
|
for f in k_*.kmx; do
|
|
keyboard=$(basename "${f}")
|
|
keyboard="${keyboard%.*}"
|
|
echo " ," >> "${KMPFILE}"
|
|
cat <<-EOF >> "${KMPFILE}"
|
|
{
|
|
"name": "${keyboard}",
|
|
"description": "${keyboard}"
|
|
}
|
|
EOF
|
|
done
|
|
cat <<-EOF >> "${KMPFILE}"
|
|
],
|
|
"keyboards": [
|
|
EOF
|
|
FIRST=true
|
|
for f in k_*.kmx; do
|
|
keyboard=$(basename "${f}")
|
|
keyboard="${keyboard%.*}"
|
|
if ${FIRST}; then
|
|
FIRST=false
|
|
else
|
|
echo " ," >> "${KMPFILE}"
|
|
fi
|
|
cat <<-EOF >> "${KMPFILE}"
|
|
{
|
|
"name": "${keyboard}",
|
|
"id": "${keyboard}",
|
|
"version": "0.0",
|
|
"languages": [
|
|
{
|
|
"name": "Undetermined",
|
|
"id": "und"
|
|
}
|
|
]
|
|
}
|
|
EOF
|
|
done
|
|
echo " ]" >> "${KMPFILE}"
|
|
echo "}" >> "${KMPFILE}"
|
|
popd > /dev/null || exit
|
|
}
|
|
|
|
function _link_test_keyboards() {
|
|
KMX_TEST_DIR=$1
|
|
TESTDIR=$2
|
|
TESTBASEDIR=$3
|
|
|
|
if [[ $(find "${KMX_TEST_DIR}/" -name k_\*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then
|
|
mkdir -p "$(realpath --canonicalize-missing "${TESTBASEDIR}")"
|
|
rm -f "${TESTDIR}"
|
|
ln -sf "$(realpath "${KMX_TEST_DIR}")" "${TESTDIR}"
|
|
else
|
|
echo "Can't find test kmx files in ${KMX_TEST_DIR}"
|
|
exit 3
|
|
fi
|
|
}
|
|
|
|
function _setup_init() {
|
|
local ENV_FILE CLEANUP_FILE PID_FILE DISPLAY_SERVER
|
|
ENV_FILE=$1
|
|
CLEANUP_FILE=$2
|
|
PID_FILE=$3
|
|
DISPLAY_SERVER=$4
|
|
|
|
if [[ -z "${TOP_SRCDIR:-}" ]]; then
|
|
TOP_SRCDIR=${G_TEST_SRCDIR:-$(realpath "$(dirname "$0")/..")}/..
|
|
fi
|
|
if [[ -z "${TOP_BINDIR:-}" ]]; then
|
|
TOP_BINDIR=${G_TEST_BUILDDIR:-$(realpath "$(dirname "$0/..")")}/..
|
|
fi
|
|
|
|
echo > "${ENV_FILE}"
|
|
|
|
if [[ -f "${CLEANUP_FILE}" ]]; then
|
|
# kill previous instances
|
|
"$(dirname "$0")"/teardown-tests.sh "${CLEANUP_FILE}" "${DISPLAY_SERVER}" || true
|
|
fi
|
|
|
|
echo > "${CLEANUP_FILE}"
|
|
echo > "${PID_FILE}"
|
|
TEMP_DATA_DIR=$(mktemp --directory)
|
|
echo "rm -rf \"${TEMP_DATA_DIR}\" || true # TEMP_DATA_DIR" >> "${CLEANUP_FILE}"
|
|
|
|
COMMON_ARCH_DIR=
|
|
[[ -d "${TOP_SRCDIR}"/../../core/build/arch ]] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../../core/build/arch
|
|
|
|
if [[ -d "${COMMON_ARCH_DIR}"/release ]]; then
|
|
COMMON_ARCH_DIR=${COMMON_ARCH_DIR}/release
|
|
elif [[ -d "${COMMON_ARCH_DIR}"/debug ]]; then
|
|
COMMON_ARCH_DIR=${COMMON_ARCH_DIR}/debug
|
|
else
|
|
echo "Can't find neither ${COMMON_ARCH_DIR}/release nor ${COMMON_ARCH_DIR}/debug"
|
|
exit 2
|
|
fi
|
|
|
|
export LD_LIBRARY_PATH=${COMMON_ARCH_DIR}/src:${LD_LIBRARY_PATH-}
|
|
echo "export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" >> "${ENV_FILE}"
|
|
}
|
|
|
|
function _setup_dbus_session() {
|
|
local ENV_FILE CLEANUP_FILE
|
|
ENV_FILE="$1"
|
|
CLEANUP_FILE="$2"
|
|
|
|
if [[ -z "${DOCKER_RUNNING:-}" ]] && [[ -z "${TEAMCITY_GIT_PATH:-}" ]] && ! pgrep -f jetbrains.buildServer.agent.AgentMain > /dev/null; then
|
|
return
|
|
fi
|
|
|
|
if [[ ! -d "/run/user/${UID:-$(id -u)}" ]]; then
|
|
# /run/user/$UID usually gets created by the session, but since we
|
|
# don't start the regular UI we don't have a session. Therefore we
|
|
# call the setupRuntimeDir.sh script to create the directory. The
|
|
# script should contain the following commands:
|
|
# mkdir -p "/run/user/${SUDO_UID:-$(id -u)}"
|
|
# chmod 0700 "/run/user/${SUDO_UID:-$(id -u)}"
|
|
# chown "${SUDO_USER:-$(whoami)}" "/run/user/${SUDO_UID:-$(id -u)}"
|
|
if [[ -f "/usr/local/bin/setupRuntimeDir.sh" ]]; then
|
|
echo "# Creating /run/user/${UID:-$(id -u)}..."
|
|
sudo /usr/local/bin/setupRuntimeDir.sh
|
|
else
|
|
echo "# WARNING: /run/user/${UID:-$(id -u)} is missing without having /usr/local/bin/setupRuntimeDir.sh, tests will likely fail"
|
|
fi
|
|
fi
|
|
|
|
if [[ -z "${XDG_RUNTIME_DIR:-}" ]]; then
|
|
export XDG_RUNTIME_DIR=/run/user/${UID:-$(id -u)}
|
|
echo "export XDG_RUNTIME_DIR=/run/user/${UID:-$(id -u)}" >> "${ENV_FILE}"
|
|
fi
|
|
if [[ ! -d "${XDG_RUNTIME_DIR}" ]]; then
|
|
echo "${XDG_RUNTIME_DIR} is missing, please create it"
|
|
exit 1
|
|
fi
|
|
|
|
export NO_AT_BRIDGE=1
|
|
echo "export NO_AT_BRIDGE=1" >> "${ENV_FILE}"
|
|
|
|
if pgrep -u "${USER:-$(whoami)}" dbus-daemon > /dev/null; then
|
|
# dbus-daemon is already running, skipping setup
|
|
return
|
|
fi
|
|
|
|
echo "# Starting dbus session..."
|
|
dbus-launch --auto-syntax >> "${ENV_FILE}"
|
|
PID=$(pidof dbus-daemon)
|
|
echo "kill -9 ${PID} || true # dbus-daemon" >> "${CLEANUP_FILE}"
|
|
}
|
|
|
|
function _setup_test_dbus_server() {
|
|
local ENV_FILE CLEANUP_FILE
|
|
ENV_FILE=$1
|
|
CLEANUP_FILE=$2
|
|
|
|
# Start test dbus server. This will create `/tmp/km-test-server.env`.
|
|
"${TOP_BINDIR}/tests/dbus-test-server/km-dbus-test-server" &> /tmp/km-test-server.log &
|
|
sleep 1
|
|
|
|
cat /tmp/km-test-server.env >> "${ENV_FILE}"
|
|
cat /tmp/km-test-server.env >> "${CLEANUP_FILE}"
|
|
echo "${TOP_BINDIR}/tests/dbus-test-server/stop-test-server" >> "${CLEANUP_FILE}"
|
|
|
|
# shellcheck disable=SC1091
|
|
source /tmp/km-test-server.env
|
|
# shellcheck disable=SC2154
|
|
echo "# DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS}"
|
|
}
|
|
|
|
function _setup_display_server() {
|
|
local DISPLAY_SERVER ENV_FILE CLEANUP_FILE PID_FILE PID DISP_XVFB DISP_XEPHYR
|
|
ENV_FILE=$1
|
|
CLEANUP_FILE=$2
|
|
PID_FILE=$3
|
|
DISPLAY_SERVER=$4
|
|
|
|
if [[ "${DISPLAY_SERVER}" == "--wayland" ]]; then
|
|
if ! can_run_wayland; then
|
|
# support for --headless got added in mutter 40.x
|
|
echo "ERROR: mutter doesn't support running headless. Can't run Wayland tests."
|
|
exit 7
|
|
fi
|
|
echo "Running on Wayland:"
|
|
echo "Starting mutter..."
|
|
TMPFILE=$(mktemp)
|
|
# mutter-Message: 18:56:15.422: Using Wayland display name 'wayland-1'
|
|
mutter --wayland --headless --no-x11 --virtual-monitor 1024x768 &> "${TMPFILE}" &
|
|
PID=$!
|
|
echo "kill -9 ${PID} &> /dev/null || true # mutter" >> "${CLEANUP_FILE}"
|
|
echo "${PID} mutter" >> "${PID_FILE}"
|
|
sleep 1s
|
|
WAYLAND_DISPLAY=$(grep "Using Wayland display" "${TMPFILE}" | cut -d"'" -f2)
|
|
export WAYLAND_DISPLAY
|
|
rm "${TMPFILE}"
|
|
echo "export WAYLAND_DISPLAY=\"${WAYLAND_DISPLAY}\"" >> "${ENV_FILE}"
|
|
else
|
|
echo "Running on X11:"
|
|
while true; do
|
|
echo "Starting Xvfb..."
|
|
DISP_XVFB=${RANDOM}
|
|
Xvfb -screen 0 1024x768x24 ":${DISP_XVFB}" &> /dev/null &
|
|
PID=$!
|
|
sleep 1
|
|
if ps --no-headers --pid="${PID}" > /dev/null; then
|
|
break
|
|
fi
|
|
done
|
|
echo "kill -9 ${PID} &> /dev/null || true # Xvfb" >> "${CLEANUP_FILE}"
|
|
echo "${PID} Xvfb" >> "${PID_FILE}"
|
|
while true; do
|
|
echo "Starting Xephyr..."
|
|
DISP_XEPHYR=${RANDOM}
|
|
DISPLAY=:${DISP_XVFB} Xephyr ":${DISP_XEPHYR}" -screen 1024x768 &> /dev/null &
|
|
PID=$!
|
|
sleep 1
|
|
if ps --no-headers --pid="${PID}" > /dev/null; then
|
|
break
|
|
fi
|
|
done
|
|
echo "kill -9 ${PID} &> /dev/null || true # Xephyr" >> "${CLEANUP_FILE}"
|
|
echo "${PID} Xephyr" >> "${PID_FILE}"
|
|
echo "Starting metacity"
|
|
metacity --display=":${DISP_XEPHYR}" &> /dev/null &
|
|
PID=$!
|
|
echo "kill -9 ${PID} &> /dev/null || true # metacity" >> "${CLEANUP_FILE}"
|
|
echo "${PID} metacity" >> "${PID_FILE}"
|
|
|
|
export DISPLAY=:${DISP_XEPHYR}
|
|
echo "export DISPLAY=\"${DISPLAY}\"" >> "${ENV_FILE}"
|
|
fi
|
|
}
|
|
|
|
function _setup_schema_and_gsettings() {
|
|
local ENV_FILE
|
|
ENV_FILE=$1
|
|
|
|
# Install schema to temporary directory. This removes the build dependency on the keyman package.
|
|
SCHEMA_DIR=${TEMP_DATA_DIR}/glib-2.0/schemas
|
|
export XDG_DATA_DIRS=${TEMP_DATA_DIR}:${XDG_DATA_DIRS-}
|
|
echo "export XDG_DATA_DIRS=${XDG_DATA_DIRS}" >> "${ENV_FILE}"
|
|
|
|
export GSETTINGS_SCHEMA_DIR=${SCHEMA_DIR}
|
|
echo "export GSETTINGS_SCHEMA_DIR=\"${SCHEMA_DIR}\"" >> "${ENV_FILE}"
|
|
|
|
mkdir -p "${SCHEMA_DIR}"
|
|
cp "${TOP_SRCDIR}"/../keyman-config/resources/com.keyman.gschema.xml "${SCHEMA_DIR}"/
|
|
glib-compile-schemas "${SCHEMA_DIR}"
|
|
|
|
# Ubuntu 18.04 Bionic doesn't have ibus-memconf, and glib is not compiled with the keyfile
|
|
# backend enabled, so we just use the default backend. Otherwise we use the keyfile
|
|
# store which interferes less when running on a dev machine.
|
|
if [[ -f /usr/libexec/ibus-memconf ]]; then
|
|
export GSETTINGS_BACKEND=keyfile
|
|
echo "export GSETTINGS_BACKEND=\"${GSETTINGS_BACKEND}\"" >> "${ENV_FILE}"
|
|
IBUS_CONFIG=--config=/usr/libexec/ibus-memconf
|
|
fi
|
|
}
|
|
|
|
function _setup_ibus() {
|
|
local ENV_FILE CLEANUP_FILE PID_FILE PID STANDALONE
|
|
ENV_FILE=$1
|
|
CLEANUP_FILE=$2
|
|
PID_FILE=$3
|
|
STANDALONE=${4:-}
|
|
|
|
echo "Starting ibus-daemon..."
|
|
#shellcheck disable=SC2086
|
|
ibus-daemon ${ARG_VERBOSE-} --replace --daemonize --panel=disable --address=unix:abstract="${TEMP_DATA_DIR}/test-ibus" ${IBUS_CONFIG-} &> /tmp/ibus-daemon.log
|
|
|
|
PID=$(pgrep -f "${TEMP_DATA_DIR}/test-ibus")
|
|
if [[ "${STANDALONE}" == "--standalone" ]] && [[ "${DOCKER_RUNNING:-false}" != "true" ]] && [[ -z "${TEAMCITY_GIT_PATH:-}" ]]; then
|
|
# manual test run
|
|
echo "if kill -9 ${PID} &> /dev/null; then ibus restart || ibus start -d; fi # ibus-daemon" >> "${CLEANUP_FILE}"
|
|
else
|
|
# test run as part of the build
|
|
echo "kill -9 ${PID} &> /dev/null || true # ibus-daemon" >> "${CLEANUP_FILE}"
|
|
fi
|
|
echo "${PID} ibus-daemon" >> "${PID_FILE}"
|
|
sleep 1s
|
|
|
|
IBUS_ADDRESS=$(ibus address)
|
|
export IBUS_ADDRESS
|
|
|
|
echo "export IBUS_ADDRESS=\"${IBUS_ADDRESS}\"" >> "${ENV_FILE}"
|
|
|
|
echo "Starting ibus-engine-keyman..."
|
|
#shellcheck disable=SC2086
|
|
"${TOP_BINDIR}/src/ibus-engine-keyman" --testing ${ARG_VERBOSE-} &> /tmp/ibus-engine-keyman.log &
|
|
PID=$!
|
|
echo "kill -9 ${PID} &> /dev/null || true # ibus-engine-keyman" >> "${CLEANUP_FILE}"
|
|
echo "${PID} ibus-engine-keyman" >> "${PID_FILE}"
|
|
sleep 1s
|
|
}
|
|
|
|
function setup() {
|
|
local DISPLAY_SERVER ENV_FILE CLEANUP_FILE PID_FILE TESTBASEDIR TESTDIR STANDALONE
|
|
DISPLAY_SERVER=$1
|
|
ENV_FILE=$2
|
|
CLEANUP_FILE=$3
|
|
PID_FILE=$4
|
|
STANDALONE=${5:-}
|
|
|
|
_setup_init "${ENV_FILE}" "${CLEANUP_FILE}" "${PID_FILE}" "${DISPLAY_SERVER}"
|
|
|
|
TESTBASEDIR=${XDG_DATA_HOME:-${HOME}/.local/share}/keyman
|
|
TESTDIR=${TESTBASEDIR}/test_kmx
|
|
|
|
_link_test_keyboards "${TOP_SRCDIR}/../../common/test/keyboards/baseline" "${TESTDIR}" "${TESTBASEDIR}"
|
|
|
|
_generate_kmpjson "${TESTDIR}"
|
|
|
|
_setup_dbus_session "${ENV_FILE}" "${CLEANUP_FILE}"
|
|
_setup_test_dbus_server "${ENV_FILE}" "${CLEANUP_FILE}"
|
|
_setup_display_server "${ENV_FILE}" "${CLEANUP_FILE}" "${PID_FILE}" "${DISPLAY_SERVER}"
|
|
_setup_schema_and_gsettings "${ENV_FILE}"
|
|
_setup_ibus "${ENV_FILE}" "${CLEANUP_FILE}" "${PID_FILE}" "${STANDALONE}"
|
|
}
|
|
|
|
function setup_display_server_only() {
|
|
local DISPLAY_SERVER ENV_FILE CLEANUP_FILE PID_FILE TESTBASEDIR TESTDIR
|
|
DISPLAY_SERVER=$1
|
|
ENV_FILE=$2
|
|
CLEANUP_FILE=$3
|
|
PID_FILE=$4
|
|
|
|
_setup_init "${ENV_FILE}" "${CLEANUP_FILE}" "${PID_FILE}" "${DISPLAY_SERVER}"
|
|
_setup_display_server "${ENV_FILE}" "${CLEANUP_FILE}" "${PID_FILE}" "${DISPLAY_SERVER}"
|
|
_setup_schema_and_gsettings "${ENV_FILE}"
|
|
}
|
|
|
|
function cleanup() {
|
|
local CLEANUP_FILE DISPLAY_SERVER
|
|
CLEANUP_FILE=$1
|
|
DISPLAY_SERVER=$2
|
|
|
|
if [[ -f "${CLEANUP_FILE}" ]]; then
|
|
echo
|
|
echo "# Shutting down processes..."
|
|
bash "${CLEANUP_FILE}" # &> /dev/null
|
|
rm "${CLEANUP_FILE}"
|
|
echo "# Finished shutdown of processes."
|
|
fi
|
|
|
|
if [[ "${DOCKER_RUNNING:-false}" == "true" ]]; then
|
|
echo "# Copying log files..."
|
|
# Note: build/tmp is build/docker-linux/<distro>/tmp on the host!
|
|
BUILD_TMP="$(dirname "$0")/../../../build/tmp"
|
|
mkdir -p "${BUILD_TMP}"
|
|
[[ -f /tmp/ibus-engine-keyman.log ]] && mv /tmp/ibus-engine-keyman.log "${BUILD_TMP}/ibus-engine-keyman${DISPLAY_SERVER}.log"
|
|
[[ -f /tmp/ibus-daemon.log ]] && mv /tmp/ibus-daemon.log "${BUILD_TMP}/ibus-daemon${DISPLAY_SERVER}.log"
|
|
[[ -f /tmp/km-test-server.log ]] && mv /tmp/km-test-server.log "${BUILD_TMP}/km-test-server${DISPLAY_SERVER}.log"
|
|
echo "# Finished copying log files"
|
|
fi
|
|
|
|
if [[ -z "${DOCKER_RUNNING:-}" ]] && [[ -z "${TEAMCITY_GIT_PATH:-}" ]] && ! pgrep -f jetbrains.buildServer.agent.AgentMain > /dev/null; then
|
|
# Not running in Docker or TeamCity:
|
|
# Killing the ibus-daemon that we started for testing might have caused
|
|
# some other ibus processes that belong to the real ibus daemon to
|
|
# be killed as well, leaving us with no way to type.
|
|
# So we kill the remaining lonely ibus-daemon and start ibus again.
|
|
if [[ ! "$(ibus engine &> /dev/null)" ]]; then
|
|
echo "# Stopping and starting ibus-daemon"
|
|
ibus exit &> /dev/null || kill -9 $(pgrep -u "${USER:-$(whoami)}" ibus-daemon) &> /dev/null || true
|
|
ibus start -d
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function exit_on_package_build() {
|
|
if [[ -v KEYMAN_PKG_BUILD ]]; then
|
|
# Skip setup during package builds - can't run headless and we won't
|
|
# run the other tests anyway
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
function _get_missing_processes() {
|
|
local PID_FILE MISSING_PROCS PID LINE
|
|
PID_FILE=$1
|
|
MISSING_PROCS=""
|
|
|
|
while read -r LINE; do
|
|
if [[ -z "${LINE}" ]]; then
|
|
continue
|
|
fi
|
|
PID=$(echo "${LINE}" | cut -d' ' -f1)
|
|
if ! ps --no-headers --pid="${PID}" > /dev/null; then
|
|
MISSING_PROCS="${MISSING_PROCS} $(echo "${LINE}" | cut -d' ' -f2)"
|
|
break
|
|
fi
|
|
done < "${PID_FILE}"
|
|
}
|
|
|
|
function check_processes_running() {
|
|
local DISPLAY_SERVER ENV_FILE CLEANUP_FILE PID_FILE MISSING_PROCS TEST_NAME
|
|
DISPLAY_SERVER=$1
|
|
ENV_FILE=$2
|
|
CLEANUP_FILE=$3
|
|
PID_FILE=$4
|
|
TEST_NAME=$5
|
|
MISSING_PROCS=$(_get_missing_processes "${PID_FILE}")
|
|
|
|
if [[ "${MISSING_PROCS}" != "" ]]; then
|
|
echo "# Some background processes no longer running. Restarting..."
|
|
{ echo "Some background processes no longer running (running ${TEST_NAME}):" ; \
|
|
echo "${MISSING_PROCS}" ; \
|
|
echo "Restarting..." ; } >> /tmp/debug.output
|
|
mv /tmp/ibus-engine-keyman.log{,"-${TEST_NAME}-$(date -Iseconds)"}
|
|
cleanup "${CLEANUP_FILE}" "${DISPLAY_SERVER}" &> /dev/null
|
|
setup "${DISPLAY_SERVER}" "${ENV_FILE}" "${CLEANUP_FILE}" "${PID_FILE}" &> /dev/null
|
|
fi
|
|
|
|
if [[ "$(_get_missing_processes "$PID_FILE")" != "" ]]; then
|
|
echo "# WARNING: Expected background processes are still missing after restart: ${MISSING_PROCS}"
|
|
echo "# Maybe an old process is still running?"
|
|
fi
|
|
}
|