public static void IndexOverflow() { // If this test is run in a 32-bit process, the 3GB allocation will fail. if (Unsafe.SizeOf <IntPtr>() == sizeof(long)) { // // Although Span constrains indexes to 0..2Gb, it does not similarly constrain index * sizeof(T). // Make sure that internal offset calculcations handle the >2Gb case properly. // unsafe { if (!AllocationHelper.TryAllocNative((IntPtr)ThreeGiB, out IntPtr memBlock)) { return; // It's not implausible to believe that a 3gb allocation will fail - if so, skip this test to avoid unnecessary test flakiness. } try { ref Guid memory = ref Unsafe.AsRef <Guid>(memBlock.ToPointer()); var span = new Span <Guid>(memBlock.ToPointer(), s_guidThreeGiBLimit); int bigIndex = checked (s_guidTwoGiBLimit + 1); uint byteOffset = checked ((uint)bigIndex * (uint)sizeof(Guid)); Assert.True(byteOffset > int.MaxValue); // Make sure byteOffset actually overflows 2Gb, or this test is pointless. ref Guid expected = ref Unsafe.Add <Guid>(ref memory, bigIndex); Assert.True(Unsafe.AreSame <Guid>(ref expected, ref span[bigIndex])); Span <Guid> slice = span.Slice(bigIndex); Assert.True(Unsafe.AreSame <Guid>(ref expected, ref slice.DangerousGetPinnableReference())); slice = span.Slice(bigIndex, 1); Assert.True(Unsafe.AreSame <Guid>(ref expected, ref slice.DangerousGetPinnableReference())); }
public static void CopyToLargeSizeTest(long bufferSize) { // If this test is run in a 32-bit process, the large allocation will fail. if (Unsafe.SizeOf <IntPtr>() != sizeof(long)) { return; } int GuidCount = (int)(bufferSize / Unsafe.SizeOf <Guid>()); bool allocatedFirst = false; bool allocatedSecond = false; IntPtr memBlockFirst = IntPtr.Zero; IntPtr memBlockSecond = IntPtr.Zero; unsafe { try { allocatedFirst = AllocationHelper.TryAllocNative((IntPtr)bufferSize, out memBlockFirst); allocatedSecond = AllocationHelper.TryAllocNative((IntPtr)bufferSize, out memBlockSecond); if (allocatedFirst && allocatedSecond) { ref Guid memoryFirst = ref Unsafe.AsRef <Guid>(memBlockFirst.ToPointer()); var spanFirst = new ReadOnlySpan <Guid>(memBlockFirst.ToPointer(), GuidCount); ref Guid memorySecond = ref Unsafe.AsRef <Guid>(memBlockSecond.ToPointer()); var spanSecond = new Span <Guid>(memBlockSecond.ToPointer(), GuidCount); Guid theGuid = Guid.Parse("900DBAD9-00DB-AD90-00DB-AD900DBADBAD"); for (int count = 0; count < GuidCount; ++count) { Unsafe.Add(ref memoryFirst, count) = theGuid; } spanFirst.CopyTo(spanSecond); for (int count = 0; count < GuidCount; ++count) { Guid guidfirst = Unsafe.Add(ref memoryFirst, count); Guid guidSecond = Unsafe.Add(ref memorySecond, count); Assert.Equal(guidfirst, guidSecond); } } }
unsafe static void ClearLongerThanUintMaxValueBytes() { if (sizeof(IntPtr) == sizeof(long)) { // Arrange IntPtr bytes = (IntPtr)(((long)int.MaxValue) * sizeof(int)); int length = (int)(((long)bytes) / sizeof(int)); if (!AllocationHelper.TryAllocNative(bytes, out IntPtr memory)) { Console.WriteLine($"Span.Clear test {nameof(ClearLongerThanUintMaxValueBytes)} skipped (could not alloc memory)."); return; } try { ref int data = ref Unsafe.AsRef <int>(memory.ToPointer()); int initial = 5; for (int i = 0; i < length; i++) { Unsafe.Add(ref data, i) = initial; } Span <int> span = new Span <int>(memory.ToPointer(), length); // Act span.Clear(); // Assert using custom code for perf and to avoid allocating extra memory for (int i = 0; i < length; i++) { var actual = Unsafe.Add(ref data, i); if (actual != 0) { Assert.Equal(0, actual); } } }