The open source OpenXR runtime
at main 6.0 kB view raw
1// Copyright 2021-2023, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief Generic callback collection tests. 6 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 7 */ 8 9#include "catch_amalgamated.hpp" 10 11#include <util/u_generic_callbacks.hpp> 12 13using xrt::auxiliary::util::GenericCallbacks; 14 15enum class MyEvent 16{ 17 ACQUIRED = 1u << 0u, 18 LOST = 1u << 1u, 19}; 20 21using mask_t = std::underlying_type_t<MyEvent>; 22 23static bool 24increment_userdata_int(MyEvent event, void *userdata) 25{ 26 *static_cast<int *>(userdata) += 1; 27 return true; 28} 29 30 31using callback_t = bool (*)(MyEvent event, void *userdata); 32 33TEST_CASE("u_generic_callbacks") 34{ 35 GenericCallbacks<callback_t, MyEvent> callbacks; 36 // Simplest possible invoker. 37 auto invoker = [](MyEvent event, callback_t callback, void *userdata) { return callback(event, userdata); }; 38 39 SECTION("call when empty") 40 { 41 CHECK(0 == callbacks.invokeCallbacks(MyEvent::ACQUIRED, invoker)); 42 CHECK(0 == callbacks.invokeCallbacks(MyEvent::LOST, invoker)); 43 CHECK(0 == callbacks.removeCallback(&increment_userdata_int, (mask_t)MyEvent::LOST, nullptr)); 44 } 45 SECTION("same function, different mask and userdata") 46 { 47 int numAcquired = 0; 48 int numLost = 0; 49 REQUIRE_NOTHROW(callbacks.addCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); 50 REQUIRE_NOTHROW(callbacks.addCallback(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); 51 SECTION("contains") 52 { 53 CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::LOST, &numLost)); 54 CHECK_FALSE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::LOST, &numAcquired)); 55 } 56 SECTION("removal matching") 57 { 58 CHECK(0 == 59 callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, &numAcquired)); 60 CHECK(0 == 61 callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numLost)); 62 } 63 SECTION("duplicates, contains, and removal") 64 { 65 REQUIRE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); 66 REQUIRE_NOTHROW( 67 callbacks.addCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); 68 CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, &numAcquired)); 69 // Now we have two ACQUIRED and one LOST callback. 70 SECTION("max_remove") 71 { 72 CHECK(0 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 73 &numAcquired, 0, 0)); 74 CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 75 &numAcquired)); 76 77 CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 78 &numAcquired, 0, 1)); 79 CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 80 &numAcquired)); 81 82 // LOST callback should still be there to remove 83 CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, 84 &numLost)); 85 } 86 SECTION("large max_remove") 87 { 88 CHECK(2 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 89 &numAcquired, 0, 3)); 90 CHECK_FALSE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 91 &numAcquired)); 92 93 // LOST callback should still be there to remove 94 CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, 95 &numLost)); 96 } 97 SECTION("num_skip") 98 { 99 CHECK(0 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 100 &numAcquired, 3)); 101 CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 102 &numAcquired)); 103 104 CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 105 &numAcquired, 1)); 106 CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 107 &numAcquired)); 108 109 // LOST callback should still be there to remove 110 CHECK(1 == callbacks.removeCallback(increment_userdata_int, (mask_t)MyEvent::LOST, 111 &numLost)); 112 } 113 SECTION("invoke acquired") 114 { 115 CHECK(2 == callbacks.invokeCallbacks(MyEvent::ACQUIRED, invoker)); 116 CHECK(2 == numAcquired); 117 CHECK(0 == numLost); 118 { 119 INFO("should have removed themselves"); 120 CHECK_FALSE(callbacks.contains(increment_userdata_int, 121 (mask_t)MyEvent::ACQUIRED, &numAcquired)); 122 } 123 124 { 125 INFO("LOST callbacks should still be there"); 126 CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::LOST, 127 &numLost)); 128 CHECK(1 == callbacks.removeCallback(increment_userdata_int, 129 (mask_t)MyEvent::LOST, &numLost)); 130 } 131 } 132 SECTION("invoke lost") 133 { 134 CHECK(1 == callbacks.invokeCallbacks(MyEvent::LOST, invoker)); 135 CHECK(0 == numAcquired); 136 CHECK(1 == numLost); 137 { 138 INFO("should have removed themselves"); 139 CHECK_FALSE(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::LOST, 140 &numLost)); 141 } 142 143 { 144 INFO("ACQUIRED callbacks should still be there"); 145 CHECK(callbacks.contains(increment_userdata_int, (mask_t)MyEvent::ACQUIRED, 146 &numAcquired)); 147 CHECK(2 == callbacks.removeCallback(increment_userdata_int, 148 (mask_t)MyEvent::ACQUIRED, &numAcquired)); 149 } 150 } 151 } 152 } 153} 154 155 156enum MyCEvent 157{ 158 MY_C_EVENT_ACQUIRE = 1u << 0u, 159 MY_C_EVENT_LOST = 1u << 1u, 160}; 161 162using c_callback_type = bool (*)(MyCEvent event, void *userdata); 163 164TEST_CASE("u_generic_callbacks-C") 165{ 166 GenericCallbacks<c_callback_type, MyCEvent> callbacks; 167}