#include "config.h" #include #include #include "util-munit.h" #include "libei.h" #include "eierpecken.h" MUNIT_TEST(test_ei_ref_unref) { 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) { _cleanup_peck_ struct peck *peck = peck_new(); /* Client is immediately rejected */ peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_REJECT_CLIENT); peck_dispatch_until_stable(peck); /* Expect the client to get a disconnect event */ with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_connect) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct 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); _cleanup_ei_event_ struct ei_event *e = peck_ei_next_event(ei, EI_EVENT_CONNECT); } with_server(peck) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *e = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_add_before_received) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct 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); } peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_device_ struct ei_device *device = ei_device_new(ei); 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) { eis_client_disconnect(client); } /* But from the POV of the client we have added our devices, so we * must receive a Removed event. */ with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *removed = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_add_after_received) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct 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); } peck_dispatch_until_stable(peck); with_client(peck) { _cleanup_ei_device_ struct ei_device *device = ei_device_new(ei); 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) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *removed = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_remove_before_received) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; _cleanup_ei_device_ struct ei_device *device = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct 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); } peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_dispatch_until_stable(peck); with_client(peck) { device = ei_device_new(ei); 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) { _cleanup_ei_event_ struct ei_event *added = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); _cleanup_ei_event_ struct ei_event *resumed = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); ei_device_remove(device); } /* Disconnect before the server processed the Removed message. This * does **not** trigger a EI_EVENT_REMOVED, the device has already * been removed by the client. */ with_server(peck) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_disconnect_after_remove_after_received) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_eis_client_ struct eis_client *client = NULL; _cleanup_ei_device_ struct ei_device *device = NULL; peck_dispatch_until_stable(peck); with_server(peck) { eis_dispatch(eis); _cleanup_eis_event_ struct 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); } peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_dispatch_until_stable(peck); with_client(peck) { device = ei_device_new(ei); 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) { _cleanup_ei_event_ struct ei_event *added = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); _cleanup_ei_event_ struct ei_event *resumed = peck_ei_next_event(ei, EI_EVENT_DEVICE_RESUMED); ei_device_remove(device); } /* Disconnect after the server processed the Removed message. This * does **not** trigger a EI_EVENT_REMOVED, the device has already * been removed by the client. */ peck_dispatch_eis(peck); with_server(peck) { eis_client_disconnect(client); } with_client(peck) { ei_dispatch(ei); _cleanup_ei_event_ struct ei_event *disconnect = peck_ei_next_event(ei, EI_EVENT_DISCONNECT); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_basics) { _cleanup_peck_ struct peck *peck = peck_new(); _cleanup_ei_device_ struct ei_device *device = NULL; peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_dispatch_until_stable(peck); /* device creation and getters/setters test */ with_client(peck) { device = ei_device_new(ei); 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_add) { _cleanup_peck_ struct peck *peck = peck_new(); with_server(peck) { peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL); peck_dispatch_eis(peck); } with_client(peck) { peck_drain_ei(ei); } _cleanup_ei_device_ struct ei_device *device = NULL; with_client(peck) { device = ei_device_new(ei); 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) { _cleanup_ei_event_ struct ei_event *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_ADDED); 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)); } return MUNIT_OK; } MUNIT_TEST(test_ei_device_add_drop_caps) { _cleanup_peck_ struct 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); _cleanup_ei_device_ struct ei_device *device = NULL; with_client(peck) { device = ei_device_new(ei); 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); _cleanup_ei_event_ struct 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) { _cleanup_peck_ struct 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); _cleanup_ei_device_ struct ei_device *device = NULL; with_client(peck) { device = ei_device_new(ei); 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); _cleanup_ei_event_ struct ei_event *event = peck_ei_next_event(ei, EI_EVENT_DEVICE_REMOVED); } return MUNIT_OK; } int main(int argc, char **argv) { return munit_tests_run(argc, argv); }