diff --git a/.gitignore b/.gitignore index b3f2406..0c0a0dd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.out *.exe *.asm +*.backup # Folder-exclusions build/ diff --git a/tests/cpp/.clang-tidy b/tests/cpp/.clang-tidy index 72affbd..d99244e 100644 --- a/tests/cpp/.clang-tidy +++ b/tests/cpp/.clang-tidy @@ -10,11 +10,12 @@ Checks: > modernize-*, performance-*, readability-*, - -cppcoreguidelines-avoid-magic-numbers, -readability-redundant-access-specifiers, + -cppcoreguidelines-non-private-member-variables-in-classes, + -cppcoreguidelines-avoid-magic-numbers, -readability-magic-numbers, - -readability-function-cognitive-complexity, -readability-identifier-length, + -readability-function-cognitive-complexity, WarningsAsErrors: '' FormatStyle: none diff --git a/tests/cpp/CMakeLists.txt b/tests/cpp/CMakeLists.txt index 7f5e4d3..f516e1c 100644 --- a/tests/cpp/CMakeLists.txt +++ b/tests/cpp/CMakeLists.txt @@ -34,10 +34,12 @@ add_executable( ${CMAKE_CURRENT_SOURCE_DIR}/test_quat_type.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_quat_operations.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_euler_type.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_pose3d_type.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_mat2_functions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_mat3_functions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_mat4_functions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_utils_spherical_coordinates.cpp) target_link_libraries(MathCppTests PRIVATE math::math Catch2::Catch2) +target_include_directories(MathCppTests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) # Discover tets and pick an integer as the random seed catch_discover_tests(MathCppTests) diff --git a/tests/cpp/common_math_generators.hpp b/tests/cpp/common_math_generators.hpp new file mode 100644 index 0000000..07c6d18 --- /dev/null +++ b/tests/cpp/common_math_generators.hpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include + +#include + +namespace math { + +template +class RandomValueBase : public Catch::Generators::IGenerator { + public: + RandomValueBase(T val_range_min, T val_range_max) + : m_Dist(val_range_min, val_range_max), // NOLINT + m_Gen(std::random_device{}()) {} // NOLINT + + auto get() const -> const V& override { return m_Value; } + + protected: + /// Distribution from which to generate random real values + std::uniform_real_distribution m_Dist; + /// The method used to generate random numbers + std::minstd_rand m_Gen; + /// The vector value to be exposed + V m_Value; +}; + +//****************************************************************************// +// Generators for Vector types // +//****************************************************************************// + +template +class RandomVec2Generator : public RandomValueBase> { + public: + RandomVec2Generator(T val_range_min, T val_range_max) + : RandomValueBase>(val_range_min, val_range_max) {} + + auto next() -> bool override { + this->m_value = {this->m_Dist(this->m_Gen), this->m_Dist(this->m_Gen)}; + return true; + } +}; + +template +class RandomVec3Generator : public RandomValueBase> { + public: + RandomVec3Generator(T val_range_min, T val_range_max) + : RandomValueBase>(val_range_min, val_range_max) {} + + auto next() -> bool override { + this->m_Value = {this->m_Dist(this->m_Gen), this->m_Dist(this->m_Gen), + this->m_Dist(this->m_Gen)}; + return true; + } +}; + +template +class RandomVec4Generator : public RandomValueBase> { + public: + RandomVec4Generator(T val_range_min, T val_range_max) + : RandomValueBase>(val_range_min, val_range_max) {} + + auto next() -> bool override { + this->m_Value = {this->m_Dist(this->m_Gen), this->m_Dist(this->m_Gen), + this->m_Dist(this->m_Gen), this->m_Dist(this->m_Gen)}; + return true; + } +}; + +template +auto random_vec2(T val_range_min = static_cast(-1.0), + T val_range_max = static_cast(1.0)) + -> Catch::Generators::GeneratorWrapper> { + return Catch::Generators::GeneratorWrapper>( + Catch::Generators::pf::make_unique>( + val_range_min, val_range_max)); +} + +template +auto random_vec3(T val_range_min = static_cast(-1.0), + T val_range_max = static_cast(1.0)) + -> Catch::Generators::GeneratorWrapper> { + return Catch::Generators::GeneratorWrapper>( + Catch::Generators::pf::make_unique>( + val_range_min, val_range_max)); +} + +template +auto random_vec4(T val_range_min = static_cast(-1.0), + T val_range_max = static_cast(1.0)) + -> Catch::Generators::GeneratorWrapper> { + return Catch::Generators::GeneratorWrapper>( + Catch::Generators::pf::make_unique>( + val_range_min, val_range_max)); +} + +//****************************************************************************// +// Generators for Quaternion type // +//****************************************************************************// + +template +class RandomQuaternion : public RandomValueBase> { + public: + RandomQuaternion() : RandomValueBase>(-1.0, 1.0) {} + + auto next() -> bool override { + this->m_Value = {this->m_Dist(this->m_Gen), this->m_Dist(this->m_Gen), + this->m_Dist(this->m_Gen), this->m_Dist(this->m_Gen)}; + return true; + } +}; + +template +auto random_quaternion() -> Catch::Generators::GeneratorWrapper> { + return Catch::Generators::GeneratorWrapper>( + Catch::Generators::pf::make_unique>()); +} + +} // namespace math diff --git a/tests/cpp/test_pose3d_type.cpp b/tests/cpp/test_pose3d_type.cpp new file mode 100644 index 0000000..b800a18 --- /dev/null +++ b/tests/cpp/test_pose3d_type.cpp @@ -0,0 +1,44 @@ +#include +#include + +#include +#include + +#include + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wimplicit-float-conversion" +#pragma clang diagnostic ignored "-Wdouble-promotion" +#endif + +// NOLINTNEXTLINE +TEMPLATE_TEST_CASE("Pose3d class (pose3d_t) constructors", + "[pose3d_t][template", ::math::float32_t, + ::math::float64_t) { + using T = TestType; + using Pose = ::math::Pose3d; + using Quat = ::math::Quaternion; + using Vec3 = ::math::Vector3; + + SECTION("Default constructor") { + Pose X; // NOLINT + REQUIRE(X.position == Vec3(0.0, 0.0, 0.0)); + REQUIRE(X.orientation == Quat(1.0, 0.0, 0.0, 0.0)); + } + + SECTION("From position(Vec3) and orientation(Quat)") { + auto position = GENERATE(take(10, ::math::random_vec3(-10.0, 10.0))); + auto orientation = GENERATE(take(10, ::math::random_quaternion())); + + Pose X(position, orientation); // NOLINT + // Position should be copied directly to the pose object + REQUIRE(X.position == position); + // Orientation normalized to ensure it represents a rotation + REQUIRE(std::abs(X.orientation.length() - 1.0) < 1e-5); + } +} + +#if defined(__clang__) +#pragma clang diagnostic pop // NOLINT +#endif