核心模板架构
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "renderive/base/Atomic_Mutex.hpp"
|
||||
#include "renderive/base/Concepts.hpp"
|
||||
struct Base_Plain_Type {};
|
||||
static_assert(Class_Type<Base_Plain_Type>);
|
||||
static_assert(Derivable_Type<Base_Plain_Type>);
|
||||
static_assert(Mutex_Type<Atomic_Spin_Mutex>);
|
||||
static_assert(Mutex_Type<Atomic_Wait_Mutex>);
|
||||
TEST(base_concepts_test, concepts_compile) {
|
||||
SUCCEED();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <type_traits>
|
||||
#include "renderive/base/node/Node.hpp"
|
||||
struct Multiway_Node_Test_Owner {};
|
||||
struct Multiway_Node_Test_Tag {};
|
||||
using Multiway_Node_Test_Type = Multiway_Node<Multiway_Node_Test_Owner, Multiway_Node_Test_Tag>;
|
||||
static_assert(Multiway_Node_Type<Multiway_Node_Test_Type, Multiway_Node_Test_Owner, Multiway_Node_Test_Tag>);
|
||||
static_assert(!std::same_as<Multiway_Node<Multiway_Node_Test_Owner>, Multiway_Node_Test_Type>);
|
||||
TEST(multiway_node_test, reparents_child_and_preserves_order) {
|
||||
Multiway_Node_Test_Owner first_owner;
|
||||
Multiway_Node_Test_Owner second_owner;
|
||||
Multiway_Node_Test_Owner third_owner;
|
||||
Multiway_Node_Test_Type root;
|
||||
Multiway_Node_Test_Type first(&first_owner);
|
||||
Multiway_Node_Test_Type second(&second_owner);
|
||||
Multiway_Node_Test_Type third(&third_owner);
|
||||
root.append_child(first);
|
||||
root.append_child(second);
|
||||
first.append_child(third);
|
||||
EXPECT_EQ(root.children.size(), 2);
|
||||
EXPECT_EQ(first.children.front(), &third);
|
||||
EXPECT_EQ(third.parent, &first);
|
||||
second.append_child(third);
|
||||
EXPECT_TRUE(first.children.empty());
|
||||
EXPECT_EQ(third.parent, &second);
|
||||
}
|
||||
TEST(multiway_node_test, rejects_cycles) {
|
||||
Multiway_Node_Test_Type root;
|
||||
Multiway_Node_Test_Type child;
|
||||
root.append_child(child);
|
||||
EXPECT_THROW(child.append_child(root), std::invalid_argument);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include "renderive/base/observer/Observer.hpp"
|
||||
struct Observer_Test_Observation {
|
||||
int value{};
|
||||
};
|
||||
struct Observer_Test_Time_Source {
|
||||
std::shared_ptr<std::atomic<std::uint64_t>> time{std::make_shared<std::atomic<std::uint64_t>>(10)};
|
||||
std::uint64_t now_ns() const noexcept {
|
||||
return time->fetch_add(5, std::memory_order_relaxed);
|
||||
}
|
||||
};
|
||||
struct Observer_Test_Recorder {
|
||||
static constexpr bool enabled = true;
|
||||
std::shared_ptr<int> value{std::make_shared<int>()};
|
||||
void observe(const Observer_Test_Observation& observation) noexcept {
|
||||
*value = observation.value;
|
||||
}
|
||||
};
|
||||
using Observer_Test_State = Observer_State<Observer_Test_Recorder, Observer_Test_Time_Source>;
|
||||
static_assert(Observation_Struct<Observer_Test_Observation>);
|
||||
static_assert(Observer_Time_Source<Observer_Test_Time_Source>);
|
||||
static_assert(Struct_Observer<Observer_Test_Recorder, Observer_Test_Observation>);
|
||||
static_assert(Timed_Struct_Observer<Observer_Test_State, Observer_Test_Observation>);
|
||||
TEST(observer_state_test, forwards_observation_structure) {
|
||||
Observer_Test_Recorder recorder;
|
||||
Observer_Test_State observer(recorder, Observer_Test_Time_Source{});
|
||||
observer.observe(Observer_Test_Observation{7});
|
||||
EXPECT_EQ(*recorder.value, 7);
|
||||
}
|
||||
TEST(observer_state_test, owns_time_source) {
|
||||
Observer_Test_State observer;
|
||||
EXPECT_EQ(observer.now_ns(), 10);
|
||||
EXPECT_EQ(observer.now_ns(), 15);
|
||||
}
|
||||
TEST(disabled_observer_test, accepts_any_observation_structure) {
|
||||
Observer_State<> observer;
|
||||
EXPECT_NO_THROW(observer.observe(Observer_Test_Observation{7}));
|
||||
EXPECT_GT(observer.now_ns(), 0);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "renderive/base/observer/Observer.hpp"
|
||||
static_assert(Observer_Time_Source<Steady_Time_Source>);
|
||||
TEST(steady_time_source_test, advances_monotonically) {
|
||||
Steady_Time_Source source;
|
||||
const auto first = source.now_ns();
|
||||
const auto second = source.now_ns();
|
||||
EXPECT_GE(second, first);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "Property_Test_Types.hpp"
|
||||
static_assert(Property_Set<Property_Direct_Properties>);
|
||||
static_assert(Property_Product<Property_Direct_Product>);
|
||||
static_assert(Value_Validator<Property_Checked_Value_Validator, int>);
|
||||
static_assert(Validated_Property_Value<Range_Value<int, 0, 10>>);
|
||||
static_assert(Property_Validator<Property_External_Validator, Property_External_Properties>);
|
||||
static_assert(Property_Constructible<Property_Direct_Product, Property_Direct_Properties, int>);
|
||||
TEST(property_concepts_test, concepts_compile) {
|
||||
SUCCEED();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <memory>
|
||||
#include "Property_Test_Types.hpp"
|
||||
TEST(property_builder_test, builds_independent_product) {
|
||||
auto product = Property_Direct_Builder{Property_Direct_Properties{.value = 42}}.build(7);
|
||||
EXPECT_EQ(product->value, 42);
|
||||
EXPECT_EQ(product->id, 7);
|
||||
}
|
||||
TEST(property_builder_test, configures_properties) {
|
||||
auto product = Property_Direct_Builder{}.set<&Property_Direct_Properties::value>(10).configure([](Property_Direct_Properties& properties) {
|
||||
properties.value += 5;
|
||||
}).build(1);
|
||||
EXPECT_EQ(product->value, 15);
|
||||
}
|
||||
TEST(property_builder_test, supports_external_validator) {
|
||||
auto builder = Property_External_Product::Builder{}.set<&Property_External_Properties::minimum>(10).set<&Property_External_Properties::maximum>(5);
|
||||
EXPECT_THROW(builder.build(), std::invalid_argument);
|
||||
}
|
||||
TEST(property_builder_test, builds_unique_product) {
|
||||
auto product = Property_Direct_Builder{Property_Direct_Properties{.value = 12}}.build_unique(3);
|
||||
static_assert(std::same_as<decltype(product), std::unique_ptr<Property_Direct_Product>>);
|
||||
EXPECT_EQ(product->value, 12);
|
||||
EXPECT_EQ(product->id, 3);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include "renderive/base/property/Property.hpp"
|
||||
struct Property_External_Properties {
|
||||
int minimum{};
|
||||
int maximum{};
|
||||
};
|
||||
struct Property_External_Validator {
|
||||
void operator()(const Property_External_Properties& properties) const {
|
||||
if (properties.minimum > properties.maximum) {
|
||||
throw std::invalid_argument("external minimum must not exceed maximum");
|
||||
}
|
||||
}
|
||||
};
|
||||
struct Property_External_Product_Base {
|
||||
explicit Property_External_Product_Base(const Property_External_Properties& properties) : properties(properties) {}
|
||||
Property_External_Properties properties;
|
||||
};
|
||||
using Property_External_Product = Attach_Builder<Property_External_Product_Base, Property_External_Properties, Property_Builder, Property_External_Validator>;
|
||||
struct Property_Direct_Properties {
|
||||
int value{};
|
||||
};
|
||||
struct Property_Direct_Product {
|
||||
Property_Direct_Product(const Property_Direct_Properties& properties, int id) : value(properties.value), id(id) {}
|
||||
int value;
|
||||
int id;
|
||||
};
|
||||
using Property_Direct_Builder = Property_Builder<Property_Direct_Product, Property_Direct_Properties>;
|
||||
struct Property_Checked_Value_Validator {
|
||||
void operator()(const int& value) const {
|
||||
if (value % 2 != 0) {
|
||||
throw std::invalid_argument("value must be even");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "Property_Test_Types.hpp"
|
||||
TEST(validated_value_test, accepts_range_boundaries) {
|
||||
Range_Value<int, 0, 10> minimum{0};
|
||||
Range_Value<int, 0, 10> maximum{10};
|
||||
EXPECT_EQ(minimum.get(), 0);
|
||||
EXPECT_EQ(maximum.get(), 10);
|
||||
}
|
||||
TEST(validated_value_test, rejects_values_outside_range) {
|
||||
EXPECT_THROW((Range_Value<int, 0, 10>{-1}), std::out_of_range);
|
||||
EXPECT_THROW((Range_Value<int, 0, 10>{11}), std::out_of_range);
|
||||
}
|
||||
TEST(validated_value_test, keeps_old_value_when_validation_fails) {
|
||||
Range_Value<int, 0, 10> value{5};
|
||||
EXPECT_THROW(value = 20, std::out_of_range);
|
||||
EXPECT_EQ(value.get(), 5);
|
||||
}
|
||||
TEST(validated_value_test, supports_custom_validator) {
|
||||
Validated_Value<int, Property_Checked_Value_Validator> value{4};
|
||||
EXPECT_NO_THROW(value = 6);
|
||||
EXPECT_THROW(value = 7, std::invalid_argument);
|
||||
EXPECT_EQ(value.get(), 6);
|
||||
}
|
||||
Reference in New Issue
Block a user