Something went wrong. Try again.
The open source OpenXR runtime
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168// Copyright 2021-2023, Collabora, Ltd.// SPDX-License-Identifier: BSL-1.0/*! * @file * @brief Generic callback collection tests. * @author Rylie Pavlik <rylie.pavlik@collabora.com> */
#include "catch_amalgamated.hpp"
#include <util/u_generic_callbacks.hpp>
using xrt::auxiliary::util::GenericCallbacks;
enum class MyEvent : std::uint8_t{ ACQUIRED = 1u << 0u, LOST = 1u << 1u,};
using mask_t = std::underlying_type_t<MyEvent>;
static boolincrement_userdata_int(MyEvent event, void *userdata){ *static_cast<int *>(userdata) += 1; return true;}
using callback_t = bool (*)(MyEvent event, void *userdata);
TEST_CASE("u_generic_callbacks"){ GenericCallbacks<callback_t, MyEvent> callbacks; // Simplest possible invoker. auto invoker = [](MyEvent event, callback_t callback, void *userdata) { return callback(event, userdata); };
SECTION("call when empty") { CHECK(0 == callbacks.invokeCallbacks(MyEvent::ACQUIRED, invoker)); CHECK(0 == callbacks.invokeCallbacks(MyEvent::LOST, invoker)); CHECK(0 == callbacks.removeCallback(&increment_userdata_int, (mask_t)MyEvent::LOST, nullptr)); } SECTION("same function, different mask and userdata") { int numAcquired = 0; int numLost = 0; REQUIRE_NOTHROW(callbacks.addCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); REQUIRE_NOTHROW(callbacks.addCallback(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); SECTION("contains") { CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); CHECK_FALSE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::LOST, &numAcquired)); } SECTION("removal matching") { CHECK(0 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, &numAcquired)); CHECK(0 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numLost)); } SECTION("duplicates, contains, and removal") { REQUIRE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); REQUIRE_NOTHROW( callbacks.addCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); // Now we have two ACQUIRED and one LOST callback. SECTION("max_remove") { CHECK(0 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired, 0, 0)); CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired));
CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired, 0, 1)); CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired));
// LOST callback should still be there to remove CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); } SECTION("large max_remove") { CHECK(2 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired, 0, 3)); CHECK_FALSE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired));
// LOST callback should still be there to remove CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); } SECTION("num_skip") { CHECK(0 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired, 3)); CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired));
CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired, 1)); CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired));
// LOST callback should still be there to remove CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); } SECTION("invoke acquired") { CHECK(2 == callbacks.invokeCallbacks(MyEvent::ACQUIRED, invoker)); CHECK(2 == numAcquired); CHECK(0 == numLost); { INFO("should have removed themselves"); CHECK_FALSE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); }
{ INFO("LOST callbacks should still be there"); CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); } } SECTION("invoke lost") { CHECK(1 == callbacks.invokeCallbacks(MyEvent::LOST, invoker)); CHECK(0 == numAcquired); CHECK(1 == numLost); { INFO("should have removed themselves"); CHECK_FALSE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); }
{ INFO("ACQUIRED callbacks should still be there"); CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); CHECK(2 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); } } } }}
enum class MyCEvent : std::uint8_t{ MY_C_EVENT_ACQUIRE = 1u << 0u, MY_C_EVENT_LOST = 1u << 1u,};
using c_callback_type = bool (*)(MyCEvent event, void *userdata);
TEST_CASE("u_generic_callbacks-C"){ GenericCallbacks<c_callback_type, MyCEvent> callbacks;}