1 #include <type_traits>
2 #include <utility>
3 #include <gtest/gtest.h>
4 #include <entt/entity/handle.hpp>
5 #include <entt/entity/registry.hpp>
6
TEST(BasicHandle,Assumptions)7 TEST(BasicHandle, Assumptions) {
8 static_assert(std::is_trivially_copyable_v<entt::handle>);
9 static_assert(std::is_trivially_assignable_v<entt::handle, entt::handle>);
10 static_assert(std::is_trivially_destructible_v<entt::handle>);
11
12 static_assert(std::is_trivially_copyable_v<entt::const_handle>);
13 static_assert(std::is_trivially_assignable_v<entt::const_handle, entt::const_handle>);
14 static_assert(std::is_trivially_destructible_v<entt::const_handle>);
15 }
16
TEST(BasicHandle,DeductionGuide)17 TEST(BasicHandle, DeductionGuide) {
18 static_assert(std::is_same_v<decltype(entt::basic_handle{std::declval<entt::registry &>(), {}}), entt::basic_handle<entt::entity>>);
19 static_assert(std::is_same_v<decltype(entt::basic_handle{std::declval<const entt::registry &>(), {}}), entt::basic_handle<const entt::entity>>);
20 }
21
TEST(BasicHandle,Construction)22 TEST(BasicHandle, Construction) {
23 entt::registry registry;
24 const auto entity = registry.create();
25
26 entt::handle handle{registry, entity};
27 entt::const_handle chandle{std::as_const(registry), entity};
28
29 ASSERT_FALSE(entt::null == handle.entity());
30 ASSERT_EQ(entity, handle);
31 ASSERT_TRUE(handle);
32
33 ASSERT_FALSE(entt::null == chandle.entity());
34 ASSERT_EQ(entity, chandle);
35 ASSERT_TRUE(chandle);
36
37 ASSERT_EQ(handle, chandle);
38
39 static_assert(std::is_same_v<entt::registry *, decltype(handle.registry())>);
40 static_assert(std::is_same_v<const entt::registry *, decltype(chandle.registry())>);
41 }
42
TEST(BasicHandle,Invalidation)43 TEST(BasicHandle, Invalidation) {
44 entt::handle handle;
45
46 ASSERT_FALSE(handle);
47 ASSERT_EQ(handle.registry(), nullptr);
48 ASSERT_EQ(handle.entity(), entt::entity{entt::null});
49
50 entt::registry registry;
51 const auto entity = registry.create();
52
53 handle = { registry, entity };
54
55 ASSERT_TRUE(handle);
56 ASSERT_NE(handle.registry(), nullptr);
57 ASSERT_NE(handle.entity(), entt::entity{entt::null});
58
59 handle = {};
60
61 ASSERT_FALSE(handle);
62 ASSERT_EQ(handle.registry(), nullptr);
63 ASSERT_EQ(handle.entity(), entt::entity{entt::null});
64 }
65
TEST(BasicHandle,Destruction)66 TEST(BasicHandle, Destruction) {
67 entt::registry registry;
68 const auto entity = registry.create();
69 entt::handle handle{registry, entity};
70
71 ASSERT_TRUE(handle);
72 ASSERT_TRUE(handle.valid());
73 ASSERT_NE(handle.registry(), nullptr);
74 ASSERT_EQ(handle.entity(), entity);
75
76 handle.destroy(registry.version(entity));
77
78 ASSERT_FALSE(handle);
79 ASSERT_FALSE(handle.valid());
80 ASSERT_NE(handle.registry(), nullptr);
81 ASSERT_EQ(handle.entity(), entity);
82 ASSERT_EQ(registry.current(entity), typename entt::registry::version_type{});
83
84 handle = entt::handle{registry, registry.create()};
85
86 ASSERT_TRUE(handle);
87 ASSERT_TRUE(handle.valid());
88 ASSERT_NE(handle.registry(), nullptr);
89 ASSERT_EQ(handle.entity(), entity);
90
91 handle.destroy();
92
93 ASSERT_FALSE(handle);
94 ASSERT_FALSE(handle.valid());
95 ASSERT_NE(handle.registry(), nullptr);
96 ASSERT_EQ(handle.entity(), entity);
97 ASSERT_NE(registry.current(entity), typename entt::registry::version_type{});
98 }
99
TEST(BasicHandle,Comparison)100 TEST(BasicHandle, Comparison) {
101 entt::registry registry;
102 const auto entity = registry.create();
103
104 entt::handle handle{registry, entity};
105 entt::const_handle chandle = handle;
106
107 ASSERT_NE(handle, entt::handle{});
108 ASSERT_FALSE(handle == entt::handle{});
109 ASSERT_TRUE(handle != entt::handle{});
110
111 ASSERT_NE(chandle, entt::const_handle{});
112 ASSERT_FALSE(chandle == entt::const_handle{});
113 ASSERT_TRUE(chandle != entt::const_handle{});
114
115 ASSERT_EQ(handle, chandle);
116 ASSERT_TRUE(handle == chandle);
117 ASSERT_FALSE(handle != chandle);
118
119 ASSERT_EQ(entt::handle{}, entt::const_handle{});
120 ASSERT_TRUE(entt::handle{} == entt::const_handle{});
121 ASSERT_FALSE(entt::handle{} != entt::const_handle{});
122
123 handle = {};
124 chandle = {};
125
126 ASSERT_EQ(handle, entt::handle{});
127 ASSERT_TRUE(handle == entt::handle{});
128 ASSERT_FALSE(handle != entt::handle{});
129
130 ASSERT_EQ(chandle, entt::const_handle{});
131 ASSERT_TRUE(chandle == entt::const_handle{});
132 ASSERT_FALSE(chandle != entt::const_handle{});
133
134 entt::registry other;
135 const auto entt = other.create();
136
137 handle = { registry, entity };
138 chandle = { other, entt };
139
140 ASSERT_NE(handle, chandle);
141 ASSERT_FALSE(chandle == handle);
142 ASSERT_TRUE(chandle != handle);
143 ASSERT_EQ(handle.entity(), chandle.entity());
144 ASSERT_NE(handle.registry(), chandle.registry());
145 }
146
TEST(BasicHandle,Component)147 TEST(BasicHandle, Component) {
148 entt::registry registry;
149 const auto entity = registry.create();
150 entt::handle_view<int, char, double> handle{registry, entity};
151
152 ASSERT_EQ(3, handle.emplace<int>(3));
153 ASSERT_EQ('c', handle.emplace_or_replace<char>('c'));
154 ASSERT_EQ(.3, handle.emplace_or_replace<double>(.3));
155
156 const auto &patched = handle.patch<int>([](auto &comp) { comp = 42; });
157
158 ASSERT_EQ(42, patched);
159 ASSERT_EQ('a', handle.replace<char>('a'));
160 ASSERT_TRUE((handle.all_of<int, char, double>()));
161 ASSERT_EQ((std::make_tuple(42, 'a', .3)), (handle.get<int, char, double>()));
162
163 handle.erase<char, double>();
164
165 ASSERT_TRUE((registry.empty<char, double>()));
166 ASSERT_EQ(0u, (handle.remove<char, double>()));
167
168 handle.visit([](auto info) { ASSERT_EQ(entt::type_id<int>(), info); });
169
170 ASSERT_TRUE((handle.any_of<int, char, double>()));
171 ASSERT_FALSE((handle.all_of<int, char, double>()));
172 ASSERT_FALSE(handle.orphan());
173
174 ASSERT_EQ(1u, (handle.remove<int>()));
175 ASSERT_DEATH(handle.erase<int>(), "");
176
177 ASSERT_TRUE(registry.empty<int>());
178 ASSERT_TRUE(handle.orphan());
179
180 ASSERT_EQ(42, handle.get_or_emplace<int>(42));
181 ASSERT_EQ(42, handle.get_or_emplace<int>(1));
182 ASSERT_EQ(42, handle.get<int>());
183
184 ASSERT_EQ(42, *handle.try_get<int>());
185 ASSERT_EQ(nullptr, handle.try_get<char>());
186 ASSERT_EQ(nullptr, std::get<1>(handle.try_get<int, char, double>()));
187 }
188
TEST(BasicHandle,FromEntity)189 TEST(BasicHandle, FromEntity) {
190 entt::registry registry;
191 const auto entity = registry.create();
192
193 registry.emplace<int>(entity, 42);
194 registry.emplace<char>(entity, 'c');
195
196 entt::handle handle{registry, entity};
197
198 ASSERT_TRUE(handle);
199 ASSERT_EQ(entity, handle.entity());
200 ASSERT_TRUE((handle.all_of<int, char>()));
201 ASSERT_EQ(handle.get<int>(), 42);
202 ASSERT_EQ(handle.get<char>(), 'c');
203 }
204
TEST(BasicHandle,Lifetime)205 TEST(BasicHandle, Lifetime) {
206 entt::registry registry;
207 const auto entity = registry.create();
208 auto *handle = new entt::handle{registry, entity};
209 handle->emplace<int>();
210
211 ASSERT_FALSE(registry.empty<int>());
212 ASSERT_FALSE(registry.empty());
213
214 registry.each([handle](const auto e) {
215 ASSERT_EQ(handle->entity(), e);
216 });
217
218 delete handle;
219
220 ASSERT_FALSE(registry.empty<int>());
221 ASSERT_FALSE(registry.empty());
222 }
223
TEST(BasicHandle,ImplicitConversions)224 TEST(BasicHandle, ImplicitConversions) {
225 entt::registry registry;
226 const entt::handle handle{registry, registry.create()};
227 const entt::const_handle chandle = handle;
228 const entt::handle_view<int, char> vhandle = handle;
229 const entt::const_handle_view<int> cvhandle = vhandle;
230
231 handle.emplace<int>(42);
232
233 ASSERT_EQ(handle.get<int>(), chandle.get<int>());
234 ASSERT_EQ(chandle.get<int>(), vhandle.get<int>());
235 ASSERT_EQ(vhandle.get<int>(), cvhandle.get<int>());
236 ASSERT_EQ(cvhandle.get<int>(), 42);
237 }
238