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