using System;
using Geospatial;
using NUnit.Framework;
using Linq = System.Linq;
using System.Collections.Generic;
namespace UnitTests
{
[TestFixture]
public sealed class LocationCollectionTest // Needs to be public for the XmlSerializer test
{
private const double Delta = 0.000001;
[Test]
public void TestAdd()
{
var collection = new LocationCollection();
Assert.Throws<ArgumentNullException>(() => collection.Add(null));
var location = TestHelpers.CreateLocation(0, 0);
Assert.AreEqual(0, collection.Count);
collection.Add(location);
Assert.AreEqual(1, collection.Count);
// Make sure we can add the same Location more than once
collection.Add(location);
Assert.AreEqual(2, collection.Count);
// Make sure the compiler call to Add also works
var initialised = new LocationCollection
{
TestHelpers.CreateLocation(0, 0),
TestHelpers.CreateLocation(1, 1)
};
Assert.AreEqual(2, initialised.Count);
}
[Test]
public void TestClear()
{
var collection = new LocationCollection
{
TestHelpers.CreateLocation(0, 0),
TestHelpers.CreateLocation(1, 1)
};
Assert.AreEqual(2, collection.Count);
collection.Clear();
Assert.AreEqual(0, collection.Count);
// Make sure we can clear an empty collection
Assert.DoesNotThrow(() => collection.Clear());
}
[Test]
public void TestContains()
{
var location = TestHelpers.CreateLocation(0, 0);
var collection = new LocationCollection
{
location,
TestHelpers.CreateLocation(1, 1)
};
Assert.IsFalse(collection.Contains(null)); // Make sure it doesn't throw
Assert.IsFalse(collection.Contains(TestHelpers.CreateLocation(0, 1)));
Assert.IsFalse(collection.Contains(TestHelpers.CreateLocation(0, 0, 0))); // Test the Altitude!
Assert.IsTrue(collection.Contains(location));
// Check it finds the same location (even if it doesn't have the same reference)
Assert.IsTrue(collection.Contains(TestHelpers.CreateLocation(1, 1)));
}
[Test]
public void TestCopyTo()
{
const int ElementCount = 100;
var source = new LocationCollection();
for (int i = 0; i < ElementCount; i++)
{
source.Add(TestHelpers.CreateLocation(0, 0, 0));
}
var destination = new Location[ElementCount];
Assert.Throws<ArgumentNullException>(() => source.CopyTo(null, 0));
Assert.Throws<ArgumentOutOfRangeException>(() => source.CopyTo(destination, int.MinValue));
Assert.Throws<ArgumentOutOfRangeException>(() => source.CopyTo(destination, -1));
Assert.Throws<ArgumentException>(() => source.CopyTo(destination, int.MaxValue));
Assert.Throws<ArgumentException>(() => source.CopyTo(destination, ElementCount - 1));
Assert.Throws<ArgumentException>(() => source.CopyTo(destination, 1));
// Make sure it's not changed the destination yet
foreach (var element in destination)
{
Assert.IsNull(element);
}
source.CopyTo(destination, 0);
CompareCollections(source, destination);
}
[Test]
public void TestCountAndGetEnumerator()
{
var collection = new LocationCollection();
Assert.AreEqual(0, collection.Count);
// We use the Linq Select extension to force the ICollection into
// an IEnumerable, which disables the Count extension from 'optimizing'
// and using the ICollection.Count property. Effectivly, this forces
// an actual iteration of all the collection object (thus testing
// the GetEnumerator method).
//
// Also, fully qualify the Linq methods so we don't need a using
// directive and ensures that the other tests don't pick the
// the wrong method by accident.
Assert.AreEqual(0, Linq.Enumerable.Count(Linq.Enumerable.Select(collection, x => x)));
const int ElementCount = 100;
for (int i = 0; i < ElementCount; i++)
{
collection.Add(TestHelpers.CreateLocation(0, 0));
}
Assert.AreEqual(ElementCount, collection.Count);
Assert.AreEqual(ElementCount, Linq.Enumerable.Count(Linq.Enumerable.Select(collection, x => x)));
}
[Test]
public void TestRemove()
{
var location = TestHelpers.CreateLocation(0, 0);
var collection = new LocationCollection
{
location,
TestHelpers.CreateLocation(1, 1)
};
Assert.AreEqual(2, collection.Count);
Assert.IsFalse(collection.Remove(null)); // Make sure it doesn't throw
Assert.IsFalse(collection.Remove(TestHelpers.CreateLocation(0, 1)));
Assert.AreEqual(2, collection.Count); // Make sure it really hasn't changed
// Check it finds the same location (even if it doesn't have the same reference)
Assert.IsTrue(collection.Remove(TestHelpers.CreateLocation(1, 1)));
Assert.AreEqual(1, collection.Count);
Assert.IsFalse(collection.Remove(TestHelpers.CreateLocation(1, 1)));
Assert.AreEqual(1, collection.Count);
Assert.IsTrue(collection.Remove(location));
Assert.AreEqual(0, collection.Count);
}
[Test]
public void TestXmlSerialization()
{
var data = new XmlSerializerTestStruct
{
Collection = new LocationCollection
{
TestHelpers.CreateLocation(12, 34, 56),
TestHelpers.CreateLocation(12, 34),
TestHelpers.CreateLocation(12, -34, 56)
},
Name = "Test Data"
};
var deserialized = TestHelpers.Serialize(data);
Assert.AreEqual(data.Name, deserialized.Name);
CompareCollections(data.Collection, deserialized.Collection);
var empty = new LocationCollection();
CompareCollections(TestHelpers.Serialize(empty), empty);
}
// Can't use anonymous classes as they don't have a parameterless constructor
public struct XmlSerializerTestStruct
{
public LocationCollection Collection;
public string Name;
}
private void CompareCollections(IEnumerable<Location> first, IEnumerable<Location> second)
{
using (IEnumerator<Location> a = first.GetEnumerator(), b = second.GetEnumerator())
{
while (true)
{
if (a.MoveNext())
{
Assert.IsTrue(b.MoveNext());
TestHelpers.AssertLocationsAreEqual(a.Current, b.Current);
}
else
{
Assert.IsFalse(b.MoveNext());
break;
}
}
}
}
}
}