From de7c28fa84df516950adb5004b3a68edefa76a8c Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Thu, 27 Nov 2008 19:02:48 +0000 Subject: [PATCH] achieved 100% test coverage for the read only collection wrapper; optimized the indexer of the license key class; increased test coverage for the license key class to 100% git-svn-id: file:///srv/devel/repo-conversion/nusu@95 d2e56fa2-650e-0410-a79f-9358c0239efd --- Nuclex.Support.csproj | 3 + Source/Collections/ReadOnlyCollection.Test.cs | 157 ++++++++++++++++++ Source/Collections/ReadOnlyCollection.cs | 6 +- Source/Licensing/LicenseKey.Test.cs | 44 +++++ Source/Licensing/LicenseKey.cs | 16 +- 5 files changed, 218 insertions(+), 8 deletions(-) create mode 100644 Source/Collections/ReadOnlyCollection.Test.cs diff --git a/Nuclex.Support.csproj b/Nuclex.Support.csproj index 7df9c25..0df9c9a 100644 --- a/Nuclex.Support.csproj +++ b/Nuclex.Support.csproj @@ -76,6 +76,9 @@ PriorityQueue.cs + + ReadOnlyCollection.cs + diff --git a/Source/Collections/ReadOnlyCollection.Test.cs b/Source/Collections/ReadOnlyCollection.Test.cs new file mode 100644 index 0000000..15e1309 --- /dev/null +++ b/Source/Collections/ReadOnlyCollection.Test.cs @@ -0,0 +1,157 @@ +#region CPL License +/* +Nuclex Framework +Copyright (C) 2002-2008 Nuclex Development Labs + +This library is free software; you can redistribute it and/or +modify it under the terms of the IBM Common Public License as +published by the IBM Corporation; either version 1.0 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +IBM Common Public License for more details. + +You should have received a copy of the IBM Common Public +License along with this library +*/ +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; + +#if UNITTEST + +using NUnit.Framework; + +namespace Nuclex.Support.Collections { + + /// Unit Test for the read only collection wrapper + [TestFixture] + public class ReadOnlyCollectionTest { + + /// + /// Verifies that the copy constructor of the read only collection works + /// + [Test] + public void TestCopyConstructor() { + int[] integers = new int[] { 12, 34, 56, 78 }; + ReadOnlyCollection testCollection = new ReadOnlyCollection(integers); + + CollectionAssert.AreEqual(integers, testCollection); + } + + /// Verifies that the IsReadOnly property returns true + [Test] + public void TestIsReadOnly() { + ReadOnlyCollection testCollection = new ReadOnlyCollection(new int[0]); + + Assert.IsTrue(testCollection.IsReadOnly); + } + + /// + /// Verifies that the CopyTo() of the read only collection works + /// + [Test] + public void TestCopyToArray() { + int[] inputIntegers = new int[] { 12, 34, 56, 78 }; + ReadOnlyCollection testCollection = new ReadOnlyCollection(inputIntegers); + + int[] outputIntegers = new int[testCollection.Count]; + testCollection.CopyTo(outputIntegers, 0); + + CollectionAssert.AreEqual(inputIntegers, outputIntegers); + } + + /// + /// Checks whether the Contains() method of the read only collection is able to + /// determine if the collection contains an item + /// + [Test] + public void TestContains() { + int[] integers = new int[] { 1234, 6789 }; + ReadOnlyCollection testCollection = new ReadOnlyCollection(integers); + + Assert.IsTrue(testCollection.Contains(1234)); + Assert.IsFalse(testCollection.Contains(4321)); + } + + /// + /// Ensures that the Add() method of the read only collection throws an exception + /// + [Test, ExpectedException(typeof(NotSupportedException))] + public void TestThrowOnAdd() { + ReadOnlyCollection testCollection = new ReadOnlyCollection(new int[0]); + (testCollection as ICollection).Add(123); + } + + /// + /// Ensures that the Remove() method of the read only collection throws an exception + /// + [Test, ExpectedException(typeof(NotSupportedException))] + public void TestThrowOnRemove() { + ReadOnlyCollection testCollection = new ReadOnlyCollection(new int[0]); + (testCollection as ICollection).Remove(123); + } + + /// + /// Ensures that the Clear() method of the read only collection throws an exception + /// + [Test, ExpectedException(typeof(NotSupportedException))] + public void TestThrowOnClear() { + ReadOnlyCollection testCollection = new ReadOnlyCollection(new int[0]); + (testCollection as ICollection).Clear(); + } + + /// + /// Tests whether the typesafe enumerator of the read only collection is working + /// + [Test] + public void TestTypesafeEnumerator() { + int[] inputIntegers = new int[] { 12, 34, 56, 78 }; + ReadOnlyCollection testCollection = new ReadOnlyCollection(inputIntegers); + + List outputIntegers = new List(); + foreach(int value in testCollection) { + outputIntegers.Add(value); + } + + CollectionAssert.AreEqual(inputIntegers, outputIntegers); + } + + /// + /// Verifies that the CopyTo() of the read only collection works if invoked via + /// the ICollection interface + /// + [Test] + public void TestCopyToArrayViaICollection() { + int[] inputIntegers = new int[] { 12, 34, 56, 78 }; + ReadOnlyCollection testCollection = new ReadOnlyCollection(inputIntegers); + + int[] outputIntegers = new int[testCollection.Count]; + (testCollection as ICollection).CopyTo(outputIntegers, 0); + + CollectionAssert.AreEqual(inputIntegers, outputIntegers); + } + + /// + /// Verifies that the IsSynchronized property and the SyncRoot property are working + /// + [Test] + public void TestSynchronization() { + ReadOnlyCollection testCollection = new ReadOnlyCollection(new int[0]); + + if(!(testCollection as ICollection).IsSynchronized) { + lock((testCollection as ICollection).SyncRoot) { + int count = testCollection.Count; + } + } + } + + } + +} // namespace Nuclex.Support.Collections + +#endif // UNITTEST diff --git a/Source/Collections/ReadOnlyCollection.cs b/Source/Collections/ReadOnlyCollection.cs index c7d296e..53929bc 100644 --- a/Source/Collections/ReadOnlyCollection.cs +++ b/Source/Collections/ReadOnlyCollection.cs @@ -115,17 +115,17 @@ namespace Nuclex.Support.Collections { /// Starting index at which to begin filling the destination array /// void ICollection.CopyTo(Array array, int index) { - throw new NotImplementedException(); + this.objectCollection.CopyTo(array, index); } /// Whether the List is synchronized for multi-threaded usage bool ICollection.IsSynchronized { - get { throw new NotImplementedException(); } + get { return this.objectCollection.IsSynchronized; } } /// Synchronization root on which the List locks object ICollection.SyncRoot { - get { throw new NotImplementedException(); } + get { return this.objectCollection.SyncRoot; } } #endregion diff --git a/Source/Licensing/LicenseKey.Test.cs b/Source/Licensing/LicenseKey.Test.cs index 16f9f0f..0e72b87 100644 --- a/Source/Licensing/LicenseKey.Test.cs +++ b/Source/Licensing/LicenseKey.Test.cs @@ -31,6 +31,13 @@ namespace Nuclex.Support.Licensing { [TestFixture] public class LicenseKeyTest { + /// Tests the default constructor of the license key class + [Test] + public void TestDefaultConstructor() { + new LicenseKey(); + } + + /// Validates the correct translation of keys to GUIDs and back [Test] public void TestGuidKeyConversion() { @@ -88,6 +95,43 @@ namespace Nuclex.Support.Licensing { } + /// Tests whether license keys can be modified without destroying them + [Test, ExpectedException(typeof(ArgumentException))] + public void TestParseInvalidLicenseKey() { + LicenseKey.Parse("hello world"); + } + + /// + /// Tests whether an exception is thrown if the indexer of a license key is used + /// with an invalid index to retrieve a component of the key + /// + [Test, ExpectedException(typeof(IndexOutOfRangeException))] + public void TestGetByIndexerWithInvalidIndex() { + LicenseKey key = new LicenseKey(); + int indexMinusOne = key[-1]; + } + + /// + /// Tests whether an exception is thrown if the indexer of a license key is used + /// with an invalid index to set a component of the key + /// + [Test, ExpectedException(typeof(IndexOutOfRangeException))] + public void TestSetByIndexerWithInvalidIndex() { + LicenseKey key = new LicenseKey(); + key[-1] = 0; + } + + /// + /// Verifies that a license key can be converted into a byte array + /// + [Test] + public void TestToByteArray() { + Guid someGuid = Guid.NewGuid(); + LicenseKey someKey = new LicenseKey(someGuid); + + CollectionAssert.AreEqual(someGuid.ToByteArray(), someKey.ToByteArray()); + } + } } // namespace Nuclex.Support.Licensing diff --git a/Source/Licensing/LicenseKey.cs b/Source/Licensing/LicenseKey.cs index 555ce92..3029501 100644 --- a/Source/Licensing/LicenseKey.cs +++ b/Source/Licensing/LicenseKey.cs @@ -113,12 +113,18 @@ namespace Nuclex.Support.Licensing { if((index < 0) || (index > 3)) throw new IndexOutOfRangeException("Index out of range"); - using(MemoryStream guidBytes = new MemoryStream(this.guid.ToByteArray())) { - guidBytes.Position = index * 4; - new BinaryWriter(guidBytes).Write(value); + // Convert the GUID into binary data so we can replace one of its values + byte[] guidBytes = this.guid.ToByteArray(); - this.guid = new Guid(guidBytes.ToArray()); - } + // Overwrite the section at the index specified by the user with the new value + Array.Copy( + BitConverter.GetBytes(value), 0, // source and start index + guidBytes, index * 4, // destination and start index + 4 // length + ); + + // Replacement finished, now we can reconstruct our guid + this.guid = new Guid(guidBytes); } }