From 4f15b79cebd6f76ff49e94c19f66ad479b66c55d Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 3 Dec 2022 13:18:11 +0200 Subject: [PATCH] Add unit tests for reflection --- tests/.gitignore | 1 + tests/Build | 17 +++++ tests/reflection.cpp | 156 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 tests/.gitignore create mode 100644 tests/Build create mode 100644 tests/reflection.cpp diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..ee4c926 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +/test diff --git a/tests/Build b/tests/Build new file mode 100644 index 0000000..db50340 --- /dev/null +++ b/tests/Build @@ -0,0 +1,17 @@ +package "mspgame-tests" +{ + require "mspcore"; + require "mspgame"; + require "msptest"; + + program "test" + { + source "."; + build_info + { + /* XXX Shouldn't be needed, but builder has a bug and doesn't + correctly propagate the standard from required packages. */ + standard CXX "c++20"; + }; + }; +}; diff --git a/tests/reflection.cpp b/tests/reflection.cpp new file mode 100644 index 0000000..a40ada3 --- /dev/null +++ b/tests/reflection.cpp @@ -0,0 +1,156 @@ +#include +#include + +using namespace std; +using namespace Msp; + +class ReflectionTests: public Test::RegisteredTest +{ +public: + ReflectionTests(); + + static const char *get_name() { return "Reflection"; } + +private: + void find_class(); + void basic_polymorphism(); + void polymorphism_conflict(); + void deep_polymorphism(); + void branching_polymorphism(); +}; + +struct A { virtual ~A() = default; }; +struct B: A { }; +struct C: B { }; +struct D: C { }; +struct C2: B { }; + + +ReflectionTests::ReflectionTests() +{ + add(&ReflectionTests::find_class, "find_class"); + add(&ReflectionTests::basic_polymorphism, "Basic polymorphism"); + add(&ReflectionTests::polymorphism_conflict, "Polymorphism conflict").expect_throw(); + add(&ReflectionTests::deep_polymorphism, "Deep polymorphism"); + add(&ReflectionTests::branching_polymorphism, "Branching polymorphism"); +} + + +void ReflectionTests::find_class() +{ + Game::Reflection::Reflector reflector; + Game::Reflection::Class *a_class = reflector.find_class(); + EXPECT_EQUAL(a_class, nullptr); + Game::Reflection::Class &a_reg = reflector.get_or_create_class(); + a_class = reflector.find_class(); + EXPECT(a_class!=nullptr); + EXPECT_EQUAL(a_class, &a_reg); +} + +void ReflectionTests::basic_polymorphism() +{ + Game::Reflection::Reflector reflector; + + Game::Reflection::Class &a_class = reflector.get_or_create_class(); + a_class.set_polymorphic_base(); + Game::Reflection::Class &b_class = reflector.get_or_create_class(); + b_class.set_polymorphic_base(B()); + + EXPECT(a_class.is_direct_base_of(b_class)); + EXPECT(!b_class.is_direct_base_of(a_class)); + + A a_obj; + EXPECT(a_class.is_instance(a_obj)); + EXPECT(!b_class.is_instance(a_obj)); + + B b_obj; + EXPECT(a_class.is_instance(b_obj)); + EXPECT(b_class.is_instance(b_obj)); + + A &a_ref_to_b = b_obj; + EXPECT(a_class.is_instance(a_ref_to_b)); + EXPECT(b_class.is_instance(a_ref_to_b)); +} + +void ReflectionTests::polymorphism_conflict() +{ + Game::Reflection::Reflector reflector; + Game::Reflection::Class &b_class = reflector.get_or_create_class(); + b_class.set_polymorphic_base(); + b_class.set_polymorphic_base(); +} + +void ReflectionTests::deep_polymorphism() +{ + Game::Reflection::Reflector reflector; + + Game::Reflection::Class &a_class = reflector.get_or_create_class(); + a_class.set_polymorphic_base(); + Game::Reflection::Class &b_class = reflector.get_or_create_class(); + b_class.set_polymorphic_base(B()); + Game::Reflection::Class &c_class = reflector.get_or_create_class(); + c_class.set_polymorphic_base(C()); + Game::Reflection::Class &d_class = reflector.get_or_create_class(); + d_class.set_polymorphic_base(D()); + + EXPECT(a_class.is_direct_base_of(b_class)); + EXPECT(!a_class.is_direct_base_of(c_class)); + EXPECT(!a_class.is_direct_base_of(d_class)); + EXPECT(a_class.is_base_of(c_class)); + EXPECT(a_class.is_base_of(d_class)); + EXPECT(b_class.is_direct_base_of(c_class)); + EXPECT(!b_class.is_direct_base_of(d_class)); + EXPECT(b_class.is_base_of(d_class)); + EXPECT(c_class.is_direct_base_of(d_class)); + + D d_obj; + EXPECT(a_class.is_instance(d_obj)); + EXPECT(b_class.is_instance(d_obj)); + EXPECT(c_class.is_instance(d_obj)); + EXPECT(d_class.is_instance(d_obj)); + + B &b_ref_to_d = d_obj; + EXPECT(a_class.is_instance(b_ref_to_d)); + EXPECT(b_class.is_instance(b_ref_to_d)); + EXPECT(c_class.is_instance(b_ref_to_d)); + EXPECT(d_class.is_instance(b_ref_to_d)); + + C &c_ref_to_d = d_obj; + EXPECT(a_class.is_instance(c_ref_to_d)); + EXPECT(b_class.is_instance(c_ref_to_d)); + EXPECT(c_class.is_instance(c_ref_to_d)); + EXPECT(d_class.is_instance(c_ref_to_d)); +} + +void ReflectionTests::branching_polymorphism() +{ + Game::Reflection::Reflector reflector; + + Game::Reflection::Class &a_class = reflector.get_or_create_class(); + a_class.set_polymorphic_base(); + Game::Reflection::Class &b_class = reflector.get_or_create_class(); + b_class.set_polymorphic_base(B()); + Game::Reflection::Class &c_class = reflector.get_or_create_class(); + c_class.set_polymorphic_base(C()); + Game::Reflection::Class &c2_class = reflector.get_or_create_class(); + c2_class.set_polymorphic_base(C2()); + + EXPECT(a_class.is_direct_base_of(b_class)); + EXPECT(a_class.is_base_of(c_class)); + EXPECT(a_class.is_base_of(c2_class)); + EXPECT(b_class.is_direct_base_of(c_class)); + EXPECT(b_class.is_direct_base_of(c2_class)); + EXPECT(!c_class.is_base_of(c2_class)); + EXPECT(!c2_class.is_base_of(c_class)); + + C c_obj; + C2 c2_obj; + EXPECT(a_class.is_instance(c_obj)); + EXPECT(a_class.is_instance(c2_obj)); + EXPECT(b_class.is_instance(c_obj)); + EXPECT(b_class.is_instance(c2_obj)); + EXPECT(c_class.is_instance(c_obj)); + EXPECT(!c_class.is_instance(c2_obj)); + EXPECT(c2_class.is_instance(c2_obj)); + EXPECT(!c2_class.is_instance(c_obj)); +} -- 2.43.0