[PATCH xserver 4/6] test: Add basic SYNC tests.

Eric Anholt eric at anholt.net
Tue Sep 19 00:34:31 UTC 2017


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 at anholt.net>
Reviewed-by: Keith Packard <keithp at keithp.com>
---
 hw/vfb/meson.build    |   2 +-
 test/meson.build      |   2 +
 test/sync/meson.build |   9 ++
 test/sync/sync.c      | 304 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 316 insertions(+), 1 deletion(-)
 create mode 100644 test/sync/meson.build
 create mode 100644 test/sync/sync.c

diff --git a/hw/vfb/meson.build b/hw/vfb/meson.build
index 6566b45907f1..89acdfacd371 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 b71d7e24909d..3e482d6f19cd 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 000000000000..dfae75b1ed53
--- /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 000000000000..f25d3fa3774a
--- /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);
+}
-- 
2.14.1



More information about the xorg-devel mailing list