1706f2543Smrg/**
2706f2543Smrg * Copyright © 2009 Red Hat, Inc.
3706f2543Smrg *
4706f2543Smrg *  Permission is hereby granted, free of charge, to any person obtaining a
5706f2543Smrg *  copy of this software and associated documentation files (the "Software"),
6706f2543Smrg *  to deal in the Software without restriction, including without limitation
7706f2543Smrg *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
8706f2543Smrg *  and/or sell copies of the Software, and to permit persons to whom the
9706f2543Smrg *  Software is furnished to do so, subject to the following conditions:
10706f2543Smrg *
11706f2543Smrg *  The above copyright notice and this permission notice (including the next
12706f2543Smrg *  paragraph) shall be included in all copies or substantial portions of the
13706f2543Smrg *  Software.
14706f2543Smrg *
15706f2543Smrg *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16706f2543Smrg *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17706f2543Smrg *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18706f2543Smrg *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19706f2543Smrg *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20706f2543Smrg *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21706f2543Smrg *  DEALINGS IN THE SOFTWARE.
22706f2543Smrg */
23706f2543Smrg
24706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
25706f2543Smrg#include <dix-config.h>
26706f2543Smrg#endif
27706f2543Smrg
28706f2543Smrg/*
29706f2543Smrg * Protocol testing for XIGetSelectedEvents request.
30706f2543Smrg *
31706f2543Smrg * Tests include:
32706f2543Smrg * BadWindow on wrong window.
33706f2543Smrg * Zero-length masks if no masks are set.
34706f2543Smrg * Valid masks for valid devices.
35706f2543Smrg * Masks set on non-existent devices are not returned.
36706f2543Smrg *
37706f2543Smrg * Note that this test is not connected to the XISelectEvents request.
38706f2543Smrg */
39706f2543Smrg#include <stdint.h>
40706f2543Smrg#include <X11/X.h>
41706f2543Smrg#include <X11/Xproto.h>
42706f2543Smrg#include <X11/extensions/XI2proto.h>
43706f2543Smrg#include "inputstr.h"
44706f2543Smrg#include "windowstr.h"
45706f2543Smrg#include "extinit.h" /* for XInputExtensionInit */
46706f2543Smrg#include "scrnintstr.h"
47706f2543Smrg#include "xiselectev.h"
48706f2543Smrg#include "exevents.h"
49706f2543Smrg
50706f2543Smrg#include "protocol-common.h"
51706f2543Smrg#include <glib.h>
52706f2543Smrg
53706f2543Smrgstatic void reply_XIGetSelectedEvents(ClientPtr client, int len, char *data, void *userdata);
54706f2543Smrgstatic void reply_XIGetSelectedEvents_data(ClientPtr client, int len, char *data, void *userdata);
55706f2543Smrg
56706f2543Smrg
57706f2543Smrgstruct {
58706f2543Smrg    int num_masks_expected;
59706f2543Smrg    unsigned char mask[MAXDEVICES][XI2LASTEVENT]; /* intentionally bigger */
60706f2543Smrg    int mask_len;
61706f2543Smrg} test_data;
62706f2543Smrg
63706f2543Smrg/* dixLookupWindow requires a lot of setup not necessary for this test.
64706f2543Smrg * Simple wrapper that returns either one of the fake root window or the
65706f2543Smrg * fake client window. If the requested ID is neither of those wanted,
66706f2543Smrg * return whatever the real dixLookupWindow does.
67706f2543Smrg */
68706f2543Smrgint __wrap_dixLookupWindow(WindowPtr *win, XID id, ClientPtr client, Mask access)
69706f2543Smrg{
70706f2543Smrg    if (id == root.drawable.id)
71706f2543Smrg    {
72706f2543Smrg        *win = &root;
73706f2543Smrg        return Success;
74706f2543Smrg    } else if (id == window.drawable.id)
75706f2543Smrg    {
76706f2543Smrg        *win = &window;
77706f2543Smrg        return Success;
78706f2543Smrg    }
79706f2543Smrg
80706f2543Smrg    return __real_dixLookupWindow(win, id, client, access);
81706f2543Smrg}
82706f2543Smrg
83706f2543Smrg/* AddResource is called from XISetSEventMask, we don't need this */
84706f2543SmrgBool __wrap_AddResource(XID id, RESTYPE type, pointer value)
85706f2543Smrg{
86706f2543Smrg    return TRUE;
87706f2543Smrg}
88706f2543Smrg
89706f2543Smrgstatic void reply_XIGetSelectedEvents(ClientPtr client, int len, char *data, void *userdata)
90706f2543Smrg{
91706f2543Smrg    xXIGetSelectedEventsReply *rep = (xXIGetSelectedEventsReply*)data;
92706f2543Smrg
93706f2543Smrg    if (client->swapped)
94706f2543Smrg    {
95706f2543Smrg        char n;
96706f2543Smrg        swapl(&rep->length, n);
97706f2543Smrg        swaps(&rep->sequenceNumber, n);
98706f2543Smrg        swaps(&rep->num_masks, n);
99706f2543Smrg    }
100706f2543Smrg
101706f2543Smrg    reply_check_defaults(rep, len, XIGetSelectedEvents);
102706f2543Smrg
103706f2543Smrg    g_assert(rep->num_masks == test_data.num_masks_expected);
104706f2543Smrg
105706f2543Smrg    reply_handler = reply_XIGetSelectedEvents_data;
106706f2543Smrg}
107706f2543Smrg
108706f2543Smrgstatic void reply_XIGetSelectedEvents_data(ClientPtr client, int len, char *data, void *userdata)
109706f2543Smrg{
110706f2543Smrg    int i;
111706f2543Smrg    xXIEventMask *mask;
112706f2543Smrg    unsigned char *bitmask;
113706f2543Smrg
114706f2543Smrg    mask = (xXIEventMask*)data;
115706f2543Smrg    for (i = 0; i < test_data.num_masks_expected; i++)
116706f2543Smrg    {
117706f2543Smrg        if (client->swapped)
118706f2543Smrg        {
119706f2543Smrg            char n;
120706f2543Smrg            swaps(&mask->deviceid, n);
121706f2543Smrg            swaps(&mask->mask_len, n);
122706f2543Smrg        }
123706f2543Smrg
124706f2543Smrg        g_assert(mask->deviceid < 6);
125706f2543Smrg        g_assert(mask->mask_len <= (((XI2LASTEVENT + 8)/8) + 3)/4) ;
126706f2543Smrg
127706f2543Smrg        bitmask = (unsigned char*)&mask[1];
128706f2543Smrg        g_assert(memcmp(bitmask,
129706f2543Smrg                    test_data.mask[mask->deviceid],
130706f2543Smrg                    mask->mask_len * 4) == 0);
131706f2543Smrg
132706f2543Smrg        mask = (xXIEventMask*)((char*)mask + mask->mask_len * 4 + sizeof(xXIEventMask));
133706f2543Smrg    }
134706f2543Smrg
135706f2543Smrg
136706f2543Smrg}
137706f2543Smrg
138706f2543Smrgstatic void request_XIGetSelectedEvents(xXIGetSelectedEventsReq* req, int error)
139706f2543Smrg{
140706f2543Smrg    char n;
141706f2543Smrg    int rc;
142706f2543Smrg    ClientRec client;
143706f2543Smrg    client = init_client(req->length, req);
144706f2543Smrg
145706f2543Smrg    reply_handler = reply_XIGetSelectedEvents;
146706f2543Smrg
147706f2543Smrg    rc = ProcXIGetSelectedEvents(&client);
148706f2543Smrg    g_assert(rc == error);
149706f2543Smrg
150706f2543Smrg    reply_handler = reply_XIGetSelectedEvents;
151706f2543Smrg    client.swapped = TRUE;
152706f2543Smrg    swapl(&req->win, n);
153706f2543Smrg    swaps(&req->length, n);
154706f2543Smrg    rc = SProcXIGetSelectedEvents(&client);
155706f2543Smrg    g_assert(rc == error);
156706f2543Smrg}
157706f2543Smrg
158706f2543Smrgstatic void test_XIGetSelectedEvents(void)
159706f2543Smrg{
160706f2543Smrg    int i, j;
161706f2543Smrg    xXIGetSelectedEventsReq request;
162706f2543Smrg    ClientRec client = init_client(0, NULL);
163706f2543Smrg    unsigned char *mask;
164706f2543Smrg    DeviceIntRec dev;
165706f2543Smrg
166706f2543Smrg    request_init(&request, XIGetSelectedEvents);
167706f2543Smrg
168706f2543Smrg    g_test_message("Testing for BadWindow on invalid window.");
169706f2543Smrg    request.win = None;
170706f2543Smrg    request_XIGetSelectedEvents(&request, BadWindow);
171706f2543Smrg
172706f2543Smrg    g_test_message("Testing for zero-length (unset) masks.");
173706f2543Smrg    /* No masks set yet */
174706f2543Smrg    test_data.num_masks_expected = 0;
175706f2543Smrg    request.win = ROOT_WINDOW_ID;
176706f2543Smrg    request_XIGetSelectedEvents(&request, Success);
177706f2543Smrg
178706f2543Smrg    request.win = CLIENT_WINDOW_ID;
179706f2543Smrg    request_XIGetSelectedEvents(&request, Success);
180706f2543Smrg
181706f2543Smrg    memset(test_data.mask, 0,
182706f2543Smrg           sizeof(test_data.mask));
183706f2543Smrg
184706f2543Smrg    g_test_message("Testing for valid masks");
185706f2543Smrg    memset(&dev, 0, sizeof(dev)); /* dev->id is enough for XISetEventMask */
186706f2543Smrg    request.win = ROOT_WINDOW_ID;
187706f2543Smrg
188706f2543Smrg    /* devices 6 - MAXDEVICES don't exist, they mustn't be included in the
189706f2543Smrg     * reply even if a mask is set */
190706f2543Smrg    for (j = 0; j < MAXDEVICES; j++)
191706f2543Smrg    {
192706f2543Smrg        test_data.num_masks_expected = min(j + 1, devices.num_devices + 2);
193706f2543Smrg        dev.id = j;
194706f2543Smrg        mask = test_data.mask[j];
195706f2543Smrg        /* bits one-by-one */
196706f2543Smrg        for (i = 0; i < XI2LASTEVENT; i++)
197706f2543Smrg        {
198706f2543Smrg            SetBit(mask, i);
199706f2543Smrg            XISetEventMask(&dev, &root, &client, (i + 8)/8, mask);
200706f2543Smrg            request_XIGetSelectedEvents(&request, Success);
201706f2543Smrg            ClearBit(mask, i);
202706f2543Smrg        }
203706f2543Smrg
204706f2543Smrg        /* all valid mask bits */
205706f2543Smrg        for (i = 0; i < XI2LASTEVENT; i++)
206706f2543Smrg        {
207706f2543Smrg            SetBit(mask, i);
208706f2543Smrg            XISetEventMask(&dev, &root, &client, (i + 8)/8, mask);
209706f2543Smrg            request_XIGetSelectedEvents(&request, Success);
210706f2543Smrg        }
211706f2543Smrg    }
212706f2543Smrg
213706f2543Smrg    g_test_message("Testing removing all masks");
214706f2543Smrg    /* Unset all masks one-by-one */
215706f2543Smrg    for (j = MAXDEVICES - 1; j >= 0; j--)
216706f2543Smrg    {
217706f2543Smrg        if (j < devices.num_devices + 2)
218706f2543Smrg            test_data.num_masks_expected--;
219706f2543Smrg
220706f2543Smrg        mask = test_data.mask[j];
221706f2543Smrg        memset(mask, 0, XI2LASTEVENT);
222706f2543Smrg
223706f2543Smrg        dev.id = j;
224706f2543Smrg        XISetEventMask(&dev, &root, &client, 0, NULL);
225706f2543Smrg
226706f2543Smrg        request_XIGetSelectedEvents(&request, Success);
227706f2543Smrg    }
228706f2543Smrg}
229706f2543Smrg
230706f2543Smrgint main(int argc, char** argv)
231706f2543Smrg{
232706f2543Smrg    g_test_init(&argc, &argv,NULL);
233706f2543Smrg    g_test_bug_base("https://bugzilla.freedesktop.org/show_bug.cgi?id=");
234706f2543Smrg
235706f2543Smrg    init_simple();
236706f2543Smrg
237706f2543Smrg    g_test_add_func("/xi2/protocol/XIGetSelectedEvents", test_XIGetSelectedEvents);
238706f2543Smrg
239706f2543Smrg    return g_test_run();
240706f2543Smrg}
241706f2543Smrg
242