Vec3/tests/unit_tests/vec_test.cpp

232 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "vec3.h"
#include <cmath>
#include <gtest/gtest.h>
#include <limits>
// Test fixture for Vec3 tests
class Vec3Test : public ::testing::Test {
protected:
// Test vectors that will be used across multiple tests
Vec3<int> intVec1, intVec2;
Vec3<float> floatVec1, floatVec2;
Vec3<double> doubleVec1, doubleVec2;
void SetUp() override {
// Initialize test vectors
intVec1 = {1, 2, 3};
intVec2 = {4, 5, 6};
floatVec1 = {1.5f, 2.5f, 3.5f};
floatVec2 = {4.5f, 5.5f, 6.5f};
doubleVec1 = {1.5, 2.5, 3.5};
doubleVec2 = {4.5, 5.5, 6.5};
}
};
// Test vector addition
TEST_F(Vec3Test, Addition) {
// Test integer vectors
auto intResult = intVec1 + intVec2;
EXPECT_EQ(intResult.x, 5);
EXPECT_EQ(intResult.y, 7);
EXPECT_EQ(intResult.z, 9);
// Test float vectors
auto floatResult = floatVec1 + floatVec2;
EXPECT_FLOAT_EQ(floatResult.x, 6.0f);
EXPECT_FLOAT_EQ(floatResult.y, 8.0f);
EXPECT_FLOAT_EQ(floatResult.z, 10.0f);
// Test double vectors
auto doubleResult = doubleVec1 + doubleVec2;
EXPECT_DOUBLE_EQ(doubleResult.x, 6.0);
EXPECT_DOUBLE_EQ(doubleResult.y, 8.0);
EXPECT_DOUBLE_EQ(doubleResult.z, 10.0);
}
// Test vector subtraction
TEST_F(Vec3Test, Subtraction) {
// Test integer vectors
auto intResult = intVec2 - intVec1;
EXPECT_EQ(intResult.x, 3);
EXPECT_EQ(intResult.y, 3);
EXPECT_EQ(intResult.z, 3);
// Test float vectors
auto floatResult = floatVec2 - floatVec1;
EXPECT_FLOAT_EQ(floatResult.x, 3.0f);
EXPECT_FLOAT_EQ(floatResult.y, 3.0f);
EXPECT_FLOAT_EQ(floatResult.z, 3.0f);
// Test double vectors
auto doubleResult = doubleVec2 - doubleVec1;
EXPECT_DOUBLE_EQ(doubleResult.x, 3.0);
EXPECT_DOUBLE_EQ(doubleResult.y, 3.0);
EXPECT_DOUBLE_EQ(doubleResult.z, 3.0);
}
// Test vector scaling
TEST_F(Vec3Test, Scale) {
// Test integer scaling
Vec3<int> intVecScaled = intVec1;
intVecScaled.scale(2);
EXPECT_EQ(intVecScaled.x, 2);
EXPECT_EQ(intVecScaled.y, 4);
EXPECT_EQ(intVecScaled.z, 6);
// Test float scaling
Vec3<float> floatVecScaled = floatVec1;
floatVecScaled.scale(2.0f);
EXPECT_FLOAT_EQ(floatVecScaled.x, 3.0f);
EXPECT_FLOAT_EQ(floatVecScaled.y, 5.0f);
EXPECT_FLOAT_EQ(floatVecScaled.z, 7.0f);
// Test double scaling
Vec3<double> doubleVecScaled = doubleVec1;
doubleVecScaled.scale(2.0);
EXPECT_DOUBLE_EQ(doubleVecScaled.x, 3.0);
EXPECT_DOUBLE_EQ(doubleVecScaled.y, 5.0);
EXPECT_DOUBLE_EQ(doubleVecScaled.z, 7.0);
// Test scaling by zero
Vec3<float> zeroScaled = floatVec1;
zeroScaled.scale(0.0f);
EXPECT_FLOAT_EQ(zeroScaled.x, 0.0f);
EXPECT_FLOAT_EQ(zeroScaled.y, 0.0f);
EXPECT_FLOAT_EQ(zeroScaled.z, 0.0f);
// Test scaling by negative number
Vec3<int> negScaled = intVec1;
negScaled.scale(-1);
EXPECT_EQ(negScaled.x, -1);
EXPECT_EQ(negScaled.y, -2);
EXPECT_EQ(negScaled.z, -3);
}
// Test dot product
TEST_F(Vec3Test, DotProduct) {
// Test integer dot product
int intDot = intVec1.dot(intVec2);
EXPECT_EQ(intDot, 32); // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
// Test float dot product
float floatDot = floatVec1.dot(floatVec2);
EXPECT_FLOAT_EQ(
floatDot,
43.25f); // 1.5*4.5 + 2.5*5.5 + 3.5*6.5 = 6.75 + 13.75 + 22.75 = 43.25
// Test double dot product
double doubleDot = doubleVec1.dot(doubleVec2);
EXPECT_DOUBLE_EQ(doubleDot, 43.25); // Same calculation as float
// Test dot product with self (should equal squared length)
int selfDot = intVec1.dot(intVec1);
EXPECT_EQ(selfDot, 14); // 1*1 + 2*2 + 3*3 = 1 + 4 + 9 = 14
// Test dot product with zero vector
Vec3<int> zeroVec = {0, 0, 0};
EXPECT_EQ(intVec1.dot(zeroVec), 0);
}
// Test cross product
TEST_F(Vec3Test, CrossProduct) {
// Test integer cross product
auto intCross = intVec1.cross(intVec2);
EXPECT_EQ(intCross.x, -3); // (2*6 - 3*5) = 12 - 15 = -3
EXPECT_EQ(intCross.y, 6); // (3*4 - 1*6) = 12 - 6 = 6
EXPECT_EQ(intCross.z, -3); // (1*5 - 2*4) = 5 - 8 = -3
// Test float cross product
auto floatCross = floatVec1.cross(floatVec2);
EXPECT_FLOAT_EQ(floatCross.x,
-3.0f); // (2.5*6.5 - 3.5*5.5) = 16.25 - 19.25 = -3
EXPECT_FLOAT_EQ(floatCross.y,
6.0f); // (3.5*4.5 - 1.5*6.5) = 15.75 - 9.75 = 6
EXPECT_FLOAT_EQ(floatCross.z,
-3.0f); // (1.5*5.5 - 2.5*4.5) = 8.25 - 11.25 = -3
// Test double cross product
auto doubleCross = doubleVec1.cross(doubleVec2);
EXPECT_DOUBLE_EQ(doubleCross.x, -3.0);
EXPECT_DOUBLE_EQ(doubleCross.y, 6.0);
EXPECT_DOUBLE_EQ(doubleCross.z, -3.0);
// Test cross product with self (should be zero)
auto selfCross = intVec1.cross(intVec1);
EXPECT_EQ(selfCross.x, 0);
EXPECT_EQ(selfCross.y, 0);
EXPECT_EQ(selfCross.z, 0);
// Test cross product of standard basis vectors (i × j = k)
Vec3<int> i = {1, 0, 0};
Vec3<int> j = {0, 1, 0};
Vec3<int> k = {0, 0, 1};
auto i_cross_j = i.cross(j);
EXPECT_EQ(i_cross_j.x, 0);
EXPECT_EQ(i_cross_j.y, 0);
EXPECT_EQ(i_cross_j.z, 1);
auto j_cross_k = j.cross(k);
EXPECT_EQ(j_cross_k.x, 1);
EXPECT_EQ(j_cross_k.y, 0);
EXPECT_EQ(j_cross_k.z, 0);
auto k_cross_i = k.cross(i);
EXPECT_EQ(k_cross_i.x, 0);
EXPECT_EQ(k_cross_i.y, 1);
EXPECT_EQ(k_cross_i.z, 0);
}
// Test with edge cases
TEST_F(Vec3Test, EdgeCases) {
// Test with max values
Vec3<int> maxVec = {std::numeric_limits<int>::max(),
std::numeric_limits<int>::max(),
std::numeric_limits<int>::max()};
// Addition with max values may overflow, but we want to test the operation
// works
auto maxAddition = maxVec + intVec1;
// Test with min values
Vec3<int> minVec = {std::numeric_limits<int>::min(),
std::numeric_limits<int>::min(),
std::numeric_limits<int>::min()};
// Subtraction with min values may underflow, but we want to test the
// operation works
auto minSubtraction = minVec - intVec1;
// Test with mixed values
Vec3<double> mixedVec1 = {0.0, -1.0, std::numeric_limits<double>::infinity()};
Vec3<double> mixedVec2 = {-0.0, 1.0,
-std::numeric_limits<double>::infinity()};
auto mixedAddition = mixedVec1 + mixedVec2;
// 0.0 + (-0.0) = 0.0
EXPECT_DOUBLE_EQ(mixedAddition.x, 0.0);
// -1.0 + 1.0 = 0.0
EXPECT_DOUBLE_EQ(mixedAddition.y, 0.0);
// inf + (-inf) = NaN
EXPECT_TRUE(std::isnan(mixedAddition.z));
// Test with NaN
Vec3<double> nanVec = {std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN()};
// Any operation with NaN should result in NaN
auto nanResult = doubleVec1 + nanVec;
EXPECT_TRUE(std::isnan(nanResult.x));
EXPECT_TRUE(std::isnan(nanResult.y));
EXPECT_TRUE(std::isnan(nanResult.z));
}
// Main function that runs the tests
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}