#include "CppUnitTest.h" #include "../Eule/Vector4.h" #include "../Eule/Matrix4x4.h" #include "../Eule/Math.h" #include "../_TestingUtilities/HandyMacros.h" #include #include using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Eule; namespace Vectors { TEST_CLASS(_Vector4) { private: std::mt19937 rng; public: // Constructor _Vector4() { rng = std::mt19937((std::random_device())()); return; } // Tests if all values are 0 after initialization via default constructor TEST_METHOD(New_Vector_All_0) { Vector4d v4; Assert::AreEqual(0.0, v4.x); Assert::AreEqual(0.0, v4.y); Assert::AreEqual(0.0, v4.z); Assert::AreEqual(0.0, v4.w); return; } // Tests if values can be set via the constructor TEST_METHOD(Can_Set_Values_Constructor) { Vector4d v4(69, 32, 16, 10); Assert::AreEqual(69.0, v4.x); Assert::AreEqual(32.0, v4.y); Assert::AreEqual(16.0, v4.z); Assert::AreEqual(10.0, v4.w); return; } // Tests if values can be set via letters TEST_METHOD(Can_Set_Values_Letters) { Vector4d v4; v4.x = 69; v4.y = 32; v4.z = 16; v4.w = 10; Assert::AreEqual(69.0, v4.x); Assert::AreEqual(32.0, v4.y); Assert::AreEqual(16.0, v4.z); Assert::AreEqual(10.0, v4.w); return; } // Tests if values can be set via array descriptors TEST_METHOD(Can_Set_Values_ArrayDescriptor) { Vector4d v4; v4[0] = 69; v4[1] = 32; v4[2] = 16; v4[3] = 10; Assert::AreEqual(69.0, v4.x); Assert::AreEqual(32.0, v4.y); Assert::AreEqual(16.0, v4.z); Assert::AreEqual(10.0, v4.w); return; } // Tests if values can be set via an initializer list TEST_METHOD(Can_Set_Values_InitializerList) { Vector4d v4 = { 69, 32, 16, 10 }; Assert::AreEqual(69.0, v4.x); Assert::AreEqual(32.0, v4.y); Assert::AreEqual(16.0, v4.z); Assert::AreEqual(10.0, v4.w); return; } // Tests for vectors copied via the copy constructor to have the same values TEST_METHOD(Copy_Constructor_Same_Values) { Vector4d a(69, 32, 16, 10); Vector4d b(a); Assert::AreEqual(69.0, b.x); Assert::AreEqual(32.0, b.y); Assert::AreEqual(16.0, b.z); Assert::AreEqual(10.0, b.w); return; } // Tests for vectors copied via the equals operator to have the same values TEST_METHOD(Operator_Equals_Same_Values) { Vector4d a(69, 32, 16, 10); Vector4d b = a; Assert::AreEqual(69.0, b.x); Assert::AreEqual(32.0, b.y); Assert::AreEqual(16.0, b.z); Assert::AreEqual(10.0, b.w); return; } // Tests for vectors copied via the copy constructor to be modifyable without modifying the original object TEST_METHOD(Copy_Constructor_Independent) { Vector4d a(69, 32, 16, 10); Vector4d b(a); b.x = 169; b.y = 132; b.z = 116; b.w = 110; Assert::AreEqual(69.0, a.x); Assert::AreEqual(32.0, a.y); Assert::AreEqual(16.0, a.z); Assert::AreEqual(10.0, a.w); Assert::AreEqual(169.0, b.x); Assert::AreEqual(132.0, b.y); Assert::AreEqual(116.0, b.z); Assert::AreEqual(110.0, b.w); return; } // Tests for vectors copied via the equals operator to be modifyable without modifying the original object TEST_METHOD(Operator_Equals_Independent) { Vector4d a(69, 32, 16, 10); Vector4d b = a; b.x = 169; b.y = 132; b.z = 116; b.w = 110; Assert::AreEqual(69.0, a.x); Assert::AreEqual(32.0, a.y); Assert::AreEqual(16.0, a.z); Assert::AreEqual(10.0, a.w); Assert::AreEqual(169.0, b.x); Assert::AreEqual(132.0, b.y); Assert::AreEqual(116.0, b.z); Assert::AreEqual(110.0, b.w); return; } // Tests the SqrMagnitude method to work as expected with random numbers TEST_METHOD(SqrMagnitude) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double x = LARGE_RAND_DOUBLE; double y = LARGE_RAND_DOUBLE; double z = LARGE_RAND_DOUBLE; double w = LARGE_RAND_DOUBLE; double expected = x*x + y*y + z*z + w*w; Assert::AreEqual(expected, Vector4d(x, y, z, w).SqrMagnitude()); } return; } // Tests for the length of the vector (0,0,0,0) being 0 TEST_METHOD(Magnitude_Is_0_On_Vec0) { Assert::AreEqual(0.0, Vector4d(0, 0, 0, 0).Magnitude()); return; } // Tests for a vector of a known length to actually return that TEST_METHOD(Magnitude_One_Axis_X) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double x = LARGE_RAND_DOUBLE; Vector4d vec(x, 0, 0, 0); Assert::AreEqual(abs(x), vec.Magnitude()); } return; } // Tests for a vector of a known length to actually return that TEST_METHOD(Magnitude_One_Axis_Y) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double y = LARGE_RAND_DOUBLE; Vector4d vec(0, y, 0, 0); Assert::AreEqual(abs(y), vec.Magnitude()); } return; } // Tests for a vector of a known length to actually return that TEST_METHOD(Magnitude_One_Axis_Z) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double z = LARGE_RAND_DOUBLE; Vector4d vec(0, 0, z, 0); Assert::AreEqual(abs(z), vec.Magnitude()); } return; } // Tests for a vector of a known length to actually return that TEST_METHOD(Magnitude_One_Axis_W) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double w = LARGE_RAND_DOUBLE; Vector4d vec(0, 0, 0, w); Assert::AreEqual(abs(w), vec.Magnitude()); } return; } // Tests for a known result TEST_METHOD(Magnitude) { // Ya'll got more of 'dem digits? Assert::AreEqual(78.5746530377322045524124405346810817718505859375, Vector4d(-23.76, 15.82, 66.75, 30.06).Magnitude()); return; } // Tests for expected lerp result 0.00 TEST_METHOD(Lerp_000) { Vector4d a(100, 1000, 10, -200); Vector4d b(200, 4000, 100, 200); Vector4d res = a.Lerp(b, 0.00); std::wstringstream wss; wss << res; Assert::IsTrue(a == res, wss.str().c_str()); return; } // Tests for expected lerp result 0.25 TEST_METHOD(Lerp_025) { Vector4d a(100, 1000, 10, -200); Vector4d b(200, 4000, 100, 200); Vector4d res = a.Lerp(b, 0.25); std::wstringstream wss; wss << res; Assert::IsTrue(Vector4d(125, 1750, 32.5, -100) == res, wss.str().c_str()); return; } // Tests for expected lerp result 0.50 TEST_METHOD(Lerp_050) { Vector4d a(100, 1000, 10, -200); Vector4d b(200, 4000, 100, 200); Vector4d res = a.Lerp(b, 0.50); std::wstringstream wss; wss << res; Assert::IsTrue(Vector4d(150, 2500, 55, 0) == res, wss.str().c_str()); return; } // Tests for expected lerp result 0.75 TEST_METHOD(Lerp_075) { Vector4d a(100, 1000, 10, -200); Vector4d b(200, 4000, 100, 200); Vector4d res = a.Lerp(b, 0.75); std::wstringstream wss; wss << res; Assert::IsTrue(Vector4d(175, 3250, 77.5, 100) == res, wss.str().c_str()); return; } // Tests for expected lerp result 1.00 TEST_METHOD(Lerp_100) { Vector4d a(100, 1000, 10, -200); Vector4d b(200, 4000, 100, 200); Vector4d res = a.Lerp(b, 1.00); std::wstringstream wss; wss << res; Assert::IsTrue(b == res, wss.str().c_str()); return; } // Tests lerpself TEST_METHOD(LerpSelf) { Vector4d a(100, 1000, 10, -200); Vector4d b(200, 4000, 100, 200); a.LerpSelf(b, 0.75); std::wstringstream wss; wss << a; Assert::IsTrue(Vector4d(175, 3250, 77.5, 100) == a, wss.str().c_str()); return; } // Tests if an input vector of length 0 is handled correctly by the normalize method TEST_METHOD(Normalize_Length_Before_Is_0) { Vector4d vec(0, 0, 0, 0); vec.NormalizeSelf(); Assert::AreEqual(0.0, vec.Magnitude()); return; } // Tests for any normalized vector to be of length 1 TEST_METHOD(Normalize_Length_Is_1) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double x = LARGE_RAND_DOUBLE; double y = LARGE_RAND_DOUBLE; double z = LARGE_RAND_DOUBLE; double w = LARGE_RAND_DOUBLE; Vector4d vec(x, y, z, w); // Prevent a vector of length 0 going in if (vec.SqrMagnitude() == 0) vec.x++; std::wstringstream wss; wss << vec; Assert::IsTrue(Math::Similar(vec.Normalize().Magnitude(), 1.0), wss.str().c_str()); // Account for floating point inaccuracy } return; } // Tests the normalize method with known values TEST_METHOD(Normalize_Oracle) { // Setup Vector4d v(3.2, -5.3, 9.88, 69.420); // Exercise v.NormalizeSelf(); // Verify Vector4d expected(0.0454594951, -0.07529228877, 0.14035619114, 0.98618692201); Assert::IsTrue(v.Similar(expected)); } // Kinda dumb method, but ok lol // DON'T NORMALIZE INT-VECTORS WHAT IS WRONG WITH YOU TEST_METHOD(Normalized_Int_Vector_Is_0) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { int x = LARGE_RAND_INT; int y = LARGE_RAND_INT; int z = LARGE_RAND_INT; int w = LARGE_RAND_INT; Vector4i vec(x, y, z, w); vec.NormalizeSelf(); std::wstringstream wss; wss << vec; Assert::AreEqual(0.0, vec.Magnitude(), wss.str().c_str()); } } // Tests that NormalizeSelf() results in the same as Normalize() TEST_METHOD(NormalizeSelf_IsSameAs_Normalize) { // Run test 1000 times for (std::size_t i = 0; i < 1000; i++) { Vector4d vec(LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE, LARGE_RAND_DOUBLE); Vector4d nVec = vec.Normalize(); vec.NormalizeSelf(); Assert::IsTrue(nVec == vec); } return; } // Tests for the VectorScale() method to work TEST_METHOD(VectorScale) { // Run test 1000 times for (std::size_t i = 0; i < 1000; i++) { const double ax = LARGE_RAND_DOUBLE; const double ay = LARGE_RAND_DOUBLE; const double az = LARGE_RAND_DOUBLE; const double aw = LARGE_RAND_DOUBLE; const double bx = LARGE_RAND_DOUBLE; const double by = LARGE_RAND_DOUBLE; const double bz = LARGE_RAND_DOUBLE; const double bw = LARGE_RAND_DOUBLE; Vector4d a(ax, ay, az, aw); Vector4d b(bx, by, bz, bw); Vector4d target( ax * bx, ay * by, az * bz, aw * bw ); Assert::IsTrue(a.VectorScale(b) == target); } return; } // Tests for operator- (unary) to work TEST_METHOD(Operator_Unary_Negative) { Vector4d v(29, -5, 35, -69); Assert::IsTrue(Vector4d(-29, 5, -35, 69) == -v); return; } // Tests for operator+ to work as expected TEST_METHOD(Operator_Add) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double ax = LARGE_RAND_DOUBLE; double ay = LARGE_RAND_DOUBLE; double az = LARGE_RAND_DOUBLE; double aw = LARGE_RAND_DOUBLE; double bx = LARGE_RAND_DOUBLE; double by = LARGE_RAND_DOUBLE; double bz = LARGE_RAND_DOUBLE; double bw = LARGE_RAND_DOUBLE; Vector4d a(ax, ay, az, aw); Vector4d b(bx, by, bz, bw); Assert::IsTrue(Vector4d(ax + bx, ay + by, az + bz, aw + bw) == a + b); } return; } // Tests for operator+= to work as expected TEST_METHOD(Operator_Add_Equals) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double ax = LARGE_RAND_DOUBLE; double ay = LARGE_RAND_DOUBLE; double az = LARGE_RAND_DOUBLE; double aw = LARGE_RAND_DOUBLE; double bx = LARGE_RAND_DOUBLE; double by = LARGE_RAND_DOUBLE; double bz = LARGE_RAND_DOUBLE; double bw = LARGE_RAND_DOUBLE; Vector4d a(ax, ay, az, aw); a += Vector4d(bx, by, bz, bw); Assert::IsTrue(Vector4d(ax + bx, ay + by, az + bz, aw + bw) == a); } return; } // Tests for operator- to work as expected TEST_METHOD(Operator_Sub) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double ax = LARGE_RAND_DOUBLE; double ay = LARGE_RAND_DOUBLE; double az = LARGE_RAND_DOUBLE; double aw = LARGE_RAND_DOUBLE; double bx = LARGE_RAND_DOUBLE; double by = LARGE_RAND_DOUBLE; double bz = LARGE_RAND_DOUBLE; double bw = LARGE_RAND_DOUBLE; Vector4d a(ax, ay, az, aw); Vector4d b(bx, by, bz, bw); Assert::IsTrue(Vector4d(ax - bx, ay - by, az - bz, aw - bw) == a - b); } return; } // Tests for operator-= to work as expected TEST_METHOD(Operator_Sub_Equals) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double ax = LARGE_RAND_DOUBLE; double ay = LARGE_RAND_DOUBLE; double az = LARGE_RAND_DOUBLE; double aw = LARGE_RAND_DOUBLE; double bx = LARGE_RAND_DOUBLE; double by = LARGE_RAND_DOUBLE; double bz = LARGE_RAND_DOUBLE; double bw = LARGE_RAND_DOUBLE; Vector4d a(ax, ay, az, aw); a -= Vector4d(bx, by, bz, bw); Assert::IsTrue(Vector4d(ax - bx, ay - by, az - bz, aw - bw) == a); } return; } // Tests for operator* to work as expected TEST_METHOD(Operator_Mult) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double x = LARGE_RAND_DOUBLE; double y = LARGE_RAND_DOUBLE; double z = LARGE_RAND_DOUBLE; double w = LARGE_RAND_DOUBLE; double scalar = LARGE_RAND_DOUBLE; Vector4d a(x, y, z, w); Assert::IsTrue(Vector4d(x * scalar, y * scalar, z * scalar, w * scalar) == a * scalar); } return; } // Tests for operator*= to work as expected TEST_METHOD(Operator_Mult_Equals) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double x = LARGE_RAND_DOUBLE; double y = LARGE_RAND_DOUBLE; double z = LARGE_RAND_DOUBLE; double w = LARGE_RAND_DOUBLE; double scalar = LARGE_RAND_DOUBLE; Vector4d a(x, y, z, w); a *= scalar; Assert::IsTrue(Vector4d(x * scalar, y * scalar, z * scalar, w * scalar) == a); } return; } // Tests for operator/ to work as expected TEST_METHOD(Operator_Div) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double x = LARGE_RAND_DOUBLE; double y = LARGE_RAND_DOUBLE; double z = LARGE_RAND_DOUBLE; double w = LARGE_RAND_DOUBLE; double scalar = LARGE_RAND_DOUBLE; Vector4d a(x, y, z, w); Assert::IsTrue(Vector4d(x / scalar, y / scalar, z / scalar, w / scalar) == a / scalar); } return; } // Tests for operator/= to work as expected TEST_METHOD(Operator_Div_Equals) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double x = LARGE_RAND_DOUBLE; double y = LARGE_RAND_DOUBLE; double z = LARGE_RAND_DOUBLE; double w = LARGE_RAND_DOUBLE; double scalar = LARGE_RAND_DOUBLE; Vector4d a(x, y, z, w); a /= scalar; Assert::IsTrue(Vector4d(x / scalar, y / scalar, z / scalar, w / scalar) == a); } return; } // Tests for operator== to work as expected TEST_METHOD(Operator_Equals) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double ax = LARGE_RAND_DOUBLE; double ay = LARGE_RAND_DOUBLE; double az = LARGE_RAND_DOUBLE; double aw = LARGE_RAND_DOUBLE; double bx = LARGE_RAND_DOUBLE; double by = LARGE_RAND_DOUBLE; double bz = LARGE_RAND_DOUBLE; double bw = LARGE_RAND_DOUBLE; Vector4d a(ax, ay, az, aw); Vector4d b(bx, by, bz, bw); Assert::IsTrue( ((ax == bx) && (ay == by) && (az == bz) && (aw == bw)) == (a == b) ); } return; } // Tests for operator!= to work as expected TEST_METHOD(Operator_Not_Equals) { // Test 1000 times for (std::size_t i = 0; i < 1000; i++) { double ax = LARGE_RAND_DOUBLE; double ay = LARGE_RAND_DOUBLE; double az = LARGE_RAND_DOUBLE; double aw = LARGE_RAND_DOUBLE; double bx = LARGE_RAND_DOUBLE; double by = LARGE_RAND_DOUBLE; double bz = LARGE_RAND_DOUBLE; double bw = LARGE_RAND_DOUBLE; Vector4d a(ax, ay, az, aw); Vector4d b(bx, by, bz, bw); Assert::IsTrue( ((ax != bx) || (ay != by) || (az != bz) || (aw != bw)) == (a != b) ); } return; } // Tests matrix multiplication with the multiplication operator (*) with a known result TEST_METHOD(MatrixMult) { Vector4d vec(117, 12, -36, 500); Matrix4x4 mat; mat[0] = { -43.7, 83, 96, 86 }; mat[1] = { 12, 34.3, 43, -47 }; mat[2] = { 36, 67, 48.9, -32 }; mat[3] = { -69, 47, 21, 89.01 }; vec = vec * mat; Assert::IsTrue(Vector4d(35427.1, -23232.4, -12744.4, 36240) == vec); return; } // Tests matrix multiplication with the multiplication equals operator (*=) with a known result TEST_METHOD(MatrixMult_Equals) { Vector4d vec(117, 12, -36, 500); Matrix4x4 mat; mat[0] = { -43.7, 83, 96, 86 }; mat[1] = { 12, 34.3, 43, -47 }; mat[2] = { 36, 67, 48.9, -32 }; mat[3] = { -69, 47, 21, 89.01 }; vec *= mat; Assert::IsTrue(Vector4d(35427.1, -23232.4, -12744.4, 36240) == vec); return; } // Tests matrix multiplication with the multiplication operator (*) with a known result, but with an int-vector TEST_METHOD(MatrixMult_Int) { Vector4i vec(112, -420, 80085, 1); Matrix4x4 mat; mat[0] = { 12, 83, 96, 86 }; mat[1] = { 12, -57, 43, -47 }; mat[2] = { 36, 67, 61, -32 }; mat[3] = { -69, 47, 21, 99 }; vec = vec * mat; Assert::IsTrue(Vector4i(7654730, 3468892, 4861045, 1654416) == vec); return; } // Tests matrix multiplication with the multiplication equals operator (*=) with a known result, but with an int - vector TEST_METHOD(MatrixMult_Equals_Int) { Vector4i vec(112, -420, 80085, 1); Matrix4x4 mat; mat[0] = { 12, 83, 96, 86 }; mat[1] = { 12, -57, 43, -47 }; mat[2] = { 36, 67, 61, -32 }; mat[3] = { -69, 47, 21, 99 }; vec *= mat; Assert::IsTrue(Vector4i(7654730, 3468892, 4861045, 1654416) == vec); return; } // Tests loose comparison via Vector4d::Similar -> true TEST_METHOD(Loose_Comparison_True_Vector4d) { Assert::IsTrue( Vector4d(0.00000000000000000000001, -6.6666666666666666666666666666, 9.9999999999999999999999999999, -3.3333333333333333333333333333333333333).Similar( Vector4d(0, -6.666666667, 10, -3.33333333333333) )); return; } // Tests loose comparison via Vector4d::Similar -> false TEST_METHOD(Loose_Comparison_False_Vector4d) { Assert::IsFalse( Vector4d(0.00000000000000000000001, -6.6666666666666666666666666666, 9.9999999999999999999999999999, -3.3333333333333333333333333333333333333).Similar( Vector4d(0.1, -6.7, 10.1, -3.333) )); return; } // Tests that the move constructor works TEST_METHOD(Move_Constructor) { Vector4d a(1, 2, 3, 4); Vector4d b(std::move(a)); Assert::AreEqual(b.x, 1.0); Assert::AreEqual(b.y, 2.0); Assert::AreEqual(b.z, 3.0); Assert::AreEqual(b.w, 4.0); return; } // Tests that the move operator works TEST_METHOD(Move_Operator) { Vector4d a(1, 2, 3, 4); Vector4d b = std::move(a); Assert::AreEqual(b.x, 1.0); Assert::AreEqual(b.y, 2.0); Assert::AreEqual(b.z, 3.0); Assert::AreEqual(b.w, 4.0); return; } }; }