#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 {
/// Unit Test for the read only dictionary wrapper
[TestFixture]
internal class ReadOnlyDictionaryTest {
///
/// Verifies that the copy constructor of the read only dictionary works
///
[Test]
public void TestCopyConstructor() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
CollectionAssert.AreEqual(numbers, testDictionary);
}
/// Verifies that the IsReadOnly property returns true
[Test]
public void TestIsReadOnly() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.IsTrue(testDictionary.IsReadOnly);
}
///
/// Checks whether the Contains() method of the read only dictionary is able to
/// determine if the dictionary contains an item
///
[Test]
public void TestContains() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.IsTrue(
testDictionary.Contains(new KeyValuePair(42, "forty-two"))
);
Assert.IsFalse(
testDictionary.Contains(new KeyValuePair(24, "twenty-four"))
);
}
///
/// Checks whether the Contains() method of the read only dictionary is able to
/// determine if the dictionary contains a key
///
[Test]
public void TestContainsKey() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.IsTrue(testDictionary.ContainsKey(42));
Assert.IsFalse(testDictionary.ContainsKey(24));
}
///
/// Verifies that the CopyTo() of the read only dictionary works
///
[Test]
public void TestCopyToArray() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
KeyValuePair[] items = new KeyValuePair[numbers.Count];
testDictionary.CopyTo(items, 0);
CollectionAssert.AreEqual(numbers, items);
}
///
/// Tests whether the typesafe enumerator of the read only dictionary is working
///
[Test]
public void TestTypesafeEnumerator() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
List> outputItems = new List>();
foreach(KeyValuePair item in testDictionary) {
outputItems.Add(item);
}
CollectionAssert.AreEqual(numbers, outputItems);
}
///
/// Tests whether the keys collection of the read only dictionary can be queried
///
[Test]
public void TestGetKeysCollection() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
ICollection inputKeys = numbers.Keys;
ICollection keys = testDictionary.Keys;
CollectionAssert.AreEqual(inputKeys, keys);
}
///
/// Tests whether the values collection of the read only dictionary can be queried
///
[Test]
public void TestGetValuesCollection() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
ICollection inputValues = numbers.Values;
ICollection values = testDictionary.Values;
CollectionAssert.AreEqual(inputValues, values);
}
///
/// Tests whether the TryGetValue() method of the read only dictionary is working
///
[Test]
public void TestTryGetValue() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary 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);
}
///
/// Tests whether the retrieval of values using the indexer of the read only
/// dictionary is working
///
[Test]
public void TestRetrieveValueByIndexer() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.AreEqual("forty-two", testDictionary[42]);
}
///
/// Tests whether an exception is thrown if the indexer of the read only dictionary
/// is used to attempt to retrieve a non-existing value
///
[Test]
public void TestThrowOnRetrieveNonExistingValueByIndexer() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { Console.WriteLine(testDictionary[24]); }
);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// Add() method is called via the generic IDictionary<> interface
///
[Test]
public void TestThrowOnAddViaGenericIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { (testDictionary as IDictionary).Add(10, "ten"); }
);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// Remove() method is called via the generic IDictionary<> interface
///
[Test]
public void TestThrowOnRemoveViaGenericIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { (testDictionary as IDictionary).Remove(3); }
);
}
///
/// Tests whether the TryGetValue() method of the read only dictionary is working
///
[Test]
public void TestRetrieveValueByIndexerViaGenericIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.AreEqual("forty-two", (testDictionary as IDictionary)[42]);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// indexer is used to insert an item via the generic IDictionar<> interface
///
[Test]
public void TestThrowOnReplaceByIndexerViaGenericIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { (testDictionary as IDictionary)[24] = "twenty-four"; }
);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// Clear() method is called via the IDictionary interface
///
[Test]
public void TestThrowOnClearViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { (testDictionary as IDictionary).Clear(); }
);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// Add() method is called via the IDictionary interface
///
[Test]
public void TestThrowOnAddViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { (testDictionary as IDictionary).Add(24, "twenty-four"); }
);
}
///
/// Checks whether the Contains() method of the read only dictionary is able to
/// determine if the dictionary contains an item via the IDictionary interface
///
[Test]
public void TestContainsViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.IsTrue((testDictionary as IDictionary).Contains(42));
Assert.IsFalse((testDictionary as IDictionary).Contains(24));
}
///
/// Checks whether the GetEnumerator() method of the read only dictionary returns
/// a working enumerator if accessed via the IDictionary interface
///
[Test]
public void TestEnumeratorViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Dictionary outputNumbers = new Dictionary();
foreach(DictionaryEntry entry in (testDictionary as IDictionary)) {
(outputNumbers as IDictionary).Add(entry.Key, entry.Value);
}
CollectionAssert.AreEquivalent(numbers, outputNumbers);
}
///
/// Checks whether the IsFixedSize property of the read only dictionary returns
/// the expected result for a read only dictionary based on a dynamic dictionary
///
[Test]
public void TestIsFixedSizeViaIList() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.IsFalse((testDictionary as IDictionary).IsFixedSize);
}
///
/// Tests whether the keys collection of the read only dictionary can be queried
/// via the IDictionary interface
///
[Test]
public void TestGetKeysCollectionViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
ICollection inputKeys = (numbers as IDictionary).Keys;
ICollection keys = (testDictionary as IDictionary).Keys;
CollectionAssert.AreEqual(inputKeys, keys);
}
///
/// Tests whether the values collection of the read only dictionary can be queried
/// via the IDictionary interface
///
[Test]
public void TestGetValuesCollectionViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
ICollection inputValues = (numbers as IDictionary).Values;
ICollection values = (testDictionary as IDictionary).Values;
CollectionAssert.AreEqual(inputValues, values);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// Remove() method is called via the IDictionary interface
///
[Test]
public void TestThrowOnRemoveViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { (testDictionary as IDictionary).Remove(3); }
);
}
///
/// Tests whether the retrieval of values using the indexer of the read only
/// dictionary is working via the IDictionary interface
///
[Test]
public void TestRetrieveValueByIndexerViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.AreEqual("forty-two", (testDictionary as IDictionary)[42]);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// indexer is used to insert an item via the IDictionary interface
///
[Test]
public void TestThrowOnReplaceByIndexerViaIDictionary() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { (testDictionary as IDictionary)[24] = "twenty-four"; }
);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// Add() method is used via the generic ICollection<> interface
///
[Test]
public void TestThrowOnAddViaGenericICollection() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() {
(testDictionary as ICollection>).Add(
new KeyValuePair(24, "twenty-four")
);
}
);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// Clear() method is used via the generic ICollection<> interface
///
[Test]
public void TestThrowOnClearViaGenericICollection() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() { (testDictionary as ICollection>).Clear(); }
);
}
///
/// Checks whether the read only dictionary will throw an exception if its
/// Remove() method is used via the generic ICollection<> interface
///
[Test]
public void TestThrowOnRemoveViaGenericICollection() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
Assert.Throws(
delegate() {
(testDictionary as ICollection>).Remove(
new KeyValuePair(42, "fourty-two")
);
}
);
}
///
/// Verifies that the CopyTo() of the read only dictionary works when called
/// via the the ICollection interface
///
[Test]
public void TestCopyToArrayViaICollection() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
DictionaryEntry[] entries = new DictionaryEntry[numbers.Count];
(testDictionary as ICollection).CopyTo(entries, 0);
KeyValuePair[] items = new KeyValuePair[numbers.Count];
for(int index = 0; index < entries.Length; ++index) {
items[index] = new KeyValuePair(
(int)entries[index].Key, (string)entries[index].Value
);
}
CollectionAssert.AreEquivalent(numbers, items);
}
///
/// Verifies that the IsSynchronized property and the SyncRoot property are working
///
[Test]
public void TestSynchronization() {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary = makeReadOnly(numbers);
if(!(testDictionary as ICollection).IsSynchronized) {
lock((testDictionary as ICollection).SyncRoot) {
Assert.AreEqual(numbers.Count, testDictionary.Count);
}
}
}
///
/// Test whether the read only dictionary can be serialized
///
[Test]
public void TestSerialization() {
BinaryFormatter formatter = new BinaryFormatter();
using(MemoryStream memory = new MemoryStream()) {
Dictionary numbers = createTestDictionary();
ReadOnlyDictionary testDictionary1 = makeReadOnly(numbers);
formatter.Serialize(memory, testDictionary1);
memory.Position = 0;
object testDictionary2 = formatter.Deserialize(memory);
CollectionAssert.AreEquivalent(testDictionary1, (IEnumerable)testDictionary2);
}
}
///
/// Creates a new read-only dictionary filled with some values for testing
///
/// The newly created read-only dictionary
private static Dictionary createTestDictionary() {
Dictionary numbers = new Dictionary();
numbers.Add(1, "one");
numbers.Add(2, "two");
numbers.Add(3, "three");
numbers.Add(42, "forty-two");
return new Dictionary(numbers);
}
///
/// Creates a new read-only dictionary filled with some values for testing
///
/// The newly created read-only dictionary
private static ReadOnlyDictionary makeReadOnly(
IDictionary dictionary
) {
return new ReadOnlyDictionary(dictionary);
}
}
} // namespace Nuclex.Support.Collections
#endif // UNITTEST