Imported Upstream version 1.15.1
[deb_xorg-server.git] / test / xi2 / protocol-xiselectevents.c
CommitLineData
a09e091a
JB
1/**
2 * Copyright © 2009 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#ifdef HAVE_DIX_CONFIG_H
25#include <dix-config.h>
26#endif
27
28/*
29 * Protocol testing for XISelectEvents request.
30 *
31 * Test approach:
32 *
33 * Wrap XISetEventMask to intercept when the server tries to apply the event
34 * mask. Ensure that the mask passed in is equivalent to the one supplied by
35 * the client. Ensure that invalid devices and invalid masks return errors
36 * as appropriate.
37 *
38 * Tests included:
39 * BadValue for num_masks < 0
40 * BadWindow for invalid windows
41 * BadDevice for non-existing devices
42 * BadImplemenation for devices >= 0xFF
43 * BadValue if HierarchyChanged bit is set for devices other than
44 * XIAllDevices
45 * BadValue for invalid mask bits
46 * Sucecss for excessive mask lengths
47 *
48 */
49
50#include <stdint.h>
51#include <X11/X.h>
52#include <X11/Xproto.h>
53#include <X11/extensions/XI2proto.h>
54#include "inputstr.h"
55#include "windowstr.h"
56#include "extinit.h" /* for XInputExtensionInit */
57#include "scrnintstr.h"
58#include "exglobals.h"
59#include "xiselectev.h"
60
61#include "protocol-common.h"
62
63static unsigned char *data[4096 * 20]; /* the request data buffer */
64
65int
66__wrap_XISetEventMask(DeviceIntPtr dev, WindowPtr win, int len,
67 unsigned char *mask)
68{
69 return Success;
70}
71
72/* dixLookupWindow requires a lot of setup not necessary for this test.
73 * Simple wrapper that returns either one of the fake root window or the
74 * fake client window. If the requested ID is neither of those wanted,
75 * return whatever the real dixLookupWindow does.
76 */
77int
78__wrap_dixLookupWindow(WindowPtr *win, XID id, ClientPtr client, Mask access)
79{
80 if (id == root.drawable.id) {
81 *win = &root;
82 return Success;
83 }
84 else if (id == window.drawable.id) {
85 *win = &window;
86 return Success;
87 }
88
89 return __real_dixLookupWindow(win, id, client, access);
90}
91
92static void
93request_XISelectEvent(xXISelectEventsReq * req, int error)
94{
95 int i;
96 int rc;
97 ClientRec client;
98 xXIEventMask *mask, *next;
99
100 req->length = (sz_xXISelectEventsReq / 4);
101 mask = (xXIEventMask *) &req[1];
102 for (i = 0; i < req->num_masks; i++) {
103 req->length += sizeof(xXIEventMask) / 4 + mask->mask_len;
104 mask = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4);
105 }
106
107 client = init_client(req->length, req);
108
109 rc = ProcXISelectEvents(&client);
110 assert(rc == error);
111
112 client.swapped = TRUE;
113
114 mask = (xXIEventMask *) &req[1];
115 for (i = 0; i < req->num_masks; i++) {
116 next = (xXIEventMask *) ((char *) &mask[1] + mask->mask_len * 4);
117 swaps(&mask->deviceid);
118 swaps(&mask->mask_len);
119 mask = next;
120 }
121
122 swapl(&req->win);
123 swaps(&req->length);
124 swaps(&req->num_masks);
125 rc = SProcXISelectEvents(&client);
126 assert(rc == error);
127}
128
129static void
130_set_bit(unsigned char *bits, int bit)
131{
132 SetBit(bits, bit);
133 if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) {
134 SetBit(bits, XI_TouchBegin);
135 SetBit(bits, XI_TouchUpdate);
136 SetBit(bits, XI_TouchEnd);
137 }
138}
139
140static void
141_clear_bit(unsigned char *bits, int bit)
142{
143 ClearBit(bits, bit);
144 if (bit >= XI_TouchBegin && bit <= XI_TouchOwnership) {
145 ClearBit(bits, XI_TouchBegin);
146 ClearBit(bits, XI_TouchUpdate);
147 ClearBit(bits, XI_TouchEnd);
148 }
149}
150
151static void
152request_XISelectEvents_masks(xXISelectEventsReq * req)
153{
154 int i, j;
155 xXIEventMask *mask;
156 int nmasks = (XI2LASTEVENT + 7) / 8;
157 unsigned char *bits;
158
159 mask = (xXIEventMask *) &req[1];
160 req->win = ROOT_WINDOW_ID;
161
162 /* if a clients submits more than 100 masks, consider it insane and untested */
163 for (i = 1; i <= 1000; i++) {
164 req->num_masks = i;
165 mask->deviceid = XIAllDevices;
166
167 /* Test 0:
168 * mask_len is 0 -> Success
169 */
170 mask->mask_len = 0;
171 request_XISelectEvent(req, Success);
172
173 /* Test 1:
174 * mask may be larger than needed for XI2LASTEVENT.
175 * Test setting each valid mask bit, while leaving unneeded bits 0.
176 * -> Success
177 */
178 bits = (unsigned char *) &mask[1];
179 mask->mask_len = (nmasks + 3) / 4 * 10;
180 memset(bits, 0, mask->mask_len * 4);
181 for (j = 0; j <= XI2LASTEVENT; j++) {
182 _set_bit(bits, j);
183 request_XISelectEvent(req, Success);
184 _clear_bit(bits, j);
185 }
186
187 /* Test 2:
188 * mask may be larger than needed for XI2LASTEVENT.
189 * Test setting all valid mask bits, while leaving unneeded bits 0.
190 * -> Success
191 */
192 bits = (unsigned char *) &mask[1];
193 mask->mask_len = (nmasks + 3) / 4 * 10;
194 memset(bits, 0, mask->mask_len * 4);
195
196 for (j = 0; j <= XI2LASTEVENT; j++) {
197 _set_bit(bits, j);
198 request_XISelectEvent(req, Success);
199 }
200
201 /* Test 3:
202 * mask is larger than needed for XI2LASTEVENT. If any unneeded bit
203 * is set -> BadValue
204 */
205 bits = (unsigned char *) &mask[1];
206 mask->mask_len = (nmasks + 3) / 4 * 10;
207 memset(bits, 0, mask->mask_len * 4);
208
209 for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++) {
210 _set_bit(bits, j);
211 request_XISelectEvent(req, BadValue);
212 _clear_bit(bits, j);
213 }
214
215 /* Test 4:
216 * Mask len is a sensible length, only valid bits are set -> Success
217 */
218 bits = (unsigned char *) &mask[1];
219 mask->mask_len = (nmasks + 3) / 4;
220 memset(bits, 0, mask->mask_len * 4);
221 for (j = 0; j <= XI2LASTEVENT; j++) {
222 _set_bit(bits, j);
223 request_XISelectEvent(req, Success);
224 }
225
226 /* Test 5:
227 * HierarchyChanged bit is BadValue for devices other than
228 * XIAllDevices
229 */
230 bits = (unsigned char *) &mask[1];
231 mask->mask_len = (nmasks + 3) / 4;
232 memset(bits, 0, mask->mask_len * 4);
233 SetBit(bits, XI_HierarchyChanged);
234 mask->deviceid = XIAllDevices;
235 request_XISelectEvent(req, Success);
236 for (j = 1; j < devices.num_devices; j++) {
237 mask->deviceid = j;
238 request_XISelectEvent(req, BadValue);
239 }
240
241 /* Test 6:
242 * All bits set minus hierarchy changed bit -> Success
243 */
244 bits = (unsigned char *) &mask[1];
245 mask->mask_len = (nmasks + 3) / 4;
246 memset(bits, 0, mask->mask_len * 4);
247 for (j = 0; j <= XI2LASTEVENT; j++)
248 _set_bit(bits, j);
249 _clear_bit(bits, XI_HierarchyChanged);
250 for (j = 1; j < 6; j++) {
251 mask->deviceid = j;
252 request_XISelectEvent(req, Success);
253 }
254
255 mask =
256 (xXIEventMask *) ((char *) mask + sizeof(xXIEventMask) +
257 mask->mask_len * 4);
258 }
259}
260
261static void
262test_XISelectEvents(void)
263{
264 int i;
265 xXIEventMask *mask;
266 xXISelectEventsReq *req;
267
268 req = (xXISelectEventsReq *) data;
269
270 request_init(req, XISelectEvents);
271
272 printf("Testing for BadValue on zero-length masks\n");
273 /* zero masks are BadValue, regardless of the window */
274 req->num_masks = 0;
275
276 req->win = None;
277 request_XISelectEvent(req, BadValue);
278
279 req->win = ROOT_WINDOW_ID;
280 request_XISelectEvent(req, BadValue);
281
282 req->win = CLIENT_WINDOW_ID;
283 request_XISelectEvent(req, BadValue);
284
285 printf("Testing for BadWindow.\n");
286 /* None window is BadWindow, regardless of the masks.
287 * We don't actually need to set the masks here, BadWindow must occur
288 * before checking the masks.
289 */
290 req->win = None;
291 req->num_masks = 1;
292 request_XISelectEvent(req, BadWindow);
293
294 req->num_masks = 2;
295 request_XISelectEvent(req, BadWindow);
296
297 req->num_masks = 0xFF;
298 request_XISelectEvent(req, BadWindow);
299
300 /* request size is 3, so 0xFFFC is the highest num_mask that doesn't
301 * overflow req->length */
302 req->num_masks = 0xFFFC;
303 request_XISelectEvent(req, BadWindow);
304
305 printf("Triggering num_masks/length overflow\n");
306 req->win = ROOT_WINDOW_ID;
307 /* Integer overflow - req->length can't hold that much */
308 req->num_masks = 0xFFFF;
309 request_XISelectEvent(req, BadLength);
310
311 req->win = ROOT_WINDOW_ID;
312 req->num_masks = 1;
313
314 printf("Triggering bogus mask length error\n");
315 mask = (xXIEventMask *) &req[1];
316 mask->deviceid = 0;
317 mask->mask_len = 0xFFFF;
318 request_XISelectEvent(req, BadLength);
319
320 /* testing various device ids */
321 printf("Testing existing device ids.\n");
322 for (i = 0; i < 6; i++) {
323 mask = (xXIEventMask *) &req[1];
324 mask->deviceid = i;
325 mask->mask_len = 1;
326 req->win = ROOT_WINDOW_ID;
327 req->num_masks = 1;
328 request_XISelectEvent(req, Success);
329 }
330
331 printf("Testing non-existing device ids.\n");
332 for (i = 6; i <= 0xFFFF; i++) {
333 req->win = ROOT_WINDOW_ID;
334 req->num_masks = 1;
335 mask = (xXIEventMask *) &req[1];
336 mask->deviceid = i;
337 mask->mask_len = 1;
338 request_XISelectEvent(req, BadDevice);
339 }
340
341 request_XISelectEvents_masks(req);
342}
343
344int
345main(int argc, char **argv)
346{
347 init_simple();
348
349 test_XISelectEvents();
350
351 return 0;
352}