1 /*
2 * Copyright © 2015 Collabora, Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #include "config.h"
27
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "shared/helpers.h"
33 #include "shared/xalloc.h"
34 #include "weston-test-client-helper.h"
35 #include "ivi-application-client-protocol.h"
36 #include "ivi-test.h"
37 #include "weston-test-fixture-compositor.h"
38
39 static enum test_result_code
fixture_setup(struct weston_test_harness * harness)40 fixture_setup(struct weston_test_harness *harness)
41 {
42 struct compositor_setup setup;
43
44 compositor_setup_defaults(&setup);
45 setup.shell = SHELL_IVI;
46 setup.extra_module = "test-ivi-layout.so";
47
48 return weston_test_harness_execute_as_client(harness, &setup);
49 }
50 DECLARE_FIXTURE_SETUP(fixture_setup);
51
52 struct runner {
53 struct client *client;
54 struct weston_test_runner *test_runner;
55 int done;
56 };
57
58 static void
runner_finished_handler(void * data,struct weston_test_runner * test_runner)59 runner_finished_handler(void *data, struct weston_test_runner *test_runner)
60 {
61 struct runner *runner = data;
62
63 runner->done = 1;
64 }
65
66 static const struct weston_test_runner_listener test_runner_listener = {
67 runner_finished_handler
68 };
69
70 static struct runner *
client_create_runner(struct client * client)71 client_create_runner(struct client *client)
72 {
73 struct runner *runner;
74 struct global *g;
75 struct global *global_runner = NULL;
76
77 runner = xzalloc(sizeof(*runner));
78 runner->client = client;
79
80 wl_list_for_each(g, &client->global_list, link) {
81 if (strcmp(g->interface, "weston_test_runner"))
82 continue;
83
84 if (global_runner)
85 assert(0 && "multiple weston_test_runner objects");
86
87 global_runner = g;
88 }
89
90 assert(global_runner && "no weston_test_runner found");
91 assert(global_runner->version == 1);
92
93 runner->test_runner = wl_registry_bind(client->wl_registry,
94 global_runner->name,
95 &weston_test_runner_interface,
96 1);
97 assert(runner->test_runner);
98
99 weston_test_runner_add_listener(runner->test_runner,
100 &test_runner_listener, runner);
101
102 return runner;
103 }
104
105 static void
runner_destroy(struct runner * runner)106 runner_destroy(struct runner *runner)
107 {
108 weston_test_runner_destroy(runner->test_runner);
109 client_roundtrip(runner->client);
110 free(runner);
111 }
112
113 static void
runner_run(struct runner * runner,const char * test_name)114 runner_run(struct runner *runner, const char *test_name)
115 {
116 testlog("weston_test_runner.run(\"%s\")\n", test_name);
117
118 runner->done = 0;
119 weston_test_runner_run(runner->test_runner, test_name);
120
121 while (!runner->done) {
122 if (wl_display_dispatch(runner->client->wl_display) < 0)
123 assert(0 && "runner wait");
124 }
125 }
126
127 static struct ivi_application *
get_ivi_application(struct client * client)128 get_ivi_application(struct client *client)
129 {
130 struct global *g;
131 struct global *global_iviapp = NULL;
132 struct ivi_application *iviapp;
133
134 wl_list_for_each(g, &client->global_list, link) {
135 if (strcmp(g->interface, "ivi_application"))
136 continue;
137
138 if (global_iviapp)
139 assert(0 && "multiple ivi_application objects");
140
141 global_iviapp = g;
142 }
143
144 assert(global_iviapp && "no ivi_application found");
145
146 assert(global_iviapp->version == 1);
147
148 iviapp = wl_registry_bind(client->wl_registry, global_iviapp->name,
149 &ivi_application_interface, 1);
150 assert(iviapp);
151
152 return iviapp;
153 }
154
155 struct ivi_window {
156 struct wl_surface *wl_surface;
157 struct ivi_surface *ivi_surface;
158 uint32_t ivi_id;
159 };
160
161 static struct ivi_window *
client_create_ivi_window(struct client * client,struct ivi_application * iviapp,uint32_t ivi_id)162 client_create_ivi_window(struct client *client,
163 struct ivi_application *iviapp,
164 uint32_t ivi_id)
165 {
166 struct ivi_window *wnd;
167
168 wnd = xzalloc(sizeof(*wnd));
169 wnd->wl_surface = wl_compositor_create_surface(client->wl_compositor);
170 wnd->ivi_surface = ivi_application_surface_create(iviapp, ivi_id,
171 wnd->wl_surface);
172 wnd->ivi_id = ivi_id;
173
174 return wnd;
175 }
176
177 static void
ivi_window_destroy(struct ivi_window * wnd)178 ivi_window_destroy(struct ivi_window *wnd)
179 {
180 ivi_surface_destroy(wnd->ivi_surface);
181 wl_surface_destroy(wnd->wl_surface);
182 free(wnd);
183 }
184
185 /******************************** tests ********************************/
186
187 /*
188 * These tests make use of weston_test_runner global interface exposed by
189 * ivi-layout-test-plugin.c. This allows these tests to trigger compositor-side
190 * checks.
191 *
192 * See ivi-layout-test-plugin.c for further details.
193 */
194
195 /**
196 * RUNNER_TEST() names are defined in ivi-layout-test-plugin.c.
197 * Each RUNNER_TEST name listed here uses the same simple initial client setup.
198 */
199 const char * const basic_test_names[] = {
200 "surface_visibility",
201 "surface_opacity",
202 "surface_dimension",
203 "surface_position",
204 "surface_destination_rectangle",
205 "surface_source_rectangle",
206 "surface_bad_opacity",
207 "surface_properties_changed_notification",
208 "surface_bad_properties_changed_notification",
209 "surface_on_many_layer",
210 };
211
212 const char * const surface_property_commit_changes_test_names[] = {
213 "commit_changes_after_visibility_set_surface_destroy",
214 "commit_changes_after_opacity_set_surface_destroy",
215 "commit_changes_after_source_rectangle_set_surface_destroy",
216 "commit_changes_after_destination_rectangle_set_surface_destroy",
217 };
218
219 const char * const render_order_test_names[] = {
220 "layer_render_order",
221 "layer_bad_render_order",
222 "layer_add_surfaces",
223 };
224
TEST_P(ivi_layout_runner,basic_test_names)225 TEST_P(ivi_layout_runner, basic_test_names)
226 {
227 /* an element from basic_test_names */
228 const char * const *test_name = data;
229 struct client *client;
230 struct runner *runner;
231 struct ivi_application *iviapp;
232 struct ivi_window *wnd;
233
234 client = create_client();
235 runner = client_create_runner(client);
236 iviapp = get_ivi_application(client);
237
238 wnd = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
239
240 runner_run(runner, *test_name);
241
242 ivi_window_destroy(wnd);
243 runner_destroy(runner);
244 }
245
TEST(ivi_layout_surface_create)246 TEST(ivi_layout_surface_create)
247 {
248 struct client *client;
249 struct runner *runner;
250 struct ivi_application *iviapp;
251 struct ivi_window *winds[2];
252
253 client = create_client();
254 runner = client_create_runner(client);
255 iviapp = get_ivi_application(client);
256
257 winds[0] = client_create_ivi_window(client, iviapp,
258 IVI_TEST_SURFACE_ID(0));
259 winds[1] = client_create_ivi_window(client, iviapp,
260 IVI_TEST_SURFACE_ID(1));
261
262 runner_run(runner, "surface_create_p1");
263
264 ivi_window_destroy(winds[0]);
265
266 runner_run(runner, "surface_create_p2");
267
268 ivi_window_destroy(winds[1]);
269 runner_destroy(runner);
270 }
271
TEST_P(commit_changes_after_properties_set_surface_destroy,surface_property_commit_changes_test_names)272 TEST_P(commit_changes_after_properties_set_surface_destroy, surface_property_commit_changes_test_names)
273 {
274 /* an element from surface_property_commit_changes_test_names */
275 const char * const *test_name = data;
276 struct client *client;
277 struct runner *runner;
278 struct ivi_application *iviapp;
279 struct ivi_window *wnd;
280
281 client = create_client();
282 runner = client_create_runner(client);
283 iviapp = get_ivi_application(client);
284
285 wnd = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
286
287 runner_run(runner, *test_name);
288
289 ivi_window_destroy(wnd);
290
291 runner_run(runner, "ivi_layout_commit_changes");
292
293 runner_destroy(runner);
294 }
295
TEST(get_surface_after_destroy_ivi_surface)296 TEST(get_surface_after_destroy_ivi_surface)
297 {
298 struct client *client;
299 struct runner *runner;
300 struct ivi_application *iviapp;
301 struct ivi_window *wnd;
302
303 client = create_client();
304 runner = client_create_runner(client);
305 iviapp = get_ivi_application(client);
306
307 wnd = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
308
309 ivi_surface_destroy(wnd->ivi_surface);
310
311 runner_run(runner, "get_surface_after_destroy_surface");
312
313 wl_surface_destroy(wnd->wl_surface);
314 free(wnd);
315 runner_destroy(runner);
316 }
317
TEST(get_surface_after_destroy_wl_surface)318 TEST(get_surface_after_destroy_wl_surface)
319 {
320 struct client *client;
321 struct runner *runner;
322 struct ivi_application *iviapp;
323 struct ivi_window *wnd;
324
325 client = create_client();
326 runner = client_create_runner(client);
327 iviapp = get_ivi_application(client);
328
329 wnd = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
330
331 wl_surface_destroy(wnd->wl_surface);
332
333 runner_run(runner, "get_surface_after_destroy_surface");
334
335 ivi_surface_destroy(wnd->ivi_surface);
336 free(wnd);
337 runner_destroy(runner);
338 }
339
TEST_P(ivi_layout_layer_render_order_runner,render_order_test_names)340 TEST_P(ivi_layout_layer_render_order_runner, render_order_test_names)
341 {
342 /* an element from render_order_test_names */
343 const char * const *test_name = data;
344 struct client *client;
345 struct runner *runner;
346 struct ivi_application *iviapp;
347 struct ivi_window *winds[3];
348
349 client = create_client();
350 runner = client_create_runner(client);
351 iviapp = get_ivi_application(client);
352
353 winds[0] = client_create_ivi_window(client, iviapp,
354 IVI_TEST_SURFACE_ID(0));
355 winds[1] = client_create_ivi_window(client, iviapp,
356 IVI_TEST_SURFACE_ID(1));
357 winds[2] = client_create_ivi_window(client, iviapp,
358 IVI_TEST_SURFACE_ID(2));
359
360 runner_run(runner, *test_name);
361
362 ivi_window_destroy(winds[0]);
363 ivi_window_destroy(winds[1]);
364 ivi_window_destroy(winds[2]);
365 runner_destroy(runner);
366 }
367
TEST(destroy_surface_after_layer_render_order)368 TEST(destroy_surface_after_layer_render_order)
369 {
370 struct client *client;
371 struct runner *runner;
372 struct ivi_application *iviapp;
373 struct ivi_window *winds[3];
374
375 client = create_client();
376 runner = client_create_runner(client);
377 iviapp = get_ivi_application(client);
378
379 winds[0] = client_create_ivi_window(client, iviapp,
380 IVI_TEST_SURFACE_ID(0));
381 winds[1] = client_create_ivi_window(client, iviapp,
382 IVI_TEST_SURFACE_ID(1));
383 winds[2] = client_create_ivi_window(client, iviapp,
384 IVI_TEST_SURFACE_ID(2));
385
386 runner_run(runner, "test_layer_render_order_destroy_one_surface_p1");
387
388 ivi_window_destroy(winds[1]);
389
390 runner_run(runner, "test_layer_render_order_destroy_one_surface_p2");
391
392 ivi_window_destroy(winds[0]);
393 ivi_window_destroy(winds[2]);
394 runner_destroy(runner);
395 }
396
TEST(commit_changes_after_render_order_set_surface_destroy)397 TEST(commit_changes_after_render_order_set_surface_destroy)
398 {
399 struct client *client;
400 struct runner *runner;
401 struct ivi_application *iviapp;
402 struct ivi_window *winds[3];
403
404 client = create_client();
405 runner = client_create_runner(client);
406 iviapp = get_ivi_application(client);
407
408 winds[0] = client_create_ivi_window(client, iviapp,
409 IVI_TEST_SURFACE_ID(0));
410 winds[1] = client_create_ivi_window(client, iviapp,
411 IVI_TEST_SURFACE_ID(1));
412 winds[2] = client_create_ivi_window(client, iviapp,
413 IVI_TEST_SURFACE_ID(2));
414
415 runner_run(runner, "commit_changes_after_render_order_set_surface_destroy");
416
417 ivi_window_destroy(winds[1]);
418
419 runner_run(runner, "ivi_layout_commit_changes");
420 runner_run(runner, "cleanup_layer");
421
422 ivi_window_destroy(winds[0]);
423 ivi_window_destroy(winds[2]);
424 runner_destroy(runner);
425 }
426
TEST(ivi_layout_surface_configure_notification)427 TEST(ivi_layout_surface_configure_notification)
428 {
429 struct client *client;
430 struct runner *runner;
431 struct ivi_application *iviapp;
432 struct ivi_window *wind;
433 struct buffer *buffer;
434
435 client = create_client();
436 runner = client_create_runner(client);
437 iviapp = get_ivi_application(client);
438
439 runner_run(runner, "surface_configure_notification_p1");
440
441 wind = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
442
443 buffer = create_shm_buffer_a8r8g8b8(client, 200, 300);
444
445 wl_surface_attach(wind->wl_surface, buffer->proxy, 0, 0);
446 wl_surface_damage(wind->wl_surface, 0, 0, 20, 30);
447 wl_surface_commit(wind->wl_surface);
448
449 runner_run(runner, "surface_configure_notification_p2");
450
451 wl_surface_attach(wind->wl_surface, buffer->proxy, 0, 0);
452 wl_surface_damage(wind->wl_surface, 0, 0, 40, 50);
453 wl_surface_commit(wind->wl_surface);
454
455 runner_run(runner, "surface_configure_notification_p3");
456
457 buffer_destroy(buffer);
458 ivi_window_destroy(wind);
459 runner_destroy(runner);
460 }
461
TEST(ivi_layout_surface_create_notification)462 TEST(ivi_layout_surface_create_notification)
463 {
464 struct client *client;
465 struct runner *runner;
466 struct ivi_application *iviapp;
467 struct ivi_window *wind;
468
469 client = create_client();
470 runner = client_create_runner(client);
471 iviapp = get_ivi_application(client);
472
473 runner_run(runner, "surface_create_notification_p1");
474
475 wind = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
476
477 runner_run(runner, "surface_create_notification_p2");
478
479 ivi_window_destroy(wind);
480 wind = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
481 runner_run(runner, "surface_create_notification_p3");
482
483 ivi_window_destroy(wind);
484 runner_destroy(runner);
485 }
486
TEST(ivi_layout_surface_remove_notification)487 TEST(ivi_layout_surface_remove_notification)
488 {
489 struct client *client;
490 struct runner *runner;
491 struct ivi_application *iviapp;
492 struct ivi_window *wind;
493
494 client = create_client();
495 runner = client_create_runner(client);
496 iviapp = get_ivi_application(client);
497
498 wind = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
499 runner_run(runner, "surface_remove_notification_p1");
500 ivi_window_destroy(wind);
501
502 runner_run(runner, "surface_remove_notification_p2");
503
504 wind = client_create_ivi_window(client, iviapp, IVI_TEST_SURFACE_ID(0));
505 ivi_window_destroy(wind);
506 runner_run(runner, "surface_remove_notification_p3");
507
508 runner_destroy(runner);
509 }
510