• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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