Skip to content

Integrating WLCS with your test suite

Christopher James Halse Rogers edited this page May 2, 2019 · 4 revisions

Using wlcs

wlcs is expected to be primarily used by compositor test-suites. To integrate into your test suite you need to:

  1. build a test fixture library; and,
  2. run the wlcs binary, with that test fixture library, as a part of your test suite.

Example from Mir

This example shows running just the tests for xdg_toplevel against Mir:

chris@Behemoth:~/Canonical/Mir/mir/build-ninja-gcc$ /usr/lib/x86_64-linux-gnu/wlcs/wlcs lib/miral_wlcs_integration.so --gtest_filter=XdgToplevelStable*
Note: Google Test filter = XdgToplevelStable*
[==========] Running 8 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 2 tests from XdgToplevelStableTest
[ RUN      ] XdgToplevelStableTest.pointer_respects_window_geom_offset
[       OK ] XdgToplevelStableTest.pointer_respects_window_geom_offset (12 ms)
[ RUN      ] XdgToplevelStableTest.touch_respects_window_geom_offset
[       OK ] XdgToplevelStableTest.touch_respects_window_geom_offset (9 ms)
[----------] 2 tests from XdgToplevelStableTest (21 ms total)

[----------] 6 tests from XdgToplevelStableConfigurationTest
[ RUN      ] XdgToplevelStableConfigurationTest.defaults
[       OK ] XdgToplevelStableConfigurationTest.defaults (8 ms)
[ RUN      ] XdgToplevelStableConfigurationTest.window_can_maximize_itself
[       OK ] XdgToplevelStableConfigurationTest.window_can_maximize_itself (9 ms)
[ RUN      ] XdgToplevelStableConfigurationTest.window_can_unmaximize_itself
[       OK ] XdgToplevelStableConfigurationTest.window_can_unmaximize_itself (8 ms)
[ RUN      ] XdgToplevelStableConfigurationTest.window_can_fullscreen_itself
[       OK ] XdgToplevelStableConfigurationTest.window_can_fullscreen_itself (7 ms)
[ RUN      ] XdgToplevelStableConfigurationTest.window_can_unfullscreen_itself
[       OK ] XdgToplevelStableConfigurationTest.window_can_unfullscreen_itself (9 ms)
[ RUN      ] XdgToplevelStableConfigurationTest.activated_state_follows_pointer
[       OK ] XdgToplevelStableConfigurationTest.activated_state_follows_pointer (9 ms)
[----------] 6 tests from XdgToplevelStableConfigurationTest (50 ms total)

[----------] Global test environment tear-down
[==========] 8 tests from 2 test cases run. (71ms total elapsed)
[  PASSED  ] 8 tests

Here, lib/miral_wlcs_integration.so is the test fixture, and you can see we can pass a GTest option (--gtest_filter=XdgToplevelStable*) to restrict the set of tests run. We could also have passed compositor-specific options to the wlcs invocation; these will be passed to the test fixture.

Integrating wlcs with your test suite

As is traditional for a development dependency, wlcs ships with pkg-config files. The pkg-config files contain both the necessary compiler and linker flags to build your compositor's test fixture library, but also the path to the test runner in the test_runner variable. By default, wlcs also builds test-runners with the ASan, TSan and UBsan sanitisers enabled; these are available with the .asan, .tsan, and .ubsan suffices.

The test runner can be invoked as /path/to/wlcs TEST_FIXTURE [ARGS], where [ARGS] is any combination of GTest-supported options (see --help for a list) or compositor-specific command line options.

Writing the test fixture library

wlcs relies on the test fixture providing a set of hooks to create a display server, start the mainloop, create fake input devices, and so on. These are versioned via a provided version field in the various structures, which should be set to whatever version the test fixture supports.

The signatures for the initial entry point and these hooks are found in wlcs/display_server.h. Particularly, the wlcs test runner begins execution by loading the wlcs_server_integration symbol and constructing all other objects from there.

You can find Mir's test fixture implementation here. While a lot of this is Mir-specific infrastructure, the wlcs entry point is here, which sets up a Mir server and so on.

For ease of debugging wlcs is set up to make it easy to run both the test code and the compositor under test in the same process; this makes tracing from test code to server code and back again easier. If the architecture of your compositor makes that difficult, your wlcs integration can choose to fork()/exec() and interact with your compositor over whatever RPC mechanism you choose.

Example build-system integration

For meson:

deps_wlcs = dependency('wlcs')
wlcs_integration = shared_library(
    'wlcs-integration',
    srcs_wlcs,
    include_directories: include_directories(whatever),
    dependencies: deps_wlcs,
    name_prefix: '',
    install: false
)
wlcs_binary = find_program(deps_wlcs.get_pkgconfig_variable('test_runner'))
test('WLCS', wlcs_binary, args : [ wlcs_integration.full_path() ])

For CMake:

add_library(
    miral_wlcs_integration MODULE
    miral_integration.cpp
)
set_target_properties(
    miral_wlcs_integration PROPERTIES
    PREFIX ""
)
pkg_get_variable(WLCS_BINARY wlcs test_runner)
add_test(NAME wlcs ${WLCS_BINARY} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/miral_wlcs_integration.so)

(For a fully-working CMake example, see Mir's build system.)