diff --git a/configure.ac b/configure.ac index d626f727..d553eaea 100644 --- a/configure.ac +++ b/configure.ac @@ -62,6 +62,12 @@ if test x$enable_xwayland = xyes; then AC_SUBST([XSERVER_PATH]) fi +AC_ARG_ENABLE(xwayland-test, [ --enable-xwayland-test],, + enable_xwayland_test=yes) +AM_CONDITIONAL(ENABLE_XWAYLAND_TEST, test x$enable_xwayland_test = xyes) +if test x$enable_xwayland_test = xyes; then + PKG_CHECK_MODULES([XWAYLAND_TEST], xcb xcb-dri2 libdrm) +fi AC_ARG_ENABLE(x11-compositor, [ --enable-x11-compositor],, enable_x11_compositor=yes) diff --git a/tests/.gitignore b/tests/.gitignore index d8086a9b..05bc024e 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -10,3 +10,4 @@ text-test keyboard-test event-test button-test +xwayland-test diff --git a/tests/Makefile.am b/tests/Makefile.am index 7d6b6e04..11cd4ecd 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -8,7 +8,8 @@ weston_tests = \ keyboard-test \ event-test \ button-test \ - text-test + text-test \ + $(xwayland_test) TESTS_ENVIRONMENT = $(SHELL) $(top_srcdir)/tests/weston-tests-env @@ -74,6 +75,14 @@ text_test_SOURCES = \ $(weston_test_client_src) text_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 +xwayland_test = xwayland_test +endif + matrix_test_SOURCES = \ matrix-test.c \ $(top_srcdir)/shared/matrix.c \ diff --git a/tests/weston-tests-env b/tests/weston-tests-env index dae1cda4..159709eb 100755 --- a/tests/weston-tests-env +++ b/tests/weston-tests-env @@ -21,7 +21,7 @@ fi case $1 in *.la|*.so) $WESTON --backend=$BACKEND \ - --modules=$abs_builddir/.libs/${1/.la/.so} \ + --modules=$abs_builddir/.libs/${1/.la/.so},xwayland.so \ --log="$SERVERLOG" \ &> "$OUTLOG" ;; @@ -29,6 +29,6 @@ case $1 in WESTON_TEST_CLIENT_PATH=$abs_builddir/$1 $WESTON \ --backend=$BACKEND \ --log="$SERVERLOG" \ - --modules=$abs_builddir/.libs/weston-test.so \ + --modules=$abs_builddir/.libs/weston-test.so,xwayland.so \ &> "$OUTLOG" esac diff --git a/tests/xwayland-test.c b/tests/xwayland-test.c new file mode 100644 index 00000000..658453f3 --- /dev/null +++ b/tests/xwayland-test.c @@ -0,0 +1,142 @@ +/* + * Copyright © 2013 Intel Corporation + * + * 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. + * + * Author: Tiago Vignatti + * + * xwayland-test: the idea is to guarantee that XWayland infrastructure in + * general works with Weston. + */ + +#include "weston-test-runner.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static int +dri2_open(xcb_connection_t *c, xcb_screen_t *screen) +{ + xcb_dri2_connect_cookie_t cookie; + xcb_dri2_connect_reply_t *reply; + xcb_dri2_authenticate_cookie_t cookie_auth; + xcb_dri2_authenticate_reply_t *reply_auth; + char *driver, *device; + int fd; + drm_magic_t magic; + + cookie = xcb_dri2_connect(c, screen->root, XCB_DRI2_DRIVER_TYPE_DRI); + reply = xcb_dri2_connect_reply(c, cookie, 0); + assert(reply); + + driver = strndup(xcb_dri2_connect_driver_name (reply), + xcb_dri2_connect_driver_name_length (reply)); + device = strndup(xcb_dri2_connect_device_name (reply), + xcb_dri2_connect_device_name_length (reply)); + + fd = open(device, O_RDWR); + printf ("Trying connect to %s driver on %s\n", driver, device); + free(driver); + free(device); + + if (fd < 0) + return -1; + + drmGetMagic(fd, &magic); + + cookie_auth = xcb_dri2_authenticate(c, screen->root, magic); + reply_auth = xcb_dri2_authenticate_reply(c, cookie_auth, 0); + assert(reply_auth); + + return fd; +} + +static int +create_window(void) +{ + xcb_connection_t *c; + xcb_screen_t *screen; + xcb_window_t win; + int fd; + + c = xcb_connect (NULL, NULL); + if (c == NULL) { + printf("failed to get X11 connection\n"); + return -1; + } + + screen = xcb_setup_roots_iterator(xcb_get_setup(c)).data; + + win = xcb_generate_id(c); + xcb_create_window(c, XCB_COPY_FROM_PARENT, win, screen->root, + 0, 0, 150, 150, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, 0, NULL); + + xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, + XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, + 5, "title"); + xcb_map_window(c, win); + xcb_flush(c); + + fd = dri2_open(c, screen); + if (fd < 0) + return -1; + + xcb_destroy_window(c, win); + xcb_disconnect(c); + return 0; +} + +/* + * Ideally, the X Window Manager (XWM) and Weston Wayland compositor shouldn't + * be in the same process because they are using two different protocol + * streams in which one does not interface with the other. Probably the + * biggest problem with such architecture are the potentials dead locks that + * it may occur. So hypothetically, an X client might issue an X11 blocking + * request via X (DRI2Authenticate) which in turn sends a Wayland blocking + * request for Weston process it. X is blocked. At the same time, XWM might be + * trying to process an XChangeProperty, so it requests a blocking X11 call to + * the X server (xcb_get_property_reply -> xcb_wait_for_reply) which therefore + * will blocks there. It's a deadlock situation and this test is trying to + * catch that. + */ +static void +check_dri2_authenticate(void) +{ + int i, num_tests; + + /* TODO: explain why num_tests times */ + num_tests = 10; + for (i = 0; i < num_tests; i++) + assert(create_window() == 0); +} + +TEST(xwayland_client_test) +{ + check_dri2_authenticate(); + exit(EXIT_SUCCESS); +}