Port Marshal API tests from CoreCLR (dotnet/corefx#30690)
authorZeng Jiang <v-jiazen@microsoft.com>
Sat, 7 Jul 2018 00:21:05 +0000 (08:21 +0800)
committerStephen Toub <stoub@microsoft.com>
Sat, 7 Jul 2018 00:21:05 +0000 (20:21 -0400)
* Port Marshal API tests from CoreCLR

* Fix comments about Marshal API tests

* Fis comments from code review for porting Marshal API.

* Scope Marshal API tests about  Variant type for Windows only

* Scope Marshal.*UTF8* API testcases only for NetCoreApp.

* Fix Marshal\PtrToStringTests.cs compile issue in linux

* Scope Marshal API test TestFieldAlignment_Variant test for Windows only

* Change the private property to public in a Struct in OffsetOfTest.cs

* Disable test NullValueArguments_ThrowsArgumentNullException with issue dotnet/corefx#30830

* Fix failing test NonGenericOffEqualsGenericOffset() in OffsetOfTests.cs

* Disable Marshal API test GetExceptionForHR_EqualsErrorCode() with dotnet/corefx#30866

Commit migrated from https://github.com/dotnet/corefx/commit/9ebc30a73c52f78a3d9d2b79a8bb4e848f39b29b

27 files changed:
src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/ByteArrayTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/CharArrayTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/DoubleArrayTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int16ArrayTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int32ArrayTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int64ArrayTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/IntPtrArrayTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/SingleArrayTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionForHRTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectsForNativeVariantsTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStructureTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/ByteTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int16Tests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int32Tests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int64Tests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/IntPtrTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/ObjectTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs [new file with mode: 0644]
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/UnsafeAddrOfPinnedArrayElementTests.cs [new file with mode: 0644]

index bae040b..110f695 100644 (file)
@@ -14,6 +14,8 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
   <ItemGroup>
     <Compile Include="System\Runtime\CompilerServices\IUnknownConstantAttributeTests.cs" />
     <Compile Include="System\Runtime\InteropServices\AllowReversePInvokeCallsAttributeTests.cs" />
     <Compile Include="System\Runtime\InteropServices\MarshalAsAttributeTests.cs" />
     <Compile Include="System\Runtime\InteropServices\MarshalTests.cs" />
     <Compile Include="System\Runtime\InteropServices\MarshalTests.Windows.cs" Condition="'$(TargetsWindows)' == 'true'" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\Copy\ByteArrayTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\Copy\CharArrayTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\Copy\DoubleArrayTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\Copy\Int16ArrayTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\Copy\Int32ArrayTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\Copy\Int64ArrayTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\Copy\IntPtrArrayTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\Copy\SingleArrayTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\DestroyStructureTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\PtrToStructureTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\PtrToStringTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\SizeOfTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\GetExceptionForHRTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\GetNativeVariantForObjectTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\GetObjectForNativeVariantTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\GetObjectsForNativeVariantsTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\OffsetOfTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\ByteTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\Int16Tests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\Int32Tests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\Int64Tests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\IntPtrTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\ReadWrite\ObjectTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\StringMarshalingTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\StructureToPtrTests.cs" />
+    <Compile Include="System\Runtime\InteropServices\Marshal\UnsafeAddrOfPinnedArrayElementTests.cs" />
     <Compile Condition="'$(TargetGroup)' != 'uap'" Include="System\Runtime\InteropServices\PrimaryInteropAssemblyAttributeTests.cs" />
     <Compile Include="System\Runtime\InteropServices\ProgIdAttributeTests.cs" />
     <Compile Include="System\Runtime\InteropServices\RuntimeEnvironmentTests.cs" />
     <Compile Include="System\Runtime\InteropServices\TypeLibVersionAttributeTests.cs" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project>
\ No newline at end of file
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/ByteArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/ByteArrayTests.cs
new file mode 100644 (file)
index 0000000..9f8f06d
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class ByteArrayTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new byte[]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValueArguments_ThrowsArgumentNullException(byte[] TestArray)
+        {
+            byte[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(byte[] TestArray)
+        {
+            int sizeOfArray = sizeof(byte) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void CopyRoundTrip_MatchesOriginalArray(byte[] TestArray)
+        {
+            int sizeOfArray = sizeof(byte) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+                byte[] array1 = new byte[TestArray.Length];
+                Marshal.Copy(ptr, array1, 0, TestArray.Length);
+                Assert.Equal<byte>(TestArray, array1);
+
+                Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+                byte[] array2 = new byte[TestArray.Length];
+                Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+                Assert.Equal<byte>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/CharArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/CharArrayTests.cs
new file mode 100644 (file)
index 0000000..0a8c8f6
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class CharArrayTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValueArguments_ThrowsArgumentNullException(char[] TestArray)
+        {
+            char[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(char[] TestArray)
+        {
+            int sizeOfArray = sizeof(char) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void CopyRoundTrip_MatchesOriginalArray(char[] TestArray)
+        {
+            int sizeOfArray = sizeof(char) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+                char[] array1 = new char[TestArray.Length];
+                Marshal.Copy(ptr, array1, 0, TestArray.Length);
+                Assert.Equal<char>(TestArray, array1);
+
+                Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+                char[] array2 = new char[TestArray.Length];
+                Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+                Assert.Equal<char>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/DoubleArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/DoubleArrayTests.cs
new file mode 100644 (file)
index 0000000..73fd257
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class DoubleArrayTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new double[] { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValueArguments_ThrowsArgumentNullException(double[] TestArray)
+        {
+            double[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(double[] TestArray)
+        {
+            int sizeOfArray = sizeof(double) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void CopyRoundTrip_MatchesOriginalArray(double[] TestArray)
+        {
+            int sizeOfArray = sizeof(double) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+                double[] array1 = new double[TestArray.Length];
+                Marshal.Copy(ptr, array1, 0, TestArray.Length);
+                Assert.Equal<double>(TestArray, array1);
+
+                Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+                double[] array2 = new double[TestArray.Length];
+                Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+                Assert.Equal<double>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int16ArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int16ArrayTests.cs
new file mode 100644 (file)
index 0000000..aa26edb
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class Int16ArrayTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValueArguments_ThrowsArgumentNullException(short[] TestArray)
+        {
+            short[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(short[] TestArray)
+        {
+            int sizeOfArray = sizeof(short) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void CopyRoundTrip_MatchesOriginalArray(short[] TestArray)
+        {
+            int sizeOfArray = sizeof(short) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+                short[] array1 = new short[TestArray.Length];
+                Marshal.Copy(ptr, array1, 0, TestArray.Length);
+                Assert.Equal<short>(TestArray, array1);
+
+                Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+                short[] array2 = new short[TestArray.Length];
+                Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+                Assert.Equal<short>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int32ArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int32ArrayTests.cs
new file mode 100644 (file)
index 0000000..19c0693
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class Int32ArrayTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValueArguments_ThrowsArgumentNullException(int[] TestArray)
+        {
+            int[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(int[] TestArray)
+        {
+            int sizeOfArray = sizeof(int) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void CopyRoundTrip_MatchesOriginalArray(int[] TestArray)
+        {
+            int sizeOfArray = sizeof(int) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+                int[] array1 = new int[TestArray.Length];
+                Marshal.Copy(ptr, array1, 0, TestArray.Length);
+                Assert.Equal<int>(TestArray, array1);
+
+                Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+                int[] array2 = new int[TestArray.Length];
+                Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+                Assert.Equal<int>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int64ArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int64ArrayTests.cs
new file mode 100644 (file)
index 0000000..cb14a92
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class Int64ArrayTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValueArguments_ThrowsArgumentNullException(long[] TestArray)
+        {
+            long[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(long[] TestArray)
+        {
+            int sizeOfArray = sizeof(long) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void CopyRoundTrip_MatchesOriginalArray(long[] TestArray)
+        {
+            int sizeOfArray = sizeof(long) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+                long[] array1 = new long[TestArray.Length];
+                Marshal.Copy(ptr, array1, 0, TestArray.Length);
+                Assert.Equal<long>(TestArray, array1);
+
+                Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+                long[] array2 = new long[TestArray.Length];
+                Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+                Assert.Equal<long>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/IntPtrArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/IntPtrArrayTests.cs
new file mode 100644 (file)
index 0000000..2cf6fdc
--- /dev/null
@@ -0,0 +1,71 @@
+// 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.Linq;
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class IntPtrArrayTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { Enumerable.Range(0, 10).Select(i => new IntPtr(i)).ToArray() }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValueArguments_ThrowsArgumentNullException(IntPtr[] TestArray)
+        {
+            IntPtr[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(IntPtr[] TestArray)
+        {
+            int sizeOfArray = IntPtr.Size * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void CopyRoundTrip_MatchesOriginalArray(IntPtr[] TestArray)
+        {
+            int sizeOfArray = IntPtr.Size * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+                IntPtr[] array1 = new IntPtr[TestArray.Length];
+                Marshal.Copy(ptr, array1, 0, TestArray.Length);
+                Assert.Equal<IntPtr>(TestArray, array1);
+
+                Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+                IntPtr[] array2 = new IntPtr[TestArray.Length];
+                Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+                Assert.Equal<IntPtr>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/SingleArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/SingleArrayTests.cs
new file mode 100644 (file)
index 0000000..8a72014
--- /dev/null
@@ -0,0 +1,70 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class SingleArrayTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new float[] { 0.0F, 1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F, 7.0F, 8.0F, 9.0F } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValueArguments_ThrowsArgumentNullException(float[] TestArray)
+        {
+            float[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(TestArray, 0, IntPtr.Zero, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(array, 0, new IntPtr(1), 0));
+            AssertExtensions.Throws<ArgumentNullException>("destination", () => Marshal.Copy(new IntPtr(1), array, 0, 0));
+            AssertExtensions.Throws<ArgumentNullException>("source", () => Marshal.Copy(IntPtr.Zero, TestArray, 0, 0));
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void OutOfRangeArguments_ThrowsArgumentOutOfRangeException(float[] TestArray)
+        {
+            int sizeOfArray = sizeof(float) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 0, ptr, TestArray.Length + 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, TestArray.Length + 1, ptr, 1));
+                Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.Copy(TestArray, 2, ptr, TestArray.Length));
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void CopyRoundTrip_MatchesOriginalArray(float[] TestArray)
+        {
+            int sizeOfArray = sizeof(float) * TestArray.Length;
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.Copy(TestArray, 0, ptr, TestArray.Length);
+
+                float[] array1 = new float[TestArray.Length];
+                Marshal.Copy(ptr, array1, 0, TestArray.Length);
+                Assert.Equal<float>(TestArray, array1);
+
+                Marshal.Copy(TestArray, 2, ptr, TestArray.Length - 4);
+                float[] array2 = new float[TestArray.Length];
+                Marshal.Copy(ptr, array2, 2, TestArray.Length - 4);
+                Assert.Equal<float>(TestArray.AsSpan(2, TestArray.Length - 4).ToArray(), array2.AsSpan(2, TestArray.Length - 4).ToArray());
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs
new file mode 100644 (file)
index 0000000..9a4c7d9
--- /dev/null
@@ -0,0 +1,60 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class DestroyStructureTests
+    {
+        [StructLayout(LayoutKind.Sequential)]
+        public struct SomeTestStruct
+        {
+            public int i;
+            public String s;
+        }
+
+        [StructLayout(LayoutKind.Auto)]
+        public struct SomeTestStruct_Auto
+        {
+            public int i;
+        }
+
+        [Fact]
+        public void DestroyStructure_Negative()
+        {
+            IntPtr ip;
+
+            ip = IntPtr.Zero;
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.DestroyStructure<SomeTestStruct>(ip));
+
+            ip = new IntPtr(123);
+            AssertExtensions.Throws<ArgumentNullException>("structureType", () => Marshal.DestroyStructure(ip, null));
+
+            SomeTestStruct_Auto someTs_Auto = new SomeTestStruct_Auto();
+            Assert.Throws<ArgumentException>(() => Marshal.DestroyStructure(ip, someTs_Auto.GetType()));
+        }
+
+        [Fact]
+        public void DestroyStructure_Positive()
+        {
+            SomeTestStruct someTestStruct = new SomeTestStruct();
+            IntPtr ip = Marshal.AllocHGlobal(Marshal.SizeOf(someTestStruct));
+            try
+            {
+                someTestStruct.s = null;
+                //Generic
+                Marshal.StructureToPtr(someTestStruct, ip, false);
+                Marshal.DestroyStructure<SomeTestStruct>(ip);
+                //None-Generic
+                Marshal.StructureToPtr(someTestStruct, ip, false);
+                Marshal.DestroyStructure(ip, typeof(SomeTestStruct));
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(ip);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionForHRTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionForHRTests.cs
new file mode 100644 (file)
index 0000000..283fbd3
--- /dev/null
@@ -0,0 +1,21 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class GetExceptionForHRTests
+    {
+        [Theory]
+        [InlineData(unchecked((int)0x80020006))]
+        [InlineData(unchecked((int)0x80020101))]
+        [ActiveIssue(30866)]
+        public void GetExceptionForHR_EqualsErrorCode(int err)
+        {
+            Exception ex = Marshal.GetExceptionForHR(err);
+            Assert.Equal(err, ex.HResult);
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs
new file mode 100644 (file)
index 0000000..fbed81b
--- /dev/null
@@ -0,0 +1,147 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class GetNativeVariantForObjectTests
+    {
+        internal struct Variant
+        {
+#pragma warning disable 0649
+            public ushort vt;
+            public ushort wReserved1;
+            public ushort wReserved2;
+            public ushort wReserved3;
+            public IntPtr bstrVal;
+            public IntPtr pRecInfo;
+#pragma warning restore 0649
+        }
+
+#pragma warning disable 618
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void NullParameter()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("pDstNativeVariant", () => Marshal.GetNativeVariantForObject(new object(), IntPtr.Zero));
+            AssertExtensions.Throws<ArgumentNullException>("pDstNativeVariant", () => Marshal.GetNativeVariantForObject<int>(1, IntPtr.Zero));
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void EmptyObject()
+        {
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject(null, pNative);
+                object o = Marshal.GetObjectForNativeVariant(pNative);
+                Assert.Null(o);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void PrimitiveType()
+        {
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<ushort>(99, pNative);
+                ushort actual = Marshal.GetObjectForNativeVariant<ushort>(pNative);
+                Assert.Equal(99, actual);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void CharType()
+        {
+            // GetNativeVariantForObject supports char, but internally recognizes it the same as ushort
+            // because the native variant type uses mscorlib type VarEnum to store what type it contains.
+            // To get back the original char, use GetObjectForNativeVariant<ushort> and cast to char.
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<char>('a', pNative);
+                ushort actual = Marshal.GetObjectForNativeVariant<ushort>(pNative);
+                char actualChar = (char)actual;
+                Assert.Equal('a', actualChar);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void CharTypeNegative()
+        {
+            // While GetNativeVariantForObject supports taking chars, GetObjectForNativeVariant will
+            // never return a char. The internal type is ushort, as mentioned above. This behavior
+            // is the same on ProjectN and Desktop CLR.
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<char>('a', pNative);
+                Assert.Throws<InvalidCastException>(() => Marshal.GetObjectForNativeVariant<char>(pNative));
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void StringType()
+        {
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<string>("99", pNative);
+                string actual = Marshal.GetObjectForNativeVariant<string>(pNative);
+                Assert.Equal("99", actual);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void DoubleType()
+        {
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<double>(3.14, pNative);
+                double actual = Marshal.GetObjectForNativeVariant<double>(pNative);
+                Assert.Equal(3.14, actual);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+}
+#pragma warning restore 618
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.cs
new file mode 100644 (file)
index 0000000..9a73c1c
--- /dev/null
@@ -0,0 +1,175 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class GetObjectForNativeVariantTests
+    {
+        [StructLayout(LayoutKind.Sequential)]
+        public struct Record
+        {
+            private IntPtr _record;
+            private IntPtr _recordInfo;
+        }
+
+        [StructLayout(LayoutKind.Explicit)]
+        public struct UnionTypes
+        {
+            [FieldOffset(0)] internal SByte _i1;
+            [FieldOffset(0)] internal Int16 _i2;
+            [FieldOffset(0)] internal Int32 _i4;
+            [FieldOffset(0)] internal Int64 _i8;
+            [FieldOffset(0)] internal Byte _ui1;
+            [FieldOffset(0)] internal UInt16 _ui2;
+            [FieldOffset(0)] internal UInt32 _ui4;
+            [FieldOffset(0)] internal UInt64 _ui8;
+            [FieldOffset(0)] internal Int32 _int;
+            [FieldOffset(0)] internal UInt32 _uint;
+            [FieldOffset(0)] internal Single _r4;
+            [FieldOffset(0)] internal Double _r8;
+            [FieldOffset(0)] internal Int64 _cy;
+            [FieldOffset(0)] internal double _date;
+            [FieldOffset(0)] internal IntPtr _bstr;
+            [FieldOffset(0)] internal IntPtr _unknown;
+            [FieldOffset(0)] internal IntPtr _dispatch;
+            [FieldOffset(0)] internal IntPtr _pvarVal;
+            [FieldOffset(0)] internal IntPtr _byref;
+            [FieldOffset(0)] internal Record _record;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct TypeUnion
+        {
+            public ushort vt;
+            public ushort wReserved1;
+            public ushort wReserved2;
+            public ushort wReserved3;
+            public UnionTypes _unionTypes;
+        }
+
+        [StructLayout(LayoutKind.Explicit)]
+        internal struct Variant
+        {
+            [FieldOffset(0)] public TypeUnion m_Variant;
+            [FieldOffset(0)] public decimal m_decimal;
+        }
+
+#pragma warning disable 618
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void NullParameter()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("pSrcNativeVariant", () => Marshal.GetObjectForNativeVariant(IntPtr.Zero));
+            AssertExtensions.Throws<ArgumentNullException>("pSrcNativeVariant", () => Marshal.GetObjectForNativeVariant<int>(IntPtr.Zero));
+        }
+
+        [DllImport(@"oleaut32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
+        static extern Int32 VariantClear(IntPtr pvarg);
+
+        private static void DeleteVariant(IntPtr pVariant)
+        {
+            VariantClear(pVariant);
+            Marshal.FreeHGlobal(pVariant);
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void DecimalType()
+        {
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject(3.14m, pNative);
+                decimal d = Marshal.GetObjectForNativeVariant<decimal>(pNative);
+                Assert.Equal(3.14m, d);
+            }
+            finally
+            {
+                DeleteVariant(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void PrimitiveType()
+        {
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<ushort>(99, pNative);
+                ushort actual = Marshal.GetObjectForNativeVariant<ushort>(pNative);
+                Assert.Equal(99, actual);
+            }
+            finally
+            {
+                DeleteVariant(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void StringType()
+        {
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<string>("99", pNative);
+                string actual = Marshal.GetObjectForNativeVariant<string>(pNative);
+                Assert.Equal("99", actual);
+            }
+            finally
+            {
+                DeleteVariant(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void DoubleType()
+        {
+            Variant v = new Variant();
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<double>(3.14, pNative);
+                double actual = Marshal.GetObjectForNativeVariant<double>(pNative);
+                Assert.Equal(3.14, actual);
+            }
+            finally
+            {
+                DeleteVariant(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void IUnknownType()
+        {
+            Variant v = new Variant();
+            object obj = new object();
+
+            // Technically we don't need this - but this is necessary for forcing
+            // COM initialization
+            IntPtr pUnk = Marshal.GetIUnknownForObject(obj);
+            IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<object>(obj, pNative);
+                object actual = Marshal.GetObjectForNativeVariant<object>(pNative);
+                Assert.Equal(obj, actual);
+            }
+            finally
+            {
+                Marshal.Release(pUnk);
+                DeleteVariant(pNative);
+            }
+        }
+#pragma warning restore 618
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectsForNativeVariantsTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectsForNativeVariantsTests.cs
new file mode 100644 (file)
index 0000000..f0dc759
--- /dev/null
@@ -0,0 +1,291 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class GetObjectsForNativeVariantsTests
+    {
+        [StructLayout(LayoutKind.Sequential)]
+        public struct Record
+        {
+            private IntPtr _record;
+            private IntPtr _recordInfo;
+        }
+
+        [StructLayout(LayoutKind.Explicit)]
+        public struct UnionTypes
+        {
+            [FieldOffset(0)] internal SByte _i1;
+            [FieldOffset(0)] internal Int16 _i2;
+            [FieldOffset(0)] internal Int32 _i4;
+            [FieldOffset(0)] internal Int64 _i8;
+            [FieldOffset(0)] internal Byte _ui1;
+            [FieldOffset(0)] internal UInt16 _ui2;
+            [FieldOffset(0)] internal UInt32 _ui4;
+            [FieldOffset(0)] internal UInt64 _ui8;
+            [FieldOffset(0)] internal Int32 _int;
+            [FieldOffset(0)] internal UInt32 _uint;
+            [FieldOffset(0)] internal Single _r4;
+            [FieldOffset(0)] internal Double _r8;
+            [FieldOffset(0)] internal Int64 _cy;
+            [FieldOffset(0)] internal double _date;
+            [FieldOffset(0)] internal IntPtr _bstr;
+            [FieldOffset(0)] internal IntPtr _unknown;
+            [FieldOffset(0)] internal IntPtr _dispatch;
+            [FieldOffset(0)] internal IntPtr _pvarVal;
+            [FieldOffset(0)] internal IntPtr _byref;
+            [FieldOffset(0)] internal Record _record;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct TypeUnion
+        {
+            public ushort vt;
+            public ushort wReserved1;
+            public ushort wReserved2;
+            public ushort wReserved3;
+            public UnionTypes _unionTypes;
+        }
+
+        [StructLayout(LayoutKind.Explicit)]
+        internal struct Variant
+        {
+            [FieldOffset(0)] public TypeUnion m_Variant;
+            [FieldOffset(0)] public decimal m_decimal;
+        }
+#pragma warning disable 618
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public static void NullParameter()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("aSrcNativeVariant", () => Marshal.GetObjectsForNativeVariants(IntPtr.Zero, 10));
+            Assert.Throws<ArgumentOutOfRangeException>("cVars", () => Marshal.GetObjectsForNativeVariants<int>(new IntPtr(100), -1));
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void SByteType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<sbyte>(99, pNative);
+                Marshal.GetNativeVariantForObject<sbyte>(100, pNative + Marshal.SizeOf(v));
+
+                sbyte[] actual = Marshal.GetObjectsForNativeVariants<sbyte>(pNative, 2);
+                Assert.Equal(99, actual[0]);
+                Assert.Equal(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void ByteType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<byte>(99, pNative);
+                Marshal.GetNativeVariantForObject<byte>(100, pNative + Marshal.SizeOf(v));
+
+                byte[] actual = Marshal.GetObjectsForNativeVariants<byte>(pNative, 2);
+                Assert.Equal(99, actual[0]);
+                Assert.Equal(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void DoubleType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<double>(99, pNative);
+                Marshal.GetNativeVariantForObject<double>(100, pNative + Marshal.SizeOf(v));
+
+                double[] actual = Marshal.GetObjectsForNativeVariants<double>(pNative, 2);
+                Assert.Equal(99, actual[0]);
+                Assert.Equal(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void ShortType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<short>(99, pNative);
+                Marshal.GetNativeVariantForObject<short>(100, pNative + Marshal.SizeOf(v));
+
+                short[] actual = Marshal.GetObjectsForNativeVariants<short>(pNative, 2);
+                Assert.Equal(99, actual[0]);
+                Assert.Equal(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void UshortType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<ushort>(99, pNative);
+                Marshal.GetNativeVariantForObject<ushort>(100, pNative + Marshal.SizeOf(v));
+
+                ushort[] actual = Marshal.GetObjectsForNativeVariants<ushort>(pNative, 2);
+                Assert.Equal(99, actual[0]);
+                Assert.Equal(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void IntType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<int>(99, pNative);
+                Marshal.GetNativeVariantForObject<int>(100, pNative + Marshal.SizeOf(v));
+
+                int[] actual = Marshal.GetObjectsForNativeVariants<int>(pNative, 2);
+                Assert.Equal(99, actual[0]);
+                Assert.Equal(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void UIntType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<uint>(99, pNative);
+                Marshal.GetNativeVariantForObject<uint>(100, pNative + Marshal.SizeOf(v));
+
+                uint[] actual = Marshal.GetObjectsForNativeVariants<uint>(pNative, 2);
+                Assert.Equal<uint>(99, actual[0]);
+                Assert.Equal<uint>(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void LongType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<long>(99, pNative);
+                Marshal.GetNativeVariantForObject<long>(100, pNative + Marshal.SizeOf(v));
+
+                long[] actual = Marshal.GetObjectsForNativeVariants<long>(pNative, 2);
+                Assert.Equal(99, actual[0]);
+                Assert.Equal(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void ULongType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<ulong>(99, pNative);
+                Marshal.GetNativeVariantForObject<ulong>(100, pNative + Marshal.SizeOf(v));
+
+                ulong[] actual = Marshal.GetObjectsForNativeVariants<ulong>(pNative, 2);
+                Assert.Equal<ulong>(99, actual[0]);
+                Assert.Equal<ulong>(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void FloatType()
+        {
+            Variant v = new Variant();
+
+            IntPtr pNative = Marshal.AllocHGlobal(2 * Marshal.SizeOf(v));
+            try
+            {
+                Marshal.GetNativeVariantForObject<float>(99, pNative);
+                Marshal.GetNativeVariantForObject<float>(100, pNative + Marshal.SizeOf(v));
+
+                float[] actual = Marshal.GetObjectsForNativeVariants<float>(pNative, 2);
+                Assert.Equal(99, actual[0]);
+                Assert.Equal(100, actual[1]);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(pNative);
+            }
+        }
+
+#pragma warning restore 618
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs
new file mode 100644 (file)
index 0000000..ae5e2a8
--- /dev/null
@@ -0,0 +1,366 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class OffsetOfTests
+    {
+        [Fact]
+        public static void NullParameter()
+        {
+            Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(null, null));
+            Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(new object().GetType(), null));
+            Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(null, "abcd"));
+        }
+
+        [Fact]
+        public void NonExistField()
+        {
+            Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(NonExistField), "NonExistField"));
+        }
+
+        [Fact]
+        public void NoLayoutClass()
+        {
+            Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(NoLayoutPoint), "x"));
+        }
+
+        [Fact]
+        public void StructField()
+        {
+            Assert.Equal(new IntPtr(4), Marshal.OffsetOf(typeof(SomeStruct), "var"));
+        }
+
+        [Fact]
+        public void ClassExplicitField()
+        {
+            Assert.Equal(new IntPtr(0), Marshal.OffsetOf(typeof(MySystemTime), "wYear"));
+            Assert.Equal(new IntPtr(8), Marshal.OffsetOf(typeof(MySystemTime), "wHour"));
+            Assert.Equal(new IntPtr(14), Marshal.OffsetOf(typeof(MySystemTime), "wMilliseconds"));
+        }
+
+        [Fact]
+        public void ClassSequentialField()
+        {
+            Assert.Equal(new IntPtr(0), Marshal.OffsetOf(typeof(MyPoint), "x"));
+            Assert.Equal(new IntPtr(4), Marshal.OffsetOf(typeof(MyPoint), "y"));
+        }
+
+        [Fact]
+        public void TestExplicitLayout()
+        {
+            Type t = typeof(ExplicitLayoutTest);
+            Assert.Equal(56, Marshal.SizeOf(t));
+            Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "m_short1"));
+            Assert.Equal(new IntPtr(2), Marshal.OffsetOf(t, "m_short2"));
+
+            Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, "union1_byte1"));
+            Assert.Equal(new IntPtr(5), Marshal.OffsetOf(t, "union1_byte2"));
+            Assert.Equal(new IntPtr(6), Marshal.OffsetOf(t, "union1_short1"));
+            Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "union1_int1"));
+            Assert.Equal(new IntPtr(12), Marshal.OffsetOf(t, "union1_int2"));
+            Assert.Equal(new IntPtr(16), Marshal.OffsetOf(t, "union1_double1"));
+
+            Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, "union2_ushort1"));
+            Assert.Equal(new IntPtr(6), Marshal.OffsetOf(t, "union2_ushort2"));
+            Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "union3_int1"));
+            Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "union3_decimal1"));
+
+            Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, "m_ushort1"));
+            Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "m_decimal1"));
+            Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, "m_char1"));
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void TestFieldAlignment_Windows()
+        {
+            Type t = typeof(FieldAlignmentTest);
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+            {
+                Assert.Equal(80, Marshal.SizeOf(t));
+            }
+            else
+            {
+                Assert.Equal(72, Marshal.SizeOf(t));
+            }
+
+            Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "m_byte1"));
+            Assert.Equal(new IntPtr(2), Marshal.OffsetOf(t, "m_short1"));
+            Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, "m_short2"));
+            Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "m_int1"));
+            Assert.Equal(new IntPtr(12), Marshal.OffsetOf(t, "m_byte2"));
+            Assert.Equal(new IntPtr(16), Marshal.OffsetOf(t, "m_int2"));
+
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+            {
+                Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, "m_double1"));
+                Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "m_char1"));
+                Assert.Equal(new IntPtr(33), Marshal.OffsetOf(t, "m_char2"));
+                Assert.Equal(new IntPtr(34), Marshal.OffsetOf(t, "m_char3"));
+                Assert.Equal(new IntPtr(40), Marshal.OffsetOf(t, "m_double2"));
+                Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, "m_byte3"));
+                Assert.Equal(new IntPtr(49), Marshal.OffsetOf(t, "m_byte4"));
+                Assert.Equal(new IntPtr(56), Marshal.OffsetOf(t, "m_decimal1"));
+                Assert.Equal(new IntPtr(72), Marshal.OffsetOf(t, "m_char4"));
+            }
+            else
+            {
+                Assert.Equal(new IntPtr(20), Marshal.OffsetOf(t, "m_double1"));
+                Assert.Equal(new IntPtr(28), Marshal.OffsetOf(t, "m_char1"));
+                Assert.Equal(new IntPtr(29), Marshal.OffsetOf(t, "m_char2"));
+                Assert.Equal(new IntPtr(30), Marshal.OffsetOf(t, "m_char3"));
+                Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "m_double2"));
+                Assert.Equal(new IntPtr(40), Marshal.OffsetOf(t, "m_byte3"));
+                Assert.Equal(new IntPtr(41), Marshal.OffsetOf(t, "m_byte4"));
+                Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, "m_decimal1"));
+                Assert.Equal(new IntPtr(64), Marshal.OffsetOf(t, "m_char4"));
+            }
+        }
+
+        [Fact]
+        public void TestFieldAlignment_Decimal()
+        {
+            Type t = typeof(FieldAlignmentTest_Decimal);
+
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+            {
+                Assert.Equal(96, Marshal.SizeOf(t));
+            }
+            else
+            {
+                Assert.Equal(88, Marshal.SizeOf(t));
+            }
+
+            Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "b"));
+            Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "p"));
+
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
+            {
+                Assert.Equal(new IntPtr(88), Marshal.OffsetOf(t, "s"));
+            }
+            else
+            {
+                Assert.Equal(new IntPtr(80), Marshal.OffsetOf(t, "s"));
+            }
+        }
+
+        [Fact]
+        public void TestFieldAlignment_Guid()
+        {
+            Type t = typeof(FieldAlignmentTest_Guid);
+            Assert.Equal(24, Marshal.SizeOf(t));
+
+            Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "b"));
+            Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, "g"));
+            Assert.Equal(new IntPtr(20), Marshal.OffsetOf(t, "s"));
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void TestFieldAlignment_Variant()
+        {
+            Type t = typeof(FieldAlignmentTest_Variant);
+
+            Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "b"));
+            Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "v"));
+
+            if (IntPtr.Size == 4)
+            {
+                Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, "s"));
+                Assert.Equal(32, Marshal.SizeOf(t));
+            }
+            else if (IntPtr.Size == 8)
+            {
+                Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "s"));
+                Assert.Equal(40, Marshal.SizeOf(t));
+            }
+            else
+            {
+                Assert.True(false, string.Format("Unexpected value '{0}' for IntPtr.Size", IntPtr.Size));
+            }
+        }
+
+        [Fact]
+        public void NonGenericOffEqualsGenericOffset()
+        {
+            IntPtr nonGenericOffsetCall = Marshal.OffsetOf(typeof(SomeStruct), "var");
+            IntPtr genericOffsetCall = Marshal.OffsetOf<SomeStruct>("var");
+            Assert.Equal(nonGenericOffsetCall, genericOffsetCall);
+
+            Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(StructWithFxdLPSTRSAFld), "Arr"));
+        }
+    }
+#pragma warning disable 169, 649, 618
+    [StructLayout(LayoutKind.Sequential)]
+    public struct StructWithFxdLPSTRSAFld
+    {
+        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 0)]
+        public String[] Arr;
+    }
+
+    public struct SomeStruct
+    {
+        public bool p;
+        public int var;
+    }
+
+    [StructLayout(LayoutKind.Explicit)]
+    public class MySystemTime
+    {
+        [FieldOffset(0)]
+        public ushort wYear;
+        [FieldOffset(2)]
+        public ushort wMonth;
+        [FieldOffset(4)]
+        public ushort wDayOfWeek;
+        [FieldOffset(6)]
+        public ushort wDay;
+        [FieldOffset(8)]
+        public ushort wHour;
+        [FieldOffset(10)]
+        public ushort wMinute;
+        [FieldOffset(12)]
+        public ushort wSecond;
+        [FieldOffset(14)]
+        public ushort wMilliseconds;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public class MyPoint
+    {
+        public int x;
+        public int y;
+    }
+
+    public class NoLayoutPoint
+    {
+        public int x;
+        public int y;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public class NonExistField
+    {
+
+    }
+
+    [StructLayout(LayoutKind.Explicit)]
+    internal struct ExplicitLayoutTest
+    {
+        [FieldOffset(0)]
+        public short m_short1; // 2 bytes
+        [FieldOffset(2)]
+        public short m_short2; // 2 bytes
+
+        [FieldOffset(4)]
+        public byte union1_byte1; // 1 byte
+        [FieldOffset(5)]
+        public byte union1_byte2; // 1 byte
+        [FieldOffset(6)]
+        public short union1_short1; // 2 bytes
+        [FieldOffset(8)]
+        public Int32 union1_int1; // 4 bytes
+        [FieldOffset(12)]
+        public Int32 union1_int2; // 4 bytes
+        [FieldOffset(16)]
+        public double union1_double1; // 8 bytes
+
+        [FieldOffset(4)]
+        public ushort union2_ushort1; // 2 bytes
+        [FieldOffset(6)]
+        public ushort union2_ushort2; // 2 bytes
+        [FieldOffset(8)]
+        public Int32 union3_int1; // 4 bytes
+        [FieldOffset(8)]
+        public decimal union3_decimal1; // 16 bytes
+
+        [FieldOffset(24)]
+        public ushort m_ushort1; // 2 bytes
+                                 // 6 bytes of padding
+
+        [FieldOffset(32)]
+        public decimal m_decimal1; // 16 bytes
+
+        [FieldOffset(48)]
+        public char m_char1; // 1 byte
+                             // 7 bytes of padding
+    }
+
+    internal struct FieldAlignmentTest
+    {
+        public byte m_byte1; // 1 byte
+                             // 1 byte of padding
+
+        public short m_short1; // 2 bytes
+        public short m_short2; // 2 bytes
+                               // 2 bytes of padding
+
+        public Int32 m_int1; // 4 bytes
+        public byte m_byte2; // 1 byte
+                             // 3 bytes of padding
+
+        public Int32 m_int2; // 4 bytes
+                             // 4 bytes of padding (0 bytes on x86/Unix according System V ABI as double 4-byte aligned)
+
+        public double m_double1; // 8 bytes
+        public char m_char1; // 1 byte
+        public char m_char2; // 1 byte
+        public char m_char3; // 1 byte
+                             // 5 bytes of padding (1 byte on x86/Unix according System V ABI as double 4-byte aligned)
+
+        public double m_double2; // 8 bytes
+        public byte m_byte3; // 1 byte
+        public byte m_byte4; // 1 byte
+                             // 6 bytes of padding
+
+        public decimal m_decimal1; // 16 bytes
+        public char m_char4; // 1 byte
+                             // 7 bytes of padding
+    }
+    struct FieldAlignmentTest_Decimal
+    {
+        public byte b; // 1 byte
+                       // 7 bytes of padding
+
+        // The largest field in below struct is decimal (16 bytes wide).
+        // However, alignment requirement for the below struct should be only  8 bytes (not 16).
+        // This is because unlike fields of other types well known to mcg (like long, char etc.)
+        // which need to be aligned according to their byte size, decimal is really a struct
+        // with 8 byte alignment requirement.
+        public FieldAlignmentTest p; // 80 bytes (72 bytes on x86/Unix)
+
+        public short s; // 2 bytes
+                        // 6 bytes of padding
+    }
+
+    struct FieldAlignmentTest_Guid
+    {
+        public byte b; // 1 byte
+                       // 3 bytes of padding
+
+        // Guid is really a struct with 4 byte alignment requirement (which is less than its byte size of 16 bytes).
+        public Guid g; // 16 bytes
+
+        public short s; // 2 bytes
+                        // 2 bytes of padding
+    }
+
+    struct FieldAlignmentTest_Variant
+    {
+        public byte b; // 1 byte
+                       // 7 bytes of padding
+
+        // Using [MarshalAs(UnmanagedType.Struct)] means that the Variant type will be used for field 'v' on native side.
+        // Variant is really a struct with 8 byte alignment requirement (which is less than its byte size of 24 / 16 bytes).
+        [MarshalAs(UnmanagedType.Struct)]
+        public object v; // 16 bytes on 32-bit, 24 bytes on 64-bit
+
+        public short s; // 2 bytes
+                        // 6 bytes of padding
+    };
+#pragma warning restore 169, 649, 618
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringTests.cs
new file mode 100644 (file)
index 0000000..24b1282
--- /dev/null
@@ -0,0 +1,47 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class PtrToStringTests
+    {
+        [Fact]
+        public void PtrToStringAnsi()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStringAnsi(IntPtr.Zero, 123));
+            Assert.Throws<ArgumentException>(() => Marshal.PtrToStringAnsi(new IntPtr(123), -77));
+        }
+
+        [Fact]
+        public void PtrToStringUni()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStringUni(IntPtr.Zero, 123));
+            Assert.Throws<ArgumentException>(() => Marshal.PtrToStringUni(new IntPtr(123), -77));
+        }
+
+        [Fact]
+        public void PtrToStringAuto()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStringAuto(IntPtr.Zero, 123));
+            Assert.Throws<ArgumentException>(() => Marshal.PtrToStringAuto(new IntPtr(123), -77));
+        }
+
+        [Fact]
+        public void PtrToStringBSTR()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStringBSTR(IntPtr.Zero));
+        }
+
+#if netcoreapp
+        [Fact]
+        public void PtrToStringUTF8()
+        {
+            Assert.Null(Marshal.PtrToStringUTF8(IntPtr.Zero, 123));
+            Assert.Throws<ArgumentOutOfRangeException>(() => Marshal.PtrToStringUTF8(new IntPtr(123), -77));
+        }
+#endif
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStructureTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStructureTests.cs
new file mode 100644 (file)
index 0000000..512acda
--- /dev/null
@@ -0,0 +1,34 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class PtrToStructureTests
+    {
+        [StructLayout(LayoutKind.Sequential)]
+        public struct SomeTestStruct
+        {
+            public int i;
+            public String s;
+        }
+
+        [Fact]
+        public void PtrToStructureTest()
+        {
+            IntPtr ip;
+            SomeTestStruct someTestStruct = new SomeTestStruct();
+            
+            ip = IntPtr.Zero;
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStructure(ip, someTestStruct));
+
+            ip = new IntPtr(123);
+            AssertExtensions.Throws<ArgumentNullException>("structureType", () => Marshal.PtrToStructure(ip, null));
+
+            ip = new IntPtr(123);
+            Assert.Throws<ArgumentException>(() => Marshal.PtrToStructure<SomeTestStruct>(ip, someTestStruct));
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/ByteTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/ByteTests.cs
new file mode 100644 (file)
index 0000000..593045b
--- /dev/null
@@ -0,0 +1,66 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class ByteTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, byte.MaxValue } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValue_ThrowsException(byte[] TestValues)
+        {
+            Exception e;
+
+            e = Record.Exception(() => Marshal.ReadByte(IntPtr.Zero));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.ReadByte(IntPtr.Zero, 2));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteByte(IntPtr.Zero, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteByte(IntPtr.Zero, 2, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void ReadWriteRoundTrip(byte[] TestValues)
+        {
+            int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.WriteByte(ptr, TestValues[0]);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    Marshal.WriteByte(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+                }
+
+                byte value = Marshal.ReadByte(ptr);
+                Assert.Equal(TestValues[0], value);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    value = Marshal.ReadByte(ptr, i * Marshal.SizeOf(TestValues[0]));
+                    Assert.Equal(TestValues[i], value);
+                }
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int16Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int16Tests.cs
new file mode 100644 (file)
index 0000000..bcbbc5e
--- /dev/null
@@ -0,0 +1,66 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class Int16Tests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, short.MaxValue } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValue_ThrowsException(short[] TestValues)
+        {
+            Exception e;
+
+            e = Record.Exception(() => Marshal.ReadInt16(IntPtr.Zero));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.ReadInt16(IntPtr.Zero, 2));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteInt16(IntPtr.Zero, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteInt16(IntPtr.Zero, 2, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void ReadWriteRoundTrip(short[] TestValues)
+        {
+            int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.WriteInt16(ptr, TestValues[0]);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    Marshal.WriteInt16(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+                }
+
+                short value = Marshal.ReadInt16(ptr);
+                Assert.Equal(TestValues[0], value);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    value = Marshal.ReadInt16(ptr, i * Marshal.SizeOf(TestValues[0]));
+                    Assert.Equal(TestValues[i], value);
+                }
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int32Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int32Tests.cs
new file mode 100644 (file)
index 0000000..1459f3b
--- /dev/null
@@ -0,0 +1,66 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class Int32Tests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, int.MaxValue } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValue_ThrowsException(int[] TestValues)
+        {
+            Exception e;
+
+            e = Record.Exception(() => Marshal.ReadInt32(IntPtr.Zero));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.ReadInt32(IntPtr.Zero, 2));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteInt32(IntPtr.Zero, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteInt32(IntPtr.Zero, 2, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void ReadWriteRoundTrip(int[] TestValues)
+        {
+            int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.WriteInt32(ptr, TestValues[0]);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    Marshal.WriteInt32(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+                }
+
+                int value = Marshal.ReadInt32(ptr);
+                Assert.Equal(TestValues[0], value);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    value = Marshal.ReadInt32(ptr, i * Marshal.SizeOf(TestValues[0]));
+                    Assert.Equal(TestValues[i], value);
+                }
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int64Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int64Tests.cs
new file mode 100644 (file)
index 0000000..e0d72f9
--- /dev/null
@@ -0,0 +1,66 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class Int64Tests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, long.MaxValue } }
+        };
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValue_ThrowsException(long[] TestValues)
+        {
+            Exception e;
+
+            e = Record.Exception(() => Marshal.ReadInt64(IntPtr.Zero));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.ReadInt64(IntPtr.Zero, 2));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteInt64(IntPtr.Zero, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteInt64(IntPtr.Zero, 2, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void ReadWriteRoundTrip(long[] TestValues)
+        {
+            int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.WriteInt64(ptr, TestValues[0]);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    Marshal.WriteInt64(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+                }
+
+                long value = Marshal.ReadInt64(ptr);
+                Assert.Equal(TestValues[0], value);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    value = Marshal.ReadInt64(ptr, i * Marshal.SizeOf(TestValues[0]));
+                    Assert.Equal(TestValues[i], value);
+                }
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/IntPtrTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/IntPtrTests.cs
new file mode 100644 (file)
index 0000000..2eef3c7
--- /dev/null
@@ -0,0 +1,74 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class IntPtrTests
+    {
+        public static readonly object[][] ArrayData =
+        {
+            new object[] { GenerateIntPtrArray() }
+        };
+
+        public static IntPtr[] GenerateIntPtrArray()
+        {
+            IntPtr[] testArray = new IntPtr[10];
+            for (int i = 0; i < testArray.Length; i++)
+                testArray[i] = new IntPtr(i);
+            return testArray;
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void NullValue_ThrowsException(IntPtr[] TestValues)
+        {
+            Exception e;
+
+            e = Record.Exception(() => Marshal.ReadIntPtr(IntPtr.Zero));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.ReadIntPtr(IntPtr.Zero, 2));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteIntPtr(IntPtr.Zero, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+
+            e = Record.Exception(() => Marshal.WriteIntPtr(IntPtr.Zero, 2, TestValues[0]));
+            Assert.True(e is AccessViolationException || e is NullReferenceException);
+        }
+
+        [Theory]
+        [MemberData(nameof(ArrayData))]
+        public void ReadWriteRoundTrip(IntPtr[] TestValues)
+        {
+            int sizeOfArray = Marshal.SizeOf(TestValues[0]) * TestValues.Length;
+
+            IntPtr ptr = Marshal.AllocCoTaskMem(sizeOfArray);
+            try
+            {
+                Marshal.WriteIntPtr(ptr, TestValues[0]);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    Marshal.WriteIntPtr(ptr, i * Marshal.SizeOf(TestValues[0]), TestValues[i]);
+                }
+
+                IntPtr value = Marshal.ReadIntPtr(ptr);
+                Assert.Equal(TestValues[0], value);
+
+                for (int i = 1; i < TestValues.Length; i++)
+                {
+                    value = Marshal.ReadIntPtr(ptr, i * Marshal.SizeOf(TestValues[0]));
+                    Assert.Equal(TestValues[i], value);
+                }
+            }
+            finally
+            {
+                Marshal.FreeCoTaskMem(ptr);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/ObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/ObjectTests.cs
new file mode 100644 (file)
index 0000000..917417d
--- /dev/null
@@ -0,0 +1,107 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    internal struct BlittableStruct
+    {
+        internal int _a;
+        internal int _b;
+        internal byte _c;
+        internal short _d;
+        internal IntPtr _p;
+    }
+
+    internal struct StructWithReferenceTypes
+    {
+        internal IntPtr _ptr;
+        internal string _str;
+        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
+        internal int[] _byValArr;
+    }
+#pragma warning disable 618
+    public class ObjectTests
+    {
+        [Fact]
+        [ActiveIssue(30830, TargetFrameworkMonikers.NetFramework)]
+        public void NullValueArguments_ThrowsArgumentNullException()
+        {
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteByte(null, 0, 0); });
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteInt16(null, 0, 0); });
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteInt32(null, 0, 0); });
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteInt64(null, 0, 0); });
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.WriteIntPtr(null, 0, IntPtr.Zero); });
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.ReadByte(null, 0); });
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.ReadInt16(null, 0); });
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.ReadInt32(null, 0); });
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => { Marshal.ReadIntPtr(null, 0); });
+        }
+
+        [Fact]
+        public void TestBlittableStruct()
+        {
+            BlittableStruct blittableStruct = new BlittableStruct();
+            blittableStruct._a = 200;
+            blittableStruct._b = 300;
+            blittableStruct._c = 10;
+            blittableStruct._d = 123;
+            blittableStruct._p = new IntPtr(100);
+
+            object boxedBlittableStruct = (object)blittableStruct;
+
+            int offsetOfB = Marshal.OffsetOf<BlittableStruct>("_b").ToInt32();
+            int offsetOfC = Marshal.OffsetOf<BlittableStruct>("_c").ToInt32();
+            int offsetOfD = Marshal.OffsetOf<BlittableStruct>("_d").ToInt32();
+            int offsetOfP = Marshal.OffsetOf<BlittableStruct>("_p").ToInt32();
+
+            Assert.Equal(200, Marshal.ReadInt32(boxedBlittableStruct, 0));
+            Assert.Equal(300, Marshal.ReadInt32(boxedBlittableStruct, offsetOfB));
+            Assert.Equal(10, Marshal.ReadByte(boxedBlittableStruct, offsetOfC));
+            Assert.Equal(123, Marshal.ReadInt16(boxedBlittableStruct, offsetOfD));
+            Assert.Equal(new IntPtr(100), Marshal.ReadIntPtr(boxedBlittableStruct, offsetOfP));
+
+            Marshal.WriteInt32(boxedBlittableStruct, 0, 300);
+            Marshal.WriteInt32(boxedBlittableStruct, offsetOfB, 400);
+            Marshal.WriteByte(boxedBlittableStruct, offsetOfC, 20);
+            Marshal.WriteInt16(boxedBlittableStruct, offsetOfD, 144);
+
+            Marshal.WriteIntPtr(boxedBlittableStruct, offsetOfP, new IntPtr(500));
+
+            Assert.Equal(300, ((BlittableStruct)boxedBlittableStruct)._a);
+            Assert.Equal(400, ((BlittableStruct)boxedBlittableStruct)._b);
+            Assert.Equal(20, ((BlittableStruct)boxedBlittableStruct)._c);
+            Assert.Equal(144, ((BlittableStruct)boxedBlittableStruct)._d);
+            Assert.Equal(new IntPtr(500), ((BlittableStruct)boxedBlittableStruct)._p);
+        }
+
+        [Fact]
+        public void TestStructWithReferenceType()
+        {
+            StructWithReferenceTypes structWithReferenceTypes = new StructWithReferenceTypes();
+            structWithReferenceTypes._ptr = new IntPtr(100);
+            structWithReferenceTypes._str = "ABC";
+            structWithReferenceTypes._byValArr = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+            object boxedStruct = (object)structWithReferenceTypes;
+
+            int offsetOfStr = Marshal.OffsetOf<StructWithReferenceTypes>("_str").ToInt32();
+            int offsetOfByValArr = Marshal.OffsetOf<StructWithReferenceTypes>("_byValArr").ToInt32();
+
+            Assert.Equal(100, Marshal.ReadInt32(boxedStruct, 0));
+            Assert.NotEqual(IntPtr.Zero, Marshal.ReadIntPtr(boxedStruct, offsetOfStr));
+            Assert.Equal(3, Marshal.ReadInt32(boxedStruct, offsetOfByValArr + sizeof(int) * 2));
+
+            Marshal.WriteInt32(boxedStruct, 0, 200);
+            Marshal.WriteInt32(boxedStruct, offsetOfByValArr + sizeof(int) * 9, 100);
+
+            Assert.Equal(new IntPtr(200), ((StructWithReferenceTypes)boxedStruct)._ptr);
+            Assert.Equal(100, ((StructWithReferenceTypes)boxedStruct)._byValArr[9]);
+            Assert.Equal(9, ((StructWithReferenceTypes)boxedStruct)._byValArr[8]);
+            Assert.Equal("ABC", ((StructWithReferenceTypes)boxedStruct)._str);
+        }
+    }
+#pragma warning restore 618
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs
new file mode 100644 (file)
index 0000000..76298bc
--- /dev/null
@@ -0,0 +1,65 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class SizeOfTests
+    {
+        public struct TestStructWithEnumArray
+        {
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+            public TestEnum[] ArrayOfEnum;
+        }
+
+        public enum TestEnum
+        {
+            red,
+            green,
+            blue
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        public struct SomeTestStruct
+        {
+            public int i;
+            public String s;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        public struct TestStructWithFxdLPSTRSAFld
+        {
+            [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 0)]
+            public String[] Arr;
+        }
+
+        [Fact]
+        public void SizeOfStructWithEnumArray()
+        {
+            TestStructWithEnumArray s = new TestStructWithEnumArray();
+            s.ArrayOfEnum = new TestEnum[3];
+            s.ArrayOfEnum[0] = TestEnum.red;
+            s.ArrayOfEnum[1] = TestEnum.green;
+            s.ArrayOfEnum[2] = TestEnum.blue;
+            int retsize = Marshal.SizeOf(s.GetType());
+            Assert.Equal(12, retsize);
+
+            retsize = 0;
+            retsize = Marshal.SizeOf(typeof(TestStructWithEnumArray));
+            int genericRetsize = Marshal.SizeOf<TestStructWithEnumArray>();
+            Assert.Equal(12, retsize);
+            Assert.Equal(retsize, genericRetsize);
+        }
+
+        [Fact]
+        public void SizeOfStructTest()
+        {
+            SomeTestStruct someTestStruct = new SomeTestStruct();
+            AssertExtensions.Throws<ArgumentNullException>("t", () => Marshal.SizeOf(null));
+            Assert.Throws<ArgumentException>(() => Marshal.SizeOf(typeof(TestStructWithFxdLPSTRSAFld)));
+            Marshal.SizeOf(someTestStruct.GetType());
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs
new file mode 100644 (file)
index 0000000..90def5f
--- /dev/null
@@ -0,0 +1,194 @@
+// 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.Linq;
+using Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class StringMarshalingTests
+    {
+        private readonly String[] TestStrings = new String[] {
+                                    "", //Empty String
+                                    "Test String",
+                                    "A", //Single character string
+                                    string.Concat(Enumerable.Repeat("This is a very long string as it repeats itself. ", 13)),
+                                    "This \n is \n a \n multiline \n string",
+                                    "This \0 is \0 a \0 string \0 with \0 nulls",
+                                    "\0string",
+                                    "string\0",
+                                    "\0\0\0\0\0\0\0\0"
+                                    };
+
+        [Fact]
+        public void StringToBStrToString()
+        {
+            foreach (String ts in TestStrings)
+            {
+                IntPtr BStr = Marshal.StringToBSTR(ts);
+                try
+                {
+                    String str = Marshal.PtrToStringBSTR(BStr);
+                    Assert.Equal(ts, str);
+                }
+                finally
+                {
+                    Marshal.FreeBSTR(BStr);
+                }
+            }
+        }
+
+        [Fact]
+        public void StringToCoTaskMemAnsiToString()
+        {
+            foreach (String ts in TestStrings)
+            {
+                if (ts.Contains("\0"))
+                    continue; //Skip the string with nulls case
+
+                IntPtr AnsiStr = Marshal.StringToCoTaskMemAnsi(ts);
+                try
+                {
+                    String str = Marshal.PtrToStringAnsi(AnsiStr);
+
+                    Assert.Equal(ts, str);
+                    if (ts.Length > 0)
+                    {
+                        String str2 = Marshal.PtrToStringAnsi(AnsiStr, ts.Length - 1);
+                        Assert.Equal(ts.Substring(0, ts.Length - 1), str2);
+                    }
+                }
+                finally
+                {
+                    Marshal.FreeCoTaskMem(AnsiStr);
+                }
+            }
+        }
+
+        [Fact]
+        public void StringToCoTaskMemUniToString()
+        {
+            foreach (String ts in TestStrings)
+            {
+                if (ts.Contains("\0"))
+                    continue; //Skip the string with nulls case
+
+                IntPtr UniStr = Marshal.StringToCoTaskMemUni(ts);
+                try
+                {
+                    String str = Marshal.PtrToStringUni(UniStr);
+
+                    Assert.Equal(ts, str);
+                    if (ts.Length > 0)
+                    {
+                        String str2 = Marshal.PtrToStringUni(UniStr, ts.Length - 1);
+                        Assert.Equal(ts.Substring(0, ts.Length - 1), str2);
+                    }
+                }
+                finally
+                {
+                    Marshal.FreeCoTaskMem(UniStr);
+                }
+            }
+        }
+
+        [Fact]
+        public void StringToHGlobalAnsiToString()
+        {
+            foreach (String ts in TestStrings)
+            {
+                if (ts.Contains("\0"))
+                    continue; //Skip the string with nulls case
+
+                IntPtr AnsiStr = Marshal.StringToHGlobalAnsi(ts);
+                try
+                {
+                    String str = Marshal.PtrToStringAnsi(AnsiStr);
+
+                    Assert.Equal(ts, str);
+                    if (ts.Length > 0)
+                    {
+                        String str2 = Marshal.PtrToStringAnsi(AnsiStr, ts.Length - 1);
+                        Assert.Equal(ts.Substring(0, ts.Length - 1), str2);
+                    }
+                }
+                finally
+                {
+                    Marshal.FreeHGlobal(AnsiStr);
+                }
+            }
+        }
+
+        [Fact]
+        public void StringToHGlobalUniToString()
+        {
+            foreach (String ts in TestStrings)
+            {
+                if (ts.Contains("\0"))
+                    continue; //Skip the string with nulls case
+
+                IntPtr UniStr = Marshal.StringToHGlobalUni(ts);
+                try
+                {
+                    String str = Marshal.PtrToStringUni(UniStr);
+
+                    Assert.Equal(ts, str);
+                    if (ts.Length > 0)
+                    {
+                        String str2 = Marshal.PtrToStringUni(UniStr, ts.Length - 1);
+                        Assert.Equal(ts.Substring(0, ts.Length - 1), str2);
+                    }
+                }
+                finally
+                {
+                    Marshal.FreeHGlobal(UniStr);
+                }
+            }
+
+        }
+
+#if netcoreapp
+        [Fact]
+        public void TestUTF8String()
+        {
+            foreach (String srcString in TestStrings)
+            {
+                // we assume string null terminated
+                if (srcString.Contains("\0"))
+                    continue;
+
+                IntPtr ptrString = Marshal.StringToCoTaskMemUTF8(srcString);
+                try
+                {
+                    string retString = Marshal.PtrToStringUTF8(ptrString);
+
+                    Assert.Equal(srcString, retString);
+                    if (srcString.Length > 0)
+                    {
+                        string retString2 = Marshal.PtrToStringUTF8(ptrString, srcString.Length - 1);
+                        Assert.Equal(srcString.Substring(0, srcString.Length - 1), retString2);
+                    }
+                }
+                finally
+                {
+                    Marshal.FreeCoTaskMem(ptrString);
+                }
+            }
+        }
+
+        [Fact]
+        public void TestNullString_UTF8()
+        {
+            Assert.Null(Marshal.PtrToStringUTF8(IntPtr.Zero));
+        }
+#endif
+
+        [Fact]
+        public void TestNullString()
+        {
+            Assert.Null(Marshal.PtrToStringUni(IntPtr.Zero));
+            Assert.Null(Marshal.PtrToStringAnsi(IntPtr.Zero));
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs
new file mode 100644 (file)
index 0000000..e327c21
--- /dev/null
@@ -0,0 +1,185 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class StructureToPtrTests
+    {
+        public struct StructWithIntField
+        {
+            public int value;
+        }
+
+        public struct StructWithByValArray
+        {
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
+            public StructWithIntField[] array;
+        }
+
+        public struct StructWithBoolArray
+        {
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+            public bool[] array;
+        }
+
+        public struct StructWithDateArray
+        {
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
+            public DateTime[] array;
+        }
+
+        [StructLayout(LayoutKind.Auto)]
+        public struct SomeTestStruct_Auto
+        {
+            public int i;
+        }
+
+        [Fact]
+        public void AutoLayoutStructureTest()
+        {
+            var someTs_Auto = new SomeTestStruct_Auto();
+            ArgumentException ex = AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.StructureToPtr(someTs_Auto, new IntPtr(123), true));
+        }
+
+        [Fact]
+        public void NullParameter()
+        {
+            IntPtr ip = IntPtr.Zero;
+            AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.StructureToPtr<SomeTestStruct_Auto>(new SomeTestStruct_Auto(), ip, true));
+
+            ip = new IntPtr(123);
+            AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.StructureToPtr<Object>(null, ip, true));
+        }
+
+        [Fact]
+        public void VerifyByValBoolArray()
+        {
+            var structure1 = new StructWithBoolArray()
+            {
+                array = new bool[]
+                {
+                    true,true,true,true
+                }
+            };
+
+            int size = Marshal.SizeOf(structure1);
+            IntPtr memory = Marshal.AllocHGlobal(size + sizeof(Int32));
+
+            try
+            {
+                Marshal.WriteInt32(memory, size, 0xFF);
+                Marshal.StructureToPtr(structure1, memory, false);
+                Marshal.StructureToPtr(structure1, memory, true);
+                Assert.Equal(0xFF, Marshal.ReadInt32(memory, size));
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(memory);
+            }
+        }
+
+        [Fact]
+        public void VerifyByValArrayInStruct()
+        {
+            // equal
+            var structure1 = new StructWithByValArray()
+            {
+                array = new StructWithIntField[]
+                {
+                    new StructWithIntField { value = 1 },
+                    new StructWithIntField { value = 2 },
+                    new StructWithIntField { value = 3 },
+                    new StructWithIntField { value = 4 },
+                    new StructWithIntField { value = 5 }
+                }
+            };
+            int size = Marshal.SizeOf(structure1);
+            IntPtr memory = Marshal.AllocHGlobal(size);
+            try
+            {
+                Marshal.StructureToPtr(structure1, memory, false);
+                Marshal.StructureToPtr(structure1, memory, true);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(memory);
+            }
+
+            // underflow
+            var structure2 = new StructWithByValArray()
+            {
+                array = new StructWithIntField[]
+                {
+                    new StructWithIntField { value = 1 },
+                    new StructWithIntField { value = 2 },
+                    new StructWithIntField { value = 3 },
+                    new StructWithIntField { value = 4 }
+                }
+            };
+            size = Marshal.SizeOf(structure2);
+            memory = Marshal.AllocHGlobal(size);
+            try
+            {
+                Assert.Throws<ArgumentException>(() => Marshal.StructureToPtr(structure2, memory, false));
+                Assert.Throws<ArgumentException>(() => Marshal.StructureToPtr(structure2, memory, true));
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(memory);
+            }
+
+            // overflow
+            var structure3 = new StructWithByValArray()
+            {
+                array = new StructWithIntField[]
+                {
+                    new StructWithIntField { value = 1 },
+                    new StructWithIntField { value = 2 },
+                    new StructWithIntField { value = 3 },
+                    new StructWithIntField { value = 4 },
+                    new StructWithIntField { value = 5 },
+                    new StructWithIntField { value = 6 }
+                }
+            };
+
+            size = Marshal.SizeOf(structure3);
+            memory = Marshal.AllocHGlobal(size);
+            try
+            {
+                Marshal.StructureToPtr(structure3, memory, false);
+                Marshal.StructureToPtr(structure3, memory, true);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(memory);
+            }
+        }
+
+        [Fact]
+        public void VerfiyByValDateArray()
+        {
+            var structure1 = new StructWithDateArray()
+            {
+                array = new DateTime[]
+                {
+                    DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now
+                }
+            };
+
+            int size = Marshal.SizeOf(structure1);
+            IntPtr memory = Marshal.AllocHGlobal(size);
+            try
+            {
+                Marshal.StructureToPtr(structure1, memory, false);
+                Marshal.StructureToPtr(structure1, memory, true);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(memory);
+            }
+        }
+    }
+}
diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/UnsafeAddrOfPinnedArrayElementTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/UnsafeAddrOfPinnedArrayElementTests.cs
new file mode 100644 (file)
index 0000000..fcb8e6a
--- /dev/null
@@ -0,0 +1,80 @@
+// 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 Xunit;
+
+namespace System.Runtime.InteropServices.Tests
+{
+    public class UnsafeAddrOfPinnedArrayElementTests
+    {
+        [Fact]
+        public void NullParameter()
+        {
+            int[] array = null;
+            AssertExtensions.Throws<ArgumentNullException>("arr", () => Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 0));
+        }
+
+        [Fact]
+        public void PrimitiveType()
+        {
+            int[] array = new int[] { 1, 2, 3 };
+            GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+            try
+            {
+                IntPtr v0 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 0);
+                Assert.Equal(1, Marshal.ReadInt32(v0));
+
+                IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 1);
+                Assert.Equal(2, Marshal.ReadInt32(v1));
+
+                IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 2);
+                Assert.Equal(3, Marshal.ReadInt32(v2));
+            }
+            finally
+            {
+                handle.Free();
+            }
+        }
+
+
+        struct Point
+        {
+            public int x;
+            public int y;
+        }
+
+        [Fact]
+        public void StructType()
+        {
+            Point[] array = new Point[]{
+            new Point(){x = 100, y = 100},
+            new Point(){x = -1, y = -1},
+            new Point(){x = 0, y = 0},
+            };
+
+            GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+            try
+            {
+                IntPtr v0 = Marshal.UnsafeAddrOfPinnedArrayElement<Point>(array, 0);
+                Point p0 = Marshal.PtrToStructure<Point>(v0);
+                Assert.Equal(100, p0.x);
+                Assert.Equal(100, p0.y);
+
+                IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement<Point>(array, 1);
+                Point p1 = Marshal.PtrToStructure<Point>(v1);
+                Assert.Equal(-1, p1.x);
+                Assert.Equal(-1, p1.y);
+
+                IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement<Point>(array, 2);
+                Point p2 = Marshal.PtrToStructure<Point>(v2);
+                Assert.Equal(0, p2.x);
+                Assert.Equal(0, p2.y);
+            }
+            finally
+            {
+                handle.Free();
+            }
+        }
+    }
+}