libei/test/test-ei.c

1138 lines
32 KiB
C
Raw Normal View History

2020-08-05 17:12:54 +10:00
#include "config.h"
#include <errno.h>
2020-08-05 17:12:54 +10:00
#include <sys/types.h>
#include <sys/socket.h>
#include "util-io.h"
#include "util-munit.h"
#include "util-memfile.h"
2020-08-05 17:12:54 +10:00
#include "libei.h"
#include "eierpecken.h"
DEFINE_UNREF_CLEANUP_FUNC(peck);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct memfile *, memfile_unref);
#define _cleanup_memfile_ _cleanup_(memfile_unrefp)
MUNIT_TEST(test_ei_ref_unref)
2020-08-05 17:12:54 +10:00
{
struct ei *ei = ei_new(NULL);
struct ei *refd = ei_ref(ei);
munit_assert_ptr_equal(ei, refd);
struct ei *unrefd = ei_unref(ei);
munit_assert_ptr_null(unrefd);
unrefd = ei_unref(ei);
munit_assert_ptr_null(unrefd);
/* memleak only shows up in valgrind */
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_immediately)
2020-08-05 17:12:54 +10:00
{
_unref_(peck) *peck = peck_new();
2020-08-05 17:12:54 +10:00
/* Client is immediately rejected */
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_REJECT_CLIENT);
peck_dispatch_until_stable(peck);
2020-08-05 17:12:54 +10:00
/* Expect the client to get a disconnect event */
with_client(peck) {
ei_dispatch(ei);
_unref_(ei_event) *disconnect =
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
2020-08-05 17:12:54 +10:00
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_connect)
2020-08-05 17:12:54 +10:00
{
_unref_(peck) *peck = peck_new();
_unref_(eis_client) *client = NULL;
2020-08-05 17:12:54 +10:00
peck_dispatch_until_stable(peck);
2020-08-05 17:12:54 +10:00
with_server(peck) {
eis_dispatch(eis);
_unref_(eis_event) *e =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
client = eis_client_ref(eis_event_get_client(e));
eis_client_connect(client);
}
with_client(peck) {
ei_dispatch(ei);
_unref_(ei_event) *e =
peck_ei_next_event(ei, EI_EVENT_CONNECT);
}
with_server(peck) {
eis_client_disconnect(client);
}
with_client(peck) {
ei_dispatch(ei);
_unref_(ei_event) *e =
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_add_before_received)
{
_unref_(peck) *peck = peck_new();
_unref_(eis_client) *client = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
_unref_(ei_device) *device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
ei_device_add(device);
}
/* We have *not* called eis_dispatch, so the device add hasn't been
* processed by the server yet */
with_server(peck) {
struct eis_client *client = peck_eis_get_default_client(peck);
eis_client_disconnect(client);
}
with_client(peck) {
ei_dispatch(ei);
_unref_(ei_event) *device_removed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
_unref_(ei_event) *seat_removed =
peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED);
_unref_(ei_event) *disconnect =
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_add_after_received)
{
_unref_(peck) *peck = peck_new();
_unref_(eis_client) *client = 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);
_unref_(ei_device) *device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
ei_device_add(device);
}
/* Receive the Added event but don't actually add the device */
peck_dispatch_eis(peck);
with_server(peck) {
struct eis_client *client = peck_eis_get_default_client(peck);
eis_client_disconnect(client);
}
2020-08-05 17:12:54 +10:00
with_client(peck) {
ei_dispatch(ei);
_unref_(ei_event) *device_removed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
_unref_(ei_event) *seat_removed =
peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED);
_unref_(ei_event) *disconnect =
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_remove_before_received)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_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);
device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
ei_device_add(device);
}
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
/* server has the device now */
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *added =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
_unref_(ei_event) *resumed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED);
ei_device_remove(device);
}
/* No server dispatch here so the server isn't aware of the
* ei_device_remove() call. Disconnect the client, this
* automatically removes all devices */
2020-08-05 17:12:54 +10:00
with_server(peck) {
struct eis_client *client = peck_eis_get_default_client(peck);
2020-08-05 17:12:54 +10:00
eis_client_disconnect(client);
}
with_client(peck) {
ei_dispatch(ei);
_unref_(ei_event) *device_removed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
_unref_(ei_event) *seat_removed =
peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED);
_unref_(ei_event) *disconnect =
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_remove_after_received)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_device) *device = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
ei_device_add(device);
}
/* server has the device now */
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *added =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
_unref_(ei_event) *resumed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED);
ei_device_remove(device);
}
/* Dispatch, server is aware of the ei_device_remove() */
peck_dispatch_eis(peck);
with_server(peck) {
struct eis_client *client = peck_eis_get_default_client(peck);
eis_client_disconnect(client);
}
peck_dispatch_ei(peck);
with_client(peck) {
_unref_(ei_event) *device_removed =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
_unref_(ei_event) *seat_removed =
peck_ei_next_event(ei, EI_EVENT_SEAT_REMOVED);
_unref_(ei_event) *disconnect =
peck_ei_next_event(ei, EI_EVENT_DISCONNECT);
2020-08-05 17:12:54 +10:00
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_basics)
2020-08-05 17:12:54 +10:00
{
_unref_(peck) *peck = peck_new();
_unref_(ei_device) *device = NULL;
2020-08-05 17:12:54 +10:00
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_dispatch_until_stable(peck);
2020-08-05 17:12:54 +10:00
/* device creation and getters/setters test */
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
2020-08-05 17:12:54 +10:00
munit_assert_not_null(device);
ei_device_configure_name(device, __func__);
munit_assert_string_equal(ei_device_get_name(device), __func__);
bool success = ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
munit_assert(success);
munit_assert(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER));
/* Add it, but we don't care about whether it worked correctly in this test */
ei_device_add(device);
/* Device is immutable after ei_device_add() */
bool failed_caps = ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
munit_assert(failed_caps == false);
munit_assert(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER));
}
/* Drain both sides, we don't care about the events themselves */
with_server(peck) {
peck_drain_eis(eis);
}
with_client(peck) {
peck_drain_ei(ei);
}
/* device is still immutable */
with_client(peck) {
bool failed_caps = ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
munit_assert(failed_caps == false);
munit_assert(ei_device_has_capability(device, EI_DEVICE_CAP_POINTER));
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_set_name)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_device) *d1 = NULL;
_unref_(ei_device) *d2 = NULL;
_unref_(ei_device) *d3 = 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);
d1 = ei_device_new(seat);
ei_device_configure_name(d1, "first device");
ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER);
ei_device_add(d1);
d2 = ei_device_new(seat);
munit_assert_not_null(d2);
ei_device_configure_name(d2, "second device");
ei_device_configure_capability(d2, EI_DEVICE_CAP_POINTER);
ei_device_add(d2);
d3 = ei_device_new(seat);
munit_assert_not_null(d3);
ei_device_configure_name(d3, "third device");
ei_device_configure_capability(d3, EI_DEVICE_CAP_POINTER);
ei_device_add(d3);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *e1 =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *d1 = eis_event_get_device(e1);
munit_assert_string_equal(eis_device_get_name(d1), "first device");
/* change the name */
eis_device_set_name(d1, "other name");
munit_assert_string_equal(eis_device_get_name(d1), "other name");
eis_device_allow_capability(d1, EIS_DEVICE_CAP_POINTER);
eis_device_connect(d1);
_unref_(eis_event) *e2 =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *d2 = eis_event_get_device(e2);
munit_assert_string_equal(eis_device_get_name(d2), "second device");
/* unset the name */
eis_device_set_name(d2, NULL);
munit_assert_ptr_null(eis_device_get_name(d2));
eis_device_allow_capability(d2, EIS_DEVICE_CAP_POINTER);
eis_device_connect(d2);
_unref_(eis_event) *e3 =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *d3 = eis_event_get_device(e3);
munit_assert_string_equal(eis_device_get_name(d3), "third device");
/* leave the name as-is */
eis_device_allow_capability(d3, EIS_DEVICE_CAP_POINTER);
eis_device_connect(d3);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *e1 =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
munit_assert_ptr_equal(d1, ei_event_get_device(e1));
munit_assert_string_equal(ei_device_get_name(d1), "other name");
_unref_(ei_event) *e2 =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
munit_assert_ptr_equal(d2, ei_event_get_device(e2));
munit_assert_ptr_null(ei_device_get_name(d2));
_unref_(ei_event) *e3 =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
munit_assert_ptr_equal(d3, ei_event_get_device(e3));
munit_assert_string_equal(ei_device_get_name(d3), "third device");
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_add_remove)
2020-08-05 17:12:54 +10:00
{
_unref_(peck) *peck = peck_new();
2020-08-05 17:12:54 +10:00
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);
_unref_(ei_device) *device = NULL;
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
ei_device_add(device);
}
peck_dispatch_until_stable(peck);
2020-08-05 17:12:54 +10:00
_unref_(eis_device) *eis_device = NULL;
with_server(peck) {
_unref_(eis_event) *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
eis_device = eis_device_ref(eis_event_get_device(event));
eis_device_allow_capability(eis_device, EIS_DEVICE_CAP_POINTER);
eis_device_connect(eis_device);
}
with_client(peck) {
peck_dispatch_ei(peck);
_unref_(ei_event) *event =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
2020-08-05 17:12:54 +10:00
struct ei_device *added = ei_event_get_device(event);
munit_assert_ptr_equal(device, added);
munit_assert(ei_device_has_capability(added, EI_DEVICE_CAP_POINTER));
ei_device_remove(device);
}
with_server(peck) {
peck_dispatch_eis(peck);
_unref_(eis_event) *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED);
munit_assert_ptr_equal(eis_event_get_device(event), eis_device);
eis_device_disconnect(eis_device);
}
with_client(peck) {
peck_dispatch_ei(peck);
_unref_(ei_event) *event =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
struct ei_device *removed = ei_event_get_device(event);
munit_assert_ptr_equal(device, removed);
}
2020-08-05 17:12:54 +10:00
2020-08-05 17:12:54 +10:00
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_remove_forget_disconnect)
{
_unref_(peck) *peck = peck_new();
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_dispatch_until_stable(peck);
_unref_(ei_device) *d1 = NULL;
_unref_(ei_device) *d2 = NULL;
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
d1 = ei_device_new(seat);
ei_device_configure_name(d1, "first");
ei_device_configure_capability(d1, EI_DEVICE_CAP_POINTER);
ei_device_add(d1);
d2 = ei_device_new(seat);
ei_device_configure_name(d2, "second");
ei_device_configure_capability(d2, EI_DEVICE_CAP_KEYBOARD);
ei_device_add(d2);
}
peck_dispatch_until_stable(peck);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
with_client(peck) {
/* remove in order d1, d2 */
ei_device_remove(d1);
ei_device_remove(d2);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *e1 =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED);
_unref_(eis_event) *e2 =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED);
/* Explicitly disconnect device d2 */
eis_device_disconnect(eis_event_get_device(e2));
/* But don't eis_device_disconnect(d1). It doesn't matter
* because libeis will do this for us when receiving the
* event. */
}
peck_dispatch_ei(peck);
with_client(peck) {
_unref_(ei_event) *e1 =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
struct ei_device *r1 = ei_event_get_device(e1);
munit_assert_ptr_equal(d1, r1);
_unref_(ei_event) *e2 =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
struct ei_device *r2 = ei_event_get_device(e2);
munit_assert_ptr_equal(d2, r2);
peck_assert_no_ei_events(ei);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_add_drop_caps)
{
_unref_(peck) *peck = peck_new();
/* Device with pointer and keyboard caps but pointer is dropped */
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DROP_POINTER);
peck_dispatch_until_stable(peck);
_unref_(ei_device) *device = NULL;
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD);
ei_device_add(device);
}
peck_dispatch_eis(peck);
with_client(peck) {
ei_dispatch(ei);
_unref_(ei_event) *event =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
struct ei_device *d = ei_event_get_device(event);
munit_assert_ptr_equal(d, device);
munit_assert(ei_device_has_capability(d, EI_DEVICE_CAP_KEYBOARD));
munit_assert(!ei_device_has_capability(d, EI_DEVICE_CAP_POINTER));
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_add_zero_caps)
{
_unref_(peck) *peck = peck_new();
/* Device with pointer caps but those caps are rejected -> device
immediately removed by EIS */
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DROP_POINTER);
peck_dispatch_until_stable(peck);
_unref_(ei_device) *device = NULL;
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
ei_device_add(device);
}
peck_dispatch_eis(peck);
with_client(peck) {
ei_dispatch(ei);
_unref_(ei_event) *event =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_pointer_rel)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_device) *device = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
munit_assert_not_null(device);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER);
ei_device_add(device);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
ei_device_pointer_motion(device, 1, 2);
ei_device_pointer_motion(device, 0.3, 1.4);
ei_device_pointer_motion(device, 100, 200);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *first =
peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION);
munit_assert_double_equal(eis_event_pointer_get_dx(first), 1.0, 2 /* precision */);
munit_assert_double_equal(eis_event_pointer_get_dy(first), 2.0, 2 /* precision */);
_unref_(eis_event) *second =
peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION);
munit_assert_double_equal(eis_event_pointer_get_dx(second), 0.3, 2 /* precision */);
munit_assert_double_equal(eis_event_pointer_get_dy(second), 1.4, 2 /* precision */);
_unref_(eis_event) *third =
peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION);
munit_assert_double_equal(eis_event_pointer_get_dx(third), 100, 2 /* precision */);
munit_assert_double_equal(eis_event_pointer_get_dy(third), 200, 2 /* precision */);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_pointer_abs)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_device) *device = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
munit_assert_not_null(device);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE);
ei_device_pointer_configure_range(device, 1920, 1200);
ei_device_add(device);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
for (int i = 0; i < 10; i++)
ei_device_pointer_motion_absolute(device, 1 * i , 2 + i);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
for (int i = 0; i < 10; i++) {
_unref_(eis_event) *e =
peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION_ABSOLUTE);
munit_assert_double_equal(eis_event_pointer_get_absolute_x(e), 1.0 * i, 2 /* precision */);
munit_assert_double_equal(eis_event_pointer_get_absolute_y(e), 2.0 + i, 2 /* precision */);
}
}
with_client(peck) {
/* outside of pointer range, expect to be discarded */
ei_device_pointer_motion_absolute(device, 1920, 1200);
ei_device_pointer_motion_absolute(device, 2000, 1400);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
peck_assert_no_eis_events(eis);
}
with_client(peck) {
ei_device_remove(device);
/* absmotion after remove must not trigger an event */
ei_device_pointer_motion_absolute(device, 100, 200);
}
with_server(peck) {
/* Don't auto-handle the removed event */
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_dispatch_eis(peck);
_unref_(eis_event) *e =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_REMOVED);
peck_assert_no_eis_events(eis);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_touch)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_device) *device = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
munit_assert_not_null(device);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_TOUCH);
ei_device_touch_configure_range(device, 1024, 768);
ei_device_add(device);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 1, 2);
ei_touch_motion(t, 200, 500);
ei_touch_up(t);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *down = peck_eis_touch_down(eis, 1, 2);
uint32_t tid = eis_event_touch_get_id(down);
_unref_(eis_event) *motion = peck_eis_touch_motion(eis, 200, 500);
munit_assert_uint32(eis_event_touch_get_id(motion), ==, tid);
_unref_(eis_event) *up = peck_eis_touch_up(eis);
munit_assert_uint32(eis_event_touch_get_id(up), ==, tid);
}
with_client(peck) {
_unref_(ei_touch) *t = ei_device_touch_new(device);
/* outside clip range, expect touch to be dropped */
ei_touch_down(t, 1200, 100);
ei_touch_motion(t, 200, 200);
ei_touch_up(t);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
peck_assert_no_eis_events(eis);
}
with_client(peck) {
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 100, 200);
/* outside allowed range, generates a touch up */
ei_touch_motion(t, 1200, 200);
ei_touch_up(t);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200);
_unref_(eis_event) *up = peck_eis_touch_up(eis);
}
with_client(peck) {
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 100, 100);
/* client forgets to touch up, touch_unref takes care of it */
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 100);
_unref_(eis_event) *up = peck_eis_touch_up(eis);
}
with_client(peck) {
/* touch only allocated, not actually set down */
_unref_(ei_touch) *t1 = ei_device_touch_new(device);
/* touch never set down */
_unref_(ei_touch) *t2 = ei_device_touch_new(device);
ei_touch_up(t2);
/* touch never set down */
_unref_(ei_touch) *t3 = ei_device_touch_new(device);
ei_touch_motion(t3, 100, 200);
ei_touch_up(t3);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
peck_assert_no_eis_events(eis);
}
with_client(peck) {
/* touch re-used */
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 100, 200);
ei_touch_up(t);
ei_touch_down(t, 200, 300);
ei_touch_motion(t, 300, 400);
ei_touch_up(t);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200);
_unref_(eis_event) *up = peck_eis_touch_up(eis);
peck_assert_no_eis_events(eis);
}
with_client(peck) {
/* double-down, double-up */
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 100, 200);
ei_touch_down(t, 200, 300); /* ignored */
ei_touch_motion(t, 300, 400);
ei_touch_up(t);
ei_touch_up(t); /* ignored */
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *down = peck_eis_touch_down(eis, 100, 200);
_unref_(eis_event) *motion = peck_eis_touch_motion(eis, 300, 400);
_unref_(eis_event) *up = peck_eis_touch_up(eis);
peck_assert_no_eis_events(eis);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_device_multitouch)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_device) *device = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
munit_assert_not_null(device);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_TOUCH);
ei_device_touch_configure_range(device, 1024, 768);
ei_device_add(device);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_touch) *t1 = ei_device_touch_new(device);
_unref_(ei_touch) *t2 = ei_device_touch_new(device);
ei_touch_down(t1, 1, 2);
ei_touch_motion(t1, 2, 3);
ei_touch_down(t2, 3, 4);
ei_touch_motion(t2, 4, 5);
ei_touch_up(t2);
ei_touch_up(t1);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *down1 = peck_eis_touch_down(eis, 1, 2);
uint32_t tid1 = eis_event_touch_get_id(down1);
_unref_(eis_event) *motion1 = peck_eis_touch_motion(eis, 2, 3);
munit_assert_uint32(eis_event_touch_get_id(motion1), ==, tid1);
_unref_(eis_event) *down2 = peck_eis_touch_down(eis, 3, 4);
uint32_t tid2 = eis_event_touch_get_id(down2);
munit_assert_uint32(tid2, !=, tid1);
_unref_(eis_event) *motion2 = peck_eis_touch_motion(eis, 4, 5);
munit_assert_uint32(eis_event_touch_get_id(motion2), ==, tid2);
_unref_(eis_event) *up2 = peck_eis_touch_up(eis);
munit_assert_uint32(eis_event_touch_get_id(up2), ==, tid2);
_unref_(eis_event) *up1 = peck_eis_touch_up(eis);
munit_assert_uint32(eis_event_touch_get_id(up1), ==, tid1);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_keymap_invalid)
{
const char data[5] = {1, 2, 3, 4, 5};
_unref_(memfile) *fd = memfile_new(data, sizeof(data));
munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB + 1,
memfile_get_fd(fd), memfile_get_size(fd)));
munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB - 1,
memfile_get_fd(fd), memfile_get_size(fd)));
munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB,
-1, memfile_get_size(fd)));
munit_assert_ptr_null(ei_keymap_new(EI_KEYMAP_TYPE_XKB,
memfile_get_fd(fd), 0));
/* Valid keymap, valgrind checks only */
_unref_(ei_keymap) *unused =
ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd), memfile_get_size(fd));
munit_assert_ptr_not_null(unused);
return MUNIT_OK;
}
MUNIT_TEST(test_ei_keymap_set)
{
const char data[5] = {1, 2, 3, 4, 5};
_unref_(peck) *peck = peck_new();
_unref_(ei_device) *device = NULL;
_unref_(memfile) *fd1 = memfile_new(data, sizeof(data));
_unref_(ei_keymap) *keymap = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(memfile) *fd2 = memfile_new(data, sizeof(data));
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD);
keymap = ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd1), memfile_get_size(fd1));
ei_device_keyboard_configure_keymap(device, keymap);
munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap);
/* Not possible to overwrite a keymap on a device */
_unref_(ei_keymap) *overwrite =
ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2));
ei_device_keyboard_configure_keymap(device, overwrite);
munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap);
ei_device_add(device);
/* Still impossible to overwrite after add */
_unref_(ei_keymap) *ignored =
ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2));
ei_device_keyboard_configure_keymap(device, ignored);
munit_assert_ptr_equal(ei_device_keyboard_get_keymap(device), keymap);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *eis_device = eis_event_get_device(event);
struct eis_keymap *eis_keymap = eis_device_keyboard_get_keymap(eis_device);
int fd = eis_keymap_get_fd(eis_keymap);
munit_assert_int(fd, !=, -1);
munit_assert_uint(eis_keymap_get_size(eis_keymap), ==, memfile_get_size(fd1));
munit_assert_uint(eis_keymap_get_type(eis_keymap), ==, EIS_KEYMAP_TYPE_XKB);
eis_device_disconnect(eis_device);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event =
peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED);
struct ei_device *d = ei_event_get_device(event);
munit_assert_ptr_equal(d, device);
/* Rejecting a device does not unset the keymap because
* you're not supposed to do anything with the device anyway */
struct ei_keymap *km = ei_device_keyboard_get_keymap(device);
munit_assert_ptr_equal(keymap, km);
munit_assert_int(ei_keymap_get_source(keymap), ==, EI_KEYMAP_SOURCE_CLIENT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_keymap_null)
{
const char data[5] = {1, 2, 3, 4, 5};
_unref_(peck) *peck = peck_new();
_unref_(memfile) *fd = memfile_new(data, sizeof(data));
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_seat *seat = peck_ei_get_default_seat(peck);
_unref_(ei_device) *device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD);
_unref_(ei_keymap) *keymap =
ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd), memfile_get_size(fd));
ei_device_keyboard_configure_keymap(device, keymap);
ei_device_add(device);
}
peck_dispatch_until_stable(peck);
/* server sets the keymap to NULL */
with_server(peck) {
_unref_(eis_event) *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *device = eis_event_get_device(event);
eis_device_keyboard_set_keymap(device, NULL);
eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD);
eis_device_connect(device);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
struct ei_device *device = ei_event_get_device(event);
struct ei_keymap *keymap = ei_device_keyboard_get_keymap(device);
munit_assert_ptr_null(keymap);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_keymap_changed)
{
const char data[5] = {1, 2, 3, 4, 5};
_unref_(peck) *peck = peck_new();
_unref_(memfile) *fd1 = memfile_new(data, sizeof(data));
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_CLIENT);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_DEFAULT_SEAT);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNNECT);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_device) *device = NULL;
const char otherdata[2] = {10, 20};
_unref_(memfile) *fd2 = memfile_new(data, sizeof(otherdata));
struct ei_seat *seat = peck_ei_get_default_seat(peck);
device = ei_device_new(seat);
ei_device_configure_name(device, __func__);
ei_device_configure_capability(device, EI_DEVICE_CAP_KEYBOARD);
_unref_(ei_keymap) *keymap =
ei_keymap_new(EI_KEYMAP_TYPE_XKB, memfile_get_fd(fd2), memfile_get_size(fd2));
ei_device_keyboard_configure_keymap(device, keymap);
ei_device_add(device);
}
peck_dispatch_until_stable(peck);
/* server sets the keymap to some other fd */
with_server(peck) {
_unref_(eis_event) *event =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_ADDED);
struct eis_device *device = eis_event_get_device(event);
_unref_(eis_keymap) *keymap =
eis_keymap_new(EIS_KEYMAP_TYPE_XKB, memfile_get_fd(fd1),
memfile_get_size(fd1));
eis_device_keyboard_set_keymap(device, keymap);
eis_device_allow_capability(device, EIS_DEVICE_CAP_KEYBOARD);
eis_device_connect(device);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event =
peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED);
struct ei_device *device = ei_event_get_device(event);
struct ei_keymap *keymap = ei_device_keyboard_get_keymap(device);
munit_assert_ptr_not_null(keymap);
munit_assert_int(ei_keymap_get_type(keymap), ==, EI_KEYMAP_TYPE_XKB);
munit_assert_int(ei_keymap_get_source(keymap), ==, EI_KEYMAP_SOURCE_SERVER);
int km = ei_keymap_get_fd(keymap);
char buf[5];
int rc = min(xread(km, buf, sizeof(buf)), 0);
peck_errno_check(rc);
munit_assert_int(memcmp(buf, data, sizeof(buf)), ==, 0);
}
return MUNIT_OK;
}
2020-08-05 17:12:54 +10:00
int
main(int argc, char **argv)
2020-08-05 17:12:54 +10:00
{
return munit_tests_run(argc, argv);
2020-08-05 17:12:54 +10:00
}