From 7d1b3c5df2eab1d42179332d467d5756aefed587 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Wed, 14 Jan 2015 02:44:09 +0100 Subject: Implemented attaching Methods and Property information to Types (this will later allow script engines to access these methods). --- test/core/common/RttiTest.cpp | 164 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 152 insertions(+), 12 deletions(-) (limited to 'test/core/common/RttiTest.cpp') diff --git a/test/core/common/RttiTest.cpp b/test/core/common/RttiTest.cpp index 36bf48f..5d02553 100644 --- a/test/core/common/RttiTest.cpp +++ b/test/core/common/RttiTest.cpp @@ -22,7 +22,10 @@ #include +#include #include +#include +#include namespace ousia { namespace { @@ -45,18 +48,15 @@ class RttiTestClass7 { extern const Rtti Type6; extern const Rtti Type7; -const Rtti Type1("Type1"); -const Rtti Type2("Type2"); -const Rtti Type3("Type3", {&Type1}); -const Rtti Type4("Type4", {&Type3, &Type2}); -const Rtti Type5("Type5", - std::unordered_set{}, - {&Type6, &Type7}); -const Rtti Type6("Type6", - std::unordered_set{}, - {&Type1}); -const Rtti Type7("Type7", {&Type6}, - std::unordered_set{}); +const Rtti Type1 = RttiBuilder{"Type1"}; +const Rtti Type2 = RttiBuilder{"Type2"}; +const Rtti Type3 = RttiBuilder{"Type3"}.parent(&Type1); +const Rtti Type4 = + RttiBuilder{"Type4"}.parent({&Type3, &Type2}); +const Rtti Type5 = + RttiBuilder{"Type5"}.composedOf({&Type6, &Type7}); +const Rtti Type6 = RttiBuilder{"Type6"}.composedOf(&Type1); +const Rtti Type7 = RttiBuilder{"Type7"}.parent(&Type6); TEST(Rtti, isa) { @@ -118,6 +118,146 @@ TEST(Rtti, composedOf) ASSERT_FALSE(Type7.composedOf(Type6)); ASSERT_FALSE(Type7.composedOf(Type7)); } + +class RttiMethodTestClass1 { +}; +class RttiMethodTestClass2 { +}; + +static const Rtti MType1 = + RttiBuilder{"MType1"} + .genericMethod( + "a", std::make_shared>([]( + Variant::arrayType &args, + RttiMethodTestClass1 *thisPtr) { return Variant{"a"}; })) + .genericMethod( + "b", std::make_shared>([]( + Variant::arrayType &args, + RttiMethodTestClass1 *thisPtr) { return Variant{"b"}; })) + .genericMethod( + "c", std::make_shared>([]( + Variant::arrayType &args, + RttiMethodTestClass1 *thisPtr) { return Variant{"c"}; })); + +static const Rtti MType2 = + TypedRttiBuilder{"MType2"} + .parent(&MType1) + .method("c", + [](Variant::arrayType &args, + RttiMethodTestClass2 *thisPtr) { return Variant{"c2"}; }) + .method("d", [](Variant::arrayType &args, + RttiMethodTestClass2 *thisPtr) { return Variant{"d"}; }) + .method("e", + {{Argument::Int("a"), Argument::Int("b")}, + [](Variant::arrayType &args, RttiMethodTestClass2 *thisPtr) { + return Variant{args[0].asInt() * args[1].asInt()}; + }}); + +TEST(Rtti, methods) +{ + auto methods = MType1.getMethods(); + ASSERT_TRUE(methods.count("a") > 0); + ASSERT_TRUE(methods.count("b") > 0); + ASSERT_TRUE(methods.count("c") > 0); + + ASSERT_FALSE(MType1.getMethod("a") == nullptr); + ASSERT_FALSE(MType1.getMethod("b") == nullptr); + ASSERT_FALSE(MType1.getMethod("c") == nullptr); + ASSERT_TRUE(MType1.getMethod("d") == nullptr); + + ASSERT_EQ("a", MType1.getMethod("a")->call().asString()); + ASSERT_EQ("b", MType1.getMethod("b")->call().asString()); + ASSERT_EQ("c", MType1.getMethod("c")->call().asString()); + + methods = MType2.getMethods(); + ASSERT_TRUE(methods.count("a") > 0); + ASSERT_TRUE(methods.count("b") > 0); + ASSERT_TRUE(methods.count("c") > 0); + ASSERT_TRUE(methods.count("d") > 0); + + ASSERT_FALSE(MType2.getMethod("a") == nullptr); + ASSERT_FALSE(MType2.getMethod("b") == nullptr); + ASSERT_FALSE(MType2.getMethod("c") == nullptr); + ASSERT_FALSE(MType2.getMethod("d") == nullptr); + + ASSERT_EQ("a", MType2.getMethod("a")->call().asString()); + ASSERT_EQ("b", MType2.getMethod("b")->call().asString()); + ASSERT_EQ("c2", MType2.getMethod("c")->call().asString()); + ASSERT_EQ("d", MType2.getMethod("d")->call().asString()); + ASSERT_EQ(42, + MType2.getMethod("e")->call(Variant::arrayType{6, 7}).asInt()); + ASSERT_THROW(MType2.getMethod("e")->call(Variant::arrayType{6, "7"}), + LoggableException); +} + +class RttiPropertyTestClass1 { +public: + int a; + + RttiPropertyTestClass1() : a(0) {} + + static Variant getA(const RttiPropertyTestClass1 *obj) { return obj->a; } + + static void setA(const Variant &value, RttiPropertyTestClass1 *obj) + { + obj->a = value.asInt(); + } +}; + +class RttiPropertyTestClass2 : public RttiPropertyTestClass1 { +public: + int b; + + RttiPropertyTestClass2() : b(0) {} + + static Variant getB(const RttiPropertyTestClass2 *obj) { return obj->b; } + + static void setB(const Variant &value, RttiPropertyTestClass2 *obj) + { + obj->b = value.asInt(); + } +}; + +static const Rtti PType1 = + TypedRttiBuilder{"PType1"}.property( + "a", {RttiTypes::Int, RttiPropertyTestClass1::getA, + RttiPropertyTestClass1::setA}); + +static const Rtti PType2 = + TypedRttiBuilder{"PType2"}.parent(&PType1).property( + "b", {RttiTypes::Int, RttiPropertyTestClass2::getB, + RttiPropertyTestClass2::setB}); + +TEST(Rtti, properties) +{ + RttiPropertyTestClass2 obj; + + auto properties = PType1.getProperties(); + ASSERT_TRUE(properties.count("a") > 0); + ASSERT_FALSE(properties.count("b") > 0); + + ASSERT_FALSE(PType1.getProperty("a") == nullptr); + ASSERT_TRUE(PType1.getProperty("b") == nullptr); + + ASSERT_EQ(0, PType1.getProperty("a")->get(&obj).asInt()); + PType1.getProperty("a")->set(4, &obj); + ASSERT_EQ(4, PType1.getProperty("a")->get(&obj).asInt()); + + properties = PType2.getProperties(); + ASSERT_TRUE(properties.count("a") > 0); + ASSERT_TRUE(properties.count("b") > 0); + + ASSERT_FALSE(PType2.getProperty("a") == nullptr); + ASSERT_FALSE(PType2.getProperty("b") == nullptr); + + ASSERT_EQ(4, PType2.getProperty("a")->get(&obj).asInt()); + PType2.getProperty("a")->set(8, &obj); + ASSERT_EQ(8, PType2.getProperty("a")->get(&obj).asInt()); + + ASSERT_EQ(0, PType2.getProperty("b")->get(&obj).asInt()); + PType2.getProperty("b")->set(5, &obj); + ASSERT_EQ(5, PType2.getProperty("b")->get(&obj).asInt()); +} } } -- cgit v1.2.3