1# GTK Layer Shell tests 2This directory is home to the gtk-layer-shell test suite. 3 4## To run tests 5`ninja -C build test` (where `build` is the path to your build directory). 6 7### To add a new integration test 81. Copy an existing integration test file 92. Implement your test as a series of one or more callbacks 103. Add its name to the list in `test/integration-tests/meson.build` 11 12## Scrpts 13- `check-licenses.py` makes sure all files have licenses at the top 14- `tests-not-enabled.py` is only run if tests are disabled, and explains to the user how to enable them 15- `run-integration-test.py` runs a single integration test 16- `check-all-tests-are-in-meson.py` fails if any test files exist that haven't been added to meson (an easy mistake to make) 17 18## Integration tests 19Most of the potential bugs in GTK Layer Shell arise from interactions between the library, GTK and the Wayland compositor, so unit tests aren't particularly useful. Instead, most of our tests are integration tests. 20 21### Integration test app 22Each integration test is a single unique GTK app that uses GTK Layer Shell. All test clients are located in `integration-tests`. Anything common to multiple tests gets pulled into `integration-test-common` or `test-common`. Tests consist of a sequence of callbacks. At the start of each callback the app can state that specific Wayland messages should be sent during or after the callback is run (see expectations format below). Each meson test runs a single integration test. 23 24Integration tests can be run directly on a normal Wayland compositor (this may be useful for debugging). When run without arguments, they open an additional layer shell window with a `Continue ->` button to manually advance the test. Pass `--auto` to run each test callback with a timeout the way they are run when automated. 25 26### Expectations format 27Integration tests emit protocol expectations by using the `EXPECT_MESSAGE` macro. Each expectation is a white-space-separated sequence of tokens written to a line of stdout. The first element must be `EXPECT:` (this is automatically inserted by `EXPECT_MESSAGE`). For an expectation to match a message, each following token must appear in order in the message line. The list of expected messages must match in the correct order. Messages are matched against the output of the app run with `WAYLAND_DEBUG=1`. Events and requests are not distinguished. 28 29When the script encounters `CHECK EXPECTATIONS COMPLETED` (emitted by the `CHECK_EXPECTATIONS()` macro), it will assert that all previous expectations have been met. This is emitted automatically at the start of each test callback. 30 31### Test runner 32`ninja -C build test` will run `run-integration-test.py` for each test defined in `test/meson.build`. This script: 33- Creates a temporary directory in `/tmp` to serve as `XDG_RUNTIME_DIR` (this allows tests to run in parallel without interfering with each other) 34- Spins up a mock Wayland server 35- Runs the given integration test within it 36- (Both are run with `WAYLAND_DEBUG=1` so protocol messages are written to stderr by libwayland) 37- Ensures both the client and server exit successfully 38- Parses the client's protocol message expectations 39- Ensures they match the protocol messages generated by libwayland 40 41### Mock server 42Rather than running the integration tests in an external Wayland compositor, we implement our own mock Wayland compositor (located in `mock-server`). This doesn't show anything on-screen or get real user input, it simply gives the required responses to protocol messages. It's only dependency is libwayland. It implements most of the protocol with a single default dispatcher. This reads the message signature and takes whatever action appears to be required. The behavior of some messages is overridden in `overrides.c`. 43