summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2017-09-18 17:34:31 -0700
committerAdam Jackson <ajax@redhat.com>2017-09-20 13:19:27 -0400
commit5cbfa276541e6a621cf9c4b44b75323e90a5bd4c (patch)
tree78e9a981ba06256da970e971f5eaaca44a9abbf8
parent3336291fc68444ee65b48ba675ec947e505fed57 (diff)
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>
-rw-r--r--hw/vfb/meson.build2
-rw-r--r--test/meson.build2
-rw-r--r--test/sync/meson.build9
-rw-r--r--test/sync/sync.c304
4 files changed, 316 insertions, 1 deletions
diff --git a/hw/vfb/meson.build b/hw/vfb/meson.build
index 6566b4590..89acdfacd 100644
--- a/hw/vfb/meson.build
+++ b/hw/vfb/meson.build
@@ -4,7 +4,7 @@ srcs = [
'../../mi/miinitext.c',
]
-executable(
+xvfb_server = executable(
'Xvfb',
srcs,
include_directories: inc,
diff --git a/test/meson.build b/test/meson.build
index b71d7e249..3e482d6f1 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -22,3 +22,5 @@ if get_option('xvfb')
)
endif
endif
+
+subdir('sync')
diff --git a/test/sync/meson.build b/test/sync/meson.build
new file mode 100644
index 000000000..dfae75b1e
--- /dev/null
+++ b/test/sync/meson.build
@@ -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
diff --git a/test/sync/sync.c b/test/sync/sync.c
new file mode 100644
index 000000000..f25d3fa37
--- /dev/null
+++ b/test/sync/sync.c
@@ -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);
+}