using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; namespace Amphora.UnitTests { public class OrderedDictionaryTests : UnitTestSharp.TestFixture { public static OrderedDictionary Seeded() { var returnMe = new OrderedDictionary(); returnMe.Add("one", 1); returnMe.Add("two", 2); returnMe.Add("three", 3); return returnMe; } public static List KeysInOrder(OrderedDictionary dictionary) { var returnMe = new List(); foreach (var pair in dictionary) { returnMe.Add(pair.Key); } return returnMe; } public static List ValuesInOrder(OrderedDictionary dictionary) { var returnMe = new List(); foreach (var pair in dictionary) { returnMe.Add(pair.Value); } return returnMe; } public class CtorTests : UnitTestSharp.TestFixture { public void StartsEmpty() { CheckEqual(0, new OrderedDictionary().Count); } public void UsesTheSuppliedComparerForLookups() { var dictionary = new OrderedDictionary(StringComparer.OrdinalIgnoreCase); dictionary.Add("key", 1); Check(dictionary.ContainsKey("KEY")); } public void AcceptsAnInitialCapacity() { CheckEqual(0, new OrderedDictionary(capacity: 16).Count); } } public class IndexerByKeyTests : UnitTestSharp.TestFixture { public void Get_ReturnsTheValue() { CheckEqual(2, Seeded()["two"]); } public void Get_MissingKey_Throws() { var dictionary = Seeded(); CheckThrow(typeof(KeyNotFoundException)); var ignored = dictionary["absent"]; } public void Set_NewKey_AppendsAtTheEnd() { var dictionary = Seeded(); dictionary["four"] = 4; CheckEqual(new[] { "one", "two", "three", "four" }, KeysInOrder(dictionary)); } public void Set_ExistingKey_UpdatesValueAndKeepsPosition() { var dictionary = Seeded(); dictionary["two"] = 22; CheckEqual(22, dictionary["two"]); CheckEqual(1, dictionary.IndexOf("two")); CheckEqual(new[] { "one", "two", "three" }, KeysInOrder(dictionary)); } } public class AddTests : UnitTestSharp.TestFixture { public void AppendsInInsertionOrder() { CheckEqual(new[] { "one", "two", "three" }, KeysInOrder(Seeded())); } public void DuplicateKey_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentException)); dictionary.Add("two", 99); } public void DuplicateKey_LeavesTheDictionaryUnchanged() { var dictionary = Seeded(); try { dictionary.Add("two", 99); } catch (ArgumentException) { } CheckEqual(3, dictionary.Count); CheckEqual(2, dictionary["two"]); CheckEqual(new[] { "one", "two", "three" }, KeysInOrder(dictionary)); } } public class AddPairTests : UnitTestSharp.TestFixture { public void AppendsThePair() { var dictionary = Seeded(); dictionary.Add(new KeyValuePair("four", 4)); CheckEqual(4, dictionary["four"]); CheckEqual(new[] { "one", "two", "three", "four" }, KeysInOrder(dictionary)); } } public class RemoveByKeyTests : UnitTestSharp.TestFixture { public void ExistingKey_RemovesAndReturnsTrue() { var dictionary = Seeded(); Check(dictionary.Remove("two")); CheckFalse(dictionary.ContainsKey("two")); CheckEqual(new[] { "one", "three" }, KeysInOrder(dictionary)); } public void MissingKey_ReturnsFalse() { CheckFalse(Seeded().Remove("absent")); } } public class ContainsKeyTests : UnitTestSharp.TestFixture { public void Present_ReturnsTrue() { Check(Seeded().ContainsKey("one")); } public void Absent_ReturnsFalse() { CheckFalse(Seeded().ContainsKey("absent")); } } public class TryGetValueTests : UnitTestSharp.TestFixture { public void Present_ReturnsTrueAndTheValue() { Check(Seeded().TryGetValue("three", out int value)); CheckEqual(3, value); } public void Absent_ReturnsFalseAndDefault() { CheckFalse(Seeded().TryGetValue("absent", out int value)); CheckEqual(0, value); } } public class ClearTests : UnitTestSharp.TestFixture { public void EmptiesTheDictionary() { var dictionary = Seeded(); dictionary.Clear(); CheckEqual(0, dictionary.Count); CheckFalse(dictionary.ContainsKey("one")); } } public class CountTests : UnitTestSharp.TestFixture { public void TracksAddsAndRemoves() { var dictionary = Seeded(); CheckEqual(3, dictionary.Count); dictionary.Remove("one"); CheckEqual(2, dictionary.Count); } } public class KeysTests : UnitTestSharp.TestFixture { public void AreInInsertionOrder() { CheckEqual(new[] { "one", "two", "three" }, new List(Seeded().Keys)); } public void AreASnapshot() { var dictionary = Seeded(); dictionary.Keys.Clear(); CheckEqual(3, dictionary.Count); } } public class ValuesTests : UnitTestSharp.TestFixture { public void AreInInsertionOrder() { CheckEqual(new[] { 1, 2, 3 }, new List(Seeded().Values)); } public void ReflectUpdatedValues() { var dictionary = Seeded(); dictionary["two"] = 22; CheckEqual(new[] { 1, 22, 3 }, new List(dictionary.Values)); } public void EmptyDictionary_HasNoValues() { CheckEqual(0, new OrderedDictionary().Values.Count); } } public class EnumerationTests : UnitTestSharp.TestFixture { public void YieldsPairsInInsertionOrder() { CheckEqual(new[] { 1, 2, 3 }, ValuesInOrder(Seeded())); } public void EmptyDictionary_YieldsNothing() { int count = 0; foreach (var pair in new OrderedDictionary()) { ++count; } CheckEqual(0, count); } } public class IndexOfTests : UnitTestSharp.TestFixture { public void Present_ReturnsThePosition() { CheckEqual(2, Seeded().IndexOf("three")); } public void Absent_ReturnsMinusOne() { CheckEqual(-1, Seeded().IndexOf("absent")); } } public class GetAtTests : UnitTestSharp.TestFixture { public void ReturnsThePairAtThePosition() { var pair = Seeded().GetAt(1); CheckEqual("two", pair.Key); CheckEqual(2, pair.Value); } public void OutOfRange_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); dictionary.GetAt(3); } } public class SetAtTests : UnitTestSharp.TestFixture { public void UpdatesTheValueLeavingTheKey() { var dictionary = Seeded(); dictionary.SetAt(1, 22); CheckEqual(22, dictionary["two"]); CheckEqual(new[] { "one", "two", "three" }, KeysInOrder(dictionary)); } public void OutOfRange_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); dictionary.SetAt(3, 0); } } public class InsertTests : UnitTestSharp.TestFixture { public void InsertsAtThePosition() { var dictionary = Seeded(); dictionary.Insert(1, "inserted", 99); CheckEqual(new[] { "one", "inserted", "two", "three" }, KeysInOrder(dictionary)); CheckEqual(99, dictionary["inserted"]); } public void AtCount_AppendsAtTheEnd() { var dictionary = Seeded(); dictionary.Insert(3, "four", 4); CheckEqual(new[] { "one", "two", "three", "four" }, KeysInOrder(dictionary)); } public void DuplicateKey_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentException)); dictionary.Insert(0, "two", 99); } public void DuplicateKey_LeavesTheDictionaryUnchanged() { var dictionary = Seeded(); try { dictionary.Insert(0, "two", 99); } catch (ArgumentException) { } CheckEqual(new[] { "one", "two", "three" }, KeysInOrder(dictionary)); } public void IndexPastEnd_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); dictionary.Insert(4, "four", 4); } public void NegativeIndex_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); dictionary.Insert(-1, "four", 4); } public void IndexPastEnd_DoesNotAddTheValue() { var dictionary = Seeded(); try { dictionary.Insert(4, "four", 4); } catch (ArgumentOutOfRangeException) { } CheckFalse(dictionary.ContainsKey("four")); CheckEqual(3, dictionary.Count); } } public class RemoveAtTests : UnitTestSharp.TestFixture { public void RemovesThePairAtThePosition() { var dictionary = Seeded(); dictionary.RemoveAt(1); CheckFalse(dictionary.ContainsKey("two")); CheckEqual(new[] { "one", "three" }, KeysInOrder(dictionary)); } public void OutOfRange_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); dictionary.RemoveAt(3); } } public class ContainsPairTests : UnitTestSharp.TestFixture { public void MatchingKeyAndValue_ReturnsTrue() { Check(Seeded().Contains(new KeyValuePair("two", 2))); } public void MatchingKeyWrongValue_ReturnsFalse() { CheckFalse(Seeded().Contains(new KeyValuePair("two", 99))); } public void MissingKey_ReturnsFalse() { CheckFalse(Seeded().Contains(new KeyValuePair("absent", 1))); } } public class RemovePairTests : UnitTestSharp.TestFixture { public void Matching_RemovesAndReturnsTrue() { var dictionary = Seeded(); Check(dictionary.Remove(new KeyValuePair("two", 2))); CheckFalse(dictionary.ContainsKey("two")); } public void WrongValue_KeepsThePairAndReturnsFalse() { var dictionary = Seeded(); CheckFalse(dictionary.Remove(new KeyValuePair("two", 99))); Check(dictionary.ContainsKey("two")); } } public class CopyToTests : UnitTestSharp.TestFixture { public void CopiesPairsInOrderStartingAtTheIndex() { var array = new KeyValuePair[4]; Seeded().CopyTo(array, 1); CheckEqual(default(KeyValuePair), array[0]); CheckEqual(new KeyValuePair("one", 1), array[1]); CheckEqual(new KeyValuePair("three", 3), array[3]); } public void NullArray_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentNullException)); dictionary.CopyTo(null, 0); } public void NegativeIndex_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); dictionary.CopyTo(new KeyValuePair[3], -1); } public void ArrayTooSmall_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentException)); dictionary.CopyTo(new KeyValuePair[2], 0); } public void IndexPastArrayEnd_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); dictionary.CopyTo(new KeyValuePair[3], 4); } public void EmptyDictionary_CopiesNothing() { var array = new KeyValuePair[1]; array[0] = new KeyValuePair("untouched", 7); new OrderedDictionary().CopyTo(array, 0); CheckEqual(new KeyValuePair("untouched", 7), array[0]); } } public class IsReadOnlyTests : UnitTestSharp.TestFixture { public void IsFalse() { CheckFalse(new OrderedDictionary().IsReadOnly); } } public class NonGenericIDictionaryTests : UnitTestSharp.TestFixture { public void Indexer_MissingKey_ReturnsNull() { IDictionary dictionary = Seeded(); CheckNull(dictionary["absent"]); } public void Indexer_ReturnsTheValue() { IDictionary dictionary = Seeded(); CheckEqual(2, dictionary["two"]); } public void Indexer_Set_UpdatesTheValue() { var dictionary = Seeded(); ((IDictionary)dictionary)["two"] = 22; CheckEqual(22, dictionary["two"]); } public void Add_AddsThePair() { var dictionary = Seeded(); ((IDictionary)dictionary).Add("four", 4); CheckEqual(4, dictionary["four"]); } public void Contains_ChecksTheKey() { IDictionary dictionary = Seeded(); Check(dictionary.Contains("one")); CheckFalse(dictionary.Contains("absent")); } public void Remove_RemovesTheKey() { var dictionary = Seeded(); ((IDictionary)dictionary).Remove("two"); CheckFalse(dictionary.ContainsKey("two")); } public void IsFixedSize_IsFalse() { CheckFalse(((IDictionary)Seeded()).IsFixedSize); } public void GetEnumerator_YieldsEntriesInInsertionOrder() { IDictionary dictionary = Seeded(); var keys = new List(); IDictionaryEnumerator enumerator = dictionary.GetEnumerator(); while (enumerator.MoveNext()) { keys.Add(enumerator.Key); } CheckEqual(new object[] { "one", "two", "three" }, keys); } public void Enumerator_EntryExposesKeyAndValue() { IDictionary dictionary = Seeded(); IDictionaryEnumerator enumerator = dictionary.GetEnumerator(); enumerator.MoveNext(); CheckEqual("one", enumerator.Entry.Key); CheckEqual(1, enumerator.Entry.Value); CheckEqual(1, enumerator.Value); } public void Enumerator_CurrentExposesTheEntry() { IDictionary dictionary = Seeded(); IDictionaryEnumerator enumerator = dictionary.GetEnumerator(); enumerator.MoveNext(); var entry = (DictionaryEntry)enumerator.Current; CheckEqual("one", entry.Key); CheckEqual(1, entry.Value); } public void Enumerator_ResetRestartsEnumeration() { IDictionary dictionary = Seeded(); IDictionaryEnumerator enumerator = dictionary.GetEnumerator(); enumerator.MoveNext(); enumerator.Reset(); enumerator.MoveNext(); CheckEqual("one", enumerator.Key); } public void Keys_AreInInsertionOrder() { IDictionary dictionary = Seeded(); var keys = new List(); foreach (object key in dictionary.Keys) { keys.Add(key); } CheckEqual(new object[] { "one", "two", "three" }, keys); } public void Values_AreInInsertionOrder() { IDictionary dictionary = Seeded(); var values = new List(); foreach (object value in dictionary.Values) { values.Add(value); } CheckEqual(new object[] { 1, 2, 3 }, values); } public void Indexer_WrongKeyType_ReturnsNull() { IDictionary dictionary = Seeded(); CheckNull(dictionary[123]); } public void Contains_WrongKeyType_ReturnsFalse() { IDictionary dictionary = Seeded(); CheckFalse(dictionary.Contains(123)); } public void Remove_WrongKeyType_DoesNothing() { var dictionary = Seeded(); ((IDictionary)dictionary).Remove(123); CheckEqual(3, dictionary.Count); } } public class NonGenericIOrderedDictionaryTests : UnitTestSharp.TestFixture { public void Indexer_ReturnsTheValueAtThePosition() { IOrderedDictionary dictionary = Seeded(); CheckEqual(2, dictionary[1]); } public void Indexer_Set_UpdatesTheValueAtThePosition() { var dictionary = Seeded(); ((IOrderedDictionary)dictionary)[1] = 22; CheckEqual(22, dictionary["two"]); } public void Insert_InsertsAtThePosition() { var dictionary = Seeded(); ((IOrderedDictionary)dictionary).Insert(1, "inserted", 99); CheckEqual(new[] { "one", "inserted", "two", "three" }, KeysInOrder(dictionary)); } } public class NonGenericICollectionTests : UnitTestSharp.TestFixture { public void CopyTo_CopiesDictionaryEntriesInOrder() { var array = new DictionaryEntry[3]; ((ICollection)Seeded()).CopyTo(array, 0); CheckEqual("one", array[0].Key); CheckEqual(1, array[0].Value); CheckEqual("three", array[2].Key); } public void IsSynchronized_IsFalse() { CheckFalse(((ICollection)Seeded()).IsSynchronized); } public void SyncRoot_IsNotNull() { CheckNotNull(((ICollection)Seeded()).SyncRoot); } public void Count_ReflectsTheSize() { CheckEqual(3, ((ICollection)Seeded()).Count); } public void CopyTo_ArrayTooSmall_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentException)); ((ICollection)dictionary).CopyTo(new DictionaryEntry[2], 0); } public void CopyTo_NullArray_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentNullException)); ((ICollection)dictionary).CopyTo(null, 0); } public void CopyTo_NegativeIndex_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); ((ICollection)dictionary).CopyTo(new DictionaryEntry[3], -1); } public void CopyTo_IndexPastArrayEnd_Throws() { var dictionary = Seeded(); CheckThrow(typeof(ArgumentOutOfRangeException)); ((ICollection)dictionary).CopyTo(new DictionaryEntry[3], 4); } public void CopyTo_EmptyDictionary_CopiesNothing() { var array = new DictionaryEntry[1]; array[0] = new DictionaryEntry("untouched", 7); ((ICollection)new OrderedDictionary()).CopyTo(array, 0); CheckEqual("untouched", array[0].Key); } } public class ReadOnlyDictionaryTests : UnitTestSharp.TestFixture { public void Keys_AreInInsertionOrder() { IReadOnlyDictionary dictionary = Seeded(); CheckEqual(new[] { "one", "two", "three" }, new List(dictionary.Keys)); } public void Values_AreInInsertionOrder() { IReadOnlyDictionary dictionary = Seeded(); CheckEqual(new[] { 1, 2, 3 }, new List(dictionary.Values)); } } // Smoke tests: both just forward to the generic enumerator, whose contents and ordering are covered by // EnumerationTests and NonGenericIDictionaryTests. public class NonGenericGetEnumeratorTests : UnitTestSharp.TestFixture { public void IEnumerable_ReturnsAnEnumerator() { CheckNotNull(((IEnumerable)Seeded()).GetEnumerator()); } public void IOrderedDictionary_ReturnsAnEnumerator() { CheckNotNull(((IOrderedDictionary)Seeded()).GetEnumerator()); } } // Smoke test: a constant forward, with the meaningful behavior covered by IsReadOnlyTests. public class IDictionaryIsReadOnlyTests : UnitTestSharp.TestFixture { public void ReturnsFalse() { CheckFalse(((IDictionary)Seeded()).IsReadOnly); } } } }