/* * Copyright © 2015 Collabora, Ltd. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "config.h" #include #include #include #include "shared/helpers.h" #include "shared/xalloc.h" #include "weston-test-client-helper.h" #include "ivi-application-client-protocol.h" #include "ivi-test.h" struct runner { struct client *client; struct weston_test_runner *test_runner; int done; }; static void runner_finished_handler(void *data, struct weston_test_runner *test_runner) { struct runner *runner = data; runner->done = 1; } static const struct weston_test_runner_listener test_runner_listener = { runner_finished_handler }; static struct runner * client_create_runner(struct client *client) { struct runner *runner; struct global *g; struct global *global_runner = NULL; runner = xzalloc(sizeof(*runner)); runner->client = client; wl_list_for_each(g, &client->global_list, link) { if (strcmp(g->interface, "weston_test_runner")) continue; if (global_runner) assert(0 && "multiple weston_test_runner objects"); global_runner = g; } assert(global_runner && "no weston_test_runner found"); assert(global_runner->version == 1); runner->test_runner = wl_registry_bind(client->wl_registry, global_runner->name, &weston_test_runner_interface, 1); assert(runner->test_runner); weston_test_runner_add_listener(runner->test_runner, &test_runner_listener, runner); return runner; } static void runner_destroy(struct runner *runner) { weston_test_runner_destroy(runner->test_runner); client_roundtrip(runner->client); free(runner); } static void runner_run(struct runner *runner, const char *test_name) { fprintf(stderr, "weston_test_runner.run(\"%s\")\n", test_name); runner->done = 0; weston_test_runner_run(runner->test_runner, test_name); while (!runner->done) { if (wl_display_dispatch(runner->client->wl_display) < 0) assert(0 && "runner wait"); } } static struct ivi_application * get_ivi_application(struct client *client) { struct global *g; struct global *global_iviapp = NULL; static struct ivi_application *iviapp; if (iviapp) return iviapp; wl_list_for_each(g, &client->global_list, link) { if (strcmp(g->interface, "ivi_application")) continue; if (global_iviapp) assert(0 && "multiple ivi_application objects"); global_iviapp = g; } assert(global_iviapp && "no ivi_application found"); assert(global_iviapp->version == 1); iviapp = wl_registry_bind(client->wl_registry, global_iviapp->name, &ivi_application_interface, 1); assert(iviapp); return iviapp; } struct ivi_window { struct wl_surface *wl_surface; struct ivi_surface *ivi_surface; uint32_t ivi_id; }; static struct ivi_window * client_create_ivi_window(struct client *client, uint32_t ivi_id) { struct ivi_application *iviapp; struct ivi_window *wnd; iviapp = get_ivi_application(client); wnd = xzalloc(sizeof(*wnd)); wnd->wl_surface = wl_compositor_create_surface(client->wl_compositor); wnd->ivi_surface = ivi_application_surface_create(iviapp, ivi_id, wnd->wl_surface); wnd->ivi_id = ivi_id; return wnd; } static void ivi_window_destroy(struct ivi_window *wnd) { ivi_surface_destroy(wnd->ivi_surface); wl_surface_destroy(wnd->wl_surface); free(wnd); } /******************************** tests ********************************/ /* * This is a test program, launched by ivi_layout-test-plugin.c. Each TEST() * is forked and exec'd as usual with the weston-test-runner framework. * * These tests make use of weston_test_runner global interface exposed by * ivi_layout-test-plugin.c. This allows these tests to trigger compositor-side * checks. * * See ivi_layout-test-plugin.c for further details. */ /** * RUNNER_TEST() names are defined in ivi_layout-test-plugin.c. * Each RUNNER_TEST name listed here uses the same simple initial client setup. */ const char * const basic_test_names[] = { "surface_visibility", "surface_opacity", "surface_dimension", "surface_position", "surface_destination_rectangle", "surface_source_rectangle", "surface_bad_opacity", "surface_properties_changed_notification", "surface_bad_properties_changed_notification", "surface_on_many_layer", }; const char * const surface_property_commit_changes_test_names[] = { "commit_changes_after_visibility_set_surface_destroy", "commit_changes_after_opacity_set_surface_destroy", "commit_changes_after_source_rectangle_set_surface_destroy", "commit_changes_after_destination_rectangle_set_surface_destroy", }; const char * const render_order_test_names[] = { "layer_render_order", "layer_bad_render_order", "layer_add_surfaces", }; TEST_P(ivi_layout_runner, basic_test_names) { /* an element from basic_test_names */ const char * const *test_name = data; struct client *client; struct runner *runner; struct ivi_window *wnd; client = create_client(); runner = client_create_runner(client); wnd = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); runner_run(runner, *test_name); ivi_window_destroy(wnd); runner_destroy(runner); } TEST(ivi_layout_surface_create) { struct client *client; struct runner *runner; struct ivi_window *winds[2]; client = create_client(); runner = client_create_runner(client); winds[0] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); winds[1] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(1)); runner_run(runner, "surface_create_p1"); ivi_window_destroy(winds[0]); runner_run(runner, "surface_create_p2"); ivi_window_destroy(winds[1]); runner_destroy(runner); } TEST_P(commit_changes_after_properties_set_surface_destroy, surface_property_commit_changes_test_names) { /* an element from surface_property_commit_changes_test_names */ const char * const *test_name = data; struct client *client; struct runner *runner; struct ivi_window *wnd; client = create_client(); runner = client_create_runner(client); wnd = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); runner_run(runner, *test_name); ivi_window_destroy(wnd); runner_run(runner, "ivi_layout_commit_changes"); runner_destroy(runner); } TEST(get_surface_after_destroy_ivi_surface) { struct client *client; struct runner *runner; struct ivi_window *wnd; client = create_client(); runner = client_create_runner(client); wnd = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); ivi_surface_destroy(wnd->ivi_surface); runner_run(runner, "get_surface_after_destroy_surface"); wl_surface_destroy(wnd->wl_surface); free(wnd); runner_destroy(runner); } TEST(get_surface_after_destroy_wl_surface) { struct client *client; struct runner *runner; struct ivi_window *wnd; client = create_client(); runner = client_create_runner(client); wnd = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); wl_surface_destroy(wnd->wl_surface); runner_run(runner, "get_surface_after_destroy_surface"); ivi_surface_destroy(wnd->ivi_surface); free(wnd); runner_destroy(runner); } TEST_P(ivi_layout_layer_render_order_runner, render_order_test_names) { /* an element from render_order_test_names */ const char * const *test_name = data; struct client *client; struct runner *runner; struct ivi_window *winds[3]; client = create_client(); runner = client_create_runner(client); winds[0] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); winds[1] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(1)); winds[2] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(2)); runner_run(runner, *test_name); ivi_window_destroy(winds[0]); ivi_window_destroy(winds[1]); ivi_window_destroy(winds[2]); runner_destroy(runner); } TEST(destroy_surface_after_layer_render_order) { struct client *client; struct runner *runner; struct ivi_window *winds[3]; client = create_client(); runner = client_create_runner(client); winds[0] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); winds[1] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(1)); winds[2] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(2)); runner_run(runner, "test_layer_render_order_destroy_one_surface_p1"); ivi_window_destroy(winds[1]); runner_run(runner, "test_layer_render_order_destroy_one_surface_p2"); ivi_window_destroy(winds[0]); ivi_window_destroy(winds[2]); runner_destroy(runner); } TEST(commit_changes_after_render_order_set_surface_destroy) { struct client *client; struct runner *runner; struct ivi_window *winds[3]; client = create_client(); runner = client_create_runner(client); winds[0] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); winds[1] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(1)); winds[2] = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(2)); runner_run(runner, "commit_changes_after_render_order_set_surface_destroy"); ivi_window_destroy(winds[1]); runner_run(runner, "ivi_layout_commit_changes"); runner_run(runner, "cleanup_layer"); ivi_window_destroy(winds[0]); ivi_window_destroy(winds[2]); runner_destroy(runner); } TEST(ivi_layout_surface_configure_notification) { struct client *client; struct runner *runner; struct ivi_window *wind; struct buffer *buffer; client = create_client(); runner = client_create_runner(client); runner_run(runner, "surface_configure_notification_p1"); wind = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); buffer = create_shm_buffer_a8r8g8b8(client, 200, 300); wl_surface_attach(wind->wl_surface, buffer->proxy, 0, 0); wl_surface_damage(wind->wl_surface, 0, 0, 20, 30); wl_surface_commit(wind->wl_surface); runner_run(runner, "surface_configure_notification_p2"); wl_surface_attach(wind->wl_surface, buffer->proxy, 0, 0); wl_surface_damage(wind->wl_surface, 0, 0, 40, 50); wl_surface_commit(wind->wl_surface); runner_run(runner, "surface_configure_notification_p3"); buffer_destroy(buffer); ivi_window_destroy(wind); runner_destroy(runner); } TEST(ivi_layout_surface_create_notification) { struct client *client; struct runner *runner; struct ivi_window *wind; client = create_client(); runner = client_create_runner(client); runner_run(runner, "surface_create_notification_p1"); wind = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); runner_run(runner, "surface_create_notification_p2"); ivi_window_destroy(wind); wind = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); runner_run(runner, "surface_create_notification_p3"); ivi_window_destroy(wind); runner_destroy(runner); } TEST(ivi_layout_surface_remove_notification) { struct client *client; struct runner *runner; struct ivi_window *wind; client = create_client(); runner = client_create_runner(client); wind = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); runner_run(runner, "surface_remove_notification_p1"); ivi_window_destroy(wind); runner_run(runner, "surface_remove_notification_p2"); wind = client_create_ivi_window(client, IVI_TEST_SURFACE_ID(0)); ivi_window_destroy(wind); runner_run(runner, "surface_remove_notification_p3"); runner_destroy(runner); }