[PATCH weston v3] tests: add tests for devices handling
Marek Chalupa
mchqwerty at gmail.com
Mon Mar 30 06:21:29 PDT 2015
Test misc races when adding/releasing devices
v2.: use one roundtrip after releasing devices
add touch support
v3.: remove useless checks
add few comments
repeat tests 30 times instead of 100 times
(it took too long, 30 is enough)
Signed-off-by: Marek Chalupa <mchqwerty at gmail.com>
---
Makefile.am | 7 +-
tests/devices-test.c | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 314 insertions(+), 1 deletion(-)
create mode 100644 tests/devices-test.c
diff --git a/Makefile.am b/Makefile.am
index f9b7210..c78d89e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -939,7 +939,8 @@ weston_tests = \
text.weston \
presentation.weston \
roles.weston \
- subsurface.weston
+ subsurface.weston \
+ devices.weston
AM_TESTS_ENVIRONMENT = \
@@ -1030,6 +1031,10 @@ button_weston_SOURCES = tests/button-test.c
button_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
button_weston_LDADD = libtest-client.la
+devices_weston_SOURCES = tests/devices-test.c
+devices_weston_CFLAGS = $(AM_CFLAGS) $(TEST_CLIENT_CFLAGS)
+devices_weston_LDADD = libtest-client.la
+
text_weston_SOURCES = tests/text-test.c
nodist_text_weston_SOURCES = \
protocol/text-protocol.c \
diff --git a/tests/devices-test.c b/tests/devices-test.c
new file mode 100644
index 0000000..0288be3
--- /dev/null
+++ b/tests/devices-test.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright © 2015 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include "weston-test-client-helper.h"
+
+/**
+ * Test (un)plugging devices
+ *
+ * At the end of each test we must return Weston to the previous state
+ * (add all removed devices and remove extra devices), so that
+ * the environment is prepared for the other tests too
+ */
+
+#define WL_SEAT_CAPABILITY_ALL (WL_SEAT_CAPABILITY_KEYBOARD |\
+ WL_SEAT_CAPABILITY_POINTER |\
+ WL_SEAT_CAPABILITY_TOUCH)
+
+/* simply test if weston sends the right capabilities when
+ * some devices are removed */
+TEST(seat_capabilities_test)
+{
+ struct client *cl = client_create(100, 100, 100, 100);
+ assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
+
+ assert(cl->input->pointer);
+ weston_test_device_release(cl->test->weston_test, "pointer");
+ client_roundtrip(cl);
+ assert(!cl->input->pointer);
+ assert(!(cl->input->caps & WL_SEAT_CAPABILITY_POINTER));
+
+ assert(cl->input->keyboard);
+ weston_test_device_release(cl->test->weston_test, "keyboard");
+ client_roundtrip(cl);
+ assert(!cl->input->keyboard);
+ assert(!(cl->input->caps & WL_SEAT_CAPABILITY_KEYBOARD));
+
+ assert(cl->input->touch);
+ weston_test_device_release(cl->test->weston_test, "touch");
+ client_roundtrip(cl);
+ assert(!cl->input->touch);
+ assert(!(cl->input->caps & WL_SEAT_CAPABILITY_TOUCH));
+
+ /* restore previous state */
+ weston_test_device_add(cl->test->weston_test, "keyboard");
+ weston_test_device_add(cl->test->weston_test, "pointer");
+ weston_test_device_add(cl->test->weston_test, "touch");
+ client_roundtrip(cl);
+
+ assert(cl->input->pointer);
+ assert(cl->input->keyboard);
+ assert(cl->input->touch);
+
+ /* add extra devices */
+ weston_test_device_add(cl->test->weston_test, "keyboard");
+ weston_test_device_add(cl->test->weston_test, "pointer");
+ weston_test_device_add(cl->test->weston_test, "touch");
+ client_roundtrip(cl);
+
+ /* remove extra devices */
+ weston_test_device_release(cl->test->weston_test, "keyboard");
+ weston_test_device_release(cl->test->weston_test, "pointer");
+ weston_test_device_release(cl->test->weston_test, "touch");
+ client_roundtrip(cl);
+
+ /* we still should have all the capabilities, since the devices
+ * were doubled */
+ assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
+
+ assert(cl->input->pointer);
+ assert(cl->input->keyboard);
+ assert(cl->input->touch);
+}
+
+#define COUNT 15
+TEST(multiple_device_add_and_remove)
+{
+ int i;
+ struct client *cl = client_create(100, 100, 100, 100);
+
+ /* add device a lot of times */
+ for (i = 0; i < COUNT; ++i) {
+ weston_test_device_add(cl->test->weston_test, "keyboard");
+ weston_test_device_add(cl->test->weston_test, "pointer");
+ weston_test_device_add(cl->test->weston_test, "touch");
+ }
+
+ client_roundtrip(cl);
+
+ assert(cl->input->pointer);
+ assert(cl->input->keyboard);
+ assert(cl->input->touch);
+
+ assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
+
+ /* release all new devices */
+ for (i = 0; i < COUNT; ++i) {
+ weston_test_device_release(cl->test->weston_test, "keyboard");
+ weston_test_device_release(cl->test->weston_test, "pointer");
+ weston_test_device_release(cl->test->weston_test, "touch");
+ }
+
+ client_roundtrip(cl);
+
+ /* there is still one from each device left */
+ assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
+
+ assert(cl->input->pointer);
+ assert(cl->input->keyboard);
+ assert(cl->input->touch);
+}
+
+TEST(device_release_before_destroy)
+{
+ struct client *cl = client_create(100, 100, 100, 100);
+
+ /* we can release pointer when we won't be using it anymore.
+ * Do it and see what happens if the device is destroyed
+ * right after that */
+ wl_pointer_release(cl->input->pointer->wl_pointer);
+ /* we must free and set to NULL the structures, otherwise
+ * seat capabilities will double-free them */
+ free(cl->input->pointer);
+ cl->input->pointer = NULL;
+
+ wl_keyboard_release(cl->input->keyboard->wl_keyboard);
+ free(cl->input->keyboard);
+ cl->input->keyboard = NULL;
+
+ wl_touch_release(cl->input->touch->wl_touch);
+ free(cl->input->touch);
+ cl->input->touch = NULL;
+
+ weston_test_device_release(cl->test->weston_test, "pointer");
+ weston_test_device_release(cl->test->weston_test, "keyboard");
+ weston_test_device_release(cl->test->weston_test, "touch");
+ client_roundtrip(cl);
+
+ assert(cl->input->caps == 0);
+
+ /* restore previous state */
+ weston_test_device_add(cl->test->weston_test, "pointer");
+ weston_test_device_add(cl->test->weston_test, "keyboard");
+ weston_test_device_add(cl->test->weston_test, "touch");
+ client_roundtrip(cl);
+
+ assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
+}
+
+TEST(device_release_before_destroy_multiple)
+{
+ int i;
+
+ /* if weston crashed during this test, then there is
+ * some inconsistency */
+ for (i = 0; i < 30; ++i) {
+ /* Fifty times run the previous test. This will create
+ * fifty clients, because we don't have any
+ * way how to destroy them (worth of adding!). Only one
+ * client will run at a time though and so should have no
+ * effect on the result of the test (after the client
+ * finishes its body, it just 'is' and does nothing). */
+ device_release_before_destroy();
+ }
+}
+
+/* normal work-flow test */
+TEST(device_release_after_destroy)
+{
+ struct client *cl = client_create(100, 100, 100, 100);
+
+ weston_test_device_release(cl->test->weston_test, "pointer");
+ wl_pointer_release(cl->input->pointer->wl_pointer);
+ /* we must free the memory manually, otherwise seat.capabilities
+ * will try to free it and will use invalid proxy */
+ free(cl->input->pointer);
+ cl->input->pointer = NULL;
+
+ client_roundtrip(cl);
+
+ weston_test_device_release(cl->test->weston_test, "keyboard");
+ wl_keyboard_release(cl->input->keyboard->wl_keyboard);
+ free(cl->input->keyboard);
+ cl->input->keyboard = NULL;
+
+ client_roundtrip(cl);
+
+ weston_test_device_release(cl->test->weston_test, "touch");
+ wl_touch_release(cl->input->touch->wl_touch);
+ free(cl->input->touch);
+ cl->input->touch = NULL;
+
+ client_roundtrip(cl);
+
+ assert(cl->input->caps == 0);
+
+ /* restore previous state */
+ weston_test_device_add(cl->test->weston_test, "pointer");
+ weston_test_device_add(cl->test->weston_test, "keyboard");
+ weston_test_device_add(cl->test->weston_test, "touch");
+ client_roundtrip(cl);
+
+ assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
+}
+
+TEST(device_release_after_destroy_multiple)
+{
+ int i;
+
+ /* if weston crashed during this test, then there is
+ * some inconsistency */
+ for (i = 0; i < 30; ++i) {
+ device_release_after_destroy();
+ }
+}
+
+/* see https://bugzilla.gnome.org/show_bug.cgi?id=745008
+ * It is a mutter bug, but highly relevant. Weston does not
+ * suffer from this bug atm, but it is worth of testing. */
+TEST(get_device_after_destroy)
+{
+ struct client *cl = client_create(100, 100, 100, 100);
+ struct wl_pointer *wl_pointer;
+ struct wl_keyboard *wl_keyboard;
+ struct wl_touch *wl_touch;
+
+ /* There's a race:
+ * 1) compositor destroyes device
+ * 2) client asks for the device, because it has not got
+ * new capabilities yet
+ * 3) compositor gets request with new_id for destroyed device
+ * 4) client uses the new_id
+ * 5) client gets new capabilities, destroying the objects
+ *
+ * If compositor just bail out in step 3) and does not create
+ * resource, then client gets error in step 4) - even though
+ * it followed the protocol (it just didn't know about new
+ * capabilities).
+ *
+ * This test simulates this situation
+ */
+
+ /* connection is buffered, so after calling client_roundtrip(),
+ * this whole batch will be delivered to compositor and will
+ * exactly simulate our situation */
+ weston_test_device_release(cl->test->weston_test, "pointer");
+ wl_pointer = wl_seat_get_pointer(cl->input->wl_seat);
+ assert(wl_pointer);
+
+ /* this should be ignored */
+ wl_pointer_set_cursor(wl_pointer, 0, NULL, 0, 0);
+
+ /* this should not be ignored */
+ wl_pointer_release(wl_pointer);
+ client_roundtrip(cl);
+
+ weston_test_device_release(cl->test->weston_test, "keyboard");
+ wl_keyboard = wl_seat_get_keyboard(cl->input->wl_seat);
+ assert(wl_keyboard);
+ wl_keyboard_release(wl_keyboard);
+ client_roundtrip(cl);
+
+ weston_test_device_release(cl->test->weston_test, "touch");
+ wl_touch = wl_seat_get_touch(cl->input->wl_seat);
+ assert(wl_touch);
+ wl_touch_release(wl_touch);
+ client_roundtrip(cl);
+
+ /* get weston to the previous state */
+ weston_test_device_add(cl->test->weston_test, "pointer");
+ weston_test_device_add(cl->test->weston_test, "keyboard");
+ weston_test_device_add(cl->test->weston_test, "touch");
+ client_roundtrip(cl);
+
+ assert(cl->input->caps == WL_SEAT_CAPABILITY_ALL);
+}
+
+TEST(get_device_afer_destroy_multiple)
+{
+ int i;
+
+ /* if weston crashed during this test, then there is
+ * some inconsistency */
+ for (i = 0; i < 30; ++i) {
+ get_device_after_destroy();
+ }
+}
--
2.1.0
More information about the wayland-devel
mailing list