tomato-testing/test/entt/meta/meta_ctor.cpp

216 lines
5.8 KiB
C++
Raw Normal View History

#include <utility>
#include <gtest/gtest.h>
#include <entt/core/hashed_string.hpp>
#include <entt/core/utility.hpp>
#include <entt/entity/registry.hpp>
#include <entt/locator/locator.hpp>
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/resolve.hpp>
struct base_t {
base_t()
: value{'c'} {}
char value;
};
struct derived_t: base_t {
derived_t()
: base_t{} {}
};
struct clazz_t {
clazz_t(const base_t &other, int &iv)
: clazz_t{iv, other.value} {}
clazz_t(const int &iv, char cv)
: i{iv}, c{cv} {}
operator int() const {
return i;
}
static clazz_t factory(int value) {
return {value, 'c'};
}
static clazz_t factory(base_t other, int value, int mul) {
return {value * mul, other.value};
}
int i{};
char c{};
};
double double_factory() {
return 42.;
}
struct MetaCtor: ::testing::Test {
void SetUp() override {
using namespace entt::literals;
entt::meta<double>()
.type("double"_hs)
.ctor<double_factory>();
entt::meta<derived_t>()
.type("derived"_hs)
.base<base_t>();
entt::meta<clazz_t>()
.type("clazz"_hs)
.ctor<&entt::registry::emplace_or_replace<clazz_t, const int &, const char &>, entt::as_ref_t>()
.ctor<const base_t &, int &>()
.ctor<const int &, char>()
.ctor<entt::overload<clazz_t(int)>(clazz_t::factory)>()
.ctor<entt::overload<clazz_t(base_t, int, int)>(clazz_t::factory)>()
.conv<int>();
}
void TearDown() override {
entt::meta_reset();
}
};
TEST_F(MetaCtor, Functionalities) {
auto any = entt::resolve<clazz_t>().construct(42, 'c');
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 42);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, Func) {
auto any = entt::resolve<clazz_t>().construct(42);
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 42);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, MetaAnyArgs) {
auto any = entt::resolve<clazz_t>().construct(entt::meta_any{42}, entt::meta_any{'c'});
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 42);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, InvalidArgs) {
ASSERT_FALSE(entt::resolve<clazz_t>().construct(entt::meta_any{}, derived_t{}));
}
TEST_F(MetaCtor, CastAndConvert) {
auto any = entt::resolve<clazz_t>().construct(derived_t{}, clazz_t{42, 'd'});
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 42);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, ArithmeticConversion) {
auto any = entt::resolve<clazz_t>().construct(true, 4.2);
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 1);
ASSERT_EQ(any.cast<clazz_t>().c, char{4});
}
TEST_F(MetaCtor, ConstNonConstRefArgs) {
int ivalue = 42;
const char cvalue = 'c';
auto any = entt::resolve<clazz_t>().construct(entt::forward_as_meta(ivalue), entt::forward_as_meta(cvalue));
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 42);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, WrongConstness) {
int value = 42;
auto any = entt::resolve<clazz_t>().construct(derived_t{}, entt::forward_as_meta(value));
auto other = entt::resolve<clazz_t>().construct(derived_t{}, entt::forward_as_meta(std::as_const(value)));
ASSERT_TRUE(any);
ASSERT_FALSE(other);
ASSERT_EQ(any.cast<clazz_t>().i, 42);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, FuncMetaAnyArgs) {
auto any = entt::resolve<clazz_t>().construct(entt::meta_any{42});
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 42);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, FuncCastAndConvert) {
auto any = entt::resolve<clazz_t>().construct(derived_t{}, 3., clazz_t{3, 'd'});
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 9);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, FuncArithmeticConversion) {
auto any = entt::resolve<clazz_t>().construct(4.2);
ASSERT_TRUE(any);
ASSERT_EQ(any.cast<clazz_t>().i, 4);
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
}
TEST_F(MetaCtor, FuncConstNonConstRefArgs) {
int ivalue = 42;
auto any = entt::resolve<clazz_t>().construct(entt::forward_as_meta(ivalue));
auto other = entt::resolve<clazz_t>().construct(entt::forward_as_meta(std::as_const(ivalue)));
ASSERT_TRUE(any);
ASSERT_TRUE(other);
ASSERT_EQ(any.cast<clazz_t>().i, 42);
ASSERT_EQ(other.cast<clazz_t>().i, 42);
}
TEST_F(MetaCtor, ExternalMemberFunction) {
entt::registry registry;
const auto entity = registry.create();
ASSERT_FALSE(registry.all_of<clazz_t>(entity));
const auto any = entt::resolve<clazz_t>().construct(entt::forward_as_meta(registry), entity, 3, 'c');
ASSERT_TRUE(any);
ASSERT_TRUE(registry.all_of<clazz_t>(entity));
ASSERT_EQ(registry.get<clazz_t>(entity).i, 3);
ASSERT_EQ(registry.get<clazz_t>(entity).c, 'c');
}
TEST_F(MetaCtor, OverrideImplicitlyGeneratedDefaultConstructor) {
auto type = entt::resolve<double>();
auto any = type.construct();
ASSERT_TRUE(any);
ASSERT_EQ(any.type(), entt::resolve<double>());
ASSERT_EQ(any.cast<double>(), 42.);
}
TEST_F(MetaCtor, NonDefaultConstructibleType) {
auto type = entt::resolve<clazz_t>();
// no implicitly generated default constructor
ASSERT_FALSE(type.construct());
}
TEST_F(MetaCtor, ReRegistration) {
SetUp();
auto &&node = entt::internal::resolve<double>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
ASSERT_TRUE(node.details);
ASSERT_FALSE(node.details->ctor.empty());
// implicitly generated default constructor is not cleared
ASSERT_NE(node.default_constructor, nullptr);
}