refactored tests

This commit is contained in:
2024-11-27 19:36:28 +03:00
parent 480d11dbc0
commit 6a9a51b39c
19 changed files with 55 additions and 26 deletions

View File

@@ -0,0 +1,17 @@
//
// Created by Vlad on 18.08.2024.
//
#include <gtest/gtest.h>
#include <omath/pathfinding/Astar.hpp>
TEST(UnitTestAstar, FindingRightPath)
{
omath::pathfinding::NavigationMesh mesh;
mesh.m_verTextMap[{0.f, 0.f, 0.f}] = {{0.f, 1.f, 0.f}};
mesh.m_verTextMap[{0.f, 1.f, 0.f}] = {{0.f, 2.f, 0.f}};
mesh.m_verTextMap[{0.f, 2.f, 0.f}] = {{0.f, 3.f, 0.f}};
mesh.m_verTextMap[{0.f, 3.f, 0.f}] = {};
std::ignore = omath::pathfinding::Astar::FindPath({}, {0.f, 3.f, 0.f}, mesh);
}

View File

@@ -0,0 +1,113 @@
//
// Created by Vlad on 01.09.2024.
//
#include <gtest/gtest.h>
#include <omath/Color.hpp>
using namespace omath;
class UnitTestColor : public ::testing::Test
{
protected:
Color color1;
Color color2;
void SetUp() override
{
color1 = Color::Red();
color2 = Color::Green();
}
};
// Test constructors
TEST_F(UnitTestColor, Constructor_Float)
{
constexpr Color color(0.5f, 0.5f, 0.5f, 1.0f);
EXPECT_FLOAT_EQ(color.x, 0.5f);
EXPECT_FLOAT_EQ(color.y, 0.5f);
EXPECT_FLOAT_EQ(color.z, 0.5f);
EXPECT_FLOAT_EQ(color.w, 1.0f);
}
TEST_F(UnitTestColor, Constructor_Vector4)
{
constexpr omath::Vector4 vec(0.2f, 0.4f, 0.6f, 0.8f);
Color color(vec);
EXPECT_FLOAT_EQ(color.x, 0.2f);
EXPECT_FLOAT_EQ(color.y, 0.4f);
EXPECT_FLOAT_EQ(color.z, 0.6f);
EXPECT_FLOAT_EQ(color.w, 0.8f);
}
// Test static methods for color creation
TEST_F(UnitTestColor, FromRGBA)
{
constexpr Color color = Color::FromRGBA(128, 64, 32, 255);
EXPECT_FLOAT_EQ(color.x, 128.0f / 255.0f);
EXPECT_FLOAT_EQ(color.y, 64.0f / 255.0f);
EXPECT_FLOAT_EQ(color.z, 32.0f / 255.0f);
EXPECT_FLOAT_EQ(color.w, 1.0f);
}
TEST_F(UnitTestColor, FromHSV)
{
constexpr Color color = Color::FromHSV(0.0f, 1.0f, 1.0f); // Red in HSV
EXPECT_FLOAT_EQ(color.x, 1.0f);
EXPECT_FLOAT_EQ(color.y, 0.0f);
EXPECT_FLOAT_EQ(color.z, 0.0f);
EXPECT_FLOAT_EQ(color.w, 1.0f);
}
// Test HSV conversion
TEST_F(UnitTestColor, ToHSV)
{
HSV hsv = color1.ToHSV(); // Red color
EXPECT_FLOAT_EQ(hsv.m_hue, 0.0f);
EXPECT_FLOAT_EQ(hsv.m_saturation, 1.0f);
EXPECT_FLOAT_EQ(hsv.m_value, 1.0f);
}
// Test color blending
TEST_F(UnitTestColor, Blend)
{
Color blended = color1.Blend(color2, 0.5f);
EXPECT_FLOAT_EQ(blended.x, 0.5f);
EXPECT_FLOAT_EQ(blended.y, 0.5f);
EXPECT_FLOAT_EQ(blended.z, 0.0f);
EXPECT_FLOAT_EQ(blended.w, 1.0f);
}
// Test predefined colors
TEST_F(UnitTestColor, PredefinedColors)
{
constexpr Color red = Color::Red();
constexpr Color green = Color::Green();
constexpr Color blue = Color::Blue();
EXPECT_FLOAT_EQ(red.x, 1.0f);
EXPECT_FLOAT_EQ(red.y, 0.0f);
EXPECT_FLOAT_EQ(red.z, 0.0f);
EXPECT_FLOAT_EQ(red.w, 1.0f);
EXPECT_FLOAT_EQ(green.x, 0.0f);
EXPECT_FLOAT_EQ(green.y, 1.0f);
EXPECT_FLOAT_EQ(green.z, 0.0f);
EXPECT_FLOAT_EQ(green.w, 1.0f);
EXPECT_FLOAT_EQ(blue.x, 0.0f);
EXPECT_FLOAT_EQ(blue.y, 0.0f);
EXPECT_FLOAT_EQ(blue.z, 1.0f);
EXPECT_FLOAT_EQ(blue.w, 1.0f);
}
// Test non-member function: Blend for Vector3
TEST_F(UnitTestColor, BlendVector3)
{
constexpr Color v1(1.0f, 0.0f, 0.0f, 1.f); // Red
constexpr Color v2(0.0f, 1.0f, 0.0f, 1.f); // Green
constexpr Color blended = Blend(v1, v2, 0.5f);
EXPECT_FLOAT_EQ(blended.x, 0.5f);
EXPECT_FLOAT_EQ(blended.y, 0.5f);
EXPECT_FLOAT_EQ(blended.z, 0.0f);
}

View File

@@ -0,0 +1,80 @@
#include "gtest/gtest.h"
#include "omath/collision/LineTracer.hpp"
#include "omath/Triangle3d.hpp"
#include "omath/Vector3.hpp"
using namespace omath;
using namespace omath::collision;
class LineTracerTest : public ::testing::Test
{
protected:
// Set up common variables for use in each test
Vector3 vertex1{0.0f, 0.0f, 0.0f};
Vector3 vertex2{1.0f, 0.0f, 0.0f};
Vector3 vertex3{0.0f, 1.0f, 0.0f};
Triangle3d triangle{vertex1, vertex2, vertex3};
};
// Test that a ray intersecting the triangle returns false for CanTraceLine
TEST_F(LineTracerTest, RayIntersectsTriangle)
{
constexpr Ray ray{{0.3f, 0.3f, -1.0f}, {0.3f, 0.3f, 1.0f}};
EXPECT_FALSE(LineTracer::CanTraceLine(ray, triangle));
}
// Test that a ray parallel to the triangle plane returns true for CanTraceLine
TEST_F(LineTracerTest, RayParallelToTriangle)
{
constexpr Ray ray{{0.3f, 0.3f, 1.0f}, {0.3f, 0.3f, 2.0f}};
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
}
// Test that a ray starting inside the triangle but pointing away returns true
TEST_F(LineTracerTest, RayStartsInTriangleButDoesNotIntersect)
{
constexpr Ray ray{{0.3f, 0.3f, 0.0f}, {0.3f, 0.3f, -1.0f}};
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
}
// Test that a ray not intersecting the triangle plane returns true
TEST_F(LineTracerTest, RayMissesTriangle)
{
constexpr Ray ray{{2.0f, 2.0f, -1.0f}, {2.0f, 2.0f, 1.0f}};
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
}
// Test that a ray lying exactly in the plane of the triangle without intersecting returns true
TEST_F(LineTracerTest, RayInPlaneNotIntersecting)
{
constexpr Ray ray{{-1.0f, -1.0f, 0.0f}, {1.5f, 1.5f, 0.0f}};
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
}
TEST_F(LineTracerTest, RayIntersectsVertex)
{
const Ray ray{{-1.0f, -1.0f, -1.0f}, vertex1}; // Intersecting at vertex1
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
}
TEST_F(LineTracerTest, RayIntersectsEdge)
{
constexpr Ray ray{{-1.0f, 0.0f, -1.0f}, {0.5f, 0.0f, 0.0f}};
// Intersecting on the edge between vertex1 and vertex2
EXPECT_TRUE(LineTracer::CanTraceLine(ray, triangle));
}
TEST_F(LineTracerTest, TriangleFarBeyondRayEndPoint)
{
// Define a ray with a short length
constexpr Ray ray{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}};
// Define a triangle far beyond the ray's endpoint
const Triangle3d distantTriangle{
{1000.0f, 1000.0f, 1000.0f}, {1001.0f, 1000.0f, 1000.0f}, {1000.0f, 1001.0f, 1000.0f}
};
// Expect true because the ray ends long before it could reach the distant triangle
EXPECT_TRUE(LineTracer::CanTraceLine(ray, distantTriangle));
}

