aboutsummaryrefslogtreecommitdiff
path: root/kernel/kapi/devices/interface_registry.tests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kapi/devices/interface_registry.tests.cpp')
-rw-r--r--kernel/kapi/devices/interface_registry.tests.cpp329
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