176 lines
4.8 KiB
C++
176 lines
4.8 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include "renderive/renderable/Inheritance.hpp"
|
|
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
namespace renderable_chain = renderive::renderable_inheritance;
|
|
|
|
enum class Visit {
|
|
parent,
|
|
child
|
|
};
|
|
|
|
struct Event {};
|
|
|
|
struct Impl_Base : renderive::inheritance::Type_Root {
|
|
explicit Impl_Base(std::vector<Visit>& visits) : visits(&visits) {}
|
|
std::vector<Visit>* visits;
|
|
};
|
|
|
|
struct Parent_Impl
|
|
: renderable_chain::Impl_Root<Parent_Impl, Impl_Base, Event> {
|
|
using Impl_Root::Impl_Root;
|
|
|
|
struct Observer : renderable_chain::Observer_Root<Parent_Impl> {
|
|
static void handle(Parent_Impl& impl, const Event&) {
|
|
impl.visits->push_back(Visit::parent);
|
|
}
|
|
};
|
|
};
|
|
|
|
struct Child_Impl : renderable_chain::Impl_Node<Child_Impl, Parent_Impl> {
|
|
using Impl_Node::Impl_Node;
|
|
|
|
struct Observer
|
|
: renderable_chain::Observer_Node<Child_Impl,
|
|
Parent_Impl::Observer> {
|
|
static void handle(Child_Impl& impl, const Event&) {
|
|
impl.visits->push_back(Visit::child);
|
|
}
|
|
};
|
|
};
|
|
|
|
struct Parent_State : renderable_chain::State_Root<Parent_State> {};
|
|
struct Child_State
|
|
: renderable_chain::State_Node<Child_State, Parent_State> {};
|
|
|
|
struct Parent_Builder_Layer
|
|
: renderable_chain::Builder_Root<Parent_Builder_Layer> {};
|
|
struct Child_Builder_Layer
|
|
: renderable_chain::Builder_Node<Child_Builder_Layer,
|
|
Parent_Builder_Layer> {};
|
|
|
|
struct Business_Builder {
|
|
explicit Business_Builder(bool& initialized) : initialized(&initialized) {}
|
|
void build() const { *initialized = true; }
|
|
bool* initialized;
|
|
};
|
|
|
|
struct Final_Builder
|
|
: renderable_chain::Builder<Final_Builder, Child_Builder_Layer,
|
|
Business_Builder> {
|
|
using Builder::Builder;
|
|
};
|
|
|
|
struct Root_Base {
|
|
public:
|
|
explicit Root_Base(bool& constructed) : constructed(&constructed) {
|
|
constructed = true;
|
|
}
|
|
|
|
bool* constructed;
|
|
};
|
|
|
|
struct Renderable_Root
|
|
: renderive::renderable::render_base<Renderable_Root, Root_Base, true> {
|
|
using render_base::render_base;
|
|
struct Impl {};
|
|
};
|
|
|
|
struct Product_Properties {
|
|
bool enabled{};
|
|
};
|
|
|
|
template <class Product_Type, class Properties_Type>
|
|
struct Product_Business_Builder {
|
|
using Product = Product_Type;
|
|
using Properties = Properties_Type;
|
|
|
|
explicit Product_Business_Builder(bool& initialized)
|
|
: initialized(&initialized) {}
|
|
|
|
void build() const { *initialized = true; }
|
|
|
|
bool* initialized;
|
|
};
|
|
|
|
struct Visual_Control
|
|
: renderive::renderable::render_base<Visual_Control, Renderable_Root> {
|
|
using State = Product_Properties;
|
|
|
|
template <class Product, class Properties>
|
|
using Business_Builder = Product_Business_Builder<Product, Properties>;
|
|
|
|
using render_base::render_base;
|
|
|
|
protected:
|
|
template <class, auto Member, class Value>
|
|
void set_state(Value&& value) {
|
|
state.*Member = std::forward<Value>(value);
|
|
}
|
|
|
|
template <class, auto Member>
|
|
auto get_state() const {
|
|
return state.*Member;
|
|
}
|
|
|
|
private:
|
|
State state;
|
|
};
|
|
|
|
using Renderable_Product = renderive::renderable::attach<Visual_Control>;
|
|
|
|
TEST(renderable_inheritance_test, dispatches_nested_observers_parent_first) {
|
|
std::vector<Visit> visits;
|
|
Child_Impl impl(visits);
|
|
|
|
impl.dispatch(Event{});
|
|
|
|
EXPECT_EQ(visits, (std::vector{Visit::parent, Visit::child}));
|
|
}
|
|
|
|
TEST(renderable_inheritance_test, preserves_business_builder_capabilities) {
|
|
bool initialized{};
|
|
Final_Builder builder(initialized);
|
|
|
|
builder.build();
|
|
|
|
EXPECT_TRUE(initialized);
|
|
static_assert(std::same_as<
|
|
renderive::inheritance::Type_At_Position_T<
|
|
typename Final_Builder::Inheritance_Registry,
|
|
renderable_chain::Builder_Chain,
|
|
Final_Builder::Inheritance_Position>,
|
|
Final_Builder>);
|
|
static_assert(std::same_as<
|
|
renderive::inheritance::Type_At_Position_T<
|
|
typename Child_State::Inheritance_Registry,
|
|
renderable_chain::State_Chain,
|
|
Child_State::Inheritance_Position>,
|
|
Child_State>);
|
|
}
|
|
|
|
TEST(renderable_inheritance_test,
|
|
composes_root_control_and_product_without_business_boilerplate) {
|
|
bool constructed{};
|
|
Renderable_Product product(constructed);
|
|
EXPECT_TRUE(constructed);
|
|
|
|
bool initialized{};
|
|
Renderable_Product::Builder builder(initialized);
|
|
builder.build();
|
|
EXPECT_TRUE(initialized);
|
|
|
|
static_assert(std::same_as<Renderable_Product::Properties,
|
|
Product_Properties>);
|
|
static_assert(std::same_as<
|
|
typename Renderable_Product::Builder::Product,
|
|
Renderable_Product>);
|
|
}
|
|
|
|
} // namespace
|