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