test: Add basic SYNC tests.
I couldn't find any, and I was modifying the implementation, so I had to write some. I would like the test to end with a "make sure there weren't any stray unchecked errors", but I didn't figure out how to do that. v2: Extend sync tests to cover alarm delta and waitvalue changes. Signed-off-by: Eric Anholt <eric@anholt.net> Reviewed-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
parent
3336291fc6
commit
5cbfa27654
|
@ -4,7 +4,7 @@ srcs = [
|
||||||
'../../mi/miinitext.c',
|
'../../mi/miinitext.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
executable(
|
xvfb_server = executable(
|
||||||
'Xvfb',
|
'Xvfb',
|
||||||
srcs,
|
srcs,
|
||||||
include_directories: inc,
|
include_directories: inc,
|
||||||
|
|
|
@ -22,3 +22,5 @@ if get_option('xvfb')
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
subdir('sync')
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
xcb_dep = dependency('xcb', required: false)
|
||||||
|
xcb_sync_dep = dependency('xcb-sync', required: false)
|
||||||
|
|
||||||
|
if get_option('xvfb')
|
||||||
|
if xcb_dep.found() and xcb_sync_dep.found()
|
||||||
|
sync = executable('sync', 'sync.c', dependencies: [xcb_dep, xcb_sync_dep])
|
||||||
|
test('sync', simple_xinit, args: [sync, '--', xvfb_server])
|
||||||
|
endif
|
||||||
|
endif
|
|
@ -0,0 +1,304 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2017 Broadcom
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice (including the next
|
||||||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <xcb/sync.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
static const int64_t some_values[] = {
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
-1,
|
||||||
|
LLONG_MAX,
|
||||||
|
LLONG_MIN,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
pack_sync_value(xcb_sync_int64_t val)
|
||||||
|
{
|
||||||
|
return ((int64_t)val.hi << 32) | val.lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
counter_value(struct xcb_connection_t *c,
|
||||||
|
xcb_sync_query_counter_cookie_t cookie)
|
||||||
|
{
|
||||||
|
xcb_sync_query_counter_reply_t *reply =
|
||||||
|
xcb_sync_query_counter_reply(c, cookie, NULL);
|
||||||
|
int64_t value = pack_sync_value(reply->counter_value);
|
||||||
|
|
||||||
|
free(reply);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static xcb_sync_int64_t
|
||||||
|
sync_value(int64_t value)
|
||||||
|
{
|
||||||
|
xcb_sync_int64_t v = {
|
||||||
|
.hi = value >> 32,
|
||||||
|
.lo = value,
|
||||||
|
};
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initializes counters with a bunch of interesting values and makes
|
||||||
|
* sure it comes back the same.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
test_create_counter(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
xcb_sync_query_counter_cookie_t queries[ARRAY_SIZE(some_values)];
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(some_values); i++) {
|
||||||
|
xcb_sync_counter_t counter = xcb_generate_id(c);
|
||||||
|
xcb_sync_create_counter(c, counter, sync_value(some_values[i]));
|
||||||
|
queries[i] = xcb_sync_query_counter_unchecked(c, counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(some_values); i++) {
|
||||||
|
int64_t value = counter_value(c, queries[i]);
|
||||||
|
|
||||||
|
if (value != some_values[i]) {
|
||||||
|
fprintf(stderr, "Creating counter with %lld returned %lld\n",
|
||||||
|
(long long)some_values[i],
|
||||||
|
(long long)value);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a single counter to a bunch of interesting values and make sure
|
||||||
|
* it comes the same.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
test_set_counter(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
xcb_sync_counter_t counter = xcb_generate_id(c);
|
||||||
|
xcb_sync_query_counter_cookie_t queries[ARRAY_SIZE(some_values)];
|
||||||
|
|
||||||
|
xcb_sync_create_counter(c, counter, sync_value(0));
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(some_values); i++) {
|
||||||
|
xcb_sync_set_counter(c, counter, sync_value(some_values[i]));
|
||||||
|
queries[i] = xcb_sync_query_counter_unchecked(c, counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(some_values); i++) {
|
||||||
|
int64_t value = counter_value(c, queries[i]);
|
||||||
|
|
||||||
|
if (value != some_values[i]) {
|
||||||
|
fprintf(stderr, "Setting counter to %lld returned %lld\n",
|
||||||
|
(long long)some_values[i],
|
||||||
|
(long long)value);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add [0, 1, 2, 3] to a counter and check that the values stick. */
|
||||||
|
static void
|
||||||
|
test_change_counter_basic(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
int iterations = 4;
|
||||||
|
xcb_sync_query_counter_cookie_t queries[iterations];
|
||||||
|
|
||||||
|
xcb_sync_counter_t counter = xcb_generate_id(c);
|
||||||
|
xcb_sync_create_counter(c, counter, sync_value(0));
|
||||||
|
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
xcb_sync_change_counter(c, counter, sync_value(i));
|
||||||
|
queries[i] = xcb_sync_query_counter_unchecked(c, counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t expected_value = 0;
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
expected_value += i;
|
||||||
|
int64_t value = counter_value(c, queries[i]);
|
||||||
|
|
||||||
|
if (value != expected_value) {
|
||||||
|
fprintf(stderr, "Adding %d to counter expected %lld returned %lld\n",
|
||||||
|
i,
|
||||||
|
(long long)expected_value,
|
||||||
|
(long long)value);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test change_counter where we trigger an integer overflow. */
|
||||||
|
static void
|
||||||
|
test_change_counter_overflow(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
int iterations = 4;
|
||||||
|
xcb_sync_query_counter_cookie_t queries[iterations];
|
||||||
|
xcb_void_cookie_t changes[iterations];
|
||||||
|
static const struct {
|
||||||
|
int64_t a, b;
|
||||||
|
} overflow_args[] = {
|
||||||
|
{ LLONG_MAX, 1 },
|
||||||
|
{ LLONG_MAX, LLONG_MAX },
|
||||||
|
{ LLONG_MIN, -1 },
|
||||||
|
{ LLONG_MIN, LLONG_MIN },
|
||||||
|
};
|
||||||
|
|
||||||
|
xcb_sync_counter_t counter = xcb_generate_id(c);
|
||||||
|
xcb_sync_create_counter(c, counter, sync_value(0));
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(overflow_args); i++) {
|
||||||
|
int64_t a = overflow_args[i].a;
|
||||||
|
int64_t b = overflow_args[i].b;
|
||||||
|
xcb_sync_set_counter(c, counter, sync_value(a));
|
||||||
|
changes[i] = xcb_sync_change_counter_checked(c, counter,
|
||||||
|
sync_value(b));
|
||||||
|
queries[i] = xcb_sync_query_counter(c, counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(overflow_args); i++) {
|
||||||
|
int64_t a = overflow_args[i].a;
|
||||||
|
int64_t b = overflow_args[i].b;
|
||||||
|
xcb_sync_query_counter_reply_t *reply =
|
||||||
|
xcb_sync_query_counter_reply(c, queries[i], NULL);
|
||||||
|
int64_t value = (((int64_t)reply->counter_value.hi << 32) |
|
||||||
|
reply->counter_value.lo);
|
||||||
|
int64_t expected_value = a;
|
||||||
|
|
||||||
|
/* The change_counter should have thrown BadValue */
|
||||||
|
xcb_generic_error_t *e = xcb_request_check(c, changes[i]);
|
||||||
|
if (!e) {
|
||||||
|
fprintf(stderr, "(%lld + %lld) failed to return an error\n",
|
||||||
|
(long long)a,
|
||||||
|
(long long)b);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->error_code != XCB_VALUE) {
|
||||||
|
fprintf(stderr, "(%lld + %lld) returned %d, not BadValue\n",
|
||||||
|
(long long)a,
|
||||||
|
(long long)b,
|
||||||
|
e->error_code);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The change_counter should have had no other effect if it
|
||||||
|
* errored out.
|
||||||
|
*/
|
||||||
|
if (value != expected_value) {
|
||||||
|
fprintf(stderr, "(%lld + %lld) expected %lld returned %lld\n",
|
||||||
|
(long long)a,
|
||||||
|
(long long)b,
|
||||||
|
(long long)expected_value,
|
||||||
|
(long long)value);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(e);
|
||||||
|
free(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_change_alarm_value(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
xcb_sync_alarm_t alarm = xcb_generate_id(c);
|
||||||
|
xcb_sync_query_alarm_cookie_t queries[ARRAY_SIZE(some_values)];
|
||||||
|
|
||||||
|
xcb_sync_create_alarm(c, alarm, 0, NULL);
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(some_values); i++) {
|
||||||
|
uint32_t values[] = { some_values[i] >> 32, some_values[i] };
|
||||||
|
|
||||||
|
xcb_sync_change_alarm(c, alarm, XCB_SYNC_CA_VALUE, values);
|
||||||
|
queries[i] = xcb_sync_query_alarm_unchecked(c, alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(some_values); i++) {
|
||||||
|
xcb_sync_query_alarm_reply_t *reply =
|
||||||
|
xcb_sync_query_alarm_reply(c, queries[i], NULL);
|
||||||
|
int64_t value = pack_sync_value(reply->trigger.wait_value);
|
||||||
|
|
||||||
|
if (value != some_values[i]) {
|
||||||
|
fprintf(stderr, "Setting alarm value to %lld returned %lld\n",
|
||||||
|
(long long)some_values[i],
|
||||||
|
(long long)value);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
free(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_change_alarm_delta(xcb_connection_t *c)
|
||||||
|
{
|
||||||
|
xcb_sync_alarm_t alarm = xcb_generate_id(c);
|
||||||
|
xcb_sync_query_alarm_cookie_t queries[ARRAY_SIZE(some_values)];
|
||||||
|
|
||||||
|
xcb_sync_create_alarm(c, alarm, 0, NULL);
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(some_values); i++) {
|
||||||
|
uint32_t values[] = { some_values[i] >> 32, some_values[i] };
|
||||||
|
|
||||||
|
xcb_sync_change_alarm(c, alarm, XCB_SYNC_CA_DELTA, values);
|
||||||
|
queries[i] = xcb_sync_query_alarm_unchecked(c, alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(some_values); i++) {
|
||||||
|
xcb_sync_query_alarm_reply_t *reply =
|
||||||
|
xcb_sync_query_alarm_reply(c, queries[i], NULL);
|
||||||
|
int64_t value = pack_sync_value(reply->delta);
|
||||||
|
|
||||||
|
if (value != some_values[i]) {
|
||||||
|
fprintf(stderr, "Setting alarm delta to %lld returned %lld\n",
|
||||||
|
(long long)some_values[i],
|
||||||
|
(long long)value);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
free(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int screen;
|
||||||
|
xcb_connection_t *c = xcb_connect(NULL, &screen);
|
||||||
|
xcb_query_extension_reply_t *ext = xcb_get_extension_data(c, &xcb_sync_id);
|
||||||
|
|
||||||
|
if (!ext->present) {
|
||||||
|
printf("No XSync present\n");
|
||||||
|
exit(77);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_create_counter(c);
|
||||||
|
test_set_counter(c);
|
||||||
|
test_change_counter_basic(c);
|
||||||
|
test_change_counter_overflow(c);
|
||||||
|
test_change_alarm_value(c);
|
||||||
|
test_change_alarm_delta(c);
|
||||||
|
|
||||||
|
xcb_disconnect(c);
|
||||||
|
exit(0);
|
||||||
|
}
|
Loading…
Reference in New Issue