blob: c39a714439bcd9dc7f3825ff74773896fea8bd1d [file] [log] [blame]
Pekka Paalanenf5b74f72015-03-25 12:50:31 +02001/*
2 * Copyright © 2012 Intel Corporation
3 * Copyright © 2013 DENSO CORPORATION
4 * Copyright © 2015 Collabora, Ltd.
5 *
Bryce Harrington2cc92972015-06-11 15:39:40 -07006 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
Pekka Paalanenf5b74f72015-03-25 12:50:31 +020013 *
Bryce Harrington2cc92972015-06-11 15:39:40 -070014 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
Pekka Paalanenf5b74f72015-03-25 12:50:31 +020026 */
27
28#include "config.h"
29
30#include <unistd.h>
31#include <signal.h>
32#include <string.h>
33
Jon Cruz4678bab2015-06-15 15:37:07 -070034#include "src/compositor.h"
Pekka Paalanenf5b74f72015-03-25 12:50:31 +020035#include "weston-test-server-protocol.h"
36#include "ivi-test.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070037#include "ivi-shell/ivi-layout-export.h"
Pekka Paalanenf5b74f72015-03-25 12:50:31 +020038
39struct test_context;
40
41struct runner_test {
42 const char *name;
43 void (*run)(struct test_context *);
44} __attribute__ ((aligned (32)));
45
46#define RUNNER_TEST(name) \
47 static void runner_func_##name(struct test_context *); \
48 \
49 const struct runner_test runner_test_##name \
50 __attribute__ ((section ("test_section"))) = \
51 { \
52 #name, runner_func_##name \
53 }; \
54 \
55 static void runner_func_##name(struct test_context *ctx)
56
57extern const struct runner_test __start_test_section;
58extern const struct runner_test __stop_test_section;
59
60static const struct runner_test *
61find_runner_test(const char *name)
62{
63 const struct runner_test *t;
64
65 for (t = &__start_test_section; t < &__stop_test_section; t++) {
66 if (strcmp(t->name, name) == 0)
67 return t;
68 }
69
70 return NULL;
71}
72
73struct test_launcher {
74 struct weston_compositor *compositor;
75 char exe[2048];
76 struct weston_process process;
77 const struct ivi_controller_interface *controller_interface;
78};
79
80static void
81runner_destroy_handler(struct wl_client *client, struct wl_resource *resource)
82{
83 wl_resource_destroy(resource);
84}
85
86struct test_context {
87 const struct ivi_controller_interface *controller_interface;
88 struct wl_resource *runner_resource;
89};
90
91static void
92runner_run_handler(struct wl_client *client, struct wl_resource *resource,
93 const char *test_name)
94{
95 struct test_launcher *launcher;
96 const struct runner_test *t;
97 struct test_context ctx;
98
99 launcher = wl_resource_get_user_data(resource);
100 ctx.controller_interface = launcher->controller_interface;
101 ctx.runner_resource = resource;
102
103 t = find_runner_test(test_name);
104 if (!t) {
105 weston_log("Error: runner test \"%s\" not found.\n",
106 test_name);
107 wl_resource_post_error(resource,
108 WESTON_TEST_RUNNER_ERROR_UNKNOWN_TEST,
109 "weston_test_runner: unknown: '%s'",
110 test_name);
111 return;
112 }
113
114 weston_log("weston_test_runner.run(\"%s\")\n", test_name);
115
116 t->run(&ctx);
117
118 weston_test_runner_send_finished(resource);
119}
120
121static const struct weston_test_runner_interface runner_implementation = {
122 runner_destroy_handler,
123 runner_run_handler
124};
125
126static void
127bind_runner(struct wl_client *client, void *data,
128 uint32_t version, uint32_t id)
129{
130 struct test_launcher *launcher = data;
131 struct wl_resource *resource;
132
133 resource = wl_resource_create(client, &weston_test_runner_interface,
134 1, id);
135 if (!resource) {
136 wl_client_post_no_memory(client);
137 return;
138 }
139
140 wl_resource_set_implementation(resource, &runner_implementation,
141 launcher, NULL);
142}
143
144static void
145test_client_sigchld(struct weston_process *process, int status)
146{
147 struct test_launcher *launcher =
148 container_of(process, struct test_launcher, process);
149 struct weston_compositor *c = launcher->compositor;
150
151 /* Chain up from weston-test-runner's exit code so that automake
152 * knows the exit status and can report e.g. skipped tests. */
153 if (WIFEXITED(status))
154 weston_compositor_exit_with_code(c, WEXITSTATUS(status));
155 else
156 weston_compositor_exit_with_code(c, EXIT_FAILURE);
157}
158
159static void
160idle_launch_client(void *data)
161{
162 struct test_launcher *launcher = data;
163 pid_t pid;
164 sigset_t allsigs;
165
166 pid = fork();
167 if (pid == -1) {
168 weston_log("fatal: failed to fork '%s': %m\n", launcher->exe);
169 weston_compositor_exit_with_code(launcher->compositor,
170 EXIT_FAILURE);
171 return;
172 }
173
174 if (pid == 0) {
175 sigfillset(&allsigs);
176 sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
177 execl(launcher->exe, launcher->exe, NULL);
178 weston_log("compositor: executing '%s' failed: %m\n",
179 launcher->exe);
180 _exit(EXIT_FAILURE);
181 }
182
183 launcher->process.pid = pid;
184 launcher->process.cleanup = test_client_sigchld;
185 weston_watch_process(&launcher->process);
186}
187
188int
189controller_module_init(struct weston_compositor *compositor,
190 int *argc, char *argv[],
191 const struct ivi_controller_interface *iface,
192 size_t iface_version);
193
194WL_EXPORT int
195controller_module_init(struct weston_compositor *compositor,
196 int *argc, char *argv[],
197 const struct ivi_controller_interface *iface,
198 size_t iface_version)
199{
200 struct wl_event_loop *loop;
201 struct test_launcher *launcher;
202 const char *path;
203
204 /* strict check, since this is an internal test module */
205 if (iface_version != sizeof(*iface)) {
206 weston_log("fatal: controller interface mismatch\n");
207 return -1;
208 }
209
210 path = getenv("WESTON_BUILD_DIR");
211 if (!path) {
212 weston_log("test setup failure: WESTON_BUILD_DIR not set\n");
213 return -1;
214 }
215
216 launcher = zalloc(sizeof *launcher);
217 if (!launcher)
218 return -1;
219
220 launcher->compositor = compositor;
221 launcher->controller_interface = iface;
222 snprintf(launcher->exe, sizeof launcher->exe,
223 "%s/ivi-layout.ivi", path);
224
225 if (wl_global_create(compositor->wl_display,
226 &weston_test_runner_interface, 1,
227 launcher, bind_runner) == NULL)
228 return -1;
229
230 loop = wl_display_get_event_loop(compositor->wl_display);
231 wl_event_loop_add_idle(loop, idle_launch_client, launcher);
232
233 return 0;
234}
235
236static void
237runner_assert_fail(const char *cond, const char *file, int line,
238 const char *func, struct test_context *ctx)
239{
240 weston_log("Assert failure in %s:%d, %s: '%s'\n",
241 file, line, func, cond);
242 wl_resource_post_error(ctx->runner_resource,
243 WESTON_TEST_RUNNER_ERROR_TEST_FAILED,
244 "Assert failure in %s:%d, %s: '%s'\n",
245 file, line, func, cond);
246}
247
248#define runner_assert(cond) ({ \
249 bool b_ = (cond); \
250 if (!b_) \
251 runner_assert_fail(#cond, __FILE__, __LINE__, \
252 __func__, ctx); \
253 b_; \
254})
255
256#define runner_assert_or_return(cond) do { \
257 bool b_ = (cond); \
258 if (!b_) { \
259 runner_assert_fail(#cond, __FILE__, __LINE__, \
260 __func__, ctx); \
261 return; \
262 } \
263} while (0)
264
265
266/*************************** tests **********************************/
267
268/*
269 * This is a controller module: a plugin to ivi-shell.so, i.e. a sub-plugin.
270 * This module is specially written to execute tests that target the
271 * ivi_layout API.
272 *
273 * This module is listed in TESTS in Makefile.am. weston-tests-env handles
274 * this module specially by loading it in ivi-shell.
275 *
276 * Once Weston init completes, this module launches one test program:
277 * ivi-layout.ivi (ivi_layout-test.c). That program uses the weston-test-runner
278 * framework to fork and exec each TEST() in ivi_layout-test.c with a fresh
279 * connection to the single compositor instance.
280 *
281 * Each TEST() in ivi_layout-test.c will bind to weston_test_runner global
282 * interface. A TEST() will set up the client state, and issue
283 * weston_test_runner.run request to execute the compositor-side of the test.
284 *
285 * The compositor-side parts of the tests are in this file. They are specified
286 * by RUNNER_TEST() macro, where the name argument matches the name string
287 * passed to weston_test_runner.run.
288 *
289 * A RUNNER_TEST() function simply returns when it succeeds. If it fails,
290 * a fatal protocol error is sent to the client from runner_assert() or
291 * runner_assert_or_return(). This module catches the test program exit
292 * code and passes it out of Weston to the test harness.
293 *
294 * A single TEST() in ivi_layout-test.c may use multiple RUNNER_TEST()s to
295 * achieve multiple test points over a client action sequence.
296 */
297
298RUNNER_TEST(surface_create_p1)
299{
300 const struct ivi_controller_interface *ctl = ctx->controller_interface;
301 struct ivi_layout_surface *ivisurf[2];
302 uint32_t ivi_id;
303
304 ivisurf[0] = ctl->get_surface_from_id(IVI_TEST_SURFACE_ID(0));
305 runner_assert_or_return(ivisurf[0]);
306
307 ivisurf[1] = ctl->get_surface_from_id(IVI_TEST_SURFACE_ID(1));
308 runner_assert_or_return(ivisurf[1]);
309
310 ivi_id = ctl->get_id_of_surface(ivisurf[0]);
311 runner_assert_or_return(ivi_id == IVI_TEST_SURFACE_ID(0));
312
313 ivi_id = ctl->get_id_of_surface(ivisurf[1]);
314 runner_assert_or_return(ivi_id == IVI_TEST_SURFACE_ID(1));
315}
316
317RUNNER_TEST(surface_create_p2)
318{
319 const struct ivi_controller_interface *ctl = ctx->controller_interface;
320 struct ivi_layout_surface *ivisurf;
321
322 /* the ivi_surface was destroyed by the client */
323 ivisurf = ctl->get_surface_from_id(IVI_TEST_SURFACE_ID(0));
324 runner_assert_or_return(ivisurf == NULL);
325}
326
327RUNNER_TEST(surface_visibility)
328{
329 const struct ivi_controller_interface *ctl = ctx->controller_interface;
330 struct ivi_layout_surface *ivisurf;
331 int32_t ret;
332 bool visibility;
333 const struct ivi_layout_surface_properties *prop;
334
335 ivisurf = ctl->get_surface_from_id(IVI_TEST_SURFACE_ID(0));
336 runner_assert_or_return(ivisurf);
337
338 ret = ctl->surface_set_visibility(ivisurf, true);
339 runner_assert_or_return(ret == IVI_SUCCEEDED);
340
341 ctl->commit_changes();
342
343 visibility = ctl->surface_get_visibility(ivisurf);
344 runner_assert_or_return(visibility == true);
345
346 prop = ctl->get_properties_of_surface(ivisurf);
347 runner_assert_or_return(prop->visibility == true);
348}
349
350RUNNER_TEST(surface_opacity)
351{
352 const struct ivi_controller_interface *ctl = ctx->controller_interface;
353 struct ivi_layout_surface *ivisurf;
354 int32_t ret;
355 wl_fixed_t opacity;
356 const struct ivi_layout_surface_properties *prop;
357
358 ivisurf = ctl->get_surface_from_id(IVI_TEST_SURFACE_ID(0));
359 runner_assert_or_return(ivisurf);
360
361 ret = ctl->surface_set_opacity(ivisurf, wl_fixed_from_double(0.5));
362 runner_assert_or_return(ret == IVI_SUCCEEDED);
363
364 ctl->commit_changes();
365
366 opacity = ctl->surface_get_opacity(ivisurf);
367 runner_assert_or_return(opacity == wl_fixed_from_double(0.5));
368
369 prop = ctl->get_properties_of_surface(ivisurf);
370 runner_assert_or_return(prop->opacity == wl_fixed_from_double(0.5));
371}