Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright  2016 Klarlvdalens Datakonsult AB, a KDAB Group company, info (at) kdab.com
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining
      5  * a copy of this software and associated documentation files (the
      6  * "Software"), to deal in the Software without restriction, including
      7  * without limitation the rights to use, copy, modify, merge, publish,
      8  * distribute, sublicense, and/or sell copies of the Software, and to
      9  * permit persons to whom the Software is furnished to do so, subject to
     10  * the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the
     13  * next paragraph) shall be included in all copies or substantial
     14  * portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  */
     25 
     26 #include <stdlib.h>
     27 #include <assert.h>
     28 #include <errno.h>
     29 #include <string.h>
     30 #include <stdio.h>
     31 #include <sys/un.h>
     32 #include <unistd.h>
     33 
     34 #include "wayland-client.h"
     35 #include "wayland-server.h"
     36 #include "test-runner.h"
     37 
     38 /* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
     39 static const char *
     40 require_xdg_runtime_dir(void)
     41 {
     42 	char *val = getenv("XDG_RUNTIME_DIR");
     43 	assert(val && "set $XDG_RUNTIME_DIR to run this test");
     44 
     45 	return val;
     46 }
     47 
     48 struct compositor {
     49 	struct wl_display *display;
     50 	struct wl_listener listener;
     51 	struct wl_client *client;
     52 };
     53 
     54 static void
     55 client_created(struct wl_listener *listener, void *data)
     56 {
     57 	struct compositor *c = wl_container_of(listener, c, listener);
     58 	c->client = data;
     59 }
     60 
     61 static void
     62 check_client_list(struct compositor *compositor)
     63 {
     64 	struct wl_list *client_list;
     65 	struct wl_client *client, *client_it;
     66 	int num_clients = 0;
     67 
     68 	client_list = wl_display_get_client_list(compositor->display);
     69 	wl_client_for_each(client_it, client_list) {
     70 		num_clients++;
     71 		client = client_it;
     72 	}
     73 	assert(num_clients == 1);
     74 	/* 'client_it' is not valid here, so we took a copy of the client in the loop.
     75 	 * We could also do this assert in the loop directly, but in case it fails it is
     76 	 * easier to understand the problem when we know that the previous assert passed,
     77 	 * so that there is only one client but the wrong one. */
     78 	assert(compositor->client == client);
     79 }
     80 
     81 static const char *
     82 setup_compositor(struct compositor *compositor)
     83 {
     84 	const char *socket;
     85 
     86 	require_xdg_runtime_dir();
     87 
     88 	compositor->display = wl_display_create();
     89 	socket = wl_display_add_socket_auto(compositor->display);
     90 
     91 	compositor->listener.notify = client_created;
     92 	wl_display_add_client_created_listener(compositor->display, &compositor->listener);
     93 
     94 	return socket;
     95 }
     96 
     97 static void
     98 cleanup_compositor(struct compositor *compositor)
     99 {
    100 	wl_client_destroy(compositor->client);
    101 	wl_display_destroy(compositor->display);
    102 }
    103 
    104 TEST(new_client_connect)
    105 {
    106 	const char *socket;
    107 	struct compositor compositor = { 0 };
    108 	struct {
    109 		struct wl_display *display;
    110 	} client;
    111 
    112 	socket = setup_compositor(&compositor);
    113 
    114 	client.display = wl_display_connect(socket);
    115 
    116 	wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
    117 
    118 	assert(compositor.client != NULL);
    119 
    120 	check_client_list(&compositor);
    121 
    122 
    123 
    124 	wl_display_disconnect(client.display);
    125 	cleanup_compositor(&compositor);
    126 }
    127 
    128 struct resource_listener {
    129 	struct wl_listener listener;
    130 	int count;
    131 };
    132 
    133 static void
    134 resource_created(struct wl_listener *listener, void *data)
    135 {
    136 	struct resource_listener *l;
    137 	l = wl_container_of(listener, l, listener);
    138 	l->count++;
    139 }
    140 
    141 TEST(new_resource)
    142 {
    143 	const char *socket;
    144 	struct compositor compositor = { 0 };
    145 	struct {
    146 		struct wl_display *display;
    147 		struct wl_callback *cb;
    148 	} client;
    149 	struct resource_listener resource_listener;
    150 
    151 	socket = setup_compositor(&compositor);
    152 	client.display = wl_display_connect(socket);
    153 	wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
    154 
    155 	resource_listener.count = 0;
    156 	resource_listener.listener.notify = resource_created;
    157 	wl_client_add_resource_created_listener(compositor.client,
    158 						&resource_listener.listener);
    159 
    160 	client.cb = wl_display_sync(client.display);
    161 	wl_display_flush(client.display);
    162 	wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
    163 
    164 	assert(resource_listener.count == 1);
    165 
    166 	wl_callback_destroy(client.cb);
    167 	wl_display_disconnect(client.display);
    168 	cleanup_compositor(&compositor);
    169 
    170 	/* This is defined to be safe also after client destruction */
    171 	wl_list_remove(&resource_listener.listener.link);
    172 }
    173