1*4882a593Smuzhiyun /**
2*4882a593Smuzhiyun * Copyright © 2009 Red Hat, Inc.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the next
12*4882a593Smuzhiyun * paragraph) shall be included in all copies or substantial portions of the
13*4882a593Smuzhiyun * Software.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*4882a593Smuzhiyun * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*4882a593Smuzhiyun * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*4882a593Smuzhiyun * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*4882a593Smuzhiyun * DEALINGS IN THE SOFTWARE.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
25*4882a593Smuzhiyun #include <dix-config.h>
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun * Protocol testing for XIQueryVersion request and reply.
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * Test approach:
32*4882a593Smuzhiyun * Wrap WriteToClient to intercept the server's reply.
33*4882a593Smuzhiyun * Repeatedly test a client/server version combination, compare version in
34*4882a593Smuzhiyun * reply with versions given. Version must be equal to either
35*4882a593Smuzhiyun * server version or client version, whichever is smaller.
36*4882a593Smuzhiyun * Client version less than 2 must return BadValue.
37*4882a593Smuzhiyun */
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include <stdint.h>
40*4882a593Smuzhiyun #include <X11/X.h>
41*4882a593Smuzhiyun #include <X11/Xproto.h>
42*4882a593Smuzhiyun #include <X11/extensions/XI2proto.h>
43*4882a593Smuzhiyun #include "inputstr.h"
44*4882a593Smuzhiyun #include "extinit.h" /* for XInputExtensionInit */
45*4882a593Smuzhiyun #include "scrnintstr.h"
46*4882a593Smuzhiyun #include "xiqueryversion.h"
47*4882a593Smuzhiyun #include "protocol-common.h"
48*4882a593Smuzhiyun #include "exglobals.h"
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun extern XExtensionVersion XIVersion;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun struct test_data {
53*4882a593Smuzhiyun int major_client;
54*4882a593Smuzhiyun int minor_client;
55*4882a593Smuzhiyun int major_server;
56*4882a593Smuzhiyun int minor_server;
57*4882a593Smuzhiyun int major_expected;
58*4882a593Smuzhiyun int minor_expected;
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun extern ClientRec client_window;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static void
reply_XIQueryVersion(ClientPtr client,int len,char * data,void * closure)64*4882a593Smuzhiyun reply_XIQueryVersion(ClientPtr client, int len, char *data, void *closure)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun xXIQueryVersionReply *rep = (xXIQueryVersionReply *) data;
67*4882a593Smuzhiyun struct test_data *versions = (struct test_data *) closure;
68*4882a593Smuzhiyun unsigned int sver, cver, ver;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun if (client->swapped) {
71*4882a593Smuzhiyun swapl(&rep->length);
72*4882a593Smuzhiyun swaps(&rep->sequenceNumber);
73*4882a593Smuzhiyun swaps(&rep->major_version);
74*4882a593Smuzhiyun swaps(&rep->minor_version);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun reply_check_defaults(rep, len, XIQueryVersion);
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun assert(rep->length == 0);
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun sver = versions->major_server * 1000 + versions->minor_server;
82*4882a593Smuzhiyun cver = versions->major_client * 1000 + versions->minor_client;
83*4882a593Smuzhiyun ver = rep->major_version * 1000 + rep->minor_version;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun assert(ver >= 2000);
86*4882a593Smuzhiyun assert((sver > cver) ? ver == cver : ver == sver);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun static void
reply_XIQueryVersion_multiple(ClientPtr client,int len,char * data,void * closure)90*4882a593Smuzhiyun reply_XIQueryVersion_multiple(ClientPtr client, int len, char *data, void *closure)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun xXIQueryVersionReply *rep = (xXIQueryVersionReply *) data;
93*4882a593Smuzhiyun struct test_data *versions = (struct test_data *) closure;
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun reply_check_defaults(rep, len, XIQueryVersion);
96*4882a593Smuzhiyun assert(rep->length == 0);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun assert(versions->major_expected == rep->major_version);
99*4882a593Smuzhiyun assert(versions->minor_expected == rep->minor_version);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /**
103*4882a593Smuzhiyun * Run a single test with server version smaj.smin and client
104*4882a593Smuzhiyun * version cmaj.cmin. Verify that return code is equal to 'error'.
105*4882a593Smuzhiyun *
106*4882a593Smuzhiyun * Test is run normal, then for a swapped client.
107*4882a593Smuzhiyun */
108*4882a593Smuzhiyun static void
request_XIQueryVersion(int smaj,int smin,int cmaj,int cmin,int error)109*4882a593Smuzhiyun request_XIQueryVersion(int smaj, int smin, int cmaj, int cmin, int error)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun int rc;
112*4882a593Smuzhiyun struct test_data versions;
113*4882a593Smuzhiyun xXIQueryVersionReq request;
114*4882a593Smuzhiyun ClientRec client;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun request_init(&request, XIQueryVersion);
117*4882a593Smuzhiyun client = init_client(request.length, &request);
118*4882a593Smuzhiyun global_userdata = (void *) &versions;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* Change the server to support smaj.smin */
121*4882a593Smuzhiyun XIVersion.major_version = smaj;
122*4882a593Smuzhiyun XIVersion.minor_version = smin;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /* remember versions we send and expect */
125*4882a593Smuzhiyun versions.major_client = cmaj;
126*4882a593Smuzhiyun versions.minor_client = cmin;
127*4882a593Smuzhiyun versions.major_server = XIVersion.major_version;
128*4882a593Smuzhiyun versions.minor_server = XIVersion.minor_version;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun request.major_version = versions.major_client;
131*4882a593Smuzhiyun request.minor_version = versions.minor_client;
132*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
133*4882a593Smuzhiyun assert(rc == error);
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun client = init_client(request.length, &request);
136*4882a593Smuzhiyun client.swapped = TRUE;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun swaps(&request.length);
139*4882a593Smuzhiyun swaps(&request.major_version);
140*4882a593Smuzhiyun swaps(&request.minor_version);
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun rc = SProcXIQueryVersion(&client);
143*4882a593Smuzhiyun assert(rc == error);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /* Client version less than 2.0 must return BadValue, all other combinations
147*4882a593Smuzhiyun * Success */
148*4882a593Smuzhiyun static void
test_XIQueryVersion(void)149*4882a593Smuzhiyun test_XIQueryVersion(void)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun reply_handler = reply_XIQueryVersion;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun printf("Server version 2.0 - client versions [1..3].0\n");
154*4882a593Smuzhiyun /* some simple tests to catch common errors quickly */
155*4882a593Smuzhiyun request_XIQueryVersion(2, 0, 1, 0, BadValue);
156*4882a593Smuzhiyun request_XIQueryVersion(2, 0, 2, 0, Success);
157*4882a593Smuzhiyun request_XIQueryVersion(2, 0, 3, 0, Success);
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun printf("Server version 3.0 - client versions [1..3].0\n");
160*4882a593Smuzhiyun request_XIQueryVersion(3, 0, 1, 0, BadValue);
161*4882a593Smuzhiyun request_XIQueryVersion(3, 0, 2, 0, Success);
162*4882a593Smuzhiyun request_XIQueryVersion(3, 0, 3, 0, Success);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun printf("Server version 2.0 - client versions [1..3].[1..3]\n");
165*4882a593Smuzhiyun request_XIQueryVersion(2, 0, 1, 1, BadValue);
166*4882a593Smuzhiyun request_XIQueryVersion(2, 0, 2, 2, Success);
167*4882a593Smuzhiyun request_XIQueryVersion(2, 0, 3, 3, Success);
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun printf("Server version 2.2 - client versions [1..3].0\n");
170*4882a593Smuzhiyun request_XIQueryVersion(2, 2, 1, 0, BadValue);
171*4882a593Smuzhiyun request_XIQueryVersion(2, 2, 2, 0, Success);
172*4882a593Smuzhiyun request_XIQueryVersion(2, 2, 3, 0, Success);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun #if 0
175*4882a593Smuzhiyun /* this one takes a while */
176*4882a593Smuzhiyun unsigned int cmin, cmaj, smin, smaj;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun printf("Testing all combinations.\n");
179*4882a593Smuzhiyun for (smaj = 2; smaj <= 0xFFFF; smaj++)
180*4882a593Smuzhiyun for (smin = 0; smin <= 0xFFFF; smin++)
181*4882a593Smuzhiyun for (cmin = 0; cmin <= 0xFFFF; cmin++)
182*4882a593Smuzhiyun for (cmaj = 0; cmaj <= 0xFFFF; cmaj++) {
183*4882a593Smuzhiyun int error = (cmaj < 2) ? BadValue : Success;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun request_XIQueryVersion(smaj, smin, cmaj, cmin, error);
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun #endif
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun reply_handler = NULL;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun static void
test_XIQueryVersion_multiple(void)195*4882a593Smuzhiyun test_XIQueryVersion_multiple(void)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun xXIQueryVersionReq request;
198*4882a593Smuzhiyun ClientRec client;
199*4882a593Smuzhiyun XIClientPtr pXIClient;
200*4882a593Smuzhiyun struct test_data versions;
201*4882a593Smuzhiyun int rc;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun request_init(&request, XIQueryVersion);
204*4882a593Smuzhiyun client = init_client(request.length, &request);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun /* Change the server to support 2.2 */
207*4882a593Smuzhiyun XIVersion.major_version = 2;
208*4882a593Smuzhiyun XIVersion.minor_version = 2;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun reply_handler = reply_XIQueryVersion_multiple;
211*4882a593Smuzhiyun global_userdata = (void *) &versions;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun /* run 1 */
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun /* client is lower than server, nonexpected */
216*4882a593Smuzhiyun versions.major_expected = request.major_version = 2;
217*4882a593Smuzhiyun versions.minor_expected = request.minor_version = 1;
218*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
219*4882a593Smuzhiyun assert(rc == Success);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* client is higher than server, no change */
222*4882a593Smuzhiyun request.major_version = 2;
223*4882a593Smuzhiyun request.minor_version = 3;
224*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
225*4882a593Smuzhiyun assert(rc == Success);
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /* client tries to set higher version, stays same */
228*4882a593Smuzhiyun request.major_version = 2;
229*4882a593Smuzhiyun request.minor_version = 2;
230*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
231*4882a593Smuzhiyun assert(rc == Success);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /* client tries to set lower version, no change */
234*4882a593Smuzhiyun request.major_version = 2;
235*4882a593Smuzhiyun request.minor_version = 0;
236*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
237*4882a593Smuzhiyun assert(rc == BadValue);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /* run 2 */
240*4882a593Smuzhiyun client = init_client(request.length, &request);
241*4882a593Smuzhiyun XIVersion.major_version = 2;
242*4882a593Smuzhiyun XIVersion.minor_version = 3;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun versions.major_expected = request.major_version = 2;
245*4882a593Smuzhiyun versions.minor_expected = request.minor_version = 2;
246*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
247*4882a593Smuzhiyun assert(rc == Success);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /* client bumps version from 2.2 to 2.3 */
250*4882a593Smuzhiyun request.major_version = 2;
251*4882a593Smuzhiyun versions.minor_expected = request.minor_version = 3;
252*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
253*4882a593Smuzhiyun assert(rc == Success);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /* real version is changed, too! */
256*4882a593Smuzhiyun pXIClient = dixLookupPrivate(&client.devPrivates, XIClientPrivateKey);
257*4882a593Smuzhiyun assert(pXIClient->minor_version == 3);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun /* client tries to set lower version, no change */
260*4882a593Smuzhiyun request.major_version = 2;
261*4882a593Smuzhiyun request.minor_version = 1;
262*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
263*4882a593Smuzhiyun assert(rc == BadValue);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /* run 3 */
266*4882a593Smuzhiyun client = init_client(request.length, &request);
267*4882a593Smuzhiyun XIVersion.major_version = 2;
268*4882a593Smuzhiyun XIVersion.minor_version = 3;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun versions.major_expected = request.major_version = 2;
271*4882a593Smuzhiyun versions.minor_expected = request.minor_version = 3;
272*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
273*4882a593Smuzhiyun assert(rc == Success);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun request.major_version = 2;
276*4882a593Smuzhiyun versions.minor_expected = request.minor_version = 2;
277*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
278*4882a593Smuzhiyun assert(rc == Success);
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun /* but real client version must not be lowered */
281*4882a593Smuzhiyun pXIClient = dixLookupPrivate(&client.devPrivates, XIClientPrivateKey);
282*4882a593Smuzhiyun assert(pXIClient->minor_version == 3);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun request.major_version = 2;
285*4882a593Smuzhiyun request.minor_version = 1;
286*4882a593Smuzhiyun rc = ProcXIQueryVersion(&client);
287*4882a593Smuzhiyun assert(rc == BadValue);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun int
protocol_xiqueryversion_test(void)291*4882a593Smuzhiyun protocol_xiqueryversion_test(void)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun init_simple();
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun test_XIQueryVersion();
296*4882a593Smuzhiyun test_XIQueryVersion_multiple();
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun return 0;
299*4882a593Smuzhiyun }
300