From 108906dfe4f6da0cc3ddb0c4c8e6904812aa6403 Mon Sep 17 00:00:00 2001 From: Jarl Gullberg Date: Wed, 31 May 2017 20:08:41 +0200 Subject: [PATCH] Ported all Vector3 tests. --- .../{MathHelper.fs => MathHelperTests.fs} | 0 tests/OpenTK.Tests/Matrix4Tests.fs | 18 +- tests/OpenTK.Tests/OpenTK.Tests.fsproj | 5 +- tests/OpenTK.Tests/Vector2Tests.fs | 10 +- tests/OpenTK.Tests/Vector3Tests.fs | 527 +++++++++++++++++++++ 5 files changed, 552 insertions(+), 8 deletions(-) rename tests/OpenTK.Tests/{MathHelper.fs => MathHelperTests.fs} (100%) create mode 100644 tests/OpenTK.Tests/Vector3Tests.fs diff --git a/tests/OpenTK.Tests/MathHelper.fs b/tests/OpenTK.Tests/MathHelperTests.fs similarity index 100% rename from tests/OpenTK.Tests/MathHelper.fs rename to tests/OpenTK.Tests/MathHelperTests.fs diff --git a/tests/OpenTK.Tests/Matrix4Tests.fs b/tests/OpenTK.Tests/Matrix4Tests.fs index 920788e..8153abf 100644 --- a/tests/OpenTK.Tests/Matrix4Tests.fs +++ b/tests/OpenTK.Tests/Matrix4Tests.fs @@ -265,10 +265,18 @@ module Matrix4 = let invalidIndexingAssignmentC = fun() -> A.[1, -2] <- a let invalidIndexingAssignmentRC = fun() -> A.[-1, -2] <- a + let invalidIndexingAccessR = fun() -> A.[-1, 2] |> ignore + let invalidIndexingAccessC = fun() -> A.[1, -2] |> ignore + let invalidIndexingAccessRC = fun() -> A.[-1, -2] |> ignore + Assert.Throws(invalidIndexingAssignmentR) |> ignore Assert.Throws(invalidIndexingAssignmentC) |> ignore Assert.Throws(invalidIndexingAssignmentRC) |> ignore + Assert.Throws(invalidIndexingAccessR) |> ignore + Assert.Throws(invalidIndexingAccessC) |> ignore + Assert.Throws(invalidIndexingAccessRC) |> ignore + [] let ``Matrix indexing throws on large indices`` (a) = let mutable A = Matrix4() @@ -277,6 +285,14 @@ module Matrix4 = let invalidIndexingAssignmentC = fun() -> A.[1, 6] <- a let invalidIndexingAssignmentRC = fun() -> A.[7, 12] <- a + let invalidIndexingAccessR = fun() -> A.[5, 2] |> ignore + let invalidIndexingAccessC = fun() -> A.[1, 6] |> ignore + let invalidIndexingAccessRC = fun() -> A.[7, 12] |> ignore + Assert.Throws(invalidIndexingAssignmentR) |> ignore Assert.Throws(invalidIndexingAssignmentC) |> ignore - Assert.Throws(invalidIndexingAssignmentRC) |> ignore \ No newline at end of file + Assert.Throws(invalidIndexingAssignmentRC) |> ignore + + Assert.Throws(invalidIndexingAccessR) |> ignore + Assert.Throws(invalidIndexingAccessC) |> ignore + Assert.Throws(invalidIndexingAccessRC) |> ignore \ No newline at end of file diff --git a/tests/OpenTK.Tests/OpenTK.Tests.fsproj b/tests/OpenTK.Tests/OpenTK.Tests.fsproj index 93abb4d..09bd26c 100644 --- a/tests/OpenTK.Tests/OpenTK.Tests.fsproj +++ b/tests/OpenTK.Tests/OpenTK.Tests.fsproj @@ -58,13 +58,14 @@ --> - - + + + diff --git a/tests/OpenTK.Tests/Vector2Tests.fs b/tests/OpenTK.Tests/Vector2Tests.fs index 1bde27d..e69f232 100644 --- a/tests/OpenTK.Tests/Vector2Tests.fs +++ b/tests/OpenTK.Tests/Vector2Tests.fs @@ -100,19 +100,19 @@ module Vector2 = module Multiplication = // [] - let ``Vector multiplication is the same as component multiplication`` (a : Vector2,b : Vector2) = + let ``Vector2 multiplication is the same as component multiplication`` (a : Vector2, b : Vector2) = let c = a * b Assert.Equal(a.X * b.X,c.X) Assert.Equal(a.Y * b.Y,c.Y) [] - let ``Vector multiplication is commutative`` (a : Vector2,b : Vector2) = + let ``Vector2 multiplication is commutative`` (a : Vector2, b : Vector2) = let r1 = a * b let r2 = b * a Assert.Equal(r1,r2) [] - let ``Vector-float multiplication is the same as component-float multiplication`` (a : Vector2,f : float32) = + let ``Vector2-float multiplication is the same as component-float multiplication`` (a : Vector2, f : float32) = let r = a * f Assert.Equal(a.X * f,r.X) Assert.Equal(a.Y * f,r.Y) @@ -126,7 +126,7 @@ module Vector2 = module Subtraction = // [] - let ``Vector subtraction is the same as component subtraction`` (a : Vector2,b : Vector2) = + let ``Vector2 subtraction is the same as component subtraction`` (a : Vector2, b : Vector2) = let c = a - b Assert.Equal(a.X - b.X,c.X) Assert.Equal(a.Y - b.Y,c.Y) @@ -135,7 +135,7 @@ module Vector2 = module Division = // [] - let ``Vector-float division is the same as component-float division`` (a : Vector2,f : float32) = + let ``Vector2-float division is the same as component-float division`` (a : Vector2, f : float32) = if not (approxEq f 0.0f) then // we don't support diving by zero. let r = a / f Assert.ApproximatelyEqual(a.X / f,r.X) diff --git a/tests/OpenTK.Tests/Vector3Tests.fs b/tests/OpenTK.Tests/Vector3Tests.fs new file mode 100644 index 0000000..77bde23 --- /dev/null +++ b/tests/OpenTK.Tests/Vector3Tests.fs @@ -0,0 +1,527 @@ +namespace OpenTK.Tests + +open Xunit +open FsCheck +open FsCheck.Xunit +open System +open OpenTK + +module Vector3 = + [ |])>] + module Constructors = + // + [] + let ``Triple value constructor sets all components to the correct values`` (a, b, c) = + let v = Vector3(a, b, c) + + Assert.Equal(a, v.X) + Assert.Equal(b, v.Y) + Assert.Equal(c, v.Z) + + [] + let ``Single value constructor sets all components to the correct values`` (a : float32) = + let v = Vector3(a) + + Assert.Equal(a, v.X) + Assert.Equal(a, v.Y) + Assert.Equal(a, v.Z) + + [] + let ``Vector2 value constructor sets all components to the correct values`` (a, b) = + let v1 = Vector2(a, b) + let v2 = Vector3(v1) + + Assert.Equal(v1.X, v2.X) + Assert.Equal(v1.Y, v2.Y) + + Assert.Equal(a, v2.X) + Assert.Equal(b, v2.Y) + Assert.Equal((float32)0, v2.Z) + + [] + let ``Vector3 value constructor sets all components to the correct values`` (a, b, c) = + let v1 = Vector3(a, b, c) + let v2 = Vector3(v1) + + Assert.Equal(v1.X, v2.X) + Assert.Equal(v1.Y, v2.Y) + Assert.Equal(v1.Z, v2.Z) + + Assert.Equal(a, v2.X) + Assert.Equal(b, v2.Y) + Assert.Equal(c, v2.Z) + + [ |])>] + module Indexing = + // + [] + let ``Index operator accesses the correct components`` (a, b, c) = + let v = Vector3(a, b, c) + + Assert.Equal(a, v.[0]) + Assert.Equal(b, v.[1]) + Assert.Equal(c, v.[2]) + + [] + let ``Index operator throws exception for negative indices`` (a, b, c) = + let mutable v = Vector3(a, b, c) + + let invalidIndexingAccess = fun() -> v.[-1] |> ignore + let invalidIndexingAssignment = fun() -> v.[-1] <- a + + Assert.Throws(invalidIndexingAccess) |> ignore + Assert.Throws(invalidIndexingAssignment) |> ignore + + [] + let ``Index operator throws exception for large indices`` (a, b, c) = + let mutable v = Vector3(a, b, c) + + let invalidIndexingAccess = fun() -> v.[3] |> ignore + let invalidIndexingAssignment = fun() -> v.[3] <- a + + Assert.Throws(invalidIndexingAccess) |> ignore + Assert.Throws(invalidIndexingAssignment) |> ignore + + [ |])>] + module Length = + // + [] + let ``Length method works`` (a, b, c) = + let v = Vector3(a, b, c) + let l = System.Math.Sqrt((float)(a * a + b * b + c * c)) + + Assert.Equal((float32)l, v.Length) + + [] + let ``Fast length method works`` (a, b, c) = + let v = Vector3(a, b, c) + let l = 1.0f / MathHelper.InverseSqrtFast(a * a + b * b + c * c) + + Assert.Equal(l, v.LengthFast) + + [] + let ``Length squared method works`` (a, b, c) = + let v = Vector3(a, b, c) + let lsq = a * a + b * b + c * c + + Assert.Equal(lsq, v.LengthSquared) + + [ |])>] + module Normalization = + // + [] + let ``Normalization of instance, creating a new vector, works`` (a, b, c) = + let v = Vector3(a, b, c) + let l = v.Length + + let norm = v.Normalized() + + Assert.ApproximatelyEqual(v.X / l, norm.X) + Assert.ApproximatelyEqual(v.Y / l, norm.Y) + Assert.ApproximatelyEqual(v.Z / l, norm.Z) + + [] + let ``Normalization of instance works`` (a, b, c) = + let v = Vector3(a, b, c) + let norm = Vector3(a, b, c) + norm.Normalize() + + let l = v.Length + + Assert.ApproximatelyEqual(v.X / l, norm.X) + Assert.ApproximatelyEqual(v.Y / l, norm.Y) + Assert.ApproximatelyEqual(v.Z / l, norm.Z) + + [] + let ``Fast approximate normalization of instance works`` (a, b, c) = + let v = Vector3(a, b, c) + let norm = Vector3(a, b, c) + norm.NormalizeFast() + + let scale = MathHelper.InverseSqrtFast(a * a + b * b + c * c) + + Assert.ApproximatelyEqual(v.X * scale, norm.X) + Assert.ApproximatelyEqual(v.Y * scale, norm.Y) + Assert.ApproximatelyEqual(v.Z * scale, norm.Z) + + [] + let ``Normalization by reference works`` (a : Vector3) = + let scale = 1.0f / a.Length + let norm = Vector3(a.X * scale, a.Y * scale, a.Z * scale) + let vRes = Vector3.Normalize(ref a) + + Assert.ApproximatelyEqual(norm, vRes) + + [] + let ``Normalization works`` (a : Vector3) = + let scale = 1.0f / a.Length + let norm = Vector3(a.X * scale, a.Y * scale, a.Z * scale) + + Assert.ApproximatelyEqual(norm, Vector3.Normalize(a)); + + [] + let ``Fast approximate normalization by reference works`` (a : Vector3) = + let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y) + + let norm = Vector3(a.X * scale, a.Y * scale, a.Z * scale) + let vRes = Vector3.NormalizeFast(ref a) + + Assert.ApproximatelyEqual(norm, vRes) + + [] + let ``Fast approximate normalization works`` (a : Vector3) = + let scale = MathHelper.InverseSqrtFast(a.X * a.X + a.Y * a.Y) + + let norm = Vector3(a.X * scale, a.Y * scale, a.Z * scale) + + Assert.ApproximatelyEqual(norm, Vector3.NormalizeFast(a)); + + [ |])>] + module Addition = + // + [] + let ``Vector3 addition is the same as component addition`` (a : Vector3, b : Vector3) = + let c = a + b + + Assert.ApproximatelyEqual(a.X + b.X,c.X) + Assert.ApproximatelyEqual(a.Y + b.Y,c.Y) + + [] + let ``Vector3 addition is commutative`` (a : Vector3, b : Vector3) = + let c = a + b + let c2 = b + a + + Assert.ApproximatelyEqual(c, c2) + + [] + let ``Vector3 addition is associative`` (a : Vector3, b : Vector3, c : Vector3) = + let r1 = (a + b) + c + let r2 = a + (b + c) + + Assert.ApproximatelyEqual(r1, r2) + + [ |])>] + module Subtraction = + // + [] + let ``Vector3 subtraction is the same as component subtraction`` (a : Vector3, b : Vector3) = + let c = a - b + + Assert.Equal(a.X - b.X,c.X) + Assert.Equal(a.Y - b.Y,c.Y) + Assert.Equal(a.Z - b.Z,c.Z) + + [ |])>] + module Multiplication = + // + [] + let ``Vector3 multiplication is the same as component multiplication`` (a : Vector3, b : Vector3) = + let c = a * b + + Assert.Equal(a.X * b.X,c.X) + Assert.Equal(a.Y * b.Y,c.Y) + Assert.Equal(a.Z * b.Z,c.Z) + + [] + let ``Vector3 multiplication is commutative`` (a : Vector3, b : Vector3) = + let r1 = a * b + let r2 = b * a + + Assert.Equal(r1, r2) + + [] + let ``Vector3-float multiplication is the same as component-float multiplication`` (a : Vector3, f : float32) = + let r = a * f + + Assert.Equal(a.X * f,r.X) + Assert.Equal(a.Y * f,r.Y) + Assert.Equal(a.Z * f,r.Z) + + // Inverse direction + let r = f * a + Assert.Equal(a.X * f,r.X) + Assert.Equal(a.Y * f,r.Y) + Assert.Equal(a.Z * f,r.Z) + + [] + let ``Vector3-Matrix3 multiplication works`` (a : Matrix3, b : Vector3) = + let res = a*b + + let c1 = b.X * a.M11 + b.Y * a.M12 + b.Z * a.M13 + let c2 = b.X * a.M21 + b.Y * a.M22 + b.Z * a.M23 + let c3 = b.X * a.M31 + b.Y * a.M32 + b.Z * a.M33 + + let exp = Vector3(c1, c2, c3) + + Assert.Equal(exp, res) + + [ |])>] + module Division = + // + [] + let ``Vector3-float division is the same as component-float division`` (a : Vector3, f : float32) = + if not (approxEq f 0.0f) then // we don't support diving by zero. + let r = a / f + + Assert.ApproximatelyEqual(a.X / f,r.X) + Assert.ApproximatelyEqual(a.Y / f,r.Y) + Assert.ApproximatelyEqual(a.Z / f,r.Z) + + [ |])>] + module Negation = + // + [] + let ``Vector negation operator works`` (x, y, z) = + let v = Vector3(x, y, z) + let vNeg = -v + Assert.Equal(-x, vNeg.X) + Assert.Equal(-y, vNeg.Y) + Assert.Equal(-z, vNeg.Z) + + [ |])>] + module Equality = + // + [] + let ``Vector equality operator works`` (x, y, z) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(x, y, z) + let equality = v1 = v2 + + Assert.True(equality) + + [] + let ``Vector inequality operator works`` (x, y, z) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(x + (float32)1 , y + (float32)1, z + (float32)1) + let inequality = v1 <> v2 + + Assert.True(inequality) + + [] + let ``Vector equality method works`` (x, y, z) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(x, y, z) + let notVector = Matrix2() + + let equality = v1.Equals(v2) + let inequalityByOtherType = v1.Equals(notVector) + + Assert.True(equality) + Assert.False(inequalityByOtherType) + + [ |])>] + module Swizzling = + // + [] + let ``Vector swizzling works`` (x, y, z) = + let v = Vector3(x, y, z) + + let xyz = Vector3(x, y, z) + let xzy = Vector3(x, z, y) + let xy = Vector2(x, y) + let xz = Vector2(x, z) + + let yxz = Vector3(y, x, z) + let yzx = Vector3(y, z, x) + let yx = Vector2(y, x) + let yz = Vector2(y, z) + + let zxy = Vector3(z, x, y) + let zyx = Vector3(z, y, x) + let zx = Vector2(z, x) + let zy = Vector2(z, y) + + Assert.Equal(xyz, v); + Assert.Equal(xzy, v.Xzy); + Assert.Equal(xy, v.Xy); + Assert.Equal(xz, v.Xz); + + Assert.Equal(yxz, v.Yxz); + Assert.Equal(yzx, v.Yzx); + Assert.Equal(yx, v.Yx); + Assert.Equal(yz, v.Yz); + + Assert.Equal(zxy, v.Zxy); + Assert.Equal(zyx, v.Zyx); + Assert.Equal(zx, v.Zx); + Assert.Equal(zy, v.Zy); + + [ |])>] + module Interpolation = + // + [] + let ``Linear interpolation works`` (a : Vector3, b : Vector3, q) = + + let blend = q + + let rX = blend * (b.X - a.X) + a.X + let rY = blend * (b.Y - a.Y) + a.Y + let rZ = blend * (b.Z - a.Z) + a.Z + let vExp = Vector3(rX, rY, rZ) + + Assert.Equal(vExp, Vector3.Lerp(a, b, q)) + + let vRes = Vector3.Lerp(ref a, ref b, q) + Assert.Equal(vExp, vRes) + + [] + let ``Barycentric interpolation works`` (a : Vector3, b : Vector3, c : Vector3, u, v) = + + let r = a + u * (b - a) + v * (c - a) + + Assert.Equal(r, Vector3.BaryCentric(a, b, c, u, v)) + + let vRes = Vector3.BaryCentric(ref a, ref b, ref c, u, v) + Assert.Equal(r, vRes) + + [ |])>] + module ``Vector products`` = + // + [] + let ``Dot product works`` (a : Vector3, b : Vector3) = + let dot = a.X * b.X + a.Y * b.Y + a.Z * b.Z + + Assert.Equal(dot, Vector3.Dot(a, b)); + + let vRes = Vector3.Dot(ref a, ref b) + Assert.Equal(dot, vRes) + + [] + let ``Cross product works`` (a : Vector3, b : Vector3) = + let crossX = a.Y * b.Z - a.Z * b.Y + let crossY = a.Z * b.X - a.X * b.Z + let crossZ = a.X * b.Y - a.Y * b.X + let cross = Vector3(crossX, crossY, crossZ) + + Assert.Equal(cross, Vector3.Cross(a, b)); + + let vRes = Vector3.Cross(ref a, ref b) + Assert.Equal(cross, vRes) + + [ |])>] + module ``Component min and max`` = + // + [] + let ``Producing a new vector from the smallest components of given vectors works`` (x, y, z, u, w, q) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(u, w, q) + + let vMin = Vector3.ComponentMin(v1, v2) + + Assert.True(vMin.X <= v1.X) + Assert.True(vMin.X <= v2.X) + + Assert.True(vMin.Y <= v1.Y) + Assert.True(vMin.Y <= v2.Y) + + Assert.True(vMin.Z <= v1.Z) + Assert.True(vMin.Z <= v2.Z) + + [] + let ``Producing a new vector from the largest components of given vectors works`` (x, y, z, u, w, q) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(u, w, q) + + let vMax = Vector3.ComponentMax(v1, v2) + + Assert.True(vMax.X >= v1.X) + Assert.True(vMax.X >= v2.X) + + Assert.True(vMax.Y >= v1.Y) + Assert.True(vMax.Y >= v2.Y) + + Assert.True(vMax.Z >= v1.Z) + Assert.True(vMax.Z >= v2.Z) + + [] + let ``Producing a new vector from the smallest components of given vectors by reference works`` (x, y, z, u, w, q) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(u, w, q) + + let vMin = Vector3.ComponentMin(ref v1, ref v2) + + Assert.True(vMin.X <= v1.X) + Assert.True(vMin.X <= v2.X) + + Assert.True(vMin.Y <= v1.Y) + Assert.True(vMin.Y <= v2.Y) + + Assert.True(vMin.Z <= v1.Z) + Assert.True(vMin.Z <= v2.Z) + + [] + let ``Producing a new vector from the largest components of given vectors by reference works`` (x, y, z, u, w, q) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(u, w, q) + + let vMax = Vector3.ComponentMax(ref v1, ref v2) + + Assert.True(vMax.X >= v1.X) + Assert.True(vMax.X >= v2.X) + + Assert.True(vMax.Y >= v1.Y) + Assert.True(vMax.Y >= v2.Y) + + Assert.True(vMax.Z >= v1.Z) + Assert.True(vMax.Z >= v2.Z) + + [] + let ``Selecting the lesser of two vectors works`` (x, y, z, u, w, q) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(u, w, q) + + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared + + let vMin = Vector3.Min(v1, v2) + + if l1 < l2 then + let equalsFirst = vMin = v1 + Assert.True(equalsFirst) + else + let equalsLast = vMin = v2 + Assert.True(equalsLast) + + [] + let ``Selecting the greater of two vectors works`` (x, y, z, u, w, q) = + let v1 = Vector3(x, y, z) + let v2 = Vector3(u, w, q) + + let l1 = v1.LengthSquared + let l2 = v2.LengthSquared + + let vMin = Vector3.Max(v1, v2) + + if l1 >= l2 then + let equalsFirst = vMin = v1 + Assert.True(equalsFirst) + else + let equalsLast = vMin = v2 + Assert.True(equalsLast) + + [ |])>] + module Clamping = + // + [] + let ``Clamping one vector between two other vectors works`` (a : Vector3, b : Vector3, w : Vector3) = + let res = Vector3.Clamp(w, a, b) + + let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X + let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y + let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z + + Assert.Equal(expX, res.X) + Assert.Equal(expY, res.Y) + Assert.Equal(expZ, res.Z) + + [] + let ``Clamping one vector between two other vectors works by reference`` (a : Vector3, b : Vector3, w : Vector3) = + let res = Vector3.Clamp(ref w, ref a, ref b) + + let expX = if w.X < a.X then a.X else if w.X > b.X then b.X else w.X + let expY = if w.Y < a.Y then a.Y else if w.Y > b.Y then b.Y else w.Y + let expZ = if w.Z < a.Z then a.Z else if w.Z > b.Z then b.Z else w.Z + + Assert.Equal(expX, res.X) + Assert.Equal(expY, res.Y) + Assert.Equal(expZ, res.Z) \ No newline at end of file -- 2.7.4