1Weston test suite 2================= 3 4Weston test suite aims to test features of the Weston compositor and libweston. 5The automatic tests are executed as part of ``meson test`` and in the Gitlab CI. 6In addition to automatic tests, there are few manual tests that have not been 7automated, but being manual means they are also not routinely (or ever) 8executed. 9 10 11Test execution 12-------------- 13 14The test execution hierarchy is: 15 16* ``meson test`` 17 18 * a test program 19 20 * a fixture setup 21 22 * a test 23 24 * a sub-test from a data array 25 26When ``meson test`` is executed, it will run all defined *test programs* 27potentially in parallel and collect their exit status. Therefore it is 28important to design each test program to be executable in parallel with every 29other test program. 30 31A **test program** is essentially one ``.c`` source code file that is built into 32one executable file (not a library, module, or plugin). Each test program is 33possible to run manually without Meson straight from the build directory 34without any environment or command line setup, e.g. with GDB or Valgrind. 35 36A test program may define one **fixture setup** function. The function may be 37defined alone or with a data array of an arbitrary data type. If an array is 38defined, the fixture setup will be called and all the tests in the program 39executed for each element in the array serially. Fixture setups are used for 40setting up the Weston compositor for the tests that need it. The array is 41useful for running the compositor with different settings for the same tests, 42e.g. with Pixman-renderer and GL-renderer. 43 44**A test** in a test program is defined with one of the macros :c:func:`TEST`, 45:c:func:`TEST_P`, or :c:func:`PLUGIN_TEST`. :c:func:`TEST` defines a single 46test with no sub-tests. :c:func:`TEST_P` defines a data-driven array of tests: 47a set of sub-tests. :c:func:`PLUGIN_TEST` is used specifically by *plugin 48tests* that require access to :type:`weston_compositor`. 49 50All tests and sub-tests are executed serially in a test program. The test 51harness does not ``fork()`` which means that any test that crashes or hits an 52assert failure will quit the whole test program on the spot, leaving following 53tests in that program not executed. 54 55The test suite has no tests that are expected to fail in general. All tests 56that test for a failure must check the exact error condition expected and 57succeed if it is met or fail for any other or no error. 58 59 60Types of tests 61-------------- 62 63Aside from manual vs. automatic, there are three types of tests: 64 65Standalone tests 66 Standalone tests do not launch the full compositor. 67 68Plugin tests 69 Plugin tests launch the Weston compositor and execute the list of tests 70 from an idle callback handler in the compositor context, blocking the 71 compositor while they run. 72 73Client tests 74 Client tests launch the Weston compositor and execute the list of tests 75 in a new thread that is created from an idle callback handler. This means 76 the compositor runs independently from the tests and one can write a test 77 like as a normal Wayland client. 78 79The type of all the tests in a test program is defined by the fixture setup 80function. A fixture setup function is any defined function with a specific 81signature and registered with either :c:func:`DECLARE_FIXTURE_SETUP` or 82:c:func:`DECLARE_FIXTURE_SETUP_WITH_ARG`. 83 84 85.. _test-suite-standalone: 86 87Standalone tests 88^^^^^^^^^^^^^^^^ 89 90Standalone tests do not have a fixture setup function defined in the test 91program or the fixture setup function calls 92:func:`weston_test_harness_execute_standalone` explicitly. All test cases must 93be defined with :c:func:`TEST` or :c:func:`TEST_P`. 94 95This is the simplest possible test example: 96 97.. code-block:: c 98 99 TEST(always_success) 100 { 101 /* true */ 102 } 103 104 105.. _test-suite-plugin: 106 107Plugin tests 108^^^^^^^^^^^^ 109 110Plugin tests must have a fixture setup function that calls 111:func:`weston_test_harness_execute_as_plugin`. All test cases must be defined 112with :c:func:`PLUGIN_TEST` which declares an implicit function argument 113:type:`weston_compositor` ``*compositor``. 114 115The compositor fixture manufactures the necessary environment variables and the 116command line argument array to launch Weston, and calls :func:`wet_main` 117directly. An idle task handler is registered, which gets invoked when 118initialization is done. All tests are executed from that idle handler, and then 119the compositor exits. 120 121This is an example of a plugin test that just logs a line: 122 123.. code-block:: c 124 125 static enum test_result_code 126 fixture_setup(struct weston_test_harness *harness) 127 { 128 struct compositor_setup setup; 129 130 compositor_setup_defaults(&setup); 131 132 return weston_test_harness_execute_as_plugin(harness, &setup); 133 } 134 DECLARE_FIXTURE_SETUP(fixture_setup); 135 136 PLUGIN_TEST(plugin_registry_test) 137 { 138 /* struct weston_compositor *compositor; */ 139 testlog("Got compositor %p\n", compositor); 140 } 141 142 143.. _test-suite-client: 144 145Client tests 146^^^^^^^^^^^^ 147 148Plugin tests must have a fixture setup function that calls 149:func:`weston_test_harness_execute_as_client`. All test cases must be 150defined with :c:func:`TEST` or :c:func:`TEST_P`. 151 152The compositor fixture manufactures the necessary environment variables and the 153command line argument array to launch Weston, and calls :func:`wet_main` 154directly. An idle task handler is registered, which gets invoked when 155initialization is done. The idle handler creates a new thread and returns. The 156new thread will execute all tests and then signal the compositor to exit. 157 158This is an incomplete example of an array of sub-tests and another test as 159clients: 160 161.. code-block:: c 162 163 static enum test_result_code 164 fixture_setup(struct weston_test_harness *harness) 165 { 166 struct compositor_setup setup; 167 168 compositor_setup_defaults(&setup); 169 170 return weston_test_harness_execute_as_client(harness, &setup); 171 } 172 DECLARE_FIXTURE_SETUP(fixture_setup); 173 174 struct bad_source_rect_args { 175 int x, y, w, h; 176 }; 177 178 static const struct bad_source_rect_args bad_source_rect_args[] = { 179 { -5, 0, 20, 10 }, 180 { 0, -5, 20, 10 }, 181 { 5, 6, 0, 10 }, 182 { 5, 6, 20, 0 }, 183 { 5, 6, -20, 10 }, 184 { 5, 6, 20, -10 }, 185 { -1, -1, 20, 10 }, 186 { 5, 6, -1, -1 }, 187 }; 188 189 TEST_P(test_viewporter_bad_source_rect, bad_source_rect_args) 190 { 191 const struct bad_source_rect_args *args = data; 192 struct client *client; 193 struct wp_viewport *vp; 194 195 client = create_client_and_test_surface(100, 50, 123, 77); 196 197 vp = create_viewport(client); 198 199 testlog("wp_viewport.set_source x=%d, y=%d, w=%d, h=%d\n", 200 args->x, args->y, args->w, args->h); 201 set_source(vp, args->x, args->y, args->w, args->h); 202 203 expect_protocol_error(client, &wp_viewport_interface, 204 WP_VIEWPORT_ERROR_BAD_VALUE); 205 } 206 207 TEST(test_roundtrip) 208 { 209 struct client *client; 210 211 client = create_client_and_test_surface(100, 50, 123, 77); 212 client_roundtrip(client); 213 } 214 215 216DRM-backend tests 217----------------- 218 219DRM-backend tests require a DRM device, so they are a special case. To select a 220device the test suite will simply look at the environment variable 221``WESTON_TEST_SUITE_DRM_DEVICE``. So the first thing the user has to do in order 222to run DRM-backend tests is to set this environment variable with the card that 223should run the tests. For instance, in order to run DRM-backend tests with 224``card0`` we need to run ``export WESTON_TEST_SUITE_DRM_DEVICE=card0``. 225 226Note that the card should not be in use by a desktop environment (or any other 227program that requires master status), as there can only be one user at a time 228with master status in a DRM device. Also, this is the reason why we can not run 229two or more DRM-backend tests simultaneously. Since the test suite tries to run 230the tests in parallel, we have a lock mechanism to enforce that DRM-backend 231tests run sequentially, one at a time. Note that this will not avoid them to run 232in parallel with other types of tests. 233 234Another specificity of DRM-backend tests is that they run using the non-default 235seat ``seat-weston-test``. This avoids unnecessarily opening input devices that 236may be present in the default seat ``seat0``. On the other hand, this will make 237``launcher-logind`` fail, as we are trying to use a seat that is different from 238the one we are logged in. In the CI we do not rely on ``logind``, so it should 239fallback to ``launcher-direct`` anyway. It requires root, but this is also not a 240problem for the CI, as ``virtme`` starts as root. The problem is that to run 241the tests locally with a real hardware the users need to run as root. 242 243 244Writing tests 245------------- 246 247Test programs do not have a ``main()`` of their own. They all share the 248``main()`` from the test harness and only define test cases and a fixture 249setup. 250 251It is recommended to have one test program (one ``.c`` file) contain only one 252type of tests to keep the fixture setup simple. See 253:ref:`test-suite-standalone`, :ref:`test-suite-plugin` and 254:ref:`test-suite-client` how to set up each type in a test program. 255 256.. note:: 257 258 **TODO:** Currently it is not possible to gracefully skip or fail a test. 259 You can skip with ``exit(RESULT_SKIP)`` but that will quit the whole test 260 program and all defined tests that were not ran yet will be counted as 261 failed. You can fail a test by any means, e.g. ``exit(RESULT_FAIL)``, but 262 the same caveat applies. Succeeded tests must simply return and not call any 263 exit function. 264 265 266.. toctree:: 267 :hidden: 268 269 test-suite-api.rst 270