Added out-of-sync check for the Deque enumerator; added unit test for the out-of-sync check

git-svn-id: file:///srv/devel/repo-conversion/nusu@166 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
Markus Ewald 2009-07-14 21:52:40 +00:00
parent a56da772d4
commit 9ec6546f70
5 changed files with 65 additions and 2 deletions

View File

@ -38,6 +38,9 @@ namespace Nuclex.Support.Collections {
this.blocks[0][this.firstBlockStartIndex] = item; this.blocks[0][this.firstBlockStartIndex] = item;
++this.count; ++this.count;
#if DEBUG
++this.version;
#endif
} }
/// <summary>Appends an item to the end of the double-ended queue</summary> /// <summary>Appends an item to the end of the double-ended queue</summary>
@ -52,6 +55,9 @@ namespace Nuclex.Support.Collections {
this.blocks[this.blocks.Count - 1][this.lastBlockEndIndex - 1] = item; this.blocks[this.blocks.Count - 1][this.lastBlockEndIndex - 1] = item;
++this.count; ++this.count;
#if DEBUG
++this.version;
#endif
} }
/// <summary>Inserts the item at the specified index</summary> /// <summary>Inserts the item at the specified index</summary>
@ -64,6 +70,9 @@ namespace Nuclex.Support.Collections {
} else { // Nope, we're closer to the right end } else { // Nope, we're closer to the right end
shiftRightAndInsert(index, item); shiftRightAndInsert(index, item);
} }
#if DEBUG
++this.version;
#endif
} }
/// <summary> /// <summary>

View File

@ -54,6 +54,9 @@ namespace Nuclex.Support.Collections {
this.firstBlockStartIndex = 0; this.firstBlockStartIndex = 0;
this.lastBlockEndIndex = 0; this.lastBlockEndIndex = 0;
this.count = 0; this.count = 0;
#if DEBUG
++this.version;
#endif
} }
/// <summary>Removes the specified item from the deque</summary> /// <summary>Removes the specified item from the deque</summary>
@ -66,6 +69,9 @@ namespace Nuclex.Support.Collections {
} }
RemoveAt(index); RemoveAt(index);
#if DEBUG
++this.version;
#endif
return true; return true;
} }
@ -92,6 +98,9 @@ namespace Nuclex.Support.Collections {
} }
} }
--this.count; --this.count;
#if DEBUG
++this.version;
#endif
} }
/// <summary>Removes the last item in the double-ended queue</summary> /// <summary>Removes the last item in the double-ended queue</summary>
@ -118,6 +127,9 @@ namespace Nuclex.Support.Collections {
} }
} }
--this.count; --this.count;
#if DEBUG
++this.version;
#endif
} }
/// <summary>Removes the item at the specified index</summary> /// <summary>Removes the item at the specified index</summary>
@ -129,6 +141,9 @@ namespace Nuclex.Support.Collections {
} else { // Nope, we're closer to the right end } else { // Nope, we're closer to the right end
removeFromRight(index); removeFromRight(index);
} }
#if DEBUG
++this.version;
#endif
} }
/// <summary> /// <summary>

View File

@ -93,7 +93,6 @@ namespace Nuclex.Support.Collections {
} }
} }
/// <summary>Verifies that the Insert() method works in all cases</summary> /// <summary>Verifies that the Insert() method works in all cases</summary>
/// <remarks> /// <remarks>
/// We have several different cases here that will be tested. The deque can /// We have several different cases here that will be tested. The deque can
@ -655,6 +654,23 @@ namespace Nuclex.Support.Collections {
delegate() { intDeque.CopyTo(new int[7], 0); } 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> /// <summary>
/// Creates a deque whose first element does not coincide with a block boundary /// Creates a deque whose first element does not coincide with a block boundary

View File

@ -65,6 +65,9 @@ namespace Nuclex.Support.Collections {
/// <summary>The item at the enumerator's current position</summary> /// <summary>The item at the enumerator's current position</summary>
public ItemType Current { public ItemType Current {
get { get {
#if DEBUG
checkVersion();
#endif
if(this.currentBlock == null) { if(this.currentBlock == null) {
throw new InvalidOperationException("Enumerator is not on a valid position"); throw new InvalidOperationException("Enumerator is not on a valid position");
} }
@ -77,6 +80,10 @@ namespace Nuclex.Support.Collections {
/// <returns>True if there was a next item</returns> /// <returns>True if there was a next item</returns>
public bool MoveNext() { public bool MoveNext() {
#if DEBUG
checkVersion();
#endif
// If we haven't reached the last block yet // If we haven't reached the last block yet
if(this.currentBlockIndex < this.lastBlock) { if(this.currentBlockIndex < this.lastBlock) {
@ -117,6 +124,7 @@ namespace Nuclex.Support.Collections {
this.currentBlock = null; this.currentBlock = null;
this.currentBlockIndex = -1; this.currentBlockIndex = -1;
this.subIndex = this.deque.blockSize - 1; this.subIndex = this.deque.blockSize - 1;
this.expectedVersion = this.deque.version;
} }
/// <summary>The item at the enumerator's current position</summary> /// <summary>The item at the enumerator's current position</summary>
@ -124,6 +132,14 @@ namespace Nuclex.Support.Collections {
get { return Current; } get { return Current; }
} }
#if DEBUG
/// <summary>Ensures that the deque has not changed</summary>
private void checkVersion() {
if(this.expectedVersion != this.deque.version)
throw new InvalidOperationException("Deque has been modified");
}
#endif
/// <summary>Deque the enumerator belongs to</summary> /// <summary>Deque the enumerator belongs to</summary>
private Deque<ItemType> deque; private Deque<ItemType> deque;
/// <summary>Size of the blocks in the deque</summary> /// <summary>Size of the blocks in the deque</summary>
@ -140,6 +156,9 @@ namespace Nuclex.Support.Collections {
/// <summary>Index in the current block</summary> /// <summary>Index in the current block</summary>
private int subIndex; private int subIndex;
/// <summary>Version the deque is expected to have</summary>
private int expectedVersion;
} }
#endregion // class Enumerator #endregion // class Enumerator
@ -303,6 +322,10 @@ namespace Nuclex.Support.Collections {
private int firstBlockStartIndex; private int firstBlockStartIndex;
/// <summary>End index of data in the last block</summary> /// <summary>End index of data in the last block</summary>
private int lastBlockEndIndex; private int lastBlockEndIndex;
#if DEBUG
/// <summary>Used to detect when enumerators go out of sync</summary>
private int version;
#endif
} }

View File

@ -43,7 +43,7 @@ namespace Nuclex.Support.Collections {
public void Reset() { public void Reset() {
this.index = -1; this.index = -1;
#if DEBUG #if DEBUG
this.expectedVersion = priorityQueue.version; this.expectedVersion = this.priorityQueue.version;
#endif #endif
} }