Use IGenericSharedAPI test harness in PriorityQueue (#50291)
authorEirik Tsarpalis <eirik.tsarpalis@gmail.com>
Sat, 27 Mar 2021 00:31:05 +0000 (00:31 +0000)
committerGitHub <noreply@github.com>
Sat, 27 Mar 2021 00:31:05 +0000 (00:31 +0000)
* Use IGenericSharedAPI test harness in PriorityQueue

* remove dead code

* remove index check from IEnumerator.Current

* Update src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Generic.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>
* Update src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Generic.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
src/libraries/System.Collections/src/System/Collections/Generic/PriorityQueue.cs
src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Generic.Tests.cs
src/libraries/System.Collections/tests/Generic/PriorityQueue/PriorityQueue.Generic.cs
src/libraries/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs

index c345ed8..ae4b3c3 100644 (file)
@@ -912,10 +912,7 @@ namespace System.Collections.Generic
                 /// Gets the element at the current position of the enumerator.
                 /// </summary>
                 public (TElement Element, TPriority Priority) Current => _current;
-
-                object IEnumerator.Current =>
-                    _index == 0 || _index == _queue._size + 1 ? throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen) :
-                    Current;
+                object IEnumerator.Current => _current;
 
                 void IEnumerator.Reset()
                 {
index 5a0ac9e..72169ac 100644 (file)
@@ -7,29 +7,29 @@ using Xunit;
 
 namespace System.Collections.Tests
 {
-    public abstract class PriorityQueue_Generic_Tests<TElement, TPriority> : TestBase<TPriority>
+    public abstract class PriorityQueue_Generic_Tests<TElement, TPriority> : IGenericSharedAPI_Tests<(TElement Element, TPriority Priority)>
     {
-        protected abstract TElement CreateElement(int seed);
+        #region PriorityQueue Helper methods
+        protected virtual IComparer<TPriority>? GetPriorityComparer() => Comparer<TPriority>.Default;
 
-        #region Helper methods
         protected IEnumerable<(TElement, TPriority)> CreateItems(int count)
         {
             const int MagicValue = 34;
             int seed = count * MagicValue;
             for (int i = 0; i < count; i++)
             {
-                yield return (CreateElement(seed++), CreateT(seed++));
+                yield return CreateT(seed++);
             }
         }
 
         protected PriorityQueue<TElement, TPriority> CreateEmptyPriorityQueue(int initialCapacity = 0)
-            => new PriorityQueue<TElement, TPriority>(initialCapacity, GetIComparer());
+            => new PriorityQueue<TElement, TPriority>(initialCapacity, GetPriorityComparer());
 
         protected PriorityQueue<TElement, TPriority> CreatePriorityQueue(
             int initialCapacity, int countOfItemsToGenerate, out List<(TElement element, TPriority priority)> generatedItems)
         {
             generatedItems = CreateItems(countOfItemsToGenerate).ToList();
-            var queue = new PriorityQueue<TElement, TPriority>(initialCapacity, GetIComparer());
+            var queue = new PriorityQueue<TElement, TPriority>(initialCapacity, GetPriorityComparer());
             queue.EnqueueRange(generatedItems);
             return queue;
         }
@@ -59,7 +59,7 @@ namespace System.Collections.Tests
         [Fact]
         public void PriorityQueue_ComparerConstructor_ComparerShouldEqualParameter()
         {
-            IComparer<TPriority> comparer = GetIComparer();
+            IComparer<TPriority> comparer = GetPriorityComparer();
             var queue = new PriorityQueue<TElement, TPriority>(comparer);
             Assert.Equal(comparer, queue.Comparer);
         }
@@ -86,7 +86,7 @@ namespace System.Collections.Tests
         public void PriorityQueue_EnumerableConstructor_ShouldContainAllElements(int count)
         {
             (TElement, TPriority)[] itemsToEnqueue = CreateItems(count).ToArray();
-            PriorityQueue<TElement, TPriority> queue = new PriorityQueue<TElement, TPriority>(itemsToEnqueue);
+            PriorityQueue<TElement, TPriority> queue = new PriorityQueue<TElement, TPriority>(itemsToEnqueue, GetPriorityComparer());
             Assert.Equal(itemsToEnqueue.Length, queue.Count);
             AssertExtensions.CollectionEqual(itemsToEnqueue, queue.UnorderedItems, EqualityComparer<(TElement, TPriority)>.Default);
         }
@@ -232,5 +232,32 @@ namespace System.Collections.Tests
         }
 
         #endregion
+
+        #region IGenericSharedAPI<T> Helper Methods
+
+        /// <summary>
+        /// <see cref="IGenericSharedAPI_Tests{T}"/> requires collections that implement IEnumerable.
+        /// Since PriorityQueue does not we use a subclass that delegates to <see cref="PriorityQueue{TElement, TPriority}.UnorderedItems"/>.
+        /// </summary>
+        protected class EnumerablePriorityQueue : PriorityQueue<TElement, TPriority>, IEnumerable<(TElement Element, TPriority Priority)>
+        {
+            public EnumerablePriorityQueue(IComparer<TPriority>? comparer) : base(comparer)
+            {
+            }
+
+            IEnumerator<(TElement Element, TPriority Priority)> IEnumerable<(TElement Element, TPriority Priority)>.GetEnumerator() => UnorderedItems.GetEnumerator();
+            IEnumerator IEnumerable.GetEnumerator() => UnorderedItems.GetEnumerator();
+        }
+
+        protected override IEnumerable<(TElement Element, TPriority Priority)> GenericIEnumerableFactory() => new EnumerablePriorityQueue(GetPriorityComparer());
+        protected override int Count(IEnumerable<(TElement Element, TPriority Priority)> enumerable) => ((EnumerablePriorityQueue)enumerable).Count;
+        protected override void Add(IEnumerable<(TElement Element, TPriority Priority)> enumerable, (TElement Element, TPriority Priority) value) => ((EnumerablePriorityQueue)enumerable).Enqueue(value.Element, value.Priority);
+        protected override void Clear(IEnumerable<(TElement Element, TPriority Priority)> enumerable) => ((EnumerablePriorityQueue)enumerable).Clear();
+        protected override bool Contains(IEnumerable<(TElement Element, TPriority Priority)> enumerable, (TElement Element, TPriority Priority) value) => ((EnumerablePriorityQueue)enumerable).Any(elem => elem.Equals(value));
+        protected override void CopyTo(IEnumerable<(TElement Element, TPriority Priority)> enumerable, (TElement Element, TPriority Priority)[] array, int index) => ((ICollection)((EnumerablePriorityQueue)enumerable).UnorderedItems).CopyTo(array, index);
+        protected override bool Remove(IEnumerable<(TElement Element, TPriority Priority)> enumerable) => ((EnumerablePriorityQueue)enumerable).TryDequeue(out _, out _);
+        protected override Type IGenericSharedAPI_CopyTo_IndexLargerThanArrayCount_ThrowType => typeof(ArgumentOutOfRangeException);
+
+        #endregion
     }
 }
index b7f964f..2697971 100644 (file)
@@ -7,34 +7,37 @@ namespace System.Collections.Tests
 {
     public class PriorityQueue_Generic_Tests_string_string : PriorityQueue_Generic_Tests<string, string>
     {
-        protected override string CreateT(int seed) => CreateString(seed);
-        protected override string CreateElement(int seed) => CreateString(seed);
-
-        protected string CreateString(int seed)
+        protected override (string, string) CreateT(int seed)
         {
-            int stringLength = seed % 10 + 5;
-            Random rand = new Random(seed);
-            byte[] bytes = new byte[stringLength];
-            rand.NextBytes(bytes);
-            return Convert.ToBase64String(bytes);
+            var random = new Random(seed);
+            return (CreateString(random), CreateString(random));
+
+            static string CreateString(Random random)
+            {
+                int stringLength = random.Next(5, 15);
+                byte[] bytes = new byte[stringLength];
+                random.NextBytes(bytes);
+                return Convert.ToBase64String(bytes);
+            }
         }
     }
 
     public class PriorityQueue_Generic_Tests_int_int : PriorityQueue_Generic_Tests<int, int>
     {
-        protected override int CreateT(int seed) => CreateInt(seed);
-        protected override int CreateElement(int seed) => CreateInt(seed);
-
-        protected int CreateInt(int seed) => new Random(seed).Next();
+        protected override (int, int) CreateT(int seed)
+        {
+            var random = new Random(seed);
+            return (random.Next(),random.Next());
+        }
     }
 
     public class PriorityQueue_Generic_Tests_string_string_CustomComparer : PriorityQueue_Generic_Tests_string_string
     {
-        protected override IComparer<string> GetIComparer() => StringComparer.InvariantCultureIgnoreCase;
+        protected override IComparer<string> GetPriorityComparer() => StringComparer.InvariantCultureIgnoreCase;
     }
 
     public class PriorityQueue_Generic_Tests_int_int_CustomComparer : PriorityQueue_Generic_Tests_int_int
     {
-        protected override IComparer<int> GetIComparer() => Comparer<int>.Create((x, y) => -x.CompareTo(y));
+        protected override IComparer<int> GetPriorityComparer() => Comparer<int>.Create((x, y) => -x.CompareTo(y));
     }
 }
index 14d54be..2aa40a0 100644 (file)
@@ -47,7 +47,7 @@ namespace System.Collections.Tests
         protected override void Clear(IEnumerable<T> enumerable) => ((Queue<T>)enumerable).Clear();
         protected override bool Contains(IEnumerable<T> enumerable, T value) => ((Queue<T>)enumerable).Contains(value);
         protected override void CopyTo(IEnumerable<T> enumerable, T[] array, int index) => ((Queue<T>)enumerable).CopyTo(array, index);
-        protected override bool Remove(IEnumerable<T> enumerable) { ((Queue<T>)enumerable).Dequeue(); return true; }
+        protected override bool Remove(IEnumerable<T> enumerable) => ((Queue<T>)enumerable).TryDequeue(out _);
         protected override bool Enumerator_Current_UndefinedOperation_Throws => true;
 
         protected override Type IGenericSharedAPI_CopyTo_IndexLargerThanArrayCount_ThrowType => typeof(ArgumentOutOfRangeException);