Tiago Vignatti | 19dadf2 | 2013-02-08 14:57:00 +0200 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright © 2013 Intel Corporation |
| 3 | * |
| 4 | * Permission to use, copy, modify, distribute, and sell this software and |
| 5 | * its documentation for any purpose is hereby granted without fee, provided |
| 6 | * that the above copyright notice appear in all copies and that both that |
| 7 | * copyright notice and this permission notice appear in supporting |
| 8 | * documentation, and that the name of the copyright holders not be used in |
| 9 | * advertising or publicity pertaining to distribution of the software |
| 10 | * without specific, written prior permission. The copyright holders make |
| 11 | * no representations about the suitability of this software for any |
| 12 | * purpose. It is provided "as is" without express or implied warranty. |
| 13 | * |
| 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
| 15 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 16 | * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| 17 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER |
| 18 | * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
| 19 | * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
| 20 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 21 | * |
| 22 | * Author: Tiago Vignatti |
| 23 | * |
| 24 | * xwayland-test: the idea is to guarantee that XWayland infrastructure in |
| 25 | * general works with Weston. |
| 26 | */ |
| 27 | |
| 28 | #include "weston-test-runner.h" |
| 29 | |
| 30 | #include <assert.h> |
| 31 | #include <unistd.h> |
| 32 | #include <stdlib.h> |
| 33 | #include <stdio.h> |
| 34 | #include <fcntl.h> |
| 35 | #include <string.h> |
| 36 | #include <xcb/xcb.h> |
| 37 | #include <xcb/dri2.h> |
| 38 | #include <xf86drm.h> |
| 39 | |
| 40 | |
| 41 | static int |
| 42 | dri2_open(xcb_connection_t *c, xcb_screen_t *screen) |
| 43 | { |
| 44 | xcb_dri2_connect_cookie_t cookie; |
| 45 | xcb_dri2_connect_reply_t *reply; |
| 46 | xcb_dri2_authenticate_cookie_t cookie_auth; |
| 47 | xcb_dri2_authenticate_reply_t *reply_auth; |
| 48 | char *driver, *device; |
| 49 | int fd; |
| 50 | drm_magic_t magic; |
| 51 | |
| 52 | cookie = xcb_dri2_connect(c, screen->root, XCB_DRI2_DRIVER_TYPE_DRI); |
| 53 | reply = xcb_dri2_connect_reply(c, cookie, 0); |
| 54 | assert(reply); |
| 55 | |
| 56 | driver = strndup(xcb_dri2_connect_driver_name (reply), |
| 57 | xcb_dri2_connect_driver_name_length (reply)); |
| 58 | device = strndup(xcb_dri2_connect_device_name (reply), |
| 59 | xcb_dri2_connect_device_name_length (reply)); |
| 60 | |
| 61 | fd = open(device, O_RDWR); |
| 62 | printf ("Trying connect to %s driver on %s\n", driver, device); |
| 63 | free(driver); |
| 64 | free(device); |
| 65 | |
| 66 | if (fd < 0) |
| 67 | return -1; |
| 68 | |
| 69 | drmGetMagic(fd, &magic); |
| 70 | |
| 71 | cookie_auth = xcb_dri2_authenticate(c, screen->root, magic); |
| 72 | reply_auth = xcb_dri2_authenticate_reply(c, cookie_auth, 0); |
| 73 | assert(reply_auth); |
| 74 | |
| 75 | return fd; |
| 76 | } |
| 77 | |
| 78 | static int |
| 79 | create_window(void) |
| 80 | { |
| 81 | xcb_connection_t *c; |
| 82 | xcb_screen_t *screen; |
| 83 | xcb_window_t win; |
| 84 | int fd; |
| 85 | |
| 86 | c = xcb_connect (NULL, NULL); |
| 87 | if (c == NULL) { |
| 88 | printf("failed to get X11 connection\n"); |
| 89 | return -1; |
| 90 | } |
| 91 | |
| 92 | screen = xcb_setup_roots_iterator(xcb_get_setup(c)).data; |
| 93 | |
| 94 | win = xcb_generate_id(c); |
| 95 | xcb_create_window(c, XCB_COPY_FROM_PARENT, win, screen->root, |
| 96 | 0, 0, 150, 150, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, |
| 97 | screen->root_visual, 0, NULL); |
| 98 | |
| 99 | xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, |
| 100 | XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, |
| 101 | 5, "title"); |
| 102 | xcb_map_window(c, win); |
| 103 | xcb_flush(c); |
| 104 | |
| 105 | fd = dri2_open(c, screen); |
| 106 | if (fd < 0) |
| 107 | return -1; |
| 108 | |
| 109 | xcb_destroy_window(c, win); |
| 110 | xcb_disconnect(c); |
| 111 | return 0; |
| 112 | } |
| 113 | |
| 114 | /* |
| 115 | * Ideally, the X Window Manager (XWM) and Weston Wayland compositor shouldn't |
| 116 | * be in the same process because they are using two different protocol |
| 117 | * streams in which one does not interface with the other. Probably the |
| 118 | * biggest problem with such architecture are the potentials dead locks that |
| 119 | * it may occur. So hypothetically, an X client might issue an X11 blocking |
| 120 | * request via X (DRI2Authenticate) which in turn sends a Wayland blocking |
| 121 | * request for Weston process it. X is blocked. At the same time, XWM might be |
| 122 | * trying to process an XChangeProperty, so it requests a blocking X11 call to |
| 123 | * the X server (xcb_get_property_reply -> xcb_wait_for_reply) which therefore |
| 124 | * will blocks there. It's a deadlock situation and this test is trying to |
| 125 | * catch that. |
| 126 | */ |
| 127 | static void |
| 128 | check_dri2_authenticate(void) |
| 129 | { |
| 130 | int i, num_tests; |
| 131 | |
| 132 | /* TODO: explain why num_tests times */ |
| 133 | num_tests = 10; |
| 134 | for (i = 0; i < num_tests; i++) |
| 135 | assert(create_window() == 0); |
| 136 | } |
| 137 | |
| 138 | TEST(xwayland_client_test) |
| 139 | { |
| 140 | check_dri2_authenticate(); |
| 141 | exit(EXIT_SUCCESS); |
| 142 | } |