aboutsummaryrefslogtreecommitdiff
path: root/kernel/kapi/devices/bus.tests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kapi/devices/bus.tests.cpp')
-rw-r--r--kernel/kapi/devices/bus.tests.cpp61
1 files changed, 61 insertions, 0 deletions
diff --git a/kernel/kapi/devices/bus.tests.cpp b/kernel/kapi/devices/bus.tests.cpp
index 9f95513b..0a33df1a 100644
--- a/kernel/kapi/devices/bus.tests.cpp
+++ b/kernel/kapi/devices/bus.tests.cpp
@@ -92,3 +92,64 @@ SCENARIO("A bus shares ownership of its children, holding a weak link to its par
}
}
}
+
+SCENARIO("Removing a child from a bus tears down the while subtree", "[devices][bus]")
+{
+ GIVEN("A bus with a child bus")
+ {
+ auto root = kstd::make_shared<test_bus>("bus_removal_root");
+ auto middle = kstd::make_shared<test_bus>("bus_removal_middle");
+ auto leaf_destroyed = false;
+ auto leaf = kstd::make_shared<flagging_device>("bus_removal_leaf", leaf_destroyed);
+
+ root->add_child(middle);
+ middle->add_child(leaf);
+
+ REQUIRE(root->children().size() == 1);
+ REQUIRE(middle->children().size() == 1);
+
+ WHEN("the middle bus is removed from the root")
+ {
+ REQUIRE(root->remove_child(*middle));
+
+ THEN("the middle bus's own subtree was torn down")
+ {
+ REQUIRE(middle->children().empty());
+ }
+
+ THEN("the leaf is marked as removed but not destroyed")
+ {
+ REQUIRE(leaf->state() == kapi::devices::state::removed);
+ REQUIRE(leaf->parent() == nullptr);
+ REQUIRE_FALSE(leaf_destroyed);
+ }
+
+ AND_WHEN("dropping the outside leaf reference")
+ {
+ leaf.reset();
+
+ THEN("the leaf is destroyed")
+ {
+ REQUIRE(leaf_destroyed);
+ }
+ }
+
+ THEN("the root no longer considers the middle its child")
+ {
+ REQUIRE(root->children().empty());
+ REQUIRE(middle->state() == kapi::devices::state::removed);
+ }
+ }
+ }
+
+ GIVEN("A bus and a device that was never actually attached to it")
+ {
+ auto bus = kstd::make_shared<test_bus>("bus_removal_unrelated_bus");
+ auto unrelated = kstd::make_shared<test_device>("bus_removal_unrelated_device");
+
+ THEN("removing the child fails")
+ {
+ REQUIRE_FALSE(bus->remove_child(*unrelated));
+ }
+ }
+}