From 4d9a9d3a952084bf9a522f8509a4eb82c890054a Mon Sep 17 00:00:00 2001 From: josh Date: Wed, 26 Jun 2024 11:43:29 -0400 Subject: [PATCH] Migrate from google-test to jtest. --- CMakeLists.txt | 14 +- cmake/gtest.cmake | 68 ------ tests/Algorithm/RNGTests.hpp | 132 +++++++++++ tests/CMakeLists.txt | 21 +- tests/Geometry/TriangleTests.cpp | 89 -------- tests/Geometry/TriangleTests.hpp | 97 ++++++++ ...ulerAngleTests.cpp => EulerAngleTests.hpp} | 4 + ...{Matrix2x2Tests.cpp => Matrix2x2Tests.hpp} | 5 +- tests/LinearAlgebra/Matrix3x3Tests.cpp | 90 -------- tests/LinearAlgebra/Matrix3x3Tests.hpp | 96 ++++++++ tests/LinearAlgebra/Matrix4x4Tests.cpp | 11 - tests/LinearAlgebra/Matrix4x4Tests.hpp | 129 +++++++++++ tests/LinearAlgebra/QuaternionTests.hpp | 75 +++++++ tests/LinearAlgebra/Vector2Tests.cpp | 183 --------------- tests/LinearAlgebra/Vector2Tests.hpp | 191 ++++++++++++++++ tests/LinearAlgebra/Vector3Tests.cpp | 198 ----------------- tests/LinearAlgebra/Vector3Tests.hpp | 208 ++++++++++++++++++ tests/LinearAlgebra/Vector4Tests.cpp | 106 --------- tests/LinearAlgebra/Vector4Tests.hpp | 116 ++++++++++ 19 files changed, 1069 insertions(+), 764 deletions(-) delete mode 100644 cmake/gtest.cmake create mode 100644 tests/Algorithm/RNGTests.hpp delete mode 100644 tests/Geometry/TriangleTests.cpp create mode 100644 tests/Geometry/TriangleTests.hpp rename tests/LinearAlgebra/{EulerAngleTests.cpp => EulerAngleTests.hpp} (50%) rename tests/LinearAlgebra/{Matrix2x2Tests.cpp => Matrix2x2Tests.hpp} (67%) delete mode 100644 tests/LinearAlgebra/Matrix3x3Tests.cpp create mode 100644 tests/LinearAlgebra/Matrix3x3Tests.hpp delete mode 100644 tests/LinearAlgebra/Matrix4x4Tests.cpp create mode 100644 tests/LinearAlgebra/Matrix4x4Tests.hpp create mode 100644 tests/LinearAlgebra/QuaternionTests.hpp delete mode 100644 tests/LinearAlgebra/Vector2Tests.cpp create mode 100644 tests/LinearAlgebra/Vector2Tests.hpp delete mode 100644 tests/LinearAlgebra/Vector3Tests.cpp create mode 100644 tests/LinearAlgebra/Vector3Tests.hpp delete mode 100644 tests/LinearAlgebra/Vector4Tests.cpp create mode 100644 tests/LinearAlgebra/Vector4Tests.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f15b4c..edaf36a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,9 +16,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Enable Package Managers include(cmake/CPM.cmake) -#include(cmake/gtest.cmake) -include(CTest) file(GLOB_RECURSE J3ML_HEADERS "include/J3ML/*.h" "include/J3ML/*.hpp") file(GLOB_RECURSE J3ML_SRC "src/J3ML/*.c" "src/J3ML/*.cpp") @@ -33,6 +31,16 @@ if (WIN32) add_library(J3ML STATIC ${J3ML_SRC}) endif() set_target_properties(J3ML PROPERTIES LINKER_LANGUAGE CXX) + +CPMAddPackage( + NAME jtest + URL https://git.redacted.cc/josh/jtest/archive/Prerelease-3.zip +) + +target_include_directories(J3ML PUBLIC ${jtest_SOURCE_DIR}/include) + +target_link_libraries(J3ML PUBLIC jtest) + if(WIN32) #target_compile_options(J3ML PRIVATE -Wno-multichar) endif() @@ -46,6 +54,8 @@ add_subdirectory(tests) add_executable(MathDemo main.cpp) target_link_libraries(MathDemo ${PROJECT_NAME}) + + if(WIN32) #target_compile_options(MathDemo PRIVATE -mwindows) endif() \ No newline at end of file diff --git a/cmake/gtest.cmake b/cmake/gtest.cmake deleted file mode 100644 index 430e588..0000000 --- a/cmake/gtest.cmake +++ /dev/null @@ -1,68 +0,0 @@ -cmake_minimum_required(VERSION 2.8 FATAL_ERROR) - -#----------------------------------------------------------------------- -# CPM configuration -#----------------------------------------------------------------------- -set(CPM_MODULE_NAME google_test) -set(CPM_LIB_TARGET_NAME ${CPM_MODULE_NAME}) - -if ((DEFINED CPM_DIR) AND (DEFINED CPM_UNIQUE_ID) AND (DEFINED CPM_TARGET_NAME)) - set(CPM_LIB_TARGET_NAME ${CPM_TARGET_NAME}) - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CPM_DIR}) - include(CPM) -else() - set(CPM_DIR "${CMAKE_CURRENT_BINARY_DIR}/cpm-packages" CACHE TYPE STRING) - find_package(Git) - if(NOT GIT_FOUND) - message(FATAL_ERROR "CPM requires Git.") - endif() - if (NOT EXISTS ${CPM_DIR}/CPM.cmake) - execute_process( - COMMAND "${GIT_EXECUTABLE}" clone https://github.com/iauns/cpm ${CPM_DIR} - RESULT_VARIABLE error_code - OUTPUT_VARIABLE head_sha) - if(error_code) - message(FATAL_ERROR "CPM failed to get the hash for HEAD") - endif() - endif() - include(${CPM_DIR}/CPM.cmake) -endif() - -# All externals *must* define this. -CPM_ForceOnlyOneModuleVersion() - -CPM_InitModule(${CPM_MODULE_NAME}) - -#------------------------------------------------------------------------------ -# Google Test -#------------------------------------------------------------------------------ -# Google test as an external project is a bad idea! You really should add it -# as a subdirectory so that it can capture your compiler flags -set(GOOGLE_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdParty/gtest) -CPM_EnsureRepoIsCurrent( - TARGET_DIR ${GOOGLE_TEST_DIR} - SVN_REPOSITORY "http://googletest.googlecode.com/svn/trunk" - SVN_REVISION "664" - USE_CACHING TRUE -) - -# Compiler flags for MSVC 2010 -if (MSVC_VERSION EQUAL 1600) - add_definitions(-DGTEST_USE_OWN_TR1_TUPLE=0) - CPM_ExportAdditionalDefinition("-DGTEST_USE_OWN_TR1_TUPLE=0") -endif() - -# Compiler flags for MSVC 2012 -if(MSVC_VERSION EQUAL 1700) - add_definitions(-D_VARIADIC_MAX=10) -endif() - -# For All versions of gtest, we force shared CRT. -set(gtest_force_shared_crt ON) -set(gtest_force_shared_crt ON) - -# Add gtest now that we have the appropriate flags set. -add_subdirectory(${GOOGLE_TEST_DIR}) - -CPM_ExportAdditionalIncludeDir("${GOOGLE_TEST_DIR}/include") -CPM_ExportAdditionalLibraryTarget("gtest") \ No newline at end of file diff --git a/tests/Algorithm/RNGTests.hpp b/tests/Algorithm/RNGTests.hpp new file mode 100644 index 0000000..1b3cc2c --- /dev/null +++ b/tests/Algorithm/RNGTests.hpp @@ -0,0 +1,132 @@ +#include +#include +using J3ML::Algorithm::RNG; + +int RNGTests() +{ + TEST("RNG::IntFast", []{ + RNG rng; + u32 prev = rng.IntFast(); + + for (int i = 0; i < 1000; ++i) + { + u32 next = rng.IntFast(); + jtest::check(next != prev); + prev = next; + } + }); + + TEST("RNG::Int", []{ + RNG rng; + assert(rng.lastNumber != 0 || rng.increment != 0); + bool allEqual = true; + for (int i = 0; i < 1000; ++i) + { + int prev = rng.Int(); + int next = rng.Int(); + jtest::check(prev != 0 || next != 0); + if (prev != next) + allEqual = false; + } + jtest::check(!allEqual); + + }); + + TEST("Rng::Int_A_B", []{ + RNG rng; + for (int i = 0; i < 1000; ++i) + { + int a = rng.Int(); + int b = rng.Int(); + if (b < a) + Swap(a, b); + int val = rng.Int(a, b); + jtest::check( a <= val); + jtest::check(val <= b); + } + }); + + TEST("Rng::Float", []{ + RNG rng; + bool allEqual = true; + for (int i = 0; i < 1000; ++i) + { + float f = rng.Float(); + float f2 = rng.Float(); + jtest::check(f < 1.f); + jtest::check(f >= 0.f); + jtest::check(f != 0.f || f2 != 0.f); + + if (f != f2) + allEqual = false; + } + jtest::check(!allEqual); + }); + + TEST("Rng::Float01Incl", []{ + RNG rng; + bool allEqual = true; + for (int i = 0; i < 1000; ++i) + { + float f = rng.Float01Incl(); + float f2 = rng.Float01Incl(); + + jtest::check(f <= 1.f); + jtest::check(f >= 0.f); + jtest::check(f != 0.f || f2 != 0.f); + if (f != f2) + allEqual = false; + } + jtest::check(!allEqual); + }); + + TEST("Rng::FloatNeg1_1", []{ + RNG rng; + bool allEqual = true; + for (int i = 0; i < 1000; ++i) + { + float f = rng.FloatNeg1_1(); + float f2 = rng.FloatNeg1_1(); + jtest::check(f < 1.f); + jtest::check(f > -1.f); + jtest::check(f != 0.f || f2 != 0.f); + if (f != f2) + allEqual = false; + } + jtest::check(!allEqual); + }); + + TEST("Rng, Float_A_B", []{ + RNG rng; + for (int i = 0; i < 1000; ++i) + { + float a = rng.Float(); + float b = rng.Float(); + if (a == b) + continue; + if (b < a) + Swap(a, b); + + float f = rng.Float(a, b); + jtest::check(a <= f); + jtest::check(f < b); + } + }); + + TEST("Rng::Float_A_B_Incl", []{ + RNG rng; + for (int i = 0; i < 1000; ++i) + { + float a = rng.Float(); + float b = rng.Float(); + if (b > a) + Swap(a, b); + + float f = rng.FloatIncl(a, b); + jtest::check(a <= f); + jtest::check(f <= b); + } + }); + + return 0; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bbb9688..1f4f8f2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,20 +1,9 @@ cmake_minimum_required(VERSION 3.18) -include(FetchContent) -FetchContent_Declare( - googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG release-1.11.0 -) -FetchContent_MakeAvailable(googletest) -add_library(GTest::GTest INTERFACE IMPORTED) -target_link_libraries(GTest::GTest INTERFACE gtest_main) +file(GLOB_RECURSE TEST_FILES "*.hpp") +add_executable(J3MLTestSuite tests.cpp) -file(GLOB_RECURSE TEST_SRC "tests.cpp" "*.cpp") -add_executable(Test ${TEST_SRC}) -target_link_libraries(Test PUBLIC J3ML) -#find_package(GTest REQUIRED) -target_link_libraries(Test PRIVATE GTest::GTest) -include_directories("include") -add_test(NAME "J3MLTestSuite" COMMAND Test) \ No newline at end of file +target_include_directories(J3MLTestSuite PUBLIC "include" $TEST_FILES) + +target_link_libraries(J3MLTestSuite PUBLIC J3ML) \ No newline at end of file diff --git a/tests/Geometry/TriangleTests.cpp b/tests/Geometry/TriangleTests.cpp deleted file mode 100644 index 0858d91..0000000 --- a/tests/Geometry/TriangleTests.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include - -using J3ML::Geometry::Interval; -using J3ML::Geometry::Triangle; - -TEST(TriangleTests, FaceNormal) -{ - Triangle t{ - Vector3{-1, -1, -1}, - Vector3{0, 1, 0}, - Vector3{1, -1, 1} - }; - - EXPECT_EQ(t.FaceNormal(), (Vector3{4, 0, -4})); -} - -TEST(TriangleTests, IntersectTriangle) -{ - Triangle xyTriangle{ - {0.0f, 0.0f, 0.0f}, - {1.0f, 1.0f, 0.0f}, - {2.0f, 0.0f, 0.0f} - }; - - // Triangle collides with itself - EXPECT_EQ(Intersects(xyTriangle, xyTriangle), true); - // Translate 1 towards x -- should collide - EXPECT_EQ(Intersects(xyTriangle, xyTriangle.Translated(Vector3(1.0f, 0.0f, 0.0f))), true); - // Translate 2 towards x -- should collide exactly on V1 - EXPECT_EQ(Intersects(xyTriangle, xyTriangle.Translated(Vector3(2.0f, 0.0f, 0.0f))), true); - // Translate 2 towards negative x -- should collide exactly on V0 - EXPECT_EQ(Intersects(xyTriangle, xyTriangle.Translated(Vector3(-2.0f, 0.0f, 0.0f))), true); - // Translate 3 towards x -- should not collide - EXPECT_EQ(Intersects(xyTriangle, xyTriangle.Translated(Vector3(3.0f, 0.0f, 0.0f))), false); - // Translate 3 towards negative x -- should not collide - EXPECT_EQ(Intersects(xyTriangle, xyTriangle.Translated(Vector3(-3.0f, 0.0f, 0.0f))), false); - // Translate 1 towards z -- should not collide - EXPECT_EQ(Intersects(xyTriangle, xyTriangle.Translated(Vector3(0.0f, 0.0f, 1.0f))), false); - // Triangle collides with contained smaller triangle - EXPECT_EQ(Intersects(xyTriangle, xyTriangle.Scaled(Vector3(0.5f, 0.5f, 0.5f)).Translated(Vector3(0.25f, 0.25f, 0.0f))), true); - - Triangle zxTriangle { - {0.0f, 0.0f, 0.0f}, - {1.0f, 0.0f, 1.0f}, - {0.0f, 0.0f, 2.0f} - }; - - // Should collide exactly on V0 - EXPECT_EQ(Intersects(xyTriangle, zxTriangle), true); - // Should collide across xyTriangle's edge and zxTriangle's face - EXPECT_EQ(Intersects(xyTriangle, zxTriangle.Translated(Vector3(0.0f, 0.0f, -1.0))), true); - // Should collide exactly on V1 - EXPECT_EQ(Intersects(xyTriangle, zxTriangle.Translated(Vector3(0.0f, 0.0f, -2.0))), true); - // xyTriangle's face should be poked by zxTriangle's V0 - EXPECT_EQ(Intersects(xyTriangle, zxTriangle.Translated(Vector3(1.0f, 1.0f, 0.0f))), true); - // xyTriangle's face should be cut by zxTriangle - EXPECT_EQ(Intersects(xyTriangle, zxTriangle.Translated(Vector3(1.0f, 1.0f, -0.5f))), true); - // Should not collide - EXPECT_EQ(Intersects(xyTriangle, zxTriangle.Translated(Vector3(1.0f, 1.0f, 1.0f))), false); - // Should not collide - EXPECT_EQ(Intersects(xyTriangle, zxTriangle.Translated(Vector3(0.0f, 0.0f, -3.0f))), false); - - Triangle yxTriangle{ - {0.0f, 0.0f, 0.0f}, - {1.0f, 1.0f, 0.0f}, - {0.0f, 2.0f, 0.0f} - }; - - // Should collide on V0-V1 edge - EXPECT_EQ(Intersects(yxTriangle, yxTriangle), true); - // Should not collide - EXPECT_EQ(Intersects(xyTriangle, yxTriangle.Translated(Vector3(0.0f, 1.0f, 0.0f))), false); - // Should not collide - EXPECT_EQ(Intersects(yxTriangle, yxTriangle.Translated(Vector3(0.0f, 0.0f, 1.0f))), false); - - Triangle zyInvertedTriangle{ - {0.0f, 1.0f, -1.0f}, - {0.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 1.0f} - }; - // Should collide exactly on V1 - EXPECT_EQ(Intersects(xyTriangle, zyInvertedTriangle), true); - // Should not collide - EXPECT_EQ(Intersects(xyTriangle, zyInvertedTriangle.Translated(Vector3(0.0f, 1.0f, 0.0f))), false); - // Should not collide - EXPECT_EQ(Intersects(xyTriangle, zyInvertedTriangle.Translated(Vector3(0.25f, 0.75f, 0.0f))), false); -} - diff --git a/tests/Geometry/TriangleTests.hpp b/tests/Geometry/TriangleTests.hpp new file mode 100644 index 0000000..4b9d811 --- /dev/null +++ b/tests/Geometry/TriangleTests.hpp @@ -0,0 +1,97 @@ +#include +#include + +using J3ML::Geometry::Interval; +using J3ML::Geometry::Triangle; + +int TriangleTests() { + TEST("Triangle::FaceNormal", [] { + Triangle t( + {-1, -1, -1}, + {0, 1, 0}, + {1, -1, 1} + ); + + jtest::check(t.FaceNormal() == Vector3{4, 0, -4}); + }); + + TEST("Triangle::IntersectTriangle", [] + { + Triangle xyTriangle( + {0.0f, 0.0f, 0.0f}, + {1.0f, 1.0f, 0.0f}, + {2.0f, 0.0f, 0.0f} + ); + + // Triangle collides with itself + jtest::check(Intersects(xyTriangle, xyTriangle)); + // Translate 1 towards x -- should collide + jtest::check(Intersects(xyTriangle, xyTriangle.Translated(Vector3(1.0f, 0.0f, 0.0f)))); + // Translate 2 towards x -- should collide exactly on V1 + jtest::check(Intersects(xyTriangle, xyTriangle.Translated(Vector3(2.0f, 0.0f, 0.0f)))); + // Translate 2 towards negative x -- should collide exactly on V0 + jtest::check(Intersects(xyTriangle, xyTriangle.Translated(Vector3(-2.0f, 0.0f, 0.0f)))); + // Translate 3 towards x -- should not collide + jtest::check(!Intersects(xyTriangle, xyTriangle.Translated(Vector3(3.0f, 0.0f, 0.0f)))); + // Translate 3 towards negative x -- should not collide + jtest::check(!Intersects(xyTriangle, xyTriangle.Translated(Vector3(-3.0f, 0.0f, 0.0f)))); + // Translate 1 towards z -- should not collide + jtest::check(!Intersects(xyTriangle, xyTriangle.Translated(Vector3(0.0f, 0.0f, 1.0f)))); + // Triangle collides with contained smaller triangle + jtest::check(!Intersects(xyTriangle, xyTriangle.Scaled(Vector3(0.5f, 0.5f, 0.5f)).Translated(Vector3(0.25f, 0.25f, 0.0f)))); + + Triangle zxTriangle ( + {0.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 2.0f} + ); + + // Should collide exactly on V0 + jtest::check(Intersects(xyTriangle, zxTriangle)); + // Should collide across xyTriangle's edge and zxTriangle's face + jtest::check(Intersects(xyTriangle, zxTriangle.Translated(Vector3(0.0f, 0.0f, -1.0)))); + // Should collide exactly on V1 + jtest::check(Intersects(xyTriangle, zxTriangle.Translated(Vector3(0.0f, 0.0f, -2.0)))); + // xyTriangle's face should be poked by zxTriangle's V0 + jtest::check(Intersects(xyTriangle, zxTriangle.Translated(Vector3(1.0f, 1.0f, 0.0f)))); + // xyTriangle's face should be cut by zxTriangle + jtest::check(Intersects(xyTriangle, zxTriangle.Translated(Vector3(1.0f, 1.0f, -0.5f)))); + // Should not collide + jtest::check(!Intersects(xyTriangle, zxTriangle.Translated(Vector3(1.0f, 1.0f, 1.0f)))); + // Should not collide + jtest::check(!Intersects(xyTriangle, zxTriangle.Translated(Vector3(0.0f, 0.0f, -3.0f)))); + + Triangle yxTriangle( + {0.0f, 0.0f, 0.0f}, + {1.0f, 1.0f, 0.0f}, + {0.0f, 2.0f, 0.0f} + ); + + // Should collide on V0-V1 edge + jtest::check(Intersects(yxTriangle, yxTriangle)); + // Should not collide + jtest::check(!Intersects(xyTriangle, yxTriangle.Translated(Vector3(0.0f, 1.0f, 0.0f)))); + // Should not collide + jtest::check(!Intersects(yxTriangle, yxTriangle.Translated(Vector3(0.0f, 0.0f, 1.0f)))); + + Triangle zyInvertedTriangle( + {0.0f, 1.0f, -1.0f}, + {0.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 1.0f} + ); + // Should collide exactly on V1 + jtest::check(Intersects(xyTriangle, zyInvertedTriangle)); + // Should not collide + jtest::check(!Intersects(xyTriangle, zyInvertedTriangle.Translated(Vector3(0.0f, 1.0f, 0.0f)))); + // Should not collide + jtest::check(!Intersects(xyTriangle, zyInvertedTriangle.Translated(Vector3(0.25f, 0.75f, 0.0f)))); + }); + + + return 0; +} + + + + + diff --git a/tests/LinearAlgebra/EulerAngleTests.cpp b/tests/LinearAlgebra/EulerAngleTests.hpp similarity index 50% rename from tests/LinearAlgebra/EulerAngleTests.cpp rename to tests/LinearAlgebra/EulerAngleTests.hpp index a8cec1d..9b56f0d 100644 --- a/tests/LinearAlgebra/EulerAngleTests.cpp +++ b/tests/LinearAlgebra/EulerAngleTests.hpp @@ -1,3 +1,7 @@ // // Created by josh on 12/26/2023. // + +int EulerAngleTests() { + return 0; +} \ No newline at end of file diff --git a/tests/LinearAlgebra/Matrix2x2Tests.cpp b/tests/LinearAlgebra/Matrix2x2Tests.hpp similarity index 67% rename from tests/LinearAlgebra/Matrix2x2Tests.cpp rename to tests/LinearAlgebra/Matrix2x2Tests.hpp index be67dd8..62d4487 100644 --- a/tests/LinearAlgebra/Matrix2x2Tests.cpp +++ b/tests/LinearAlgebra/Matrix2x2Tests.hpp @@ -1,5 +1,8 @@ -#include + #include using namespace J3ML::LinearAlgebra; +int Matrix2x2Tests() { + return 0; +} \ No newline at end of file diff --git a/tests/LinearAlgebra/Matrix3x3Tests.cpp b/tests/LinearAlgebra/Matrix3x3Tests.cpp deleted file mode 100644 index 95f0b64..0000000 --- a/tests/LinearAlgebra/Matrix3x3Tests.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include - -using namespace J3ML::LinearAlgebra; - -// TODO: create RNG instance - -RNG rng; - -TEST(Mat3x3, Add_Unary) -{ - Matrix3x3 m(1,2,3, 4,5,6, 7,8,9); - Matrix3x3 m2 = +m; - assert(m.Equals(m2)); -} - -TEST(Mat3x3, Solve_Axb) -{ - Matrix3x3 A = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); - bool mayFail = Math::EqualAbs(A.Determinant(), 0.f, 1e-2f); - - Vector3 b = Vector3::RandomBox(rng, Vector3::FromScalar(-10.f), Vector3::FromScalar(10.f)); - - Vector3 x; - bool success = A.SolveAxb(b, x); - assert(success || mayFail); - if (success) - { - Vector3 b2 = A*x; - assert(b2.Equals(b, 1e-1f)); - } -} - -TEST(Mat3x3, Inverse_Case) -{ - Matrix3x3 m(-8.75243664f,6.71196938f,-5.95816374f,6.81996822f,-6.85106039f,2.38949537f,-0.856015682f,3.45762491f,3.311584f); - - bool success = m.Inverse(); - assert(success); -} - -TEST(Mat3x3, Inverse) -{ - Matrix3x3 A = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); - bool mayFail = Math::EqualAbs(A.Determinant(), 0.f, 1e-2f); - - Matrix3x3 A2 = A; - bool success = A2.Inverse(); - assert(success || mayFail); - if (success) - { - Matrix3x3 id = A * A2; - Matrix3x3 id2 = A2 * A; - assert(id.Equals(Matrix3x3::Identity, 0.3f)); - assert(id2.Equals(Matrix3x3::Identity, 0.3f)); - } -} - -TEST(Mat3x3, InverseFast) -{ - // TODO: Fix implementation of InverseFast - /* - Matrix3x3 A = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); - bool mayFail = Math::EqualAbs(A.Determinant(), 0.f, 1e-2f); - - Matrix3x3 A2 = A; - bool success = A2.InverseFast(); - assert(success || mayFail); - - if (success) - { - Matrix3x3 id = A * A2; - Matrix3x3 id2 = A2 * A; - assert(id.Equals(Matrix3x3::Identity, 0.3f)); - assert(id2.Equals(Matrix3x3::Identity, 0.3f)); - } - */ -} - -TEST(Mat3x3, MulMat4x4) -{ - Matrix3x3 m = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); - Matrix4x4 m_ = m; - Matrix4x4 m2 = Matrix4x4::RandomGeneral(rng, -10.f, 10.f); - - Matrix4x4 test = m * m2; - Matrix4x4 correct = m_ * m2; - assert(test.Equals(correct)); -} \ No newline at end of file diff --git a/tests/LinearAlgebra/Matrix3x3Tests.hpp b/tests/LinearAlgebra/Matrix3x3Tests.hpp new file mode 100644 index 0000000..9576829 --- /dev/null +++ b/tests/LinearAlgebra/Matrix3x3Tests.hpp @@ -0,0 +1,96 @@ +#include +#include + +using namespace J3ML::LinearAlgebra; + +// TODO: create RNG instance + +int Matrix3x3Tests() { + + + TEST("Mat3x3::Add_Unary", [] + { + Matrix3x3 m(1,2,3, 4,5,6, 7,8,9); + Matrix3x3 m2 = +m; + jtest::check(m.Equals(m2)); + }); + + TEST("Mat3x3::Solve_Axb", []{ + RNG rng; + Matrix3x3 A = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); + bool mayFail = Math::EqualAbs(A.Determinant(), 0.f, 1e-2f); + + Vector3 b = Vector3::RandomBox(rng, Vector3::FromScalar(-10.f), Vector3::FromScalar(10.f)); + + Vector3 x; + bool success = A.SolveAxb(b, x); + jtest::check(success || mayFail); + if (success) + { + Vector3 b2 = A*x; + jtest::check(b2.Equals(b, 1e-1f)); + } + }); + + TEST("Mat3x3::Inverse_Case", [] + { + Matrix3x3 m(-8.75243664f,6.71196938f,-5.95816374f,6.81996822f,-6.85106039f,2.38949537f,-0.856015682f,3.45762491f,3.311584f); + + bool success = m.Inverse(); + jtest::check(success); + }); + + TEST("Mat3x3::Inverse", [] + { + RNG rng; + Matrix3x3 A = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); + bool mayFail = Math::EqualAbs(A.Determinant(), 0.f, 1e-2f); + + Matrix3x3 A2 = A; + bool success = A2.Inverse(); + jtest::check(success || mayFail); + if (success) + { + Matrix3x3 id = A * A2; + Matrix3x3 id2 = A2 * A; + jtest::check(id.Equals(Matrix3x3::Identity, 0.3f)); + jtest::check(id2.Equals(Matrix3x3::Identity, 0.3f)); + } + }); + + + TEST("Mat3x3::InverseFast", [] + { + // TODO: Fix implementation of InverseFast + /* + Matrix3x3 A = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); + bool mayFail = Math::EqualAbs(A.Determinant(), 0.f, 1e-2f); + + Matrix3x3 A2 = A; + bool success = A2.InverseFast(); + assert(success || mayFail); + + if (success) + { + Matrix3x3 id = A * A2; + Matrix3x3 id2 = A2 * A; + assert(id.Equals(Matrix3x3::Identity, 0.3f)); + assert(id2.Equals(Matrix3x3::Identity, 0.3f)); + } + */ + }); + + TEST("Mat3x3::MulMat4x4", [] + { + RNG rng; + Matrix3x3 m = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); + Matrix4x4 m_ = m; + Matrix4x4 m2 = Matrix4x4::RandomGeneral(rng, -10.f, 10.f); + + Matrix4x4 test = m * m2; + Matrix4x4 correct = m_ * m2; + jtest::check(test.Equals(correct)); + }); + + return 0; +} diff --git a/tests/LinearAlgebra/Matrix4x4Tests.cpp b/tests/LinearAlgebra/Matrix4x4Tests.cpp deleted file mode 100644 index 1bb89ad..0000000 --- a/tests/LinearAlgebra/Matrix4x4Tests.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -using namespace J3ML::LinearAlgebra; - -TEST(Mat4x4, Add_Unary) -{ - Matrix4x4 m(1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16); - Matrix4x4 m2 = +m; - assert(m.Equals(m2)); -} diff --git a/tests/LinearAlgebra/Matrix4x4Tests.hpp b/tests/LinearAlgebra/Matrix4x4Tests.hpp new file mode 100644 index 0000000..64ade94 --- /dev/null +++ b/tests/LinearAlgebra/Matrix4x4Tests.hpp @@ -0,0 +1,129 @@ +#include +#include +#include + +using namespace J3ML::LinearAlgebra; + +int Matrix4x4Tests() { + + TEST("Mat4x4::Add_Unary", [] + { + Matrix4x4 m(1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16); + Matrix4x4 m2 = +m; + jtest::check(m.Equals(m2)); + }); + + TEST("Mat4x4::Inverse", [] { + RNG rng; + Matrix4x4 A = Matrix4x4::RandomGeneral(rng, -10.f, 10.f); + bool mayFail = Math::EqualAbs(A.Determinant(), 0.f, 1e-2f); + + Matrix4x4 A2 = A; + bool success = A2.Inverse(); + + jtest::check(success || mayFail); + + if (success) + { + Matrix4x4 id = A * A2; + Matrix4x4 id2 = A2 * A; + + jtest::check(id.Equals(Matrix4x4::Identity, 0.3f)); + jtest::check(id2.Equals(Matrix4x4::Identity, 0.3f)); + } + }); + + TEST("Mat4x4::Ctor", []{ + RNG rng; + Matrix3x3 m = Matrix3x3::RandomGeneral(rng, -10.f, 10.f); + + Matrix4x4 m2(m); + + for (int y = 0; y < 3; ++y) + for (int x = 0; x < 3; ++x) + assert(Math::EqualAbs(m.At(y, x), m2.At(y, x))); + + jtest::check(Math::EqualAbs(m2[0][3], 0.f)); + jtest::check(Math::EqualAbs(m2[1][3], 0.f)); + jtest::check(Math::EqualAbs(m2[2][3], 0.f)); + + jtest::check(Math::EqualAbs(m2[3][0], 0.f)); + jtest::check(Math::EqualAbs(m2[3][1], 0.f)); + jtest::check(Math::EqualAbs(m2[3][2], 0.f)); + jtest::check(Math::EqualAbs(m2[3][3], 0.f)); + }); + + TEST("Mat4x4::SetRow", [] + { + Matrix4x4 m; + m.SetRow(0, 1,2,3,4); + m.SetRow(1, Vector4(5,6,7,8)); + m.SetRow(2, 9,10,11,12); + m.SetRow(3, 13, 14, 15, 16); + + + Matrix4x4 m3(1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16); + Matrix4x4 m2; + m2.Set(1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16); + jtest::check(m.Equals(m2)); + jtest::check(m.Equals(m3)); + }); + + TEST("Mat4x4::SwapRows", [] + { + Matrix4x4 m(1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16); + Matrix4x4 m2(13,14,15,16, 9,10,11,12, 5,6,7,8, 1,2,3,4); + m.SwapRows(0,3); + m.SwapRows(1,2); + jtest::check(m.Equals(m2)); + }); + + TEST("Mat4x4::CtorCols", [] + { + Matrix4x4 m(Vector4(1,2,3,4), Vector4(5,6,7,8), Vector4(9,10,11,12), Vector4(13,14,15,16)); + Matrix4x4 m2(1,5,9,13, 2,6,10,14, 3,7,11,15, 4,8,12,16); + jtest::check(m.Equals(m2)); + }); + + TEST("Mat4x4::CtorFromQuat", [] + { + RNG rng; + // TODO: Multiple random passes + Quaternion q = Quaternion::RandomRotation(rng); + Matrix4x4 m(q); + + Vector3 v = Vector3(-1, 5, 20.f); + Vector3 v1 = q * v; + Vector3 v2 = m.Transform(v); //m.TransformPos(v); + jtest::check(v1.Equals(v2)); + }); + + + TEST("Mat4x4::CtorFromQuatTrans", [] {}); + TEST("Mat4x4::Translate", [] {}); + TEST("Mat4x4::Scale", [] {}); + TEST("Mat4x4::InverseOrthogonalUniformScale", [] {}); + TEST("Mat4x4::InverseOrthonormal", [] {}); + TEST("Mat4x4::DeterminantCorrectness", [] { }); + TEST("Mat4x4::MulMat3x3", [] {}); + + return 0; +} + + + + + + + + + + + + + + + + + + diff --git a/tests/LinearAlgebra/QuaternionTests.hpp b/tests/LinearAlgebra/QuaternionTests.hpp new file mode 100644 index 0000000..0b8a4d1 --- /dev/null +++ b/tests/LinearAlgebra/QuaternionTests.hpp @@ -0,0 +1,75 @@ + +#include + +using namespace J3ML::LinearAlgebra; + +Quaternion PreciseSlerp(const Quaternion &a, const Quaternion& b, float t) +{ + double angle = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + + double sign = 1.0; + + if (angle > 0) { + angle = -angle; + sign = -1.0; + } + double A; + double B; + + if (angle <= 1.0) // perform spherical linear interpolation + { + angle = std::acos(angle); // After this, angle is in the range pi / 2 -> 0 as the original angle variable ranged from 0 -> 1. + + double angleT = t * angle; + + double s[3] = { std::sin(angle), std::sin(angle - angleT), std::sin(angleT)}; + double c = 1.0 / s[0]; + + A = s[1] * c; + B = s[2] * c; + } else { // If angle is close to taking the denominator to zero, resort to linear interpolation (and normalization). + A = 1.0 - t; + B = t; + } + + Quaternion C; + C.x = (float)(a.x*A*sign + b.x*B); + C.y = (float)(a.y*A*sign + b.y*B); + C.z = (float)(a.z*A*sign + b.z*B); + C.w = (float)(a.w*A*sign + b.w*B); + return C.Normalized(); +} + + +int QuaternionTests() +{ + + TEST("Quat::SlerpPrecision", [] { + RNG rng; + float maxError = 0; + float maxLerpError = 0; + float magnitudeError = 0; + for (int i = 0; i < 10000; ++i) + { + Quaternion q = Quaternion::RandomRotation(rng); + Quaternion q2 = Quaternion::RandomRotation(rng); + float t = rng.Float01Incl(); + + Quaternion correct = PreciseSlerp(q, q2, t); + Quaternion fast = q.Slerp(q2, t); + magnitudeError = std::max(magnitudeError, std::abs(1.f - fast.LengthSquared())); + Quaternion lerp = q.Lerp(q2, t); + } + }); + TEST("Quat::Mat4x4Conversion", [] {}); + TEST("Quat::MulOpQuat", [] {}); + TEST("Quat::DivOpQuat", [] {}); + TEST("Quat::Lerp", [] {}); + TEST("Quat::RotateFromTo", [] {}); + TEST("Quat::Transform", [] {}); + + return 0; +} + + + diff --git a/tests/LinearAlgebra/Vector2Tests.cpp b/tests/LinearAlgebra/Vector2Tests.cpp deleted file mode 100644 index 2da3fb1..0000000 --- a/tests/LinearAlgebra/Vector2Tests.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include -#include - -using J3ML::LinearAlgebra::Vector2; - -TEST(Vector2Test, V2_Constructor_Default) -{ - EXPECT_EQ(Vector2(), Vector2::Zero); -} - -TEST(Vector2Test, V2_Constructor_XY) -{ - Vector2 vec {1, 0}; - EXPECT_EQ(vec, Vector2::Right); -} - -TEST(Vector2Test, V2_Addition_Op) -{ - Vector2 A {1,1}; - Vector2 B {2,2}; - - Vector2 C {3, 3}; - - EXPECT_EQ(A+B, C); -} - -TEST(Vector2Test, V2_Addition_Method) -{ - Vector2 A {2,2}; - Vector2 B {2,2}; - - Vector2 C {4, 4}; - - EXPECT_EQ(A.Add(B), C); -} - -TEST(Vector2Test, V2_Addition_Static) -{ - Vector2 A {3, 3}; - Vector2 B {2, 2}; - - Vector2 C {5, 5}; - - EXPECT_EQ(Vector2::Add(A, B), C); -} - -TEST(Vector2Test, V2_Subtract_Op) -{ - Vector2 A {1,1}; - Vector2 B {2,2}; - - Vector2 C {-1, -1}; - - EXPECT_EQ(A-B, C); -} - -TEST(Vector2Test, V2_Subtract_Method) -{ - Vector2 A {1,1}; - Vector2 B {2,2}; - - Vector2 C {-1, -1}; - - EXPECT_EQ(A.Sub(B), C); -} - -TEST(Vector2Test, V2_Subtract_Static) -{ - Vector2 A {1,1}; - Vector2 B {2,2}; - - Vector2 C {-1, -1}; - - EXPECT_EQ(Vector2::Sub(A, B), C); -} - -TEST(Vector2Test, V2_Scalar_Multiplication) -{ - Vector2 A {5, 1}; - float B = 0.5f; - Vector2 C = {2.5f, .5f}; - EXPECT_EQ(A*B, C); -} - -TEST(Vector2Test, V2_Size) -{ - EXPECT_EQ(sizeof(Vector2), 8); -} - -TEST(Vector2Test, V2_NaN) -{ - - EXPECT_NE(Vector2::Zero, Vector2::NaN); - EXPECT_NE(Vector2::Up, Vector2::NaN); - EXPECT_NE(Vector2::Left, Vector2::NaN); - EXPECT_NE(Vector2::Down, Vector2::NaN); - EXPECT_NE(Vector2::Right, Vector2::NaN); - EXPECT_NE(Vector2::NaN, Vector2::NaN); -} - -TEST(Vector2Test, V2_MarginOfError) -{ - Vector2 A {2,2}; - Vector2 B {1.85, 1.85}; - - EXPECT_TRUE(A.IsWithinMarginOfError(B, 0.5f)); -} - -TEST(Vector2Test, V2_Min) -{ - Vector2 A {2,2}; - Vector2 B {1.85, 1.85}; - - EXPECT_EQ( Vector2::Min(A, B), B); -} - -TEST(Vector2Test, V2_Max) -{ - Vector2 A {2,2}; - Vector2 B {1.85, 1.85}; - - EXPECT_EQ( Vector2::Max(A, B), A); -} - -TEST(Vector2Test, V2_Clamp) -{ - Vector2 Input{0, 20}; - - Vector2 Minimum { 2, 2}; - Vector2 Maximum {16, 16}; - - Vector2 ExpectedResult {2, 16}; - - EXPECT_EQ(Input.Clamp(Minimum, Maximum), ExpectedResult); -} - -TEST(Vector2Test, V2_DotProduct) -{ - // TODO: Equality - Vector2 A {2, 2}; - Vector2 B {1, 1}; - EXPECT_FLOAT_EQ(A.Dot(B), 4.f); -} - -TEST(Vector2Test, V2_Project) -{ - Vector2 Base {4, 4}; - Vector2 Projected {1, 0}; - - Vector2 ExpectedResult {4, 0}; - - EXPECT_EQ(Base.Project(Projected), ExpectedResult); -} - -TEST(Vector2Test, V2_Normalize) -{ - Vector2 A{2, 0}; - Vector2 B{1, 0}; - EXPECT_EQ(A.Normalized(), B); -} - -TEST(Vector2Test, V2_Lerp) -{ - Vector2 A {2,2}; - Vector2 B {10, 10}; - Vector2 C {6, 6}; - - EXPECT_EQ(A.Lerp(B, 0.f), A); - EXPECT_EQ(A.Lerp(B, 1.f), B); - EXPECT_EQ(A.Lerp(B, 0.5f), C); -} - -TEST(Vector2Test, V2_AngleBetween) -{ - Vector2 A {0.5f, 0.5}; - Vector2 B {0.5f, 0.1f}; - - A = A.Normalized(); - B = B.Normalized(); - - // TODO: AngleBetween returns not a number - EXPECT_FLOAT_EQ(A.AngleBetween(B), 0.58800244); -} \ No newline at end of file diff --git a/tests/LinearAlgebra/Vector2Tests.hpp b/tests/LinearAlgebra/Vector2Tests.hpp new file mode 100644 index 0000000..c443bfa --- /dev/null +++ b/tests/LinearAlgebra/Vector2Tests.hpp @@ -0,0 +1,191 @@ + +#include + +using J3ML::LinearAlgebra::Vector2; + +int Vector2Tests() +{ + TEST("Vector2::Ctor_Default", [] + { + // TODO: implement check_eq + jtest::check(Vector2() == Vector2::Zero); + }); + + TEST("Vector2::Ctor_XY", [] + { + Vector2 vec (1, 0); + // TODO: implement check_eq + jtest::check(vec == Vector2::Right); + }); + + TEST("Vector2::Addition_Op", [] + { + Vector2 A (1,1); + Vector2 B (2,2); + + Vector2 C (3, 3); + // TODO: implement check_eq + jtest::check(A+B == C); + }); + + TEST("Vector2::Addition_Method", [] + { + Vector2 A (2,2); + Vector2 B (2,2); + + Vector2 C (4, 4); + // TODO: implement check_eq + jtest::check(A.Add(B) == C); + }); + + TEST("Vector2::Addition_Static", [] + { + Vector2 A (3, 3); + Vector2 B (2, 2); + + Vector2 C (5, 5); + // TODO: implement check_eq + jtest::check(Vector2::Add(A, B) == C); + }); + + TEST("Vector2::Subtract_Op", [] + { + Vector2 A (1,1); + Vector2 B (2,2); + + Vector2 C (-1, -1); + + jtest::check(A-B == C); + }); + + TEST("Vector2::Subtract_Method", [] + { + Vector2 A (1,1); + Vector2 B (2,2); + + Vector2 C (-1, -1); + + jtest::check(A.Sub(B) == C); + }); + + TEST("Vector2::Subtract_Static", [] + { + Vector2 A (1,1); + Vector2 B (2,2); + + Vector2 C (-1, -1); + + jtest::check(Vector2::Sub(A, B) == C); + }); + + TEST("Vector2::Scalar_Multiplication", [] + { + Vector2 A (5, 1); + float B = 0.5f; + Vector2 C (2.5f, .5f); + jtest::check(A*B == C); + }); + + TEST("Vector2::Size", [] + { + jtest::check(sizeof(Vector2) == 8); + }); + + TEST("Vector2::NaN", [] + { + + jtest::check(Vector2::Zero != Vector2::NaN); + jtest::check(Vector2::Up != Vector2::NaN); + jtest::check(Vector2::Left != Vector2::NaN); + jtest::check(Vector2::Down != Vector2::NaN); + jtest::check(Vector2::Right != Vector2::NaN); + jtest::check(Vector2::NaN != Vector2::NaN); + }); + + TEST("Vector2::MarginOfError", [] + { + Vector2 A (2,2); + Vector2 B (1.85, 1.85); + + jtest::check(A.IsWithinMarginOfError(B, 0.5f)); + }); + + TEST("Vector2::Min", [] + { + Vector2 A (2,2); + Vector2 B (1.85, 1.85); + + jtest::check( Vector2::Min(A, B) == B); + }); + + TEST("Vector2::Max", [] + { + Vector2 A (2,2); + Vector2 B (1.85, 1.85); + + jtest::check( Vector2::Max(A, B) == A); + }); + + TEST("Vector2::Clamp", [] + { + Vector2 Input (0, 20); + + Vector2 Minimum ( 2, 2); + Vector2 Maximum (16, 16); + + Vector2 ExpectedResult (2, 16); + + jtest::check(Input.Clamp(Minimum, Maximum) == ExpectedResult); + }); + + TEST("Vector2::DotProduct", [] + { + + Vector2 A (2, 2); + Vector2 B (1, 1); + jtest::check(A.Dot(B) == 4.f); + }); + + TEST("Vector2::Project", [] + { + Vector2 Base (4, 4); + Vector2 Projected (1, 0); + + Vector2 ExpectedResult (4, 0); + + jtest::check(Base.Project(Projected) == ExpectedResult); + }); + + TEST("Vector2::Normalize", [] + { + Vector2 A(2, 0); + Vector2 B(1, 0); + jtest::check(A.Normalized() == B); + }); + + TEST("Vector2::Lerp", [] + { + Vector2 A (2,2); + Vector2 B (10, 10); + Vector2 C (6, 6); + + jtest::check(A.Lerp(B, 0.f) == A); + jtest::check(A.Lerp(B, 1.f) == B); + jtest::check(A.Lerp(B, 0.5f) == C); + }); + + TEST("Vector2::AngleBetween", [] + { + Vector2 A (0.5f, 0.5); + Vector2 B (0.5f, 0.1f); + + A = A.Normalized(); + B = B.Normalized(); + + // TODO: AngleBetween returns not a number + // TODO: implement jtest::check_float_eq + jtest::check(A.AngleBetween(B) == 0.58800244); + }); + + return 0; +} diff --git a/tests/LinearAlgebra/Vector3Tests.cpp b/tests/LinearAlgebra/Vector3Tests.cpp deleted file mode 100644 index 2b3fd4d..0000000 --- a/tests/LinearAlgebra/Vector3Tests.cpp +++ /dev/null @@ -1,198 +0,0 @@ -#include -#include - -using J3ML::LinearAlgebra::Vector3; - -void EXPECT_V3_EQ(const Vector3& lhs, const Vector3& rhs) -{ - EXPECT_FLOAT_EQ(lhs.x, rhs.x); - EXPECT_FLOAT_EQ(lhs.y, rhs.y); - EXPECT_FLOAT_EQ(lhs.z, rhs.z); -} - -TEST(Vector3Test, V3_Constructor_Default) -{ - EXPECT_V3_EQ(Vector3(), Vector3::Zero); -} - -TEST(Vector3Test, V3_Constructor_XYZ) -{ - Vector3 Input {0, 1, 0}; - - EXPECT_V3_EQ(Input, Vector3::Down); -} - -TEST(Vector3Test, V3_Addition_Op) { - Vector3 A {1,1,1}; - Vector3 B {2,2,2}; - - Vector3 ExpectedResult {3,3,3}; - - EXPECT_V3_EQ(A + B, ExpectedResult); -} -TEST(Vector3Test, V3_Addition_Method) { - Vector3 A {1,1,1}; - Vector3 B {2,2,2}; - - Vector3 ExpectedResult {3,3,3}; - - EXPECT_V3_EQ(A.Add(B), ExpectedResult); -} -TEST(Vector3Test, V3_Addition_Static) { - Vector3 A {1,1,1}; - Vector3 B {3,3,3}; - - Vector3 ExpectedResult {4,4,4}; - - EXPECT_V3_EQ(Vector3::Add(A, B), ExpectedResult); -} -TEST(Vector3Test, V3_Subtract_Op) { - Vector3 A {2,2,2}; - Vector3 B {.5f, .5f, .5f}; - - Vector3 ExpectedResult {1.5f, 1.5f, 1.5f}; - - EXPECT_V3_EQ(A - B, ExpectedResult); -} -TEST(Vector3Test, V3_Subtract_Method) { - Vector3 A {3,3,3}; - Vector3 B {1,1,1}; - - Vector3 ExpectedResult {2,2,2}; - - EXPECT_V3_EQ(A.Sub(B), ExpectedResult); -} -TEST(Vector3Test, V3_Subtract_Static) { - Vector3 A {4,4,4}; - Vector3 B {1,1,1}; - - Vector3 ExpectedResult {3,3,3}; - - EXPECT_V3_EQ(Vector3::Sub(A, B), ExpectedResult); -} -TEST(Vector3Test, V3_Scalar_Mult_Op) { - Vector3 A { 1,1,1}; - float B = 1.5f; - - Vector3 ExpectedResult {1.5f, 1.5f, 1.5f}; - - EXPECT_V3_EQ(A * B, ExpectedResult); -} -TEST(Vector3Test, V3_Scalar_Mult_Method) { - Vector3 A {3,3,3}; - float B = 1.5f; - - Vector3 ExpectedResult {4.5f, 4.5f, 4.5f}; - - EXPECT_V3_EQ(A.Mul(B), ExpectedResult); -} -TEST(Vector3Test, V3_Scalar_Mult_Static) { - Vector3 A {2,2,2}; - float B = 1.5f; - - Vector3 ExpectedResult {3.f, 3.f, 3.f}; - - EXPECT_V3_EQ(Vector3::Mul(A, B), ExpectedResult); -} -TEST(Vector3Test, V3_Scalar_Div_Op) { - Vector3 A {4,4,4}; - float B = 2.f; - - Vector3 ExpectedResult {2,2,2}; - EXPECT_V3_EQ(A / B, ExpectedResult); -} -TEST(Vector3Test, V3_Scalar_Div_Method) { - Vector3 A {6,6,6}; - float B = 2.f; - Vector3 ExpectedResult { 3,3,3}; - - EXPECT_V3_EQ(A.Div(B), ExpectedResult); -} -TEST(Vector3Test, V3_Scalar_Div_Static) { - Vector3 A {3,3,3}; - float B = 1.5f; - - Vector3 ExpectedResult { 2.f, 2.f, 2.f}; - - EXPECT_V3_EQ(Vector3::Div(A, B), ExpectedResult); -} -TEST(Vector3Test, V3_Sizeof) { - EXPECT_EQ(sizeof(Vector3), 12); -} -TEST(Vector3Test, V3_NaN) { - EXPECT_NE(Vector3(0, 0, 0), Vector3::NaN); - -} -TEST(Vector3Test, V3_Min) { - Vector3 Input {2,2,2}; - Vector3 Minimum {3,3,3}; - Vector3 ExpectedResult {2,2,2}; - - EXPECT_V3_EQ(Input.Min(Minimum), ExpectedResult); -} -TEST(Vector3Test, V3_Max) { - Vector3 Input {2,2,2}; - Vector3 Maximum {3,3,3}; - Vector3 ExpectedResult {3,3,3}; - - EXPECT_V3_EQ(Input.Max(Maximum), ExpectedResult); -} -TEST(Vector3Test, V3_Clamp) { - Vector3 Input {5,-1,8}; - Vector3 Minimum {1,1,1}; - Vector3 Maximum {5,5,5}; - - Vector3 ExpectedResult {5,1,5}; - - EXPECT_V3_EQ(Input.Clamp(Minimum, Maximum), ExpectedResult); - -} -TEST(Vector3Test, V3_DotProduct) { - Vector3 A{6,6,6}; - Vector3 B{1,1,1}; - - - float ExpectedResult = 18; - - EXPECT_FLOAT_EQ(A.Dot(B), ExpectedResult); -} -TEST(Vector3Test, V3_CrossProduct) { - Vector3 A{1,1,1}; - Vector3 B{2,2,2}; - - Vector3 ExpectedResult {0,0,0}; - - EXPECT_V3_EQ(A.Cross(B), ExpectedResult); - -} -TEST(Vector3Test, V3_Project) { - Vector3 Base {}; - Vector3 Projection {}; - Vector3 ExpectedResult {}; -} -TEST(Vector3Test, V3_Normalize) { - Vector3 Input {2, 0, 0}; - Vector3 ExpectedResult {1, 0, 0}; - - EXPECT_V3_EQ(Input.Normalized(), ExpectedResult); -} -TEST(Vector3Test, V3_Lerp) -{ - Vector3 Start {}; - Vector3 Finish {}; - float Percent = 50; - Vector3 ExpectedResult {}; - EXPECT_V3_EQ(Start.Lerp(Finish, Percent), ExpectedResult); -} -TEST(Vector3Test, V3_AngleBetween) { - using J3ML::LinearAlgebra::Angle2D; - Vector3 A{ .5f, .5f, .5f}; - Vector3 B {.25f, .75f, .25f}; - A = A.Normalized(); - B = B.Normalized(); - Angle2D ExpectedResult {-0.69791365, -2.3561945}; - std::cout << A.AngleBetween(B).x << ", " << A.AngleBetween(B).y << ""; - auto angle = A.AngleBetween(B); - EXPECT_FLOAT_EQ(angle.x, ExpectedResult.x); - EXPECT_FLOAT_EQ(angle.y, ExpectedResult.y); -} diff --git a/tests/LinearAlgebra/Vector3Tests.hpp b/tests/LinearAlgebra/Vector3Tests.hpp new file mode 100644 index 0000000..eba3d2b --- /dev/null +++ b/tests/LinearAlgebra/Vector3Tests.hpp @@ -0,0 +1,208 @@ + +#include + +using J3ML::LinearAlgebra::Vector3; + +inline void EXPECT_V3_EQ(const Vector3& lhs, const Vector3& rhs) +{ + jtest::check(lhs.x == rhs.x); + jtest::check(lhs.y == rhs.y); + jtest::check(lhs.z == rhs.z); +} + +int Vector3Tests() { + TEST("Vector3::Ctor_Default", [] + { + EXPECT_V3_EQ(Vector3(), Vector3::Zero); + }); + + TEST("Vector3::Ctor_XYZ", [] + { + Vector3 Input (0, 1, 0); + + EXPECT_V3_EQ(Input, Vector3::Down); + }); + + TEST("Vector3::Addition_Op", [] { + Vector3 A (1,1,1); + Vector3 B (2,2,2); + + Vector3 ExpectedResult (3,3,3); + + EXPECT_V3_EQ(A + B, ExpectedResult); + }); + + TEST("Vector3::Addition_Method", [] { + Vector3 A (1,1,1); + Vector3 B (2,2,2); + + Vector3 ExpectedResult (3,3,3); + + EXPECT_V3_EQ(A.Add(B), ExpectedResult); + }); + TEST("Vector3::Addition_Static", [] { + Vector3 A (1,1,1); + Vector3 B (3,3,3); + + Vector3 ExpectedResult (4,4,4); + + EXPECT_V3_EQ(Vector3::Add(A, B), ExpectedResult); + }); + TEST("Vector3::Subtract_Op", [] { + Vector3 A (2,2,2); + Vector3 B (.5f, .5f, .5f); + + Vector3 ExpectedResult (1.5f, 1.5f, 1.5f); + + EXPECT_V3_EQ(A - B, ExpectedResult); + }); + TEST("Vector3::Subtract_Method", [] { + Vector3 A (3,3,3); + Vector3 B (1,1,1); + + Vector3 ExpectedResult (2,2,2); + + EXPECT_V3_EQ(A.Sub(B), ExpectedResult); + }); + TEST("Vector3Test, V3_Subtract_Static", [] { + Vector3 A (4,4,4); + Vector3 B (1,1,1); + + Vector3 ExpectedResult (3,3,3); + + EXPECT_V3_EQ(Vector3::Sub(A, B), ExpectedResult); + }); + TEST("Vector3::Scalar_Mult_Op", [] { + Vector3 A ( 1,1,1); + float B = 1.5f; + + Vector3 ExpectedResult (1.5f, 1.5f, 1.5f); + + EXPECT_V3_EQ(A * B, ExpectedResult); + }); + TEST("Vector3::Scalar_Mult_Method", [] { + Vector3 A (3,3,3); + float B = 1.5f; + + Vector3 ExpectedResult (4.5f, 4.5f, 4.5f); + + EXPECT_V3_EQ(A.Mul(B), ExpectedResult); + }); + TEST("Vector3::Scalar_Mult_Static", [] { + Vector3 A (2,2,2); + float B = 1.5f; + + Vector3 ExpectedResult (3.f, 3.f, 3.f); + + EXPECT_V3_EQ(Vector3::Mul(A, B), ExpectedResult); + }); + TEST("Vector3::Scalar_Div_Op", [] { + Vector3 A (4,4,4); + float B = 2.f; + + Vector3 ExpectedResult (2,2,2); + EXPECT_V3_EQ(A / B, ExpectedResult); + }); + TEST("Vector3::Scalar_Div_Method", [] { + Vector3 A (6,6,6); + float B = 2.f; + Vector3 ExpectedResult ( 3,3,3); + + EXPECT_V3_EQ(A.Div(B), ExpectedResult); + }); + TEST("Vector3::Scalar_Div_Static", [] { + Vector3 A (3,3,3); + float B = 1.5f; + + Vector3 ExpectedResult ( 2.f, 2.f, 2.f); + + EXPECT_V3_EQ(Vector3::Div(A, B), ExpectedResult); + }); + TEST("Vector3::Sizeof", [] { + jtest::check(sizeof(Vector3) == 12); + }); + TEST("Vector3::NaN", [] { + jtest::check(Vector3(0, 0, 0) != Vector3::NaN); + + }); + TEST("Vector3::Min", [] { + Vector3 Input (2,2,2); + Vector3 Minimum (3,3,3); + Vector3 ExpectedResult (2,2,2); + + EXPECT_V3_EQ(Input.Min(Minimum), ExpectedResult); + }); + TEST("Vector3::Max", [] { + Vector3 Input (2,2,2); + Vector3 Maximum (3,3,3); + Vector3 ExpectedResult (3,3,3); + + EXPECT_V3_EQ(Input.Max(Maximum), ExpectedResult); + }); + TEST("Vector3::Clamp", [] { + Vector3 Input (5,-1,8); + Vector3 Minimum (1,1,1); + Vector3 Maximum (5,5,5); + + Vector3 ExpectedResult (5,1,5); + + EXPECT_V3_EQ(Input.Clamp(Minimum, Maximum), ExpectedResult); + + }); + TEST("Vector3::DotProduct", [] { + Vector3 A(6,6,6); + Vector3 B(1,1,1); + + + float ExpectedResult = 18; + + // TODO: Add check_float_eq + jtest::check(A.Dot(B) == ExpectedResult); + }); + TEST("Vector3::CrossProduct", [] { + Vector3 A(1,1,1); + Vector3 B(2,2,2); + + Vector3 ExpectedResult (0,0,0); + + EXPECT_V3_EQ(A.Cross(B), ExpectedResult); + + }); + TEST("Vector3::Project", [] { + Vector3 Base; + Vector3 Projection; + Vector3 ExpectedResult; + }); + TEST("Vector3::Normalize", [] { + Vector3 Input (2, 0, 0); + Vector3 ExpectedResult (1, 0, 0); + + EXPECT_V3_EQ(Input.Normalized(), ExpectedResult); + }); + TEST("Vector3::Lerp", [] + { + Vector3 Start; + Vector3 Finish; + float Percent = 50; + Vector3 ExpectedResult; + EXPECT_V3_EQ(Start.Lerp(Finish, Percent), ExpectedResult); + }); + TEST("Vector3::AngleBetween", [] { + using J3ML::LinearAlgebra::Angle2D; + Vector3 A ( .5f, .5f, .5f); + Vector3 B (.25f, .75f, .25f); + A = A.Normalized(); + B = B.Normalized(); + Angle2D ExpectedResult (-0.69791365, -2.3561945); + //std::cout << A.AngleBetween(B).x << ", " << A.AngleBetween(B).y << ""; + auto angle = A.AngleBetween(B); + + jtest::check(angle.x == ExpectedResult.x); + jtest::check(angle.y == ExpectedResult.y); + }); + return 0; +} + + + + diff --git a/tests/LinearAlgebra/Vector4Tests.cpp b/tests/LinearAlgebra/Vector4Tests.cpp deleted file mode 100644 index a87c752..0000000 --- a/tests/LinearAlgebra/Vector4Tests.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include - -using Vector4 = J3ML::LinearAlgebra::Vector4; - - -void EXPECT_V4_EQ(const Vector4& lhs, const Vector4& rhs) -{ - -} - -TEST(Vector4Test, V4_Constructor_Default) -{ - EXPECT_V4_EQ(Vector4(), Vector4::Zero); -} - -TEST(Vector4Test, V4_Constructor_XYZW) -{ - Vector4 Input {0, 1, 0, 1}; - EXPECT_FLOAT_EQ(Input.x, 0); - EXPECT_FLOAT_EQ(Input.y, 1); - EXPECT_FLOAT_EQ(Input.z, 0); - EXPECT_FLOAT_EQ(Input.w, 1); -} - -TEST(Vector4Test, V4_Addition_Op) { - Vector4 A {1, 1, 1, 1}; - Vector4 B {2, 2, 2, 2}; - - Vector4 ExpectedResult {3, 3, 3, 3}; - - EXPECT_V4_EQ(A + B, ExpectedResult); -} - -TEST(Vector4Test, V4_Addition_Method) -{ - -} - -TEST(Vector4Test, V4_Addition_Static) -{ - -} - -TEST(Vector4Test, V4_Subtract_Op) -{ - -} - -TEST(Vector4Test, V4_Subtract_Method) -{ - -} - -TEST(Vector4Test, V4_Subtract_Static) -{ - -} - -TEST(Vector4Test, V4_Scalar_Mult_Op) -{ - -} - -TEST(Vector4Test, V4_Scalar_Mult_Method) -{ - -} - -TEST(Vector4Test, V4_Scalar_Mult_Static) -{ - -} - -TEST(Vector4Test, V4_Scalar_Div_Op) -{ - -} - -TEST(Vector4Test, V4_Scalar_Div_Method) -{ - -} - -TEST(Vector4Test, V4_Scalar_Div_Static) -{ - -} - -TEST(Vector4Test, V4_Sizeof) -{ - -} - -TEST(Vector4Test, V4_NaN) -{ - -} - -TEST(Vector4Tests, V4_Min) {} -TEST(Vector4Tests, V4_Max) {} -TEST(Vector4Tests, V4_Clamp) {} -TEST(Vector4Tests, V4_DotProduct) {} -TEST(Vector4Tests, V4_CrossProduct) {} -TEST(Vector4Tests, V4_Project) {} -TEST(Vector4Test, V4_Normalize) {} \ No newline at end of file diff --git a/tests/LinearAlgebra/Vector4Tests.hpp b/tests/LinearAlgebra/Vector4Tests.hpp new file mode 100644 index 0000000..2375081 --- /dev/null +++ b/tests/LinearAlgebra/Vector4Tests.hpp @@ -0,0 +1,116 @@ + +#include + +using Vector4 = J3ML::LinearAlgebra::Vector4; + +void EXPECT_V4_EQ(const Vector4& lhs, const Vector4& rhs) +{ + jtest::check(lhs.x == rhs.x); + jtest::check(lhs.y == rhs.y); + jtest::check(lhs.z == rhs.z); + jtest::check(lhs.w == rhs.w); +} + +int Vector4Tests() +{ + TEST("Vector4::Ctor_Default", [] + { + EXPECT_V4_EQ(Vector4(), Vector4::Zero); + }); + + TEST("Vector4::Constructor_XYZW", [] + { + Vector4 Input (0, 1, 0, 1); + // TODO: implement jtest::check_float_eq + jtest::check(Input.x == 0); + jtest::check(Input.y == 1); + jtest::check(Input.z == 0); + jtest::check(Input.w == 1); + }); + + TEST("Vector4::Addition_Op", [] { + Vector4 A (1, 1, 1, 1); + Vector4 B (2, 2, 2, 2); + + Vector4 ExpectedResult (3, 3, 3, 3); + + EXPECT_V4_EQ(A + B, ExpectedResult); + }); + + /*TEST(Vector4Test, V4_Addition_Method) + { + + } + + TEST(Vector4Test, V4_Addition_Static) + { + + } + + TEST(Vector4Test, V4_Subtract_Op) + { + + } + + TEST(Vector4Test, V4_Subtract_Method) + { + + } + + TEST(Vector4Test, V4_Subtract_Static) + { + + } + + TEST(Vector4Test, V4_Scalar_Mult_Op) + { + + } + + TEST(Vector4Test, V4_Scalar_Mult_Method) + { + + } + + TEST(Vector4Test, V4_Scalar_Mult_Static) + { + + } + + TEST(Vector4Test, V4_Scalar_Div_Op) + { + + } + + TEST(Vector4Test, V4_Scalar_Div_Method) + { + + } + + TEST(Vector4Test, V4_Scalar_Div_Static) + { + + } + + TEST(Vector4Test, V4_Sizeof) + { + + } + + TEST(Vector4Test, V4_NaN) + { + + } + + TEST(Vector4Tests, V4_Min) {} + TEST(Vector4Tests, V4_Max) {} + TEST(Vector4Tests, V4_Clamp) {} + TEST(Vector4Tests, V4_DotProduct) {} + TEST(Vector4Tests, V4_CrossProduct) {} + TEST(Vector4Tests, V4_Project) {} + TEST(Vector4Test, V4_Normalize) {}*/ + return 0; +} + + +