blob: d5a2d1cfd1dd4fa36b598fa1fc025500be37a4cd (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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);
}
}
}
}
|