refactor: major qol changes
Some checks reported errors
continuous-integration/drone/push Build was killed
Some checks reported errors
continuous-integration/drone/push Build was killed
This commit is contained in:
parent
b372b95ede
commit
abb9c1b1ec
30 changed files with 231 additions and 320 deletions
|
|
@ -14,6 +14,7 @@ add_module(
|
|||
NAME
|
||||
test
|
||||
INTERFACES
|
||||
module.cppm
|
||||
test.cppm
|
||||
expects.cppm
|
||||
registry.cppm
|
||||
|
|
@ -39,6 +40,8 @@ add_module(
|
|||
components.cppm
|
||||
DEPENDENCIES
|
||||
preliminary
|
||||
TESTS
|
||||
vec2.test.cpp
|
||||
)
|
||||
|
||||
add_module(
|
||||
|
|
|
|||
|
|
@ -1,48 +1,42 @@
|
|||
import preliminary;
|
||||
import test;
|
||||
import assets.metadata;
|
||||
import assets.shader;
|
||||
import logger;
|
||||
import logger;
|
||||
import test.test;
|
||||
import test.expects;
|
||||
|
||||
using ::lt::assets::AssetMetadata;
|
||||
using ::lt::assets::Blob;
|
||||
using ::lt::assets::BlobMetadata;
|
||||
using ::lt::assets::ShaderAsset;
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::expect_eq;
|
||||
using ::lt::test::expect_throw;
|
||||
using ::lt::test::expect_true;
|
||||
using ::lt::test::Suite;
|
||||
using ::lt::test::operator""_suite;
|
||||
|
||||
const auto test_data_path = std::filesystem::path { "./data/test_assets" };
|
||||
const auto tmp_path = std::filesystem::path { "/tmp/lt_assets_tests/" };
|
||||
|
||||
[[nodiscard]] auto generate_blob(size_t size) -> Blob
|
||||
{
|
||||
auto blob = Blob {};
|
||||
for (auto idx : std::views::iota(0u, size))
|
||||
{
|
||||
blob.emplace_back(static_cast<byte>(idx));
|
||||
}
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
Suite raii = "shader_raii"_suite = [] {
|
||||
std::filesystem::current_path(test_data_path);
|
||||
std::filesystem::create_directories(tmp_path);
|
||||
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
auto shader_asset = ShaderAsset { "triangle.frag.asset" };
|
||||
};
|
||||
|
||||
Case { "many won't freeze/throw" } = [] {
|
||||
for (auto idx : std::views::iota(0u, 1'000u))
|
||||
{
|
||||
ignore = idx;
|
||||
auto shader_asset = ShaderAsset { "triangle.frag.asset" };
|
||||
}
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
// non-existent file
|
||||
expect_throw([] { ShaderAsset { "path" }; });
|
||||
|
||||
// incompatible type
|
||||
expect_throw([] { ShaderAsset { "dummytext" }; });
|
||||
|
||||
// random stressing
|
||||
// some random stressing
|
||||
expect_throw([] {
|
||||
for (auto idx : std::views::iota(0u, 1'000u))
|
||||
{
|
||||
|
|
@ -50,16 +44,22 @@ Suite raii = "shader_raii"_suite = [] {
|
|||
}
|
||||
});
|
||||
};
|
||||
|
||||
Case { "many" } = [] {
|
||||
for (auto idx : std::views::iota(0u, 1'000u))
|
||||
{
|
||||
ignore = idx;
|
||||
auto shader_asset = ShaderAsset { "triangle.frag.asset" };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Suite packing = "shader_pack"_suite = [] {
|
||||
Case { "" } = [] {
|
||||
Case { "Unpacking packed data returns the same data" } = [] {
|
||||
const auto out_path = tmp_path / "shader_packing";
|
||||
auto dummy_blob = lt::assets::Blob {};
|
||||
for (auto idx : std::views::iota(0u, 255u))
|
||||
{
|
||||
dummy_blob.emplace_back(static_cast<byte>(idx));
|
||||
}
|
||||
constexpr auto blob_size = size_t { 255u };
|
||||
|
||||
auto blob = generate_blob(blob_size);
|
||||
|
||||
const auto expected_size = //
|
||||
sizeof(AssetMetadata::type) //
|
||||
|
|
@ -70,7 +70,7 @@ Suite packing = "shader_pack"_suite = [] {
|
|||
+ sizeof(BlobMetadata::compression_type) //
|
||||
+ sizeof(BlobMetadata::compressed_size) //
|
||||
+ sizeof(BlobMetadata::uncompressed_size) //
|
||||
+ dummy_blob.size();
|
||||
+ blob.size();
|
||||
|
||||
ShaderAsset::pack(
|
||||
out_path,
|
||||
|
|
@ -81,7 +81,7 @@ Suite packing = "shader_pack"_suite = [] {
|
|||
ShaderAsset::Metadata {
|
||||
.type = ShaderAsset::Type::vertex,
|
||||
},
|
||||
std::move(dummy_blob)
|
||||
std::move(blob)
|
||||
);
|
||||
|
||||
auto stream = std::ifstream {
|
||||
|
|
@ -104,12 +104,12 @@ Suite packing = "shader_pack"_suite = [] {
|
|||
const auto &metadata = shader_asset.get_metadata();
|
||||
expect_eq(metadata.type, ShaderAsset::Type::vertex);
|
||||
|
||||
auto blob = shader_asset.unpack(ShaderAsset::BlobTag::code);
|
||||
expect_eq(blob.size(), 255u);
|
||||
auto unpakced_blob = shader_asset.unpack(ShaderAsset::BlobTag::code);
|
||||
expect_eq(unpakced_blob.size(), blob_size);
|
||||
|
||||
for (auto idx : std::views::iota(0u, 255u))
|
||||
for (auto idx : std::views::iota(0u, blob_size))
|
||||
{
|
||||
expect_eq(blob[idx], static_cast<byte>(idx));
|
||||
expect_eq(unpakced_blob[idx], static_cast<byte>(idx));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,17 +1,8 @@
|
|||
import preliminary;
|
||||
import test;
|
||||
import ecs.registry;
|
||||
import test.test;
|
||||
import test.expects;
|
||||
|
||||
using ::lt::ecs::EntityId;
|
||||
using ::lt::ecs::Registry;
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::expect_eq;
|
||||
using ::lt::test::expect_false;
|
||||
using ::lt::test::expect_true;
|
||||
using ::lt::test::expect_unreachable;
|
||||
using ::lt::test::Suite;
|
||||
using ::lt::test::operator""_suite;
|
||||
|
||||
struct Component
|
||||
{
|
||||
|
|
@ -61,11 +52,14 @@ struct std::formatter<Component_B>
|
|||
};
|
||||
|
||||
Suite raii = "raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
ignore = Registry {};
|
||||
};
|
||||
|
||||
Case { "many won't freeze/throw" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
};
|
||||
|
||||
Case { "many" } = [] {
|
||||
for (auto idx : std::views::iota(0, 100'000))
|
||||
{
|
||||
ignore = idx;
|
||||
|
|
@ -73,9 +67,6 @@ Suite raii = "raii"_suite = [] {
|
|||
}
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
};
|
||||
|
||||
Case { "post construct has correct state" } = [] {
|
||||
auto registry = Registry {};
|
||||
expect_eq(registry.get_entity_count(), 0);
|
||||
|
|
@ -227,7 +218,7 @@ Suite each = "each"_suite = [] {
|
|||
component_map_a[entity] = component;
|
||||
}
|
||||
|
||||
auto component_map_b = std::unordered_map<lt::ecs::EntityId, Component_B> {};
|
||||
auto component_map_b = std::unordered_map<EntityId, Component_B> {};
|
||||
for (auto idx : std::views::iota(0, 10'000))
|
||||
{
|
||||
auto entity = EntityId {};
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ public:
|
|||
|
||||
auto insert(Identifier_T identifier, Value_T value) -> Dense_T &
|
||||
{
|
||||
ensure(identifier < max_capacity, "SparseSet::insert: identifier < max_capacity");
|
||||
|
||||
if (m_sparse.size() < identifier + 1)
|
||||
{
|
||||
auto new_capacity = std::max(static_cast<size_t>(identifier + 1), m_sparse.size() * 2);
|
||||
|
|
@ -70,7 +72,27 @@ public:
|
|||
*/
|
||||
void remove(Identifier_T identifier) override
|
||||
{
|
||||
ensure(
|
||||
identifier < m_sparse.size(),
|
||||
"Failed to ensure: identifier < m_sparse.size() [{} < {}]",
|
||||
identifier,
|
||||
m_sparse.size()
|
||||
);
|
||||
|
||||
auto &idx = m_sparse[identifier];
|
||||
ensure(
|
||||
idx != null_identifier,
|
||||
"Failed to ensure: idx != null_identifier [{} != {}]",
|
||||
idx,
|
||||
null_identifier
|
||||
);
|
||||
ensure(
|
||||
idx < m_dense.size(),
|
||||
"Failed to ensure: idx < m_dense.size() [{} < {}]",
|
||||
idx,
|
||||
m_dense.size()
|
||||
);
|
||||
|
||||
auto &[entity, component] = m_dense[idx];
|
||||
|
||||
auto &[last_entity, last_component] = m_dense.back();
|
||||
|
|
|
|||
|
|
@ -1,31 +1,28 @@
|
|||
import preliminary;
|
||||
import test;
|
||||
import ecs.sparse_set;
|
||||
import test.test;
|
||||
import test.expects;
|
||||
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::expect_eq;
|
||||
using ::lt::test::expect_false;
|
||||
using ::lt::test::expect_ne;
|
||||
using ::lt::test::expect_throw;
|
||||
using ::lt::test::expect_true;
|
||||
using ::lt::test::Suite;
|
||||
using ::lt::test::operator""_suite;
|
||||
|
||||
using Value_T = i32;
|
||||
using Set = lt::ecs::SparseSet<Value_T>;
|
||||
|
||||
constexpr auto capacity = 100;
|
||||
|
||||
Suite raii = "raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
ignore = Set {};
|
||||
ignore = Set { Set::max_capacity };
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
expect_throw([] { ignore = Set { Set::max_capacity + 1 }; });
|
||||
};
|
||||
|
||||
Case { "many" } = [] {
|
||||
for (auto idx : std::views::iota(0, 1'000))
|
||||
{
|
||||
ignore = Set { static_cast<size_t>(idx) };
|
||||
}
|
||||
};
|
||||
|
||||
Case { "post construct has correct state" } = [&] {
|
||||
auto set = Set { capacity };
|
||||
expect_eq(set.get_size(), 0);
|
||||
|
|
@ -34,7 +31,29 @@ Suite raii = "raii"_suite = [] {
|
|||
};
|
||||
|
||||
Suite element_raii = "element_raii"_suite = [] {
|
||||
Case { "many inserts/removes won't freeze/throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
auto set = Set { capacity };
|
||||
set.insert(0, {});
|
||||
set.remove(0);
|
||||
};
|
||||
|
||||
Case { "unhappy paths" } = [] {
|
||||
expect_throw([] {
|
||||
auto set = Set { capacity };
|
||||
set.insert(Set::max_capacity + 1, {});
|
||||
});
|
||||
|
||||
expect_throw([] {
|
||||
auto set = Set { capacity };
|
||||
set.insert(0, {});
|
||||
set.insert(1, {});
|
||||
set.insert(2, {});
|
||||
|
||||
set.remove(3);
|
||||
});
|
||||
};
|
||||
|
||||
Case { "many" } = [] {
|
||||
auto set = Set {};
|
||||
for (auto idx : std::views::iota(0, 10'000))
|
||||
{
|
||||
|
|
@ -160,5 +179,10 @@ Suite clear = "clear"_suite = [] {
|
|||
|
||||
set.clear();
|
||||
expect_eq(set.get_size(), 0);
|
||||
|
||||
for (auto idx : std::views::iota(0, 10'000))
|
||||
{
|
||||
expect_throw([&] { ignore = set.at(idx); });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
import std;
|
||||
import test;
|
||||
import input.system;
|
||||
import input.codes;
|
||||
import std;
|
||||
import test.test;
|
||||
import test.expects;
|
||||
import surface.events;
|
||||
import memory.scope;
|
||||
import memory.reference;
|
||||
|
|
@ -12,22 +9,10 @@ import ecs.entity;
|
|||
import ecs.registry;
|
||||
import surface.system;
|
||||
|
||||
using ::lt::input::InputComponent;
|
||||
using ::lt::input::System;
|
||||
|
||||
// NOLINTBEGIN
|
||||
using namespace lt;
|
||||
using input::InputComponent;
|
||||
using input::System;
|
||||
using test::Case;
|
||||
using test::expect_eq;
|
||||
using test::expect_false;
|
||||
using test::expect_ne;
|
||||
using test::expect_not_nullptr;
|
||||
using test::operator""_suite;
|
||||
using test::expect_throw;
|
||||
using test::Suite;
|
||||
// NOLINTEND
|
||||
|
||||
[[nodiscard]] auto tick_info() -> app::TickInfo
|
||||
[[nodiscard]] auto tick_info() -> lt::app::TickInfo
|
||||
{
|
||||
return {
|
||||
.delta_time = std::chrono::milliseconds { 16 },
|
||||
|
|
@ -39,12 +24,12 @@ using test::Suite;
|
|||
class Fixture
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] auto registry() -> memory::Ref<ecs::Registry>
|
||||
[[nodiscard]] auto registry() -> lt::memory::Ref<lt::ecs::Registry>
|
||||
{
|
||||
return m_registry;
|
||||
}
|
||||
|
||||
auto add_input_component() -> ecs::EntityId
|
||||
auto add_input_component() -> lt::ecs::EntityId
|
||||
{
|
||||
auto entity = m_registry->create_entity();
|
||||
m_registry->add<InputComponent>(entity, {});
|
||||
|
|
@ -52,7 +37,7 @@ public:
|
|||
return entity;
|
||||
}
|
||||
|
||||
auto add_surface_component() -> ecs::EntityId
|
||||
auto add_surface_component() -> lt::ecs::EntityId
|
||||
{
|
||||
auto entity = m_registry->create_entity();
|
||||
m_surface_system.create_surface_component(
|
||||
|
|
@ -64,17 +49,21 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
memory::Ref<ecs::Registry> m_registry = memory::create_ref<ecs::Registry>();
|
||||
lt::memory::Ref<lt::ecs::Registry> m_registry = lt::memory::create_ref<lt::ecs::Registry>();
|
||||
|
||||
surface::System m_surface_system = surface::System { m_registry };
|
||||
lt::surface::System m_surface_system = lt::surface::System { m_registry };
|
||||
};
|
||||
|
||||
Suite raii = "raii"_suite = "raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [&] {
|
||||
Case { "happy paths" } = [&] {
|
||||
System { Fixture {}.registry() };
|
||||
};
|
||||
|
||||
Case { "many won't freeze/throw" } = [&] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
expect_throw([] { ignore = System { {} }; });
|
||||
};
|
||||
|
||||
Case { "many" } = [&] {
|
||||
auto fixture = Fixture {};
|
||||
for (auto idx : std::views::iota(0, 10'000))
|
||||
{
|
||||
|
|
@ -82,10 +71,6 @@ Suite raii = "raii"_suite = "raii"_suite = [] {
|
|||
ignore = System { fixture.registry() };
|
||||
}
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
expect_throw([] { ignore = System { {} }; });
|
||||
};
|
||||
};
|
||||
|
||||
Suite system_events = "system_events"_suite = [] {
|
||||
|
|
@ -122,7 +107,7 @@ Suite registry_events = "registry_events"_suite = [] {
|
|||
Case { "on_destrroy<InputComponent>" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto registry = fixture.registry();
|
||||
auto system = memory::create_scope<System>(registry);
|
||||
auto system = lt::memory::create_scope<System>(registry);
|
||||
|
||||
auto entity_a = fixture.add_input_component();
|
||||
auto entity_b = fixture.add_input_component();
|
||||
|
|
@ -154,7 +139,7 @@ Suite tick = "tick"_suite = [] {
|
|||
auto system = System { fixture.registry() };
|
||||
|
||||
auto surface_entity = fixture.add_surface_component();
|
||||
auto &surface = registry->get<surface::SurfaceComponent>(surface_entity);
|
||||
auto &surface = registry->get<lt::surface::SurfaceComponent>(surface_entity);
|
||||
|
||||
auto input_entity = fixture.add_input_component();
|
||||
auto &input = registry->get<InputComponent>(input_entity);
|
||||
|
|
@ -166,24 +151,25 @@ Suite tick = "tick"_suite = [] {
|
|||
}
|
||||
);
|
||||
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
|
||||
using enum ::lt::input::InputAction::State;
|
||||
expect_eq(input.get_action(action_key).state, inactive);
|
||||
system.tick(tick_info());
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
|
||||
expect_eq(input.get_action(action_key).state, inactive);
|
||||
|
||||
surface.push_event(surface::KeyPressedEvent(Key::a));
|
||||
surface.push_event(lt::surface::KeyPressedEvent(Key::a));
|
||||
system.tick(tick_info());
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::triggered);
|
||||
expect_eq(input.get_action(action_key).state, triggered);
|
||||
|
||||
system.tick(tick_info());
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::active);
|
||||
expect_eq(input.get_action(action_key).state, active);
|
||||
|
||||
system.tick(tick_info());
|
||||
system.tick(tick_info());
|
||||
system.tick(tick_info());
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::active);
|
||||
expect_eq(input.get_action(action_key).state, active);
|
||||
|
||||
surface.push_event(surface::KeyReleasedEvent(Key::a));
|
||||
surface.push_event(lt::surface::KeyReleasedEvent(Key::a));
|
||||
system.tick(tick_info());
|
||||
expect_eq(input.get_action(action_key).state, input::InputAction::State::inactive);
|
||||
expect_eq(input.get_action(action_key).state, inactive);
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* Hence, both `Surface` and `Input` needs to agree to the same input codes, while `Input` depends
|
||||
* on `Surface`. The simplest solution is to keep the codes in a 3rd module and make both depend on
|
||||
* it.
|
||||
* it. (I did not want to give `Surface` the responsibility of defining input codes...)
|
||||
*/
|
||||
export module input.codes;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import logger;
|
||||
import test.test;
|
||||
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::Suite;
|
||||
import test;
|
||||
|
||||
Suite suite = [] {
|
||||
Case { "no format" } = [] {
|
||||
Case { "formatless" } = [] {
|
||||
lt::log::trace("trace");
|
||||
lt::log::debug("debug");
|
||||
lt::log::info("info");
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ import math.vec2;
|
|||
import math.vec3;
|
||||
import math.vec4;
|
||||
|
||||
namespace lt::math {
|
||||
export namespace lt::math {
|
||||
|
||||
export template<typename T = f32>
|
||||
template<typename T = f32>
|
||||
requires(std::is_arithmetic_v<T>)
|
||||
struct mat4_impl
|
||||
{
|
||||
using Column_T = vec4_impl<T>;
|
||||
|
|
@ -79,34 +80,38 @@ struct mat4_impl
|
|||
std::array<Column_T, 4u> values;
|
||||
};
|
||||
|
||||
export template<typename T>
|
||||
/** @todo(Light): Implement */
|
||||
template<typename T>
|
||||
[[nodiscard]] auto translate(const vec3_impl<T> &value) -> mat4_impl<T>
|
||||
{
|
||||
return mat4_impl<T> {};
|
||||
}
|
||||
|
||||
export template<typename T>
|
||||
/** @todo(Light): Implement */
|
||||
template<typename T>
|
||||
[[nodiscard]] auto rotate(f32 value, const vec3_impl<T> &xyz) -> mat4_impl<T>
|
||||
{
|
||||
return mat4_impl<T> {};
|
||||
}
|
||||
|
||||
export template<typename T>
|
||||
/** @todo(Light): Implement */
|
||||
template<typename T>
|
||||
[[nodiscard]] auto scale(const vec3_impl<T> &value) -> mat4_impl<T>
|
||||
{
|
||||
return mat4_impl<T> {};
|
||||
}
|
||||
|
||||
export template<typename T>
|
||||
/** @todo(Light): Implement */
|
||||
template<typename T>
|
||||
[[nodiscard]] auto inverse(const mat4_impl<T> &value) -> mat4_impl<T>
|
||||
{
|
||||
return mat4_impl<T> {};
|
||||
}
|
||||
|
||||
export using mat4 = mat4_impl<f32>;
|
||||
using mat4 = mat4_impl<f32>;
|
||||
|
||||
export using imat4 = mat4_impl<i32>;
|
||||
using imat4 = mat4_impl<i32>;
|
||||
|
||||
export using umat4 = mat4_impl<u32>;
|
||||
using umat4 = mat4_impl<u32>;
|
||||
|
||||
} // namespace lt::math
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ export module math.vec2;
|
|||
|
||||
import preliminary;
|
||||
|
||||
namespace lt::math {
|
||||
export namespace lt::math {
|
||||
|
||||
export template<typename T = f32>
|
||||
template<typename T = f32>
|
||||
requires(std::is_arithmetic_v<T>)
|
||||
struct vec2_impl
|
||||
{
|
||||
|
|
@ -88,11 +88,11 @@ struct vec2_impl
|
|||
};
|
||||
|
||||
|
||||
export using vec2 = vec2_impl<f32>;
|
||||
using vec2 = vec2_impl<f32>;
|
||||
|
||||
export using ivec2 = vec2_impl<i32>;
|
||||
using ivec2 = vec2_impl<i32>;
|
||||
|
||||
export using uvec2 = vec2_impl<u32>;
|
||||
using uvec2 = vec2_impl<u32>;
|
||||
|
||||
} // namespace lt::math
|
||||
|
||||
|
|
|
|||
7
modules/math/vec2.test.cpp
Normal file
7
modules/math/vec2.test.cpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import test;
|
||||
import math.vec2;
|
||||
|
||||
Suite raii = "raii"_suite = [] {
|
||||
Case { "happy path" } = [] {
|
||||
};
|
||||
};
|
||||
|
|
@ -3,9 +3,9 @@ export module math.vec3;
|
|||
import preliminary;
|
||||
import math.vec2;
|
||||
|
||||
namespace lt::math {
|
||||
export namespace lt::math {
|
||||
|
||||
export template<typename T = f32>
|
||||
template<typename T = f32>
|
||||
requires(std::is_arithmetic_v<T>)
|
||||
struct vec3_impl
|
||||
{
|
||||
|
|
@ -102,11 +102,11 @@ struct vec3_impl
|
|||
T z;
|
||||
};
|
||||
|
||||
export using vec3 = vec3_impl<f32>;
|
||||
using vec3 = vec3_impl<f32>;
|
||||
|
||||
export using ivec3 = vec3_impl<i32>;
|
||||
using ivec3 = vec3_impl<i32>;
|
||||
|
||||
export using uvec3 = vec3_impl<u32>;
|
||||
using uvec3 = vec3_impl<u32>;
|
||||
|
||||
} // namespace lt::math
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import preliminary;
|
|||
import math.vec2;
|
||||
import math.vec3;
|
||||
|
||||
namespace lt::math {
|
||||
export namespace lt::math {
|
||||
|
||||
export template<typename T = f32>
|
||||
template<typename T = f32>
|
||||
requires(std::is_arithmetic_v<T>)
|
||||
struct vec4_impl
|
||||
{
|
||||
|
|
@ -121,11 +121,11 @@ struct vec4_impl
|
|||
T w;
|
||||
};
|
||||
|
||||
export using vec4 = vec4_impl<f32>;
|
||||
using vec4 = vec4_impl<f32>;
|
||||
|
||||
export using ivec4 = vec4_impl<i32>;
|
||||
using ivec4 = vec4_impl<i32>;
|
||||
|
||||
export using uvec4 = vec4_impl<u32>;
|
||||
using uvec4 = vec4_impl<u32>;
|
||||
|
||||
} // namespace lt::math
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ using ::std::this_thread::sleep_for;
|
|||
|
||||
// TODO(Light): finish these (and many other) tests...
|
||||
Suite raii = "buffer_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
};
|
||||
sleep_for(std::chrono::milliseconds { 500u });
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
};
|
||||
sleep_for(std::chrono::milliseconds { 500u });
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import renderer.frontend;
|
|||
import renderer.test_utils;
|
||||
|
||||
Suite raii = "debugger_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
ignore = lt::renderer::create_debugger(
|
||||
lt::renderer::Api::vulkan,
|
||||
lt::renderer::get_instance(lt::renderer::Api::vulkan),
|
||||
|
|
@ -14,7 +14,7 @@ Suite raii = "debugger_raii"_suite = [] {
|
|||
);
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
expect_throw([] {
|
||||
ignore = lt::renderer::create_debugger(
|
||||
lt::renderer::Api::vulkan,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import renderer.frontend;
|
|||
import renderer.test_utils;
|
||||
|
||||
Suite raii = "device_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
auto fixture = Fixture_SurfaceGpu {};
|
||||
ignore = lt::renderer::create_device(constants::api, fixture.gpu(), fixture.surface());
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
auto fixture = Fixture_SurfaceGpu {};
|
||||
|
||||
expect_throw([&] {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import renderer.frontend;
|
|||
import renderer.test_utils;
|
||||
|
||||
Suite raii = "pass_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
ignore = lt::renderer::create_pass(
|
||||
constants::api,
|
||||
|
|
@ -17,7 +17,7 @@ Suite raii = "pass_raii"_suite = [] {
|
|||
);
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
expect_throw([&] {
|
||||
ignore = lt::renderer::create_pass(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import renderer.frontend;
|
|||
import renderer.test_utils;
|
||||
|
||||
Suite raii = "renderer_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
ignore = lt::renderer::create_renderer(
|
||||
constants::api,
|
||||
|
|
@ -18,7 +18,7 @@ Suite raii = "renderer_raii"_suite = [] {
|
|||
);
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
expect_throw([&] {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import renderer.frontend;
|
|||
import renderer.test_utils;
|
||||
|
||||
Suite raii = "surface"_suite = [] {
|
||||
Case { "happy path won't throw" } = [&] {
|
||||
Case { "happy paths" } = [&] {
|
||||
auto fixture = Fixture_SurfaceSystem {};
|
||||
|
||||
const auto surface = lt::renderer::create_surface(
|
||||
|
|
@ -16,7 +16,7 @@ Suite raii = "surface"_suite = [] {
|
|||
expect_eq(y, constants::resolution.y);
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [&] {
|
||||
Case { "unhappy paths" } = [&] {
|
||||
auto registry = lt::memory::create_ref<lt::ecs::Registry>();
|
||||
auto entity = lt::ecs::Entity { registry, registry->create_entity() };
|
||||
auto system = lt::surface::System(registry);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ struct RendererContext
|
|||
};
|
||||
|
||||
Suite raii = "system_raii"_suite = [] {
|
||||
Case { "happy path has no errors" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
auto fixture = Fixture_RendererSystem {};
|
||||
expect_false(fixture.has_any_messages_of(lt::renderer::IDebugger::MessageSeverity::error));
|
||||
expect_false(
|
||||
|
|
@ -26,7 +26,7 @@ Suite raii = "system_raii"_suite = [] {
|
|||
);
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
auto fixture = Fixture_SurfaceSystem {};
|
||||
auto empty_entity = lt::ecs::Entity { fixture.registry(),
|
||||
fixture.registry()->create_entity() };
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
export module renderer.test_utils;
|
||||
|
||||
export import preliminary;
|
||||
export import logger;
|
||||
export import test;
|
||||
export import surface.system;
|
||||
export import ecs.registry;
|
||||
export import renderer.factory;
|
||||
export import test.test;
|
||||
export import test.expects;
|
||||
export import memory.reference;
|
||||
export import renderer.frontend;
|
||||
export import renderer.system;
|
||||
|
|
@ -15,15 +12,6 @@ export import math.vec3;
|
|||
export import math.vec4;
|
||||
export import math.mat4;
|
||||
|
||||
export using ::lt::test::Case;
|
||||
export using ::lt::test::expect_eq;
|
||||
export using ::lt::test::expect_false;
|
||||
export using ::lt::test::expect_not_nullptr;
|
||||
export using ::lt::test::expect_throw;
|
||||
export using ::lt::test::operator""_suite;
|
||||
export using ::lt::test::expect_true;
|
||||
export using ::lt::test::Suite;
|
||||
|
||||
export namespace constants {
|
||||
|
||||
constexpr auto api = lt::renderer::Api::vulkan;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
add_executable(sandbox sandbox.cpp)
|
||||
target_link_libraries(sandbox PRIVATE preliminary logger bitwise env memory time test math assets app ecs surface renderer input mirror)
|
||||
target_link_libraries(sandbox PRIVATE preliminary logger bitwise memory time test math assets app ecs surface renderer input mirror)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import preliminary;
|
||||
import test.test;
|
||||
import time;
|
||||
import test.expects;
|
||||
import surface.system;
|
||||
|
|
|
|||
|
|
@ -1099,6 +1099,7 @@ void System::modify_resolution(SurfaceComponent &surface, const ModifyResolution
|
|||
|
||||
void System::modify_position(SurfaceComponent &surface, const ModifyPositionRequest &request)
|
||||
{
|
||||
log::debug("Setting window position to: {}, {}", request.position.x, request.position.y);
|
||||
SetWindowPos(
|
||||
surface.m_native_data.window,
|
||||
{},
|
||||
|
|
|
|||
|
|
@ -1,26 +1,16 @@
|
|||
import preliminary;
|
||||
import test.test;
|
||||
import test;
|
||||
import time;
|
||||
import test.expects;
|
||||
import surface.system;
|
||||
import surface.events;
|
||||
import surface.requests;
|
||||
import ecs.registry;
|
||||
import memory.scope;
|
||||
import memory.reference;
|
||||
import logger;
|
||||
import math.vec2;
|
||||
import app.system;
|
||||
|
||||
using ::lt::surface::SurfaceComponent;
|
||||
using ::lt::surface::System;
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::expect_eq;
|
||||
using ::lt::test::expect_ne;
|
||||
using ::lt::test::expect_not_nullptr;
|
||||
using ::lt::test::expect_throw;
|
||||
using ::lt::test::Suite;
|
||||
using ::lt::test::operator""_suite;
|
||||
|
||||
[[nodiscard]] auto tick_info() -> lt::app::TickInfo
|
||||
{
|
||||
|
|
@ -87,12 +77,16 @@ private:
|
|||
};
|
||||
|
||||
Suite raii = "raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
};
|
||||
|
||||
Case { "many won't freeze/throw" } = [] {
|
||||
Case { "unhappy paths" } = [] {
|
||||
expect_throw([] { ignore = System { {} }; });
|
||||
};
|
||||
|
||||
Case { "many" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
for (auto idx : std::views::iota(0, 250))
|
||||
{
|
||||
|
|
@ -101,10 +95,6 @@ Suite raii = "raii"_suite = [] {
|
|||
}
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
expect_throw([] { ignore = System { {} }; });
|
||||
};
|
||||
|
||||
Case { "post construct has correct state" } = [] {
|
||||
auto fixture = Fixture {};
|
||||
auto system = System { fixture.registry() };
|
||||
|
|
@ -269,15 +259,5 @@ Suite tick_handles_requests = "tick_handles_requests"_suite = [] {
|
|||
expect_eq(surface.get_title(), title);
|
||||
expect_eq(surface.get_position(), position);
|
||||
expect_eq(surface.get_resolution(), resolution);
|
||||
|
||||
lt::log::debug("EVENT COUNT: {}", surface.peek_events().size());
|
||||
for (const auto &event : surface.peek_events())
|
||||
{
|
||||
const auto visitor = overloads {
|
||||
[&](auto event) { lt::log::debug("event: {}", event.to_string()); },
|
||||
};
|
||||
|
||||
std::visit(visitor, event);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
import logger;
|
||||
import test.test;
|
||||
import test;
|
||||
import test.registry;
|
||||
|
||||
import preliminary;
|
||||
|
||||
using namespace ::lt::test;
|
||||
|
||||
void parse_option(std::string_view argument, Registry::Options &options)
|
||||
void parse_option(std::string_view argument, lt::test::Registry::Options &options)
|
||||
{
|
||||
constexpr auto case_str = std::string_view { "--case=" };
|
||||
constexpr auto suite_str = std::string_view { "--suite=" };
|
||||
|
|
@ -19,7 +14,7 @@ void parse_option(std::string_view argument, Registry::Options &options)
|
|||
|
||||
if (argument.starts_with("--mode=") && argument.substr(7ul) == "stats")
|
||||
{
|
||||
options.execution_policy = Registry::ExecutionPolicy::stats;
|
||||
options.execution_policy = lt::test::Registry::ExecutionPolicy::stats;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +51,7 @@ try
|
|||
{
|
||||
auto raw_arguments = std::span<char *>(argv, argc);
|
||||
|
||||
auto options = Registry::Options {};
|
||||
auto options = lt::test::Registry::Options {};
|
||||
for (auto idx = 0; auto &raw_argument : raw_arguments)
|
||||
{
|
||||
// First argument is the "cwd'
|
||||
|
|
@ -83,7 +78,7 @@ try
|
|||
}
|
||||
}
|
||||
|
||||
return static_cast<i32>(Registry::run_all(options));
|
||||
return static_cast<i32>(lt::test::Registry::run_all(options));
|
||||
}
|
||||
catch (const std::exception &exp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,86 +0,0 @@
|
|||
|
||||
#include <cstring>
|
||||
#include <test/test.hpp>
|
||||
|
||||
namespace lt::test {
|
||||
|
||||
class FuzzDataProvider
|
||||
{
|
||||
public:
|
||||
FuzzDataProvider(const uint8_t *data, size_t size): m_data(data, size)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires(
|
||||
std::is_trivially_constructible_v<T> //
|
||||
&& std::is_trivially_copy_constructible_v<T> //
|
||||
&& std::is_trivially_copy_assignable_v<T>
|
||||
)
|
||||
|
||||
auto consume() -> std::optional<T>
|
||||
{
|
||||
if (m_data.size() < sizeof(T))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
T value;
|
||||
std::memcpy(&value, m_data.data(), sizeof(T));
|
||||
|
||||
m_data = m_data.subspan(sizeof(T));
|
||||
return value;
|
||||
}
|
||||
|
||||
auto consume_string(size_t size) -> std::optional<std::string>
|
||||
{
|
||||
if (m_data.size() < size)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
auto value = std::string { (const char *)m_data.data(), size };
|
||||
m_data = m_data.subspan(size);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
auto consume_remaining_as_string() -> std::string
|
||||
{
|
||||
if (m_data.empty())
|
||||
{
|
||||
return std::string {};
|
||||
}
|
||||
|
||||
return { m_data.begin(), m_data.end() };
|
||||
};
|
||||
|
||||
private:
|
||||
std::span<const uint8_t> m_data;
|
||||
};
|
||||
|
||||
} // namespace lt::test
|
||||
|
||||
namespace lt::test {
|
||||
|
||||
auto process_fuzz_input(const uint8_t *data, size_t size) -> int32_t
|
||||
try
|
||||
{
|
||||
return details::Registry::process_fuzz_input(data, size);
|
||||
}
|
||||
catch (const std::exception &exp)
|
||||
{
|
||||
std::println("Fuzz input resulted in uncaught exception:");
|
||||
std::println("\twhat: {}", exp.what());
|
||||
std::println("\tinput size: {}", size);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
}; // namespace lt::test
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
return lt::test::process_fuzz_input(data, size);
|
||||
}
|
||||
23
modules/test/module.cppm
Normal file
23
modules/test/module.cppm
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
export module test;
|
||||
|
||||
export import preliminary;
|
||||
export import test.test;
|
||||
export import test.expects;
|
||||
export import test.expects;
|
||||
export import logger;
|
||||
|
||||
export using ::lt::test::Suite;
|
||||
export using ::lt::test::Case;
|
||||
|
||||
export using ::lt::test::expect_eq;
|
||||
export using ::lt::test::expect_ne;
|
||||
export using ::lt::test::expect_le;
|
||||
|
||||
export using ::lt::test::expect_true;
|
||||
export using ::lt::test::expect_false;
|
||||
|
||||
export using ::lt::test::expect_throw;
|
||||
export using ::lt::test::expect_not_nullptr;
|
||||
export using ::lt::test::expect_unreachable;
|
||||
|
||||
export using ::lt::test::operator""_suite;
|
||||
|
|
@ -1,20 +1,6 @@
|
|||
import preliminary;
|
||||
import test.test;
|
||||
import test.expects;
|
||||
|
||||
using lt::test::Case;
|
||||
using lt::test::Suite;
|
||||
using lt::test::operator""_suite;
|
||||
import test;
|
||||
|
||||
Suite expects = "expects"_suite = []() {
|
||||
using lt::test::expect_unreachable;
|
||||
using lt::test::expect_true;
|
||||
using lt::test::expect_false;
|
||||
using lt::test::expect_eq;
|
||||
using lt::test::expect_ne;
|
||||
using lt::test::expect_le;
|
||||
using lt::test::expect_throw;
|
||||
|
||||
Case { "" } = [] {
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,31 +1,22 @@
|
|||
import preliminary;
|
||||
import test;
|
||||
import time;
|
||||
import test.test;
|
||||
import test.expects;
|
||||
|
||||
using ::lt::test::Case;
|
||||
using ::lt::test::expect_le;
|
||||
using ::lt::test::operator""_suite;
|
||||
using ::lt::test::Suite;
|
||||
using ::lt::time::Timer;
|
||||
|
||||
// error margin is high since run-time may slow down extremely due to
|
||||
// sanitization/debugging or execution through valgrind...
|
||||
//
|
||||
// <1us error margin is tested manually in release builds and it works fine.
|
||||
/* @note: error margin is high since run-time may slow down extremely due to
|
||||
* sanitization/debugging or execution through valgrind...
|
||||
* <1us error margin is tested manually in release builds and it works fine.
|
||||
**/
|
||||
constexpr auto max_error_margin = std::chrono::milliseconds { 1 };
|
||||
|
||||
Suite raii = "raii"_suite = [] {
|
||||
using std::chrono::microseconds;
|
||||
|
||||
Case { "default" } = [] {
|
||||
Case { "happy paths" } = [] {
|
||||
Timer {};
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
};
|
||||
|
||||
Case { "plenty" } = [] {
|
||||
Case { "many" } = [] {
|
||||
for (auto idx : std::views::iota(0, 100'001))
|
||||
{
|
||||
ignore = idx;
|
||||
|
|
@ -38,7 +29,7 @@ Suite reset_and_elapsed_time = "reset_and_elapsed_time"_suite = [] {
|
|||
using std::chrono::hours;
|
||||
using std::chrono::microseconds;
|
||||
|
||||
Case { "won't throw" } = [] {
|
||||
Case { "happy path" } = [] {
|
||||
Timer {}.reset();
|
||||
ignore = Timer {}.elapsed_time();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue