Fix MultipleCallsToGetSpan test with pinning (dotnet/corefx#37373)
authorStephen Toub <stoub@microsoft.com>
Thu, 2 May 2019 18:41:02 +0000 (14:41 -0400)
committerGitHub <noreply@github.com>
Thu, 2 May 2019 18:41:02 +0000 (14:41 -0400)
The test is getting two pointers to an array and validating that they're the same pointer.  But if the array is moved by the GC between the two calls, the test fails.  The fix is to pin the array.

Commit migrated from https://github.com/dotnet/corefx/commit/1a2401cd4c3f56c022173d2ac1e0c34799d387e3

src/libraries/System.Memory/tests/ArrayBufferWriter/ArrayBufferWriterTests.T.cs

index 1675955..013307a 100644 (file)
@@ -357,25 +357,39 @@ namespace System.Buffers.Tests
         [Fact]
         public void MultipleCallsToGetSpan()
         {
+            if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+            {
+                return;
+            }
+
             var output = new ArrayBufferWriter<T>(300);
-            int previousAvailable = output.FreeCapacity;
-            Assert.True(previousAvailable >= 300);
-            Assert.True(output.Capacity >= 300);
-            Assert.Equal(previousAvailable, output.Capacity);
-            Span<T> span = output.GetSpan();
-            Assert.True(span.Length >= previousAvailable);
-            Assert.True(span.Length >= 256);
-            Span<T> newSpan = output.GetSpan();
-            Assert.Equal(span.Length, newSpan.Length);
+            Assert.True(MemoryMarshal.TryGetArray(output.GetMemory(), out ArraySegment<T> array));
+            GCHandle pinnedArray = GCHandle.Alloc(array.Array, GCHandleType.Pinned);
+            try
+            {
+                int previousAvailable = output.FreeCapacity;
+                Assert.True(previousAvailable >= 300);
+                Assert.True(output.Capacity >= 300);
+                Assert.Equal(previousAvailable, output.Capacity);
+                Span<T> span = output.GetSpan();
+                Assert.True(span.Length >= previousAvailable);
+                Assert.True(span.Length >= 256);
+                Span<T> newSpan = output.GetSpan();
+                Assert.Equal(span.Length, newSpan.Length);
 
-            unsafe
+                unsafe
+                {
+                    void* pSpan = Unsafe.AsPointer(ref MemoryMarshal.GetReference(span));
+                    void* pNewSpan = Unsafe.AsPointer(ref MemoryMarshal.GetReference(newSpan));
+                    Assert.Equal((IntPtr)pSpan, (IntPtr)pNewSpan);
+                }
+
+                Assert.Equal(span.Length, output.GetSpan().Length);
+            }
+            finally
             {
-                void* pSpan = Unsafe.AsPointer(ref MemoryMarshal.GetReference(span));
-                void* pNewSpan = Unsafe.AsPointer(ref MemoryMarshal.GetReference(newSpan));
-                Assert.Equal((IntPtr)pSpan, (IntPtr)pNewSpan);
+                pinnedArray.Free();
             }
-
-            Assert.Equal(span.Length, output.GetSpan().Length);
         }
 
         public abstract void WriteData(IBufferWriter<T> bufferWriter, int numBytes);