diff --git a/core/src/meson.build b/core/src/meson.build index cbf2f8c6da..254eefcad6 100644 --- a/core/src/meson.build +++ b/core/src/meson.build @@ -58,18 +58,7 @@ if compiler.get_id() == 'emscripten' links = [] endif -lib = library('kmnkbp0', - 'option.cpp', - 'keyboard.cpp', - 'state.cpp', - 'km_kbp_context_api.cpp', - 'km_kbp_keyboard_api.cpp', - 'km_kbp_options_api.cpp', - 'km_kbp_state_api.cpp', - 'km_kbp_debug_api.cpp', - 'km_kbp_processevent_api.cpp', - 'jsonpp.cpp', - 'mock/mock_processor.cpp', +kmxfiles = files( 'kmx/kmx_consts.cpp', 'kmx/kmx_processevent.cpp', 'kmx/kmx_actions.cpp', @@ -84,7 +73,30 @@ lib = library('kmnkbp0', 'kmx/kmx_options.cpp', 'kmx/kmx_processor.cpp', 'kmx/kmx_xstring.cpp', +) + +apifiles = files( + 'km_kbp_context_api.cpp', + 'km_kbp_keyboard_api.cpp', + 'km_kbp_options_api.cpp', + 'km_kbp_state_api.cpp', + 'km_kbp_debug_api.cpp', + 'km_kbp_processevent_api.cpp', +) + +corefiles = files( + 'option.cpp', + 'keyboard.cpp', + 'state.cpp', + 'jsonpp.cpp', 'utfcodec.cpp', +) + +lib = library('kmnkbp0', + apifiles, + corefiles, + kmxfiles, + 'mock/mock_processor.cpp', version_res, cpp_args: defns + warns + flags, link_args: links, diff --git a/core/tests/unit/kmx/meson.build b/core/tests/unit/kmx/meson.build index 63188c764a..014983a9af 100644 --- a/core/tests/unit/kmx/meson.build +++ b/core/tests/unit/kmx/meson.build @@ -25,9 +25,13 @@ else test_path = meson.current_build_dir() endif +coretestfiles = files( + 'kmx_test_source.cpp', +) + kmx = executable('kmx', 'kmx.cpp', - 'kmx_test_source.cpp', + coretestfiles, cpp_args: defns + warns, include_directories: [inc, libsrc], link_args: links + tests_flags, diff --git a/docs/linux/keyman-config.md b/docs/linux/keyman-config.md index c12db30c94..f050fd96ad 100644 --- a/docs/linux/keyman-config.md +++ b/docs/linux/keyman-config.md @@ -13,7 +13,8 @@ sudo apt install python3-lxml python3-magic python3-numpy python3-qrcode python3 python3-setuptools python3-pip python3-dbus ibus libglib2.0-bin liblocale-gettext-perl ``` -Either `python3-raven` or `python3-sentry-sdk` (>= 1.4) is required as well. On Ubuntu 22.04 and later run: +Either `python3-raven` or `python3-sentry-sdk` (>= 1.4) is required as well. +On Ubuntu 22.04 and later run: ```bash sudo apt install python3-sentry-sdk @@ -34,8 +35,8 @@ or install it with pip: pip3 install sentry-sdk ``` -Run the script `./createkeymandirs.sh` to create the directories for these programs to -install the packages to. +Run the script `./createkeymandirs.sh` to create the directories for these +programs to install the packages to. Also copy and compile the GSettings schema: @@ -65,7 +66,8 @@ To uninstall you can run `sudo make uninstall`. `./km-config` -This displays a configuration panel that shows the currently installed Keyman keyboard packages and can download and install additional keyboards. +This displays a configuration panel that shows the currently installed Keyman +keyboard packages and can download and install additional keyboards. #### Buttons diff --git a/linux/.gitignore b/linux/.gitignore index cf78b5ab49..bb6ad7a741 100644 --- a/linux/.gitignore +++ b/linux/.gitignore @@ -92,7 +92,6 @@ test.sh debianpackage/ *.deb *.ddeb -*.build *.buildinfo *.changes *.tar.xz diff --git a/linux/ibus-keyman/icons/meson.build b/linux/ibus-keyman/icons/meson.build new file mode 100644 index 0000000000..dce1d23614 --- /dev/null +++ b/linux/ibus-keyman/icons/meson.build @@ -0,0 +1,6 @@ +icons = files('default.png') + +install_data( + icons, + install_dir: '{datadir}/keyman/icons' +) diff --git a/linux/ibus-keyman/meson.build b/linux/ibus-keyman/meson.build new file mode 100644 index 0000000000..fa807e8842 --- /dev/null +++ b/linux/ibus-keyman/meson.build @@ -0,0 +1,65 @@ +project('ibus-keyman', 'c', 'cpp', + version: run_command('cat', '../../VERSION.md', check: true).stdout().strip(), + license: 'GPL-2+', + # default_options : ['buildtype=release', + # 'cpp_std=c++14', + # 'b_vscrt=static_from_buildtype', + # 'warning_level=2'], + meson_version: '>=0.53.0') +cc = meson.get_compiler('c') +conf = configuration_data() + +ibus = dependency('ibus-1.0', version: '>= 1.2.0') +gtk = dependency('gtk+-3.0', version: '>= 2.4') +x11 = dependency('x11', version: '>= 1.6') +json_glib = dependency('json-glib-1.0', version: '>= 1.0') +kmnkbp = dependency('keyman_kmn_processor', version: '>= 0.0.0') + +env = find_program('env') + +# define some variables. We wouldn't need this if we'd have a meson.build file +# in the Keyman root directory... +coredir = '@0@/../../core'.format(meson.current_source_dir()) + +kmxfiles = files( + join_paths(coredir, 'src/kmx/kmx_consts.cpp'), + join_paths(coredir, 'src/kmx/kmx_processevent.cpp'), + join_paths(coredir, 'src/kmx/kmx_actions.cpp'), + join_paths(coredir, 'src/kmx/kmx_capslock.cpp'), + join_paths(coredir, 'src/kmx/kmx_context.cpp'), + join_paths(coredir, 'src/kmx/kmx_conversion.cpp'), + join_paths(coredir, 'src/kmx/kmx_debug.cpp'), + join_paths(coredir, 'src/kmx/kmx_debugger.cpp'), + join_paths(coredir, 'src/kmx/kmx_environment.cpp'), + join_paths(coredir, 'src/kmx/kmx_file.cpp'), + join_paths(coredir, 'src/kmx/kmx_modifiers.cpp'), + join_paths(coredir, 'src/kmx/kmx_options.cpp'), + join_paths(coredir, 'src/kmx/kmx_processor.cpp'), + join_paths(coredir, 'src/kmx/kmx_xstring.cpp'), +) +corefiles = files( + join_paths(coredir, 'src/option.cpp'), + join_paths(coredir, 'src/keyboard.cpp'), + join_paths(coredir, 'src/state.cpp'), + join_paths(coredir, 'src/jsonpp.cpp'), + join_paths(coredir, 'src/utfcodec.cpp'), +) +coretestfiles = files( + join_paths(coredir, 'tests/unit/kmx/kmx_test_source.cpp'), +) + +# Check if we have patched ibus +code = '''#include +int x = IBUS_PREFILTER_MASK | IBUS_CAP_PREFILTER; +''' +if cc.compiles(code, dependencies: [ibus], name: 'check for patched ibus') + conf.set('IBUS_HAS_PREFILTER', 1) +endif + +conf.set('HAVE_CONFIG_H', 1) +configure_file(output : 'config.h', + configuration : conf) + +subdir('icons') +subdir('src') +subdir('tests') diff --git a/linux/ibus-keyman/src/Makefile.am b/linux/ibus-keyman/src/Makefile.am index 95361020c5..ce9f72640a 100644 --- a/linux/ibus-keyman/src/Makefile.am +++ b/linux/ibus-keyman/src/Makefile.am @@ -50,11 +50,11 @@ TESTS = \ $(NULL) print_kmp_SOURCES = \ - print_kmp.c + test/print_kmp.c print_kmpdetails_SOURCES = \ kmpdetails.c \ - print_kmpdetails.c \ + test/print_kmpdetails.c \ $(NULL) print_kmpdetails_CFLAGS = \ $(AM_CFLAGS) \ diff --git a/linux/ibus-keyman/src/keyman.xml.in b/linux/ibus-keyman/src/keyman.xml.in new file mode 100644 index 0000000000..d41cc8021c --- /dev/null +++ b/linux/ibus-keyman/src/keyman.xml.in @@ -0,0 +1,17 @@ + + + org.freedesktop.IBus.Keyman + Keyman Component + @libexecdir@/ibus-engine-keyman --ibus + @VERSION@ + Keyman Team <support@keyman.com> + GPL + https://keyman.com + ibus-keyman + + /usr/share/keyman/ + /usr/local/share/keyman/ + ~/.local/share/keyman/ + + + diff --git a/linux/ibus-keyman/src/meson.build b/linux/ibus-keyman/src/meson.build new file mode 100644 index 0000000000..63ab8ded94 --- /dev/null +++ b/linux/ibus-keyman/src/meson.build @@ -0,0 +1,43 @@ +utilfiles = files( + 'keymanutil.c', + 'keymanutil.h', + 'kmpdetails.c', + 'kmpdetails.h', +) + +engine_sources = files( + 'main.c', + 'engine.c', + 'engine.h', + 'keycodes.h', + 'keyman-service.c', + 'keyman-service.h', +) + +deps = [ibus, gtk, x11, json_glib, kmnkbp] + +prefix = get_option('prefix') +cfg = configuration_data() +cfg.set('VERSION', meson.project_version()) +cfg.set('libexecdir', join_paths(prefix, get_option('libexecdir'))) + +configure_file( + configuration: cfg, + input: 'keyman.xml.in', + output: 'keyman.xml' +) + +configure_file( + configuration: cfg, + input: 'keyman-version.h.in', + output: 'keyman-version.h' +) + +exe = executable( + 'ibus-engine-keyman', + sources: [engine_sources, utilfiles], + dependencies: deps, + include_directories: include_directories('@0@/..'.format(meson.current_build_dir())), +) + +subdir('test') diff --git a/linux/ibus-keyman/src/test/meson.build b/linux/ibus-keyman/src/test/meson.build new file mode 100644 index 0000000000..57302d2dcf --- /dev/null +++ b/linux/ibus-keyman/src/test/meson.build @@ -0,0 +1,65 @@ +keymanutil_sources = [ + 'keymanutil_tests.c', + utilfiles, +] + +keymanutil_deps = [ibus, gtk, x11, json_glib, kmnkbp] + +include_dirs = [ + include_directories('@0@/..'.format(meson.current_build_dir())), + '..' +] + +executable( + 'keymanutil-tests', + sources: keymanutil_sources, + dependencies: keymanutil_deps, + include_directories : include_dirs +) + +test( + 'keymanutil-tests', + find_program('run-tests.sh'), + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + protocol: 'tap', +) + +test( + 'print-kmpdetails-test', + executable( + 'print_kmpdetails', + sources: [ + 'print_kmpdetails.c', + '../kmpdetails.c' + ], + dependencies: [ json_glib ], + include_directories: include_dirs + ), + args: [ '@0@'.format(meson.current_source_dir()) ], + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + protocol: 'exitcode', +) + +test( + 'print-kmp-test', + executable( + 'print_kmp', + sources: [ + 'print_kmp.c', + ], + dependencies: [ json_glib ], + include_directories: include_dirs + ), + args: [ join_paths('@0@'.format(meson.current_source_dir()), 'kmp.json') ], + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + protocol: 'exitcode', +) diff --git a/linux/ibus-keyman/src/print_kmp.c b/linux/ibus-keyman/src/test/print_kmp.c similarity index 100% rename from linux/ibus-keyman/src/print_kmp.c rename to linux/ibus-keyman/src/test/print_kmp.c diff --git a/linux/ibus-keyman/src/print_kmpdetails.c b/linux/ibus-keyman/src/test/print_kmpdetails.c similarity index 100% rename from linux/ibus-keyman/src/print_kmpdetails.c rename to linux/ibus-keyman/src/test/print_kmpdetails.c diff --git a/linux/ibus-keyman/src/test/run-tests.sh b/linux/ibus-keyman/src/test/run-tests.sh index 04b78a95fe..932f64b886 100755 --- a/linux/ibus-keyman/src/test/run-tests.sh +++ b/linux/ibus-keyman/src/test/run-tests.sh @@ -1,6 +1,6 @@ #!/bin/bash -SRCDIR=${top_srcdir:-$(realpath $(dirname $0)/../..)} +SRCDIR=${top_srcdir:-$(realpath "$(dirname $0)/../..")} PID_FILE=/tmp/keymanutil-tests-pids if [ -v KEYMAN_PKG_BUILD ]; then @@ -12,19 +12,20 @@ if [ -v KEYMAN_PKG_BUILD ]; then exit 0 fi + if ! which Xvfb > /dev/null || ! which Xephyr > /dev/null || ! which metacity > /dev/null; then - echo "Please install Xvfb, Xephyr and metacity before running these tests!" + echo "# Please install Xvfb, Xephyr and metacity before running these tests!" exit 1 fi function cleanup() { if [ -f $PID_FILE ]; then echo - echo "Shutting down processes..." + echo "# Shutting down processes..." bash $PID_FILE > /dev/null 2>&1 rm $PID_FILE - rm -rf $TEMP_DATA_DIR - echo "Finished shutdown of processes." + rm -rf "$TEMP_DATA_DIR" + echo "# Finished shutdown of processes." fi } @@ -32,15 +33,15 @@ echo > $PID_FILE trap cleanup EXIT SIGINT -echo "Starting Xvfb..." +echo "# Starting Xvfb..." Xvfb -screen 0 1024x768x24 :33 &> /dev/null & echo "kill -9 $!" >> $PID_FILE sleep 1 -echo "Starting Xephyr..." +echo "# Starting Xephyr..." DISPLAY=:33 Xephyr :32 -screen 1024x768 &> /dev/null & echo "kill -9 $!" >> $PID_FILE sleep 1 -echo "Starting metacity" +echo "# Starting metacity" metacity --display=:32 &> /dev/null & echo "kill -9 $!" >> $PID_FILE @@ -51,10 +52,10 @@ TEMP_DATA_DIR=$(mktemp --directory) SCHEMA_DIR=$TEMP_DATA_DIR/glib-2.0/schemas export XDG_DATA_DIRS=$TEMP_DATA_DIR:$XDG_DATA_DIRS -mkdir -p $SCHEMA_DIR -cp $SRCDIR/../keyman-config/com.keyman.gschema.xml $SCHEMA_DIR/ -glib-compile-schemas $SCHEMA_DIR +mkdir -p "$SCHEMA_DIR" +cp "$SRCDIR/../keyman-config/com.keyman.gschema.xml" "$SCHEMA_DIR/" +glib-compile-schemas "$SCHEMA_DIR" export GSETTINGS_BACKEND=memory -./keymanutil-tests $@ +${G_TEST_BUILDDIR:-.}/keymanutil-tests "$@" diff --git a/linux/ibus-keyman/tests/README.md b/linux/ibus-keyman/tests/README.md index 8088f2f534..f7537a79fd 100644 --- a/linux/ibus-keyman/tests/README.md +++ b/linux/ibus-keyman/tests/README.md @@ -13,7 +13,7 @@ The tests get run as part of building `ibus-keyman`, more specifically when runn All tests can be run with the test script: ```bash -./run-tests.sh +scripts/run-tests.sh ``` ### Run specific tests @@ -22,5 +22,5 @@ To run a single test you pass the testname (as found in `core/build/arch/*/tests/unit/kmx`). Multiple tests should be separated by space. ```bash -./run-tests.sh -- k_000___null_keyboard k_005___nul_with_initial_context +scripts/run-tests.sh -- k_000___null_keyboard k_005___nul_with_initial_context ``` diff --git a/linux/ibus-keyman/tests/ibusimcontext.c b/linux/ibus-keyman/tests/ibusimcontext.c index d35441a695..dc83cf8b97 100644 --- a/linux/ibus-keyman/tests/ibusimcontext.c +++ b/linux/ibus-keyman/tests/ibusimcontext.c @@ -28,9 +28,7 @@ // simplyfying the code a bit by replacing async calls with direct synchronous // method calls. -#ifdef HAVE_CONFIG_H #include -#endif #ifndef IBUS_HAS_PREFILTER #warning Compiling against ibus version that does not include prefilter mask patch (https://github.com/ibus/ibus/pull/2440). Output ordering guarantees will be disabled. diff --git a/linux/ibus-keyman/tests/meson.build b/linux/ibus-keyman/tests/meson.build new file mode 100644 index 0000000000..494196cc35 --- /dev/null +++ b/linux/ibus-keyman/tests/meson.build @@ -0,0 +1,152 @@ +sources = [ + 'ibusimcontext.c', + 'ibusimcontext.h', + 'testfixture.cpp', + 'testmodule.c', + 'testmodule.h', + kmxfiles, + corefiles, + utilfiles, + coretestfiles, +] + +deps = [ibus, gtk, x11, json_glib, kmnkbp] + +include_dirs = [ + include_directories('../../../core/src'), + include_directories('../../../core/src/kmx'), + include_directories('../../../core/tests/unit/kmx'), + include_directories('../../../common/include'), + include_directories('../src'), + include_directories('..'), +] + +test_exe = executable( + 'ibus-keyman-tests', + sources: sources, + dependencies: deps, + include_directories: include_dirs +) + +env_file = '/tmp/env.txt' +pid_file = '/tmp/ibus-keyman-test-pids' + +setup_tests = find_program('setup-tests.sh', dirs: [join_paths(meson.current_source_dir(), 'scripts')]) +teardown_tests = find_program('teardown-tests.sh', dirs: [join_paths(meson.current_source_dir(), 'scripts')]) +run_test = find_program('run-single-test.sh', dirs: [join_paths(meson.current_source_dir(), 'scripts')]) +find_tests = find_program('find-tests.sh', dirs: [join_paths(meson.current_source_dir(), 'scripts')]) + +test( + 'setup-x11', + setup_tests, + args: ['--x11', env_file, pid_file], + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + priority: -10, + is_parallel: false, + protocol: 'exitcode' +) + +test( + 'setup-wayland', + setup_tests, + args: ['--wayland', env_file, pid_file], + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + priority: -20, + is_parallel: false, + protocol: 'exitcode' +) + +test( + 'teardown-x11', + teardown_tests, + args: [pid_file], + priority: -19, + is_parallel: false, + protocol: 'exitcode' +) + +test( + 'teardown-wayland', + teardown_tests, + args: [pid_file], + priority: -29, + is_parallel: false, + protocol: 'exitcode' +) + +kmx_dir = join_paths(meson.current_source_dir(), '../../../core/build/arch/debug/tests/unit/kmx') +kmx_files = run_command( + find_tests, + kmx_dir, + check: true, +).stdout().split('\n') + +foreach kmx: kmx_files + filename = kmx.split('\t') + if filename[0] == '' + continue + endif + testname = filename[1].split('.kmx')[0] + test( + 'X11-' + testname + '__surrounding-text', + run_test, + args: [ '--tap', '-k', '--x11', '--env', env_file, '--surrounding-text', '--', filename], + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + depends: [test_exe], + priority: -11, + is_parallel: false, + timeout: 120, + protocol: 'tap', + ) + test( + 'X11-' + testname + '__no-surrounding-text', + run_test, + args: [ '--tap', '-k', '--x11', '--env', env_file, '--no-surrounding-text', '--', filename], + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + depends: [test_exe], + priority: -12, + is_parallel: false, + timeout: 120, + protocol: 'tap', + ) + test( + 'Wayland-' + testname + '__surrounding-text', + run_test, + args: [ '--tap', '-k', '--wayland', '--env', env_file, '--surrounding-text', '--', filename], + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + depends: [test_exe], + priority: -21, + is_parallel: false, + timeout: 120, + protocol: 'tap', + ) + test( + 'Wayland-' + testname + '__no-surrounding-text', + run_test, + args: [ '--tap', '-k', '--wayland', '--env', env_file, '--no-surrounding-text', '--', filename], + env: [ + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), + ], + depends: [test_exe], + priority: -22, + is_parallel: false, + timeout: 120, + protocol: 'tap', + ) +endforeach diff --git a/linux/ibus-keyman/tests/scripts/find-tests.sh b/linux/ibus-keyman/tests/scripts/find-tests.sh new file mode 100755 index 0000000000..e5a144225f --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/find-tests.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +cd "$1" || exit +while IFS= read -r -d '' file; do + testname=$(basename "$file" .kmx) + printf "$(basename "$file")\t${testname#k_}\n" +done < <(find . -name \*.kmx -print0 | sort -z) diff --git a/linux/ibus-keyman/tests/scripts/run-single-test.sh b/linux/ibus-keyman/tests/scripts/run-single-test.sh new file mode 100755 index 0000000000..c265c27ccd --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/run-single-test.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +TESTDIR=${XDG_DATA_HOME:-$HOME/.local/share}/keyman/test_kmx + +. "$(dirname "$0")"/test-helper.sh + +if [ -v KEYMAN_PKG_BUILD ]; then + # During package builds we skip these tests that require to start ibus because + # ibus requires to find /var/lib/dbus/machine-id or /etc/machine-id, otherwise it fails with: + # "Bail out! IBUS-FATAL-WARNING: Unable to load /var/lib/dbus/machine-id: Failed to open file + # “/var/lib/dbus/machine-id”: No such file or directory" + echo "1..1" + echo "ok 1 - Integration tests # SKIP on package build" + exit 0 +fi + +if ! which Xvfb > /dev/null || ! which Xephyr > /dev/null || ! which metacity > /dev/null || ! which mutter > /dev/null; then + echo "Please install Xvfb, Xephyr, metacity and mutter before running these tests!" + exit 1 +fi + +function help() { + echo "Usage:" + echo " $0 [--env ] [-k] [--tap] [--surrounding-text] [--no-surrounding-text] [--wayland|--x11] [--] TEST" + echo + echo "Arguments:" + echo " --help, -h, -? Display this help" + echo " --verbose, -v Run tests verbosely" + echo " --debug debug test logging output" + echo " -k passed to GLib testing framework" + echo " --tap output in TAP format. Passed to GLib testing framework" + echo " --surrounding-text run tests with surrounding texts enabled" + echo " --no-surrounding-text run tests without support for surrounding text" + echo " --wayland run tests with Wayland" + echo " --x11 run tests with X11" + echo " --env Name of the file containing environment variables to use" + exit 0 +} + +function run_tests() { + echo "# NOTE: When the tests fail check /tmp/ibus-engine-keyman.log and /tmp/ibus-daemon.log!" + echo "" + + echo "# Starting tests..." + # Note: -k and --tap are consumed by the GLib testing framework + # shellcheck disable=SC2086 + "${G_TEST_BUILDDIR:-.}"/ibus-keyman-tests ${ARG_K-} ${ARG_TAP-} \ + ${ARG_VERBOSE-} ${ARG_DEBUG-} ${ARG_SURROUNDING_TEXT-} ${ARG_NO_SURROUNDING_TEXT-} \ + --directory "$TESTDIR" ${ARG_DISPLAY_SERVER} "$TESTFILE" + echo "# Finished tests." +} + +while (( $# )); do + case $1 in + --help|-h|-\?) help ;; + -k) ARG_K=$1 ;; + --tap) ARG_TAP=$1 ;; + --surrounding-text) ARG_SURROUNDING_TEXT=$1 ;; + --no-surrounding-text) ARG_NO_SURROUNDING_TEXT=$1 ;; + --wayland) ARG_DISPLAY_SERVER=$1 ;; + --x11) ARG_DISPLAY_SERVER=$1 ;; + --verbose|-v) ARG_VERBOSE=--verbose;; + --debug) ARG_DEBUG=--debug-log;; + --env) shift ; ARG_ENV=$1 ;; + --) shift ; TESTFILE=$1; break ;; + *) echo "Error: Unexpected argument \"$1\". Exiting." ; exit 4 ;; + esac + shift || (echo "Error: The last argument is missing a value. Exiting."; false) || exit 5 +done + +# shellcheck source=/dev/null +. "$ARG_ENV" + +run_tests diff --git a/linux/ibus-keyman/tests/scripts/run-tests.sh b/linux/ibus-keyman/tests/scripts/run-tests.sh new file mode 100755 index 0000000000..b80dd1a5f4 --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/run-tests.sh @@ -0,0 +1,206 @@ +#!/usr/bin/env bash + +TOP_SRCDIR=${top_srcdir:-$(realpath "$(dirname "$0")/..")} +TESTDIR=${XDG_DATA_HOME:-$HOME/.local/share}/keyman/test_kmx + +. "$(dirname "$0")"/test-helper.sh + +if [ -v KEYMAN_PKG_BUILD ]; then + # During package builds we skip these tests that require to start ibus because + # ibus requires to find /var/lib/dbus/machine-id or /etc/machine-id, otherwise it fails with: + # "Bail out! IBUS-FATAL-WARNING: Unable to load /var/lib/dbus/machine-id: Failed to open file + # “/var/lib/dbus/machine-id”: No such file or directory" + echo "1..1" + echo "ok 1 - Integration tests # SKIP on package build" + exit 0 +fi + +if ! which Xvfb > /dev/null || ! which Xephyr > /dev/null || ! which metacity > /dev/null || ! which mutter > /dev/null; then + echo "Please install Xvfb, Xephyr, metacity and mutter before running these tests!" + exit 1 +fi + +function cleanup() { + if [ -f "$PID_FILE" ]; then + echo + echo "# Shutting down processes..." + bash "$PID_FILE" > /dev/null 2>&1 + rm "$PID_FILE" + echo "# Finished shutdown of processes." + fi +} + +function help() { + echo "Usage:" + echo " $0 [-k] [--tap] [--surrounding-text] [--no-surrounding-text] [--no-wayland] [--no-x11] [[--] TEST...]" + echo + echo "Arguments:" + echo " --help, -h, -? Display this help" + echo " --verbose, -v Run tests verbosely" + echo " --debug debug test logging output" + echo " -k passed to GLib testing framework" + echo " --tap output in TAP format. Passed to GLib testing framework" + echo " --surrounding-text run tests with surrounding texts enabled" + echo " --no-surrounding-text run tests without support for surrounding text" + echo " --no-wayland don't run tests with Wayland" + echo " --no-x11 don't run tests with X11" + echo + echo "If no TESTs are specified then all tests are run." + echo "If neither --surrounding-text nor --no-surrounding-text are specified then the tests run with both settings." + exit 0 +} + +function run_tests() { + DISPLAY_SERVER=$1 + shift + + echo > "$PID_FILE" + TEMP_DATA_DIR=$(mktemp --directory) + echo "rm -rf ${TEMP_DATA_DIR}" >> "$PID_FILE" + + COMMON_ARCH_DIR= + [ -d "${TOP_SRCDIR}"/../../core/build/arch ] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../../core/build/arch + [ -d "${TOP_SRCDIR}"/../keyboardprocessor/arch ] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../keyboardprocessor/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 + + if [ ! -d "$TESTDIR" ] || ! [[ $(find "${TESTDIR}/" -name \*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then + if [[ $(find "${COMMON_ARCH_DIR}/tests/unit/kmx/" -name \*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then + mkdir -p "$(realpath --canonicalize-missing "$TESTDIR"/..)" + ln -sf "$(realpath "${COMMON_ARCH_DIR}"/tests/unit/kmx)" "$TESTDIR" + else + echo "Can't find kmx files in ${COMMON_ARCH_DIR}/tests/unit/kmx" + exit 3 + fi + fi + + echo "# NOTE: When the tests fail check /tmp/ibus-engine-keyman.log and /tmp/ibus-daemon.log!" + echo "" + + 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..." + TMPFILE=$(mktemp) + # mutter-Message: 18:56:15.422: Using Wayland display name 'wayland-1' + mutter --wayland --headless --no-x11 --virtual-monitor 1024x768 &> "$TMPFILE" & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + export WAYLAND_DISPLAY + WAYLAND_DISPLAY=$(cat "$TMPFILE" | grep "Using Wayland display" | cut -d"'" -f2) + rm "$TMPFILE" + else + echo "# Starting Xvfb..." + Xvfb -screen 0 1024x768x24 :33 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1 + echo "# Starting Xephyr..." + DISPLAY=:33 Xephyr :32 -screen 1024x768 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1 + echo "# Starting metacity" + metacity --display=:32 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + + export DISPLAY=:32 + fi + + # 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 + + mkdir -p "$SCHEMA_DIR" + cp "${TOP_SRCDIR}"/../keyman-config/com.keyman.gschema.xml "$SCHEMA_DIR"/ + glib-compile-schemas "$SCHEMA_DIR" + + if [ $# -gt 0 ]; then + TESTFILES=($@) + else + pushd "$TESTDIR" > /dev/null || exit + TESTFILES=(*.kmx) + popd > /dev/null || exit + fi + + export LD_LIBRARY_PATH=${COMMON_ARCH_DIR}/src:$LD_LIBRARY_PATH + + # 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 + IBUS_CONFIG=--config=/usr/libexec/ibus-memconf + fi + + ibus-daemon "${ARG_VERBOSE-}" --panel=disable ${IBUS_CONFIG-} &> /tmp/ibus-daemon.log & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + + ../src/ibus-engine-keyman "${ARG_VERBOSE-}" &> /tmp/ibus-engine-keyman.log & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + + echo "# Starting tests..." + # Note: -k and --tap are consumed by the GLib testing framework + "${G_TEST_BUILDDIR:-.}"/ibus-keyman-tests "${ARG_K-}" "${ARG_TAP-}" \ + "${ARG_VERBOSE-}" "${ARG_DEBUG-}" "${ARG_SURROUNDING_TEXT-}" "${ARG_NO_SURROUNDING_TEXT-}" \ + --directory "$TESTDIR" --"${DISPLAY_SERVER}" "${TESTFILES[@]}" + echo "# Finished tests." + + cleanup +} + +USE_WAYLAND=1 +USE_X11=1 + +while (( $# )); do + case $1 in + --help|-h|-\?) help ;; + -k) ARG_K=$1 ;; + --tap) ARG_TAP=$1 ;; + --surrounding-text) ARG_SURROUNDING_TEXT=$1 ;; + --no-surrounding-text) ARG_NO_SURROUNDING_TEXT=$1 ;; + --no-wayland) USE_WAYLAND=0;; + --no-x11) USE_X11=0;; + --verbose|-v) ARG_VERBOSE=--verbose;; + --debug) ARG_DEBUG=--debug-log;; + --) shift && break ;; + *) echo "Error: Unexpected argument \"$1\". Exiting." ; exit 4 ;; + esac + shift || (echo "Error: The last argument is missing a value. Exiting."; false) || exit 5 +done + +if ! can_run_wayland; then + # support for --headless got added in mutter 40.x + echo "# WARNING: mutter doesn't support running headless. Skipping Wayland tests." + USE_WAYLAND=0 + if [ "$USE_X11" == "0" ]; then + echo "ERROR: no tests to run. Can't run Wayland tests, and --no-x11 is specified." + exit 8 + fi +fi + +if [ "$USE_WAYLAND" == "0" ] && [ "$USE_X11" == "0" ]; then + echo "ERROR: I'll have to run somewhere. Specifying both --no-wayland and --no-x11 is not allowed." + exit 6 +fi + +echo > "$PID_FILE" +trap cleanup EXIT SIGINT + +if [ "$USE_WAYLAND" == "1" ]; then + run_tests wayland "$@" +fi + +if [ "$USE_X11" == "1" ]; then + run_tests x11 "$@" +fi diff --git a/linux/ibus-keyman/tests/scripts/setup-tests.sh b/linux/ibus-keyman/tests/scripts/setup-tests.sh new file mode 100755 index 0000000000..e48d36eba9 --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/setup-tests.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash +DISPLAY_SERVER=$1 +ENV_FILE=$2 +PID_FILE=$3 + +TOP_SRCDIR=${G_TEST_SRCDIR:-$(realpath "$(dirname "$0")/..")}/.. +TOP_BINDIR=${G_TEST_BUILDDIR:-$(realpath "$(dirname "$0/..")")}/.. +TESTDIR=${XDG_DATA_HOME:-$HOME/.local/share}/keyman/test_kmx + +. "$(dirname "$0")/"/test-helper.sh + +echo > "$ENV_FILE" + +if [ -f "$PID_FILE" ]; then + # kill previous instances + "$(dirname "$0")"/teardown-tests.sh "$PID_FILE" +fi + +echo > "$PID_FILE" +TEMP_DATA_DIR=$(mktemp --directory) +echo "rm -rf ${TEMP_DATA_DIR}" >> "$PID_FILE" + +COMMON_ARCH_DIR= +[ -d "${TOP_SRCDIR}"/../../core/build/arch ] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../../core/build/arch +[ -d "${TOP_SRCDIR}"/../keyboardprocessor/arch ] && COMMON_ARCH_DIR=${TOP_SRCDIR}/../keyboardprocessor/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 + +if [ ! -d "$TESTDIR" ] || ! [[ $(find "${TESTDIR}/" -name \*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then + if [[ $(find "${COMMON_ARCH_DIR}/tests/unit/kmx/" -name \*.kmx 2>/dev/null | wc -l) -gt 0 ]]; then + mkdir -p "$(realpath --canonicalize-missing "$TESTDIR"/..)" + ln -sf "$(realpath "${COMMON_ARCH_DIR}"/tests/unit/kmx)" "$TESTDIR" + else + echo "Can't find kmx files in ${COMMON_ARCH_DIR}/tests/unit/kmx" + exit 3 + fi +fi + +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..." + TMPFILE=$(mktemp) + # mutter-Message: 18:56:15.422: Using Wayland display name 'wayland-1' + mutter --wayland --headless --no-x11 --virtual-monitor 1024x768 &> "$TMPFILE" & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + export WAYLAND_DISPLAY + WAYLAND_DISPLAY=$(grep "Using Wayland display" "$TMPFILE" | cut -d"'" -f2) + rm "$TMPFILE" + echo "export WAYLAND_DISPLAY=\"$WAYLAND_DISPLAY\"" >> "$ENV_FILE" +else + echo "Starting Xvfb..." + Xvfb -screen 0 1024x768x24 :33 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1 + echo "Starting Xephyr..." + DISPLAY=:33 Xephyr :32 -screen 1024x768 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1 + echo "Starting metacity" + metacity --display=:32 &> /dev/null & + echo "kill -9 $!" >> "$PID_FILE" + + export DISPLAY=:32 + echo "export DISPLAY=\"$DISPLAY\"" >> "$ENV_FILE" +fi + + # 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" + + mkdir -p "$SCHEMA_DIR" + cp "${TOP_SRCDIR}"/../keyman-config/com.keyman.gschema.xml "$SCHEMA_DIR"/ + glib-compile-schemas "$SCHEMA_DIR" + + export LD_LIBRARY_PATH=${COMMON_ARCH_DIR}/src:$LD_LIBRARY_PATH + echo "export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH\"" >> "$ENV_FILE" + + # 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 + + ibus-daemon "${ARG_VERBOSE-}" --daemonize --panel=disable ${IBUS_CONFIG-} &> /tmp/ibus-daemon.log + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s + + IBUS_ADDRESS=$(ibus address) + export IBUS_ADDRESS + + echo "export IBUS_ADDRESS=\"$IBUS_ADDRESS\"" >> "$ENV_FILE" + + "${TOP_BINDIR}"/src/ibus-engine-keyman "${ARG_VERBOSE-}" &> /tmp/ibus-engine-keyman.log & + echo "kill -9 $!" >> "$PID_FILE" + sleep 1s diff --git a/linux/ibus-keyman/tests/scripts/teardown-tests.sh b/linux/ibus-keyman/tests/scripts/teardown-tests.sh new file mode 100755 index 0000000000..489769d721 --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/teardown-tests.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +PID_FILE=$1 + +echo "Shutting down processes..." +bash "$PID_FILE" > /dev/null 2>&1 +rm "$PID_FILE" +echo "Finished shutdown of processes." diff --git a/linux/ibus-keyman/tests/scripts/test-helper.sh b/linux/ibus-keyman/tests/scripts/test-helper.sh new file mode 100644 index 0000000000..92c8a7e528 --- /dev/null +++ b/linux/ibus-keyman/tests/scripts/test-helper.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env 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 +}