#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
using System;
using System.Collections;
using System.Collections.Generic;
#if UNITTEST
using NUnit.Framework;
using NMock2;
namespace Nuclex.Support.Collections {
/// Unit Test for the weak collection wrapper
[TestFixture]
public class WeakCollectionTest {
#region class Dummy
/// Dummy class used to test the weakly referencing collection
private class Dummy {
/// Initializes a new dummy
/// Value that will be stored by the dummy
public Dummy(int value) {
this.Value = value;
}
///
/// Determines whether the specified System.Object is equal to
/// the current Dummy object.
///
///
/// The System.Object to compare with the current Dummy object
///
///
/// True if the specified System.Object is equal to the current Dummy object;
/// otherwise, false.
///
public override bool Equals(object otherAsObject) {
Dummy other = otherAsObject as Dummy;
if(other == null) {
return false;
}
return this.Value.Equals(other.Value);
}
/// Serves as a hash function for a particular type.
/// A hash code for the current System.Object.
public override int GetHashCode() {
return this.Value.GetHashCode();
}
/// Some value that can be used for testing
public int Value;
}
#endregion // class Dummy
/// Verifies that the constructor of the weak collection is working
[Test]
public void TestConstructor() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Assert.IsNotNull(dummies);
}
///
/// Test whether the non-typesafe Add() method of the weak collection works
///
[Test]
public void TestAddAsObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(12345);
(dummies as IList).Add((object)oneTwoThreeDummy);
CollectionAssert.Contains(dummies, oneTwoThreeDummy);
}
///
/// Test whether the non-typesafe Add() method throws an exception if an object is
/// added that is not compatible to the collection's item type
///
[Test, ExpectedException(typeof(ArgumentException))]
public void TestThrowOnAddIncompatibleObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
(dummies as IList).Add(new object());
}
///
/// Test whether the generic Add() method of the weak collection works
///
[Test]
public void TestAdd() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(12345);
dummies.Add(oneTwoThreeDummy);
CollectionAssert.Contains(dummies, oneTwoThreeDummy);
}
/// Tests whether the Clear() method works
[Test]
public void TestClear() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(12345);
dummies.Add(oneTwoThreeDummy);
Dummy threeTwoOneDummy = new Dummy(54321);
dummies.Add(threeTwoOneDummy);
Assert.AreEqual(2, dummies.Count);
dummies.Clear();
Assert.AreEqual(0, dummies.Count);
}
/// Tests whether the Contains() method works
[Test]
public void TestContains() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(12345);
dummies.Add(oneTwoThreeDummy);
Dummy threeTwoOneDummy = new Dummy(54321);
Assert.IsTrue(dummies.Contains(oneTwoThreeDummy));
Assert.IsFalse(dummies.Contains(threeTwoOneDummy));
}
/// Tests whether the non-typesafe Contains() method works
[Test]
public void TestContainsWithObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(12345);
dummies.Add(oneTwoThreeDummy);
Dummy threeTwoOneDummy = new Dummy(54321);
Assert.IsTrue((dummies as IList).Contains((object)oneTwoThreeDummy));
Assert.IsFalse((dummies as IList).Contains((object)threeTwoOneDummy));
}
///
/// Verifies that the Enumerator of the dummy collection correctly
/// implements the Reset() method
///
[Test]
public void TestEnumeratorReset() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
IEnumerator dummyEnumerator = dummies.GetEnumerator();
Assert.IsTrue(dummyEnumerator.MoveNext());
Assert.IsTrue(dummyEnumerator.MoveNext());
Assert.IsFalse(dummyEnumerator.MoveNext());
dummyEnumerator.Reset();
Assert.IsTrue(dummyEnumerator.MoveNext());
Assert.IsTrue(dummyEnumerator.MoveNext());
Assert.IsFalse(dummyEnumerator.MoveNext());
}
/// Verifies that the IndexOf() method is working as intended
[Test]
public void TestIndexOf() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Dummy sevenEightNineDummy = new Dummy(789);
Assert.AreEqual(0, dummies.IndexOf(oneTwoThreeDummy));
Assert.AreEqual(1, dummies.IndexOf(fourFiveSixDummy));
Assert.AreEqual(-1, dummies.IndexOf(sevenEightNineDummy));
}
///
/// Verifies that the non-typesafe IndexOf() method is working as intended
///
[Test]
public void TestIndexOfWithObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Dummy sevenEightNineDummy = new Dummy(789);
Assert.AreEqual(0, (dummies as IList).IndexOf((object)oneTwoThreeDummy));
Assert.AreEqual(1, (dummies as IList).IndexOf((object)fourFiveSixDummy));
Assert.AreEqual(-1, (dummies as IList).IndexOf((object)sevenEightNineDummy));
}
///
/// Verifies that an exception is thrown if an incompatible object is passed to
/// the non-typesafe variant of the IndexOf() method
///
[Test, ExpectedException(typeof(ArgumentException))]
public void TestThrowOnIndexOfWithIncompatibleObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Assert.IsNull((dummies as IList).IndexOf(new object()));
}
/// Test whether the IndexOf() method can cope with null references
[Test]
public void TestIndexOfNull() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Assert.AreEqual(-1, dummies.IndexOf(null));
dummies.Add(null);
Assert.AreEqual(0, dummies.IndexOf(null));
}
///
/// Verifies that the CopyTo() method of the weak collection works
///
[Test]
public void TestCopyToArray() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Dummy[] inputDummies = new Dummy[] { oneTwoThreeDummy, fourFiveSixDummy };
Dummy[] outputDummies = new Dummy[dummies.Count];
dummies.CopyTo(outputDummies, 0);
CollectionAssert.AreEqual(inputDummies, outputDummies);
}
///
/// Verifies that the CopyTo() method of the weak collection throws an exception
/// if the target array is too small to hold the collection's contents
///
[Test, ExpectedException(typeof(ArgumentException))]
public void TestThrowOnCopyToTooSmallArray() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Dummy[] outputStrings = new Dummy[dummies.Count - 1];
dummies.CopyTo(outputStrings, 0);
}
///
/// Verifies that the CopyTo() method of the transforming read only collection
/// works if invoked via the ICollection interface
///
[Test]
public void TestCopyToArrayViaICollection() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Dummy[] inputDummies = new Dummy[] { oneTwoThreeDummy, fourFiveSixDummy };
Dummy[] outputDummies = new Dummy[dummies.Count];
(dummies as ICollection).CopyTo(outputDummies, 0);
CollectionAssert.AreEqual(inputDummies, outputDummies);
}
///
/// Verifies that the Insert() method correctly shifts items in the collection
///
[Test]
public void TestInsert() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Insert(0, fourFiveSixDummy);
Assert.AreEqual(2, dummies.Count);
Assert.AreSame(fourFiveSixDummy, dummies[0]);
Assert.AreSame(oneTwoThreeDummy, dummies[1]);
}
///
/// Verifies that the non-typesafe Insert() method correctly shifts items in
/// the collection
///
[Test]
public void TestInsertObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
(dummies as IList).Insert(0, (object)fourFiveSixDummy);
Assert.AreEqual(2, dummies.Count);
Assert.AreSame(fourFiveSixDummy, dummies[0]);
Assert.AreSame(oneTwoThreeDummy, dummies[1]);
}
///
/// Verifies that the non-typesafe Insert() method correctly shifts items in
/// the collection
///
[Test, ExpectedException(typeof(ArgumentException))]
public void TestThrowOnInsertIncompatibleObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
(dummies as IList).Insert(0, new object());
}
///
/// Checks whether the IsFixedSize property of the weak collection returns
/// the expected result for a weak collection based on a fixed array
///
[Test]
public void TestIsFixedSizeViaIList() {
Dummy oneTwoThreeDummy = new Dummy(123);
Dummy fourFiveSixDummy = new Dummy(456);
WeakReference[] dummyReferences = new WeakReference[] {
new WeakReference(oneTwoThreeDummy),
new WeakReference(fourFiveSixDummy)
};
WeakCollection dummies = new WeakCollection(dummyReferences);
Assert.IsTrue((dummies as IList).IsFixedSize);
}
///
/// Tests whether the IsReadOnly property of the weak collection works
///
[Test]
public void TestIsReadOnly() {
Dummy oneTwoThreeDummy = new Dummy(123);
Dummy fourFiveSixDummy = new Dummy(456);
List> dummyReferences = new List>();
dummyReferences.Add(new WeakReference(oneTwoThreeDummy));
dummyReferences.Add(new WeakReference(fourFiveSixDummy));
ReadOnlyList> readOnlyDummyReferences =
new ReadOnlyList>(dummyReferences);
WeakCollection dummies = new WeakCollection(dummyReferences);
WeakCollection readOnlydummies = new WeakCollection(
readOnlyDummyReferences
);
Assert.IsFalse(dummies.IsReadOnly);
Assert.IsTrue(readOnlydummies.IsReadOnly);
}
///
/// Tests whether the IsSynchronized property of the weak collection works
///
[Test]
public void TestIsSynchronized() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Assert.IsFalse((dummies as IList).IsSynchronized);
}
/// Tests the indexer of the weak collection
[Test]
public void TestIndexer() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Assert.AreSame(oneTwoThreeDummy, dummies[0]);
Assert.AreSame(fourFiveSixDummy, dummies[1]);
dummies[0] = fourFiveSixDummy;
Assert.AreSame(fourFiveSixDummy, dummies[0]);
}
/// Tests the non-typesafe indexer of the weak collection
[Test]
public void TestIndexerWithObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Assert.AreSame((object)oneTwoThreeDummy, (dummies as IList)[0]);
Assert.AreSame((object)fourFiveSixDummy, (dummies as IList)[1]);
(dummies as IList)[0] = (object)fourFiveSixDummy;
Assert.AreSame((object)fourFiveSixDummy, (dummies as IList)[0]);
}
///
/// Tests whether the non-typesafe indexer of the weak collection throws
/// the correct exception if an incompatible object is assigned
///
[Test, ExpectedException(typeof(ArgumentException))]
public void TestThrowOnIndexerWithIncompatibleObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
(dummies as IList)[0] = new object();
}
/// Tests the Remove() method of the weak collection
[Test]
public void TestRemove() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Assert.AreEqual(2, dummies.Count);
Assert.IsTrue(dummies.Remove(oneTwoThreeDummy));
Assert.AreEqual(1, dummies.Count);
Assert.IsFalse(dummies.Remove(oneTwoThreeDummy));
}
/// Tests the non-typesafe Remove() method of the weak collection
[Test]
public void TestRemoveObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Assert.AreEqual(2, dummies.Count);
(dummies as IList).Remove((object)oneTwoThreeDummy);
Assert.AreEqual(1, dummies.Count);
}
///
/// Tests whether a null object can be managed by and removed from the weak collection
///
[Test]
public void TestRemoveNull() {
WeakCollection dummies = new WeakCollection(
new List>()
);
dummies.Add(null);
Assert.AreEqual(1, dummies.Count);
Assert.IsTrue(dummies.Remove(null));
Assert.AreEqual(0, dummies.Count);
}
///
/// Tests whether the non-typesafe Remove() method of the weak collection throws
/// an exception if an object is tried to be removed that is incompatible with
/// the collection's item type
///
[Test, ExpectedException(typeof(ArgumentException))]
public void TestThrowOnRemoveIncompatibleObject() {
WeakCollection dummies = new WeakCollection(
new List>()
);
(dummies as IList).Remove(new object());
}
/// Tests the RemoveAt() method of the weak collection
[Test]
public void TestRemoveAt() {
WeakCollection dummies = new WeakCollection(
new List>()
);
Dummy oneTwoThreeDummy = new Dummy(123);
dummies.Add(oneTwoThreeDummy);
Dummy fourFiveSixDummy = new Dummy(456);
dummies.Add(fourFiveSixDummy);
Assert.AreSame(oneTwoThreeDummy, dummies[0]);
dummies.RemoveAt(0);
Assert.AreSame(fourFiveSixDummy, dummies[0]);
}
///
/// Verifies that the IsSynchronized property and the SyncRoot property are working
///
[Test]
public void TestSynchronization() {
WeakCollection dummies = new WeakCollection(
new List>()
);
if(!(dummies as ICollection).IsSynchronized) {
lock((dummies as ICollection).SyncRoot) {
Assert.AreEqual(0, dummies.Count);
}
}
}
private class ListWithoutICollection : IList> {
public int IndexOf(WeakReference item) { throw new NotImplementedException(); }
public void Insert(int index, WeakReference item) {
throw new NotImplementedException();
}
public void RemoveAt(int index) { throw new NotImplementedException(); }
public WeakReference this[int index] {
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public void Add(WeakReference item) { throw new NotImplementedException(); }
public void Clear() { throw new NotImplementedException(); }
public bool Contains(WeakReference item) { throw new NotImplementedException(); }
public void CopyTo(WeakReference[] array, int arrayIndex) {
throw new NotImplementedException();
}
public int Count { get { return 12345; } }
public bool IsReadOnly { get { throw new NotImplementedException(); } }
public bool Remove(WeakReference item) { throw new NotImplementedException(); }
public IEnumerator> GetEnumerator() {
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
}
///
/// Verifies that the IsSynchronized property and the SyncRoot property are working
/// on transforming read only collections based on IList<>s that do not
/// implement the ICollection interface
///
[Test]
public void TestSynchronizationOfIListWithoutICollection() {
WeakCollection dummies = new WeakCollection(
new ListWithoutICollection()
);
if(!(dummies as ICollection).IsSynchronized) {
lock((dummies as ICollection).SyncRoot) {
int count = dummies.Count;
Assert.AreEqual(12345, count); // ;-)
}
}
}
/// Tests the RemoveDeadItems() method
[Test]
public void TestRemoveDeadItems() {
List> dummyReferences = new List>();
Dummy oneTwoThreeDummy = new Dummy(123);
dummyReferences.Add(new WeakReference(oneTwoThreeDummy));
dummyReferences.Add(new WeakReference(null));
Dummy fourFiveSixDummy = new Dummy(456);
dummyReferences.Add(new WeakReference(fourFiveSixDummy));
WeakCollection dummies = new WeakCollection(dummyReferences);
Assert.AreEqual(3, dummies.Count);
dummies.RemoveDeadItems();
Assert.AreEqual(2, dummies.Count);
Assert.AreSame(oneTwoThreeDummy, dummies[0]);
Assert.AreSame(fourFiveSixDummy, dummies[1]);
}
}
} // namespace Nuclex.Support.Collections
#endif // UNITTEST