View File

@@ -0,0 +1,227 @@
// UnitTestMat.cpp
#include <gtest/gtest.h>
#include "omath/Mat.hpp"
#include "omath/Vector3.hpp"
using namespace omath;
class UnitTestMat : public ::testing::Test
{
protected:
Mat<2, 2> m1;
Mat<2, 2> m2;
void SetUp() override
{
m1 = Mat<2, 2>();
m2 = Mat<2, 2>{{1.0f, 2.0f}, {3.0f, 4.0f}};
}
};
// Test constructors
TEST_F(UnitTestMat, Constructor_Default)
{
Mat<3, 3> m;
EXPECT_EQ(m.RowCount(), 3);
EXPECT_EQ(m.ColumnsCount(), 3);
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 3; ++j)
EXPECT_FLOAT_EQ(m.At(i, j), 0.0f);
}
TEST_F(UnitTestMat, Constructor_InitializerList)
{
constexpr Mat<2, 2> m{{1.0f, 2.0f}, {3.0f, 4.0f}};
EXPECT_EQ(m.RowCount(), 2);
EXPECT_EQ(m.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(m.At(0, 0), 1.0f);
EXPECT_FLOAT_EQ(m.At(0, 1), 2.0f);
EXPECT_FLOAT_EQ(m.At(1, 0), 3.0f);
EXPECT_FLOAT_EQ(m.At(1, 1), 4.0f);
}
TEST_F(UnitTestMat, Constructor_Copy)
{
Mat<2, 2> m3 = m2;
EXPECT_EQ(m3.RowCount(), m2.RowCount());
EXPECT_EQ(m3.ColumnsCount(), m2.ColumnsCount());
EXPECT_FLOAT_EQ(m3.At(0, 0), m2.At(0, 0));
EXPECT_FLOAT_EQ(m3.At(1, 1), m2.At(1, 1));
}
TEST_F(UnitTestMat, Constructor_Move)
{
Mat<2, 2> m3 = std::move(m2);
EXPECT_EQ(m3.RowCount(), 2);
EXPECT_EQ(m3.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(m3.At(0, 0), 1.0f);
EXPECT_FLOAT_EQ(m3.At(1, 1), 4.0f);
// m2 is in a valid but unspecified state after move
}
// Test matrix operations
TEST_F(UnitTestMat, Operator_Multiplication_Matrix)
{
Mat<2, 2> m3 = m2 * m2;
EXPECT_EQ(m3.RowCount(), 2);
EXPECT_EQ(m3.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(m3.At(0, 0), 7.0f);
EXPECT_FLOAT_EQ(m3.At(0, 1), 10.0f);
EXPECT_FLOAT_EQ(m3.At(1, 0), 15.0f);
EXPECT_FLOAT_EQ(m3.At(1, 1), 22.0f);
}
TEST_F(UnitTestMat, Operator_Multiplication_Scalar)
{
Mat<2, 2> m3 = m2 * 2.0f;
EXPECT_FLOAT_EQ(m3.At(0, 0), 2.0f);
EXPECT_FLOAT_EQ(m3.At(1, 1), 8.0f);
}
TEST_F(UnitTestMat, Operator_Division_Scalar)
{
Mat<2, 2> m3 = m2 / 2.0f;
EXPECT_FLOAT_EQ(m3.At(0, 0), 0.5f);
EXPECT_FLOAT_EQ(m3.At(1, 1), 2.0f);
}
// Test matrix functions
TEST_F(UnitTestMat, Transpose)
{
Mat<2, 2> m3 = m2.Transposed();
EXPECT_FLOAT_EQ(m3.At(0, 0), m2.At(0, 0));
EXPECT_FLOAT_EQ(m3.At(0, 1), m2.At(1, 0));
EXPECT_FLOAT_EQ(m3.At(1, 0), m2.At(0, 1));
EXPECT_FLOAT_EQ(m3.At(1, 1), m2.At(1, 1));
}
TEST_F(UnitTestMat, Determinant)
{
const float det = m2.Determinant();
EXPECT_FLOAT_EQ(det, -2.0f);
}
TEST_F(UnitTestMat, Sum)
{
const float sum = m2.Sum();
EXPECT_FLOAT_EQ(sum, 10.0f);
}
TEST_F(UnitTestMat, Clear)
{
m2.Clear();
for (size_t i = 0; i < m2.RowCount(); ++i)
for (size_t j = 0; j < m2.ColumnsCount(); ++j)
EXPECT_FLOAT_EQ(m2.At(i, j), 0.0f);
}
TEST_F(UnitTestMat, ToString)
{
const std::string str = m2.ToString();
EXPECT_FALSE(str.empty());
EXPECT_EQ(str, "1 2\n3 4\n");
}
// Test assignment operators
TEST_F(UnitTestMat, AssignmentOperator_Copy)
{
Mat<2, 2> m3;
m3 = m2;
EXPECT_EQ(m3.RowCount(), m2.RowCount());
EXPECT_EQ(m3.ColumnsCount(), m2.ColumnsCount());
EXPECT_FLOAT_EQ(m3.At(0, 0), m2.At(0, 0));
}
TEST_F(UnitTestMat, AssignmentOperator_Move)
{
Mat<2, 2> m3;
m3 = std::move(m2);
EXPECT_EQ(m3.RowCount(), 2);
EXPECT_EQ(m3.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(m3.At(0, 0), 1.0f);
EXPECT_FLOAT_EQ(m3.At(1, 1), 4.0f);
// m2 is in a valid but unspecified state after move
}
// Test static methods
TEST_F(UnitTestMat, StaticMethod_ToScreenMat)
{
Mat<4, 4> screenMat = Mat<4, 4>::ToScreenMat(800.0f, 600.0f);
EXPECT_FLOAT_EQ(screenMat.At(0, 0), 400.0f);
EXPECT_FLOAT_EQ(screenMat.At(1, 1), -300.0f);
EXPECT_FLOAT_EQ(screenMat.At(3, 0), 400.0f);
EXPECT_FLOAT_EQ(screenMat.At(3, 1), 300.0f);
EXPECT_FLOAT_EQ(screenMat.At(3, 3), 1.0f);
}
// Test static method: TranslationMat
TEST_F(UnitTestMat, StaticMethod_TranslationMat)
{
Vector3 diff{10.0f, 20.0f, 30.0f};
Mat<4, 4> transMat = Mat<4, 4>::TranslationMat(diff);
EXPECT_FLOAT_EQ(transMat.At(0, 0), 1.0f);
EXPECT_FLOAT_EQ(transMat.At(3, 0), diff.x);
EXPECT_FLOAT_EQ(transMat.At(3, 1), diff.y);
EXPECT_FLOAT_EQ(transMat.At(3, 2), diff.z);
EXPECT_FLOAT_EQ(transMat.At(3, 3), 1.0f);
}
// Test static method: OrientationMat
TEST_F(UnitTestMat, StaticMethod_OrientationMat)
{
constexpr Vector3 forward{0.0f, 0.0f, 1.0f};
constexpr Vector3 right{1.0f, 0.0f, 0.0f};
constexpr Vector3 up{0.0f, 1.0f, 0.0f};
constexpr Mat<4, 4> orientMat = Mat<4, 4>::OrientationMat(forward, right, up);
EXPECT_FLOAT_EQ(orientMat.At(0, 0), right.x);
EXPECT_FLOAT_EQ(orientMat.At(0, 1), up.x);
EXPECT_FLOAT_EQ(orientMat.At(0, 2), forward.x);
EXPECT_FLOAT_EQ(orientMat.At(1, 0), right.y);
EXPECT_FLOAT_EQ(orientMat.At(1, 1), up.y);
EXPECT_FLOAT_EQ(orientMat.At(1, 2), forward.y);
EXPECT_FLOAT_EQ(orientMat.At(2, 0), right.z);
EXPECT_FLOAT_EQ(orientMat.At(2, 1), up.z);
EXPECT_FLOAT_EQ(orientMat.At(2, 2), forward.z);
}
// Test exception handling in At() method
TEST_F(UnitTestMat, Method_At_OutOfRange)
{
EXPECT_THROW(std::ignore = m2.At(2, 0), std::out_of_range);
EXPECT_THROW(std::ignore = m2.At(0, 2), std::out_of_range);
}
// Test Determinant for 3x3 matrix
TEST(UnitTestMatStandalone, Determinant_3x3)
{
constexpr auto det = Mat<3, 3>{{6, 1, 1}, {4, -2, 5}, {2, 8, 7}}.Determinant();
EXPECT_FLOAT_EQ(det, -306.0f);
}
// Test Minor for 3x3 matrix
TEST(UnitTestMatStandalone, Minor_3x3)
{
constexpr Mat<3, 3> m{{3, 0, 2}, {2, 0, -2}, {0, 1, 1}};
auto minor = m.Minor(0, 0);
EXPECT_EQ(minor.RowCount(), 2);
EXPECT_EQ(minor.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(minor.At(0, 0), 0.0f);
EXPECT_FLOAT_EQ(minor.At(0, 1), -2.0f);
EXPECT_FLOAT_EQ(minor.At(1, 0), 1.0f);
EXPECT_FLOAT_EQ(minor.At(1, 1), 1.0f);
}
// Test Transpose for non-square matrix
TEST(UnitTestMatStandalone, Transpose_NonSquare)
{
constexpr Mat<2, 3> m{{1.0f, 2.0f, 3.0f}, {4.0f, 5.0f, 6.0f}};
auto transposed = m.Transposed();
EXPECT_EQ(transposed.RowCount(), 3);
EXPECT_EQ(transposed.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(transposed.At(0, 0), 1.0f);
EXPECT_FLOAT_EQ(transposed.At(1, 0), 2.0f);
EXPECT_FLOAT_EQ(transposed.At(2, 0), 3.0f);
EXPECT_FLOAT_EQ(transposed.At(0, 1), 4.0f);
EXPECT_FLOAT_EQ(transposed.At(1, 1), 5.0f);
EXPECT_FLOAT_EQ(transposed.At(2, 1), 6.0f);
}

View File

@@ -0,0 +1,171 @@
//
// Created by vlad on 5/18/2024.
//
#include <gtest/gtest.h>
#include <omath/Matrix.hpp>
#include "omath/Vector3.hpp"
using namespace omath;
class UnitTestMatrix : public ::testing::Test
{
protected:
Matrix m1;
Matrix m2;
void SetUp() override
{
m1 = Matrix(2, 2);
m2 = Matrix{{1.0f, 2.0f}, {3.0f, 4.0f}};
}
};
// Test constructors
TEST_F(UnitTestMatrix, Constructor_Size)
{
const Matrix m(3, 3);
EXPECT_EQ(m.RowCount(), 3);
EXPECT_EQ(m.ColumnsCount(), 3);
}
TEST_F(UnitTestMatrix, Constructor_InitializerList)
{
Matrix m{{1.0f, 2.0f}, {3.0f, 4.0f}};
EXPECT_EQ(m.RowCount(), 2);
EXPECT_EQ(m.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(m.At(0, 0), 1.0f);
EXPECT_FLOAT_EQ(m.At(1, 1), 4.0f);
}
TEST_F(UnitTestMatrix, Constructor_Copy)
{
Matrix m3 = m2;
EXPECT_EQ(m3.RowCount(), m2.RowCount());
EXPECT_EQ(m3.ColumnsCount(), m2.ColumnsCount());
EXPECT_FLOAT_EQ(m3.At(0, 0), m2.At(0, 0));
}
TEST_F(UnitTestMatrix, Constructor_Move)
{
Matrix m3 = std::move(m2);
EXPECT_EQ(m3.RowCount(), 2);
EXPECT_EQ(m3.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(m3.At(0, 0), 1.0f);
EXPECT_EQ(m2.RowCount(), 0); // m2 should be empty after the move
EXPECT_EQ(m2.ColumnsCount(), 0);
}
// Test matrix operations
TEST_F(UnitTestMatrix, Operator_Multiplication_Matrix)
{
Matrix m3 = m2 * m2;
EXPECT_EQ(m3.RowCount(), 2);
EXPECT_EQ(m3.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(m3.At(0, 0), 7.0f);
EXPECT_FLOAT_EQ(m3.At(1, 1), 22.0f);
}
TEST_F(UnitTestMatrix, Operator_Multiplication_Scalar)
{
Matrix m3 = m2 * 2.0f;
EXPECT_FLOAT_EQ(m3.At(0, 0), 2.0f);
EXPECT_FLOAT_EQ(m3.At(1, 1), 8.0f);
}
TEST_F(UnitTestMatrix, Operator_Division_Scalar)
{
Matrix m3 = m2 / 2.0f;
EXPECT_FLOAT_EQ(m3.At(0, 0), 0.5f);
EXPECT_FLOAT_EQ(m3.At(1, 1), 2.0f);
}
// Test matrix functions
TEST_F(UnitTestMatrix, Transpose)
{
Matrix m3 = m2.Transpose();
EXPECT_FLOAT_EQ(m3.At(0, 1), 3.0f);
EXPECT_FLOAT_EQ(m3.At(1, 0), 2.0f);
}
TEST_F(UnitTestMatrix, Determinant)
{
const float det = m2.Determinant();
EXPECT_FLOAT_EQ(det, -2.0f);
}
TEST_F(UnitTestMatrix, Minor)
{
const float minor = m2.Minor(0, 0);
EXPECT_FLOAT_EQ(minor, 4.0f);
}
TEST_F(UnitTestMatrix, AlgComplement)
{
const float algComp = m2.AlgComplement(0, 0);
EXPECT_FLOAT_EQ(algComp, 4.0f);
}
TEST_F(UnitTestMatrix, Strip)
{
Matrix m3 = m2.Strip(0, 0);
EXPECT_EQ(m3.RowCount(), 1);
EXPECT_EQ(m3.ColumnsCount(), 1);
EXPECT_FLOAT_EQ(m3.At(0, 0), 4.0f);
}
TEST_F(UnitTestMatrix, ProjectionMatrix)
{
const Matrix proj = Matrix::ProjectionMatrix(45.0f, 1.33f, 0.1f, 100.0f);
EXPECT_EQ(proj.RowCount(), 4);
EXPECT_EQ(proj.ColumnsCount(), 4);
// Further checks on projection matrix elements could be added
}
// Test other member functions
TEST_F(UnitTestMatrix, Set)
{
m1.Set(3.0f);
EXPECT_FLOAT_EQ(m1.At(0, 0), 3.0f);
EXPECT_FLOAT_EQ(m1.At(1, 1), 3.0f);
}
TEST_F(UnitTestMatrix, Sum)
{
const float sum = m2.Sum();
EXPECT_FLOAT_EQ(sum, 10.0f);
}
TEST_F(UnitTestMatrix, Clear)
{
m2.Clear();
EXPECT_FLOAT_EQ(m2.At(0, 0), 0.0f);
EXPECT_FLOAT_EQ(m2.At(1, 1), 0.0f);
}
TEST_F(UnitTestMatrix, ToString)
{
const std::string str = m2.ToString();
EXPECT_FALSE(str.empty());
}
// Test assignment operators
TEST_F(UnitTestMatrix, AssignmentOperator_Copy)
{
Matrix m3(2, 2);
m3 = m2;
EXPECT_EQ(m3.RowCount(), m2.RowCount());
EXPECT_EQ(m3.ColumnsCount(), m2.ColumnsCount());
EXPECT_FLOAT_EQ(m3.At(0, 0), m2.At(0, 0));
}
TEST_F(UnitTestMatrix, AssignmentOperator_Move)
{
Matrix m3(2, 2);
m3 = std::move(m2);
EXPECT_EQ(m3.RowCount(), 2);
EXPECT_EQ(m3.ColumnsCount(), 2);
EXPECT_FLOAT_EQ(m3.At(0, 0), 1.0f);
EXPECT_EQ(m2.RowCount(), 0); // m2 should be empty after the move
EXPECT_EQ(m2.ColumnsCount(), 0);
}

View File

@@ -0,0 +1,14 @@
#include <gtest/gtest.h>
#include <omath/prediction/Engine.hpp>
TEST(UnitTestPrediction, PredictionTest)
{
const omath::prediction::Target target{.m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_isAirborne = false};
const omath::prediction::Projectile proj = {.m_origin = {3,2,1}, .m_launchSpeed = 5000, .m_gravityScale= 0.4};
const auto viewPoint = omath::prediction::Engine(400, 1.f / 1000.f, 50, 5.f).MaybeCalculateAimPoint(proj, target);
const auto [pitch, yaw, _] = proj.m_origin.ViewAngleTo(viewPoint.value()).AsTuple();
EXPECT_NEAR(42.547142, pitch, 0.0001f);
EXPECT_NEAR(-1.181189, yaw, 0.0001f);
}

View File

@@ -0,0 +1,19 @@
//
// Created by Vlad on 27.08.2024.
//
#include <complex>
#include <gtest/gtest.h>
#include <omath/Matrix.hpp>
#include <print>
#include <omath/projection/Camera.hpp>
TEST(UnitTestProjection, Projection)
{
const omath::projection::Camera camera({0.f, 0.f, 0.f}, {0, 0.f, 0.f} , {1920.f, 1080.f}, 110.f, 0.375f, 5000.f, 1.335f);
const auto projected = camera.WorldToScreen({5000, 0, 0});
EXPECT_TRUE(projected.has_value());
EXPECT_EQ(projected->z, 1.f);
}

View File

@@ -0,0 +1,353 @@
//
// Created by Vlad on 02.09.2024.
//
#include <gtest/gtest.h>
#include <omath/Vector2.hpp>
#include <cmath> // For std::isinf and std::isnan
#include <cfloat> // For FLT_MAX and FLT_MIN
using namespace omath;
class UnitTestVector2 : public ::testing::Test
{
protected:
Vector2 v1;
Vector2 v2;
constexpr void SetUp() override
{
v1 = Vector2(1.0f, 2.0f);
v2 = Vector2(4.0f, 5.0f);
}
};
// Test constructor and default values
TEST_F(UnitTestVector2, Constructor_Default)
{
constexpr Vector2 v;
EXPECT_FLOAT_EQ(v.x, 0.0f);
EXPECT_FLOAT_EQ(v.y, 0.0f);
}
TEST_F(UnitTestVector2, Constructor_Values)
{
constexpr Vector2 v(1.0f, 2.0f);
EXPECT_FLOAT_EQ(v.x, 1.0f);
EXPECT_FLOAT_EQ(v.y, 2.0f);
}
// Test equality operators
TEST_F(UnitTestVector2, EqualityOperator)
{
constexpr Vector2 v3(1.0f, 2.0f);
EXPECT_TRUE(v1 == v3);
EXPECT_FALSE(v1 == v2);
}
TEST_F(UnitTestVector2, InequalityOperator)
{
constexpr Vector2 v3(1.0f, 2.0f);
EXPECT_FALSE(v1 != v3);
EXPECT_TRUE(v1 != v2);
}
// Test arithmetic operators
TEST_F(UnitTestVector2, AdditionOperator)
{
constexpr Vector2 v3 = Vector2(1.0f, 2.0f) + Vector2(4.0f, 5.0f);
EXPECT_FLOAT_EQ(v3.x, 5.0f);
EXPECT_FLOAT_EQ(v3.y, 7.0f);
}
TEST_F(UnitTestVector2, SubtractionOperator)
{
constexpr Vector2 v3 = Vector2(4.0f, 5.0f) - Vector2(1.0f, 2.0f);
EXPECT_FLOAT_EQ(v3.x, 3.0f);
EXPECT_FLOAT_EQ(v3.y, 3.0f);
}
TEST_F(UnitTestVector2, MultiplicationOperator)
{
constexpr Vector2 v3 = Vector2(1.0f, 2.0f) * 2.0f;
EXPECT_FLOAT_EQ(v3.x, 2.0f);
EXPECT_FLOAT_EQ(v3.y, 4.0f);
}
TEST_F(UnitTestVector2, DivisionOperator)
{
constexpr Vector2 v3 = Vector2(4.0f, 5.0f) / 2.0f;
EXPECT_FLOAT_EQ(v3.x, 2.0f);
EXPECT_FLOAT_EQ(v3.y, 2.5f);
}
TEST_F(UnitTestVector2, NegationOperator)
{
constexpr Vector2 v3 = -Vector2(1.0f, 2.0f);
EXPECT_FLOAT_EQ(v3.x, -1.0f);
EXPECT_FLOAT_EQ(v3.y, -2.0f);
}
// Test compound assignment operators
TEST_F(UnitTestVector2, AdditionAssignmentOperator)
{
v1 += v2;
EXPECT_FLOAT_EQ(v1.x, 5.0f);
EXPECT_FLOAT_EQ(v1.y, 7.0f);
}
TEST_F(UnitTestVector2, SubtractionAssignmentOperator)
{
v1 -= v2;
EXPECT_FLOAT_EQ(v1.x, -3.0f);
EXPECT_FLOAT_EQ(v1.y, -3.0f);
}
TEST_F(UnitTestVector2, MultiplicationAssignmentOperator)
{
v1 *= 2.0f;
EXPECT_FLOAT_EQ(v1.x, 2.0f);
EXPECT_FLOAT_EQ(v1.y, 4.0f);
}
TEST_F(UnitTestVector2, DivisionAssignmentOperator)
{
v1 /= 2.0f;
EXPECT_FLOAT_EQ(v1.x, 0.5f);
EXPECT_FLOAT_EQ(v1.y, 1.0f);
}
// New tests for compound assignment with vectors
TEST_F(UnitTestVector2, MultiplicationAssignmentOperator_Vector)
{
v1 *= v2;
EXPECT_FLOAT_EQ(v1.x, 1.0f * 4.0f);
EXPECT_FLOAT_EQ(v1.y, 2.0f * 5.0f);
}
TEST_F(UnitTestVector2, DivisionAssignmentOperator_Vector)
{
v1 /= v2;
EXPECT_FLOAT_EQ(v1.x, 1.0f / 4.0f);
EXPECT_FLOAT_EQ(v1.y, 2.0f / 5.0f);
}
// New tests for compound assignment with floats
TEST_F(UnitTestVector2, AdditionAssignmentOperator_Float)
{
v1 += 3.0f;
EXPECT_FLOAT_EQ(v1.x, 4.0f);
EXPECT_FLOAT_EQ(v1.y, 5.0f);
}
TEST_F(UnitTestVector2, SubtractionAssignmentOperator_Float)
{
v1 -= 1.0f;
EXPECT_FLOAT_EQ(v1.x, 0.0f);
EXPECT_FLOAT_EQ(v1.y, 1.0f);
}
// Test other member functions
TEST_F(UnitTestVector2, DistTo)
{
const float dist = v1.DistTo(v2);
EXPECT_FLOAT_EQ(dist, std::sqrt(18.0f));
}
TEST_F(UnitTestVector2, DistTo_SamePoint)
{
const float dist = v1.DistTo(v1);
EXPECT_FLOAT_EQ(dist, 0.0f);
}
TEST_F(UnitTestVector2, DistToSqr)
{
constexpr float distSqr = Vector2(1.0f, 2.0f).DistToSqr(Vector2(4.0f, 5.0f));
EXPECT_FLOAT_EQ(distSqr, 18.0f);
}
TEST_F(UnitTestVector2, DistToSqr_SamePoint)
{
constexpr float distSqr = Vector2(1.0f, 2.0f).DistToSqr(Vector2(1.0f, 2.0f));
EXPECT_FLOAT_EQ(distSqr, 0.0f);
}
TEST_F(UnitTestVector2, DotProduct)
{
constexpr float dot = Vector2(1.0f, 2.0f).Dot(Vector2(4.0f, 5.0f));
EXPECT_FLOAT_EQ(dot, 14.0f);
}
TEST_F(UnitTestVector2, DotProduct_PerpendicularVectors)
{
constexpr float dot = Vector2(1.0f, 0.0f).Dot(Vector2(0.0f, 1.0f));
EXPECT_FLOAT_EQ(dot, 0.0f);
}
TEST_F(UnitTestVector2, DotProduct_ParallelVectors)
{
constexpr float dot = Vector2(1.0f, 1.0f).Dot(Vector2(2.0f, 2.0f));
EXPECT_FLOAT_EQ(dot, 4.0f);
}
TEST_F(UnitTestVector2, Length)
{
const float length = v1.Length();
EXPECT_FLOAT_EQ(length, std::sqrt(5.0f));
}
TEST_F(UnitTestVector2, Length_ZeroVector)
{
constexpr Vector2 v_zero(0.0f, 0.0f);
const float length = v_zero.Length();
EXPECT_FLOAT_EQ(length, 0.0f);
}
TEST_F(UnitTestVector2, Length_LargeValues)
{
constexpr Vector2 v_large(FLT_MAX, FLT_MAX);
const float length = v_large.Length();
EXPECT_TRUE(std::isinf(length));
}
TEST_F(UnitTestVector2, LengthSqr)
{
constexpr float lengthSqr = Vector2(1.0f, 2.0f).LengthSqr();
EXPECT_FLOAT_EQ(lengthSqr, 5.0f);
}
TEST_F(UnitTestVector2, Abs)
{
Vector2 v3(-1.0f, -2.0f);
v3.Abs();
EXPECT_FLOAT_EQ(v3.x, 1.0f);
EXPECT_FLOAT_EQ(v3.y, 2.0f);
}
TEST_F(UnitTestVector2, Abs_PositiveValues)
{
Vector2 v3(1.0f, 2.0f);
v3.Abs();
EXPECT_FLOAT_EQ(v3.x, 1.0f);
EXPECT_FLOAT_EQ(v3.y, 2.0f);
}
TEST_F(UnitTestVector2, Abs_ZeroValues)
{
Vector2 v3(0.0f, 0.0f);
v3.Abs();
EXPECT_FLOAT_EQ(v3.x, 0.0f);
EXPECT_FLOAT_EQ(v3.y, 0.0f);
}
TEST_F(UnitTestVector2, Sum)
{
constexpr float sum = Vector2(1.0f, 2.0f).Sum();
EXPECT_FLOAT_EQ(sum, 3.0f);
}
TEST_F(UnitTestVector2, Sum_NegativeValues)
{
constexpr float sum = Vector2(-1.0f, -2.0f).Sum();
EXPECT_FLOAT_EQ(sum, -3.0f);
}
TEST_F(UnitTestVector2, Normalized)
{
const Vector2 v3 = v1.Normalized();
EXPECT_NEAR(v3.x, 0.44721f, 0.0001f);
EXPECT_NEAR(v3.y, 0.89443f, 0.0001f);
}
TEST_F(UnitTestVector2, Normalized_ZeroVector)
{
constexpr Vector2 v_zero(0.0f, 0.0f);
const Vector2 v_norm = v_zero.Normalized();
EXPECT_FLOAT_EQ(v_norm.x, 0.0f);
EXPECT_FLOAT_EQ(v_norm.y, 0.0f);
}
// Test AsTuple method
TEST_F(UnitTestVector2, AsTuple)
{
const auto tuple = v1.AsTuple();
EXPECT_FLOAT_EQ(std::get<0>(tuple), v1.x);
EXPECT_FLOAT_EQ(std::get<1>(tuple), v1.y);
}
// Test division by zero
TEST_F(UnitTestVector2, DivisionOperator_DivideByZero)
{
constexpr Vector2 v(1.0f, 2.0f);
constexpr float zero = 0.0f;
const Vector2 result = v / zero;
EXPECT_TRUE(std::isinf(result.x) || std::isnan(result.x));
EXPECT_TRUE(std::isinf(result.y) || std::isnan(result.y));
}
TEST_F(UnitTestVector2, DivisionAssignmentOperator_DivideByZero)
{
Vector2 v(1.0f, 2.0f);
constexpr float zero = 0.0f;
v /= zero;
EXPECT_TRUE(std::isinf(v.x) || std::isnan(v.x));
EXPECT_TRUE(std::isinf(v.y) || std::isnan(v.y));
}
TEST_F(UnitTestVector2, DivisionAssignmentOperator_VectorWithZero)
{
Vector2 v(1.0f, 2.0f);
constexpr Vector2 v_zero(0.0f, 1.0f);
v /= v_zero;
EXPECT_TRUE(std::isinf(v.x) || std::isnan(v.x));
EXPECT_FLOAT_EQ(v.y, 2.0f / 1.0f);
}
// Test operations with infinity and NaN
TEST_F(UnitTestVector2, Operator_WithInfinity)
{
constexpr Vector2 v_inf(INFINITY, INFINITY);
const Vector2 result = v1 + v_inf;
EXPECT_TRUE(std::isinf(result.x));
EXPECT_TRUE(std::isinf(result.y));
}
TEST_F(UnitTestVector2, Operator_WithNaN)
{
constexpr Vector2 v_nan(NAN, NAN);
const Vector2 result = v1 + v_nan;
EXPECT_TRUE(std::isnan(result.x));
EXPECT_TRUE(std::isnan(result.y));
}
// Test negative values in arithmetic operations
TEST_F(UnitTestVector2, AdditionOperator_NegativeValues)
{
constexpr Vector2 v_neg(-1.0f, -2.0f);
const Vector2 result = v1 + v_neg;
EXPECT_FLOAT_EQ(result.x, 0.0f);
EXPECT_FLOAT_EQ(result.y, 0.0f);
}
TEST_F(UnitTestVector2, SubtractionOperator_NegativeValues)
{
constexpr Vector2 v_neg(-1.0f, -2.0f);
const Vector2 result = v1 - v_neg;
EXPECT_FLOAT_EQ(result.x, 2.0f);
EXPECT_FLOAT_EQ(result.y, 4.0f);
}
// Test negation of zero vector
TEST_F(UnitTestVector2, NegationOperator_ZeroVector)
{
constexpr Vector2 v_zero(0.0f, 0.0f);
constexpr Vector2 result = -v_zero;
EXPECT_FLOAT_EQ(result.x, -0.0f);
EXPECT_FLOAT_EQ(result.y, -0.0f);
}
// Static assertions (compile-time checks)
static_assert(Vector2(1.0f, 2.0f).LengthSqr() == 5.0f, "LengthSqr should be 5");
static_assert(Vector2(1.0f, 2.0f).Dot(Vector2(4.0f, 5.0f)) == 14.0f, "Dot product should be 14");
static_assert(Vector2(4.0f, 5.0f).DistToSqr(Vector2(1.0f, 2.0f)) == 18.0f, "DistToSqr should be 18");
static_assert(Vector2(-1.0f, -2.0f).Abs() == Vector2(1.0f, 2.0f), "Abs should convert negative values to positive");

View File

@@ -0,0 +1,394 @@
//
// Created by Vlad on 01.09.2024.
//
#include <gtest/gtest.h>
#include <omath/Vector3.hpp>
#include <cmath>
#include <cfloat> // For FLT_MAX, FLT_MIN
#include <limits> // For std::numeric_limits
using namespace omath;
class UnitTestVector3 : public ::testing::Test
{
protected:
Vector3 v1;
Vector3 v2;
void SetUp() override
{
v1 = Vector3(1.0f, 2.0f, 3.0f);
v2 = Vector3(4.0f, 5.0f, 6.0f);
}
};
// Test constructor and default values
TEST_F(UnitTestVector3, Constructor_Default)
{
constexpr Vector3 v;
EXPECT_FLOAT_EQ(v.x, 0.0f);
EXPECT_FLOAT_EQ(v.y, 0.0f);
EXPECT_FLOAT_EQ(v.z, 0.0f);
}
TEST_F(UnitTestVector3, Constructor_Values)
{
constexpr Vector3 v(1.0f, 2.0f, 3.0f);
EXPECT_FLOAT_EQ(v.x, 1.0f);
EXPECT_FLOAT_EQ(v.y, 2.0f);
EXPECT_FLOAT_EQ(v.z, 3.0f);
}
// Test equality operators
TEST_F(UnitTestVector3, EqualityOperator)
{
constexpr Vector3 v3(1.0f, 2.0f, 3.0f);
EXPECT_TRUE(v1 == v3);
EXPECT_FALSE(v1 == v2);
}
TEST_F(UnitTestVector3, InequalityOperator)
{
constexpr Vector3 v3(1.0f, 2.0f, 3.0f);
EXPECT_FALSE(v1 != v3);
EXPECT_TRUE(v1 != v2);
}
// Test arithmetic operators
TEST_F(UnitTestVector3, AdditionOperator)
{
constexpr Vector3 v3 = Vector3(1.0f, 2.0f, 3.0f) + Vector3(4.0f, 5.0f, 6.0f);
EXPECT_FLOAT_EQ(v3.x, 5.0f);
EXPECT_FLOAT_EQ(v3.y, 7.0f);
EXPECT_FLOAT_EQ(v3.z, 9.0f);
}
TEST_F(UnitTestVector3, SubtractionOperator)
{
constexpr Vector3 v3 = Vector3(4.0f, 5.0f, 6.0f) - Vector3(1.0f, 2.0f, 3.0f);
EXPECT_FLOAT_EQ(v3.x, 3.0f);
EXPECT_FLOAT_EQ(v3.y, 3.0f);
EXPECT_FLOAT_EQ(v3.z, 3.0f);
}
TEST_F(UnitTestVector3, MultiplicationOperator_Scalar)
{
constexpr Vector3 v3 = Vector3(1.0f, 2.0f, 3.0f) * 2.0f;
EXPECT_FLOAT_EQ(v3.x, 2.0f);
EXPECT_FLOAT_EQ(v3.y, 4.0f);
EXPECT_FLOAT_EQ(v3.z, 6.0f);
}
TEST_F(UnitTestVector3, MultiplicationOperator_Vector)
{
constexpr auto v3 = Vector3(1.0f, 2.0f, 3.0f) * Vector3(4.0f, 5.0f, 6.0f);
EXPECT_FLOAT_EQ(v3.x, 4.0f);
EXPECT_FLOAT_EQ(v3.y, 10.0f);
EXPECT_FLOAT_EQ(v3.z, 18.0f);
}
TEST_F(UnitTestVector3, DivisionOperator_Scalar)
{
constexpr auto v3 = Vector3(4.0f, 5.0f, 6.0f) / 2.0f;
EXPECT_FLOAT_EQ(v3.x, 2.0f);
EXPECT_FLOAT_EQ(v3.y, 2.5f);
EXPECT_FLOAT_EQ(v3.z, 3.0f);
}
TEST_F(UnitTestVector3, DivisionOperator_Vector)
{
constexpr auto v3 = Vector3(4.0f, 5.0f, 6.0f) / Vector3(1.0f, 2.0f, 3.0f);
EXPECT_FLOAT_EQ(v3.x, 4.0f);
EXPECT_FLOAT_EQ(v3.y, 2.5f);
EXPECT_FLOAT_EQ(v3.z, 2.0f);
}
// Test compound assignment operators
TEST_F(UnitTestVector3, AdditionAssignmentOperator)
{
v1 += v2;
EXPECT_FLOAT_EQ(v1.x, 5.0f);
EXPECT_FLOAT_EQ(v1.y, 7.0f);
EXPECT_FLOAT_EQ(v1.z, 9.0f);
}
TEST_F(UnitTestVector3, SubtractionAssignmentOperator)
{
v1 -= v2;
EXPECT_FLOAT_EQ(v1.x, -3.0f);
EXPECT_FLOAT_EQ(v1.y, -3.0f);
EXPECT_FLOAT_EQ(v1.z, -3.0f);
}
TEST_F(UnitTestVector3, MultiplicationAssignmentOperator_Scalar)
{
v1 *= 2.0f;
EXPECT_FLOAT_EQ(v1.x, 2.0f);
EXPECT_FLOAT_EQ(v1.y, 4.0f);
EXPECT_FLOAT_EQ(v1.z, 6.0f);
}
TEST_F(UnitTestVector3, MultiplicationAssignmentOperator_Vector)
{
v1 *= v2;
EXPECT_FLOAT_EQ(v1.x, 4.0f);
EXPECT_FLOAT_EQ(v1.y, 10.0f);
EXPECT_FLOAT_EQ(v1.z, 18.0f);
}
TEST_F(UnitTestVector3, DivisionAssignmentOperator_Scalar)
{
v1 /= 2.0f;
EXPECT_FLOAT_EQ(v1.x, 0.5f);
EXPECT_FLOAT_EQ(v1.y, 1.0f);
EXPECT_FLOAT_EQ(v1.z, 1.5f);
}
TEST_F(UnitTestVector3, DivisionAssignmentOperator_Vector)
{
v1 /= v2;
EXPECT_FLOAT_EQ(v1.x, 0.25f);
EXPECT_FLOAT_EQ(v1.y, 0.4f);
EXPECT_FLOAT_EQ(v1.z, 0.5f);
}
TEST_F(UnitTestVector3, NegationOperator)
{
constexpr auto v3 = -Vector3(1.0f, 2.0f, 3.0f);
EXPECT_FLOAT_EQ(v3.x, -1.0f);
EXPECT_FLOAT_EQ(v3.y, -2.0f);
EXPECT_FLOAT_EQ(v3.z, -3.0f);
}
// Test other member functions
TEST_F(UnitTestVector3, DistToSqr)
{
constexpr auto distSqr = Vector3(1.0f, 2.0f, 3.0f).DistToSqr(Vector3(4.0f, 5.0f, 6.0f));
EXPECT_FLOAT_EQ(distSqr, 27.0f);
}
TEST_F(UnitTestVector3, DotProduct)
{
constexpr auto dot = Vector3(1.0f, 2.0f, 3.0f).Dot(Vector3(4.0f, 5.0f, 6.0f));
EXPECT_FLOAT_EQ(dot, 32.0f);
}
TEST_F(UnitTestVector3, LengthSqr)
{
constexpr auto lengthSqr = Vector3(1.0f, 2.0f, 3.0f).LengthSqr();
EXPECT_FLOAT_EQ(lengthSqr, 14.0f);
}
TEST_F(UnitTestVector3, Abs)
{
auto v3 = Vector3(-1.0f, -2.0f, -3.0f);
v3.Abs();
EXPECT_FLOAT_EQ(v3.x, 1.0f);
EXPECT_FLOAT_EQ(v3.y, 2.0f);
EXPECT_FLOAT_EQ(v3.z, 3.0f);
}
TEST_F(UnitTestVector3, Sum)
{
constexpr auto sum = Vector3(1.0f, 2.0f, 3.0f).Sum();
EXPECT_FLOAT_EQ(sum, 6.0f);
}
TEST_F(UnitTestVector3, Sum2D)
{
constexpr auto sum2D = Vector3(1.0f, 2.0f, 3.0f).Sum2D();
EXPECT_FLOAT_EQ(sum2D, 3.0f);
}
TEST_F(UnitTestVector3, CrossProduct)
{
constexpr Vector3 v3 = Vector3(1.0f, 2.0f, 3.0f).Cross(Vector3(4.0f, 5.0f, 6.0f));
EXPECT_FLOAT_EQ(v3.x, -3.0f);
EXPECT_FLOAT_EQ(v3.y, 6.0f);
EXPECT_FLOAT_EQ(v3.z, -3.0f);
}
// New tests to cover corner cases
// Test operations with zero vectors
TEST_F(UnitTestVector3, Addition_WithZeroVector)
{
constexpr Vector3 v_zero(0.0f, 0.0f, 0.0f);
const Vector3 result = v1 + v_zero;
EXPECT_FLOAT_EQ(result.x, v1.x);
EXPECT_FLOAT_EQ(result.y, v1.y);
EXPECT_FLOAT_EQ(result.z, v1.z);
}
TEST_F(UnitTestVector3, Subtraction_WithZeroVector)
{
constexpr Vector3 v_zero(0.0f, 0.0f, 0.0f);
const Vector3 result = v1 - v_zero;
EXPECT_FLOAT_EQ(result.x, v1.x);
EXPECT_FLOAT_EQ(result.y, v1.y);
EXPECT_FLOAT_EQ(result.z, v1.z);
}
TEST_F(UnitTestVector3, Multiplication_WithZeroVector)
{
constexpr Vector3 v_zero(0.0f, 0.0f, 0.0f);
const Vector3 result = v1 * v_zero;
EXPECT_FLOAT_EQ(result.x, 0.0f);
EXPECT_FLOAT_EQ(result.y, 0.0f);
EXPECT_FLOAT_EQ(result.z, 0.0f);
}
TEST_F(UnitTestVector3, Division_ByZeroVector)
{
constexpr Vector3 v_zero(0.0f, 0.0f, 0.0f);
const Vector3 result = v1 / v_zero;
EXPECT_TRUE(std::isinf(result.x) || std::isnan(result.x));
EXPECT_TRUE(std::isinf(result.y) || std::isnan(result.y));
EXPECT_TRUE(std::isinf(result.z) || std::isnan(result.z));
}
TEST_F(UnitTestVector3, Division_ByZeroScalar)
{
constexpr float zero = 0.0f;
const Vector3 result = v1 / zero;
EXPECT_TRUE(std::isinf(result.x) || std::isnan(result.x));
EXPECT_TRUE(std::isinf(result.y) || std::isnan(result.y));
EXPECT_TRUE(std::isinf(result.z) || std::isnan(result.z));
}
// Test operations with infinity
TEST_F(UnitTestVector3, Addition_WithInfinity)
{
constexpr Vector3 v_inf(INFINITY, INFINITY, INFINITY);
const Vector3 result = v1 + v_inf;
EXPECT_TRUE(std::isinf(result.x));
EXPECT_TRUE(std::isinf(result.y));
EXPECT_TRUE(std::isinf(result.z));
}
TEST_F(UnitTestVector3, Subtraction_WithInfinity)
{
constexpr Vector3 v_inf(INFINITY, INFINITY, INFINITY);
const Vector3 result = v1 - v_inf;
EXPECT_TRUE(std::isinf(result.x));
EXPECT_TRUE(std::isinf(result.y));
EXPECT_TRUE(std::isinf(result.z));
}
// Test operations with NaN
TEST_F(UnitTestVector3, Multiplication_WithNaN)
{
constexpr Vector3 v_nan(NAN, NAN, NAN);
const Vector3 result = v1 * v_nan;
EXPECT_TRUE(std::isnan(result.x));
EXPECT_TRUE(std::isnan(result.y));
EXPECT_TRUE(std::isnan(result.z));
}
TEST_F(UnitTestVector3, Division_WithNaN)
{
constexpr Vector3 v_nan(NAN, NAN, NAN);
const Vector3 result = v1 / v_nan;
EXPECT_TRUE(std::isnan(result.x));
EXPECT_TRUE(std::isnan(result.y));
EXPECT_TRUE(std::isnan(result.z));
}
// Test Length, Length2D, and Normalized
TEST_F(UnitTestVector3, Length)
{
const float length = v1.Length();
EXPECT_FLOAT_EQ(length, std::sqrt(14.0f));
}
TEST_F(UnitTestVector3, Length_ZeroVector)
{
constexpr Vector3 v_zero(0.0f, 0.0f, 0.0f);
const float length = v_zero.Length();
EXPECT_FLOAT_EQ(length, 0.0f);
}
TEST_F(UnitTestVector3, Length_LargeValues)
{
constexpr Vector3 v_large(FLT_MAX, FLT_MAX, FLT_MAX);
const float length = v_large.Length();
EXPECT_TRUE(std::isinf(length));
}
TEST_F(UnitTestVector3, Length2D)
{
const float length2D = v1.Length2D();
EXPECT_FLOAT_EQ(length2D, std::sqrt(5.0f));
}
TEST_F(UnitTestVector3, Normalized)
{
const Vector3 v_norm = v1.Normalized();
const float length = v_norm.Length();
EXPECT_NEAR(length, 1.0f, 0.0001f);
}
TEST_F(UnitTestVector3, Normalized_ZeroVector)
{
constexpr Vector3 v_zero(0.0f, 0.0f, 0.0f);
const Vector3 v_norm = v_zero.Normalized();
EXPECT_FLOAT_EQ(v_norm.x, 0.0f);
EXPECT_FLOAT_EQ(v_norm.y, 0.0f);
EXPECT_FLOAT_EQ(v_norm.z, 0.0f);
}
// Test Cross Product edge cases
TEST_F(UnitTestVector3, CrossProduct_ParallelVectors)
{
constexpr Vector3 v_a(1.0f, 2.0f, 3.0f);
constexpr Vector3 v_b = v_a * 2.0f; // Parallel to v_a
constexpr Vector3 cross = v_a.Cross(v_b);
EXPECT_FLOAT_EQ(cross.x, 0.0f);
EXPECT_FLOAT_EQ(cross.y, 0.0f);
EXPECT_FLOAT_EQ(cross.z, 0.0f);
}
TEST_F(UnitTestVector3, CrossProduct_OrthogonalVectors)
{
constexpr Vector3 v_a(1.0f, 0.0f, 0.0f);
constexpr Vector3 v_b(0.0f, 1.0f, 0.0f);
constexpr Vector3 cross = v_a.Cross(v_b);
EXPECT_FLOAT_EQ(cross.x, 0.0f);
EXPECT_FLOAT_EQ(cross.y, 0.0f);
EXPECT_FLOAT_EQ(cross.z, 1.0f);
}
// Test negative values
TEST_F(UnitTestVector3, Addition_NegativeValues)
{
constexpr Vector3 v_neg(-1.0f, -2.0f, -3.0f);
const Vector3 result = v1 + v_neg;
EXPECT_FLOAT_EQ(result.x, 0.0f);
EXPECT_FLOAT_EQ(result.y, 0.0f);
EXPECT_FLOAT_EQ(result.z, 0.0f);
}
TEST_F(UnitTestVector3, Subtraction_NegativeValues)
{
constexpr Vector3 v_neg(-1.0f, -2.0f, -3.0f);
const Vector3 result = v1 - v_neg;
EXPECT_FLOAT_EQ(result.x, 2.0f);
EXPECT_FLOAT_EQ(result.y, 4.0f);
EXPECT_FLOAT_EQ(result.z, 6.0f);
}
// Test AsTuple method
TEST_F(UnitTestVector3, AsTuple)
{
const auto tuple = v1.AsTuple();
EXPECT_FLOAT_EQ(std::get<0>(tuple), v1.x);
EXPECT_FLOAT_EQ(std::get<1>(tuple), v1.y);
EXPECT_FLOAT_EQ(std::get<2>(tuple), v1.z);
}
// Static assertions (compile-time checks)
static_assert(Vector3(1.0f, 2.0f, 3.0f).LengthSqr() == 14.0f, "LengthSqr should be 14");
static_assert(Vector3(1.0f, 2.0f, 3.0f).Dot(Vector3(4.0f, 5.0f, 6.0f)) == 32.0f, "Dot product should be 32");
static_assert(Vector3(4.0f, 5.0f, 6.0f).DistToSqr(Vector3(1.0f, 2.0f, 3.0f)) == 27.0f, "DistToSqr should be 27");
static_assert(Vector3(-1.0f, -2.0f, -3.0f).Abs() == Vector3(1.0f, 2.0f, 3.0f), "Abs should convert negative values to positive");

View File

@@ -0,0 +1,217 @@
//
// Created by vlad on 9/24/2024.
//
//
// Vector4Test.cpp
//
#include <gtest/gtest.h>
#include <omath/Vector4.hpp>
#include <limits> // For std::numeric_limits
using namespace omath;
class UnitTestVector4 : public ::testing::Test
{
protected:
Vector4 v1;
Vector4 v2;
void SetUp() override
{
v1 = Vector4(1.0f, 2.0f, 3.0f, 4.0f);
v2 = Vector4(4.0f, 5.0f, 6.0f, 7.0f);
}
};
// Test constructor and default values
TEST_F(UnitTestVector4, Constructor_Default)
{
constexpr Vector4 v;
EXPECT_FLOAT_EQ(v.x, 0.0f);
EXPECT_FLOAT_EQ(v.y, 0.0f);
EXPECT_FLOAT_EQ(v.z, 0.0f);
EXPECT_FLOAT_EQ(v.w, 0.0f);
}
TEST_F(UnitTestVector4, Constructor_Values)
{
constexpr Vector4 v(1.0f, 2.0f, 3.0f, 4.0f);
EXPECT_FLOAT_EQ(v.x, 1.0f);
EXPECT_FLOAT_EQ(v.y, 2.0f);
EXPECT_FLOAT_EQ(v.z, 3.0f);
EXPECT_FLOAT_EQ(v.w, 4.0f);
}
// Test equality operators
TEST_F(UnitTestVector4, EqualityOperator)
{
constexpr Vector4 v3(1.0f, 2.0f, 3.0f, 4.0f);
EXPECT_TRUE(v1 == v3);
EXPECT_FALSE(v1 == v2);
}
TEST_F(UnitTestVector4, InequalityOperator)
{
constexpr Vector4 v3(1.0f, 2.0f, 3.0f, 4.0f);
EXPECT_FALSE(v1 != v3);
EXPECT_TRUE(v1 != v2);
}
// Test arithmetic operators
TEST_F(UnitTestVector4, AdditionOperator)
{
constexpr Vector4 v3 = Vector4(1.0f, 2.0f, 3.0f, 4.0f) + Vector4(4.0f, 5.0f, 6.0f, 7.0f);
EXPECT_FLOAT_EQ(v3.x, 5.0f);
EXPECT_FLOAT_EQ(v3.y, 7.0f);
EXPECT_FLOAT_EQ(v3.z, 9.0f);
EXPECT_FLOAT_EQ(v3.w, 11.0f);
}
TEST_F(UnitTestVector4, SubtractionOperator)
{
constexpr Vector4 v3 = Vector4(4.0f, 5.0f, 6.0f, 7.0f) - Vector4(1.0f, 2.0f, 3.0f, 4.0f);
EXPECT_FLOAT_EQ(v3.x, 3.0f);
EXPECT_FLOAT_EQ(v3.y, 3.0f);
EXPECT_FLOAT_EQ(v3.z, 3.0f);
EXPECT_FLOAT_EQ(v3.w, 3.0f);
}
TEST_F(UnitTestVector4, MultiplicationOperator_Scalar)
{
constexpr Vector4 v3 = Vector4(1.0f, 2.0f, 3.0f, 4.0f) * 2.0f;
EXPECT_FLOAT_EQ(v3.x, 2.0f);
EXPECT_FLOAT_EQ(v3.y, 4.0f);
EXPECT_FLOAT_EQ(v3.z, 6.0f);
EXPECT_FLOAT_EQ(v3.w, 8.0f);
}
TEST_F(UnitTestVector4, MultiplicationOperator_Vector)
{
constexpr Vector4 v3 = Vector4(1.0f, 2.0f, 3.0f, 4.0f) * Vector4(4.0f, 5.0f, 6.0f, 7.0f);
EXPECT_FLOAT_EQ(v3.x, 4.0f);
EXPECT_FLOAT_EQ(v3.y, 10.0f);
EXPECT_FLOAT_EQ(v3.z, 18.0f);
EXPECT_FLOAT_EQ(v3.w, 28.0f);
}
TEST_F(UnitTestVector4, DivisionOperator_Scalar)
{
constexpr Vector4 v3 = Vector4(4.0f, 5.0f, 6.0f, 7.0f) / 2.0f;
EXPECT_FLOAT_EQ(v3.x, 2.0f);
EXPECT_FLOAT_EQ(v3.y, 2.5f);
EXPECT_FLOAT_EQ(v3.z, 3.0f);
EXPECT_FLOAT_EQ(v3.w, 3.5f);
}
TEST_F(UnitTestVector4, DivisionOperator_Vector)
{
constexpr Vector4 v3 = Vector4(4.0f, 5.0f, 6.0f, 7.0f) / Vector4(1.0f, 2.0f, 3.0f, 4.0f);
EXPECT_FLOAT_EQ(v3.x, 4.0f);
EXPECT_FLOAT_EQ(v3.y, 2.5f);
EXPECT_FLOAT_EQ(v3.z, 2.0f);
EXPECT_FLOAT_EQ(v3.w, 1.75f);
}
// Test compound assignment operators
TEST_F(UnitTestVector4, AdditionAssignmentOperator)
{
v1 += v2;
EXPECT_FLOAT_EQ(v1.x, 5.0f);
EXPECT_FLOAT_EQ(v1.y, 7.0f);
EXPECT_FLOAT_EQ(v1.z, 9.0f);
EXPECT_FLOAT_EQ(v1.w, 11.0f);
}
TEST_F(UnitTestVector4, SubtractionAssignmentOperator)
{
v1 -= v2;
EXPECT_FLOAT_EQ(v1.x, -3.0f);
EXPECT_FLOAT_EQ(v1.y, -3.0f);
EXPECT_FLOAT_EQ(v1.z, -3.0f);
EXPECT_FLOAT_EQ(v1.w, -3.0f);
}
TEST_F(UnitTestVector4, MultiplicationAssignmentOperator_Scalar)
{
v1 *= 2.0f;
EXPECT_FLOAT_EQ(v1.x, 2.0f);
EXPECT_FLOAT_EQ(v1.y, 4.0f);
EXPECT_FLOAT_EQ(v1.z, 6.0f);
EXPECT_FLOAT_EQ(v1.w, 8.0f);
}
TEST_F(UnitTestVector4, MultiplicationAssignmentOperator_Vector)
{
v1 *= v2;
EXPECT_FLOAT_EQ(v1.x, 4.0f);
EXPECT_FLOAT_EQ(v1.y, 10.0f);
EXPECT_FLOAT_EQ(v1.z, 18.0f);
EXPECT_FLOAT_EQ(v1.w, 28.0f);
}
TEST_F(UnitTestVector4, DivisionAssignmentOperator_Scalar)
{
v1 /= 2.0f;
EXPECT_FLOAT_EQ(v1.x, 0.5f);
EXPECT_FLOAT_EQ(v1.y, 1.0f);
EXPECT_FLOAT_EQ(v1.z, 1.5f);
EXPECT_FLOAT_EQ(v1.w, 2.0f);
}
TEST_F(UnitTestVector4, DivisionAssignmentOperator_Vector)
{
v1 /= v2;
EXPECT_FLOAT_EQ(v1.x, 0.25f);
EXPECT_FLOAT_EQ(v1.y, 0.4f);
EXPECT_FLOAT_EQ(v1.z, 0.5f);
EXPECT_FLOAT_EQ(v1.w, 4.0f / 7.0f);
}
TEST_F(UnitTestVector4, NegationOperator)
{
constexpr Vector4 v3 = -Vector4(1.0f, 2.0f, 3.0f, 4.0f);
EXPECT_FLOAT_EQ(v3.x, -1.0f);
EXPECT_FLOAT_EQ(v3.y, -2.0f);
EXPECT_FLOAT_EQ(v3.z, -3.0f);
EXPECT_FLOAT_EQ(v3.w, -4.0f);
}
// Test other member functions
TEST_F(UnitTestVector4, LengthSqr)
{
constexpr float lengthSqr = Vector4(1.0f, 2.0f, 3.0f, 4.0f).LengthSqr();
EXPECT_FLOAT_EQ(lengthSqr, 30.0f);
}
TEST_F(UnitTestVector4, DotProduct)
{
constexpr float dot = Vector4(1.0f, 2.0f, 3.0f, 4.0f).Dot(Vector4(4.0f, 5.0f, 6.0f, 7.0f));
EXPECT_FLOAT_EQ(dot, 60.0f);
}
TEST_F(UnitTestVector4, Abs)
{
Vector4 v3 = Vector4(-1.0f, -2.0f, -3.0f, -4.0f);
v3.Abs();
EXPECT_FLOAT_EQ(v3.x, 1.0f);
EXPECT_FLOAT_EQ(v3.y, 2.0f);
EXPECT_FLOAT_EQ(v3.z, 3.0f);
EXPECT_FLOAT_EQ(v3.w, 4.0f);
}
TEST_F(UnitTestVector4, Sum)
{
constexpr float sum = Vector4(1.0f, 2.0f, 3.0f, 4.0f).Sum();
EXPECT_FLOAT_EQ(sum, 10.0f);
}
TEST_F(UnitTestVector4, Clamp)
{
Vector4 v3 = Vector4(1.0f, 2.0f, 3.0f, 4.0f);
v3.Clamp(1.5f, 2.5f);
EXPECT_FLOAT_EQ(v3.x, 1.5f);
EXPECT_FLOAT_EQ(v3.y, 2.0f);
EXPECT_FLOAT_EQ(v3.z, 2.5f);
EXPECT_FLOAT_EQ(v3.w, 4.0f); // w is not clamped in this method
}