libei/test/test-ei.c

546 lines
15 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: MIT */
/*
* 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.
*/
2020-08-05 17:12:54 +10:00
#include "config.h"
#include <unistd.h>
#include <fcntl.h>
#include "util-munit.h"
#include "util-strings.h"
2020-08-05 17:12:54 +10:00
#include "eierpecken.h"
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_self_immediately)
{
_unref_(peck) *peck = peck_new();
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_dispatch_until_stable(peck);
/* Disconnect before server processed CONNECT */
with_client(peck) {
peck_drop_ei(peck);
ei_unref(ei);
}
peck_dispatch_until_stable(peck);
/* Expect the client to get a disconnect event */
with_server(peck) {
_unref_(eis_event) *connect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
_unref_(eis_event) *disconnect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT);
}
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_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
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_self_after_connect)
{
_unref_(peck) *peck = peck_new();
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_dispatch_until_stable(peck);
with_client(peck) {
peck_drop_ei(peck);
ei_unref(ei);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *connect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
_unref_(eis_event) *disconnect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_seat)
{
_unref_(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_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *connect =
peck_ei_next_event(ei, EI_EVENT_CONNECT);
_unref_(ei_event) *seat =
peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
}
with_server(peck) {
struct eis_client *client = peck_eis_get_default_client(peck);
eis_client_disconnect(client);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *seat =
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_self_after_seat)
{
_unref_(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_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *connect =
peck_ei_next_event(ei, EI_EVENT_CONNECT);
_unref_(ei_event) *seat =
peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
peck_drop_ei(peck);
/* Disconnect from client */
ei_unref(ei);
/* There is no way to disconnect from the server without
* destroying the context, so we don't care about the actual
* events here
*/
}
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *disconnect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_bind_before_received)
{
_unref_(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_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
struct ei_seat *seat = ei_event_get_seat(event);
ei_seat_bind_capability(seat, EI_DEVICE_CAP_POINTER);
}
/* We have *not* called eis_dispatch, so the seat bind 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) *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_self_after_bind_before_received)
{
_unref_(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_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
struct ei_seat *seat = ei_event_get_seat(event);
ei_seat_bind_capability(seat, EI_DEVICE_CAP_POINTER);
/* Disconnect before the server can process the bind event */
peck_drop_ei(peck);
ei_unref(ei);
}
peck_dispatch_eis(peck);
with_server(peck) {
/* Server got the bind event but client disconnected
* immediately after */
_unref_(eis_event) *bind =
peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND);
_unref_(eis_event) *unbind =
peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND);
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_POINTER));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_POINTER_ABSOLUTE));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_KEYBOARD));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_TOUCH));
_unref_(eis_event) *disconnect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_bind_after_received)
{
_unref_(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_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
struct ei_seat *seat = ei_event_get_seat(event);
ei_seat_bind_capability(seat, EI_DEVICE_CAP_POINTER);
}
/* Receive the Bind event but don't actually add any devices,
* disconnect the client instead */
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) *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_self_after_bind_after_received)
{
_unref_(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_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
struct ei_seat *seat = ei_event_get_seat(event);
ei_seat_bind_capability(seat, EI_DEVICE_CAP_POINTER);
}
/* Make sure server sees Bind, then disconnect from server */
peck_dispatch_eis(peck);
with_client(peck) {
peck_drop_ei(peck);
ei_unref(ei);
}
peck_dispatch_eis(peck);
with_server(peck) {
_unref_(eis_event) *bind =
peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND);
_unref_(eis_event) *unbind =
peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND);
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_POINTER));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_POINTER_ABSOLUTE));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_KEYBOARD));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_TOUCH));
_unref_(eis_event) *disconnect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_disconnect_after_unbind_before_received)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_seat) *seat = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
seat = ei_seat_ref(ei_event_get_seat(event));
ei_seat_bind_capability(seat, EI_DEVICE_CAP_POINTER);
}
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
/* server has the Bind event now */
peck_dispatch_until_stable(peck);
with_client(peck) {
ei_seat_unbind_capability(seat, EI_DEVICE_CAP_POINTER);
}
/* No server dispatch here so the server isn't aware of the
* ei_seat_unbind() call. Disconnect the client
*/
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) *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_unbind_after_received)
{
_unref_(peck) *peck = peck_new();
_unref_(ei_seat) *seat = NULL;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *event = peck_ei_next_event(ei, EI_EVENT_SEAT_ADDED);
seat = ei_seat_ref(ei_event_get_seat(event));
ei_seat_bind_capability(seat, EI_DEVICE_CAP_POINTER);
}
/* server has the Bind event now */
peck_dispatch_until_stable(peck);
with_client(peck) {
ei_seat_unbind_capability(seat, EI_DEVICE_CAP_POINTER);
}
/* Dispatch, server is aware of the ei_seat_unbind() */
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) *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_client_is_sender)
{
_unref_(peck) *peck = peck_new_context(PECK_EI_SENDER);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *connect = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
struct eis_client *client = eis_event_get_client(connect);
munit_assert_true(eis_client_is_sender(client));
}
return MUNIT_OK;
}
MUNIT_TEST(test_client_is_receiver)
{
_unref_(peck) *peck = peck_new_context(PECK_EI_RECEIVER);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_HANDLE_CONNECT);
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *connect = peck_eis_next_event(eis, EIS_EVENT_CLIENT_CONNECT);
struct eis_client *client = eis_event_get_client(connect);
munit_assert_false(eis_client_is_sender(client));
}
return MUNIT_OK;
}
/* Emulates the XWayland behavior for calling
* xdotool mousemove_relative -- -1 10
*/
MUNIT_TEST(test_xdotool_rel_motion)
{
_unref_(peck) *peck = peck_new();
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_POINTER);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOSTART);
peck_dispatch_until_stable(peck);
with_client(peck) {
struct ei_device *device = peck_ei_get_default_pointer(peck);
ei_device_pointer_motion(device, -1, 10);
ei_device_frame(device, peck_ei_now(peck));
ei_device_close(device);
ei_unref(ei);
peck_drop_ei(peck);
}
peck_dispatch_eis(peck);
with_server(peck) {
_unref_(eis_event) *motion =
peck_eis_next_event(eis, EIS_EVENT_POINTER_MOTION);
_unref_(eis_event) *stop =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_STOP_EMULATING);
_unref_(eis_event) *close =
peck_eis_next_event(eis, EIS_EVENT_DEVICE_CLOSED);
_unref_(eis_event) *unbind =
peck_eis_next_event(eis, EIS_EVENT_SEAT_BIND);
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_POINTER));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_POINTER_ABSOLUTE));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_KEYBOARD));
munit_assert_false(eis_event_seat_has_capability(unbind, EIS_DEVICE_CAP_TOUCH));
_unref_(eis_event) *disconnect =
peck_eis_next_event(eis, EIS_EVENT_CLIENT_DISCONNECT);
peck_assert_no_eis_events(eis);
}
return MUNIT_OK;
}