diff options
Diffstat (limited to 'kernel/kapi/devices/interface_registry.tests.cpp')
| -rw-r--r-- | kernel/kapi/devices/interface_registry.tests.cpp | 329 |
1 files changed, 0 insertions, 329 deletions
diff --git a/kernel/kapi/devices/interface_registry.tests.cpp b/kernel/kapi/devices/interface_registry.tests.cpp deleted file mode 100644 index 071b9a6d..00000000 --- a/kernel/kapi/devices/interface_registry.tests.cpp +++ /dev/null @@ -1,329 +0,0 @@ -#include <kapi/devices.hpp> - -#include <kstd/memory.hpp> - -#include <catch2/catch_test_macros.hpp> - -#include <cstddef> - -namespace -{ - struct probe_device - { - constexpr auto static id = kapi::devices::interface_id{"probe"}; - - virtual ~probe_device() = default; - - [[nodiscard]] auto virtual get_value() const noexcept -> int = 0; - }; - - struct const_device - { - constexpr auto static id = kapi::devices::interface_id{"flip"}; - - virtual ~const_device() = default; - - [[nodiscard]] auto get_constant() const noexcept -> int - { - return 0; - } - }; - - struct unimplemented_device - { - constexpr auto static id = kapi::devices::interface_id{"unimplemented"}; - - virtual ~unimplemented_device() = default; - }; - - struct test_device final : kapi::devices::device, probe_device - { - explicit test_device(int value, const_device & const_device) - : device{"probeable"} - , m_value{value} - , m_const_device{&const_device} - {} - - [[nodiscard]] constexpr auto get_value() const noexcept -> int override - { - return m_value; - } - - auto query_interface(kapi::devices::interface_id interface) -> void * override - { - if (interface == probe_device::id) - { - return static_cast<probe_device *>(this); - } - if (interface == const_device::id) - { - return m_const_device; - } - - return kapi::devices::device::query_interface(interface); - } - - private: - int m_value; - const_device * m_const_device; - }; - - struct counting_observer final : kapi::devices::interface_registry_observer - { - auto on_interface_published(kapi::devices::interface_id, kapi::devices::interface_registry::entry const &) - -> void override - { - ++published; - } - - auto on_interface_withdrawn(kapi::devices::interface_id, kapi::devices::device &) -> void override - { - ++withdrawn; - } - - std::size_t published{}; - std::size_t withdrawn{}; - }; - - struct evil_observer final : kapi::devices::interface_registry_observer - { - explicit evil_observer(kstd::shared_ptr<counting_observer> & victim) - : m_victim{victim} - {} - - auto on_interface_published(kapi::devices::interface_id, kapi::devices::interface_registry::entry const &) - -> void override - { - m_victim.reset(); - } - - auto on_interface_withdrawn(kapi::devices::interface_id, kapi::devices::device &) -> void override - { - m_victim.reset(); - } - - private: - kstd::shared_ptr<counting_observer> & m_victim; // NOLINT - }; - -} // namespace - -SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]") -{ - GIVEN("An empty registry, a device, and an interface the device implements by inheritance") - { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared<test_device>(128, free_standing_interface); - - THEN("Publishing an interface without a name fails") - { - REQUIRE_FALSE(registry.publish<probe_device>(device, "")); - } - - WHEN("publishing the interface for the device") - { - CHECK(device->is_a<probe_device>()); - CHECK(device->is_a<const_device>()); - auto published = registry.publish(device, "probe0", device->as<probe_device>()); - - THEN("publishing is successful") - { - REQUIRE(published); - } - - THEN("publishing the same device and interface with a different name fails") - { - REQUIRE_FALSE(registry.publish(device, "probe1", device->as<probe_device>())); - } - - THEN("publishing a second interface for the same device succeeds") - { - REQUIRE(registry.publish<const_device>(device, "probe0")); - } - - THEN("publishing a free standing second interface for the same device succeeds") - { - REQUIRE(registry.publish(device, "probe0", &free_standing_interface)); - } - - AND_WHEN("getting all devices implementing that interface") - { - auto probeable_devices = registry.all(probe_device::id); - - THEN("there is exactly one such device") - { - REQUIRE(probeable_devices.size() == 1); - } - - THEN("the name of the device is 'probe0'") - { - REQUIRE(probeable_devices[0].name() == "probe0"); - } - - THEN("the returned device pointer is valid") - { - REQUIRE(probeable_devices[0].device()); - } - - THEN("the returned implementation equals the result of device::as") - { - REQUIRE(probeable_devices[0].implementation() == device->as<probe_device>()); - } - - THEN("the interface provided function can be invoked") - { - auto implementation = probeable_devices[0].as<probe_device>(); - REQUIRE(implementation->get_value() == device->get_value()); - } - } - - THEN("resolve finds the published capability by name") - { - REQUIRE(registry.resolve<probe_device>("probe0")); - } - - THEN("resolve finds a capability the device implements but never published") - { - REQUIRE(registry.resolve<const_device>("probe0")); - } - - THEN("resolve for a capability the device implements nowhere at all does not find anything") - { - REQUIRE_FALSE(registry.resolve<unimplemented_device>("probe0")); - } - - THEN("resolve for an unpublished device does not find a device") - { - REQUIRE_FALSE(registry.resolve<probe_device>("probe1")); - } - - THEN("withdrawing an interface for a device removes it from the registry") - { - registry.withdraw(*device, probe_device::id); - REQUIRE_FALSE(registry.resolve<probe_device>("probe0")); - } - } - - WHEN("the device is destroyed without withdrawing it") - { - CHECK(registry.publish(device, "probe0", device->as<probe_device>())); - device.reset(); - - THEN("querying all does no longer report it") - { - REQUIRE(registry.all(probe_device::id).empty()); - } - - THEN("resolve() no longer finds it") - { - REQUIRE_FALSE(registry.resolve<probe_device>("probe0")); - } - } - } - - GIVEN("no device has ever been published") - { - auto registry = kapi::devices::interface_registry{}; - - THEN("all() returns an empty vector") - { - REQUIRE(registry.all(probe_device::id).empty()); - } - } - - GIVEN("a null device") - { - auto registry = kapi::devices::interface_registry{}; - auto device = kstd::shared_ptr<kapi::devices::device>{}; - auto interface = const_device{}; - - THEN("publishing the interface for the device fails") - { - REQUIRE_FALSE(registry.publish(device, "probe0", &interface)); - } - } -} - -SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_registry]") -{ - GIVEN("a device and a subscribed observer") - { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared<test_device>(128, free_standing_interface); - auto observer = kstd::make_shared<counting_observer>(); - - registry.subscribe(observer); - - WHEN("an interface is published for the device") - { - CHECK(registry.publish(device, "probe0", device->as<probe_device>())); - - THEN("the observer is notified exactly once") - { - REQUIRE(observer->published == 1); - REQUIRE(observer->withdrawn == 0); - } - } - - WHEN("an interface is published and then withdrawn") - { - CHECK(registry.publish(device, "probe0", device->as<probe_device>())); - registry.withdraw(*device, probe_device::id); - - THEN("the observer is notified of both exactly one") - { - REQUIRE(observer->published == 1); - REQUIRE(observer->withdrawn == 1); - } - } - - WHEN("the observer is destroyed before anything is published") - { - observer.reset(); - - THEN("publishing afterward does not crash") - { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>())); - } - } - - WHEN("the observer unsubscribes before anything is published") - { - registry.unsubscribe(*observer); - - THEN("publishing afterward does not crash") - { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>())); - } - - THEN("the subscriber is not notified") - { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>())); - REQUIRE_NOTHROW(registry.withdraw(*device, probe_device::id)); - REQUIRE(observer->published == 0); - REQUIRE(observer->withdrawn == 0); - } - } - } - - GIVEN("two subscriber, the first destroying the second") - { - auto registry = kapi::devices::interface_registry{}; - auto free_standing_interface = const_device{}; - auto device = kstd::make_shared<test_device>(128, free_standing_interface); - - auto second = kstd::make_shared<counting_observer>(); - auto first = kstd::make_shared<evil_observer>(second); - - registry.subscribe(first); - registry.subscribe(second); - - THEN("publishing an interface does not crash") - { - REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>())); - REQUIRE(second == nullptr); - } - } -}
\ No newline at end of file |
