#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2011 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;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using NUnit.Framework;
namespace Nuclex.Game.Serialization {
/// Ensures that the binary serializer is working correctly
[TestFixture]
internal class BinarySerializerTest {
#region class TestSerializable
/// Serializable class used to test the serialization code
private class TestSerializable : IBinarySerializable {
/// Loads the state of the object from binary data
/// Reader containing the binary state of the object
public void Load(BinaryReader reader) { this.Dummy = reader.ReadInt32(); }
/// Saves the state of the object as binary data
///
/// Writer into which the binary state of the object will be written
///
public void Save(BinaryWriter writer) { writer.Write(this.Dummy); }
/// Serialized value representing the state of this object
public int Dummy;
}
#endregion // class TestSerializable
#region class CurveComparer
/// Compares two curves against each other
private class CurveComparer : IComparer, IComparer {
/// Initializes a new curve comparer
private CurveComparer() { }
/// The one and only instance of the curve comparer
public static CurveComparer Instance {
get { return instance; }
}
/// Compares two curves against each other
/// Compared curve in the left side
/// Compared curve on the right side
/// The relation of the provided curves to each other
public int Compare(Curve left, Curve right) {
// Compare IsConstant flag (bool)
if(left.IsConstant != right.IsConstant) {
if(left.IsConstant) {
return -1;
} else {
return 1;
}
}
// Compare PreLoop (enum)
int preLoopDifference = (int)right.PreLoop - (int)left.PreLoop;
if(preLoopDifference != 0) {
return preLoopDifference;
}
// Compare keys (collection)
int keysDifference = compareKeys(left.Keys, right.Keys);
if(keysDifference != 0) {
return keysDifference;
}
// Compare PostLoop (enum)
int postLoopDifference = (int)right.PostLoop - (int)left.PostLoop;
if(postLoopDifference != 0) {
return postLoopDifference;
}
return 0;
}
/// Compares two curves against each other
/// Compared curve in the left side
/// Compared curve on the right side
/// The relation of the provided curves to each other
public int Compare(object left, object right) {
if(!(left is Curve)) {
throw new ArgumentException("Left argument is not a curve", "left");
}
if(!(right is Curve)) {
throw new ArgumentException("Right argument is not a curve", "right");
}
return Compare((Curve)left, (Curve)right);
}
/// Compares the key collections of two curves against each other
/// Keys in the key collection to the left side
/// Keys in the key collection to the right side
/// The rleation of the two provided key collections to each other
private int compareKeys(CurveKeyCollection leftKeys, CurveKeyCollection rightKeys) {
// Compare number of keys (int)
int keyCountDifference = (int)rightKeys.Count - (int)leftKeys.Count;
if(keyCountDifference != 0) {
return keyCountDifference;
}
for(int index = 0; index < leftKeys.Count; ++index) {
// Compare Continuity (enum)
int continuityDifference =
(int)rightKeys[index].Continuity - (int)leftKeys[index].Continuity;
if(continuityDifference != 0) {
return continuityDifference;
}
// Compare TangentIn (float)
if(leftKeys[index].TangentIn > rightKeys[index].TangentIn) {
return +1;
} else if(leftKeys[index].TangentIn < rightKeys[index].TangentIn) {
return -1;
}
// Compare Position (float)
if(leftKeys[index].Position > rightKeys[index].Position) {
return +1;
} else if(leftKeys[index].Position < rightKeys[index].Position) {
return -1;
}
// Compare Value (float)
if(leftKeys[index].Value > rightKeys[index].Value) {
return +1;
} else if(leftKeys[index].Value < rightKeys[index].Value) {
return -1;
}
// Compare TangentOut (float)
if(leftKeys[index].TangentOut > rightKeys[index].TangentOut) {
return +1;
} else if(leftKeys[index].TangentOut < rightKeys[index].TangentOut) {
return -1;
}
}
// No differences found
return 0;
}
/// The one and only instance of the curve comparer
private static CurveComparer instance = new CurveComparer();
}
#endregion // class CurveComparer
///
/// Tests wether a simple collection can be successfully saved and loaded again
///
[Test]
public void TestSimpleCollection() {
MemoryStream buffer = new MemoryStream();
// Fill and save
{
List serializables = new List();
serializables.Add(new TestSerializable());
serializables.Add(new TestSerializable());
serializables[0].Dummy = 123;
serializables[1].Dummy = 456;
BinarySerializer.SaveCollection(new BinaryWriter(buffer), serializables);
buffer.Position = 0;
}
// Load and validate
{
List serializables = new List();
BinarySerializer.LoadCollection(new BinaryReader(buffer), serializables);
Assert.AreEqual(2, serializables.Count);
Assert.AreEqual(123, serializables[0].Dummy);
Assert.AreEqual(456, serializables[1].Dummy);
}
}
///
/// Verifies that matrices can be serialized and restored again
///
[Test]
public void TestMatrixSerialization() {
MemoryStream buffer = new MemoryStream();
Matrix testMatrix = new Matrix(
1.1f, 1.2f, 1.3f, 1.4f,
2.1f, 2.2f, 2.3f, 2.4f,
3.1f, 3.2f, 3.3f, 3.4f,
4.1f, 4.2f, 4.3f, 4.4f
);
// Save
{
BinarySerializer.Save(new BinaryWriter(buffer), ref testMatrix);
buffer.Position = 0;
}
// Load and validate
{
Matrix loadedMatrix;
BinarySerializer.Load(new BinaryReader(buffer), out loadedMatrix);
Assert.AreEqual(testMatrix, loadedMatrix);
}
}
///
/// Verifies that a Vector2 can be serialized and restored again
///
[Test]
public void TestVector2Serialization() {
MemoryStream buffer = new MemoryStream();
Vector2 testVector = new Vector2(1.1f, 2.2f);
// Save
{
BinarySerializer.Save(new BinaryWriter(buffer), ref testVector);
buffer.Position = 0;
}
// Load and validate
{
Vector2 loadedVector;
BinarySerializer.Load(new BinaryReader(buffer), out loadedVector);
Assert.AreEqual(testVector, loadedVector);
}
}
///
/// Verifies that a Vector3 can be serialized and restored again
///
[Test]
public void TestVector3Serialization() {
MemoryStream buffer = new MemoryStream();
Vector3 testVector = new Vector3(1.1f, 2.2f, 3.3f);
// Save
{
BinarySerializer.Save(new BinaryWriter(buffer), ref testVector);
buffer.Position = 0;
}
// Load and validate
{
Vector3 loadedVector;
BinarySerializer.Load(new BinaryReader(buffer), out loadedVector);
Assert.AreEqual(testVector, loadedVector);
}
}
///
/// Verifies that a Vector4 can be serialized and restored again
///
[Test]
public void TestVector4Serialization() {
MemoryStream buffer = new MemoryStream();
Vector4 testVector = new Vector4(1.1f, 2.2f, 3.3f, 4.4f);
// Save
{
BinarySerializer.Save(new BinaryWriter(buffer), ref testVector);
buffer.Position = 0;
}
// Load and validate
{
Vector4 loadedVector;
BinarySerializer.Load(new BinaryReader(buffer), out loadedVector);
Assert.AreEqual(testVector, loadedVector);
}
}
///
/// Verifies that a quaternion can be serialized and restored again
///
[Test]
public void TestQuaternionSerialization() {
MemoryStream buffer = new MemoryStream();
Quaternion testQuaternion = new Quaternion(1.1f, 2.2f, 3.3f, 4.4f);
// Save
{
BinarySerializer.Save(new BinaryWriter(buffer), ref testQuaternion);
buffer.Position = 0;
}
// Load and validate
{
Quaternion loadedQuaternion;
BinarySerializer.Load(new BinaryReader(buffer), out loadedQuaternion);
Assert.AreEqual(testQuaternion, loadedQuaternion);
}
}
///
/// Verifies that a curve can be serialized and restored again
///
[Test]
public void TestCurveSerialization() {
MemoryStream buffer = new MemoryStream();
Curve testCurve = new Curve();
testCurve.PreLoop = CurveLoopType.Cycle;
testCurve.PostLoop = CurveLoopType.Oscillate;
testCurve.Keys.Add(new CurveKey(1.2f, 3.4f, 5.6f, 7.8f));
testCurve.Keys[0].Continuity = CurveContinuity.Smooth;
testCurve.Keys.Add(new CurveKey(8.7f, 6.5f, 4.3f, 2.1f));
testCurve.Keys[1].Continuity = CurveContinuity.Step;
// Save
{
BinarySerializer.Save(new BinaryWriter(buffer), testCurve);
buffer.Position = 0;
}
// Load and validate
{
Curve loadedCurve = new Curve();
BinarySerializer.Load(new BinaryReader(buffer), loadedCurve);
Assert.That(
testCurve, Is.EqualTo(loadedCurve).Using(CurveComparer.Instance)
);
}
}
}
} // namespace Nuclex.Game.Serialization
#endif // UNITTEST