diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2012-04-23 10:35:53 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-05-01 11:36:30 +1000 |
commit | ea51e9b2877df60135edaf2a8f88d0f2a2b41060 (patch) | |
tree | 64e39f4ade95456f6445e6c06c996cf859b85d49 | |
parent | 93d6ba5b711cbd3f502d83e54c9739856d2e6f2a (diff) |
Xi: return BadValue on XIQueryVersion if the version is less than first call
Clients that use plugin systems may require multiple calls to
XIQueryVersion from different plugins. The current error handling requires
client-side synchronisation of version numbers.
The first call to XIQueryVersion defines the server behaviour. Once cached,
always return that version number to any clients. Unless a client requests a
version lower than the first defined one, then a BadValue must be returned
to be protocol-compatible.
Introduced in 2c23ef83b0e03e163aeeb06133538606886f4e9c
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
-rw-r--r-- | Xi/xiqueryversion.c | 41 | ||||
-rw-r--r-- | test/xi2/protocol-xiqueryversion.c | 113 |
2 files changed, 134 insertions, 20 deletions
diff --git a/Xi/xiqueryversion.c b/Xi/xiqueryversion.c index fc0ca751b..6081c413d 100644 --- a/Xi/xiqueryversion.c +++ b/Xi/xiqueryversion.c @@ -70,28 +70,29 @@ ProcXIQueryVersion(ClientPtr client) pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); - if (pXIClient->major_version && - (stuff->major_version != pXIClient->major_version || - stuff->minor_version != pXIClient->minor_version)) - { - client->errorValue = stuff->major_version; - return BadValue; + if (pXIClient->major_version) { + if (version_compare(stuff->major_version, stuff->minor_version, + pXIClient->major_version, pXIClient->minor_version) < 0) { + client->errorValue = stuff->major_version; + return BadValue; + } + major = pXIClient->major_version; + minor = pXIClient->minor_version; + } else { + if (version_compare(XIVersion.major_version, XIVersion.minor_version, + stuff->major_version, stuff->minor_version) > 0) { + major = stuff->major_version; + minor = stuff->minor_version; + } + else { + major = XIVersion.major_version; + minor = XIVersion.minor_version; + } + + pXIClient->major_version = major; + pXIClient->minor_version = minor; } - - if (version_compare(XIVersion.major_version, XIVersion.minor_version, - stuff->major_version, stuff->minor_version) > 0) { - major = stuff->major_version; - minor = stuff->minor_version; - } - else { - major = XIVersion.major_version; - minor = XIVersion.minor_version; - } - - pXIClient->major_version = major; - pXIClient->minor_version = minor; - memset(&rep, 0, sizeof(xXIQueryVersionReply)); rep.repType = X_Reply; rep.RepType = X_XIQueryVersion; diff --git a/test/xi2/protocol-xiqueryversion.c b/test/xi2/protocol-xiqueryversion.c index 2552307f2..1347e866c 100644 --- a/test/xi2/protocol-xiqueryversion.c +++ b/test/xi2/protocol-xiqueryversion.c @@ -54,6 +54,8 @@ struct test_data { int minor_client; int major_server; int minor_server; + int major_cached; + int minor_cached; }; static void @@ -82,6 +84,24 @@ reply_XIQueryVersion(ClientPtr client, int len, char *data, void *userdata) assert((sver > cver) ? ver == cver : ver == sver); } +static void +reply_XIQueryVersion_multiple(ClientPtr client, int len, char *data, void *userdata) +{ + xXIQueryVersionReply *rep = (xXIQueryVersionReply *) data; + struct test_data *versions = (struct test_data *) userdata; + + reply_check_defaults(rep, len, XIQueryVersion); + assert(rep->length == 0); + + if (versions->major_cached == -1) { + versions->major_cached = rep->major_version; + versions->minor_cached = rep->minor_version; + } + + assert(versions->major_cached == rep->major_version); + assert(versions->minor_cached == rep->minor_version); +} + /** * Run a single test with server version smaj.smin and client * version cmaj.cmin. Verify that return code is equal to 'error'. @@ -173,12 +193,105 @@ test_XIQueryVersion(void) reply_handler = NULL; } + +static void +test_XIQueryVersion_multiple(void) +{ + xXIQueryVersionReq request; + ClientRec client; + struct test_data versions; + int rc; + + request_init(&request, XIQueryVersion); + client = init_client(request.length, &request); + + /* Change the server to support 2.2 */ + XIVersion.major_version = 2; + XIVersion.minor_version = 2; + + reply_handler = reply_XIQueryVersion_multiple; + userdata = (void *) &versions; + + /* run 1 */ + versions.major_cached = -1; + versions.minor_cached = -1; + + /* client is lower than server, noncached */ + request.major_version = 2; + request.minor_version = 1; + rc = ProcXIQueryVersion(&client); + assert(rc == Success); + + /* client is higher than server, cached */ + request.major_version = 2; + request.minor_version = 3; + rc = ProcXIQueryVersion(&client); + assert(rc == Success); + + /* client is equal, cached */ + request.major_version = 2; + request.minor_version = 2; + rc = ProcXIQueryVersion(&client); + assert(rc == Success); + + /* client is low than cached */ + request.major_version = 2; + request.minor_version = 0; + rc = ProcXIQueryVersion(&client); + assert(rc == BadValue); + + /* run 2 */ + client = init_client(request.length, &request); + XIVersion.major_version = 2; + XIVersion.minor_version = 2; + versions.major_cached = -1; + versions.minor_cached = -1; + + request.major_version = 2; + request.minor_version = 2; + rc = ProcXIQueryVersion(&client); + assert(rc == Success); + + request.major_version = 2; + request.minor_version = 3; + rc = ProcXIQueryVersion(&client); + assert(rc == Success); + + request.major_version = 2; + request.minor_version = 1; + rc = ProcXIQueryVersion(&client); + assert(rc == BadValue); + + /* run 3 */ + client = init_client(request.length, &request); + XIVersion.major_version = 2; + XIVersion.minor_version = 2; + versions.major_cached = -1; + versions.minor_cached = -1; + + request.major_version = 2; + request.minor_version = 3; + rc = ProcXIQueryVersion(&client); + assert(rc == Success); + + request.major_version = 2; + request.minor_version = 2; + rc = ProcXIQueryVersion(&client); + assert(rc == Success); + + request.major_version = 2; + request.minor_version = 1; + rc = ProcXIQueryVersion(&client); + assert(rc == BadValue); +} + int main(int argc, char **argv) { init_simple(); test_XIQueryVersion(); + test_XIQueryVersion_multiple(); return 0; } |