<Compile Include="System\Runtime\InteropServices\Marshal\ZeroFreeGlobalAllocUnicodeTests.cs" />
<Compile Include="System\Runtime\InteropServices\Marshal\Common\CommonTypes.cs" />
<Compile Include="System\Runtime\InteropServices\Marshal\Common\CommonTypes.Windows.cs" Condition="'$(TargetsWindows)' == 'true'" />
+ <Compile Include="System\Runtime\InteropServices\Marshal\Common\Variant.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" />
[InlineData(-1)]
[InlineData(0)]
[InlineData(4)]
- public void Ctor_ShortClassInterfaceType(ClassInterfaceType classInterfaceType)
+ public void Ctor_ShortClassInterfaceType(short classInterfaceType)
{
var attribute = new ClassInterfaceAttribute(classInterfaceType);
- Assert.Equal(classInterfaceType, attribute.Value);
+ Assert.Equal((ClassInterfaceType)classInterfaceType, attribute.Value);
}
[Theory]
// 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.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices.Tests.Common;
using Xunit;
namespace System.Runtime.InteropServices.Tests
{
- public class ChangeWrapperHandleStrengthTests
+ public partial class ChangeWrapperHandleStrengthTests
{
+ public static IEnumerable<object[]> ChangeWrapperHandleStrength_TestData()
+ {
+ yield return new object[] { new object() };
+ yield return new object[] { 10 };
+ yield return new object[] { "string" };
+
+ yield return new object[] { new NonGenericClass() };
+ yield return new object[] { new GenericClass<string>() };
+ yield return new object[] { new Dictionary<string, int>() };
+ yield return new object[] { new NonGenericStruct() };
+ yield return new object[] { new GenericStruct<string>() };
+ yield return new object[] { Int32Enum.Value1 };
+
+ yield return new object[] { new int[] { 10 } };
+ yield return new object[] { new int[][] { new int[] { 10 } } };
+ yield return new object[] { new int[,] { { 10 } } };
+
+ MethodInfo method = typeof(ChangeWrapperHandleStrengthTests).GetMethod(nameof(NonGenericMethod));
+ Delegate d = method.CreateDelegate(typeof(NonGenericDelegate));
+ yield return new object[] { d };
+ }
+
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNetNative))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ [MemberData(nameof(ChangeWrapperHandleStrength_TestData))]
+ public void ChangeWrapperHandleStrength_ValidObject_Success(object otp)
+ {
+ Marshal.ChangeWrapperHandleStrength(otp, fIsWeak: true);
+ Marshal.ChangeWrapperHandleStrength(otp, fIsWeak: false);
+ }
+
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNetNative))]
[PlatformSpecific(TestPlatforms.Windows)]
public void ChangeWrapperHandleStrength_NullObject_ThrowsArgumentNullException()
AssertExtensions.Throws<ArgumentNullException>("otp", () => Marshal.ChangeWrapperHandleStrength(null, fIsWeak: false));
}
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNetNative))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void ChangeWrapperHandleStrength_ObjectNotCollectible_ThrowsNotSupportedException()
+ {
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.RunAndCollect);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ Type type = typeBuilder.CreateType();
+
+ object o = Activator.CreateInstance(type);
+ Assert.Throws<NotSupportedException>(() => Marshal.ChangeWrapperHandleStrength(o, fIsWeak: true));
+ }
+
[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void ChangeWrapperHandleStrength_Unix_ThrowsPlatformNotSupportedException()
Assert.Throws<PlatformNotSupportedException>(() => Marshal.ChangeWrapperHandleStrength(null, fIsWeak: true));
Assert.Throws<PlatformNotSupportedException>(() => Marshal.ChangeWrapperHandleStrength(null, fIsWeak: false));
}
+
+ public static void NonGenericMethod(int i) { }
+ public delegate void NonGenericDelegate(int i);
+
+ public enum Int32Enum : int { Value1, Value2 }
}
}
--- /dev/null
+// 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.
+
+namespace System.Runtime.InteropServices.Tests.Common
+{
+ public 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
+ }
+}
// 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.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices.Tests.Common;
using Xunit;
namespace System.Runtime.InteropServices.Tests
{
public class DestroyStructureTests
{
- [StructLayout(LayoutKind.Sequential)]
- public struct SomeTestStruct
+ [Fact]
+ public void DestroyStructure_Generic_Success()
{
- public int i;
- public String s;
+ var structure = new TestStruct();
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(structure));
+ try
+ {
+ structure.s = null;
+
+ Marshal.StructureToPtr(structure, ptr, fDeleteOld: false);
+ Marshal.DestroyStructure<TestStruct>(ptr);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
}
- [StructLayout(LayoutKind.Auto)]
- public struct SomeTestStruct_Auto
+ [Fact]
+ public void DestroyStructure_NonGeneric_Succes()
{
- public int i;
+ var structure = new TestStruct();
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(structure));
+ try
+ {
+ structure.s = null;
+
+ Marshal.StructureToPtr(structure, ptr, fDeleteOld: false);
+ Marshal.DestroyStructure(ptr, typeof(TestStruct));
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+
+ [Fact]
+ public void DestroyStructure_Blittable_Success()
+ {
+ Marshal.DestroyStructure<int>((IntPtr)1);
+ Marshal.DestroyStructure((IntPtr)1, typeof(int));
+ }
+
+ [Fact]
+ public void DestroyStructure_ZeroPointer_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.DestroyStructure<TestStruct>(IntPtr.Zero));
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.DestroyStructure(IntPtr.Zero, typeof(TestStruct)));
}
[Fact]
- public void DestroyStructure_Negative()
+ public void DestroyStructure_NullStructureType_ThrowsArgumentNullException()
{
- IntPtr ip;
+ AssertExtensions.Throws<ArgumentNullException>("structureType", () => Marshal.DestroyStructure((IntPtr)1, null));
+ }
+
+ public static IEnumerable<object[]> DestroyStructure_InvalidType_TestData()
+ {
+ yield return new object[] { typeof(int).MakeByRefType() };
+ yield return new object[] { typeof(string) };
+
+ yield return new object[] { typeof(NonGenericClass) };
+ yield return new object[] { typeof(GenericClass<>) };
+ yield return new object[] { typeof(GenericClass<string>) };
+ yield return new object[] { typeof(AbstractClass) };
- ip = IntPtr.Zero;
- AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.DestroyStructure<SomeTestStruct>(ip));
+ yield return new object[] { typeof(GenericStruct<>) };
+ yield return new object[] { typeof(GenericStruct<string>) };
+ yield return new object[] { typeof(GenericInterface<>) };
+ yield return new object[] { typeof(GenericInterface<string>) };
- ip = new IntPtr(123);
- AssertExtensions.Throws<ArgumentNullException>("structureType", () => Marshal.DestroyStructure(ip, null));
+ yield return new object[] { typeof(GenericClass<>).GetTypeInfo().GenericTypeParameters[0] };
- SomeTestStruct_Auto someTs_Auto = new SomeTestStruct_Auto();
- Assert.Throws<ArgumentException>(() => Marshal.DestroyStructure(ip, someTs_Auto.GetType()));
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.Run);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ yield return new object[] { typeBuilder };
+ }
+
+ [Theory]
+ [MemberData(nameof(DestroyStructure_InvalidType_TestData))]
+ public void DestroyStructure_NonRuntimeType_ThrowsArgumentException(Type invalidType)
+ {
+ AssertExtensions.Throws<ArgumentException>("structureType", () => Marshal.DestroyStructure((IntPtr)1, invalidType));
}
[Fact]
- public void DestroyStructure_Positive()
+ public void DestroyStructure_AutoLayout_ThrowsArgumentException()
{
- 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);
- }
+ AssertExtensions.Throws<ArgumentException>("structureType", () => Marshal.DestroyStructure<AutoLayoutStruct>((IntPtr)1));
+ AssertExtensions.Throws<ArgumentException>("structureType", () => Marshal.DestroyStructure((IntPtr)1, typeof(AutoLayoutStruct)));
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TestStruct
+ {
+ public int i;
+ public string s;
+ }
+
+ [StructLayout(LayoutKind.Auto)]
+ public struct AutoLayoutStruct
+ {
+ public int i;
}
}
}
}
yield return new object[] { typeof(ClassWithGuidAttribute) };
+
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.RunAndCollect);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ Type collectibleType = typeBuilder.CreateType();
+ yield return new object[] { collectibleType };
}
[Theory]
yield return new object[] { typeof(GenericClass<>) };
yield return new object[] { typeof(GenericClass<>).GetTypeInfo().GenericTypeParameters[0] };
+
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.RunAndCollect);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ Type collectibleType = typeBuilder.CreateType();
+ yield return new object[] { collectibleType };
}
[Theory]
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
using System.Runtime.InteropServices.Tests.Common;
using Xunit;
namespace System.Runtime.InteropServices.Tests
{
- public class GetIDispatchForObjectTests
+ public partial class GetIDispatchForObjectTests
{
public static IEnumerable<object[]> GetIDispatchForObject_Valid_TestData()
{
yield return new object[] { new NonGenericClass() };
yield return new object[] { new NonGenericStruct() };
-
- Type type = Type.GetTypeFromCLSID(new Guid("927971f5-0939-11d1-8be1-00c04fd8d503"));
- object comObject = Activator.CreateInstance(type);
- yield return new object[] { comObject };
}
[Theory]
[MemberData(nameof(GetIDispatchForObject_Valid_TestData))]
[SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "Marshal.GetIDispatchForObject is not implemented in .NET Core.")]
- public void GetIDispatchForObject_NetFramework_ReturnsNonZero(object o)
+ public void GetIDispatchForObject_ValidObject_Roundtrips(object o)
{
- IntPtr iDispatch = Marshal.GetIDispatchForObject(o);
+ IntPtr ptr = Marshal.GetIDispatchForObject(o);
try
{
- Assert.NotEqual(IntPtr.Zero, iDispatch);
+ Assert.NotEqual(IntPtr.Zero, ptr);
}
finally
{
- Marshal.Release(iDispatch);
+ Marshal.Release(ptr);
}
}
yield return new object[] { new GenericStruct<string>() };
}
- [Theory]
- [MemberData(nameof(GetIDispatchForObject_Invalid_TestData))]
+ [Fact]
[SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "Marshal.GetIDispatchForObject is not implemented in .NET Core.")]
- public void GetIDispatchForObject_InvalidObject_ThrowsInvalidCastException(object o)
+ public void GetIDispatchForObject_NullObject_ThrowsArgumentNullException()
{
- Assert.Throws<InvalidCastException>(() => Marshal.GetIDispatchForObject(o));
+ AssertExtensions.Throws<ArgumentNullException>("o", () => Marshal.GetIDispatchForObject(null));
}
- [Fact]
+ [ConditionalFact]
+ [PlatformSpecific(TestPlatforms.Windows)]
[SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "Marshal.GetIDispatchForObject is not implemented in .NET Core.")]
- public void GetIDispatchForObject_NullObject_ThrowsArgumentNullException()
+ public void GetIDispatchForObject_ObjectNotCollectible_ThrowsNotSupportedException()
{
- AssertExtensions.Throws<ArgumentNullException>("o", () => Marshal.GetIDispatchForObject(null));
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.RunAndCollect);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ Type type = typeBuilder.CreateType();
+
+ object o = Activator.CreateInstance(type);
+ Assert.Throws<NotSupportedException>(() => Marshal.GetIDispatchForObject(o));
+ }
+
+ [Theory]
+ [MemberData(nameof(GetIDispatchForObject_Invalid_TestData))]
+ [SkipOnTargetFramework(~TargetFrameworkMonikers.NetFramework, "Marshal.GetIDispatchForObject is not implemented in .NET Core.")]
+ public void GetIDispatchForObject_InvalidObject_ThrowsInvalidCastException(object o)
+ {
+ Assert.Throws<InvalidCastException>(() => Marshal.GetIDispatchForObject(o));
}
}
}
// 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.Collections.Generic;
+using System.Drawing;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices.Tests.Common;
using Xunit;
+#pragma warning disable 618
+
namespace System.Runtime.InteropServices.Tests
{
[SkipOnTargetFramework(TargetFrameworkMonikers.Uap, "GetNativeVariantForObject() not supported on UWP")]
- public class GetNativeVariantForObjectTests
+ public partial class GetNativeVariantForObjectTests
{
- internal struct Variant
+ public static IEnumerable<object[]> GetNativeVariantForObject_RoundtrippingPrimitives_TestData()
{
-#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
+ yield return new object[] { null, VarEnum.VT_EMPTY, IntPtr.Zero };
+
+ yield return new object[] { (sbyte)10, VarEnum.VT_I1, (IntPtr)10 };
+ yield return new object[] { (short)10, VarEnum.VT_I2, (IntPtr)10 };
+ yield return new object[] { 10, VarEnum.VT_I4, (IntPtr)10 };
+ yield return new object[] { (long)10, VarEnum.VT_I8, (IntPtr)10 };
+ yield return new object[] { (byte)10, VarEnum.VT_UI1, (IntPtr)10 };
+ yield return new object[] { (ushort)10, VarEnum.VT_UI2, (IntPtr)10 };
+ yield return new object[] { (uint)10, VarEnum.VT_UI4, (IntPtr)10 };
+ yield return new object[] { (ulong)10, VarEnum.VT_UI8, (IntPtr)10 };
+
+ yield return new object[] { true, VarEnum.VT_BOOL, (IntPtr)ushort.MaxValue };
+ yield return new object[] { false, VarEnum.VT_BOOL, IntPtr.Zero };
+
+ yield return new object[] { 10m, VarEnum.VT_DECIMAL, (IntPtr)10 };
+
+ // Well known types.
+ DateTime dateTime = new DateTime(1899, 12, 30).AddDays(20);
+ yield return new object[] { dateTime, VarEnum.VT_DATE, (IntPtr)(-1) };
+
+ yield return new object[] { DBNull.Value, VarEnum.VT_NULL, IntPtr.Zero };
+ yield return new object[] { DBNull.Value, VarEnum.VT_NULL, IntPtr.Zero };
+
+ // Arrays.
+ yield return new object[] { new sbyte[] { 10, 11, 12 }, (VarEnum)8208, (IntPtr)(-1) };
+ yield return new object[] { new short[] { 10, 11, 12 }, (VarEnum)8194, (IntPtr)(-1) };
+ yield return new object[] { new int[] { 10, 11, 12 }, (VarEnum)8195, (IntPtr)(-1) };
+ yield return new object[] { new long[] { 10, 11, 12 }, (VarEnum)8212, (IntPtr)(-1) };
+ yield return new object[] { new byte[] { 10, 11, 12 }, (VarEnum)8209, (IntPtr)(-1) };
+ yield return new object[] { new ushort[] { 10, 11, 12 }, (VarEnum)8210, (IntPtr)(-1) };
+ yield return new object[] { new uint[] { 10, 11, 12 }, (VarEnum)8211, (IntPtr)(-1) };
+ yield return new object[] { new ulong[] { 10, 11, 12 }, (VarEnum)8213, (IntPtr)(-1) };
+
+ yield return new object[] { new bool[] { true, false }, (VarEnum)8203, (IntPtr)(-1) };
+
+ yield return new object[] { new float[] { 10, 11, 12 }, (VarEnum)8196, (IntPtr)(-1) };
+ yield return new object[] { new double[] { 10, 11, 12 }, (VarEnum)8197, (IntPtr)(-1) };
+ yield return new object[] { new decimal[] { 10m, 11m, 12m }, (VarEnum)8206, (IntPtr)(-1) };
+
+ yield return new object[] { new object[] { 10, 11, 12 }, (VarEnum)8204, (IntPtr)(-1) };
+ yield return new object[] { new string[] { "a", "b", "c" }, (VarEnum)8200, (IntPtr)(-1) };
+
+ yield return new object[] { new TimeSpan[] { new TimeSpan(10) }, (VarEnum)8228, (IntPtr)(-1) };
+ yield return new object[] { new int[,] { { 10 }, { 11 }, { 12 } }, (VarEnum)8195, (IntPtr)(-1) };
+
+ // Objects.
+ var nonGenericClass = new NonGenericClass();
+ yield return new object[] { nonGenericClass, VarEnum.VT_DISPATCH, (IntPtr)(-1) };
+
+ var valueType = new StructWithValue { Value = 10 };
+ yield return new object[] { valueType, VarEnum.VT_RECORD, (IntPtr)(-1) };
+
+ var genericClass = new GenericClass<string>();
+ yield return new object[] { new object[] { nonGenericClass, genericClass, null }, (VarEnum)8204, (IntPtr)(-1) };
+
+ yield return new object[] { new object[] { valueType, null }, (VarEnum)8204, (IntPtr)(-1) };
+
+ // Delegate.
+ MethodInfo method = typeof(GetNativeVariantForObjectTests).GetMethod(nameof(NonGenericMethod));
+ Delegate d = method.CreateDelegate(typeof(NonGenericDelegate));
+ yield return new object[] { d, VarEnum.VT_DISPATCH, (IntPtr)(-1) };
}
-#pragma warning disable 618
+ [Theory]
+ [MemberData(nameof(GetNativeVariantForObject_RoundtrippingPrimitives_TestData))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ [ActiveIssue(31077, ~TargetFrameworkMonikers.NetFramework)]
+ public void GetNativeVariantForObject_RoundtrippingPrimitives_Success(object primitive, VarEnum expectedVarType, IntPtr expectedValue)
+ {
+ GetNativeVariantForObject_ValidObject_Success(primitive, expectedVarType, expectedValue, primitive);
+ }
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
- public static void EmptyObject()
+ public void GetNativeVariantForObject_TypeMissing_Success()
+ {
+ // This cannot be in the test data as XUnit uses MethodInfo.Invoke to call test methods and
+ // Type.Missing is handled specially for parameters with default values.
+ GetNativeVariantForObject_RoundtrippingPrimitives_Success(Type.Missing, VarEnum.VT_ERROR, (IntPtr)(-1));
+ }
+
+ public static IEnumerable<object[]> GetNativeVariantForObject_NonRoundtrippingPrimitives_TestData()
{
- Variant v = new Variant();
+ // 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.
+ yield return new object[] { 'a', VarEnum.VT_UI2, (IntPtr)'a', (ushort)97 };
+ yield return new object[] { new char[] { 'a', 'b', 'c' }, (VarEnum)8210, (IntPtr)(-1), new ushort[] { 'a', 'b', 'c' } };
+
+ // IntPtr/UIntPtr objects are converted to int/uint respectively.
+ yield return new object[] { (IntPtr)10, VarEnum.VT_INT, (IntPtr)10, 10 };
+ yield return new object[] { (UIntPtr)10, VarEnum.VT_UINT, (IntPtr)10, (uint)10 };
+
+ yield return new object[] { new IntPtr[] { (IntPtr)10, (IntPtr)11, (IntPtr)12 }, (VarEnum)8212, (IntPtr)(-1), new long[] { 10, 11, 12 } };
+ yield return new object[] { new UIntPtr[] { (UIntPtr)10, (UIntPtr)11, (UIntPtr)12 }, (VarEnum)8213, (IntPtr)(-1), new ulong[] { 10, 11, 12 } };
+
+ // DateTime is converted to VT_DATE which is offset from December 30, 1899.
+ DateTime earlyDateTime = new DateTime(1899, 12, 30);
+ yield return new object[] { earlyDateTime, VarEnum.VT_DATE, IntPtr.Zero, new DateTime(1899, 12, 30) };
+
+ // Wrappers.
+ yield return new object[] { new UnknownWrapper(10), VarEnum.VT_UNKNOWN, IntPtr.Zero, null };
+ if (!PlatformDetection.IsNetCore)
+ {
+ yield return new object[] { new DispatchWrapper(10), VarEnum.VT_DISPATCH, IntPtr.Zero, null };
+ }
+ else
+ {
+ Assert.Throws<PlatformNotSupportedException>(() => new DispatchWrapper(10));
+ }
+ yield return new object[] { new ErrorWrapper(10), VarEnum.VT_ERROR, (IntPtr)10, 10 };
+ yield return new object[] { new CurrencyWrapper(10), VarEnum.VT_CY, (IntPtr)100000, 10m };
+ yield return new object[] { new BStrWrapper("a"), VarEnum.VT_BSTR, (IntPtr)(-1), "a" };
+ yield return new object[] { new BStrWrapper(null), VarEnum.VT_BSTR, IntPtr.Zero, null };
+
+ yield return new object[] { new UnknownWrapper[] { new UnknownWrapper(null), new UnknownWrapper(10) }, (VarEnum)8205, (IntPtr)(-1), new object[] { null, 10 } };
+ if (!PlatformDetection.IsNetCore)
+ {
+ yield return new object[] { new DispatchWrapper[] { new DispatchWrapper(null), new DispatchWrapper(10) }, (VarEnum)8201, (IntPtr)(-1), new object[] { null, 10 } };
+ }
+ else
+ {
+ Assert.Throws<PlatformNotSupportedException>(() => new DispatchWrapper(10));
+ }
+ yield return new object[] { new ErrorWrapper[] { new ErrorWrapper(10) }, (VarEnum)8202, (IntPtr)(-1), new uint[] { 10 } };
+ yield return new object[] { new CurrencyWrapper[] { new CurrencyWrapper(10) }, (VarEnum)8198, (IntPtr)(-1), new decimal[] { 10 } };
+ yield return new object[] { new BStrWrapper[] { new BStrWrapper("a"), new BStrWrapper(null), new BStrWrapper("c") }, (VarEnum)8200, (IntPtr)(-1), new string[] { "a", null, "c" } };
+
+ // Objects.
+ var nonGenericClass = new NonGenericClass();
+ yield return new object[] { new NonGenericClass[] { nonGenericClass, null }, (VarEnum)8201, (IntPtr)(-1), new object[] { nonGenericClass, null } };
+
+ var genericClass = new GenericClass<string>();
+ yield return new object[] { new GenericClass<string>[] { genericClass, null }, (VarEnum)8205, (IntPtr)(-1), new object[] { genericClass, null } };
+
+ var nonGenericStruct = new NonGenericStruct();
+ yield return new object[] { new NonGenericStruct[] { nonGenericStruct }, (VarEnum)8228, (IntPtr)(-1), new NonGenericStruct[] { nonGenericStruct } };
+
+ var classWithInterface = new ClassWithInterface();
+ var structWithInterface = new StructWithInterface();
+ yield return new object[] { new ClassWithInterface[] { classWithInterface, null }, (VarEnum)8201, (IntPtr)(-1), new object[] { classWithInterface, null } };
+ yield return new object[] { new StructWithInterface[] { structWithInterface }, (VarEnum)8228, (IntPtr)(-1), new StructWithInterface[] { structWithInterface } };
+ yield return new object[] { new NonGenericInterface[] { classWithInterface, structWithInterface, null }, (VarEnum)8201, (IntPtr)(-1), new object[] { classWithInterface, structWithInterface, null } };
+
+ // Enums.
+ yield return new object[] { SByteEnum.Value2, VarEnum.VT_I1, (IntPtr)1, (sbyte)1 };
+ yield return new object[] { Int16Enum.Value2, VarEnum.VT_I2, (IntPtr)1, (short)1 };
+ yield return new object[] { Int32Enum.Value2, VarEnum.VT_I4, (IntPtr)1, 1 };
+ yield return new object[] { Int64Enum.Value2, VarEnum.VT_I8, (IntPtr)1, (long)1 };
+ yield return new object[] { ByteEnum.Value2, VarEnum.VT_UI1, (IntPtr)1, (byte)1 };
+ yield return new object[] { UInt16Enum.Value2, VarEnum.VT_UI2, (IntPtr)1, (ushort)1 };
+ yield return new object[] { UInt32Enum.Value2, VarEnum.VT_UI4, (IntPtr)1, (uint)1 };
+ yield return new object[] { UInt64Enum.Value2, VarEnum.VT_UI8, (IntPtr)1, (ulong)1 };
+
+ yield return new object[] { new SByteEnum[] { SByteEnum.Value2 }, (VarEnum)8208, (IntPtr)(-1), new sbyte[] { 1 } };
+ yield return new object[] { new Int16Enum[] { Int16Enum.Value2 }, (VarEnum)8194, (IntPtr)(-1), new short[] { 1 } };
+ yield return new object[] { new Int32Enum[] { Int32Enum.Value2 }, (VarEnum)8195, (IntPtr)(-1), new int[] { 1 } };
+ yield return new object[] { new Int64Enum[] { Int64Enum.Value2 }, (VarEnum)8212, (IntPtr)(-1), new long[] { 1 } };
+ yield return new object[] { new ByteEnum[] { ByteEnum.Value2 }, (VarEnum)8209, (IntPtr)(-1), new byte[] { 1 } };
+ yield return new object[] { new UInt16Enum[] { UInt16Enum.Value2 }, (VarEnum)8210, (IntPtr)(-1), new ushort[] { 1 } };
+ yield return new object[] { new UInt32Enum[] { UInt32Enum.Value2 }, (VarEnum)8211, (IntPtr)(-1), new uint[] { 1 } };
+ yield return new object[] { new UInt64Enum[] { UInt64Enum.Value2 }, (VarEnum)8213, (IntPtr)(-1), new ulong[] { 1 } };
+
+ // Color is converted to uint.
+ yield return new object[] { Color.FromArgb(10), VarEnum.VT_UI4, (IntPtr)655360, (uint)655360 };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetNativeVariantForObject_NonRoundtrippingPrimitives_TestData))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ [ActiveIssue(31077, ~TargetFrameworkMonikers.NetFramework)]
+ public void GetNativeVariantForObject_ValidObject_Success(object primitive, VarEnum expectedVarType, IntPtr expectedValue, object expectedRoundtripValue)
+ {
+ var v = new Variant();
IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
try
{
- Marshal.GetNativeVariantForObject(null, pNative);
+ Marshal.GetNativeVariantForObject(primitive, pNative);
+
+ Variant result = Marshal.PtrToStructure<Variant>(pNative);
+ Assert.Equal(expectedVarType, (VarEnum)result.vt);
+ if (expectedValue != (IntPtr)(-1))
+ {
+ Assert.Equal(expectedValue, result.bstrVal);
+ }
+ else
+ {
+ Assert.NotEqual((IntPtr)(-1), result.bstrVal);
+ Assert.NotEqual(IntPtr.Zero, result.bstrVal);
+ }
+
+ // Make sure it roundtrips.
+ Assert.Equal(expectedRoundtripValue, Marshal.GetObjectForNativeVariant(pNative));
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Theory]
+ [InlineData("")]
+ [InlineData("99")]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void GetNativeVariantForObject_String_Success(string obj)
+ {
+ var v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject(obj, pNative);
+
+ Variant result = Marshal.PtrToStructure<Variant>(pNative);
+ try
+ {
+ Assert.Equal(VarEnum.VT_BSTR, (VarEnum)result.vt);
+ Assert.Equal(obj, Marshal.PtrToStringBSTR(result.bstrVal));
+
+ object o = Marshal.GetObjectForNativeVariant(pNative);
+ Assert.Equal(obj, o);
+ }
+ finally
+ {
+ Marshal.FreeBSTR(result.bstrVal);
+ }
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ [Theory]
+ [InlineData(3.14)]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public unsafe void GetNativeVariantForObject_Double_Success(double obj)
+ {
+ var v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Marshal.GetNativeVariantForObject(obj, pNative);
+
+ Variant result = Marshal.PtrToStructure<Variant>(pNative);
+ Assert.Equal(VarEnum.VT_R8, (VarEnum)result.vt);
+ Assert.Equal(*((IntPtr*)&obj), result.bstrVal);
+
object o = Marshal.GetObjectForNativeVariant(pNative);
- Assert.Null(o);
+ Assert.Equal(obj, o);
}
finally
{
}
}
- [Fact]
+ [Theory]
+ [InlineData(3.14f)]
[PlatformSpecific(TestPlatforms.Windows)]
- public static void PrimitiveType()
+ public unsafe void GetNativeVariantForObject_Float_Success(float obj)
{
- Variant v = new Variant();
+ var 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);
+ Marshal.GetNativeVariantForObject(obj, pNative);
+
+ Variant result = Marshal.PtrToStructure<Variant>(pNative);
+ Assert.Equal(VarEnum.VT_R4, (VarEnum)result.vt);
+ Assert.Equal(*((IntPtr*)&obj), result.bstrVal);
+
+ object o = Marshal.GetObjectForNativeVariant(pNative);
+ Assert.Equal(obj, o);
}
finally
{
}
[Fact]
+ [PlatformSpecific(TestPlatforms.AnyUnix)]
+ public void GetNativeVariantForObject_Unix_ThrowsPlatformNotSupportedException()
+ {
+ Assert.Throws<PlatformNotSupportedException>(() => Marshal.GetNativeVariantForObject(new object(), IntPtr.Zero));
+ Assert.Throws<PlatformNotSupportedException>(() => Marshal.GetNativeVariantForObject(1, IntPtr.Zero));
+ }
+
+ [Fact]
[PlatformSpecific(TestPlatforms.Windows)]
- public static void CharType()
+ public void GetNativeVariantForObject_ZeroPointer_ThrowsArgumentNullException()
{
- // 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();
+ AssertExtensions.Throws<ArgumentNullException>("pDstNativeVariant", () => Marshal.GetNativeVariantForObject(new object(), IntPtr.Zero));
+ AssertExtensions.Throws<ArgumentNullException>("pDstNativeVariant", () => Marshal.GetNativeVariantForObject<int>(1, IntPtr.Zero));
+ }
+
+ public static IEnumerable<object[]> GetNativeVariantForObject_GenericObject_TestData()
+ {
+ yield return new object[] { new GenericClass<string>() };
+ yield return new object[] { new GenericStruct<string>() };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetNativeVariantForObject_GenericObject_TestData))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void GetNativeVariantForObject_GenericObject_ThrowsArgumentException(object obj)
+ {
+ AssertExtensions.Throws<ArgumentException>("obj", () => Marshal.GetNativeVariantForObject(obj, (IntPtr)1));
+ AssertExtensions.Throws<ArgumentException>("obj", () => Marshal.GetNativeVariantForObject<object>(obj, (IntPtr)1));
+ }
+
+ public static IEnumerable<object[]> GetNativeVariant_NotInteropCompatible_TestData()
+ {
+ yield return new object[] { new TimeSpan(10) };
+
+ yield return new object[] { new object[] { new GenericStruct<string>() } };
+
+ yield return new object[] { new GenericStruct<string>[0]};
+ yield return new object[] { new GenericStruct<string>[] { new GenericStruct<string>() } };
+
+ yield return new object[] { new Color[0] };
+ yield return new object[] { new Color[] { Color.FromArgb(10) } };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetNativeVariant_NotInteropCompatible_TestData))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ [ActiveIssue(31077, ~TargetFrameworkMonikers.NetFramework)]
+ public void GetNativeVariant_NotInteropCompatible_ThrowsArgumentException(object obj)
+ {
+ var 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);
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.GetNativeVariantForObject(obj, pNative));
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.GetNativeVariantForObject<object>(obj, pNative));
}
finally
{
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
- public static void CharTypeNegative()
+ public void GetNativeVariant_InvalidArray_ThrowsSafeArrayTypeMismatchException()
{
- // 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();
+ var v = new Variant();
IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
try
{
- Marshal.GetNativeVariantForObject<char>('a', pNative);
- Assert.Throws<InvalidCastException>(() => Marshal.GetObjectForNativeVariant<char>(pNative));
+ Assert.Throws<SafeArrayTypeMismatchException>(() => Marshal.GetNativeVariantForObject(new int[][] { }, pNative));
+ Assert.Throws<SafeArrayTypeMismatchException>(() => Marshal.GetNativeVariantForObject<object>(new int[][] { }, pNative));
}
finally
{
}
}
- [Fact]
+ public static IEnumerable<object[]> GetNativeVariant_VariantWrapper_TestData()
+ {
+ yield return new object[] { new VariantWrapper(null) };
+ yield return new object[] { new VariantWrapper[] { new VariantWrapper(null) } };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetNativeVariant_VariantWrapper_TestData))]
[PlatformSpecific(TestPlatforms.Windows)]
- public static void StringType()
+ public void GetNativeVariant_VariantWrapper_ThrowsArgumentException(object obj)
{
- Variant v = new Variant();
+ var 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);
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.GetNativeVariantForObject(obj, pNative));
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.GetNativeVariantForObject<object>(obj, pNative));
}
finally
{
}
}
- [Fact]
+ public static IEnumerable<object[]> GetNativeVariant_HandleObject_TestData()
+ {
+ yield return new object[] { new FakeSafeHandle() };
+ yield return new object[] { new FakeCriticalHandle() };
+
+ yield return new object[] { new FakeSafeHandle[] { new FakeSafeHandle() } };
+ yield return new object[] { new FakeCriticalHandle[] { new FakeCriticalHandle() } };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetNativeVariant_HandleObject_TestData))]
[PlatformSpecific(TestPlatforms.Windows)]
- public static void DoubleType()
+ public void GetNativeVariant_HandleObject_ThrowsArgumentException(object obj)
{
- Variant v = new Variant();
+ var 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);
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.GetNativeVariantForObject(obj, pNative));
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.GetNativeVariantForObject<object>(obj, pNative));
}
finally
{
}
[Fact]
- [PlatformSpecific(TestPlatforms.AnyUnix)]
- public void GetNativeVariantForObject_Unix_ThrowsPlatformNotSupportedException()
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public static void GetNativeVariantForObject_CantCastToObject_ThrowsInvalidCastException()
{
- Assert.Throws<PlatformNotSupportedException>(() => Marshal.GetNativeVariantForObject(new object(), IntPtr.Zero));
- Assert.Throws<PlatformNotSupportedException>(() => Marshal.GetNativeVariantForObject<int>(1, IntPtr.Zero));
+ // 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.
+ var 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]
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNetNative))]
[PlatformSpecific(TestPlatforms.Windows)]
- public static void GetNativeVariantForObject_ZeroPointer_ThrowsArgumentNullException()
+ public void GetNativeVariantForObject_ObjectNotCollectible_ThrowsNotSupportedException()
{
- AssertExtensions.Throws<ArgumentNullException>("pDstNativeVariant", () => Marshal.GetNativeVariantForObject(new object(), IntPtr.Zero));
- AssertExtensions.Throws<ArgumentNullException>("pDstNativeVariant", () => Marshal.GetNativeVariantForObject<int>(1, IntPtr.Zero));
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.RunAndCollect);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ Type type = typeBuilder.CreateType();
+
+ object o = Activator.CreateInstance(type);
+
+ var v = new Variant();
+ IntPtr pNative = Marshal.AllocHGlobal(Marshal.SizeOf(v));
+ try
+ {
+ Assert.Throws<NotSupportedException>(() => Marshal.GetNativeVariantForObject(o, pNative));
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(pNative);
+ }
+ }
+
+ public struct StructWithValue
+ {
+ public int Value;
+ }
+
+ public class ClassWithInterface : NonGenericInterface { }
+ public struct StructWithInterface : NonGenericInterface { }
+
+ public enum SByteEnum : sbyte { Value1, Value2 }
+ public enum Int16Enum : short { Value1, Value2 }
+ public enum Int32Enum : int { Value1, Value2 }
+ public enum Int64Enum : long { Value1, Value2 }
+
+ public enum ByteEnum : byte { Value1, Value2 }
+ public enum UInt16Enum : ushort { Value1, Value2 }
+ public enum UInt32Enum : uint { Value1, Value2 }
+ public enum UInt64Enum : ulong { Value1, Value2 }
+
+ public static void NonGenericMethod(int i) { }
+ public delegate void NonGenericDelegate(int i);
+
+ public class FakeSafeHandle : SafeHandle
+ {
+ public FakeSafeHandle() : base(IntPtr.Zero, false) { }
+
+ public override bool IsInvalid => throw new NotImplementedException();
+
+ protected override bool ReleaseHandle() => throw new NotImplementedException();
+
+ protected override void Dispose(bool disposing) { }
+ }
+
+ public class FakeCriticalHandle : CriticalHandle
+ {
+ public FakeCriticalHandle() : base(IntPtr.Zero) { }
+
+ public override bool IsInvalid => true;
+
+ protected override bool ReleaseHandle() => throw new NotImplementedException();
+
+ protected override void Dispose(bool disposing) { }
}
-#pragma warning restore 618
}
}
+
+#pragma warning restore 618
namespace System.Runtime.InteropServices.Tests
{
- public class GetTypedObjectForIUnknownTests
+ public partial class GetTypedObjectForIUnknownTests
{
- [Fact]
+ public static IEnumerable<object> GetTypedObjectForIUnknown_RoundtrippableType_TestData()
+ {
+ yield return new object();
+ yield return 10;
+ yield return "string";
+
+ yield return new NonGenericClass();
+ yield return new NonGenericStruct();
+ yield return Int32Enum.Value1;
+
+ MethodInfo method = typeof(GetTypedObjectForIUnknownTests).GetMethod(nameof(NonGenericMethod));
+ Delegate d = method.CreateDelegate(typeof(NonGenericDelegate));
+ yield return d;
+ }
+
+ public static IEnumerable<object[]> GetTypedObjectForIUnknown_TestData()
+ {
+ foreach (object o in GetTypedObjectForIUnknown_RoundtrippableType_TestData())
+ {
+ yield return new object[] { o, o.GetType() };
+ yield return new object[] { o, typeof(GenericClass<>).GetTypeInfo().GenericTypeParameters[0] };
+ yield return new object[] { o, typeof(int).MakeByRefType() };
+
+ Type baseType = o.GetType().BaseType;
+ while (baseType != null)
+ {
+ yield return new object[] { o, baseType };
+ baseType = baseType.BaseType;
+ }
+ }
+
+ yield return new object[] { new ClassWithInterface(), typeof(NonGenericInterface) };
+ yield return new object[] { new StructWithInterface(), typeof(NonGenericInterface) };
+
+ yield return new object[] { new GenericClass<string>(), typeof(object) };
+ yield return new object[] { new Dictionary<string, int>(), typeof(object) };
+ yield return new object[] { new GenericStruct<string>(), typeof(object) };
+ yield return new object[] { new GenericStruct<string>(), typeof(ValueType) };
+
+ yield return new object[] { new int[] { 10 }, typeof(object) };
+ yield return new object[] { new int[] { 10 }, typeof(Array) };
+
+ yield return new object[] { new int[][] { new int[] { 10 } }, typeof(object) };
+ yield return new object[] { new int[][] { new int[] { 10 } }, typeof(Array) };
+
+ yield return new object[] { new int[,] { { 10 } }, typeof(object) };
+ yield return new object[] { new int[,] { { 10 } }, typeof(Array) };
+
+ yield return new object[] { new KeyValuePair<string, int>("key", 10), typeof(object) };
+ yield return new object[] { new KeyValuePair<string, int>("key", 10), typeof(ValueType) };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetTypedObjectForIUnknown_TestData))]
[PlatformSpecific(TestPlatforms.Windows)]
- public void GetTypedObjectForIUnknown_GenericTypeParameter_ReturnsExpected()
+ public void GetTypedObjectForIUnknown_ValidPointer_ReturnsExpected(object o, Type type)
{
- Type type = typeof(GenericClass<>).GetTypeInfo().GenericTypeParameters[0];
- IntPtr iUnknown = Marshal.GetIUnknownForObject(new object());
+ IntPtr ptr = Marshal.GetIUnknownForObject(o);
try
{
- object typedObject = Marshal.GetTypedObjectForIUnknown(iUnknown, type);
- Assert.IsType<object>(typedObject);
+ Assert.Equal(o, Marshal.GetTypedObjectForIUnknown(ptr, type));
}
finally
{
- Marshal.Release(iUnknown);
+ Marshal.Release(ptr);
}
}
}
[Theory]
- [PlatformSpecific(TestPlatforms.Windows)]
[MemberData(nameof(GetTypedObjectForIUnknown_Invalid_TestData))]
+ [PlatformSpecific(TestPlatforms.Windows)]
public void GetTypedObjectForIUnknown_InvalidType_ThrowsArgumentException(Type type)
{
- IntPtr iUnknown = Marshal.GetIUnknownForObject(new object());
+ IntPtr ptr = Marshal.GetIUnknownForObject(new object());
try
{
- AssertExtensions.Throws<ArgumentException>("t", () => Marshal.GetTypedObjectForIUnknown(iUnknown, type));
+ AssertExtensions.Throws<ArgumentException>("t", () => Marshal.GetTypedObjectForIUnknown(ptr, type));
}
finally
{
- Marshal.Release(iUnknown);
+ Marshal.Release(ptr);
+ }
+ }
+
+ public static IEnumerable<object[]> GetTypedObjectForIUnknownType_UncastableObject_TestData()
+ {
+ yield return new object[] { new object(), typeof(AbstractClass) };
+ yield return new object[] { new object(), typeof(NonGenericClass) };
+ yield return new object[] { new object(), typeof(NonGenericStruct) };
+ yield return new object[] { new object(), typeof(NonGenericStruct) };
+ yield return new object[] { new object(), typeof(NonGenericInterface) };
+
+ yield return new object[] { new NonGenericClass(), typeof(IFormattable) };
+ yield return new object[] { new ClassWithInterface(), typeof(IFormattable) };
+
+ yield return new object[] { new object(), typeof(int).MakePointerType() };
+
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.RunAndCollect);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ Type collectibleType = typeBuilder.CreateType();
+ yield return new object[] { new object(), collectibleType };
+ }
+
+ [Theory]
+ [MemberData(nameof(GetTypedObjectForIUnknownType_UncastableObject_TestData))]
+ [PlatformSpecific(TestPlatforms.Windows)]
+ public void GetTypedObjectForIUnknown_UncastableObject_ThrowsInvalidCastException(object o, Type type)
+ {
+ IntPtr ptr = Marshal.GetIUnknownForObject(o);
+ try
+ {
+ Assert.Throws<InvalidCastException>(() => Marshal.GetTypedObjectForIUnknown(ptr, type));
+ }
+ finally
+ {
+ Marshal.Release(ptr);
}
}
+ public static IEnumerable<object[]> GetTypedObjectForIUnknown_ArrayObjects_TestData()
+ {
+ yield return new object[] { new int[] { 10 } };
+ yield return new object[] { new int[][] { new int[] { 10 } } };
+ yield return new object[] { new int[,] { { 10 } } };
+ }
+
[Theory]
+ [MemberData(nameof(GetTypedObjectForIUnknown_ArrayObjects_TestData))]
[PlatformSpecific(TestPlatforms.Windows)]
- [InlineData(typeof(AbstractClass))]
- [InlineData(typeof(NonGenericClass))]
- [InlineData(typeof(NonGenericStruct))]
- [InlineData(typeof(NonGenericInterface))]
- public void GetTypedObjectForIUnknown_UncastableType_ThrowsInvalidCastException(Type type)
+ public void GetTypedObjectForIUnknown_ArrayType_ThrowsBadImageFormatException(object o)
{
- IntPtr iUnknown = Marshal.GetIUnknownForObject(new object());
+ IntPtr ptr = Marshal.GetIUnknownForObject(o);
try
{
- Assert.Throws<InvalidCastException>(() => Marshal.GetTypedObjectForIUnknown(iUnknown, type));
+ Assert.Throws<BadImageFormatException>(() => Marshal.GetTypedObjectForIUnknown(ptr, o.GetType()));
}
finally
{
- Marshal.Release(iUnknown);
+ Marshal.Release(ptr);
}
}
+
+ public class ClassWithInterface : NonGenericInterface { }
+ public struct StructWithInterface : NonGenericInterface { }
+
+ public static void NonGenericMethod(int i) { }
+ public delegate void NonGenericDelegate(int i);
+
+ public enum Int32Enum : int { Value1, Value2 }
}
}
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
using System.Runtime.InteropServices.Tests.Common;
using Xunit;
{
public static IEnumerable<object[]> IsComObject_TestData()
{
+ yield return new object[] { new object() };
yield return new object[] { 0 };
yield return new object[] { "string" };
- yield return new object[] { new int[0] };
+
yield return new object[] { new NonGenericClass() };
yield return new object[] { new GenericClass<int>() };
+ yield return new object[] { new Dictionary<string, int>() };
yield return new object[] { new NonGenericStruct() };
yield return new object[] { new GenericStruct<string>() };
+ yield return new object[] { Int32Enum.Value1 };
+
+ yield return new object[] { new int[] { 10 } };
+ yield return new object[] { new int[][] { new int[] { 10 } } };
+ yield return new object[] { new int[,] { { 10 } } };
+
+ MethodInfo method = typeof(IsComObjectTests).GetMethod(nameof(NonGenericMethod));
+ Delegate d = method.CreateDelegate(typeof(NonGenericDelegate));
+ yield return new object[] { d };
+
+ yield return new object[] { new KeyValuePair<string, int>("key", 10) };
+
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.RunAndCollect);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ Type collectibleType = typeBuilder.CreateType();
+ object collectibleObject = Activator.CreateInstance(collectibleType);
+ yield return new object[] { collectibleObject };
+
+ ConstructorInfo comImportConstructor = typeof(ComImportAttribute).GetConstructor(new Type[0]);
+ var comImportAttributeBuilder = new CustomAttributeBuilder(comImportConstructor, new object[0]);
+
+ AssemblyBuilder comImportAssemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.RunAndCollect);
+ ModuleBuilder comImportModuleBuilder = comImportAssemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder comImportTypeBuilder = comImportModuleBuilder.DefineType("Type");
+ comImportTypeBuilder.SetCustomAttribute(comImportAttributeBuilder);
+
+ Type collectibleComImportObject = comImportTypeBuilder.CreateType();
+ yield return new object[] { collectibleComImportObject };
}
[Theory]
{
AssertExtensions.Throws<ArgumentNullException>("o", () => Marshal.IsComObject(null));
}
+
+ public static void NonGenericMethod(int i) { }
+ public delegate void NonGenericDelegate(int i);
+
+ public enum Int32Enum : int { Value1, Value2 }
}
}
// 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.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Reflection.Emit;
using Xunit;
namespace System.Runtime.InteropServices.Tests
public class OffsetOfTests
{
[Fact]
- public static void NullParameter()
+ public void OffsetOf_StructField_ReturnsExpected()
{
- Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(null, null));
- Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(new object().GetType(), null));
- Assert.Throws<ArgumentNullException>(() => Marshal.OffsetOf(null, "abcd"));
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(typeof(SomeStruct), nameof(SomeStruct.var)));
}
[Fact]
- public void NonExistField()
+ public void OffsetOf_ClassWithExplicitLayout_ReturnsExpected()
{
- Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(NonExistField), "NonExistField"));
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(typeof(MySystemTime), nameof(MySystemTime.wYear)));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(typeof(MySystemTime), nameof(MySystemTime.wHour)));
+ Assert.Equal(new IntPtr(14), Marshal.OffsetOf(typeof(MySystemTime), nameof(MySystemTime.wMilliseconds)));
}
[Fact]
- public void NoLayoutClass()
+ public void OffsetOf_ClassWithSequentialLayout_ReturnsExpected()
{
- Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(NoLayoutPoint), "x"));
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(typeof(MyPoint), nameof(MyPoint.x)));
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(typeof(MyPoint), nameof(MyPoint.y)));
}
[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()
+ public void OffsetOf_ExplicitLayout_ReturnsExpected()
{
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"));
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.m_short1)));
+ Assert.Equal(new IntPtr(2), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.m_short2)));
+
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union1_byte1)));
+ Assert.Equal(new IntPtr(5), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union1_byte2)));
+ Assert.Equal(new IntPtr(6), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union1_short1)));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union1_int1)));
+ Assert.Equal(new IntPtr(12), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union1_int2)));
+ Assert.Equal(new IntPtr(16), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union1_double1)));
+
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union2_ushort1)));
+ Assert.Equal(new IntPtr(6), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union2_ushort2)));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union3_int1)));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.union3_decimal1)));
+
+ Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.m_ushort1)));
+ Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.m_decimal1)));
+ Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.m_char1)));
}
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
- public void TestFieldAlignment_Windows()
+ public void OffsetOf_ValidField_ReturnsExpected()
{
Type t = typeof(FieldAlignmentTest);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
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"));
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_byte1)));
+ Assert.Equal(new IntPtr(2), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_short1)));
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_short2)));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_int1)));
+ Assert.Equal(new IntPtr(12), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_byte2)));
+ Assert.Equal(new IntPtr(16), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.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"));
+ Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_double1)));
+ Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_char1)));
+ Assert.Equal(new IntPtr(33), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_char2)));
+ Assert.Equal(new IntPtr(34), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_char3)));
+ Assert.Equal(new IntPtr(40), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_double2)));
+ Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_byte3)));
+ Assert.Equal(new IntPtr(49), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_byte4)));
+ Assert.Equal(new IntPtr(56), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_decimal1)));
+ Assert.Equal(new IntPtr(72), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.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"));
+ Assert.Equal(new IntPtr(20), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_double1)));
+ Assert.Equal(new IntPtr(28), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_char1)));
+ Assert.Equal(new IntPtr(29), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_char2)));
+ Assert.Equal(new IntPtr(30), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_char3)));
+ Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_double2)));
+ Assert.Equal(new IntPtr(40), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_byte3)));
+ Assert.Equal(new IntPtr(41), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_byte4)));
+ Assert.Equal(new IntPtr(48), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_decimal1)));
+ Assert.Equal(new IntPtr(64), Marshal.OffsetOf(t, nameof(FieldAlignmentTest.m_char4)));
}
}
[Fact]
- public void TestFieldAlignment_Decimal()
+ public void OffsetOf_Decimal_ReturnsExpected()
{
Type t = typeof(FieldAlignmentTest_Decimal);
Assert.Equal(88, Marshal.SizeOf(t));
}
- Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "b"));
- Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "p"));
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.b)));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.p)));
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.ProcessArchitecture != Architecture.X86))
{
- Assert.Equal(new IntPtr(88), Marshal.OffsetOf(t, "s"));
+ Assert.Equal(new IntPtr(88), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.s)));
}
else
{
- Assert.Equal(new IntPtr(80), Marshal.OffsetOf(t, "s"));
+ Assert.Equal(new IntPtr(80), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.s)));
}
}
[Fact]
- public void TestFieldAlignment_Guid()
+ public void OffsetOf_Guid_ReturnsExpected()
{
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"));
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Guid.b)));
+ Assert.Equal(new IntPtr(4), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Guid.g)));
+ Assert.Equal(new IntPtr(20), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Guid.s)));
}
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
- public void TestFieldAlignment_Variant()
+ public void OffsetOf_Variant_ReturnsExpected()
{
Type t = typeof(FieldAlignmentTest_Variant);
- Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, "b"));
- Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, "v"));
+ Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Variant.b)));
+ Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Variant.v)));
if (IntPtr.Size == 4)
{
- Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, "s"));
+ Assert.Equal(new IntPtr(24), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Variant.s)));
Assert.Equal(32, Marshal.SizeOf(t));
}
else if (IntPtr.Size == 8)
{
- Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, "s"));
+ Assert.Equal(new IntPtr(32), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Variant.s)));
Assert.Equal(40, Marshal.SizeOf(t));
}
else
}
[Fact]
- public void NonGenericOffEqualsGenericOffset()
+ public void OffsetOf_Generic_MatchedNonGeneric()
{
IntPtr nonGenericOffsetCall = Marshal.OffsetOf(typeof(SomeStruct), "var");
IntPtr genericOffsetCall = Marshal.OffsetOf<SomeStruct>("var");
Assert.Equal(nonGenericOffsetCall, genericOffsetCall);
+ }
+
+ [Fact]
+ public void OffsetOf_NullType_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("t", () => Marshal.OffsetOf(null, null));
+ AssertExtensions.Throws<ArgumentNullException>("t", () => Marshal.OffsetOf(null, "abcd"));
+ }
+
+ [Fact]
+ public void OffsetOf_NullFieldName_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>(null, () => Marshal.OffsetOf(new object().GetType(), null));
+ AssertExtensions.Throws<ArgumentNullException>(null, () => Marshal.OffsetOf<object>(null));
+ }
+
+ [Fact]
+ public void OffsetOf_NoSuchFieldName_ThrowsArgumentException()
+ {
+ AssertExtensions.Throws<ArgumentException>("fieldName", () => Marshal.OffsetOf(typeof(NonExistField), "NonExistField"));
+ AssertExtensions.Throws<ArgumentException>("fieldName", () => Marshal.OffsetOf<NonExistField>("NonExistField"));
+ }
+
+ [Fact]
+ public void OffsetOf_NonRuntimeField_ThrowsArgumentException()
+ {
+ AssertExtensions.Throws<ArgumentException>("fieldName", () => Marshal.OffsetOf(new NonRuntimeType(), "Field"));
+ }
- Assert.Throws<ArgumentException>(() => Marshal.OffsetOf(typeof(StructWithFxdLPSTRSAFld), "Arr"));
+ public static IEnumerable<object[]> OffsetOf_NotMarshallable_TestData()
+ {
+ yield return new object[] { typeof(StructWithFxdLPSTRSAFld), nameof(StructWithFxdLPSTRSAFld.Arr) };
+ }
+
+ [Theory]
+ [MemberData(nameof(OffsetOf_NotMarshallable_TestData))]
+ public void OffsetOf_NotMarshallable_ThrowsArgumentException(Type t, string fieldName)
+ {
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.OffsetOf(t, fieldName));
+ }
+
+ [Fact]
+ public void OffsetOf_NoLayoutPoint_ThrowsArgumentException()
+ {
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.OffsetOf(typeof(NoLayoutPoint), nameof(NoLayoutPoint.x)));
+ AssertExtensions.Throws<ArgumentException>(null, () => Marshal.OffsetOf<NoLayoutPoint>(nameof(NoLayoutPoint.x)));
+ }
+
+ public class NonRuntimeType : Type
+ {
+ public override FieldInfo GetField(string name, BindingFlags bindingAttr)
+ {
+ return new NonRuntimeFieldInfo();
+ }
+
+ public override Assembly Assembly => throw new NotImplementedException();
+
+ public override string AssemblyQualifiedName => throw new NotImplementedException();
+
+ public override Type BaseType => throw new NotImplementedException();
+
+ public override string FullName => throw new NotImplementedException();
+
+ public override Guid GUID => throw new NotImplementedException();
+
+ public override Module Module => throw new NotImplementedException();
+
+ public override string Namespace => throw new NotImplementedException();
+
+ public override Type UnderlyingSystemType => throw new NotImplementedException();
+
+ public override string Name => throw new NotImplementedException();
+
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override object[] GetCustomAttributes(bool inherit) => throw new NotImplementedException();
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotImplementedException();
+
+ public override Type GetElementType() => throw new NotImplementedException();
+
+ public override EventInfo GetEvent(string name, BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override Type GetInterface(string name, bool ignoreCase) => throw new NotImplementedException();
+
+ public override Type[] GetInterfaces() => throw new NotImplementedException();
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override Type GetNestedType(string name, BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => throw new NotImplementedException();
+
+ public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters) => throw new NotImplementedException();
+
+ public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException();
+
+ protected override TypeAttributes GetAttributeFlagsImpl() => throw new NotImplementedException();
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotImplementedException();
+
+ protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) => throw new NotImplementedException();
+
+ protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) => throw new NotImplementedException();
+
+ protected override bool HasElementTypeImpl() => throw new NotImplementedException();
+
+ protected override bool IsArrayImpl() => throw new NotImplementedException();
+
+ protected override bool IsByRefImpl() => throw new NotImplementedException();
+
+ protected override bool IsCOMObjectImpl() => throw new NotImplementedException();
+
+ protected override bool IsPointerImpl() => throw new NotImplementedException();
+
+ protected override bool IsPrimitiveImpl() => throw new NotImplementedException();
+ }
+
+ public class NonRuntimeFieldInfo : FieldInfo
+ {
+ public override FieldAttributes Attributes => throw new NotImplementedException();
+
+ public override RuntimeFieldHandle FieldHandle => throw new NotImplementedException();
+
+ public override Type FieldType => throw new NotImplementedException();
+
+ public override Type DeclaringType => throw new NotImplementedException();
+
+ public override string Name => throw new NotImplementedException();
+
+ public override Type ReflectedType => throw new NotImplementedException();
+
+ public override object[] GetCustomAttributes(bool inherit) => throw new NotImplementedException();
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotImplementedException();
+
+ public override object GetValue(object obj) => throw new NotImplementedException();
+
+ public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException();
+
+ public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) => throw new NotImplementedException();
}
}
+
#pragma warning disable 169, 649, 618
[StructLayout(LayoutKind.Sequential)]
public struct StructWithFxdLPSTRSAFld
{
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 0)]
- public String[] Arr;
+ public string[] Arr;
}
public struct SomeStruct
[FieldOffset(6)]
public short union1_short1; // 2 bytes
[FieldOffset(8)]
- public Int32 union1_int1; // 4 bytes
+ public int union1_int1; // 4 bytes
[FieldOffset(12)]
- public Int32 union1_int2; // 4 bytes
+ public int union1_int2; // 4 bytes
[FieldOffset(16)]
public double union1_double1; // 8 bytes
[FieldOffset(6)]
public ushort union2_ushort2; // 2 bytes
[FieldOffset(8)]
- public Int32 union3_int1; // 4 bytes
+ public int union3_int1; // 4 bytes
[FieldOffset(8)]
public decimal union3_decimal1; // 16 bytes
public short m_short2; // 2 bytes
// 2 bytes of padding
- public Int32 m_int1; // 4 bytes
+ public int m_int1; // 4 bytes
public byte m_byte2; // 1 byte
// 3 bytes of padding
- public Int32 m_int2; // 4 bytes
+ public int 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
// 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.Collections.Generic;
using System.Globalization;
using System.Reflection;
using Xunit;
// 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.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices.Tests.Common;
using Xunit;
namespace System.Runtime.InteropServices.Tests
{
public class PtrToStructureTests
{
+ [Fact]
+ public void StructureToPtr_NonGenericType_ReturnsExpected()
+ {
+ var structure = new SomeTestStruct
+ {
+ i = 10,
+ s = "hello"
+ };
+
+ int size = Marshal.SizeOf(structure);
+ IntPtr ptr = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr(structure, ptr, false);
+
+ SomeTestStruct result = Assert.IsType<SomeTestStruct>(Marshal.PtrToStructure(ptr, typeof(SomeTestStruct)));
+ Assert.Equal(10, result.i);
+ Assert.Equal("hello", result.s);
+ }
+ finally
+ {
+ Marshal.DestroyStructure(ptr, structure.GetType());
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+
+ [Fact]
+ public void StructureToPtr_GenericType_ReturnsExpected()
+ {
+ var structure = new SomeTestStruct
+ {
+ i = 10,
+ s = "hello"
+ };
+
+ int size = Marshal.SizeOf(structure);
+ IntPtr ptr = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr(structure, ptr, false);
+
+ SomeTestStruct result = Marshal.PtrToStructure<SomeTestStruct>(ptr);
+ Assert.Equal(10, result.i);
+ Assert.Equal("hello", result.s);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+
+ [Fact]
+ public void StructureToPtr_NonGenericObject_ReturnsExpected()
+ {
+ var structure = new SomeTestStruct
+ {
+ i = 10,
+ s = "hello"
+ };
+
+ int size = Marshal.SizeOf(structure);
+ IntPtr ptr = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr(structure, ptr, false);
+
+ var result = new SequentialClass();
+ Marshal.PtrToStructure(ptr, (object)result);
+ Assert.Equal(10, result.i);
+ Assert.Equal("hello", result.s);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+
+ [Fact]
+ public void StructureToPtr_GenericObject_ReturnsExpected()
+ {
+ var structure = new SomeTestStruct
+ {
+ i = 10,
+ s = "hello"
+ };
+
+ int size = Marshal.SizeOf(structure);
+ IntPtr ptr = Marshal.AllocHGlobal(size);
+ try
+ {
+ Marshal.StructureToPtr(structure, ptr, false);
+
+ var result = new SequentialClass();
+ Marshal.PtrToStructure(ptr, result);
+ Assert.Equal(10, result.i);
+ Assert.Equal("hello", result.s);
+ }
+ finally
+ {
+ Marshal.DestroyStructure(ptr, structure.GetType());
+ Marshal.FreeHGlobal(ptr);
+ }
+ }
+
+ [Fact]
+ public void PtrToStructure_ZeroPointerWithType_ReturnsNull()
+ {
+ Assert.Null(Marshal.PtrToStructure(IntPtr.Zero, typeof(SomeTestStruct)));
+ Assert.Null(Marshal.PtrToStructure<NonGenericClass>(IntPtr.Zero));
+ Assert.Throws<NullReferenceException>(() => Marshal.PtrToStructure<SomeTestStruct>(IntPtr.Zero));
+ }
+
+ [Fact]
+ public void PtrToStructure_ZeroPointer_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStructure(IntPtr.Zero, (object)new SomeTestStruct()));
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.PtrToStructure(IntPtr.Zero, new SomeTestStruct()));
+ }
+
+ [Fact]
+ public void PtrToStructure_NullStructure_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.PtrToStructure((IntPtr)1, (object)null));
+ AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.PtrToStructure<object>((IntPtr)1, null));
+ }
+
+ public static IEnumerable<object[]> PtrToStructure_GenericClass_TestData()
+ {
+ yield return new object[] { new GenericClass<string>() };
+ yield return new object[] { new GenericStruct<string>() };
+ }
+
+ [Theory]
+ [MemberData(nameof(PtrToStructure_GenericClass_TestData))]
+ public void PtrToStructure_GenericObject_ThrowsArgumentException(object o)
+ {
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.PtrToStructure((IntPtr)1, o));
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.PtrToStructure<object>((IntPtr)1, o));
+ }
+
+ public static IEnumerable<object[]> PtrToStructure_ObjectNotValueClass_TestData()
+ {
+ yield return new object[] { new NonGenericStruct() };
+ yield return new object[] { Int32Enum.Value1 };
+ }
+
+ [Theory]
+ [MemberData(nameof(PtrToStructure_ObjectNotValueClass_TestData))]
+ public void PtrToStructure_ObjectNotValueClass_ThrowsArgumentException(object structure)
+ {
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.PtrToStructure((IntPtr)1, structure));
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.PtrToStructure<object>((IntPtr)1, structure));
+ }
+
+ public static IEnumerable<object[]> PtrToStructure_ObjectNotBlittable_TestData()
+ {
+ yield return new object[] { new NonGenericClass() };
+ }
+
+ [Theory]
+ [MemberData(nameof(PtrToStructure_ObjectNotBlittable_TestData))]
+ public void PtrToStructure_ObjectNoBlittable_ThrowsArgumentException(object structure)
+ {
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.PtrToStructure((IntPtr)1, structure));
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.PtrToStructure<object>((IntPtr)1, structure));
+ }
+
+ [Fact]
+ public void PtrToStructure_NullStructureType_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("structureType", () => Marshal.PtrToStructure((IntPtr)1, null));
+ }
+
+ public static IEnumerable<object[]> PtrToStructure_GenericType_TestData()
+ {
+ yield return new object[] { typeof(GenericClass<string>) };
+ yield return new object[] { typeof(GenericClass<>) };
+ yield return new object[] { typeof(GenericStruct<string>) };
+ yield return new object[] { typeof(GenericStruct<>) };
+ yield return new object[] { typeof(GenericInterface<string>) };
+ yield return new object[] { typeof(GenericInterface<>) };
+ }
+
+ [Theory]
+ [MemberData(nameof(PtrToStructure_GenericType_TestData))]
+ public void PtrToStructure_GenericType_ThrowsArgumentException(Type structureType)
+ {
+ AssertExtensions.Throws<ArgumentException>("structureType", () => Marshal.PtrToStructure((IntPtr)1, structureType));
+ }
+
+ [Fact]
+ public void PtrToStructure_NonRuntimeType_ThrowsArgumentException()
+ {
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.Run);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ AssertExtensions.Throws<ArgumentException>("structureType", "type", () => Marshal.PtrToStructure((IntPtr)1, (Type)typeBuilder));
+ }
+
+ public static IEnumerable<object[]> PtrToStructure_NonBlittableType_TestData()
+ {
+ yield return new object[] { typeof(AutoLayoutStruct) };
+ yield return new object[] { typeof(NonGenericClass) };
+ yield return new object[] { typeof(AbstractClass) };
+ }
+
+ [Theory]
+ [MemberData(nameof(PtrToStructure_NonBlittableType_TestData))]
+ public void PtrToStructure_NonBlittablType_ThrowsArgumentException(Type structureType)
+ {
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.PtrToStructure((IntPtr)1, structureType));
+ }
+
+ public static IEnumerable<object[]> PtrToStructure_CantCreateType_TestData()
+ {
+ yield return new object[] { typeof(GenericClass<>).GetTypeInfo().GenericTypeParameters[0], typeof(ArgumentException) };
+ yield return new object[] { typeof(int).MakePointerType(), typeof(MissingMethodException) };
+ yield return new object[] { typeof(int).MakeByRefType(), typeof(MissingMethodException) };
+ }
+
+ [Theory]
+ [MemberData(nameof(PtrToStructure_CantCreateType_TestData))]
+ public void PtrToStructure_CantCreateType_ThrowsArgumentException(Type structureType, Type exceptionType)
+ {
+ Assert.Throws(exceptionType, () => Marshal.PtrToStructure((IntPtr)1, structureType));
+ }
+
[StructLayout(LayoutKind.Sequential)]
public struct SomeTestStruct
{
public int i;
- public String s;
+ public string s;
}
- [Fact]
- public void PtrToStructureTest()
+ [StructLayout(LayoutKind.Auto)]
+ public struct AutoLayoutStruct
{
- 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));
+ public int i;
+ }
- ip = new IntPtr(123);
- Assert.Throws<ArgumentException>(() => Marshal.PtrToStructure<SomeTestStruct>(ip, someTestStruct));
+ [StructLayout(LayoutKind.Sequential)]
+ public class SequentialClass
+ {
+ public int i;
+ public string s;
}
+
+ public enum Int32Enum : int { Value1, Value2 }
}
}
// 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.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices.Tests.Common;
using Xunit;
namespace System.Runtime.InteropServices.Tests
{
public class SizeOfTests
{
+ [Fact]
+ public void SizeOf_StructWithEnumArray_ReturnsExpected()
+ {
+ var s = new TestStructWithEnumArray
+ {
+ ArrayOfEnum = new TestEnum[] { TestEnum.Red, TestEnum.Green, TestEnum.Blue }
+ };
+
+ Assert.Equal(12, Marshal.SizeOf((object)s));
+ Assert.Equal(12, Marshal.SizeOf(s));
+ Assert.Equal(12, Marshal.SizeOf(typeof(TestStructWithEnumArray)));
+ Assert.Equal(12, Marshal.SizeOf<TestStructWithEnumArray>());
+ }
+
+ [Fact]
+ public void SizeOf_Object_ReturnsExpected()
+ {
+ SomeTestStruct someTestStruct = new SomeTestStruct();
+ Assert.NotEqual(0, Marshal.SizeOf(someTestStruct.GetType()));
+ }
+
+ [Fact]
+ public void SizeOf_Pointer_ReturnsExpected()
+ {
+ Assert.Equal(IntPtr.Size, Marshal.SizeOf(typeof(int).MakePointerType()));
+ }
+
+ [Fact]
+ public void SizeOf_NullType_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("t", () => Marshal.SizeOf(null));
+ }
+
+ [Fact]
+ public void SizeOf_NullStructure_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.SizeOf((object)null));
+ AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.SizeOf<string>(null));
+ }
+
+ public static IEnumerable<object[]> SizeOf_InvalidType_TestData()
+ {
+ yield return new object[] { typeof(int).MakeByRefType(), null };
+
+ yield return new object[] { typeof(GenericClass<>), "t" };
+ yield return new object[] { typeof(GenericClass<string>), "t" };
+ yield return new object[] { typeof(GenericStruct<>), "t" };
+ yield return new object[] { typeof(GenericStruct<string>), "t" };
+ yield return new object[] { typeof(GenericInterface<>), "t" };
+ yield return new object[] { typeof(GenericInterface<string>), "t" };
+
+ yield return new object[] { typeof(GenericClass<>).GetTypeInfo().GenericTypeParameters[0], null };
+
+ AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Assembly"), AssemblyBuilderAccess.Run);
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");
+ TypeBuilder typeBuilder = moduleBuilder.DefineType("Type");
+ yield return new object[] { typeBuilder, "t" };
+
+ yield return new object[] { typeof(TestStructWithFxdLPSTRSAFld), null };
+ }
+
+ [Theory]
+ [MemberData(nameof(SizeOf_InvalidType_TestData))]
+ public void SizeOf_InvalidType_ThrowsArgumentException(Type type, string paramName)
+ {
+ AssertExtensions.Throws<ArgumentException>(paramName, () => Marshal.SizeOf(type));
+ }
+
public struct TestStructWithEnumArray
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public enum TestEnum
{
- red,
- green,
- blue
+ Red,
+ Green,
+ Blue
}
[StructLayout(LayoutKind.Sequential)]
public struct SomeTestStruct
{
public int i;
- public String s;
+ 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());
+ public string[] Arr;
}
}
}
// 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.Collections.Generic;
+using System.Runtime.InteropServices.Tests.Common;
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()
+ public void StructureToPtr_ByValBoolArray_Success()
{
var structure1 = new StructWithBoolArray()
{
- array = new bool[]
- {
- true,true,true,true
- }
+ array = new bool[] { true, true, true, true }
};
int size = Marshal.SizeOf(structure1);
- IntPtr memory = Marshal.AllocHGlobal(size + sizeof(Int32));
-
+ IntPtr memory = Marshal.AllocHGlobal(size + sizeof(int));
try
{
Marshal.WriteInt32(memory, size, 0xFF);
}
[Fact]
- public void VerifyByValArrayInStruct()
+ public void StructureToPtr_ByValArrayInStruct_Success()
{
- // equal
- var structure1 = new StructWithByValArray()
+ var structure = new StructWithByValArray()
{
array = new StructWithIntField[]
{
new StructWithIntField { value = 5 }
}
};
- int size = Marshal.SizeOf(structure1);
+ int size = Marshal.SizeOf(structure);
IntPtr memory = Marshal.AllocHGlobal(size);
try
{
- Marshal.StructureToPtr(structure1, memory, false);
- Marshal.StructureToPtr(structure1, memory, true);
+ Marshal.StructureToPtr(structure, memory, false);
+ Marshal.StructureToPtr(structure, memory, true);
}
finally
{
Marshal.FreeHGlobal(memory);
}
+ }
- // underflow
- var structure2 = new StructWithByValArray()
+ [Fact]
+ public void StructureToPtr_OverflowByValArrayInStruct_Success()
+ {
+ var structure = new StructWithByValArray()
{
array = new StructWithIntField[]
{
new StructWithIntField { value = 1 },
new StructWithIntField { value = 2 },
new StructWithIntField { value = 3 },
- new StructWithIntField { value = 4 }
+ new StructWithIntField { value = 4 },
+ new StructWithIntField { value = 5 },
+ new StructWithIntField { value = 6 }
}
};
- size = Marshal.SizeOf(structure2);
- memory = Marshal.AllocHGlobal(size);
+
+ int size = Marshal.SizeOf(structure);
+ IntPtr memory = Marshal.AllocHGlobal(size);
try
{
- Assert.Throws<ArgumentException>(() => Marshal.StructureToPtr(structure2, memory, false));
- Assert.Throws<ArgumentException>(() => Marshal.StructureToPtr(structure2, memory, true));
+ Marshal.StructureToPtr(structure, memory, false);
+ Marshal.StructureToPtr(structure, memory, true);
}
finally
{
Marshal.FreeHGlobal(memory);
}
+ }
- // overflow
- var structure3 = new StructWithByValArray()
+ [Fact]
+ public void StructureToPtr_ByValDateArray_Success()
+ {
+ var structure = new StructWithDateArray()
{
- array = new StructWithIntField[]
+ array = new DateTime[]
{
- new StructWithIntField { value = 1 },
- new StructWithIntField { value = 2 },
- new StructWithIntField { value = 3 },
- new StructWithIntField { value = 4 },
- new StructWithIntField { value = 5 },
- new StructWithIntField { value = 6 }
+ DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now
}
};
- size = Marshal.SizeOf(structure3);
- memory = Marshal.AllocHGlobal(size);
+ int size = Marshal.SizeOf(structure);
+ IntPtr memory = Marshal.AllocHGlobal(size);
try
{
- Marshal.StructureToPtr(structure3, memory, false);
- Marshal.StructureToPtr(structure3, memory, true);
+ Marshal.StructureToPtr(structure, memory, false);
+ Marshal.StructureToPtr(structure, memory, true);
}
finally
{
+ Marshal.DestroyStructure(memory, structure.GetType());
Marshal.FreeHGlobal(memory);
}
}
[Fact]
- public void VerfiyByValDateArray()
+ public void StructureToPtr_NullPtr_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.StructureToPtr((object)new SomeTestStruct_Auto(), IntPtr.Zero, fDeleteOld: true));
+ AssertExtensions.Throws<ArgumentNullException>("ptr", () => Marshal.StructureToPtr(new SomeTestStruct_Auto(), IntPtr.Zero, fDeleteOld: true));
+ }
+
+ [Fact]
+ public void StructureToPtr_NullStructure_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.StructureToPtr(null, (IntPtr)1, fDeleteOld: true));
+ AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.StructureToPtr<object>(null, (IntPtr)1, fDeleteOld: true));
+ }
+
+ public static IEnumerable<object[]> StructureToPtr_GenericClass_TestData()
+ {
+ yield return new object[] { new GenericClass<string>() };
+ yield return new object[] { new GenericStruct<string>() };
+ }
+
+ [Theory]
+ [MemberData(nameof(StructureToPtr_GenericClass_TestData))]
+ public void StructureToPtr_GenericObject_ThrowsArgumentException(object o)
+ {
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.StructureToPtr(o, (IntPtr)1, fDeleteOld: true));
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.StructureToPtr<object>(o, (IntPtr)1, fDeleteOld: true));
+ }
+
+ public static IEnumerable<object[]> StructureToPtr_NonBlittableObject_TestData()
+ {
+ yield return new object[] { new NonGenericClass() };
+ yield return new object[] { "string" };
+ }
+
+ [Theory]
+ [MemberData(nameof(StructureToPtr_NonBlittableObject_TestData))]
+ public void StructureToPtr_NonBlittable_ThrowsArgumentException(object o)
{
- var structure1 = new StructWithDateArray()
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.StructureToPtr(o, (IntPtr)1, fDeleteOld: true));
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.StructureToPtr<object>(o, (IntPtr)1, fDeleteOld: true));
+ }
+
+ [Fact]
+ public void StructureToPtr_AutoLayout_ThrowsArgumentException()
+ {
+ var someTs_Auto = new SomeTestStruct_Auto();
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.StructureToPtr((object)someTs_Auto, (IntPtr)1, fDeleteOld: true));
+ AssertExtensions.Throws<ArgumentException>("structure", () => Marshal.StructureToPtr(someTs_Auto, (IntPtr)1, fDeleteOld: true));
+ }
+
+ [Fact]
+ public void StructureToPtr_InvalidLengthByValArrayInStruct_ThrowsArgumentException()
+ {
+ var structure = new StructWithByValArray
{
- array = new DateTime[]
+ array = new StructWithIntField[]
{
- DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now , DateTime.Now, DateTime.Now
+ new StructWithIntField { value = 1 },
+ new StructWithIntField { value = 2 },
+ new StructWithIntField { value = 3 },
+ new StructWithIntField { value = 4 }
}
};
-
- int size = Marshal.SizeOf(structure1);
+ int size = Marshal.SizeOf(structure);
IntPtr memory = Marshal.AllocHGlobal(size);
try
{
- Marshal.StructureToPtr(structure1, memory, false);
- Marshal.StructureToPtr(structure1, memory, true);
+ Assert.Throws<ArgumentException>(() => Marshal.StructureToPtr(structure, memory, false));
+ Assert.Throws<ArgumentException>(() => Marshal.StructureToPtr(structure, memory, true));
}
finally
{
Marshal.FreeHGlobal(memory);
}
}
+
+ 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;
+ }
}
}
public class UnsafeAddrOfPinnedArrayElementTests
{
[Fact]
- public void NullParameter()
+ public void UnsafeAddrOfPinnedArrayElement_NonGenericPrimitiveArray_ReturnsExpected()
{
- int[] array = null;
- AssertExtensions.Throws<ArgumentNullException>("arr", () => Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 0));
- }
-
- [Fact]
- public void PrimitiveType()
- {
- int[] array = new int[] { 1, 2, 3 };
+ Array array = new int[] { 1, 2, 3 };
GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
try
{
- IntPtr v0 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 0);
+ IntPtr v0 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0);
Assert.Equal(1, Marshal.ReadInt32(v0));
- IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 1);
+ IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 1);
Assert.Equal(2, Marshal.ReadInt32(v1));
- IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement<int>(array, 2);
+ IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 2);
Assert.Equal(3, Marshal.ReadInt32(v2));
}
finally
}
}
+ [Fact]
+ public void UnsafeAddrOfPinnedArrayElement_NonGenericStructureArray_ReturnsExpected()
+ {
+ Array 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(array, 0);
+ Point p0 = Marshal.PtrToStructure<Point>(v0);
+ Assert.Equal(100, p0.x);
+ Assert.Equal(100, p0.y);
+
+ IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 1);
+ Point p1 = Marshal.PtrToStructure<Point>(v1);
+ Assert.Equal(-1, p1.x);
+ Assert.Equal(-1, p1.y);
- struct Point
+ IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 2);
+ Point p2 = Marshal.PtrToStructure<Point>(v2);
+ Assert.Equal(0, p2.x);
+ Assert.Equal(0, p2.y);
+ }
+ finally
+ {
+ handle.Free();
+ }
+ }
+
+ [Fact]
+ public void UnsafeAddrOfPinnedArrayElement_GenericPrimitiveArray_ReturnsExpected()
{
- public int x;
- public int y;
+ var array = new int[] { 1, 2, 3 };
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ try
+ {
+ IntPtr v0 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 0);
+ Assert.Equal(1, Marshal.ReadInt32(v0));
+
+ IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 1);
+ Assert.Equal(2, Marshal.ReadInt32(v1));
+
+ IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 2);
+ Assert.Equal(3, Marshal.ReadInt32(v2));
+ }
+ finally
+ {
+ handle.Free();
+ }
}
[Fact]
- public void StructType()
+ public void UnsafeAddrOfPinnedArrayElement_GenericStructureArray_ReturnsExpected()
{
- Point[] array = new Point[]{
- new Point(){x = 100, y = 100},
- new Point(){x = -1, y = -1},
- new Point(){x = 0, y = 0},
+ var 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);
+ IntPtr v0 = Marshal.UnsafeAddrOfPinnedArrayElement(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);
+ IntPtr v1 = Marshal.UnsafeAddrOfPinnedArrayElement(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);
+ IntPtr v2 = Marshal.UnsafeAddrOfPinnedArrayElement(array, 2);
Point p2 = Marshal.PtrToStructure<Point>(v2);
Assert.Equal(0, p2.x);
Assert.Equal(0, p2.y);
handle.Free();
}
}
+
+ [Fact]
+ public void UnsafeAddrOfPinnedArrayElement_NullArray_ThrowsArgumentNullException()
+ {
+ AssertExtensions.Throws<ArgumentNullException>("arr", () => Marshal.UnsafeAddrOfPinnedArrayElement(null, 0));
+ AssertExtensions.Throws<ArgumentNullException>("arr", () => Marshal.UnsafeAddrOfPinnedArrayElement((int[])null, 0));
+ }
+
+ public struct Point
+ {
+ public int x;
+ public int y;
+ }
}
}