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