tests: add tests for devices handling
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@gmail.com> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
parent
8a5523c3ec
commit
5fd814090e
@ -938,7 +938,8 @@ weston_tests = \
|
||||
text.weston \
|
||||
presentation.weston \
|
||||
roles.weston \
|
||||
subsurface.weston
|
||||
subsurface.weston \
|
||||
devices.weston
|
||||
|
||||
|
||||
AM_TESTS_ENVIRONMENT = \
|
||||
@ -1029,6 +1030,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 \
|
||||
|
308
tests/devices-test.c
Normal file
308
tests/devices-test.c
Normal file
@ -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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user