From 805437c96e4c90777cf95755f19acefed9277544 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 28 Nov 2021 23:37:31 +0100 Subject: [PATCH] Add unit tests for Dictionary2 --- .../Internals/Test_Dictionary2.cs | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 tests/CommunityToolkit.Mvvm.UnitTests/Internals/Test_Dictionary2.cs diff --git a/tests/CommunityToolkit.Mvvm.UnitTests/Internals/Test_Dictionary2.cs b/tests/CommunityToolkit.Mvvm.UnitTests/Internals/Test_Dictionary2.cs new file mode 100644 index 00000000..a97053cd --- /dev/null +++ b/tests/CommunityToolkit.Mvvm.UnitTests/Internals/Test_Dictionary2.cs @@ -0,0 +1,170 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace CommunityToolkit.Mvvm.UnitTests.Internals; + +[TestClass] +public class Test_Dictionary2 +{ + private static void AddItems(T[] keys) + where T : IEquatable + { + object[] values = Enumerable.Range(0, keys.Length).Select(static x => new object()).ToArray(); + + Dictionary2 dictionary = new(); + + // Go through all keys once + for (int i = 0; i < keys.Length; i++) + { + T key = keys[i]; + + // Verify the key doesn't exist yet + Assert.AreEqual(i, dictionary.Count); + Assert.IsFalse(dictionary.ContainsKey(key)); + Assert.IsFalse(dictionary.TryGetValue(key, out object? obj)); + Assert.IsNull(obj); + Assert.IsFalse(dictionary.TryRemove(key)); + + _ = Assert.ThrowsException(() => _ = dictionary[key]); + + // This should create a new entry + ref object? value = ref dictionary.GetOrAddValueRef(key); + + Assert.IsNull(value); + + value = values[i]; + + // Verify the key now exists + Assert.IsTrue(dictionary.ContainsKey(key)); + Assert.IsTrue(dictionary.TryGetValue(key, out obj)); + Assert.AreSame(obj, value); + Assert.AreSame(obj, values[i]); + + // Get the key again, should point to the same location + ref object? value2 = ref dictionary.GetOrAddValueRef(key); + + Assert.IsTrue(Unsafe.AreSame(ref value, ref value2!)); + } + + Assert.AreEqual(keys.Length, dictionary.Count); + + HashSet keysSet = new(); + HashSet valuesSet = new(); + + Dictionary2.Enumerator enumerator = dictionary.GetEnumerator(); + + // Gather all key/value pairs through the enumerator + while (enumerator.MoveNext()) + { + Assert.IsTrue(keysSet.Add(enumerator.GetKey())); + Assert.IsTrue(valuesSet.Add(enumerator.GetValue())); + } + + // Verify we have all values we expect + CollectionAssert.AreEquivalent(keys, keysSet.ToArray()); + CollectionAssert.AreEquivalent(values, valuesSet.ToArray()); + + dictionary.Clear(); + + // Verify the dictionary was cleared properly + Assert.AreEqual(0, dictionary.Count); + + enumerator = dictionary.GetEnumerator(); + + while (enumerator.MoveNext()) + { + // Since the dictionary is now empty, we should never get here + Assert.Fail(); + } + } + + [TestMethod] + [DataRow(1)] + [DataRow(101)] + [DataRow(2467)] + public void AddItems_Int(int count) + { + AddItems(Enumerable.Range(0, count).ToArray()); + } + + [TestMethod] + [DataRow(1)] + [DataRow(101)] + [DataRow(2467)] + public void AddItems_String(int count) + { + AddItems(Enumerable.Range(0, count).Select(static x => x.ToString()).ToArray()); + } + + private static void TryRemoveItems(T[] keys) + where T : IEquatable + { + object[] values = Enumerable.Range(0, keys.Length).Select(static x => new object()).ToArray(); + + Dictionary2 dictionary = new(); + + // Populate the dictionary + for (int i = 0; i < keys.Length; i++) + { + T key = keys[i]; + + dictionary.GetOrAddValueRef(key) = values[i]; + } + + Random random = new(42); + + keys = keys + .Select(x => (Key: x, Index: random.Next())) + .OrderBy(static x => x.Index) + .Select(static x => x.Key) + .ToArray(); + + values = keys.Select(k => dictionary[k]).ToArray(); + + for (int i = 0; i < keys.Length; i++) + { + T key = keys[i]; + + // Verify the state is consistent across removals + Assert.AreEqual(keys.Length - i, dictionary.Count); + Assert.IsTrue(dictionary.ContainsKey(key)); + Assert.IsTrue(dictionary.TryGetValue(key, out object? obj)); + Assert.AreSame(values[i], obj); + + // Remove the item + Assert.IsTrue(dictionary.TryRemove(key)); + + // Verify the state is consistent after the removal + Assert.IsFalse(dictionary.ContainsKey(key)); + Assert.IsFalse(dictionary.TryGetValue(key, out obj)); + Assert.IsNull(obj); + } + + Assert.AreEqual(0, dictionary.Count); + } + + [TestMethod] + [DataRow(1)] + [DataRow(101)] + [DataRow(2467)] + public void TryRemoveItems_Int(int count) + { + TryRemoveItems(Enumerable.Range(0, count).ToArray()); + } + + [TestMethod] + [DataRow(1)] + [DataRow(101)] + [DataRow(2467)] + public void TryRemoveItems_String(int count) + { + TryRemoveItems(Enumerable.Range(0, count).Select(static x => x.ToString()).ToArray()); + } +}