From 4c408a56ad6ae7cc1ae284660dc2fffdbe259c96 Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Sat, 3 Mar 2012 15:06:02 +0000 Subject: [PATCH] Unit tests for the ObservableSet not also tests the change notification events resulting from union/intersect/except methods; added unit tests for read-only set git-svn-id: file:///srv/devel/repo-conversion/nusu@264 d2e56fa2-650e-0410-a79f-9358c0239efd --- Source/Collections/ObservableSet.Test.cs | 104 +++++++++++--- Source/Collections/ObservableSet.cs | 14 +- Source/Collections/ReadOnlySet.Test.cs | 169 ++++++++++++++++++++++- 3 files changed, 260 insertions(+), 27 deletions(-) diff --git a/Source/Collections/ObservableSet.Test.cs b/Source/Collections/ObservableSet.Test.cs index ea9d26c..aae951f 100644 --- a/Source/Collections/ObservableSet.Test.cs +++ b/Source/Collections/ObservableSet.Test.cs @@ -97,6 +97,18 @@ namespace Nuclex.Support.Collections { this.observableSet.Add(123); } + /// + /// Verifies that removing items from the set triggers the 'ItemRemoved' event + /// + [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); + } + /// /// Verifies that adding items to the set triggers the 'ItemAdded' event /// @@ -114,14 +126,21 @@ namespace Nuclex.Support.Collections { /// [Test] public void ExceptWithSelfEmptiesSet() { - var set = new ObservableSet(); - set.Add(1); - set.Add(2); - set.Add(3); + this.subscriber.Expects.Exactly(3).Method( + (s) => s.ItemAdded(null, null) + ).WithAnyArguments(); - Assert.AreEqual(3, set.Count); - set.ExceptWith(set); - Assert.AreEqual(0, set.Count); + 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); } /// @@ -129,16 +148,19 @@ namespace Nuclex.Support.Collections { /// [Test] public void SetCanBeExceptedWithCollection() { - var set = new ObservableSet(); - set.Add(1); - set.Add(2); + this.subscriber.Expects.Exactly(2).Method( + (s) => s.ItemAdded(null, null) + ).WithAnyArguments(); + + this.observableSet.Add(1); + this.observableSet.Add(2); var collection = new List() { 1 }; - Assert.AreEqual(2, set.Count); - set.ExceptWith(collection); - Assert.AreEqual(1, set.Count); - Assert.IsTrue(set.Contains(2)); + 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)); } /// @@ -146,16 +168,19 @@ namespace Nuclex.Support.Collections { /// [Test] public void SetCanBeIntersectedWithCollection() { - var set = new ObservableSet(); - set.Add(1); - set.Add(2); + this.subscriber.Expects.Exactly(2).Method( + (s) => s.ItemAdded(null, null) + ).WithAnyArguments(); + + this.observableSet.Add(1); + this.observableSet.Add(2); var collection = new List() { 1 }; - Assert.AreEqual(2, set.Count); - set.IntersectWith(collection); - Assert.AreEqual(1, set.Count); - Assert.IsTrue(set.Contains(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)); } /// @@ -223,6 +248,41 @@ namespace Nuclex.Support.Collections { Assert.IsFalse(set2.SetEquals(set1)); } + /// + /// Verifies that a set can be symmetrically excepted with another set + /// + [Test] + public void CanBeSymmetricallyExcepted() { + var set1 = new ObservableSet() { 1, 2, 3 }; + var set2 = new ObservableSet() { 3, 4, 5 }; + + set1.SymmetricExceptWith(set2); + + Assert.AreEqual(4, set1.Count); + } + + /// + /// Verifies that a union of two sets can be built + /// + [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() { 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); + } + /// Creates mock object for the test private MockFactory mockFactory; /// Observable set being tested @@ -234,4 +294,4 @@ namespace Nuclex.Support.Collections { } // namespace Nuclex.Support.Collections -#endif // UNITTEST \ No newline at end of file +#endif // UNITTEST diff --git a/Source/Collections/ObservableSet.cs b/Source/Collections/ObservableSet.cs index bdb6172..10089ac 100644 --- a/Source/Collections/ObservableSet.cs +++ b/Source/Collections/ObservableSet.cs @@ -247,7 +247,11 @@ namespace Nuclex.Support.Collections { /// True if the item was contained in the set and is now removed /// public bool Remove(TItem item) { - return this.set.Remove(item); + bool wasRemoved = this.set.Remove(item); + if(wasRemoved) { + OnRemoved(item); + } + return wasRemoved; } /// Creates an enumerator for the set's contents @@ -307,18 +311,26 @@ namespace Nuclex.Support.Collections { #endif } + #region ICollection implementation + /// Adds an item to the set /// Item that will be added to the set void ICollection.Add(TItem item) { this.set.Add(item); } + #endregion // ICollection implementation + + #region IEnumerable implementation + /// Creates an enumerator for the set's contents /// A new enumerator for the sets contents IEnumerator IEnumerable.GetEnumerator() { return this.set.GetEnumerator(); } + #endregion // IEnumerable implementation + /// The set being wrapped private ISet set; diff --git a/Source/Collections/ReadOnlySet.Test.cs b/Source/Collections/ReadOnlySet.Test.cs index c10ad72..a334706 100644 --- a/Source/Collections/ReadOnlySet.Test.cs +++ b/Source/Collections/ReadOnlySet.Test.cs @@ -31,13 +31,174 @@ using NMock; namespace Nuclex.Support.Collections { -#if false - /// Unit Test for the read-only set wrapper + /// Unit Test for the observable set wrapper [TestFixture] internal class ReadOnlySetTest { + + /// Called before each test is run + [SetUp] + public void Setup() { + this.set = new HashSet(); + this.readOnlySet = new ReadOnlySet(this.set); + } + + /// + /// Verifies that the observable set has a default constructor + /// + [Test] + public void HasDefaultConstructor() { + Assert.IsNotNull(new ReadOnlySet(new HashSet())); + } + + /// + /// Verifies that an exception is thrown upon any attempt to add items + /// to a read-only set + /// + [Test] + public void AddingThrowsException() { + Assert.Throws( + delegate() { ((ISet)this.readOnlySet).Add(123); } + ); + } + + /// + /// Verifies that an exception is thrown upon any attempt to remove items + /// from a read-only set + /// + [Test] + public void RemovingThrowsException() { + Assert.Throws( + delegate() { ((ISet)this.readOnlySet).Remove(123); } + ); + } + + /// + /// Verifies that an exception is thrown upon any attempt to except + /// the set with another set + /// + [Test] + public void ExceptingThrowsException() { + Assert.Throws( + delegate() { ((ISet)this.readOnlySet).ExceptWith(null); } + ); + } + + /// + /// Verifies that an exception is thrown upon any attempt to intersect + /// the set with another set + /// + [Test] + public void InsersectThrowsException() { + Assert.Throws( + delegate() { ((ISet)this.readOnlySet).IntersectWith(null); } + ); + } + + /// + /// Verifies that it's possible to determine whether a set is a proper subset + /// or superset of another set + /// + [Test] + public void CanDetermineProperSubsetAndSuperset() { + this.set.Add(1); + this.set.Add(2); + this.set.Add(3); + + var set2 = new HashSet() { 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)); + } + + /// + /// Verifies that it's possible to determine whether a set is a subset + /// or a superset of another set + /// + [Test] + public void CanDetermineSubsetAndSuperset() { + this.set.Add(1); + this.set.Add(2); + this.set.Add(3); + + var set2 = new HashSet() { 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)); + } + + /// + /// Verifies that a set can determine if another set overlaps with it + /// + [Test] + public void CanDetermineOverlap() { + this.set.Add(1); + this.set.Add(3); + this.set.Add(5); + + var set2 = new HashSet() { 3 }; + + Assert.IsTrue(this.readOnlySet.Overlaps(set2)); + Assert.IsTrue(set2.Overlaps(this.readOnlySet)); + } + + /// + /// Verifies that a set can determine if another set contains the same elements + /// + [Test] + public void CanDetermineSetEquality() { + this.set.Add(1); + this.set.Add(3); + this.set.Add(5); + + var set2 = new HashSet() { 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)); + } + + /// + /// Verifies that any attempt to symmetrically except a read-only set + /// causes an exception + /// + [Test] + public void SymmetricallyExceptingThrowsException() { + Assert.Throws( + delegate() { ((ISet)this.readOnlySet).SymmetricExceptWith(null); } + ); + } + + /// + /// Verifies that any attempt to union a read-only set causes an exception + /// + [Test] + public void UnioningThrowsException() { + Assert.Throws( + delegate() { ((ISet)this.readOnlySet).UnionWith(null); } + ); + } + + /// Set being wrapped in a read-only set + private ISet set; + /// Read-only wrapper around the set + private ReadOnlySet readOnlySet; + } -#endif } // namespace Nuclex.Support.Collections -#endif // UNITTEST \ No newline at end of file +#endif // UNITTEST