aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-23 08:50:51 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-23 08:50:51 +0200
commitf37a571da89a21262709694786573df01ce651cc (patch)
tree6a11eb9ca616bdc91b42751147bf2b1617323110 /kernel
parent7a758c0e1c4fe1d47e8f7bc2c3a1261ffca24bdb (diff)
downloadkernel-f37a571da89a21262709694786573df01ce651cc.tar.xz
kernel-f37a571da89a21262709694786573df01ce651cc.zip
kernel: add basic bus tests
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kapi/devices/bus.tests.cpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/kernel/kapi/devices/bus.tests.cpp b/kernel/kapi/devices/bus.tests.cpp
new file mode 100644
index 00000000..d5a2d1cf
--- /dev/null
+++ b/kernel/kapi/devices/bus.tests.cpp
@@ -0,0 +1,104 @@
+#include <kapi/devices.hpp>
+
+#include <kstd/memory.hpp>
+#include <kstd/string.hpp>
+
+#include <catch2/catch_test_macros.hpp>
+
+namespace
+{
+
+ struct test_bus final : kapi::devices::bus
+ {
+ using kapi::devices::bus::bus;
+ };
+
+ struct test_device final : kapi::devices::device
+ {
+ using kapi::devices::device::device;
+
+ auto init() -> bool override
+ {
+ return true;
+ }
+ };
+
+ struct flagging_device final : kapi::devices::device
+ {
+ flagging_device(kstd::string const & name, bool & destroyed_flag)
+ : device{name}
+ , m_destroyed_flag{&destroyed_flag}
+ {}
+
+ ~flagging_device() override
+ {
+ *m_destroyed_flag = true;
+ }
+
+ auto init() -> bool override
+ {
+ return true;
+ }
+
+ private:
+ bool * m_destroyed_flag;
+ };
+
+} // namespace
+
+SCENARIO("A bus shares ownership of its children, holding a weak link to its parent", "[devices][bus]")
+{
+ GIVEN("A bus with one attached child device")
+ {
+ auto parent_bus = kstd::make_shared<test_bus>("bus_ownership_parent");
+ auto child = kstd::make_shared<test_device>("bus_ownership_child");
+
+ parent_bus->add_child(child);
+
+ THEN("the child is reachable through children()")
+ {
+ REQUIRE(parent_bus->children().size() == 1);
+ REQUIRE(parent_bus->children()[0]->name() == "bus_ownership_child");
+ }
+
+ THEN("the child's parent resolves back to the bus")
+ {
+ auto locked_parent = child->parent();
+ REQUIRE(locked_parent);
+ REQUIRE(locked_parent->name() == "bus_ownership_parent");
+ }
+
+ WHEN("the bus is destroyed while the caller still holds the child directly")
+ {
+ parent_bus.reset();
+
+ THEN("the child outlives the bus")
+ {
+ REQUIRE(child != nullptr);
+ }
+
+ THEN("the child's parent link no longer resolves")
+ {
+ REQUIRE(child->parent() == nullptr);
+ }
+ }
+ }
+
+ GIVEN("a bus that is the only thing keeping its child alive")
+ {
+ auto destroyed = false;
+ auto parent_bus = kstd::make_shared<test_bus>("bus_lifetime_parent");
+ parent_bus->add_child(kstd::make_shared<flagging_device>("bus_lifetime_child", destroyed));
+
+ WHEN("the bus is destroyed")
+ {
+ CHECK_FALSE(destroyed);
+ parent_bus.reset();
+
+ THEN("the child is destroyed along with it")
+ {
+ REQUIRE(destroyed);
+ }
+ }
+ }
+}