libei/test/test-eis.c
Peter Hutterer 93b96e42ad Add an EIS-controlled seat to the hierarchy
After CONNECT, the EIS implementation needs to add one or more seats. The
libei client can only create devices within those seats. This mirrors the
wayland hierarchy as well as the X.Org one.

The seat has a set of allowed capabilities, so the client knows ahead of time
when it may not be possible to create a specific device.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2020-10-21 10:47:47 +10:00

332 lines
9.5 KiB
C

/*
* Copyright © 2020 Red Hat, Inc.
*
* 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 "config.h"
#include "util-munit.h"
#include "eierpecken.h"
MUNIT_TEST(eistest_ref_unref)
{
struct eis *eis = eis_new(NULL);
struct eis *refd = eis_ref(eis);
munit_assert_ptr_equal(eis, refd);
struct eis *unrefd = eis_unref(eis);
munit_assert_ptr_null(unrefd);
unrefd = eis_unref(eis);
munit_assert_ptr_null(unrefd);
/* memleak only shows up in valgrind */
return MUNIT_OK;
}
MUNIT_TEST(eistest_name)
{
_cleanup_peck_ struct peck *peck = peck_new();
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
/* The name is set by peck_new() and immutable after the
* backend was set, which peck_new() does for us as well.
* So the name we should see is the one hardcoded in peck_new()
*/
with_client(peck) {
ei_configure_name(ei, "this name should not be used");
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_cleanup_eis_event_ struct eis_event *event = eis_get_event(eis);
munit_assert_ptr_not_null(event);
munit_assert_int(eis_event_get_type(event), ==, EIS_EVENT_CLIENT_CONNECT);
struct eis_client *client = eis_event_get_client(event);
munit_assert_string_equal(eis_client_get_name(client), "eierpecken test context");
}
return MUNIT_OK;
}
MUNIT_TEST(eistest_ranges)
{
_cleanup_peck_ struct peck *peck = peck_new();
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER_ABSOLUTE);
ei_device_configure_capability(d, EI_DEVICE_CAP_TOUCH);
ei_device_pointer_configure_range(d, 1024, 768);
ei_device_touch_configure_range(d, 1920, 1200);
ei_device_add(d);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_cleanup_eis_event_ struct eis_event *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *device = eis_event_get_device(event);
munit_assert(eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE));
munit_assert(eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH));
munit_assert_int(eis_device_pointer_get_width(device), ==, 1024);
munit_assert_int(eis_device_pointer_get_height(device), ==, 768);
munit_assert_int(eis_device_touch_get_width(device), ==, 1920);
munit_assert_int(eis_device_touch_get_height(device), ==, 1200);
}
return MUNIT_OK;
}
MUNIT_TEST(eistest_device_resume_suspend_twice)
{
_cleanup_peck_ struct peck *peck = peck_new();
_cleanup_eis_device_ struct eis_device *device = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER);
ei_device_add(d);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_cleanup_eis_event_ struct eis_event *added =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
device = eis_device_ref(eis_event_get_device(added));
eis_device_allow_capability(device, EIS_DEVICE_CAP_POINTER);
eis_device_connect(device);
/* Resuming multiple times should only trigger one event */
eis_device_resume(device);
eis_device_resume(device); /* noop */
eis_device_resume(device); /* noop */
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_cleanup_ei_event_ struct ei_event *added =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
/* _until_stable() may stop after DEVICE_ADDED since it's
* punting to the caller, so we need another dispatch to
* make sure the RESUMED is really waiting for us here */
ei_dispatch(ei);
_cleanup_ei_event_ struct ei_event *resumed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED);
peck_assert_no_ei_events(ei);
}
/* Suspending multiple times should only trigger one event */
with_server(peck) {
eis_device_suspend(device);
eis_device_suspend(device); /* noop */
eis_device_suspend(device); /* noop */
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_cleanup_ei_event_ struct ei_event *suspended =
peck_ei_next_event(ei, EI_EVENT_DEVICE_SUSPENDED);
peck_assert_no_ei_events(ei);
}
return MUNIT_OK;
}
MUNIT_TEST(eistest_device_ignore_suspended)
{
_cleanup_peck_ struct peck *peck = peck_new();
_cleanup_eis_device_ struct eis_device *device = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
_cleanup_ei_device_ struct ei_device *d = ei_device_new(seat);
ei_device_configure_capability(d, EI_DEVICE_CAP_POINTER);
ei_device_add(d);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_cleanup_eis_event_ struct eis_event *added =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
device = eis_device_ref(eis_event_get_device(added));
eis_device_allow_capability(device, EIS_DEVICE_CAP_POINTER);
eis_device_connect(device);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_cleanup_ei_event_ struct ei_event *added =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
struct ei_device *device = ei_event_get_device(added);
peck_assert_no_ei_events(ei);
ei_device_pointer_motion(device, 1, 1);
}
for (size_t i = 0; i < 3; i++) {
/* Device is suspended */
with_server(peck) {
peck_assert_no_eis_events(eis);
eis_device_resume(device);
}
peck_dispatch_until_stable(peck);
/* Device is resumed */
with_client(peck) {
_cleanup_ei_event_ struct ei_event *resumed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED);
struct ei_device *device = ei_event_get_device(resumed);
peck_assert_no_ei_events(ei);
ei_device_pointer_motion(device, 1, 1);
}
peck_dispatch_until_stable(peck);
/* Device is resumed */
with_server(peck) {
_cleanup_eis_event_ struct eis_event *rel =
peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION);
peck_assert_no_eis_events(eis);
eis_device_suspend(device);
}
peck_dispatch_until_stable(peck);
/* Device is suspended */
with_client(peck) {
_cleanup_ei_event_ struct ei_event *suspended =
peck_ei_next_event(ei, EI_EVENT_DEVICE_SUSPENDED);
struct ei_device *device = ei_event_get_device(suspended);
peck_assert_no_ei_events(ei);
ei_device_pointer_motion(device, 1, 1);
}
}
return MUNIT_OK;
}
MUNIT_TEST(eistest_device_late_connect)
{
_cleanup_peck_ struct peck *peck = peck_new();
_cleanup_eis_device_ struct eis_device *eis_device = NULL;
_cleanup_ei_device_ struct ei_device *ei_device = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
ei_device = ei_device_new(seat);
ei_device_configure_capability(ei_device, EI_DEVICE_CAP_POINTER);
ei_device_add(ei_device);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_cleanup_eis_event_ struct eis_event *added =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
eis_device = eis_device_ref(eis_event_get_device(added));
/* Do not connect here */
}
peck_dispatch_until_stable(peck);
with_client(peck) {
/* remove before server accepted */
ei_device_remove(ei_device);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
/* accept even though the remove event is already pending */
eis_device_allow_capability(eis_device, EIS_DEVICE_CAP_POINTER);
eis_device_connect(eis_device);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_cleanup_eis_event_ struct eis_event *removed =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED);
peck_assert_no_eis_events(eis);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_cleanup_ei_event_ struct ei_event *added =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
_cleanup_ei_event_ struct ei_event *removed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
peck_assert_no_ei_events(ei);
}
return MUNIT_OK;
}
int
main(int argc, char **argv)
{
return munit_tests_run(argc, argv);
}