Moved all unit test files into a separate directory in preparation for splitting the project
This commit is contained in:
parent
28b96fd557
commit
ba5234f701
58 changed files with 0 additions and 853 deletions
52
Tests/Collections/ConstantsTest.cs
Normal file
52
Tests/Collections/ConstantsTest.cs
Normal file
|
@ -0,0 +1,52 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the collection constants</summary>
|
||||
[TestFixture]
|
||||
internal class ConstantsTest {
|
||||
|
||||
#if !NO_SPECIALIZED_COLLECTIONS
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the collection reset event arguments have 'reset' specified as
|
||||
/// their action
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CollectionResetEventArgsHaveResetActionSet() {
|
||||
Assert.AreEqual(
|
||||
NotifyCollectionChangedAction.Reset, Constants.NotifyCollectionResetEventArgs.Action
|
||||
);
|
||||
}
|
||||
|
||||
#endif // !NO_SPECIALIZED_COLLECTIONS
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
710
Tests/Collections/DequeTest.cs
Normal file
710
Tests/Collections/DequeTest.cs
Normal file
|
@ -0,0 +1,710 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the double ended queue</summary>
|
||||
[TestFixture]
|
||||
internal class DequeTest {
|
||||
|
||||
/// <summary>Verifies that the AddLast() method of the deque is working</summary>
|
||||
[Test]
|
||||
public void TestAddLast() {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 0; item < 48; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
|
||||
for(int item = 0; item < 48; ++item) {
|
||||
Assert.AreEqual(item, intDeque[item]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the AddFirst() method of the deque is working</summary>
|
||||
[Test]
|
||||
public void TestAddFirst() {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 0; item < 48; ++item) {
|
||||
intDeque.AddFirst(item);
|
||||
}
|
||||
|
||||
for(int item = 0; item < 48; ++item) {
|
||||
Assert.AreEqual(47 - item, intDeque[item]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the RemoveFirst() method of the deque is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveFirst() {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 0; item < 48; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
|
||||
for(int item = 0; item < 48; ++item) {
|
||||
Assert.AreEqual(item, intDeque.First);
|
||||
Assert.AreEqual(48 - item, intDeque.Count);
|
||||
intDeque.RemoveFirst();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the RemoveLast() method of the deque is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveLast() {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 0; item < 48; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
|
||||
for(int item = 0; item < 48; ++item) {
|
||||
Assert.AreEqual(47 - item, intDeque.Last);
|
||||
Assert.AreEqual(48 - item, intDeque.Count);
|
||||
intDeque.RemoveLast();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the Insert() method works in all cases</summary>
|
||||
/// <remarks>
|
||||
/// We have several different cases here that will be tested. The deque can
|
||||
/// shift items to the left or right (depending on which end is closer to
|
||||
/// the insertion point) and the insertion point may fall in an only partially
|
||||
/// occupied block, requiring elaborate index calculations
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void TestInsert() {
|
||||
for(int testedIndex = 0; testedIndex <= 96; ++testedIndex) {
|
||||
Deque<int> intDeque = createDeque(96);
|
||||
|
||||
intDeque.Insert(testedIndex, 12345);
|
||||
|
||||
Assert.AreEqual(97, intDeque.Count);
|
||||
|
||||
for(int index = 0; index < testedIndex; ++index) {
|
||||
Assert.AreEqual(index, intDeque[index]);
|
||||
}
|
||||
Assert.AreEqual(12345, intDeque[testedIndex]);
|
||||
for(int index = testedIndex + 1; index < 97; ++index) {
|
||||
Assert.AreEqual(index - 1, intDeque[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Insert() method works in all cases when the deque doesn't
|
||||
/// start at a block boundary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInsertNonNormalized() {
|
||||
for(int testedIndex = 0; testedIndex <= 96; ++testedIndex) {
|
||||
Deque<int> intDeque = createNonNormalizedDeque(96);
|
||||
|
||||
intDeque.Insert(testedIndex, 12345);
|
||||
|
||||
Assert.AreEqual(97, intDeque.Count);
|
||||
|
||||
for(int index = 0; index < testedIndex; ++index) {
|
||||
Assert.AreEqual(index, intDeque[index]);
|
||||
}
|
||||
Assert.AreEqual(12345, intDeque[testedIndex]);
|
||||
for(int index = testedIndex + 1; index < 97; ++index) {
|
||||
Assert.AreEqual(index - 1, intDeque[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies the the RemoveAt() method works in all cases</summary>
|
||||
[Test]
|
||||
public void TestRemoveAt() {
|
||||
for(int testedIndex = 0; testedIndex < 96; ++testedIndex) {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 0; item < 96; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
|
||||
intDeque.RemoveAt(testedIndex);
|
||||
|
||||
Assert.AreEqual(95, intDeque.Count);
|
||||
|
||||
for(int index = 0; index < testedIndex; ++index) {
|
||||
Assert.AreEqual(index, intDeque[index]);
|
||||
}
|
||||
for(int index = testedIndex; index < 95; ++index) {
|
||||
Assert.AreEqual(index + 1, intDeque[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the the RemoveAt() method works in all cases when the deque doesn't
|
||||
/// start at a block boundary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveAtNonNormalized() {
|
||||
for(int testedIndex = 0; testedIndex < 96; ++testedIndex) {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 4; item < 96; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
intDeque.AddFirst(3);
|
||||
intDeque.AddFirst(2);
|
||||
intDeque.AddFirst(1);
|
||||
intDeque.AddFirst(0);
|
||||
|
||||
intDeque.RemoveAt(testedIndex);
|
||||
|
||||
Assert.AreEqual(95, intDeque.Count);
|
||||
|
||||
for(int index = 0; index < testedIndex; ++index) {
|
||||
Assert.AreEqual(index, intDeque[index]);
|
||||
}
|
||||
for(int index = testedIndex; index < 95; ++index) {
|
||||
Assert.AreEqual(index + 1, intDeque[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the RemoveAt() method keeps the state of the deque intact when
|
||||
/// it has to remove a block from the left end of the deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveAtEmptiesLeftBlock() {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 1; item <= 16; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
intDeque.AddFirst(0);
|
||||
intDeque.RemoveAt(3);
|
||||
|
||||
Assert.AreEqual(16, intDeque.Count);
|
||||
|
||||
for(int index = 0; index < 3; ++index) {
|
||||
Assert.AreEqual(index, intDeque[index]);
|
||||
}
|
||||
for(int index = 3; index < 16; ++index) {
|
||||
Assert.AreEqual(index + 1, intDeque[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the RemoveAt() method keeps the state of the deque intact when
|
||||
/// it has to remove a block from the right end of the deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveAtEmptiesRightBlock() {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 0; item <= 16; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
intDeque.RemoveAt(13);
|
||||
|
||||
Assert.AreEqual(16, intDeque.Count);
|
||||
|
||||
for(int index = 0; index < 13; ++index) {
|
||||
Assert.AreEqual(index, intDeque[index]);
|
||||
}
|
||||
for(int index = 13; index < 16; ++index) {
|
||||
Assert.AreEqual(index + 1, intDeque[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that an exception is thrown if the 'First' property is accessed
|
||||
/// in an empty deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAccessFirstInEmptyDeque() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { Console.WriteLine(intDeque.First); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that an exception is thrown if the 'Last' property is accessed
|
||||
/// in an empty deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAccessLastInEmptyDeque() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { Console.WriteLine(intDeque.Last); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that an exception is thrown if the first item is attempted to be
|
||||
/// removed from an empty deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveFirstFromEmptyDeque() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { intDeque.RemoveFirst(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that an exception is thrown if the last item is attempted to be
|
||||
/// removed from an empty deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveLastFromEmptyDeque() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { intDeque.RemoveLast(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that items can be assigned by their index
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIndexAssignment() {
|
||||
Deque<int> intDeque = createDeque(32);
|
||||
intDeque[16] = 12345;
|
||||
intDeque[17] = 54321;
|
||||
|
||||
for(int index = 0; index < 16; ++index) {
|
||||
intDeque.RemoveFirst();
|
||||
}
|
||||
|
||||
Assert.AreEqual(12345, intDeque.First);
|
||||
intDeque.RemoveFirst();
|
||||
Assert.AreEqual(54321, intDeque.First);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown if an invalid index is accessed
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnInvalidIndex() {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 0; item < 32; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
|
||||
Assert.Throws<ArgumentOutOfRangeException>(
|
||||
delegate() { Console.WriteLine(intDeque[32]); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests the IndexOf() method</summary>
|
||||
[Test, TestCase(0), TestCase(16), TestCase(32), TestCase(48)]
|
||||
public void TestIndexOf(int count) {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
for(int item = 0; item < count; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
|
||||
for(int item = 0; item < count; ++item) {
|
||||
Assert.AreEqual(item, intDeque.IndexOf(item));
|
||||
}
|
||||
Assert.AreEqual(-1, intDeque.IndexOf(count));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the IndexOf() method with the deque not starting at a block boundary
|
||||
/// </summary>
|
||||
[Test, TestCase(0), TestCase(16), TestCase(32), TestCase(48)]
|
||||
public void TestIndexOfNonNormalized(int count) {
|
||||
Deque<int> intDeque = createNonNormalizedDeque(count);
|
||||
|
||||
for(int item = 0; item < count; ++item) {
|
||||
Assert.AreEqual(item, intDeque.IndexOf(item));
|
||||
}
|
||||
Assert.AreEqual(-1, intDeque.IndexOf(count));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the deque's enumerator works</summary>
|
||||
[Test]
|
||||
public void TestEnumerator() {
|
||||
Deque<int> intDeque = createNonNormalizedDeque(40);
|
||||
|
||||
for(int testRun = 0; testRun < 2; ++testRun) {
|
||||
using(IEnumerator<int> enumerator = intDeque.GetEnumerator()) {
|
||||
for(int index = 0; index < intDeque.Count; ++index) {
|
||||
Assert.IsTrue(enumerator.MoveNext());
|
||||
Assert.AreEqual(index, enumerator.Current);
|
||||
}
|
||||
|
||||
Assert.IsFalse(enumerator.MoveNext());
|
||||
|
||||
enumerator.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the deque's enumerator works</summary>
|
||||
[Test]
|
||||
public void TestObjectEnumerator() {
|
||||
Deque<int> intDeque = createNonNormalizedDeque(40);
|
||||
|
||||
for(int testRun = 0; testRun < 2; ++testRun) {
|
||||
IEnumerator enumerator = ((IEnumerable)intDeque).GetEnumerator();
|
||||
for(int index = 0; index < intDeque.Count; ++index) {
|
||||
Assert.IsTrue(enumerator.MoveNext());
|
||||
Assert.AreEqual(index, enumerator.Current);
|
||||
}
|
||||
|
||||
Assert.IsFalse(enumerator.MoveNext());
|
||||
|
||||
enumerator.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown if the enumerator is accessed in
|
||||
/// an invalid position
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnInvalidEnumeratorPosition() {
|
||||
Deque<int> intDeque = createNonNormalizedDeque(40);
|
||||
|
||||
using(IEnumerator<int> enumerator = intDeque.GetEnumerator()) {
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { Console.WriteLine(enumerator.Current); }
|
||||
);
|
||||
|
||||
while(enumerator.MoveNext()) { }
|
||||
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { Console.WriteLine(enumerator.Current); }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Tests whether a small deque can be cleared</summary>
|
||||
[Test]
|
||||
public void TestClearSmallDeque() {
|
||||
Deque<int> intDeque = createDeque(12);
|
||||
intDeque.Clear();
|
||||
Assert.AreEqual(0, intDeque.Count);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether a large deque can be cleared</summary>
|
||||
[Test]
|
||||
public void TestClearLargeDeque() {
|
||||
Deque<int> intDeque = createDeque(40);
|
||||
intDeque.Clear();
|
||||
Assert.AreEqual(0, intDeque.Count);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the non-typesafe Add() method is working</summary>
|
||||
[Test]
|
||||
public void TestAddObject() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.AreEqual(0, ((IList)intDeque).Add(123));
|
||||
Assert.AreEqual(1, intDeque.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether an exception is thrown if the non-typesafe Add() method is
|
||||
/// used to add an incompatible object into the deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddIncompatibleObject() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { ((IList)intDeque).Add("Hello World"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the Add() method is working</summary>
|
||||
[Test]
|
||||
public void TestAdd() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
((IList<int>)intDeque).Add(123);
|
||||
Assert.AreEqual(1, intDeque.Count);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the Contains() method is working</summary>
|
||||
[Test]
|
||||
public void TestContains() {
|
||||
Deque<int> intDeque = createDeque(16);
|
||||
Assert.IsTrue(intDeque.Contains(14));
|
||||
Assert.IsFalse(intDeque.Contains(16));
|
||||
}
|
||||
|
||||
/// <summary>Tests the non-typesafe Contains() method</summary>
|
||||
[Test]
|
||||
public void TestContainsObject() {
|
||||
Deque<int> intDeque = createDeque(16);
|
||||
Assert.IsTrue(((IList)intDeque).Contains(14));
|
||||
Assert.IsFalse(((IList)intDeque).Contains(16));
|
||||
Assert.IsFalse(((IList)intDeque).Contains("Hello World"));
|
||||
}
|
||||
|
||||
/// <summary>Tests the non-typesafe Contains() method</summary>
|
||||
[Test]
|
||||
public void TestIndexOfObject() {
|
||||
Deque<int> intDeque = createDeque(16);
|
||||
Assert.AreEqual(14, ((IList)intDeque).IndexOf(14));
|
||||
Assert.AreEqual(-1, ((IList)intDeque).IndexOf(16));
|
||||
Assert.AreEqual(-1, ((IList)intDeque).IndexOf("Hello World"));
|
||||
}
|
||||
|
||||
/// <summary>Tests wether the non-typesafe Insert() method is working</summary>
|
||||
[Test]
|
||||
public void TestInsertObject() {
|
||||
for(int testedIndex = 0; testedIndex <= 96; ++testedIndex) {
|
||||
Deque<int> intDeque = createDeque(96);
|
||||
|
||||
((IList)intDeque).Insert(testedIndex, 12345);
|
||||
|
||||
Assert.AreEqual(97, intDeque.Count);
|
||||
|
||||
for(int index = 0; index < testedIndex; ++index) {
|
||||
Assert.AreEqual(index, intDeque[index]);
|
||||
}
|
||||
Assert.AreEqual(12345, intDeque[testedIndex]);
|
||||
for(int index = testedIndex + 1; index < 97; ++index) {
|
||||
Assert.AreEqual(index - 1, intDeque[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown if an incompatible object is inserted
|
||||
/// into the deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnInsertIncompatibleObject() {
|
||||
Deque<int> intDeque = createDeque(12);
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { ((IList)intDeque).Insert(8, "Hello World"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Validates that the IsFixedObject property is set to false</summary>
|
||||
[Test]
|
||||
public void TestIsFixedObject() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.IsFalse(((IList)intDeque).IsFixedSize);
|
||||
}
|
||||
|
||||
/// <summary>Validates that the IsSynchronized property is set to false</summary>
|
||||
[Test]
|
||||
public void TestIsSynchronized() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.IsFalse(((IList)intDeque).IsSynchronized);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that items can be assigned by their index using the non-typesafe
|
||||
/// IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestObjectIndexAssignment() {
|
||||
Deque<int> intDeque = createDeque(32);
|
||||
|
||||
((IList)intDeque)[16] = 12345;
|
||||
((IList)intDeque)[17] = 54321;
|
||||
|
||||
Assert.AreEqual(12345, ((IList)intDeque)[16]);
|
||||
Assert.AreEqual(54321, ((IList)intDeque)[17]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether an exception is thrown if an incompatible object is assigned
|
||||
/// to the deque
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIncompatibleObjectIndexAssignment() {
|
||||
Deque<int> intDeque = createDeque(2);
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { ((IList)intDeque)[0] = "Hello World"; }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the Remove() method is working correctly</summary>
|
||||
[Test]
|
||||
public void TestRemove() {
|
||||
Deque<int> intDeque = createDeque(16);
|
||||
Assert.AreEqual(16, intDeque.Count);
|
||||
Assert.IsTrue(intDeque.Remove(13));
|
||||
Assert.IsFalse(intDeque.Remove(13));
|
||||
Assert.AreEqual(15, intDeque.Count);
|
||||
}
|
||||
|
||||
/// <summary>Tests the non-typesafe remove method</summary>
|
||||
[Test]
|
||||
public void TestRemoveObject() {
|
||||
Deque<int> intDeque = createDeque(10);
|
||||
Assert.IsTrue(intDeque.Contains(8));
|
||||
Assert.AreEqual(10, intDeque.Count);
|
||||
((IList)intDeque).Remove(8);
|
||||
Assert.IsFalse(intDeque.Contains(8));
|
||||
Assert.AreEqual(9, intDeque.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests the non-typesafe remove method used to remove an incompatible object
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveIncompatibleObject() {
|
||||
Deque<int> intDeque = createDeque(10);
|
||||
((IList)intDeque).Remove("Hello World"); // should simply do nothing
|
||||
Assert.AreEqual(10, intDeque.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the IsSynchronized property and the SyncRoot property are working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronization() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
|
||||
if(!(intDeque as ICollection).IsSynchronized) {
|
||||
lock((intDeque as ICollection).SyncRoot) {
|
||||
Assert.AreEqual(0, intDeque.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the IsReadOnly property of the deque returns false
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIsReadOnly() {
|
||||
Deque<int> intDeque = new Deque<int>();
|
||||
Assert.IsFalse(((IList)intDeque).IsReadOnly);
|
||||
Assert.IsFalse(((ICollection<int>)intDeque).IsReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>Tests the non-typesafe CopyTo() method</summary>
|
||||
[Test]
|
||||
public void TestCopyToObjectArray() {
|
||||
Deque<int> intDeque = createNonNormalizedDeque(40);
|
||||
|
||||
int[] array = new int[40];
|
||||
((ICollection)intDeque).CopyTo(array, 0);
|
||||
|
||||
Assert.AreEqual(intDeque, array);
|
||||
}
|
||||
|
||||
/// <summary>Tests the CopyTo() method</summary>
|
||||
[Test]
|
||||
public void TestCopyToArray() {
|
||||
Deque<int> intDeque = createDeque(12);
|
||||
intDeque.RemoveFirst();
|
||||
intDeque.RemoveFirst();
|
||||
|
||||
int[] array = new int[14];
|
||||
intDeque.CopyTo(array, 4);
|
||||
|
||||
Assert.AreEqual(
|
||||
new int[] { 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 },
|
||||
array
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the non-typesafe CopyTo() method throws an exception if
|
||||
/// the array is of an incompatible type
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnCopyToIncompatibleObjectArray() {
|
||||
Deque<int> intDeque = createDeque(4);
|
||||
|
||||
short[] array = new short[4];
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { ((ICollection)intDeque).CopyTo(array, 4); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() method throws an exception if the target array
|
||||
/// is too small
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnCopyToTooSmallArray() {
|
||||
Deque<int> intDeque = createDeque(8);
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { intDeque.CopyTo(new int[7], 0); }
|
||||
);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Tests whether the deque enumerator detects when it runs out of sync
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInvalidatedEnumeratorDetection() {
|
||||
Deque<int> intDeque = createDeque(8);
|
||||
using(IEnumerator<int> enumerator = intDeque.GetEnumerator()) {
|
||||
Assert.IsTrue(enumerator.MoveNext());
|
||||
intDeque.AddFirst(12345);
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { enumerator.MoveNext(); }
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Creates a deque whose first element does not coincide with a block boundary
|
||||
/// </summary>
|
||||
/// <param name="count">Number of items the deque will be filled with</param>
|
||||
/// <returns>The newly created deque</returns>
|
||||
private static Deque<int> createNonNormalizedDeque(int count) {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
|
||||
for(int item = 4; item < count; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
if(count > 3) { intDeque.AddFirst(3); }
|
||||
if(count > 2) { intDeque.AddFirst(2); }
|
||||
if(count > 1) { intDeque.AddFirst(1); }
|
||||
if(count > 0) { intDeque.AddFirst(0); }
|
||||
|
||||
return intDeque;
|
||||
}
|
||||
|
||||
/// <summary>Creates a deque filled with the specified number of items
|
||||
/// </summary>
|
||||
/// <param name="count">Number of items the deque will be filled with</param>
|
||||
/// <returns>The newly created deque</returns>
|
||||
private static Deque<int> createDeque(int count) {
|
||||
Deque<int> intDeque = new Deque<int>(16);
|
||||
|
||||
for(int item = 0; item < count; ++item) {
|
||||
intDeque.AddLast(item);
|
||||
}
|
||||
|
||||
return intDeque;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
136
Tests/Collections/IListExtensionsTest.cs
Normal file
136
Tests/Collections/IListExtensionsTest.cs
Normal file
|
@ -0,0 +1,136 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the IList extension methods</summary>
|
||||
[TestFixture]
|
||||
internal class IListExtensionsTest {
|
||||
|
||||
/// <summary>Tests whether the insertion sort algorithm sorts a list correctly</summary>
|
||||
[Test]
|
||||
public void InsertionSortCanSortWholeList() {
|
||||
var testList = new List<int>(capacity: 5) { 1, 5, 2, 4, 3 };
|
||||
var testListAsIList = (IList<int>)testList;
|
||||
|
||||
testListAsIList.InsertionSort();
|
||||
|
||||
CollectionAssert.AreEqual(
|
||||
new List<int>(capacity: 5) { 1, 2, 3, 4, 5 },
|
||||
testList
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the insertion sort algorithm works on big lists</summary>
|
||||
[Test]
|
||||
public void InsertionSortCanSortBigList() {
|
||||
const int ListSize = 16384;
|
||||
|
||||
var testList = new List<int>(capacity: ListSize);
|
||||
{
|
||||
var random = new Random();
|
||||
for(int index = 0; index < ListSize; ++index) {
|
||||
testList.Add(random.Next());
|
||||
}
|
||||
}
|
||||
|
||||
var testListAsIList = (IList<int>)testList;
|
||||
testListAsIList.InsertionSort();
|
||||
|
||||
for(int index = 1; index < ListSize; ++index) {
|
||||
Assert.LessOrEqual(testListAsIList[index - 1], testListAsIList[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the insertion sort algorithm respects custom boundaries</summary>
|
||||
[Test]
|
||||
public void InsertionSortCanSortListSegment() {
|
||||
var testList = new List<int>(capacity: 7) { 9, 1, 5, 2, 4, 3, 0 };
|
||||
var testListAsIList = (IList<int>)testList;
|
||||
|
||||
testListAsIList.InsertionSort(1, 5, Comparer<int>.Default);
|
||||
|
||||
CollectionAssert.AreEqual(
|
||||
new List<int>(capacity: 7) { 9, 1, 2, 3, 4, 5, 0 },
|
||||
testList
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the quicksort algorithm sorts a list correctly</summary>
|
||||
[Test]
|
||||
public void QuickSortCanSortWholeList() {
|
||||
var testList = new List<int>(capacity: 5) { 1, 5, 2, 4, 3 };
|
||||
var testListAsIList = (IList<int>)testList;
|
||||
|
||||
testListAsIList.QuickSort();
|
||||
|
||||
CollectionAssert.AreEqual(
|
||||
new List<int>(capacity: 5) { 1, 2, 3, 4, 5 },
|
||||
testList
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the quicksort algorithm works on big lists</summary>
|
||||
[Test]
|
||||
public void QuickSortCanSortBigList() {
|
||||
const int ListSize = 16384;
|
||||
|
||||
var testList = new List<int>(capacity: ListSize);
|
||||
{
|
||||
var random = new Random();
|
||||
for(int index = 0; index < ListSize; ++index) {
|
||||
testList.Add(random.Next());
|
||||
}
|
||||
}
|
||||
|
||||
var testListAsIList = (IList<int>)testList;
|
||||
testListAsIList.QuickSort();
|
||||
|
||||
for(int index = 1; index < ListSize; ++index) {
|
||||
Assert.LessOrEqual(testListAsIList[index - 1], testListAsIList[index]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the quicksort algorithm respects custom boundaries</summary>
|
||||
[Test]
|
||||
public void QuickSortCanSortListSegment() {
|
||||
var testList = new List<int>(capacity: 7) { 9, 1, 5, 2, 4, 3, 0 };
|
||||
var testListAsIList = (IList<int>)testList;
|
||||
|
||||
testListAsIList.QuickSort(1, 5, Comparer<int>.Default);
|
||||
|
||||
CollectionAssert.AreEqual(
|
||||
new List<int>(capacity: 7) { 9, 1, 2, 3, 4, 5, 0 },
|
||||
testList
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
55
Tests/Collections/ItemEventArgsTest.cs
Normal file
55
Tests/Collections/ItemEventArgsTest.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the item event argument container</summary>
|
||||
[TestFixture]
|
||||
internal class ItemEventArgsTest {
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether an integer argument can be stored in the argument container
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void IntegersCanBeCarried() {
|
||||
var test = new ItemEventArgs<int>(12345);
|
||||
Assert.AreEqual(12345, test.Item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether a string argument can be stored in the argument container
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void StringsCanBeCarried() {
|
||||
var test = new ItemEventArgs<string>("hello world");
|
||||
Assert.AreEqual("hello world", test.Item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
57
Tests/Collections/ItemReplaceEventArgsTest.cs
Normal file
57
Tests/Collections/ItemReplaceEventArgsTest.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the item event argument container</summary>
|
||||
[TestFixture]
|
||||
internal class ItemReplaceEventArgsTest {
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether an integer argument can be stored in the argument container
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void IntegersCanBeCarried() {
|
||||
var test = new ItemReplaceEventArgs<int>(12345, 54321);
|
||||
Assert.AreEqual(12345, test.OldItem);
|
||||
Assert.AreEqual(54321, test.NewItem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether a string argument can be stored in the argument container
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void StringsCanBeCarried() {
|
||||
var test = new ItemReplaceEventArgs<string>("hello", "world");
|
||||
Assert.AreEqual("hello", test.OldItem);
|
||||
Assert.AreEqual("world", test.NewItem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
256
Tests/Collections/ListSegmentTest.cs
Normal file
256
Tests/Collections/ListSegmentTest.cs
Normal file
|
@ -0,0 +1,256 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the list segment class</summary>
|
||||
[TestFixture]
|
||||
internal class ListSegmentTest {
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the default constructor of the ListSegment class throws the
|
||||
/// right exception when being passed 'null' instead of a list
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SimpleConstructorThrowsWhenListIsNull() {
|
||||
Assert.Throws<ArgumentNullException>(
|
||||
delegate() { new ListSegment<int>(null); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the simple constructor of the ListSegment class accepts
|
||||
/// an empty list
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SimpleConstructorAcceptsEmptyList() {
|
||||
new ListSegment<int>(new List<int>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the full constructor of the ListSegment class throws the
|
||||
/// right exception when being passed 'null' instead of a string
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ConstructorThrowsWhenListIsNull() {
|
||||
Assert.Throws<ArgumentNullException>(
|
||||
delegate() { new ListSegment<int>(null, 0, 0); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the full constructor of the ListSegment class accepts
|
||||
/// an empty string
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ConstructorAcceptsEmptyList() {
|
||||
new ListSegment<int>(new List<int>(), 0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the full constructor of the ListSegment class throws the
|
||||
/// right exception when being passed an invalid start offset
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ConstructorThrowsOnInvalidOffset() {
|
||||
Assert.Throws<ArgumentOutOfRangeException>(
|
||||
delegate() { new ListSegment<int>(new List<int>(), -1, 0); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the full constructor of the ListSegment class throws the
|
||||
/// right exception when being passed an invalid element count
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ConstructorThrowsOnInvalidCount() {
|
||||
Assert.Throws<ArgumentOutOfRangeException>(
|
||||
delegate() { new ListSegment<int>(new List<int>(), 0, -1); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the full constructor of the ListSegment class throws the
|
||||
/// right exception when being passed a string length that's too large
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ConstructorThrowsOnListOverrun() {
|
||||
var testList = new List<int>(capacity: 5) { 1, 2, 3, 4, 5 };
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { new ListSegment<int>(testList, 3, 3); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the 'Text' property works as expected</summary>
|
||||
[Test]
|
||||
public void ListPropertyStoresOriginalList() {
|
||||
var testList = new List<int>(capacity: 5) { 1, 2, 3, 4, 5 };
|
||||
ListSegment<int> testSegment = new ListSegment<int>(testList, 1, 3);
|
||||
Assert.AreSame(testList, testSegment.List);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the 'Offset' property works as expected</summary>
|
||||
[Test]
|
||||
public void OffsetPropertyIsStored() {
|
||||
var testList = new List<int>(capacity: 5) { 1, 2, 3, 4, 5 };
|
||||
ListSegment<int> testSegment = new ListSegment<int>(testList, 1, 3);
|
||||
Assert.AreEqual(1, testSegment.Offset);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the 'Count' property works as expected</summary>
|
||||
[Test]
|
||||
public void CountPropertyIsStored() {
|
||||
var testList = new List<int>(capacity: 5) { 1, 2, 3, 4, 5 };
|
||||
ListSegment<int> testSegment = new ListSegment<int>(testList, 1, 3);
|
||||
Assert.AreEqual(3, testSegment.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether two differing instances produce different hash codes
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DifferentInstancesHaveDifferentHashCodes_Usually() {
|
||||
var forwardCountSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
var reverseCountSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 9, 8, 7, 6, 5, 4, 3, 2, 1 }, 1, 8
|
||||
);
|
||||
|
||||
Assert.AreNotEqual(
|
||||
forwardCountSegment.GetHashCode(), reverseCountSegment.GetHashCode()
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether two equivalent instances produce an identical hash code
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void EquivalentInstancesHaveSameHashcode() {
|
||||
var testSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
var identicalSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
|
||||
Assert.AreEqual(
|
||||
testSegment.GetHashCode(), identicalSegment.GetHashCode()
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests the equals method performing a comparison against null</summary>
|
||||
[Test]
|
||||
public void EqualsAgainstNullIsAlwaysFalse() {
|
||||
var testList = new List<int>(capacity: 5) { 1, 2, 3, 4, 5 };
|
||||
ListSegment<int> testSegment = new ListSegment<int>(testList, 1, 3);
|
||||
|
||||
Assert.IsFalse(
|
||||
testSegment.Equals(null)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests the equality operator with differing instances</summary>
|
||||
[Test]
|
||||
public void DifferingInstancesAreNotEqual() {
|
||||
var forwardCountSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
var reverseCountSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 9, 8, 7, 6, 5, 4, 3, 2, 1 }, 1, 8
|
||||
);
|
||||
|
||||
Assert.IsFalse(forwardCountSegment == reverseCountSegment);
|
||||
}
|
||||
|
||||
/// <summary>Tests the equality operator with equivalent instances</summary>
|
||||
[Test]
|
||||
public void EquivalentInstancesAreEqual() {
|
||||
var testSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
var identicalSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
|
||||
Assert.IsTrue(testSegment == identicalSegment);
|
||||
}
|
||||
|
||||
/// <summary>Tests the inequality operator with differing instances</summary>
|
||||
[Test]
|
||||
public void DifferingInstancesAreUnequal() {
|
||||
var forwardCountSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
var reverseCountSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 9, 8, 7, 6, 5, 4, 3, 2, 1 }, 1, 8
|
||||
);
|
||||
|
||||
Assert.IsTrue(forwardCountSegment != reverseCountSegment);
|
||||
}
|
||||
|
||||
/// <summary>Tests the inequality operator with equivalent instances</summary>
|
||||
[Test]
|
||||
public void EquivalentInstancesAreNotUnequal() {
|
||||
var testSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
var identicalSegment = new ListSegment<int>(
|
||||
new List<int>(capacity: 9) { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 2, 7
|
||||
);
|
||||
|
||||
Assert.IsFalse(testSegment != identicalSegment);
|
||||
}
|
||||
|
||||
/// <summary>Tests the ToString() method of the string segment</summary>
|
||||
[Test]
|
||||
public void TestToString() {
|
||||
var testList = new List<int>(capacity: 6) { 1, 2, 3, 4, 5, 6 };
|
||||
ListSegment<int> testSegment = new ListSegment<int>(testList, 2, 2);
|
||||
|
||||
string stringRepresentation = testSegment.ToString();
|
||||
StringAssert.Contains("3, 4", stringRepresentation);
|
||||
StringAssert.DoesNotContain("2", stringRepresentation);
|
||||
StringAssert.DoesNotContain("5", stringRepresentation);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the 'Text' property works as expected</summary>
|
||||
[Test]
|
||||
public void ToListReturnsSubset() {
|
||||
var testList = new List<int>(capacity: 5) { 1, 2, 3, 4, 5 };
|
||||
ListSegment<int> testSegment = new ListSegment<int>(testList, 1, 3);
|
||||
CollectionAssert.AreEqual(
|
||||
new List<int>(capacity: 3) { 2, 3, 4 },
|
||||
testSegment.ToList()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
390
Tests/Collections/MultiDictionaryTest.cs
Normal file
390
Tests/Collections/MultiDictionaryTest.cs
Normal file
|
@ -0,0 +1,390 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
using NMock;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit tests for the multi dictionary</summary>
|
||||
[TestFixture]
|
||||
internal class MultiDictionaryTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that new instances of the multi dictionary can be created
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanConstructNewDictionary() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
Assert.IsNotNull(dictionary); // nonsense, prevents compiler warning
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the count is initialized correctly when building
|
||||
/// a multi dictionary from a dictionary of value collections.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CountIsCalculatedIfInitializedFromDictionary() {
|
||||
var contents = new Dictionary<int, ICollection<string>>();
|
||||
contents.Add(1, new List<string>(new string[] { "one", "eins" }));
|
||||
contents.Add(2, new List<string>(new string[] { "two", "zwei" }));
|
||||
|
||||
var multiDictionary = new MultiDictionary<int, string>(contents);
|
||||
Assert.AreEqual(4, multiDictionary.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a new multi dictionary based on a read-only dictionary is
|
||||
/// also read-only
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void IsReadOnlyWhenBasedOnReadOnlyContainer() {
|
||||
var readOnly = new ReadOnlyDictionary<int, ICollection<string>>(
|
||||
new Dictionary<int, ICollection<string>>()
|
||||
);
|
||||
var dictionary = new MultiDictionary<int, string>(readOnly);
|
||||
|
||||
Assert.IsTrue(dictionary.IsReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the multi dictionary can contain the same key multiple times
|
||||
/// (or in other words, multiple values on the same key)
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanContainKeyMultipleTimes() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(123, "one two three");
|
||||
dictionary.Add(123, "eins zwei drei");
|
||||
|
||||
Assert.AreEqual(2, dictionary.Count);
|
||||
|
||||
CollectionAssert.AreEquivalent(
|
||||
new KeyValuePair<int, string>[] {
|
||||
new KeyValuePair<int, string>(123, "one two three"),
|
||||
new KeyValuePair<int, string>(123, "eins zwei drei")
|
||||
},
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that adding values through the indexer still updates the item count
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AddingValuesFromIndexerUpdatesCount() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(42, "the answer to everything");
|
||||
dictionary[42].Add("21x2");
|
||||
|
||||
Assert.AreEqual(2, dictionary.Count);
|
||||
|
||||
CollectionAssert.AreEquivalent(
|
||||
new KeyValuePair<int, string>[] {
|
||||
new KeyValuePair<int, string>(42, "the answer to everything"),
|
||||
new KeyValuePair<int, string>(42, "21x2")
|
||||
},
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the collection can count the number of values stored
|
||||
/// under a key
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ValuesWithSameKeyCanBeCounted() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(20, "twenty");
|
||||
dictionary.Add(30, "thirty");
|
||||
dictionary.Add(10, "zehn");
|
||||
dictionary.Add(20, "zwanzig");
|
||||
dictionary.Add(10, "dix");
|
||||
|
||||
Assert.AreEqual(6, dictionary.Count);
|
||||
Assert.AreEqual(3, dictionary.CountValues(10));
|
||||
Assert.AreEqual(2, dictionary.CountValues(20));
|
||||
Assert.AreEqual(1, dictionary.CountValues(30));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that counting the values of a non-existing key returns 0
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CountingValuesOfNonExistentKeyReturnsNull() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
Assert.AreEqual(0, dictionary.CountValues(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that its possible to remove values individually without affecting
|
||||
/// other values stored under the same key
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ValuesCanBeRemovedIndividually() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
dictionary.Add(10, "dix");
|
||||
|
||||
dictionary.Remove(10, "zehn");
|
||||
|
||||
Assert.AreEqual(2, dictionary.Count);
|
||||
CollectionAssert.AreEquivalent(
|
||||
new KeyValuePair<int, string>[] {
|
||||
new KeyValuePair<int, string>(10, "ten"),
|
||||
new KeyValuePair<int, string>(10, "dix")
|
||||
},
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Count property returns the number of unique keys if it is called
|
||||
/// on the collection-of-collections interface implemented by the multi dictionary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CollectionOfCollectionCountIsUniqueKeyCount() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
|
||||
Assert.AreEqual(2, dictionary.Count);
|
||||
var collectionOfCollections =
|
||||
(ICollection<KeyValuePair<int, ICollection<string>>>)dictionary;
|
||||
Assert.AreEqual(1, collectionOfCollections.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the multi dictionary can be tested for containment of a specific value
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ContainmentCanBeTested() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
|
||||
Assert.IsTrue(dictionary.Contains(new KeyValuePair<int, string>(10, "ten")));
|
||||
Assert.IsTrue(dictionary.Contains(new KeyValuePair<int, string>(10, "zehn")));
|
||||
Assert.IsFalse(dictionary.Contains(new KeyValuePair<int, string>(10, "dix")));
|
||||
Assert.IsFalse(dictionary.Contains(new KeyValuePair<int, string>(20, "ten")));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the multi dictionary can be tested for containment of a specific key
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void KeyContainmentCanBeTested() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
|
||||
Assert.IsTrue(dictionary.ContainsKey(10));
|
||||
Assert.IsFalse(dictionary.ContainsKey(20));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the key collection can be retrieved from the dictionary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void KeyCollectionCanBeRetrieved() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
|
||||
ICollection<int> keys = dictionary.Keys;
|
||||
Assert.IsNotNull(keys);
|
||||
Assert.AreEqual(1, keys.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the key collection can be retrieved from the dictionary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ValueCollectionCanBeRetrieved() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
dictionary.Add(20, "twenty");
|
||||
|
||||
ICollection<string> values = dictionary.Values;
|
||||
Assert.IsNotNull(values);
|
||||
Assert.AreEqual(3, values.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that TryGetValue() returns false and doesn't throw if a key
|
||||
/// is not found in the collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TryGetValueReturnsFalseOnMissingKey() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
ICollection<string> values;
|
||||
Assert.IsFalse(dictionary.TryGetValue(123, out values));
|
||||
}
|
||||
|
||||
/// <summary>Verifies that keys can be looked up via TryGetValue()</summary>
|
||||
[Test]
|
||||
public void TryGetValueCanLookUpValues() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
ICollection<string> values;
|
||||
Assert.IsTrue(dictionary.TryGetValue(10, out values));
|
||||
Assert.AreEqual(2, values.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that assigning null to a key deletes all the values stored
|
||||
/// under it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AssigningNullToKeyRemovesAllValues() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
dictionary.Add(20, "twenty");
|
||||
|
||||
Assert.AreEqual(3, dictionary.Count);
|
||||
dictionary[10] = null;
|
||||
Assert.AreEqual(1, dictionary.Count);
|
||||
Assert.IsFalse(dictionary.ContainsKey(10));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that assigning null to a key deletes all the values stored
|
||||
/// under it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ValueListCanBeAssignedToNewKey() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary[3] = new List<string>() { "three", "drei" };
|
||||
|
||||
Assert.AreEqual(2, dictionary.Count);
|
||||
Assert.IsTrue(dictionary.Contains(new KeyValuePair<int, string>(3, "three")));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that assigning null to a key deletes all the values stored
|
||||
/// under it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ValueListCanOverwriteExistingKey() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "dix");
|
||||
|
||||
Assert.AreEqual(1, dictionary.Count);
|
||||
|
||||
dictionary[10] = new List<string>() { "ten", "zehn" };
|
||||
|
||||
Assert.AreEqual(2, dictionary.Count);
|
||||
Assert.IsFalse(dictionary.Contains(new KeyValuePair<int, string>(10, "dix")));
|
||||
Assert.IsTrue(dictionary.Contains(new KeyValuePair<int, string>(10, "ten")));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that nothing bad happens when a key is removed from the dictionary
|
||||
/// that it doesn't contain
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NonExistingKeyCanBeRemoved() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
Assert.AreEqual(0, dictionary.RemoveKey(123));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the remove method returns the number of values that have
|
||||
/// been removed from the dictionary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void RemoveReturnsNumberOfValuesRemoved() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
Assert.AreEqual(2, dictionary.RemoveKey(10));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the dictionary becomes empty after clearing it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DictionaryIsEmptyAfterClear() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(10, "ten");
|
||||
dictionary.Add(10, "zehn");
|
||||
dictionary.Add(20, "twenty");
|
||||
Assert.AreEqual(3, dictionary.Count);
|
||||
dictionary.Clear();
|
||||
Assert.AreEqual(0, dictionary.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that non-existing values can be removed from the dictionary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NonExistingValueCanBeRemoved() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
Assert.IsFalse(dictionary.Remove(123, "test"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that nothing bad happens when the last value under a key is removed
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void LastValueOfKeyCanBeRemoved() {
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
dictionary.Add(123, "test");
|
||||
dictionary.Remove(123, "test");
|
||||
Assert.AreEqual(0, dictionary.CountValues(123));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the dictionary can be copied into an array
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void DictionaryCanBeCopiedIntoArray() {
|
||||
var expected = new List<KeyValuePair<int, string>>() {
|
||||
new KeyValuePair<int, string>(1, "one"),
|
||||
new KeyValuePair<int, string>(1, "eins"),
|
||||
new KeyValuePair<int, string>(2, "two"),
|
||||
new KeyValuePair<int, string>(2, "zwei")
|
||||
};
|
||||
|
||||
var dictionary = new MultiDictionary<int, string>();
|
||||
foreach(KeyValuePair<int, string> entry in expected) {
|
||||
dictionary.Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
var actual = new KeyValuePair<int, string>[4];
|
||||
dictionary.CopyTo(actual, 0);
|
||||
|
||||
CollectionAssert.AreEquivalent(expected, actual);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
144
Tests/Collections/ObservableCollectionTest.cs
Normal file
144
Tests/Collections/ObservableCollectionTest.cs
Normal file
|
@ -0,0 +1,144 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if !NO_NMOCK
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
using NMock;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the observable collection class</summary>
|
||||
[TestFixture]
|
||||
internal class ObservableCollectionTest {
|
||||
|
||||
#region interface IObservableCollectionSubscriber
|
||||
|
||||
/// <summary>Interface used to test the observable collection</summary>
|
||||
public interface IObservableCollectionSubscriber {
|
||||
|
||||
/// <summary>Called when the collection is about to clear its contents</summary>
|
||||
/// <param name="sender">Collection that is clearing its contents</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
void Clearing(object sender, EventArgs arguments);
|
||||
|
||||
/// <summary>Called when the collection has been cleared of its contents</summary>
|
||||
/// <param name="sender">Collection that was cleared of its contents</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
void Cleared(object sender, EventArgs arguments);
|
||||
|
||||
/// <summary>Called when an item is added to the collection</summary>
|
||||
/// <param name="sender">Collection to which an item is being added</param>
|
||||
/// <param name="arguments">Contains the item that is being added</param>
|
||||
void ItemAdded(object sender, ItemEventArgs<int> arguments);
|
||||
|
||||
/// <summary>Called when an item is removed from the collection</summary>
|
||||
/// <param name="sender">Collection from which an item is being removed</param>
|
||||
/// <param name="arguments">Contains the item that is being removed</param>
|
||||
void ItemRemoved(object sender, ItemEventArgs<int> arguments);
|
||||
|
||||
}
|
||||
|
||||
#endregion // interface IObservableCollectionSubscriber
|
||||
|
||||
/// <summary>Initialization routine executed before each test is run</summary>
|
||||
[SetUp]
|
||||
public void Setup() {
|
||||
this.mockery = new MockFactory();
|
||||
|
||||
this.mockedSubscriber = this.mockery.CreateMock<IObservableCollectionSubscriber>();
|
||||
|
||||
this.observedCollection = new ObservableCollection<int>();
|
||||
this.observedCollection.Clearing += new EventHandler(
|
||||
this.mockedSubscriber.MockObject.Clearing
|
||||
);
|
||||
this.observedCollection.Cleared += new EventHandler(
|
||||
this.mockedSubscriber.MockObject.Cleared
|
||||
);
|
||||
this.observedCollection.ItemAdded += new EventHandler<ItemEventArgs<int>>(
|
||||
this.mockedSubscriber.MockObject.ItemAdded
|
||||
);
|
||||
this.observedCollection.ItemRemoved += new EventHandler<ItemEventArgs<int>>(
|
||||
this.mockedSubscriber.MockObject.ItemRemoved
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the Clearing event is fired</summary>
|
||||
[Test]
|
||||
public void TestClearingEvent() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.Clearing(null, null)).WithAnyArguments();
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.Cleared(null, null)).WithAnyArguments();
|
||||
this.observedCollection.Clear();
|
||||
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the ItemAdded event is fired</summary>
|
||||
[Test]
|
||||
public void TestItemAddedEvent() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemAdded(null, null)).WithAnyArguments();
|
||||
|
||||
this.observedCollection.Add(123);
|
||||
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the ItemRemoved event is fired</summary>
|
||||
[Test]
|
||||
public void TestItemRemovedEvent() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemAdded(null, null)).WithAnyArguments();
|
||||
|
||||
this.observedCollection.Add(123);
|
||||
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemRemoved(null, null)).WithAnyArguments();
|
||||
|
||||
this.observedCollection.Remove(123);
|
||||
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
}
|
||||
|
||||
/// <summary>Tests whether a the list constructor is working</summary>
|
||||
[Test]
|
||||
public void TestListConstructor() {
|
||||
int[] integers = new int[] { 12, 34, 56, 78 };
|
||||
|
||||
var testCollection = new ObservableCollection<int>(integers);
|
||||
|
||||
CollectionAssert.AreEqual(integers, testCollection);
|
||||
}
|
||||
|
||||
/// <summary>Mock object factory</summary>
|
||||
private MockFactory mockery;
|
||||
/// <summary>The mocked observable collection subscriber</summary>
|
||||
private Mock<IObservableCollectionSubscriber> mockedSubscriber;
|
||||
/// <summary>An observable collection to which a mock will be subscribed</summary>
|
||||
private ObservableCollection<int> observedCollection;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
||||
|
||||
#endif // !NO_NMOCK
|
589
Tests/Collections/ObservableDictionaryTest.cs
Normal file
589
Tests/Collections/ObservableDictionaryTest.cs
Normal file
|
@ -0,0 +1,589 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if !NO_NMOCK
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
using NUnit.Framework;
|
||||
using NMock;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the observable dictionary wrapper</summary>
|
||||
[TestFixture]
|
||||
internal class ObservableDictionaryTest {
|
||||
|
||||
#region interface IObservableDictionarySubscriber
|
||||
|
||||
/// <summary>Interface used to test the observable dictionary</summary>
|
||||
public interface IObservableDictionarySubscriber {
|
||||
|
||||
/// <summary>Called when the dictionary is about to clear its contents</summary>
|
||||
/// <param name="sender">Dictionary that is clearing its contents</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
void Clearing(object sender, EventArgs arguments);
|
||||
|
||||
/// <summary>Called when the dictionary has been clear of its contents</summary>
|
||||
/// <param name="sender">Dictionary that was cleared of its contents</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
void Cleared(object sender, EventArgs arguments);
|
||||
|
||||
/// <summary>Called when an item is added to the dictionary</summary>
|
||||
/// <param name="sender">Dictionary to which an item is being added</param>
|
||||
/// <param name="arguments">Contains the item that is being added</param>
|
||||
void ItemAdded(object sender, ItemEventArgs<KeyValuePair<int, string>> arguments);
|
||||
|
||||
/// <summary>Called when an item is removed from the dictionary</summary>
|
||||
/// <param name="sender">Dictionary from which an item is being removed</param>
|
||||
/// <param name="arguments">Contains the item that is being removed</param>
|
||||
void ItemRemoved(object sender, ItemEventArgs<KeyValuePair<int, string>> arguments);
|
||||
|
||||
/// <summary>Called when an item is replaced in the dictionary</summary>
|
||||
/// <param name="sender">Dictionary in which an item is being replaced</param>
|
||||
/// <param name="arguments">Contains the replaced item and its replacement</param>
|
||||
void ItemReplaced(
|
||||
object sender, ItemReplaceEventArgs<KeyValuePair<int, string>> arguments
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#endregion // interface IObservableDictionarySubscriber
|
||||
|
||||
/// <summary>Initialization routine executed before each test is run</summary>
|
||||
[SetUp]
|
||||
public void Setup() {
|
||||
this.mockery = new MockFactory();
|
||||
|
||||
this.mockedSubscriber = this.mockery.CreateMock<IObservableDictionarySubscriber>();
|
||||
|
||||
this.observedDictionary = new ObservableDictionary<int, string>();
|
||||
this.observedDictionary.Add(1, "one");
|
||||
this.observedDictionary.Add(2, "two");
|
||||
this.observedDictionary.Add(3, "three");
|
||||
this.observedDictionary.Add(42, "forty-two");
|
||||
|
||||
this.observedDictionary.Clearing +=
|
||||
new EventHandler(this.mockedSubscriber.MockObject.Clearing);
|
||||
this.observedDictionary.Cleared +=
|
||||
new EventHandler(this.mockedSubscriber.MockObject.Cleared);
|
||||
this.observedDictionary.ItemAdded +=
|
||||
new EventHandler<ItemEventArgs<KeyValuePair<int, string>>>(
|
||||
this.mockedSubscriber.MockObject.ItemAdded
|
||||
);
|
||||
this.observedDictionary.ItemRemoved +=
|
||||
new EventHandler<ItemEventArgs<KeyValuePair<int, string>>>(
|
||||
this.mockedSubscriber.MockObject.ItemRemoved
|
||||
);
|
||||
this.observedDictionary.ItemReplaced +=
|
||||
new EventHandler<ItemReplaceEventArgs<KeyValuePair<int, string>>>(
|
||||
this.mockedSubscriber.MockObject.ItemReplaced
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the default constructor of the observable dictionary works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDefaultConstructor() {
|
||||
ObservableDictionary<int, string> testDictionary =
|
||||
new ObservableDictionary<int, string>();
|
||||
|
||||
Assert.AreEqual(0, testDictionary.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the copy constructor of the observable dictionary works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyConstructor() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
CollectionAssert.AreEqual(numbers, testDictionary);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the IsReadOnly property is working</summary>
|
||||
[Test]
|
||||
public void TestIsReadOnly() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
Assert.IsFalse(testDictionary.IsReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the observable dictionary is able to
|
||||
/// determine if the dictionary contains an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContains() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
Assert.IsTrue(
|
||||
testDictionary.Contains(new KeyValuePair<int, string>(42, "forty-two"))
|
||||
);
|
||||
Assert.IsFalse(
|
||||
testDictionary.Contains(new KeyValuePair<int, string>(24, "twenty-four"))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the observable dictionary is able to
|
||||
/// determine if the dictionary contains a key
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContainsKey() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
Assert.IsTrue(testDictionary.ContainsKey(42));
|
||||
Assert.IsFalse(testDictionary.ContainsKey(24));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() of the observable dictionary works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArray() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
KeyValuePair<int, string>[] items = new KeyValuePair<int, string>[numbers.Count];
|
||||
|
||||
testDictionary.CopyTo(items, 0);
|
||||
|
||||
CollectionAssert.AreEqual(numbers, items);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the typesafe enumerator of the observable dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTypesafeEnumerator() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
List<KeyValuePair<int, string>> outputItems = new List<KeyValuePair<int, string>>();
|
||||
foreach(KeyValuePair<int, string> item in testDictionary) {
|
||||
outputItems.Add(item);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEqual(numbers, outputItems);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the keys collection of the observable dictionary can be queried
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetKeysCollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
ICollection<int> inputKeys = numbers.Keys;
|
||||
ICollection<int> keys = testDictionary.Keys;
|
||||
CollectionAssert.AreEquivalent(inputKeys, keys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the values collection of the observable dictionary can be queried
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetValuesCollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
ICollection<string> inputValues = numbers.Values;
|
||||
ICollection<string> values = testDictionary.Values;
|
||||
CollectionAssert.AreEquivalent(inputValues, values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the TryGetValue() method of the observable dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTryGetValue() {
|
||||
string value;
|
||||
|
||||
Assert.IsTrue(this.observedDictionary.TryGetValue(42, out value));
|
||||
Assert.AreEqual("forty-two", value);
|
||||
|
||||
Assert.IsFalse(this.observedDictionary.TryGetValue(24, out value));
|
||||
Assert.AreEqual(null, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the retrieval of values using the indexer of the observable
|
||||
/// dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveValueByIndexer() {
|
||||
Assert.AreEqual("forty-two", this.observedDictionary[42]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether an exception is thrown if the indexer of the observable dictionary
|
||||
/// is used to attempt to retrieve a non-existing value
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveNonExistingValueByIndexer() {
|
||||
Assert.Throws<KeyNotFoundException>(
|
||||
delegate() { Console.WriteLine(this.observedDictionary[24]); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Add() methods works via the generic
|
||||
/// IDictionary<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddViaGenericIDictionary() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemAdded(null, null)).WithAnyArguments();
|
||||
(this.observedDictionary as IDictionary<int, string>).Add(10, "ten");
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
CollectionAssert.Contains(
|
||||
this.observedDictionary, new KeyValuePair<int, string>(10, "ten")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Remove() method works via the generic
|
||||
/// IDictionary<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveViaGenericIDictionary() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemRemoved(null, null)).WithAnyArguments();
|
||||
(this.observedDictionary as IDictionary<int, string>).Remove(3);
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
CollectionAssert.DoesNotContain(this.observedDictionary.Keys, 3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the TryGetValue() method of the observable dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveValueByIndexerViaGenericIDictionary() {
|
||||
Assert.AreEqual(
|
||||
"forty-two", (this.observedDictionary as IDictionary<int, string>)[42]
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the indexer can be used to insert an item via the generic
|
||||
/// IDictionar<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReplaceByIndexerViaGenericIDictionary() {
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.ItemReplaced(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
(this.observedDictionary as IDictionary<int, string>)[42] = "two and fourty";
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
Assert.AreEqual("two and fourty", this.observedDictionary[42]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Clear() method of observable dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestClearViaIDictionary() {
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.Clearing(null, null)
|
||||
).WithAnyArguments();
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.Cleared(null, null)
|
||||
).WithAnyArguments();
|
||||
(this.observedDictionary as IDictionary).Clear();
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
Assert.AreEqual(0, this.observedDictionary.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Add() method works via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddViaIDictionary() {
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
(this.observedDictionary as IDictionary).Add(24, "twenty-four");
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
CollectionAssert.Contains(
|
||||
this.observedDictionary, new KeyValuePair<int, string>(24, "twenty-four")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the observable dictionary is able to
|
||||
/// determine if the dictionary contains an item via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContainsViaIDictionary() {
|
||||
Assert.IsTrue((this.observedDictionary as IDictionary).Contains(42));
|
||||
Assert.IsFalse((this.observedDictionary as IDictionary).Contains(24));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the GetEnumerator() method of the observable dictionary
|
||||
/// returns a working enumerator if accessed via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestEnumeratorViaIDictionary() {
|
||||
Dictionary<int, string> outputNumbers = new Dictionary<int, string>();
|
||||
foreach(DictionaryEntry entry in (this.observedDictionary as IDictionary)) {
|
||||
(outputNumbers as IDictionary).Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEquivalent(this.observedDictionary, outputNumbers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IsFixedSize property of the observable dictionary returns
|
||||
/// the expected result for a read only dictionary based on a dynamic dictionary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIsFixedSizeViaIList() {
|
||||
Assert.IsFalse((this.observedDictionary as IDictionary).IsFixedSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the keys collection of the observable dictionary can be queried
|
||||
/// via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetKeysCollectionViaIDictionary() {
|
||||
ICollection keys = (this.observedDictionary as IDictionary).Keys;
|
||||
Assert.AreEqual(this.observedDictionary.Count, keys.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the values collection of the observable dictionary can be queried
|
||||
/// via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetValuesCollectionViaIDictionary() {
|
||||
ICollection values = (this.observedDictionary as IDictionary).Values;
|
||||
Assert.AreEqual(this.observedDictionary.Count, values.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether Remove() method works via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveViaIDictionary() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemRemoved(null, null)).WithAnyArguments();
|
||||
(this.observedDictionary as IDictionary).Remove(3);
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
CollectionAssert.DoesNotContain(this.observedDictionary.Keys, 3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the retrieval of values using the indexer of the observable
|
||||
/// dictionary is working via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveValueByIndexerViaIDictionary() {
|
||||
Assert.AreEqual("forty-two", (this.observedDictionary as IDictionary)[42]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the indexer can be used to insert an item via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReplaceByIndexerViaIDictionary() {
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.ItemRemoved(null, null)
|
||||
).WithAnyArguments();
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
(this.observedDictionary as IDictionary)[42] = "two and fourty";
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
Assert.AreEqual("two and fourty", this.observedDictionary[42]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether Add() method is working via the generic
|
||||
/// ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddViaGenericICollection() {
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
(this.observedDictionary as ICollection<KeyValuePair<int, string>>).Add(
|
||||
new KeyValuePair<int, string>(24, "twenty-four")
|
||||
);
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
CollectionAssert.Contains(
|
||||
this.observedDictionary, new KeyValuePair<int, string>(24, "twenty-four")
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Clear() method is working via the generic
|
||||
/// ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestClearViaGenericICollection() {
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.Clearing(null, null)
|
||||
).WithAnyArguments();
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.Cleared(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
(this.observedDictionary as ICollection<KeyValuePair<int, string>>).Clear();
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
Assert.AreEqual(0, this.observedDictionary.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Remove() method is working via the
|
||||
/// generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveViaGenericICollection() {
|
||||
IEnumerator<KeyValuePair<int, string>> enumerator =
|
||||
(this.observedDictionary as ICollection<KeyValuePair<int, string>>).GetEnumerator();
|
||||
enumerator.MoveNext();
|
||||
|
||||
this.mockedSubscriber.Expects.One.Method(
|
||||
m => m.ItemRemoved(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
(this.observedDictionary as ICollection<KeyValuePair<int, string>>).Remove(
|
||||
enumerator.Current
|
||||
);
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
CollectionAssert.DoesNotContain(this.observedDictionary, enumerator.Current);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() of the observable dictionary works when called
|
||||
/// via the the ICollection interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArrayViaICollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
DictionaryEntry[] entries = new DictionaryEntry[numbers.Count];
|
||||
(testDictionary as ICollection).CopyTo(entries, 0);
|
||||
|
||||
KeyValuePair<int, string>[] items = new KeyValuePair<int, string>[numbers.Count];
|
||||
for(int index = 0; index < entries.Length; ++index) {
|
||||
items[index] = new KeyValuePair<int, string>(
|
||||
(int)entries[index].Key, (string)entries[index].Value
|
||||
);
|
||||
}
|
||||
CollectionAssert.AreEquivalent(numbers, items);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the IsSynchronized property and the SyncRoot property are working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronization() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary = makeObservable(numbers);
|
||||
|
||||
if(!(testDictionary as ICollection).IsSynchronized) {
|
||||
lock((testDictionary as ICollection).SyncRoot) {
|
||||
Assert.AreEqual(numbers.Count, testDictionary.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the observable dictionary can be serialized
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSerialization() {
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
|
||||
using(MemoryStream memory = new MemoryStream()) {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ObservableDictionary<int, string> testDictionary1 = makeObservable(numbers);
|
||||
|
||||
formatter.Serialize(memory, testDictionary1);
|
||||
memory.Position = 0;
|
||||
object testDictionary2 = formatter.Deserialize(memory);
|
||||
|
||||
CollectionAssert.AreEquivalent(testDictionary1, (IEnumerable)testDictionary2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new observable dictionary filled with some values for testing
|
||||
/// </summary>
|
||||
/// <returns>The newly created observable dictionary</returns>
|
||||
private static Dictionary<int, string> createTestDictionary() {
|
||||
Dictionary<int, string> numbers = new Dictionary<int, string>();
|
||||
numbers.Add(1, "one");
|
||||
numbers.Add(2, "two");
|
||||
numbers.Add(3, "three");
|
||||
numbers.Add(42, "forty-two");
|
||||
return new Dictionary<int, string>(numbers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new observable dictionary filled with some values for testing
|
||||
/// </summary>
|
||||
/// <returns>The newly created observable dictionary</returns>
|
||||
private static ObservableDictionary<int, string> makeObservable(
|
||||
IDictionary<int, string> dictionary
|
||||
) {
|
||||
return new ObservableDictionary<int, string>(dictionary);
|
||||
}
|
||||
|
||||
/// <summary>Mock object factory</summary>
|
||||
private MockFactory mockery;
|
||||
/// <summary>The mocked observable collection subscriber</summary>
|
||||
private Mock<IObservableDictionarySubscriber> mockedSubscriber;
|
||||
/// <summary>An observable dictionary to which a mock will be subscribed</summary>
|
||||
private ObservableDictionary<int, string> observedDictionary;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
||||
|
||||
#endif // !NO_NMOCK
|
175
Tests/Collections/ObservableListTest.cs
Normal file
175
Tests/Collections/ObservableListTest.cs
Normal file
|
@ -0,0 +1,175 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if !NO_NMOCK
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
using NMock;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the observable list class</summary>
|
||||
[TestFixture]
|
||||
internal class ObservableListTest {
|
||||
|
||||
#region interface IObservableCollectionSubscriber
|
||||
|
||||
/// <summary>Interface used to test the observable collection</summary>
|
||||
public interface IObservableCollectionSubscriber {
|
||||
|
||||
/// <summary>Called when the collection is about to clear its contents</summary>
|
||||
/// <param name="sender">Collection that is clearing its contents</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
void Clearing(object sender, EventArgs arguments);
|
||||
|
||||
/// <summary>Called when the collection has been cleared of its contents</summary>
|
||||
/// <param name="sender">Collection that was cleared of its contents</param>
|
||||
/// <param name="arguments">Not used</param>
|
||||
void Cleared(object sender, EventArgs arguments);
|
||||
|
||||
/// <summary>Called when an item is added to the collection</summary>
|
||||
/// <param name="sender">Collection to which an item is being added</param>
|
||||
/// <param name="arguments">Contains the item that is being added</param>
|
||||
void ItemAdded(object sender, ItemEventArgs<int> arguments);
|
||||
|
||||
/// <summary>Called when an item is removed from the collection</summary>
|
||||
/// <param name="sender">Collection from which an item is being removed</param>
|
||||
/// <param name="arguments">Contains the item that is being removed</param>
|
||||
void ItemRemoved(object sender, ItemEventArgs<int> arguments);
|
||||
|
||||
/// <summary>Called when an item is replaced in the dictionary</summary>
|
||||
/// <param name="sender">Dictionary in which an item is being replaced</param>
|
||||
/// <param name="arguments">Contains the replaced item and its replacement</param>
|
||||
void ItemReplaced(object sender, ItemReplaceEventArgs<int> arguments);
|
||||
|
||||
}
|
||||
|
||||
#endregion // interface IObservableCollectionSubscriber
|
||||
|
||||
/// <summary>Initialization routine executed before each test is run</summary>
|
||||
[SetUp]
|
||||
public void Setup() {
|
||||
this.mockery = new MockFactory();
|
||||
|
||||
this.mockedSubscriber = this.mockery.CreateMock<IObservableCollectionSubscriber>();
|
||||
|
||||
this.observedList = new ObservableList<int>();
|
||||
this.observedList.Clearing += new EventHandler(
|
||||
this.mockedSubscriber.MockObject.Clearing
|
||||
);
|
||||
this.observedList.Cleared += new EventHandler(
|
||||
this.mockedSubscriber.MockObject.Cleared
|
||||
);
|
||||
this.observedList.ItemAdded += new EventHandler<ItemEventArgs<int>>(
|
||||
this.mockedSubscriber.MockObject.ItemAdded
|
||||
);
|
||||
this.observedList.ItemRemoved += new EventHandler<ItemEventArgs<int>>(
|
||||
this.mockedSubscriber.MockObject.ItemRemoved
|
||||
);
|
||||
this.observedList.ItemReplaced += new EventHandler<ItemReplaceEventArgs<int>>(
|
||||
this.mockedSubscriber.MockObject.ItemReplaced
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the Clearing event is fired</summary>
|
||||
[Test]
|
||||
public void TestClearingEvent() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.Clearing(null, null)).WithAnyArguments();
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.Cleared(null, null)).WithAnyArguments();
|
||||
this.observedList.Clear();
|
||||
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the ItemAdded event is fired</summary>
|
||||
[Test]
|
||||
public void TestItemAddedEvent() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemAdded(null, null)).WithAnyArguments();
|
||||
|
||||
this.observedList.Add(123);
|
||||
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the ItemRemoved event is fired</summary>
|
||||
[Test]
|
||||
public void TestItemRemovedEvent() {
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemAdded(null, null)).WithAnyArguments();
|
||||
|
||||
this.observedList.Add(123);
|
||||
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemRemoved(null, null)).WithAnyArguments();
|
||||
|
||||
this.observedList.Remove(123);
|
||||
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
}
|
||||
|
||||
/// <summary>Tests whether items in the collection can be replaced</summary>
|
||||
[Test]
|
||||
public void TestItemReplacement() {
|
||||
this.mockedSubscriber.Expects.Exactly(3).Method(
|
||||
m => m.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
this.observedList.Add(1);
|
||||
this.observedList.Add(2);
|
||||
this.observedList.Add(3);
|
||||
|
||||
this.mockedSubscriber.Expects.One.Method(m => m.ItemReplaced(null, null)).WithAnyArguments();
|
||||
|
||||
// Replace the middle item with something else
|
||||
this.observedList[1] = 4;
|
||||
|
||||
Assert.AreEqual(
|
||||
1, this.observedList.IndexOf(4)
|
||||
);
|
||||
|
||||
this.mockery.VerifyAllExpectationsHaveBeenMet();
|
||||
}
|
||||
|
||||
/// <summary>Tests whether a the list constructor is working</summary>
|
||||
[Test]
|
||||
public void TestListConstructor() {
|
||||
int[] integers = new int[] { 12, 34, 56, 78 };
|
||||
|
||||
var testList = new ObservableList<int>(integers);
|
||||
|
||||
CollectionAssert.AreEqual(integers, testList);
|
||||
}
|
||||
|
||||
/// <summary>Mock object factory</summary>
|
||||
private MockFactory mockery;
|
||||
/// <summary>The mocked observable collection subscriber</summary>
|
||||
private Mock<IObservableCollectionSubscriber> mockedSubscriber;
|
||||
/// <summary>An observable collection to which a mock will be subscribed</summary>
|
||||
private ObservableList<int> observedList;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
||||
|
||||
#endif // !NO_NMOCK
|
300
Tests/Collections/ObservableSetTest.cs
Normal file
300
Tests/Collections/ObservableSetTest.cs
Normal file
|
@ -0,0 +1,300 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if !NO_SETS
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
using NUnit.Framework;
|
||||
using NMock;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the observable set wrapper</summary>
|
||||
[TestFixture]
|
||||
internal class ObservableSetTest {
|
||||
|
||||
#region interface IObservableCollectionSubscriber<TItem>
|
||||
|
||||
public interface IObservableCollectionSubscriber<TItem> {
|
||||
|
||||
/// <summary>Called when an item has been added to the collection</summary>
|
||||
void ItemAdded(object sender, ItemEventArgs<TItem> arguments);
|
||||
/// <summary>Called when an item is removed from the collection</summary>
|
||||
void ItemRemoved(object sender, ItemEventArgs<TItem> arguments);
|
||||
/// <summary>Called when an item is replaced in the collection</summary>
|
||||
void ItemReplaced(object sender, ItemReplaceEventArgs<TItem> arguments);
|
||||
/// <summary>Called when the collection is about to be cleared</summary>
|
||||
void Clearing(object sender, EventArgs arguments);
|
||||
/// <summary>Called when the collection has been cleared</summary>
|
||||
void Cleared(object sender, EventArgs arguments);
|
||||
|
||||
}
|
||||
|
||||
#endregion // interface IObservableCollectionSubscriber<TItem>
|
||||
|
||||
/// <summary>Called before each test is run</summary>
|
||||
[SetUp]
|
||||
public void Setup() {
|
||||
this.mockFactory = new MockFactory();
|
||||
this.observableSet = new ObservableSet<int>();
|
||||
|
||||
this.subscriber = this.mockFactory.CreateMock<IObservableCollectionSubscriber<int>>();
|
||||
this.observableSet.ItemAdded += this.subscriber.MockObject.ItemAdded;
|
||||
this.observableSet.ItemRemoved += this.subscriber.MockObject.ItemRemoved;
|
||||
this.observableSet.ItemReplaced += this.subscriber.MockObject.ItemReplaced;
|
||||
this.observableSet.Clearing += this.subscriber.MockObject.Clearing;
|
||||
this.observableSet.Cleared += this.subscriber.MockObject.Cleared;
|
||||
}
|
||||
|
||||
/// <summary>Called after each test has run</summary>
|
||||
[TearDown]
|
||||
public void Teardown() {
|
||||
if(this.mockFactory != null) {
|
||||
this.mockFactory.VerifyAllExpectationsHaveBeenMet();
|
||||
|
||||
this.subscriber = null;
|
||||
this.mockFactory.Dispose();
|
||||
this.mockFactory = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the observable set has a default constructor
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void HasDefaultConstructor() {
|
||||
Assert.IsNotNull(new ObservableSet<int>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that adding items to the set triggers the 'ItemAdded' event
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AddingItemsTriggersEvent() {
|
||||
this.subscriber.Expects.One.Method((s) => s.ItemAdded(null, null)).WithAnyArguments();
|
||||
this.observableSet.Add(123);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that removing items from the set triggers the 'ItemRemoved' event
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void RemovingItemsTriggersEvent() {
|
||||
this.subscriber.Expects.One.Method((s) => s.ItemAdded(null, null)).WithAnyArguments();
|
||||
this.observableSet.Add(123);
|
||||
|
||||
this.subscriber.Expects.One.Method((s) => s.ItemRemoved(null, null)).WithAnyArguments();
|
||||
this.observableSet.Remove(123);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that adding items to the set triggers the 'ItemAdded' event
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AddingAlreadyContainedItemDoesNotTriggerEvent() {
|
||||
this.subscriber.Expects.One.Method((s) => s.ItemAdded(null, null)).WithAnyArguments();
|
||||
this.observableSet.Add(123);
|
||||
|
||||
this.subscriber.Expects.No.Method((s) => s.ItemAdded(null, null)).WithAnyArguments();
|
||||
this.observableSet.Add(123);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that excepting the set with itself empties the set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ExceptWithSelfEmptiesSet() {
|
||||
this.subscriber.Expects.Exactly(3).Method(
|
||||
(s) => s.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
this.observableSet.Add(1);
|
||||
this.observableSet.Add(2);
|
||||
this.observableSet.Add(3);
|
||||
|
||||
Assert.AreEqual(3, this.observableSet.Count);
|
||||
|
||||
this.subscriber.Expects.One.Method((s) => s.Clearing(null, null)).WithAnyArguments();
|
||||
this.subscriber.Expects.One.Method((s) => s.Cleared(null, null)).WithAnyArguments();
|
||||
|
||||
this.observableSet.ExceptWith(this.observableSet);
|
||||
Assert.AreEqual(0, this.observableSet.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a set can be excepted with a collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SetCanBeExceptedWithCollection() {
|
||||
this.subscriber.Expects.Exactly(2).Method(
|
||||
(s) => s.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
this.observableSet.Add(1);
|
||||
this.observableSet.Add(2);
|
||||
|
||||
var collection = new List<int>() { 1 };
|
||||
|
||||
this.subscriber.Expects.One.Method((s) => s.ItemRemoved(null, null)).WithAnyArguments();
|
||||
this.observableSet.ExceptWith(collection);
|
||||
Assert.AreEqual(1, this.observableSet.Count);
|
||||
Assert.IsTrue(this.observableSet.Contains(2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a set can be intersected with a collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SetCanBeIntersectedWithCollection() {
|
||||
this.subscriber.Expects.Exactly(2).Method(
|
||||
(s) => s.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
this.observableSet.Add(1);
|
||||
this.observableSet.Add(2);
|
||||
|
||||
var collection = new List<int>() { 1 };
|
||||
|
||||
this.subscriber.Expects.One.Method((s) => s.ItemRemoved(null, null)).WithAnyArguments();
|
||||
this.observableSet.IntersectWith(collection);
|
||||
Assert.AreEqual(1, this.observableSet.Count);
|
||||
Assert.IsTrue(this.observableSet.Contains(1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to determine whether a set is a proper subset
|
||||
/// or superset of another set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanDetermineProperSubsetAndSuperset() {
|
||||
var set1 = new ObservableSet<int>() { 1, 2, 3 };
|
||||
var set2 = new HashSet<int>() { 1, 3 };
|
||||
|
||||
Assert.IsTrue(set1.IsProperSupersetOf(set2));
|
||||
Assert.IsTrue(set2.IsProperSubsetOf(set1));
|
||||
|
||||
set2.Add(2);
|
||||
|
||||
Assert.IsFalse(set1.IsProperSupersetOf(set2));
|
||||
Assert.IsFalse(set2.IsProperSubsetOf(set1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to determine whether a set is a subset
|
||||
/// or a superset of another set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanDetermineSubsetAndSuperset() {
|
||||
var set1 = new ObservableSet<int>() { 1, 2, 3 };
|
||||
var set2 = new HashSet<int>() { 1, 2, 3 };
|
||||
|
||||
Assert.IsTrue(set1.IsSupersetOf(set2));
|
||||
Assert.IsTrue(set2.IsSubsetOf(set1));
|
||||
|
||||
set2.Add(4);
|
||||
|
||||
Assert.IsFalse(set1.IsSupersetOf(set2));
|
||||
Assert.IsFalse(set2.IsSubsetOf(set1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a set can determine if another set overlaps with it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanDetermineOverlap() {
|
||||
var set1 = new ObservableSet<int>() { 1, 3, 5 };
|
||||
var set2 = new HashSet<int>() { 3 };
|
||||
|
||||
Assert.IsTrue(set1.Overlaps(set2));
|
||||
Assert.IsTrue(set2.Overlaps(set1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a set can determine if another set contains the same elements
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanDetermineSetEquality() {
|
||||
var set1 = new ObservableSet<int>() { 1, 3, 5 };
|
||||
var set2 = new HashSet<int>() { 3, 1, 5 };
|
||||
|
||||
Assert.IsTrue(set1.SetEquals(set2));
|
||||
Assert.IsTrue(set2.SetEquals(set1));
|
||||
|
||||
set1.Add(7);
|
||||
|
||||
Assert.IsFalse(set1.SetEquals(set2));
|
||||
Assert.IsFalse(set2.SetEquals(set1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a set can be symmetrically excepted with another set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanBeSymmetricallyExcepted() {
|
||||
var set1 = new ObservableSet<int>() { 1, 2, 3 };
|
||||
var set2 = new HashSet<int>() { 3, 4, 5 };
|
||||
|
||||
set1.SymmetricExceptWith(set2);
|
||||
|
||||
Assert.AreEqual(4, set1.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a union of two sets can be built
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanBeUnioned() {
|
||||
this.subscriber.Expects.Exactly(3).Method(
|
||||
(s) => s.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
|
||||
this.observableSet.Add(1);
|
||||
this.observableSet.Add(2);
|
||||
this.observableSet.Add(3);
|
||||
|
||||
var set2 = new ObservableSet<int>() { 3, 4, 5 };
|
||||
|
||||
this.subscriber.Expects.Exactly(2).Method(
|
||||
(s) => s.ItemAdded(null, null)
|
||||
).WithAnyArguments();
|
||||
this.observableSet.UnionWith(set2);
|
||||
Assert.AreEqual(5, this.observableSet.Count);
|
||||
}
|
||||
|
||||
/// <summary>Creates mock object for the test</summary>
|
||||
private MockFactory mockFactory;
|
||||
/// <summary>Observable set being tested</summary>
|
||||
private ObservableSet<int> observableSet;
|
||||
/// <summary>Subscriber for the observable set's events</summary>
|
||||
private Mock<IObservableCollectionSubscriber<int>> subscriber;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
||||
|
||||
#endif // !NO_SETS
|
150
Tests/Collections/PairPriorityQueueTest.cs
Normal file
150
Tests/Collections/PairPriorityQueueTest.cs
Normal file
|
@ -0,0 +1,150 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the priority queue class</summary>
|
||||
[TestFixture]
|
||||
internal class PairPriorityQueueTest {
|
||||
|
||||
/// <summary>Tests to ensure the count property is properly updated</summary>
|
||||
[Test]
|
||||
public void TestCount() {
|
||||
PairPriorityQueue<float, string> testQueue = new PairPriorityQueue<float, string>();
|
||||
|
||||
Assert.AreEqual(0, testQueue.Count);
|
||||
testQueue.Enqueue(12.34f, "a");
|
||||
Assert.AreEqual(1, testQueue.Count);
|
||||
testQueue.Enqueue(56.78f, "b");
|
||||
Assert.AreEqual(2, testQueue.Count);
|
||||
testQueue.Dequeue();
|
||||
Assert.AreEqual(1, testQueue.Count);
|
||||
testQueue.Enqueue(9.0f, "c");
|
||||
Assert.AreEqual(2, testQueue.Count);
|
||||
testQueue.Clear();
|
||||
Assert.AreEqual(0, testQueue.Count);
|
||||
}
|
||||
|
||||
/// <summary>Tests to ensure that the priority collection actually sorts items</summary>
|
||||
[Test]
|
||||
public void TestOrdering() {
|
||||
PairPriorityQueue<float, string> testQueue = new PairPriorityQueue<float, string>();
|
||||
|
||||
testQueue.Enqueue(1.0f, "a");
|
||||
testQueue.Enqueue(9.0f, "i");
|
||||
testQueue.Enqueue(2.0f, "b");
|
||||
testQueue.Enqueue(8.0f, "h");
|
||||
testQueue.Enqueue(3.0f, "c");
|
||||
testQueue.Enqueue(7.0f, "g");
|
||||
testQueue.Enqueue(4.0f, "d");
|
||||
testQueue.Enqueue(6.0f, "f");
|
||||
testQueue.Enqueue(5.0f, "e");
|
||||
|
||||
Assert.AreEqual("i", testQueue.Dequeue().Item);
|
||||
Assert.AreEqual("h", testQueue.Dequeue().Item);
|
||||
Assert.AreEqual("g", testQueue.Dequeue().Item);
|
||||
Assert.AreEqual("f", testQueue.Dequeue().Item);
|
||||
Assert.AreEqual("e", testQueue.Dequeue().Item);
|
||||
Assert.AreEqual("d", testQueue.Dequeue().Item);
|
||||
Assert.AreEqual("c", testQueue.Dequeue().Item);
|
||||
Assert.AreEqual("b", testQueue.Dequeue().Item);
|
||||
Assert.AreEqual("a", testQueue.Dequeue().Item);
|
||||
}
|
||||
|
||||
/// <summary>Tests to ensure that the priority collection's Peek() method works</summary>
|
||||
[Test]
|
||||
public void TestPeek() {
|
||||
PairPriorityQueue<float, string> testQueue = new PairPriorityQueue<float, string>();
|
||||
|
||||
testQueue.Enqueue(1.0f, "a");
|
||||
testQueue.Enqueue(2.0f, "b");
|
||||
testQueue.Enqueue(0.0f, "c");
|
||||
|
||||
Assert.AreEqual("b", testQueue.Peek().Item);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the priority collection can copy itself into an array</summary>
|
||||
[Test]
|
||||
public void TestCopyTo() {
|
||||
PairPriorityQueue<float, string> testQueue = new PairPriorityQueue<float, string>();
|
||||
|
||||
testQueue.Enqueue(1.0f, "a");
|
||||
testQueue.Enqueue(9.0f, "i");
|
||||
testQueue.Enqueue(2.0f, "b");
|
||||
testQueue.Enqueue(8.0f, "h");
|
||||
testQueue.Enqueue(3.0f, "c");
|
||||
testQueue.Enqueue(7.0f, "g");
|
||||
testQueue.Enqueue(4.0f, "d");
|
||||
testQueue.Enqueue(6.0f, "f");
|
||||
testQueue.Enqueue(5.0f, "e");
|
||||
|
||||
PriorityItemPair<float, string>[] itemArray = new PriorityItemPair<float, string>[9];
|
||||
testQueue.CopyTo(itemArray, 0);
|
||||
|
||||
CollectionAssert.AreEquivalent(testQueue, itemArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the priority collection provides a synchronization root
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSyncRoot() {
|
||||
PairPriorityQueue<int, int> testQueue = new PairPriorityQueue<int, int>();
|
||||
|
||||
// If IsSynchronized returns true, SyncRoot is allowed to be null
|
||||
if(!testQueue.IsSynchronized) {
|
||||
lock(testQueue.SyncRoot) {
|
||||
testQueue.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the priority collection provides a working type-safe enumerator
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestEnumerator() {
|
||||
PairPriorityQueue<float, string> testQueue = new PairPriorityQueue<float, string>();
|
||||
|
||||
testQueue.Enqueue(1.0f, "a");
|
||||
testQueue.Enqueue(2.0f, "b");
|
||||
testQueue.Enqueue(0.0f, "c");
|
||||
|
||||
List<PriorityItemPair<float, string>> testList =
|
||||
new List<PriorityItemPair<float,string>>();
|
||||
|
||||
foreach(PriorityItemPair<float, string> entry in testQueue) {
|
||||
testList.Add(entry);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEquivalent(testQueue, testList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
100
Tests/Collections/ParentableTest.cs
Normal file
100
Tests/Collections/ParentableTest.cs
Normal file
|
@ -0,0 +1,100 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the Parentable class</summary>
|
||||
[TestFixture]
|
||||
internal class ParentableTest {
|
||||
|
||||
#region class TestParentable
|
||||
|
||||
/// <summary>Parentable object that can be the child of an int</summary>
|
||||
private class TestParentable : Parentable<int> {
|
||||
|
||||
/// <summary>Initializes a new instance of the parentable test class</summary>
|
||||
public TestParentable() { }
|
||||
|
||||
/// <summary>The parent object that owns this instance</summary>
|
||||
public int GetParent() {
|
||||
return base.Parent;
|
||||
}
|
||||
|
||||
/// <summary>Invoked whenever the instance's owner changes</summary>
|
||||
/// <remarks>
|
||||
/// When items are parented for the first time, the oldParent argument will
|
||||
/// be null. Also, if the element is removed from the collection, the
|
||||
/// current parent will be null.
|
||||
/// </remarks>
|
||||
/// <param name="oldParent">Previous owner of the instance</param>
|
||||
protected override void OnParentChanged(int oldParent) {
|
||||
this.parentChangedCalled = true;
|
||||
|
||||
base.OnParentChanged(oldParent); // to satisfy NCover :-/
|
||||
}
|
||||
|
||||
/// <summary>Whether the OnParentChanged method has been called</summary>
|
||||
public bool ParentChangedCalled {
|
||||
get { return this.parentChangedCalled; }
|
||||
}
|
||||
|
||||
/// <summary>Whether the OnParentChanged method has been called</summary>
|
||||
private bool parentChangedCalled;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class TestParentable
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether a parent can be assigned and then retrieved from
|
||||
/// the parentable object
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestParentAssignment() {
|
||||
TestParentable testParentable = new TestParentable();
|
||||
|
||||
testParentable.SetParent(12345);
|
||||
Assert.AreEqual(12345, testParentable.GetParent());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether a parent can be assigned and then retrieved from
|
||||
/// the parentable object
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestParentChangedNotification() {
|
||||
TestParentable testParentable = new TestParentable();
|
||||
|
||||
testParentable.SetParent(12345);
|
||||
|
||||
Assert.IsTrue(testParentable.ParentChangedCalled);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
189
Tests/Collections/ParentingCollectionTest.cs
Normal file
189
Tests/Collections/ParentingCollectionTest.cs
Normal file
|
@ -0,0 +1,189 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the Parenting Collection class</summary>
|
||||
[TestFixture]
|
||||
internal class ParentingCollectionTest {
|
||||
|
||||
#region class TestParentable
|
||||
|
||||
/// <summary>Parentable object that can be the child of an int</summary>
|
||||
private class TestParentable : Parentable<int>, IDisposable {
|
||||
|
||||
/// <summary>Initializes a new instance of the parentable test class</summary>
|
||||
public TestParentable() { }
|
||||
|
||||
/// <summary>The parent object that owns this instance</summary>
|
||||
public int GetParent() {
|
||||
return base.Parent;
|
||||
}
|
||||
|
||||
/// <summary>Immediately releases all resources owned by the item</summary>
|
||||
public void Dispose() {
|
||||
this.disposeCalled = true;
|
||||
}
|
||||
|
||||
/// <summary>Whether Dispose() has been called on this item</summary>
|
||||
public bool DisposeCalled {
|
||||
get { return this.disposeCalled; }
|
||||
}
|
||||
|
||||
/// <summary>Whether Dispose() has been called on this item</summary>
|
||||
private bool disposeCalled;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class TestParentable
|
||||
|
||||
#region class TestParentingCollection
|
||||
|
||||
/// <summary>Parentable object that can be the child of an int</summary>
|
||||
private class TestParentingCollection : ParentingCollection<int, TestParentable> {
|
||||
|
||||
/// <summary>Changes the parent of the collection</summary>
|
||||
/// <param name="parent">New parent to assign to the collection</param>
|
||||
public void SetParent(int parent) {
|
||||
base.Reparent(parent);
|
||||
}
|
||||
|
||||
/// <summary>Disposes all items contained in the collection</summary>
|
||||
public new void DisposeItems() {
|
||||
base.DisposeItems();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion // class TestParentingCollection
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the parenting collection propagates its parent to an item that
|
||||
/// is added to the collection after the collection's aprent is already assigned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestPropagatePreassignedParent() {
|
||||
TestParentingCollection testCollection = new TestParentingCollection();
|
||||
TestParentable testParentable = new TestParentable();
|
||||
|
||||
testCollection.SetParent(54321);
|
||||
testCollection.Add(testParentable);
|
||||
|
||||
Assert.AreEqual(54321, testParentable.GetParent());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the parenting collection propagates a new parent to all items
|
||||
/// contained in it when its parent is changed
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestPropagateParentChange() {
|
||||
TestParentingCollection testCollection = new TestParentingCollection();
|
||||
TestParentable testParentable = new TestParentable();
|
||||
|
||||
testCollection.Add(testParentable);
|
||||
testCollection.SetParent(54321);
|
||||
|
||||
Assert.AreEqual(54321, testParentable.GetParent());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the parenting collection propagates its parent to an item that
|
||||
/// is added to the collection after the collection's aprent is already assigned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestPropagateParentOnReplace() {
|
||||
TestParentingCollection testCollection = new TestParentingCollection();
|
||||
TestParentable testParentable1 = new TestParentable();
|
||||
TestParentable testParentable2 = new TestParentable();
|
||||
|
||||
testCollection.SetParent(54321);
|
||||
testCollection.Add(testParentable1);
|
||||
testCollection[0] = testParentable2;
|
||||
|
||||
Assert.AreEqual(0, testParentable1.GetParent());
|
||||
Assert.AreEqual(54321, testParentable2.GetParent());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the parenting collection unsets the parent when an item is removed
|
||||
/// from the collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestUnsetParentOnRemoveItem() {
|
||||
TestParentingCollection testCollection = new TestParentingCollection();
|
||||
TestParentable testParentable = new TestParentable();
|
||||
|
||||
testCollection.Add(testParentable);
|
||||
testCollection.SetParent(54321);
|
||||
|
||||
Assert.AreEqual(54321, testParentable.GetParent());
|
||||
|
||||
testCollection.RemoveAt(0);
|
||||
|
||||
Assert.AreEqual(0, testParentable.GetParent());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the parenting collection unsets the parent when all item are
|
||||
/// removed from the collection by clearing it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestUnsetParentOnClear() {
|
||||
TestParentingCollection testCollection = new TestParentingCollection();
|
||||
TestParentable testParentable = new TestParentable();
|
||||
|
||||
testCollection.Add(testParentable);
|
||||
testCollection.SetParent(54321);
|
||||
|
||||
Assert.AreEqual(54321, testParentable.GetParent());
|
||||
|
||||
testCollection.Clear();
|
||||
|
||||
Assert.AreEqual(0, testParentable.GetParent());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the parenting collection calls Dispose() on all contained items
|
||||
/// that implement IDisposable when its DisposeItems() method is called
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDisposeItems() {
|
||||
TestParentingCollection testCollection = new TestParentingCollection();
|
||||
TestParentable testParentable = new TestParentable();
|
||||
|
||||
testCollection.Add(testParentable);
|
||||
|
||||
testCollection.DisposeItems();
|
||||
|
||||
Assert.IsTrue(testParentable.DisposeCalled);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
117
Tests/Collections/PoolTest.cs
Normal file
117
Tests/Collections/PoolTest.cs
Normal file
|
@ -0,0 +1,117 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit tests for the Pool class</summary>
|
||||
[TestFixture]
|
||||
internal class PoolTest {
|
||||
|
||||
#region class TestClass
|
||||
|
||||
/// <summary>Used to test the pool</summary>
|
||||
private class TestClass : IRecyclable {
|
||||
|
||||
/// <summary>Returns the object to its initial state</summary>
|
||||
public void Recycle() {
|
||||
this.Recycled = true;
|
||||
}
|
||||
|
||||
/// <summary>Whether the instance has been recycled</summary>
|
||||
public bool Recycled;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class TestClass
|
||||
|
||||
#region class NoDefaultConstructor
|
||||
|
||||
/// <summary>Used to test the pool</summary>
|
||||
private class NoDefaultConstructor {
|
||||
|
||||
/// <summary>Private constructor so no instances can be created</summary>
|
||||
private NoDefaultConstructor() { }
|
||||
|
||||
}
|
||||
|
||||
#endregion // class NoDefaultConstructor
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the pool can return newly constructed objects
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void NewInstancesCanBeObtained() {
|
||||
Pool<TestClass> pool = new Pool<TestClass>();
|
||||
Assert.IsNotNull(pool.Get());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown if the pool's default instance creator is used
|
||||
/// on a type that doesn't have a default constructor
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void UsingDefaultInstanceCreatorRequiresDefaultConstructor() {
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { new Pool<NoDefaultConstructor>(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the pool can redeem objects that are no longer used
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void InstancesCanBeRedeemed() {
|
||||
Pool<TestClass> pool = new Pool<TestClass>();
|
||||
pool.Redeem(new TestClass());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the Recycle() method is called at the appropriate time
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void RedeemedItemsWillBeRecycled() {
|
||||
Pool<TestClass> pool = new Pool<TestClass>();
|
||||
TestClass x = new TestClass();
|
||||
|
||||
Assert.IsFalse(x.Recycled);
|
||||
pool.Redeem(x);
|
||||
Assert.IsTrue(x.Recycled);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the pool's Capacity is applied correctly</summary>
|
||||
[Test]
|
||||
public void PoolCapacityCanBeAdjusted() {
|
||||
Pool<TestClass> pool = new Pool<TestClass>(123);
|
||||
Assert.AreEqual(123, pool.Capacity);
|
||||
pool.Capacity = 321;
|
||||
Assert.AreEqual(321, pool.Capacity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
99
Tests/Collections/PriorityItemPairTest.cs
Normal file
99
Tests/Collections/PriorityItemPairTest.cs
Normal file
|
@ -0,0 +1,99 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the Priority/Item pair class</summary>
|
||||
[TestFixture]
|
||||
internal class PriorityItemPairTest {
|
||||
|
||||
#region class ToStringNullReturner
|
||||
|
||||
/// <summary>Test class in which ToString() can return null</summary>
|
||||
private class ToStringNullReturner {
|
||||
|
||||
/// <summary>
|
||||
/// Returns a System.String that represents the current System.Object
|
||||
/// </summary>
|
||||
/// <returns>A System.String that represents the current System.Object</returns>
|
||||
public override string ToString() { return null; }
|
||||
|
||||
}
|
||||
|
||||
#endregion // class ToStringNullReturner
|
||||
|
||||
/// <summary>Tests whether the pair's default constructor works</summary>
|
||||
[Test]
|
||||
public void TestDefaultConstructor() {
|
||||
new PriorityItemPair<int, string>();
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the priority can be retrieved from the pair</summary>
|
||||
[Test]
|
||||
public void TestPriorityRetrieval() {
|
||||
PriorityItemPair<int, string> testPair = new PriorityItemPair<int, string>(
|
||||
12345, "hello world"
|
||||
);
|
||||
|
||||
Assert.AreEqual(12345, testPair.Priority);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the item can be retrieved from the pair</summary>
|
||||
[Test]
|
||||
public void TestItemRetrieval() {
|
||||
PriorityItemPair<int, string> testPair = new PriorityItemPair<int, string>(
|
||||
12345, "hello world"
|
||||
);
|
||||
|
||||
Assert.AreEqual("hello world", testPair.Item);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the ToString() methods works with valid strings</summary>
|
||||
[Test]
|
||||
public void TestToStringWithValidStrings() {
|
||||
PriorityItemPair<string, string> testPair = new PriorityItemPair<string, string>(
|
||||
"hello", "world"
|
||||
);
|
||||
|
||||
Assert.AreEqual("[hello, world]", testPair.ToString());
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the ToString() methods works with null strings</summary>
|
||||
[Test]
|
||||
public void TestToStringWithNullStrings() {
|
||||
PriorityItemPair<ToStringNullReturner, ToStringNullReturner> testPair =
|
||||
new PriorityItemPair<ToStringNullReturner, ToStringNullReturner>(
|
||||
new ToStringNullReturner(), new ToStringNullReturner()
|
||||
);
|
||||
|
||||
Assert.AreEqual("[, ]", testPair.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
157
Tests/Collections/PriorityQueueTest.cs
Normal file
157
Tests/Collections/PriorityQueueTest.cs
Normal file
|
@ -0,0 +1,157 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the priority queue class</summary>
|
||||
[TestFixture]
|
||||
internal class PriorityQueueTest {
|
||||
|
||||
#region class FloatComparer
|
||||
|
||||
/// <summary>Comparer for two floating point values</summary>
|
||||
private class FloatComparer : IComparer<float> {
|
||||
|
||||
/// <summary>The default instance of this comparer</summary>
|
||||
public static readonly FloatComparer Default = new FloatComparer();
|
||||
|
||||
/// <summary>Compares two floating points against each other</summary>
|
||||
/// <param name="left">First float to compare</param>
|
||||
/// <param name="right">Second float to compare</param>
|
||||
/// <returns>The relationship of the two floats to each other</returns>
|
||||
public int Compare(float left, float right) {
|
||||
return Math.Sign(left - right);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion // class FloatComparer
|
||||
|
||||
/// <summary>Tests to ensure the count property is properly updated</summary>
|
||||
[Test]
|
||||
public void TestCount() {
|
||||
PriorityQueue<float> testQueue = new PriorityQueue<float>(FloatComparer.Default);
|
||||
|
||||
Assert.AreEqual(0, testQueue.Count);
|
||||
testQueue.Enqueue(12.34f);
|
||||
Assert.AreEqual(1, testQueue.Count);
|
||||
testQueue.Enqueue(56.78f);
|
||||
Assert.AreEqual(2, testQueue.Count);
|
||||
testQueue.Dequeue();
|
||||
Assert.AreEqual(1, testQueue.Count);
|
||||
testQueue.Enqueue(9.0f);
|
||||
Assert.AreEqual(2, testQueue.Count);
|
||||
testQueue.Clear();
|
||||
Assert.AreEqual(0, testQueue.Count);
|
||||
}
|
||||
|
||||
/// <summary>Tests to ensure that the priority collection actually sorts items</summary>
|
||||
[Test]
|
||||
public void TestOrdering() {
|
||||
PriorityQueue<float> testQueue = new PriorityQueue<float>(FloatComparer.Default);
|
||||
|
||||
testQueue.Enqueue(1.0f);
|
||||
testQueue.Enqueue(9.0f);
|
||||
testQueue.Enqueue(2.0f);
|
||||
testQueue.Enqueue(8.0f);
|
||||
testQueue.Enqueue(3.0f);
|
||||
testQueue.Enqueue(7.0f);
|
||||
testQueue.Enqueue(4.0f);
|
||||
testQueue.Enqueue(6.0f);
|
||||
testQueue.Enqueue(5.0f);
|
||||
|
||||
Assert.AreEqual(9.0f, testQueue.Dequeue());
|
||||
Assert.AreEqual(8.0f, testQueue.Dequeue());
|
||||
Assert.AreEqual(7.0f, testQueue.Dequeue());
|
||||
Assert.AreEqual(6.0f, testQueue.Dequeue());
|
||||
Assert.AreEqual(5.0f, testQueue.Dequeue());
|
||||
Assert.AreEqual(4.0f, testQueue.Dequeue());
|
||||
Assert.AreEqual(3.0f, testQueue.Dequeue());
|
||||
Assert.AreEqual(2.0f, testQueue.Dequeue());
|
||||
Assert.AreEqual(1.0f, testQueue.Dequeue());
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Tests whether the priority queue's enumerators are invalidated when the queue's
|
||||
/// contents are modified
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestEnumeratorInvalidationOnModify() {
|
||||
PriorityQueue<int> testQueue = new PriorityQueue<int>();
|
||||
IEnumerator<int> testQueueEnumerator = testQueue.GetEnumerator();
|
||||
|
||||
testQueue.Enqueue(123);
|
||||
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { testQueueEnumerator.MoveNext(); }
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown when Peek() is called on an empty queue
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestPeekEmptyQueue() {
|
||||
PriorityQueue<int> testQueue = new PriorityQueue<int>();
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { testQueue.Peek(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown when Dequeue() is called on an empty queue
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDequeueEmptyQueue() {
|
||||
PriorityQueue<int> testQueue = new PriorityQueue<int>();
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
delegate() { testQueue.Dequeue(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the priority queue can handle large amounts of data
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestLargeQueue() {
|
||||
PriorityQueue<int> testQueue = new PriorityQueue<int>();
|
||||
List<int> testList = new List<int>();
|
||||
|
||||
for(int index = 0; index < 1000; ++index) {
|
||||
testQueue.Enqueue(index * 2);
|
||||
testList.Add(index * 2);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEquivalent(testList, testQueue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
162
Tests/Collections/ReadOnlyCollectionTest.cs
Normal file
162
Tests/Collections/ReadOnlyCollectionTest.cs
Normal file
|
@ -0,0 +1,162 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the read only collection wrapper</summary>
|
||||
[TestFixture]
|
||||
internal class ReadOnlyCollectionTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the copy constructor of the read only collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyConstructor() {
|
||||
int[] integers = new int[] { 12, 34, 56, 78 };
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(integers);
|
||||
|
||||
CollectionAssert.AreEqual(integers, testCollection);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the IsReadOnly property returns true</summary>
|
||||
[Test]
|
||||
public void TestIsReadOnly() {
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(new int[0]);
|
||||
|
||||
Assert.IsTrue(testCollection.IsReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() of the read only collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArray() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(inputIntegers);
|
||||
|
||||
int[] outputIntegers = new int[testCollection.Count];
|
||||
testCollection.CopyTo(outputIntegers, 0);
|
||||
|
||||
CollectionAssert.AreEqual(inputIntegers, outputIntegers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the read only collection is able to
|
||||
/// determine if the collection contains an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContains() {
|
||||
int[] integers = new int[] { 1234, 6789 };
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(integers);
|
||||
|
||||
Assert.IsTrue(testCollection.Contains(1234));
|
||||
Assert.IsFalse(testCollection.Contains(4321));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the Add() method of the read only collection throws an exception
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAdd() {
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as ICollection<int>).Add(123); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the Remove() method of the read only collection throws an exception
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemove() {
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as ICollection<int>).Remove(123); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the Clear() method of the read only collection throws an exception
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnClear() {
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as ICollection<int>).Clear(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the typesafe enumerator of the read only collection is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTypesafeEnumerator() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(inputIntegers);
|
||||
|
||||
List<int> outputIntegers = new List<int>();
|
||||
foreach(int value in testCollection) {
|
||||
outputIntegers.Add(value);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEqual(inputIntegers, outputIntegers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() of the read only collection works if invoked via
|
||||
/// the ICollection interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArrayViaICollection() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(inputIntegers);
|
||||
|
||||
int[] outputIntegers = new int[testCollection.Count];
|
||||
(testCollection as ICollection).CopyTo(outputIntegers, 0);
|
||||
|
||||
CollectionAssert.AreEqual(inputIntegers, outputIntegers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the IsSynchronized property and the SyncRoot property are working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronization() {
|
||||
ReadOnlyCollection<int> testCollection = new ReadOnlyCollection<int>(new int[0]);
|
||||
|
||||
if(!(testCollection as ICollection).IsSynchronized) {
|
||||
lock((testCollection as ICollection).SyncRoot) {
|
||||
Assert.AreEqual(0, testCollection.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
509
Tests/Collections/ReadOnlyDictionaryTest.cs
Normal file
509
Tests/Collections/ReadOnlyDictionaryTest.cs
Normal file
|
@ -0,0 +1,509 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the read only dictionary wrapper</summary>
|
||||
[TestFixture]
|
||||
internal class ReadOnlyDictionaryTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the copy constructor of the read only dictionary works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyConstructor() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
CollectionAssert.AreEqual(numbers, testDictionary);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the IsReadOnly property returns true</summary>
|
||||
[Test]
|
||||
public void TestIsReadOnly() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.IsTrue(testDictionary.IsReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the read only dictionary is able to
|
||||
/// determine if the dictionary contains an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContains() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.IsTrue(
|
||||
testDictionary.Contains(new KeyValuePair<int, string>(42, "forty-two"))
|
||||
);
|
||||
Assert.IsFalse(
|
||||
testDictionary.Contains(new KeyValuePair<int, string>(24, "twenty-four"))
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the read only dictionary is able to
|
||||
/// determine if the dictionary contains a key
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContainsKey() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.IsTrue(testDictionary.ContainsKey(42));
|
||||
Assert.IsFalse(testDictionary.ContainsKey(24));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() of the read only dictionary works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArray() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
KeyValuePair<int, string>[] items = new KeyValuePair<int, string>[numbers.Count];
|
||||
|
||||
testDictionary.CopyTo(items, 0);
|
||||
|
||||
CollectionAssert.AreEqual(numbers, items);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the typesafe enumerator of the read only dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTypesafeEnumerator() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
List<KeyValuePair<int, string>> outputItems = new List<KeyValuePair<int, string>>();
|
||||
foreach(KeyValuePair<int, string> item in testDictionary) {
|
||||
outputItems.Add(item);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEqual(numbers, outputItems);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the keys collection of the read only dictionary can be queried
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetKeysCollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
ICollection<int> inputKeys = numbers.Keys;
|
||||
ICollection<int> keys = testDictionary.Keys;
|
||||
CollectionAssert.AreEqual(inputKeys, keys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the values collection of the read only dictionary can be queried
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetValuesCollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
ICollection<string> inputValues = numbers.Values;
|
||||
ICollection<string> values = testDictionary.Values;
|
||||
CollectionAssert.AreEqual(inputValues, values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the TryGetValue() method of the read only dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTryGetValue() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
string value;
|
||||
|
||||
Assert.IsTrue(testDictionary.TryGetValue(42, out value));
|
||||
Assert.AreEqual("forty-two", value);
|
||||
|
||||
Assert.IsFalse(testDictionary.TryGetValue(24, out value));
|
||||
Assert.AreEqual(null, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the retrieval of values using the indexer of the read only
|
||||
/// dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveValueByIndexer() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.AreEqual("forty-two", testDictionary[42]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether an exception is thrown if the indexer of the read only dictionary
|
||||
/// is used to attempt to retrieve a non-existing value
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRetrieveNonExistingValueByIndexer() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<KeyNotFoundException>(
|
||||
delegate() { Console.WriteLine(testDictionary[24]); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// Add() method is called via the generic IDictionary<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddViaGenericIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testDictionary as IDictionary<int, string>).Add(10, "ten"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// Remove() method is called via the generic IDictionary<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaGenericIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testDictionary as IDictionary<int, string>).Remove(3); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the TryGetValue() method of the read only dictionary is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveValueByIndexerViaGenericIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.AreEqual("forty-two", (testDictionary as IDictionary<int, string>)[42]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// indexer is used to insert an item via the generic IDictionar<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnReplaceByIndexerViaGenericIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testDictionary as IDictionary<int, string>)[24] = "twenty-four"; }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// Clear() method is called via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnClearViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testDictionary as IDictionary).Clear(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// Add() method is called via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testDictionary as IDictionary).Add(24, "twenty-four"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the read only dictionary is able to
|
||||
/// determine if the dictionary contains an item via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContainsViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.IsTrue((testDictionary as IDictionary).Contains(42));
|
||||
Assert.IsFalse((testDictionary as IDictionary).Contains(24));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the GetEnumerator() method of the read only dictionary returns
|
||||
/// a working enumerator if accessed via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestEnumeratorViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Dictionary<int, string> outputNumbers = new Dictionary<int, string>();
|
||||
foreach(DictionaryEntry entry in (testDictionary as IDictionary)) {
|
||||
(outputNumbers as IDictionary).Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEquivalent(numbers, outputNumbers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IsFixedSize property of the read only dictionary returns
|
||||
/// the expected result for a read only dictionary based on a dynamic dictionary
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIsFixedSizeViaIList() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.IsFalse((testDictionary as IDictionary).IsFixedSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the keys collection of the read only dictionary can be queried
|
||||
/// via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetKeysCollectionViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
ICollection inputKeys = (numbers as IDictionary).Keys;
|
||||
ICollection keys = (testDictionary as IDictionary).Keys;
|
||||
CollectionAssert.AreEqual(inputKeys, keys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the values collection of the read only dictionary can be queried
|
||||
/// via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestGetValuesCollectionViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
ICollection inputValues = (numbers as IDictionary).Values;
|
||||
ICollection values = (testDictionary as IDictionary).Values;
|
||||
CollectionAssert.AreEqual(inputValues, values);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// Remove() method is called via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testDictionary as IDictionary).Remove(3); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the retrieval of values using the indexer of the read only
|
||||
/// dictionary is working via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveValueByIndexerViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.AreEqual("forty-two", (testDictionary as IDictionary)[42]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// indexer is used to insert an item via the IDictionary interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnReplaceByIndexerViaIDictionary() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testDictionary as IDictionary)[24] = "twenty-four"; }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// Add() method is used via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddViaGenericICollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() {
|
||||
(testDictionary as ICollection<KeyValuePair<int, string>>).Add(
|
||||
new KeyValuePair<int, string>(24, "twenty-four")
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// Clear() method is used via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnClearViaGenericICollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testDictionary as ICollection<KeyValuePair<int, string>>).Clear(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only dictionary will throw an exception if its
|
||||
/// Remove() method is used via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaGenericICollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() {
|
||||
(testDictionary as ICollection<KeyValuePair<int, string>>).Remove(
|
||||
new KeyValuePair<int, string>(42, "fourty-two")
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() of the read only dictionary works when called
|
||||
/// via the the ICollection interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArrayViaICollection() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
DictionaryEntry[] entries = new DictionaryEntry[numbers.Count];
|
||||
(testDictionary as ICollection).CopyTo(entries, 0);
|
||||
|
||||
KeyValuePair<int, string>[] items = new KeyValuePair<int, string>[numbers.Count];
|
||||
for(int index = 0; index < entries.Length; ++index) {
|
||||
items[index] = new KeyValuePair<int, string>(
|
||||
(int)entries[index].Key, (string)entries[index].Value
|
||||
);
|
||||
}
|
||||
CollectionAssert.AreEquivalent(numbers, items);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the IsSynchronized property and the SyncRoot property are working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronization() {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary = makeReadOnly(numbers);
|
||||
|
||||
if(!(testDictionary as ICollection).IsSynchronized) {
|
||||
lock((testDictionary as ICollection).SyncRoot) {
|
||||
Assert.AreEqual(numbers.Count, testDictionary.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the read only dictionary can be serialized
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSerialization() {
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
|
||||
using(MemoryStream memory = new MemoryStream()) {
|
||||
Dictionary<int, string> numbers = createTestDictionary();
|
||||
ReadOnlyDictionary<int, string> testDictionary1 = makeReadOnly(numbers);
|
||||
|
||||
formatter.Serialize(memory, testDictionary1);
|
||||
memory.Position = 0;
|
||||
object testDictionary2 = formatter.Deserialize(memory);
|
||||
|
||||
CollectionAssert.AreEquivalent(testDictionary1, (IEnumerable)testDictionary2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new read-only dictionary filled with some values for testing
|
||||
/// </summary>
|
||||
/// <returns>The newly created read-only dictionary</returns>
|
||||
private static Dictionary<int, string> createTestDictionary() {
|
||||
Dictionary<int, string> numbers = new Dictionary<int, string>();
|
||||
numbers.Add(1, "one");
|
||||
numbers.Add(2, "two");
|
||||
numbers.Add(3, "three");
|
||||
numbers.Add(42, "forty-two");
|
||||
return new Dictionary<int, string>(numbers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new read-only dictionary filled with some values for testing
|
||||
/// </summary>
|
||||
/// <returns>The newly created read-only dictionary</returns>
|
||||
private static ReadOnlyDictionary<int, string> makeReadOnly(
|
||||
IDictionary<int, string> dictionary
|
||||
) {
|
||||
return new ReadOnlyDictionary<int, string>(dictionary);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
380
Tests/Collections/ReadOnlyListTest.cs
Normal file
380
Tests/Collections/ReadOnlyListTest.cs
Normal file
|
@ -0,0 +1,380 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the read only list wrapper</summary>
|
||||
[TestFixture]
|
||||
internal class ReadOnlyListTest {
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the copy constructor of the read only list works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyConstructor() {
|
||||
int[] integers = new int[] { 12, 34, 56, 78 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
CollectionAssert.AreEqual(integers, testList);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the IsReadOnly property returns true</summary>
|
||||
[Test]
|
||||
public void TestIsReadOnly() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[0]);
|
||||
|
||||
Assert.IsTrue(testList.IsReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() of the read only list works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArray() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(inputIntegers);
|
||||
|
||||
int[] outputIntegers = new int[testList.Count];
|
||||
testList.CopyTo(outputIntegers, 0);
|
||||
|
||||
CollectionAssert.AreEqual(inputIntegers, outputIntegers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the read only list is able to
|
||||
/// determine if the list contains an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContains() {
|
||||
int[] integers = new int[] { 1234, 6789 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.IsTrue(testList.Contains(1234));
|
||||
Assert.IsFalse(testList.Contains(4321));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IndexOf() method of the read only list is able to
|
||||
/// determine if the index of an item in the list
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIndexOf() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.AreEqual(0, testList.IndexOf(12));
|
||||
Assert.AreEqual(1, testList.IndexOf(34));
|
||||
Assert.AreEqual(2, testList.IndexOf(67));
|
||||
Assert.AreEqual(3, testList.IndexOf(89));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the read only list is able to
|
||||
/// retrieve items from the list
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveByIndexer() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.AreEqual(12, testList[0]);
|
||||
Assert.AreEqual(34, testList[1]);
|
||||
Assert.AreEqual(67, testList[2]);
|
||||
Assert.AreEqual(89, testList[3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Insert() method
|
||||
/// is called via the generic IList<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnInsertViaGenericIList() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList<int>).Insert(0, 12345); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its RemoveAt() method
|
||||
/// is called via the generic IList<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaGenericIList() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[1]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList<int>).RemoveAt(0); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the read only list will throw an exception
|
||||
/// if it is attempted to be used for replacing an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveByIndexerViaGenericIList() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.AreEqual(12, (testList as IList<int>)[0]);
|
||||
Assert.AreEqual(34, (testList as IList<int>)[1]);
|
||||
Assert.AreEqual(67, (testList as IList<int>)[2]);
|
||||
Assert.AreEqual(89, (testList as IList<int>)[3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the read only list will throw an exception
|
||||
/// if it is attempted to be used for replacing an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnReplaceByIndexerViaGenericIList() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[1]);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList<int>)[0] = 12345; }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Add() method
|
||||
/// is called via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddViaGenericICollection() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as ICollection<int>).Add(12345); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Clear() method
|
||||
/// is called via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnClearViaGenericICollection() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[1]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as ICollection<int>).Clear(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Remove() method
|
||||
/// is called via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaGenericICollection() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as ICollection<int>).Remove(89); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the typesafe enumerator of the read only list is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTypesafeEnumerator() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(inputIntegers);
|
||||
|
||||
List<int> outputIntegers = new List<int>();
|
||||
foreach(int value in testList) {
|
||||
outputIntegers.Add(value);
|
||||
}
|
||||
|
||||
CollectionAssert.AreEqual(inputIntegers, outputIntegers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Clear() method
|
||||
/// is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnClearViaIList() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[1]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList).Clear(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Add() method
|
||||
/// is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddViaIList() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList).Add(12345); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the read only list is able to
|
||||
/// determine if the list contains an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContainsViaIList() {
|
||||
int[] integers = new int[] { 1234, 6789 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.IsTrue((testList as IList).Contains(1234));
|
||||
Assert.IsFalse((testList as IList).Contains(4321));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IndexOf() method of the read only list is able to
|
||||
/// determine if the index of an item in the list
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIndexOfViaIList() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.AreEqual(0, (testList as IList).IndexOf(12));
|
||||
Assert.AreEqual(1, (testList as IList).IndexOf(34));
|
||||
Assert.AreEqual(2, (testList as IList).IndexOf(67));
|
||||
Assert.AreEqual(3, (testList as IList).IndexOf(89));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Insert() method
|
||||
/// is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnInsertViaIList() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList).Insert(0, 12345); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IsFixedSize property of the read only list returns the
|
||||
/// expected result for a read only list based on a fixed array
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIsFixedSizeViaIList() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.IsTrue((testList as IList).IsFixedSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Remove() method
|
||||
/// is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaIList() {
|
||||
int[] integers = new int[] { 1234, 6789 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList).Remove(6789); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the read only list will throw an exception if its Remove() method
|
||||
/// is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveAtViaIList() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[1]);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList).RemoveAt(0); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the read only list will throw an exception
|
||||
/// if it is attempted to be used for replacing an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveByIndexerViaIList() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(integers);
|
||||
|
||||
Assert.AreEqual(12, (testList as IList)[0]);
|
||||
Assert.AreEqual(34, (testList as IList)[1]);
|
||||
Assert.AreEqual(67, (testList as IList)[2]);
|
||||
Assert.AreEqual(89, (testList as IList)[3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the read only list will throw an exception
|
||||
/// if it is attempted to be used for replacing an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnReplaceByIndexerViaIList() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[1]);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testList as IList)[0] = 12345; }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() of the read only list works if invoked via
|
||||
/// the ICollection interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArrayViaICollection() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(inputIntegers);
|
||||
|
||||
int[] outputIntegers = new int[testList.Count];
|
||||
(testList as ICollection).CopyTo(outputIntegers, 0);
|
||||
|
||||
CollectionAssert.AreEqual(inputIntegers, outputIntegers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the IsSynchronized property and the SyncRoot property are working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronization() {
|
||||
ReadOnlyList<int> testList = new ReadOnlyList<int>(new int[0]);
|
||||
|
||||
if(!(testList as ICollection).IsSynchronized) {
|
||||
lock((testList as ICollection).SyncRoot) {
|
||||
Assert.AreEqual(0, testList.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
207
Tests/Collections/ReadOnlySetTest.cs
Normal file
207
Tests/Collections/ReadOnlySetTest.cs
Normal file
|
@ -0,0 +1,207 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if !NO_SETS
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
|
||||
using NUnit.Framework;
|
||||
using NMock;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the observable set wrapper</summary>
|
||||
[TestFixture]
|
||||
internal class ReadOnlySetTest {
|
||||
|
||||
/// <summary>Called before each test is run</summary>
|
||||
[SetUp]
|
||||
public void Setup() {
|
||||
this.set = new HashSet<int>();
|
||||
this.readOnlySet = new ReadOnlySet<int>(this.set);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the observable set has a default constructor
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void HasDefaultConstructor() {
|
||||
Assert.IsNotNull(new ReadOnlySet<int>(new HashSet<int>()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown upon any attempt to add items
|
||||
/// to a read-only set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AddingThrowsException() {
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { ((ISet<int>)this.readOnlySet).Add(123); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown upon any attempt to remove items
|
||||
/// from a read-only set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void RemovingThrowsException() {
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { ((ISet<int>)this.readOnlySet).Remove(123); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown upon any attempt to except
|
||||
/// the set with another set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ExceptingThrowsException() {
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { ((ISet<int>)this.readOnlySet).ExceptWith(null); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown upon any attempt to intersect
|
||||
/// the set with another set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void InsersectThrowsException() {
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { ((ISet<int>)this.readOnlySet).IntersectWith(null); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to determine whether a set is a proper subset
|
||||
/// or superset of another set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanDetermineProperSubsetAndSuperset() {
|
||||
this.set.Add(1);
|
||||
this.set.Add(2);
|
||||
this.set.Add(3);
|
||||
|
||||
var set2 = new HashSet<int>() { 1, 3 };
|
||||
|
||||
Assert.IsTrue(this.readOnlySet.IsProperSupersetOf(set2));
|
||||
Assert.IsTrue(set2.IsProperSubsetOf(this.readOnlySet));
|
||||
|
||||
set2.Add(2);
|
||||
|
||||
Assert.IsFalse(this.readOnlySet.IsProperSupersetOf(set2));
|
||||
Assert.IsFalse(set2.IsProperSubsetOf(this.readOnlySet));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that it's possible to determine whether a set is a subset
|
||||
/// or a superset of another set
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanDetermineSubsetAndSuperset() {
|
||||
this.set.Add(1);
|
||||
this.set.Add(2);
|
||||
this.set.Add(3);
|
||||
|
||||
var set2 = new HashSet<int>() { 1, 2, 3 };
|
||||
|
||||
Assert.IsTrue(this.readOnlySet.IsSupersetOf(set2));
|
||||
Assert.IsTrue(set2.IsSubsetOf(this.readOnlySet));
|
||||
|
||||
set2.Add(4);
|
||||
|
||||
Assert.IsFalse(this.readOnlySet.IsSupersetOf(set2));
|
||||
Assert.IsFalse(set2.IsSubsetOf(this.readOnlySet));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a set can determine if another set overlaps with it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanDetermineOverlap() {
|
||||
this.set.Add(1);
|
||||
this.set.Add(3);
|
||||
this.set.Add(5);
|
||||
|
||||
var set2 = new HashSet<int>() { 3 };
|
||||
|
||||
Assert.IsTrue(this.readOnlySet.Overlaps(set2));
|
||||
Assert.IsTrue(set2.Overlaps(this.readOnlySet));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a set can determine if another set contains the same elements
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanDetermineSetEquality() {
|
||||
this.set.Add(1);
|
||||
this.set.Add(3);
|
||||
this.set.Add(5);
|
||||
|
||||
var set2 = new HashSet<int>() { 3, 1, 5 };
|
||||
|
||||
Assert.IsTrue(this.readOnlySet.SetEquals(set2));
|
||||
Assert.IsTrue(set2.SetEquals(this.readOnlySet));
|
||||
|
||||
this.set.Add(7);
|
||||
|
||||
Assert.IsFalse(this.readOnlySet.SetEquals(set2));
|
||||
Assert.IsFalse(set2.SetEquals(this.readOnlySet));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that any attempt to symmetrically except a read-only set
|
||||
/// causes an exception
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void SymmetricallyExceptingThrowsException() {
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { ((ISet<int>)this.readOnlySet).SymmetricExceptWith(null); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that any attempt to union a read-only set causes an exception
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void UnioningThrowsException() {
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { ((ISet<int>)this.readOnlySet).UnionWith(null); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Set being wrapped in a read-only set</summary>
|
||||
private ISet<int> set;
|
||||
/// <summary>Read-only wrapper around the set</summary>
|
||||
private ReadOnlySet<int> readOnlySet;
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
||||
|
||||
#endif // !NO_SETS
|
116
Tests/Collections/ReverseComparerTest.cs
Normal file
116
Tests/Collections/ReverseComparerTest.cs
Normal file
|
@ -0,0 +1,116 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the ReverseComparer helper class</summary>
|
||||
[TestFixture]
|
||||
internal class ReverseComparerTest {
|
||||
|
||||
#region class FortyTwoComparer
|
||||
|
||||
/// <summary>Special comparer in which 42 is larger than everything</summary>
|
||||
private class FortyTwoComparer : IComparer<int> {
|
||||
|
||||
/// <summary>Compares the left value to the right value</summary>
|
||||
/// <param name="left">Value on the left side</param>
|
||||
/// <param name="right">Value on the right side</param>
|
||||
/// <returns>The relationship of the two values</returns>
|
||||
public int Compare(int left, int right) {
|
||||
|
||||
// Is there a 42 in the arguments?
|
||||
if(left == 42) {
|
||||
if(right == 42) {
|
||||
return 0; // both are equal
|
||||
} else {
|
||||
return +1; // left is larger
|
||||
}
|
||||
} else if(right == 42) {
|
||||
return -1; // right is larger
|
||||
}
|
||||
|
||||
// No 42 encountered, proceed as normal
|
||||
return Math.Sign(left - right);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion // class FortyTwoComparer
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the default constructor of the reverse comparer works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestDefaultConstructor() {
|
||||
new ReverseComparer<int>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the full constructor of the reverse comparer works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestFullConstructor() {
|
||||
new ReverseComparer<int>(new FortyTwoComparer());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the full constructor of the reverse comparer works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReversedDefaultComparer() {
|
||||
Comparer<int> comparer = Comparer<int>.Default;
|
||||
ReverseComparer<int> reverseComparer = new ReverseComparer<int>(comparer);
|
||||
|
||||
Assert.Greater(0, comparer.Compare(10, 20));
|
||||
Assert.Less(0, comparer.Compare(20, 10));
|
||||
|
||||
Assert.Less(0, reverseComparer.Compare(10, 20));
|
||||
Assert.Greater(0, reverseComparer.Compare(20, 10));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the full constructor of the reverse comparer works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestReversedCustomComparer() {
|
||||
FortyTwoComparer fortyTwoComparer = new FortyTwoComparer();
|
||||
ReverseComparer<int> reverseFortyTwoComparer = new ReverseComparer<int>(
|
||||
fortyTwoComparer
|
||||
);
|
||||
|
||||
Assert.Less(0, fortyTwoComparer.Compare(42, 84));
|
||||
Assert.Greater(0, fortyTwoComparer.Compare(84, 42));
|
||||
|
||||
Assert.Greater(0, reverseFortyTwoComparer.Compare(42, 84));
|
||||
Assert.Less(0, reverseFortyTwoComparer.Compare(84, 42));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
119
Tests/Collections/SortableBindingListTest.cs
Normal file
119
Tests/Collections/SortableBindingListTest.cs
Normal file
|
@ -0,0 +1,119 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the SortableBindingList class</summary>
|
||||
[TestFixture]
|
||||
internal class SortableBindingListTest {
|
||||
|
||||
#region class TestRecord
|
||||
|
||||
/// <summary>Dummy record used to test the sortable binding list</summary>
|
||||
private class TestRecord {
|
||||
|
||||
/// <summary>A property of type integer</summary>
|
||||
public int IntegerValue { get; set; }
|
||||
|
||||
/// <summary>A property of type string</summary>
|
||||
public string StringValue { get; set; }
|
||||
|
||||
/// <summary>A property of type float</summary>
|
||||
public float FloatValue { get; set; }
|
||||
|
||||
}
|
||||
|
||||
#endregion // class TestRecord
|
||||
|
||||
/// <summary>Verifies that the sortable binding list is default constructible</summary>
|
||||
[Test]
|
||||
public void HasDefaultConstructor() {
|
||||
Assert.DoesNotThrow(
|
||||
delegate () { new SortableBindingList<TestRecord>(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the sortable binding list can copy an existing list
|
||||
/// when being constructed
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void HasEnumerableConstructor() {
|
||||
var items = new List<TestRecord>() {
|
||||
new TestRecord() { IntegerValue = 123 },
|
||||
new TestRecord() { IntegerValue = 456 }
|
||||
};
|
||||
|
||||
var testList = new SortableBindingList<TestRecord>(items);
|
||||
|
||||
Assert.AreEqual(2, testList.Count);
|
||||
Assert.AreSame(items[0], testList[0]);
|
||||
Assert.AreSame(items[1], testList[1]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the sortable binding list supports sorting</summary>
|
||||
[Test]
|
||||
public void SupportsSorting() {
|
||||
var testList = new SortableBindingList<TestRecord>();
|
||||
IBindingList testListAsBindingList = testList;
|
||||
|
||||
Assert.IsTrue(testListAsBindingList.SupportsSorting);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the sortable binding list can sort its elements by different properties
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void CanSortItems() {
|
||||
var items = new List<TestRecord>() {
|
||||
new TestRecord() { IntegerValue = 456 },
|
||||
new TestRecord() { IntegerValue = 789 },
|
||||
new TestRecord() { IntegerValue = 123 }
|
||||
};
|
||||
|
||||
var testList = new SortableBindingList<TestRecord>(items);
|
||||
IBindingList testListAsBindingList = testList;
|
||||
|
||||
PropertyDescriptor integerValuePropertyDescriptor = (
|
||||
TypeDescriptor.GetProperties(typeof(TestRecord))[nameof(TestRecord.IntegerValue)]
|
||||
);
|
||||
testListAsBindingList.ApplySort(
|
||||
integerValuePropertyDescriptor, ListSortDirection.Ascending
|
||||
);
|
||||
|
||||
Assert.AreEqual(3, testList.Count);
|
||||
Assert.AreEqual(123, testList[0].IntegerValue);
|
||||
Assert.AreEqual(456, testList[1].IntegerValue);
|
||||
Assert.AreEqual(789, testList[2].IntegerValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
500
Tests/Collections/TransformingReadOnlyCollectionTest.cs
Normal file
500
Tests/Collections/TransformingReadOnlyCollectionTest.cs
Normal file
|
@ -0,0 +1,500 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if !NO_NMOCK
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
using NMock;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the transforming read only collection wrapper</summary>
|
||||
[TestFixture]
|
||||
internal class TransformingReadOnlyCollectionTest {
|
||||
|
||||
#region class StringTransformer
|
||||
|
||||
/// <summary>Test implementation of a transforming collection</summary>
|
||||
private class StringTransformer : TransformingReadOnlyCollection<int, string> {
|
||||
|
||||
/// <summary>Initializes a new int-to-string transforming collection</summary>
|
||||
/// <param name="items">Items the transforming collection will contain</param>
|
||||
public StringTransformer(IList<int> items) : base(items) { }
|
||||
|
||||
/// <summary>Transforms an item into the exposed type</summary>
|
||||
/// <param name="item">Item to be transformed</param>
|
||||
/// <returns>The transformed item</returns>
|
||||
/// <remarks>
|
||||
/// This method is used to transform an item in the wrapped collection into
|
||||
/// the exposed item type whenever the user accesses an item. Expect it to
|
||||
/// be called frequently, because the TransformingReadOnlyCollection does
|
||||
/// not cache or otherwise store the transformed items.
|
||||
/// </remarks>
|
||||
protected override string Transform(int item) {
|
||||
if(item == 42) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return item.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion // class StringTransformer
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the copy constructor of the transforming read only collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyConstructor() {
|
||||
int[] integers = new int[] { 12, 34, 56, 78 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
string[] strings = new string[] { "12", "34", "56", "78" };
|
||||
CollectionAssert.AreEqual(strings, testCollection);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the IsReadOnly property returns true</summary>
|
||||
[Test]
|
||||
public void TestIsReadOnly() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[0]);
|
||||
|
||||
Assert.IsTrue(testCollection.IsReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() method of the transforming read only collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArray() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
StringTransformer testCollection = new StringTransformer(inputIntegers);
|
||||
|
||||
string[] inputStrings = new string[] { "12", "34", "56", "78" };
|
||||
string[] outputStrings = new string[testCollection.Count];
|
||||
testCollection.CopyTo(outputStrings, 0);
|
||||
|
||||
CollectionAssert.AreEqual(inputStrings, outputStrings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() method of the transforming read only collection throws
|
||||
/// an exception if the target array is too small to hold the collection's contents
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnCopyToTooSmallArray() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
StringTransformer testCollection = new StringTransformer(inputIntegers);
|
||||
|
||||
string[] outputStrings = new string[testCollection.Count - 1];
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { testCollection.CopyTo(outputStrings, 0); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the transforming read only collection
|
||||
/// is able to determine if the collection contains an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContains() {
|
||||
int[] integers = new int[] { 1234, 6789 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.IsTrue(testCollection.Contains("1234"));
|
||||
Assert.IsFalse(testCollection.Contains("4321"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IndexOf() method of the transforming read only collection
|
||||
/// is able to determine if the index of an item in the collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIndexOf() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.AreEqual(0, testCollection.IndexOf("12"));
|
||||
Assert.AreEqual(1, testCollection.IndexOf("34"));
|
||||
Assert.AreEqual(2, testCollection.IndexOf("67"));
|
||||
Assert.AreEqual(3, testCollection.IndexOf("89"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IndexOf() method of the transforming read only collection
|
||||
/// can cope with queries for 'null' when no 'null' item is contained on it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIndexOfWithNullItemNotContained() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.AreEqual(-1, testCollection.IndexOf(null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IndexOf() method of the transforming read only collection
|
||||
/// can cope with queries for 'null' when a 'null' item is contained on it
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIndexOfWithNullItemContained() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89, 42 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.AreEqual(4, testCollection.IndexOf(null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Enumerator of the transforming read only collection correctly
|
||||
/// implements the Reset() method
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestEnumeratorReset() {
|
||||
int[] integers = new int[] { 1234, 6789 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
IEnumerator<string> stringEnumerator = testCollection.GetEnumerator();
|
||||
Assert.IsTrue(stringEnumerator.MoveNext());
|
||||
Assert.IsTrue(stringEnumerator.MoveNext());
|
||||
Assert.IsFalse(stringEnumerator.MoveNext());
|
||||
|
||||
stringEnumerator.Reset();
|
||||
|
||||
Assert.IsTrue(stringEnumerator.MoveNext());
|
||||
Assert.IsTrue(stringEnumerator.MoveNext());
|
||||
Assert.IsFalse(stringEnumerator.MoveNext());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the transforming read only collection
|
||||
/// is able to retrieve items from the collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveByIndexer() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.AreEqual("12", testCollection[0]);
|
||||
Assert.AreEqual("34", testCollection[1]);
|
||||
Assert.AreEqual("67", testCollection[2]);
|
||||
Assert.AreEqual("89", testCollection[3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Insert() method is called via the generic IList<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnInsertViaGenericIList() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList<string>).Insert(0, "12345"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its RemoveAt() method is called via the generic IList<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaGenericIList() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[1]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList<string>).RemoveAt(0); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the transforming read only collection will
|
||||
/// throw an exception if it is attempted to be used for replacing an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveByIndexerViaGenericIList() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.AreEqual("12", (testCollection as IList<string>)[0]);
|
||||
Assert.AreEqual("34", (testCollection as IList<string>)[1]);
|
||||
Assert.AreEqual("67", (testCollection as IList<string>)[2]);
|
||||
Assert.AreEqual("89", (testCollection as IList<string>)[3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the transforming read only collection
|
||||
/// will throw an exception if it is attempted to be used for replacing an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnReplaceByIndexerViaGenericIList() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[1]);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList<string>)[0] = "12345"; }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Add() method is called via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddViaGenericICollection() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as ICollection<string>).Add("12345"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Clear() method is called via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnClearViaGenericICollection() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[1]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as ICollection<string>).Clear(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Remove() method is called via the generic ICollection<> interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaGenericICollection() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as ICollection<string>).Remove("89"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the typesafe enumerator of the read only collection is working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestTypesafeEnumerator() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
StringTransformer testCollection = new StringTransformer(inputIntegers);
|
||||
|
||||
List<string> outputStrings = new List<string>();
|
||||
foreach(string value in testCollection) {
|
||||
outputStrings.Add(value);
|
||||
}
|
||||
|
||||
string[] inputStrings = new string[] { "12", "34", "56", "78" };
|
||||
CollectionAssert.AreEqual(inputStrings, outputStrings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Clear() method is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnClearViaIList() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[1]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList).Clear(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Add() method is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddViaIList() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList).Add("12345"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the Contains() method of the transforming read only collection
|
||||
/// is able to determine if the collection contains an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestContainsViaIList() {
|
||||
int[] integers = new int[] { 1234, 6789 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.IsTrue((testCollection as IList).Contains("1234"));
|
||||
Assert.IsFalse((testCollection as IList).Contains("4321"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IndexOf() method of the transforming read only collection
|
||||
/// is able to determine if the index of an item in the collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIndexOfViaIList() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.AreEqual(0, (testCollection as IList).IndexOf("12"));
|
||||
Assert.AreEqual(1, (testCollection as IList).IndexOf("34"));
|
||||
Assert.AreEqual(2, (testCollection as IList).IndexOf("67"));
|
||||
Assert.AreEqual(3, (testCollection as IList).IndexOf("89"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Insert() method is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnInsertViaIList() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[0]);
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList).Insert(0, "12345"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IsFixedSize property of the transforming read only collection
|
||||
/// returns the expected result for a transforming read only collection based on
|
||||
/// a fixed array
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIsFixedSizeViaIList() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.IsTrue((testCollection as IList).IsFixedSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Remove() method is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveViaIList() {
|
||||
int[] integers = new int[] { 1234, 6789 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList).Remove("6789"); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the transforming read only collection will throw an exception
|
||||
/// if its Remove() method is called via the IList interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveAtViaIList() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[1]);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList).RemoveAt(0); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the transforming read only collection
|
||||
/// will throw an exception if it is attempted to be used for replacing an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRetrieveByIndexerViaIList() {
|
||||
int[] integers = new int[] { 12, 34, 67, 89 };
|
||||
StringTransformer testCollection = new StringTransformer(integers);
|
||||
|
||||
Assert.AreEqual("12", (testCollection as IList)[0]);
|
||||
Assert.AreEqual("34", (testCollection as IList)[1]);
|
||||
Assert.AreEqual("67", (testCollection as IList)[2]);
|
||||
Assert.AreEqual("89", (testCollection as IList)[3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the indexer method of the transforming read only collection
|
||||
/// will throw an exception if it is attempted to be used for replacing an item
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnReplaceByIndexerViaIList() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[1]);
|
||||
|
||||
Assert.Throws<NotSupportedException>(
|
||||
delegate() { (testCollection as IList)[0] = "12345"; }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() method of the transforming read only collection
|
||||
/// works if invoked via the ICollection interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArrayViaICollection() {
|
||||
int[] inputIntegers = new int[] { 12, 34, 56, 78 };
|
||||
StringTransformer testCollection = new StringTransformer(inputIntegers);
|
||||
|
||||
string[] outputStrings = new string[testCollection.Count];
|
||||
(testCollection as ICollection).CopyTo(outputStrings, 0);
|
||||
|
||||
string[] inputStrings = new string[] { "12", "34", "56", "78" };
|
||||
CollectionAssert.AreEqual(inputStrings, outputStrings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the IsSynchronized property and the SyncRoot property are working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronization() {
|
||||
StringTransformer testCollection = new StringTransformer(new int[0]);
|
||||
|
||||
if(!(testCollection as ICollection).IsSynchronized) {
|
||||
lock((testCollection as ICollection).SyncRoot) {
|
||||
Assert.AreEqual(0, testCollection.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronizationOfIListWithoutICollection() {
|
||||
MockFactory mockery = new MockFactory();
|
||||
Mock<IList<int>> mockedIList = mockery.CreateMock<IList<int>>();
|
||||
StringTransformer testCollection = new StringTransformer(mockedIList.MockObject);
|
||||
|
||||
if(!(testCollection as ICollection).IsSynchronized) {
|
||||
lock((testCollection as ICollection).SyncRoot) {
|
||||
mockedIList.Expects.One.GetProperty(p => p.Count).WillReturn(12345);
|
||||
int count = testCollection.Count;
|
||||
Assert.AreEqual(12345, count); // ;-)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
||||
|
||||
#endif // !NO_NMOCK
|
87
Tests/Collections/VariegatorTest.cs
Normal file
87
Tests/Collections/VariegatorTest.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
#if !NO_SETS
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the Variegator multi dictionary</summary>
|
||||
[TestFixture]
|
||||
internal class VariegatorTest {
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the default constructor of the reverse comparer works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void InstancesCanBeCreated() {
|
||||
new Variegator<int, string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that querying for a missing value leads to an exception being thrown
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void QueryingMissingValueThrowsException() {
|
||||
var variegator = new Variegator<int, string>();
|
||||
Assert.Throws<KeyNotFoundException>(
|
||||
() => {
|
||||
variegator.Get(123);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the variegator resolves ambiguous matches according to its design
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void AmbiguityResolvesToLeastRecentValue() {
|
||||
var variegator = new Variegator<int, string>();
|
||||
variegator.Add(1, "one");
|
||||
variegator.Add(1, "eins");
|
||||
|
||||
string first = variegator.Get(1);
|
||||
string second = variegator.Get(1);
|
||||
|
||||
// The variegator should have selected the first value by random and then
|
||||
// returned the other value on the second query
|
||||
Assert.AreNotEqual(first, second);
|
||||
|
||||
// Now the variegator should return the first value again because it is
|
||||
// the least recently used value
|
||||
Assert.AreEqual(first, variegator.Get(1));
|
||||
|
||||
// Repeating the query, the second should be returned again because now
|
||||
// it has become the least recently used value
|
||||
Assert.AreEqual(second, variegator.Get(1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Nuclex.Support.Collections
|
||||
|
||||
#endif // UNITTEST
|
||||
|
||||
#endif // !NO_SETS
|
668
Tests/Collections/WeakCollectionTest.cs
Normal file
668
Tests/Collections/WeakCollectionTest.cs
Normal file
|
@ -0,0 +1,668 @@
|
|||
#region Apache License 2.0
|
||||
/*
|
||||
Nuclex .NET Framework
|
||||
Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
#endregion // Apache License 2.0
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if UNITTEST
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Nuclex.Support.Collections {
|
||||
|
||||
/// <summary>Unit Test for the weak collection wrapper</summary>
|
||||
[TestFixture]
|
||||
internal class WeakCollectionTest {
|
||||
|
||||
#region class Dummy
|
||||
|
||||
/// <summary>Dummy class used to test the weakly referencing collection</summary>
|
||||
private class Dummy {
|
||||
|
||||
/// <summary>Initializes a new dummy</summary>
|
||||
/// <param name="value">Value that will be stored by the dummy</param>
|
||||
public Dummy(int value) {
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified System.Object is equal to
|
||||
/// the current Dummy object.
|
||||
/// </summary>
|
||||
/// <param name="otherAsObject">
|
||||
/// The System.Object to compare with the current Dummy object
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// True if the specified System.Object is equal to the current Dummy object;
|
||||
/// otherwise, false.
|
||||
/// </returns>
|
||||
public override bool Equals(object otherAsObject) {
|
||||
Dummy other = otherAsObject as Dummy;
|
||||
if(other == null) {
|
||||
return false;
|
||||
}
|
||||
return this.Value.Equals(other.Value);
|
||||
}
|
||||
|
||||
/// <summary>Serves as a hash function for a particular type.</summary>
|
||||
/// <returns>A hash code for the current System.Object.</returns>
|
||||
public override int GetHashCode() {
|
||||
return this.Value.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>Some value that can be used for testing</summary>
|
||||
public int Value;
|
||||
|
||||
}
|
||||
|
||||
#endregion // class Dummy
|
||||
|
||||
#region class ListWithoutICollection
|
||||
|
||||
private class ListWithoutICollection : IList<WeakReference<Dummy>> {
|
||||
public int IndexOf(WeakReference<Dummy> item) { throw new NotImplementedException(); }
|
||||
public void Insert(int index, WeakReference<Dummy> item) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public void RemoveAt(int index) { throw new NotImplementedException(); }
|
||||
public WeakReference<Dummy> this[int index] {
|
||||
get { throw new NotImplementedException(); }
|
||||
set { throw new NotImplementedException(); }
|
||||
}
|
||||
public void Add(WeakReference<Dummy> item) { throw new NotImplementedException(); }
|
||||
public void Clear() { throw new NotImplementedException(); }
|
||||
public bool Contains(WeakReference<Dummy> item) { throw new NotImplementedException(); }
|
||||
public void CopyTo(WeakReference<Dummy>[] array, int arrayIndex) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public int Count { get { return 12345; } }
|
||||
public bool IsReadOnly { get { throw new NotImplementedException(); } }
|
||||
public bool Remove(WeakReference<Dummy> item) { throw new NotImplementedException(); }
|
||||
public IEnumerator<WeakReference<Dummy>> GetEnumerator() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
#endregion // class ListWithoutICollection
|
||||
|
||||
/// <summary>Verifies that the constructor of the weak collection is working</summary>
|
||||
[Test]
|
||||
public void TestConstructor() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
Assert.IsNotNull(dummies);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the non-typesafe Add() method of the weak collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAddAsObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
Dummy oneTwoThreeDummy = new Dummy(12345);
|
||||
(dummies as IList).Add((object)oneTwoThreeDummy);
|
||||
|
||||
CollectionAssert.Contains(dummies, oneTwoThreeDummy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnAddIncompatibleObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { (dummies as IList).Add(new object()); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test whether the generic Add() method of the weak collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAdd() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
Dummy oneTwoThreeDummy = new Dummy(12345);
|
||||
dummies.Add(oneTwoThreeDummy);
|
||||
|
||||
CollectionAssert.Contains(dummies, oneTwoThreeDummy);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the Clear() method works</summary>
|
||||
[Test]
|
||||
public void TestClear() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the Contains() method works</summary>
|
||||
[Test]
|
||||
public void TestContains() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
Dummy oneTwoThreeDummy = new Dummy(12345);
|
||||
dummies.Add(oneTwoThreeDummy);
|
||||
Dummy threeTwoOneDummy = new Dummy(54321);
|
||||
|
||||
Assert.IsTrue(dummies.Contains(oneTwoThreeDummy));
|
||||
Assert.IsFalse(dummies.Contains(threeTwoOneDummy));
|
||||
}
|
||||
|
||||
/// <summary>Tests whether the non-typesafe Contains() method works</summary>
|
||||
[Test]
|
||||
public void TestContainsWithObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Enumerator of the dummy collection correctly
|
||||
/// implements the Reset() method
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestEnumeratorReset() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
Dummy oneTwoThreeDummy = new Dummy(123);
|
||||
dummies.Add(oneTwoThreeDummy);
|
||||
Dummy fourFiveSixDummy = new Dummy(456);
|
||||
dummies.Add(fourFiveSixDummy);
|
||||
|
||||
IEnumerator<Dummy> 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());
|
||||
}
|
||||
|
||||
/// <summary>Verifies that the IndexOf() method is working as intended</summary>
|
||||
[Test]
|
||||
public void TestIndexOf() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the non-typesafe IndexOf() method is working as intended
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIndexOfWithObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that an exception is thrown if an incompatible object is passed to
|
||||
/// the non-typesafe variant of the IndexOf() method
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnIndexOfWithIncompatibleObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { Assert.IsNull((dummies as IList).IndexOf(new object())); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Test whether the IndexOf() method can cope with null references</summary>
|
||||
[Test]
|
||||
public void TestIndexOfNull() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
Assert.AreEqual(-1, dummies.IndexOf(null));
|
||||
dummies.Add(null);
|
||||
Assert.AreEqual(0, dummies.IndexOf(null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() method of the weak collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArray() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnCopyToTooSmallArray() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
Dummy oneTwoThreeDummy = new Dummy(123);
|
||||
dummies.Add(oneTwoThreeDummy);
|
||||
Dummy fourFiveSixDummy = new Dummy(456);
|
||||
dummies.Add(fourFiveSixDummy);
|
||||
|
||||
Dummy[] outputStrings = new Dummy[dummies.Count - 1];
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { dummies.CopyTo(outputStrings, 0); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the CopyTo() method of the transforming read only collection
|
||||
/// works if invoked via the ICollection interface
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestCopyToArrayViaICollection() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Insert() method correctly shifts items in the collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInsert() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the non-typesafe Insert() method correctly shifts items in
|
||||
/// the collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestInsertObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the non-typesafe Insert() method correctly shifts items in
|
||||
/// the collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnInsertIncompatibleObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
Dummy oneTwoThreeDummy = new Dummy(123);
|
||||
dummies.Add(oneTwoThreeDummy);
|
||||
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { (dummies as IList).Insert(0, new object()); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the IsFixedSize property of the weak collection returns
|
||||
/// the expected result for a weak collection based on a fixed array
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIsFixedSizeViaIList() {
|
||||
Dummy oneTwoThreeDummy = new Dummy(123);
|
||||
Dummy fourFiveSixDummy = new Dummy(456);
|
||||
|
||||
WeakReference<Dummy>[] dummyReferences = new WeakReference<Dummy>[] {
|
||||
new WeakReference<Dummy>(oneTwoThreeDummy),
|
||||
new WeakReference<Dummy>(fourFiveSixDummy)
|
||||
};
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(dummyReferences);
|
||||
|
||||
Assert.IsTrue((dummies as IList).IsFixedSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the IsReadOnly property of the weak collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIsReadOnly() {
|
||||
Dummy oneTwoThreeDummy = new Dummy(123);
|
||||
Dummy fourFiveSixDummy = new Dummy(456);
|
||||
|
||||
List<WeakReference<Dummy>> dummyReferences = new List<WeakReference<Dummy>>();
|
||||
dummyReferences.Add(new WeakReference<Dummy>(oneTwoThreeDummy));
|
||||
dummyReferences.Add(new WeakReference<Dummy>(fourFiveSixDummy));
|
||||
|
||||
ReadOnlyList<WeakReference<Dummy>> readOnlyDummyReferences =
|
||||
new ReadOnlyList<WeakReference<Dummy>>(dummyReferences);
|
||||
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(dummyReferences);
|
||||
WeakCollection<Dummy> readOnlydummies = new WeakCollection<Dummy>(
|
||||
readOnlyDummyReferences
|
||||
);
|
||||
|
||||
Assert.IsFalse(dummies.IsReadOnly);
|
||||
Assert.IsTrue(readOnlydummies.IsReadOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the IsSynchronized property of the weak collection works
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestIsSynchronized() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
Assert.IsFalse((dummies as IList).IsSynchronized);
|
||||
}
|
||||
|
||||
/// <summary>Tests the indexer of the weak collection</summary>
|
||||
[Test]
|
||||
public void TestIndexer() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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]);
|
||||
}
|
||||
|
||||
/// <summary>Tests the non-typesafe indexer of the weak collection</summary>
|
||||
[Test]
|
||||
public void TestIndexerWithObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether the non-typesafe indexer of the weak collection throws
|
||||
/// the correct exception if an incompatible object is assigned
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnIndexerWithIncompatibleObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
Dummy oneTwoThreeDummy = new Dummy(123);
|
||||
dummies.Add(oneTwoThreeDummy);
|
||||
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { (dummies as IList)[0] = new object(); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests the Remove() method of the weak collection</summary>
|
||||
[Test]
|
||||
public void TestRemove() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>Tests the non-typesafe Remove() method of the weak collection</summary>
|
||||
[Test]
|
||||
public void TestRemoveObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests whether a null object can be managed by and removed from the weak collection
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestRemoveNull() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
dummies.Add(null);
|
||||
|
||||
Assert.AreEqual(1, dummies.Count);
|
||||
Assert.IsTrue(dummies.Remove(null));
|
||||
Assert.AreEqual(0, dummies.Count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestThrowOnRemoveIncompatibleObject() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
Assert.Throws<ArgumentException>(
|
||||
delegate() { (dummies as IList).Remove(new object()); }
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>Tests the RemoveAt() method of the weak collection</summary>
|
||||
[Test]
|
||||
public void TestRemoveAt() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
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]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the IsSynchronized property and the SyncRoot property are working
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronization() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new List<WeakReference<Dummy>>()
|
||||
);
|
||||
|
||||
if(!(dummies as ICollection).IsSynchronized) {
|
||||
lock((dummies as ICollection).SyncRoot) {
|
||||
Assert.AreEqual(0, dummies.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSynchronizationOfIListWithoutICollection() {
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(
|
||||
new ListWithoutICollection()
|
||||
);
|
||||
|
||||
if(!(dummies as ICollection).IsSynchronized) {
|
||||
lock((dummies as ICollection).SyncRoot) {
|
||||
int count = dummies.Count;
|
||||
Assert.AreEqual(12345, count); // ;-)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Tests the RemoveDeadItems() method</summary>
|
||||
[Test]
|
||||
public void TestRemoveDeadItems() {
|
||||
List<WeakReference<Dummy>> dummyReferences = new List<WeakReference<Dummy>>();
|
||||
|
||||
Dummy oneTwoThreeDummy = new Dummy(123);
|
||||
dummyReferences.Add(new WeakReference<Dummy>(oneTwoThreeDummy));
|
||||
|
||||
dummyReferences.Add(new WeakReference<Dummy>(null));
|
||||
|
||||
Dummy fourFiveSixDummy = new Dummy(456);
|
||||
dummyReferences.Add(new WeakReference<Dummy>(fourFiveSixDummy));
|
||||
|
||||
WeakCollection<Dummy> dummies = new WeakCollection<Dummy>(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
|
Loading…
Add table
Add a link
Reference in a new issue