#include "vec3.h" #include #include #include // Test fixture for Vec3 tests class Vec3Test : public ::testing::Test { protected: // Test vectors that will be used across multiple tests Vec3 int_vec1, int_vec2; Vec3 float_vec1, float_vec2; Vec3 double_vec1, double_vec2; void SetUp() override { // Initialize test vectors int_vec1 = {1, 2, 3}; int_vec2 = {4, 5, 6}; float_vec1 = {1.5f, 2.5f, 3.5f}; float_vec2 = {4.5f, 5.5f, 6.5f}; double_vec1 = {1.5, 2.5, 3.5}; double_vec2 = {4.5, 5.5, 6.5}; } }; // Test vector addition TEST_F(Vec3Test, Addition) { // Test integer vectors auto int_result = int_vec1 + int_vec2; EXPECT_EQ(int_result.x, 5); EXPECT_EQ(int_result.y, 7); EXPECT_EQ(int_result.z, 9); // Test float vectors auto float_result = float_vec1 + float_vec2; EXPECT_FLOAT_EQ(float_result.x, 6.0f); EXPECT_FLOAT_EQ(float_result.y, 8.0f); EXPECT_FLOAT_EQ(float_result.z, 10.0f); // Test double vectors auto double_result = double_vec1 + double_vec2; EXPECT_DOUBLE_EQ(double_result.x, 6.0); EXPECT_DOUBLE_EQ(double_result.y, 8.0); EXPECT_DOUBLE_EQ(double_result.z, 10.0); } // Test vector subtraction TEST_F(Vec3Test, Subtraction) { // Test integer vectors auto int_result = int_vec2 - int_vec1; EXPECT_EQ(int_result.x, 3); EXPECT_EQ(int_result.y, 3); EXPECT_EQ(int_result.z, 3); // Test float vectors auto float_result = float_vec2 - float_vec1; EXPECT_FLOAT_EQ(float_result.x, 3.0f); EXPECT_FLOAT_EQ(float_result.y, 3.0f); EXPECT_FLOAT_EQ(float_result.z, 3.0f); // Test double vectors auto double_result = double_vec2 - double_vec1; EXPECT_DOUBLE_EQ(double_result.x, 3.0); EXPECT_DOUBLE_EQ(double_result.y, 3.0); EXPECT_DOUBLE_EQ(double_result.z, 3.0); } // Test vector scaling TEST_F(Vec3Test, Scale) { // Test integer scaling Vec3 int_vec_scaled = int_vec1; int_vec_scaled.scale(2); EXPECT_EQ(int_vec_scaled.x, 2); EXPECT_EQ(int_vec_scaled.y, 4); EXPECT_EQ(int_vec_scaled.z, 6); // Test float scaling Vec3 float_vec_scaled = float_vec1; float_vec_scaled.scale(2.0f); EXPECT_FLOAT_EQ(float_vec_scaled.x, 3.0f); EXPECT_FLOAT_EQ(float_vec_scaled.y, 5.0f); EXPECT_FLOAT_EQ(float_vec_scaled.z, 7.0f); // Test double scaling Vec3 double_vec_scaled = double_vec1; double_vec_scaled.scale(2.0); EXPECT_DOUBLE_EQ(double_vec_scaled.x, 3.0); EXPECT_DOUBLE_EQ(double_vec_scaled.y, 5.0); EXPECT_DOUBLE_EQ(double_vec_scaled.z, 7.0); // Test scaling by zero Vec3 zero_scaled = float_vec1; zero_scaled.scale(0.0f); EXPECT_FLOAT_EQ(zero_scaled.x, 0.0f); EXPECT_FLOAT_EQ(zero_scaled.y, 0.0f); EXPECT_FLOAT_EQ(zero_scaled.z, 0.0f); // Test scaling by negative number Vec3 neg_scaled = int_vec1; neg_scaled.scale(-1); EXPECT_EQ(neg_scaled.x, -1); EXPECT_EQ(neg_scaled.y, -2); EXPECT_EQ(neg_scaled.z, -3); } // Test dot product TEST_F(Vec3Test, DotProduct) { // Test integer dot product int int_dot = int_vec1.dot(int_vec2); EXPECT_EQ(int_dot, 32); // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32 // Test float dot product float float_dot = float_vec1.dot(float_vec2); EXPECT_FLOAT_EQ( float_dot, 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 double_dot = double_vec1.dot(double_vec2); EXPECT_DOUBLE_EQ(double_dot, 43.25); // Same calculation as float // Test dot product with self (should equal squared length) int self_dot = int_vec1.dot(int_vec1); EXPECT_EQ(self_dot, 14); // 1*1 + 2*2 + 3*3 = 1 + 4 + 9 = 14 // Test dot product with zero vector Vec3 zero_vec = {0, 0, 0}; EXPECT_EQ(int_vec1.dot(zero_vec), 0); } // Test cross product TEST_F(Vec3Test, CrossProduct) { // Test integer cross product auto int_cross = int_vec1.cross(int_vec2); EXPECT_EQ(int_cross.x, -3); // (2*6 - 3*5) = 12 - 15 = -3 EXPECT_EQ(int_cross.y, 6); // (3*4 - 1*6) = 12 - 6 = 6 EXPECT_EQ(int_cross.z, -3); // (1*5 - 2*4) = 5 - 8 = -3 // Test float cross product auto float_cross = float_vec1.cross(float_vec2); EXPECT_FLOAT_EQ(float_cross.x, -3.0f); // (2.5*6.5 - 3.5*5.5) = 16.25 - 19.25 = -3 EXPECT_FLOAT_EQ(float_cross.y, 6.0f); // (3.5*4.5 - 1.5*6.5) = 15.75 - 9.75 = 6 EXPECT_FLOAT_EQ(float_cross.z, -3.0f); // (1.5*5.5 - 2.5*4.5) = 8.25 - 11.25 = -3 // Test double cross product auto double_cross = double_vec1.cross(double_vec2); EXPECT_DOUBLE_EQ(double_cross.x, -3.0); EXPECT_DOUBLE_EQ(double_cross.y, 6.0); EXPECT_DOUBLE_EQ(double_cross.z, -3.0); // Test cross product with self (should be zero) auto self_cross = int_vec1.cross(int_vec1); EXPECT_EQ(self_cross.x, 0); EXPECT_EQ(self_cross.y, 0); EXPECT_EQ(self_cross.z, 0); // Test cross product of standard basis vectors (i × j = k) Vec3 vec_i = {1, 0, 0}; Vec3 vec_j = {0, 1, 0}; Vec3 vec_k = {0, 0, 1}; auto i_cross_j = vec_i.cross(vec_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 = vec_j.cross(vec_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 = vec_k.cross(vec_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 max_vec = {std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max()}; // Addition with max values may overflow, but we want to test the operation // works auto max_addition = max_vec + int_vec1; // Test with min values Vec3 min_vec = {std::numeric_limits::min(), std::numeric_limits::min(), std::numeric_limits::min()}; // Subtraction with min values may underflow, but we want to test the // operation works auto min_subtraction = min_vec - int_vec1; // Test with mixed values Vec3 mixed_vec1 = {0.0, -1.0, std::numeric_limits::infinity()}; Vec3 mixed_vec2 = {-0.0, 1.0, -std::numeric_limits::infinity()}; auto mixed_addition = mixed_vec1 + mixed_vec2; // 0.0 + (-0.0) = 0.0 EXPECT_DOUBLE_EQ(mixed_addition.x, 0.0); // -1.0 + 1.0 = 0.0 EXPECT_DOUBLE_EQ(mixed_addition.y, 0.0); // inf + (-inf) = NaN EXPECT_TRUE(std::isnan(mixed_addition.z)); // Test with NaN Vec3 nan_vec = {std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()}; // Any operation with NaN should result in NaN auto nan_result = double_vec1 + nan_vec; EXPECT_TRUE(std::isnan(nan_result.x)); EXPECT_TRUE(std::isnan(nan_result.y)); EXPECT_TRUE(std::isnan(nan_result.z)); } // Test squared_norm2 and norm2 methods TEST_F(Vec3Test, NormMethods) { // Test squared_norm2 for integer vector EXPECT_DOUBLE_EQ(int_vec1.squared_norm2(), 14.0); // 1*1 + 2*2 + 3*3 = 14 // Test norm2 for integer vector EXPECT_DOUBLE_EQ(int_vec1.norm2(), std::sqrt(14.0)); // √14 ≈ 3.741657... // Test squared_norm2 for float vector EXPECT_DOUBLE_EQ( float_vec1.squared_norm2(), 20.75); // 1.5*1.5 + 2.5*2.5 + 3.5*3.5 = 2.25 + 6.25 + 12.25 = 20.75 // Test norm2 for float vector EXPECT_DOUBLE_EQ(float_vec1.norm2(), std::sqrt(20.75)); // √20.75 ≈ 4.5552... // Test squared_norm2 for double vector EXPECT_DOUBLE_EQ(double_vec1.squared_norm2(), 20.75); // Same as float calculation // Test norm2 for double vector EXPECT_DOUBLE_EQ(double_vec1.norm2(), std::sqrt(20.75)); // Test with zero vector Vec3 zero_vec = {0, 0, 0}; EXPECT_DOUBLE_EQ(zero_vec.squared_norm2(), 0.0); EXPECT_DOUBLE_EQ(zero_vec.norm2(), 0.0); // Test with unit vectors Vec3 unit_x = {1.0, 0.0, 0.0}; Vec3 unit_y = {0.0, 1.0, 0.0}; Vec3 unit_z = {0.0, 0.0, 1.0}; EXPECT_DOUBLE_EQ(unit_x.squared_norm2(), 1.0); EXPECT_DOUBLE_EQ(unit_x.norm2(), 1.0); EXPECT_DOUBLE_EQ(unit_y.squared_norm2(), 1.0); EXPECT_DOUBLE_EQ(unit_y.norm2(), 1.0); EXPECT_DOUBLE_EQ(unit_z.squared_norm2(), 1.0); EXPECT_DOUBLE_EQ(unit_z.norm2(), 1.0); // Test with negative components Vec3 neg_vec = {-1, -2, -3}; EXPECT_DOUBLE_EQ(neg_vec.squared_norm2(), 14.0); // (-1)² + (-2)² + (-3)² = 14 EXPECT_DOUBLE_EQ(neg_vec.norm2(), std::sqrt(14.0)); } // Test norm methods with special values TEST_F(Vec3Test, NormEdgeCases) { // Test with infinity Vec3 inf_vec = {std::numeric_limits::infinity(), 0.0, 0.0}; EXPECT_TRUE(std::isinf(inf_vec.squared_norm2())); EXPECT_TRUE(std::isinf(inf_vec.norm2())); // Test with large values that might cause overflow in intermediate // calculations double large_val = std::sqrt(std::numeric_limits::max()) / 2.0; Vec3 large_vec = {large_val, large_val, large_val}; // The squared norm should be approximately 3 * large_val² double expected_squared = 3.0 * large_val * large_val; EXPECT_DOUBLE_EQ(large_vec.squared_norm2(), expected_squared); // The norm should be √(3) * large_val double expected_norm = std::sqrt(3.0) * large_val; EXPECT_DOUBLE_EQ(large_vec.norm2(), expected_norm); // Test with NaN values Vec3 nan_vec = {std::numeric_limits::quiet_NaN(), 0.0, 0.0}; EXPECT_TRUE(std::isnan(nan_vec.squared_norm2())); EXPECT_TRUE(std::isnan(nan_vec.norm2())); } // Main function that runs the tests int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }