diff --git a/tests/.gitignore b/tests/.gitignore index fa19888c..fac1f7bd 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -13,3 +13,4 @@ button-test xwayland-test subsurface-client-protocol.h subsurface-protocol.c +subsurface-test diff --git a/tests/Makefile.am b/tests/Makefile.am index a42a1fcb..9f711cf6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -9,6 +9,7 @@ weston_tests = \ event-test \ button-test \ text-test \ + subsurface-test \ $(xwayland_test) AM_TESTS_ENVIRONMENT = \ @@ -86,8 +87,10 @@ text_test_SOURCES = \ $(weston_test_client_src) text_test_LDADD = $(weston_test_client_libs) -xwayland_test_SOURCES = xwayland-test.c $(weston_test_client_src) +subsurface_test_SOURCES = subsurface-test.c $(weston_test_client_src) +subsurface_test_LDADD = $(weston_test_client_libs) +xwayland_test_SOURCES = xwayland-test.c $(weston_test_client_src) xwayland_test_LDADD = $(weston_test_client_libs) $(XWAYLAND_TEST_LIBS) if ENABLE_XWAYLAND_TEST diff --git a/tests/subsurface-test.c b/tests/subsurface-test.c new file mode 100644 index 00000000..8f1fd143 --- /dev/null +++ b/tests/subsurface-test.c @@ -0,0 +1,325 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "weston-test-client-helper.h" +#include "subsurface-client-protocol.h" + +#define NUM_SUBSURFACES 3 + +struct compound_surface { + struct wl_subcompositor *subco; + struct wl_surface *parent; + struct wl_surface *child[NUM_SUBSURFACES]; + struct wl_subsurface *sub[NUM_SUBSURFACES]; +}; + +static struct wl_subcompositor * +get_subcompositor(struct client *client) +{ + struct global *g; + struct global *global_sub = NULL; + struct wl_subcompositor *sub; + + wl_list_for_each(g, &client->global_list, link) { + if (strcmp(g->interface, "wl_subcompositor")) + continue; + + if (global_sub) + assert(0 && "multiple wl_subcompositor objects"); + + global_sub = g; + } + + assert(global_sub && "no wl_subcompositor found"); + + assert(global_sub->version == 1); + + sub = wl_registry_bind(client->wl_registry, global_sub->name, + &wl_subcompositor_interface, 1); + assert(sub); + + return sub; +} + +static void +populate_compound_surface(struct compound_surface *com, struct client *client) +{ + int i; + + com->subco = get_subcompositor(client); + + com->parent = wl_compositor_create_surface(client->wl_compositor); + + for (i = 0; i < NUM_SUBSURFACES; i++) { + com->child[i] = + wl_compositor_create_surface(client->wl_compositor); + com->sub[i] = + wl_subcompositor_get_subsurface(com->subco, + com->child[i], + com->parent); + } +} + +TEST(test_subsurface_basic_protocol) +{ + struct client *client; + struct compound_surface com1; + struct compound_surface com2; + + client = client_create(100, 50, 123, 77); + assert(client); + + populate_compound_surface(&com1, client); + populate_compound_surface(&com2, client); + + client_roundtrip(client); +} + +TEST(test_subsurface_position_protocol) +{ + struct client *client; + struct compound_surface com; + int i; + + client = client_create(100, 50, 123, 77); + assert(client); + + populate_compound_surface(&com, client); + for (i = 0; i < NUM_SUBSURFACES; i++) + wl_subsurface_set_position(com.sub[i], + (i + 2) * 20, (i + 2) * 10); + + client_roundtrip(client); +} + +TEST(test_subsurface_placement_protocol) +{ + struct client *client; + struct compound_surface com; + + client = client_create(100, 50, 123, 77); + assert(client); + + populate_compound_surface(&com, client); + + wl_subsurface_place_above(com.sub[0], com.child[1]); + wl_subsurface_place_above(com.sub[1], com.parent); + wl_subsurface_place_below(com.sub[2], com.child[0]); + wl_subsurface_place_below(com.sub[1], com.parent); + + client_roundtrip(client); +} + +FAIL_TEST(test_subsurface_paradox) +{ + struct client *client; + struct wl_surface *parent; + struct wl_subcompositor *subco; + + client = client_create(100, 50, 123, 77); + assert(client); + + subco = get_subcompositor(client); + parent = wl_compositor_create_surface(client->wl_compositor); + + /* surface is its own parent */ + wl_subcompositor_get_subsurface(subco, parent, parent); + + client_roundtrip(client); +} + +FAIL_TEST(test_subsurface_identical_link) +{ + struct client *client; + struct compound_surface com; + + client = client_create(100, 50, 123, 77); + assert(client); + + populate_compound_surface(&com, client); + + /* surface is already a subsurface */ + wl_subcompositor_get_subsurface(com.subco, com.child[0], com.parent); + + client_roundtrip(client); +} + +FAIL_TEST(test_subsurface_change_link) +{ + struct client *client; + struct compound_surface com; + struct wl_surface *stranger; + + client = client_create(100, 50, 123, 77); + assert(client); + + stranger = wl_compositor_create_surface(client->wl_compositor); + populate_compound_surface(&com, client); + + /* surface is already a subsurface */ + wl_subcompositor_get_subsurface(com.subco, com.child[0], stranger); + + client_roundtrip(client); +} + +TEST(test_subsurface_nesting) +{ + struct client *client; + struct compound_surface com; + struct wl_surface *stranger; + + client = client_create(100, 50, 123, 77); + assert(client); + + stranger = wl_compositor_create_surface(client->wl_compositor); + populate_compound_surface(&com, client); + + /* parent is a sub-surface */ + wl_subcompositor_get_subsurface(com.subco, stranger, com.child[0]); + + client_roundtrip(client); +} + +TEST(test_subsurface_nesting_parent) +{ + struct client *client; + struct compound_surface com; + struct wl_surface *stranger; + + client = client_create(100, 50, 123, 77); + assert(client); + + stranger = wl_compositor_create_surface(client->wl_compositor); + populate_compound_surface(&com, client); + + /* surface is already a parent */ + wl_subcompositor_get_subsurface(com.subco, com.parent, stranger); + + client_roundtrip(client); +} + +FAIL_TEST(test_subsurface_place_above_stranger) +{ + struct client *client; + struct compound_surface com; + struct wl_surface *stranger; + + client = client_create(100, 50, 123, 77); + assert(client); + + stranger = wl_compositor_create_surface(client->wl_compositor); + populate_compound_surface(&com, client); + + /* bad sibling */ + wl_subsurface_place_above(com.sub[0], stranger); + + client_roundtrip(client); +} + +FAIL_TEST(test_subsurface_place_below_stranger) +{ + struct client *client; + struct compound_surface com; + struct wl_surface *stranger; + + client = client_create(100, 50, 123, 77); + assert(client); + + stranger = wl_compositor_create_surface(client->wl_compositor); + populate_compound_surface(&com, client); + + /* bad sibling */ + wl_subsurface_place_below(com.sub[0], stranger); + + client_roundtrip(client); +} + +FAIL_TEST(test_subsurface_place_above_foreign) +{ + struct client *client; + struct compound_surface com1; + struct compound_surface com2; + + client = client_create(100, 50, 123, 77); + assert(client); + + populate_compound_surface(&com1, client); + populate_compound_surface(&com2, client); + + /* bad sibling */ + wl_subsurface_place_above(com1.sub[0], com2.child[0]); + + client_roundtrip(client); +} + +FAIL_TEST(test_subsurface_place_below_foreign) +{ + struct client *client; + struct compound_surface com1; + struct compound_surface com2; + + client = client_create(100, 50, 123, 77); + assert(client); + + populate_compound_surface(&com1, client); + populate_compound_surface(&com2, client); + + /* bad sibling */ + wl_subsurface_place_below(com1.sub[0], com2.child[0]); + + client_roundtrip(client); +} + +TEST(test_subsurface_destroy_protocol) +{ + struct client *client; + struct compound_surface com; + + client = client_create(100, 50, 123, 77); + assert(client); + + populate_compound_surface(&com, client); + + /* not needed anymore */ + wl_subcompositor_destroy(com.subco); + + /* detach child from parent */ + wl_subsurface_destroy(com.sub[0]); + + /* destroy: child, parent */ + wl_surface_destroy(com.child[1]); + wl_surface_destroy(com.parent); + + /* destroy: parent, child */ + wl_surface_destroy(com.child[2]); + + /* destroy: sub, child */ + wl_surface_destroy(com.child[0]); + + /* 2x destroy: child, sub */ + wl_subsurface_destroy(com.sub[2]); + wl_subsurface_destroy(com.sub[1]); + + client_roundtrip(client); +}