#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2009 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
#if UNITTEST
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using NUnit.Framework;
namespace Nuclex.Graphics {
/// Unit tests for the vertex element attribute
[TestFixture]
internal class VertexDeclarationHelperTest {
#region struct TestVertex
///
/// A vertex used to unit-test the format auto-detection of
/// the vertex declaration helper
///
private struct TestVertex {
/// A vertex element of type Vector2
[VertexElement(VertexElementUsage.TextureCoordinate)]
public Vector2 TestVector2;
/// A vertex element of type Vector3
[VertexElement(VertexElementUsage.Position)]
public Vector3 TestVector3;
/// A vertex element of type Vector4
[VertexElement(VertexElementUsage.Normal)]
public Vector4 TestVector4;
/// A vertex element of type Color
[VertexElement(VertexElementUsage.Color)]
public Color TestColor;
/// A vertex element of type float
[VertexElement(VertexElementUsage.BlendWeight)]
public float TestSingle;
/// A vertex element of type int
[VertexElement(VertexElementUsage.Sample)]
public int TestInt;
/// A vertex element of type short
[VertexElement(VertexElementUsage.Sample, UsageIndex = 1)]
public short TestShort;
/// A vertex element of type short
[VertexElement(VertexElementUsage.BlendWeight, VertexElementFormat.Vector4)]
public Matrix TestExplicitMatrix;
}
#endregion // struct TestVertex
#region struct UnknownTypeVertex
///
/// A vertex containing a data type not recognized by the format auto-detection of
/// the vertex declaration helper
///
private struct UnknownTypeVertex {
/// A vertex element of type DateTime
[VertexElement(VertexElementUsage.Sample, UsageIndex = 1)]
public DateTime TestTimestamp;
}
#endregion // struct UnknownTypeVertex
#region struct EmptyVertex
/// An empty vertex type used to unit-test error behavior
private struct EmptyVertex { }
#endregion // struct EmptyVertex
#region struct UnattributedFieldVertex
///
/// A vertex type containing a field without a vertex element attribute
///
private struct UnattributedFieldVertex {
/// A vertex element of type Vector3
public Vector3 TestVector3;
/// A vertex element of type Color
public Color TestColor;
}
#endregion // struct UnattributedFieldVertex
#region struct SecondStreamVertex
///
/// A vertex containing an additional data element to be used as second vertex stream
///
private struct SecondStreamVertex {
/// A vertex element of type DateTime
[VertexElement(VertexElementUsage.BlendWeight, UsageIndex = 1)]
public float BlendWeight;
}
#endregion // struct SecondStreamVertex
#region struct GapVertex
///
/// A vertex in which not all elements are used by the shader
///
private struct GapVertex {
/// Position of the vertex
[VertexElement(VertexElementUsage.Position)]
public Vector3 Position;
/// Velocity the vertex is moving at
public Vector3 Velocity;
/// Size of the vertex when rendered as a point sprite
[VertexElement(VertexElementUsage.PointSize)]
public float Size;
}
#endregion // struct GapVertex
///
/// Verifies that the stride of a vertex structure can be determined
///
[Test]
public void TestStrideDetermination() {
Assert.AreEqual(114, VertexDeclarationHelper.GetStride());
Assert.AreEqual(4, VertexDeclarationHelper.GetStride());
}
///
/// Tests whether the vertex declaration helper fails is provieed with two
/// null references instead of two vertex element lists
///
[Test]
public void TestThrowOnCombineNull() {
Assert.Throws(
delegate() { VertexDeclarationHelper.Combine(null, null); }
);
}
///
/// Tests whether the vertex declaration helper is able to combine two vertex element
/// lists into a single one
///
[Test]
public void TestCombine() {
VertexElement[] firstElements = VertexDeclarationHelper.BuildElementList();
VertexElement[] secondElements = VertexDeclarationHelper.BuildElementList<
SecondStreamVertex
>();
VertexElement[] combinedElements =
VertexDeclarationHelper.Combine(firstElements, secondElements);
Assert.AreEqual(firstElements.Length + secondElements.Length, combinedElements.Length);
CollectionAssert.IsSubsetOf(firstElements, combinedElements);
CollectionAssert.IsSubsetOf(secondElements, combinedElements);
}
///
/// Tests whether the vertex declaration helper fails on empty vertices
///
[Test]
public void TestThrowOnEmptyVertex() {
Assert.Throws(
delegate() {
VertexElement[] elements = VertexDeclarationHelper.BuildElementList();
}
);
}
///
/// Tests whether the vertex declaration helper fails when format auto-detection
/// is used on unknown data types
///
[Test]
public void TestThrowOnUnknownTypeVertex() {
Assert.Throws(
delegate() {
VertexElement[] elements = VertexDeclarationHelper.BuildElementList<
UnknownTypeVertex
>();
}
);
}
///
/// Tests whether the vertex declaration helper fails when no field of
/// a Vertex has have the vertex element attribute assigned to it
///
[Test]
public void TestThrowOnUnattributedFieldVertex() {
Assert.Throws(
delegate() {
VertexElement[] elements = VertexDeclarationHelper.BuildElementList<
UnattributedFieldVertex
>();
}
);
}
/// Tests the format auto-detection of vertex elements
[Test]
public void TestFormatAutoDetection() {
VertexElement[] elements = VertexDeclarationHelper.BuildElementList();
Assert.AreEqual(8, elements.Length);
Assert.AreEqual(VertexElementFormat.Vector2, elements[0].VertexElementFormat);
Assert.AreEqual(VertexElementFormat.Vector3, elements[1].VertexElementFormat);
Assert.AreEqual(VertexElementFormat.Vector4, elements[2].VertexElementFormat);
Assert.AreEqual(VertexElementFormat.Color, elements[3].VertexElementFormat);
Assert.AreEqual(VertexElementFormat.Single, elements[4].VertexElementFormat);
Assert.AreEqual(VertexElementFormat.Short4, elements[5].VertexElementFormat);
Assert.AreEqual(VertexElementFormat.Short2, elements[6].VertexElementFormat);
Assert.AreEqual(VertexElementFormat.Vector4, elements[7].VertexElementFormat);
Assert.AreEqual(1, elements[6].UsageIndex);
}
///
/// Tests whether a vertex containing a field in its middle that isn't seen by
/// the vertex shader is processed correctly
///
[Test]
public void TestGapVertexElements() {
VertexElement[] elements = VertexDeclarationHelper.BuildElementList();
Assert.AreEqual(2, elements.Length);
Assert.Greater(elements[1].Offset, elements[0].Offset);
}
///
/// Only serves to satisfy the compiler. Otherwise, warning CS0414 would occur
/// since the fields of the private vertex structures are never assigned to
///
protected void EliminateCompilerWarnings() {
TestVertex testVertex;
testVertex.TestVector2 = Vector2.Zero;
testVertex.TestVector3 = Vector3.Zero;
testVertex.TestVector4 = Vector4.Zero;
testVertex.TestColor = Color.White;
testVertex.TestSingle = 0.0f;
testVertex.TestInt = 0;
testVertex.TestShort = 0;
testVertex.TestExplicitMatrix = Matrix.Identity;
UnknownTypeVertex unknownTypeVertex;
unknownTypeVertex.TestTimestamp = DateTime.MinValue;
UnattributedFieldVertex unattributedFieldVertex;
unattributedFieldVertex.TestVector3 = Vector3.Zero;
unattributedFieldVertex.TestColor = Color.White;
SecondStreamVertex secondStreamVertex;
secondStreamVertex.BlendWeight = 0.0f;
GapVertex gapVertex;
gapVertex.Position = Vector3.Zero;
gapVertex.Velocity = Vector3.Zero;
gapVertex.Size = 0.0f;
}
}
} // namespace Nuclex.Graphics
#endif // UNITTEST