1 | /* |
2 | * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@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(name: "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(display: 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(display: compositor->display); |
90 | |
91 | compositor->listener.notify = client_created; |
92 | wl_display_add_client_created_listener(display: compositor->display, listener: &compositor->listener); |
93 | |
94 | return socket; |
95 | } |
96 | |
97 | static void |
98 | cleanup_compositor(struct compositor *compositor) |
99 | { |
100 | wl_client_destroy(client: compositor->client); |
101 | wl_display_destroy(display: 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(name: socket); |
115 | |
116 | wl_event_loop_dispatch(loop: wl_display_get_event_loop(display: compositor.display), timeout: 100); |
117 | |
118 | assert(compositor.client != NULL); |
119 | |
120 | check_client_list(compositor: &compositor); |
121 | |
122 | |
123 | |
124 | wl_display_disconnect(display: client.display); |
125 | cleanup_compositor(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(name: socket); |
153 | wl_event_loop_dispatch(loop: wl_display_get_event_loop(display: compositor.display), timeout: 100); |
154 | |
155 | resource_listener.count = 0; |
156 | resource_listener.listener.notify = resource_created; |
157 | wl_client_add_resource_created_listener(client: compositor.client, |
158 | listener: &resource_listener.listener); |
159 | |
160 | client.cb = wl_display_sync(wl_display: client.display); |
161 | wl_display_flush(display: client.display); |
162 | wl_event_loop_dispatch(loop: wl_display_get_event_loop(display: compositor.display), timeout: 100); |
163 | |
164 | assert(resource_listener.count == 1); |
165 | |
166 | wl_callback_destroy(wl_callback: client.cb); |
167 | wl_display_disconnect(display: client.display); |
168 | cleanup_compositor(compositor: &compositor); |
169 | |
170 | /* This is defined to be safe also after client destruction */ |
171 | wl_list_remove(elm: &resource_listener.listener.link); |
172 | } |
173 | |