mirror of https://github.com/dahall/Vanara.git
431 lines
15 KiB
C#
431 lines
15 KiB
C#
using NUnit.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using Vanara.InteropServices;
|
|
using Vanara.PInvoke;
|
|
|
|
namespace Vanara.Extensions.Tests
|
|
{
|
|
[TestFixture()]
|
|
public class InteropExtensionsTests
|
|
{
|
|
private readonly int intSz = Marshal.SizeOf(typeof(int));
|
|
|
|
[Test()]
|
|
public void IsBlittableTest()
|
|
{
|
|
Assert.That(typeof(int).IsBlittable(), Is.True);
|
|
Assert.That(typeof(Guid).IsBlittable(), Is.True);
|
|
Assert.That(typeof(RECT).IsBlittable(), Is.True);
|
|
Assert.That(typeof(TypeCode).IsBlittable(), Is.True);
|
|
Assert.That(typeof(PRECT).IsBlittable(), Is.True);
|
|
Assert.That(typeof(int[]).IsBlittable(), Is.True);
|
|
Assert.That(typeof(RECT[]).IsBlittable(), Is.True);
|
|
Assert.That(typeof(decimal).IsBlittable(), Is.True);
|
|
Assert.That(typeof(bool).IsBlittable(), Is.True);
|
|
Assert.That(typeof(DateTime).IsBlittable(), Is.False);
|
|
Assert.That(typeof(string).IsBlittable(), Is.False);
|
|
Assert.That(typeof(string[]).IsBlittable(), Is.False);
|
|
Assert.That(typeof(AbsClass).IsBlittable(), Is.False);
|
|
Assert.That(typeof(IDisposable).IsBlittable(), Is.False);
|
|
//Assert.That(typeof(int[][]).IsBlittable(), Is.False);
|
|
Assert.That(typeof(RECT?).IsBlittable(), Is.False);
|
|
}
|
|
|
|
[Test()]
|
|
public void IsNullableTest()
|
|
{
|
|
Assert.That(typeof(int).IsNullable(), Is.False);
|
|
Assert.That(typeof(RECT?).IsNullable(), Is.True);
|
|
Assert.That(typeof(int?).IsNullable(), Is.True);
|
|
}
|
|
|
|
[Test()]
|
|
public void MarshalToPtrTest()
|
|
{
|
|
var h = new SafeHGlobalHandle(Marshal.SizeOf(typeof(RECT)) * 2 + intSz);
|
|
var rs = new[] { new RECT(), new RECT(10, 11, 12, 13) };
|
|
((IntPtr)h).Write(rs, intSz, h.Size);
|
|
Assert.That(Marshal.ReadInt32((IntPtr)h, 4 * intSz) == 0);
|
|
Assert.That(Marshal.ReadInt32((IntPtr)h, 5 * intSz) == 10);
|
|
Assert.That(Marshal.ReadInt32((IntPtr)h, 7 * intSz) == 12);
|
|
var ro = ((IntPtr)h).ToArray<RECT>(2, intSz);
|
|
Assert.That(ro.Length == 2);
|
|
Assert.That(ro[0].left == 0);
|
|
Assert.That(ro[1].right == 12);
|
|
}
|
|
|
|
[Test()]
|
|
public void MarshalToPtrTest1()
|
|
{
|
|
var h = IntPtr.Zero;
|
|
try
|
|
{
|
|
var rs = new[] { new RECT(), new RECT(10, 11, 12, 13) };
|
|
h = rs.MarshalToPtr(Marshal.AllocHGlobal, out var a, intSz);
|
|
Assert.That(h, Is.Not.EqualTo(IntPtr.Zero));
|
|
Assert.That(a, Is.EqualTo(Marshal.SizeOf(typeof(RECT)) * rs.Length + intSz));
|
|
Assert.That(Marshal.ReadInt32(h, 4 * intSz) == 0);
|
|
Assert.That(Marshal.ReadInt32(h, 5 * intSz) == 10);
|
|
Assert.That(Marshal.ReadInt32(h, 7 * intSz) == 12);
|
|
var ro = h.ToArray<RECT>(rs.Length, intSz);
|
|
Assert.That(ro.Length == 2);
|
|
Assert.That(ro[0].left == 0);
|
|
Assert.That(ro[1].right == 12);
|
|
Marshal.FreeHGlobal(h);
|
|
|
|
h = new RECT[0].MarshalToPtr(Marshal.AllocHGlobal, out a, intSz);
|
|
Assert.That(h, Is.Not.EqualTo(IntPtr.Zero));
|
|
Assert.That(a, Is.EqualTo(intSz));
|
|
|
|
Assert.That(() => new DateTime[1].MarshalToPtr(Marshal.AllocHGlobal, out a, intSz), Throws.Exception);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(h);
|
|
}
|
|
}
|
|
|
|
[Test()]
|
|
public void MarshalToPtrTest2()
|
|
{
|
|
var h = IntPtr.Zero;
|
|
try
|
|
{
|
|
var rs = new[] { "str1", "str2", "str3" };
|
|
h = rs.MarshalToPtr(StringListPackMethod.Concatenated, Marshal.AllocHGlobal, out var a, CharSet.Unicode, intSz);
|
|
Assert.That(h, Is.Not.EqualTo(IntPtr.Zero));
|
|
var chSz = 2;
|
|
Assert.That(a, Is.EqualTo(chSz * (rs[0].Length + 1) * rs.Length + chSz + intSz));
|
|
var ro = h.ToArray<byte>(a - intSz, intSz);
|
|
var chars = System.Text.Encoding.Unicode.GetChars(ro);
|
|
Assert.That(chars.Length, Is.EqualTo((a - intSz) / chSz));
|
|
Assert.That(chars[0], Is.EqualTo('s'));
|
|
Assert.That(chars[4], Is.EqualTo('\0'));
|
|
Assert.That(chars[chars.Length - 2], Is.EqualTo('\0'));
|
|
Assert.That(chars[chars.Length - 1], Is.EqualTo('\0'));
|
|
Marshal.FreeHGlobal(h);
|
|
|
|
h = rs.MarshalToPtr(StringListPackMethod.Concatenated, Marshal.AllocHGlobal, out a, CharSet.Ansi, intSz);
|
|
Assert.That(h, Is.Not.EqualTo(IntPtr.Zero));
|
|
chSz = 1;
|
|
Assert.That(a, Is.EqualTo(chSz * (rs[0].Length + 1) * rs.Length + chSz + intSz));
|
|
ro = h.ToArray<byte>(a - intSz, intSz);
|
|
chars = System.Text.Encoding.ASCII.GetChars(ro);
|
|
Assert.That(chars.Length, Is.EqualTo((a - intSz) / chSz));
|
|
Assert.That(chars[0], Is.EqualTo('s'));
|
|
Assert.That(chars[4], Is.EqualTo('\0'));
|
|
Assert.That(chars[chars.Length - 2], Is.EqualTo('\0'));
|
|
Assert.That(chars[chars.Length - 1], Is.EqualTo('\0'));
|
|
Marshal.FreeHGlobal(h);
|
|
|
|
h = new string[0].MarshalToPtr(StringListPackMethod.Concatenated, Marshal.AllocHGlobal, out a, CharSet.Unicode, intSz);
|
|
Assert.That(h, Is.Not.EqualTo(IntPtr.Zero));
|
|
Assert.That(a, Is.EqualTo(intSz + 2));
|
|
|
|
Assert.That(() => new[] { "" }.MarshalToPtr(StringListPackMethod.Concatenated, Marshal.AllocHGlobal, out a, CharSet.Unicode, intSz), Throws.ArgumentException);
|
|
Assert.That(() => new string[] { null }.MarshalToPtr(StringListPackMethod.Concatenated, Marshal.AllocHGlobal, out a, CharSet.Unicode, intSz), Throws.ArgumentException);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(h);
|
|
}
|
|
}
|
|
|
|
[Test()]
|
|
public void MarshalToPtrTest3()
|
|
{
|
|
var h = IntPtr.Zero;
|
|
try
|
|
{
|
|
var rs = new[] { "str1", "str2", "str3" };
|
|
h = rs.MarshalToPtr(StringListPackMethod.Packed, Marshal.AllocHGlobal, out var a, CharSet.Unicode, intSz);
|
|
Assert.That(h, Is.Not.EqualTo(IntPtr.Zero));
|
|
var chSz = 2;
|
|
Assert.That(a, Is.EqualTo(chSz * (rs[0].Length + 1) * rs.Length + ((rs.Length + 1) * IntPtr.Size) + intSz));
|
|
var ro = h.ToIEnum<IntPtr>(rs.Length, intSz).ToArray();
|
|
Assert.That(ro, Has.None.EqualTo(IntPtr.Zero));
|
|
for (var i = 0; i < ro.Length; i++)
|
|
Assert.That(StringHelper.GetString(ro[i], CharSet.Unicode), Is.EqualTo(rs[i]));
|
|
Marshal.FreeHGlobal(h);
|
|
|
|
h = rs.MarshalToPtr(StringListPackMethod.Packed, Marshal.AllocHGlobal, out a, CharSet.Ansi, intSz);
|
|
Assert.That(h, Is.Not.EqualTo(IntPtr.Zero));
|
|
chSz = 1;
|
|
Assert.That(a, Is.EqualTo(chSz * (rs[0].Length + 1) * rs.Length + ((rs.Length + 1) * IntPtr.Size) + intSz));
|
|
ro = h.ToIEnum<IntPtr>(rs.Length, intSz).ToArray();
|
|
Assert.That(ro, Has.None.EqualTo(IntPtr.Zero));
|
|
for (var i = 0; i < ro.Length; i++)
|
|
Assert.That(StringHelper.GetString(ro[i], CharSet.Ansi), Is.EqualTo(rs[i]));
|
|
Marshal.FreeHGlobal(h);
|
|
|
|
h = new string[0].MarshalToPtr(StringListPackMethod.Packed, Marshal.AllocHGlobal, out a, CharSet.Unicode, intSz);
|
|
Assert.That(h, Is.Not.EqualTo(IntPtr.Zero));
|
|
Assert.That(a, Is.EqualTo(intSz + IntPtr.Size));
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(h);
|
|
}
|
|
}
|
|
|
|
[Test()]
|
|
public void StructureToPtrTest()
|
|
{
|
|
var rect = new RECT(10, 11, 12, 13);
|
|
var ptr = rect.MarshalToPtr(Marshal.AllocCoTaskMem, out var a);
|
|
Assert.That(ptr != IntPtr.Zero);
|
|
Assert.That(Marshal.ReadInt32(ptr, 1 * intSz) == 11);
|
|
Marshal.FreeCoTaskMem(ptr);
|
|
}
|
|
|
|
[Test()]
|
|
public void ToArrayTest()
|
|
{
|
|
var rs = new[] { 10, 11, 12, 13, 14 };
|
|
var h = SafeHGlobalHandle.CreateFromList(rs, rs.Length, intSz);
|
|
var ro = ((IntPtr)h).ToArray<int>(4, intSz);
|
|
Assert.That(ro.Length, Is.EqualTo(4));
|
|
Assert.That(ro[2], Is.EqualTo(rs[2]));
|
|
|
|
Assert.That(((IntPtr)h).ToArray<int>(0, intSz), Is.Empty);
|
|
Assert.That(IntPtr.Zero.ToArray<int>(3, intSz), Is.Null);
|
|
}
|
|
|
|
[Test()]
|
|
public void ToIEnumTest()
|
|
{
|
|
var rs = new[] { 10, 11, 12, 13, 14 };
|
|
var h = SafeHGlobalHandle.CreateFromList(rs, rs.Length, intSz);
|
|
var ro = ((IntPtr)h).ToIEnum<int>(4, intSz);
|
|
var v = 10;
|
|
foreach (var rv in ro)
|
|
Assert.That(rv, Is.EqualTo(v++));
|
|
Assert.That(v, Is.EqualTo(14));
|
|
|
|
Assert.That(((IntPtr)h).ToIEnum<int>(0, intSz), Is.Empty);
|
|
Assert.That(IntPtr.Zero.ToIEnum<int>(0, intSz), Is.Empty);
|
|
}
|
|
|
|
[Test()]
|
|
public void ConvertPtrTest()
|
|
{
|
|
Assert.That(new UIntPtr(0x0E924356).ToIntPtr(), Is.EqualTo(new IntPtr(0x0E924356)));
|
|
Assert.That(new IntPtr(0x0E924356).ToUIntPtr(), Is.EqualTo(new UIntPtr(0x0E924356)));
|
|
}
|
|
|
|
[Test()]
|
|
public void ToNullableStructureTest()
|
|
{
|
|
Assert.That(IntPtr.Zero.ToNullableStructure<RECT>(), Is.Null);
|
|
var h = SafeHGlobalHandle.CreateFromStructure(new RECT(10, 11, 12, 13));
|
|
Assert.That(((IntPtr)h).ToNullableStructure<RECT>(), Is.Not.Null);
|
|
}
|
|
|
|
[Test()]
|
|
public void ToStructureTest()
|
|
{
|
|
var h = SafeHGlobalHandle.CreateFromStructure(new RECT(10, 11, 12, 13));
|
|
Assert.That(((IntPtr)h).ToStructure<RECT>().left == 10);
|
|
h.Dispose();
|
|
Assert.That(() => ((IntPtr)h).ToStructure<RECT>(), Throws.TypeOf<NullReferenceException>());
|
|
}
|
|
|
|
[Test()]
|
|
public void ToStructureTest1()
|
|
{
|
|
using var h = SafeHGlobalHandle.CreateFromStructure(new PRECT(10, 11, 12, 13));
|
|
var r = new PRECT(0, 0, 0, 0);
|
|
Assert.That(() => ((IntPtr)h).ToStructure(r), Throws.Nothing);
|
|
Assert.That(r.left, Is.EqualTo(10));
|
|
}
|
|
|
|
private abstract class AbsClass
|
|
{
|
|
public abstract int Value { get; }
|
|
}
|
|
|
|
[Test]
|
|
public void GetNulledPtrArrayLengthTest()
|
|
{
|
|
var ptrs = new[] { (IntPtr)1, (IntPtr)1, (IntPtr)1, (IntPtr)1, (IntPtr)1, IntPtr.Zero };
|
|
var mp = ptrs.MarshalToPtr<IntPtr>(Marshal.AllocCoTaskMem, out _);
|
|
Assert.That(mp.GetNulledPtrArrayLength(), Is.EqualTo(ptrs.Length - 1));
|
|
Marshal.WriteIntPtr(mp, IntPtr.Size, IntPtr.Zero);
|
|
Assert.That(mp.GetNulledPtrArrayLength(), Is.EqualTo(1));
|
|
Marshal.WriteIntPtr(mp, IntPtr.Zero);
|
|
Assert.That(mp.GetNulledPtrArrayLength(), Is.EqualTo(0));
|
|
Assert.That(IntPtr.Zero.GetNulledPtrArrayLength(), Is.EqualTo(0));
|
|
Marshal.FreeCoTaskMem(mp);
|
|
}
|
|
|
|
[Test()]
|
|
public void ToStringEnumTest()
|
|
{
|
|
var rs = new[] { "str1", "str2", "str3" };
|
|
using (var sa = SafeHGlobalHandle.CreateFromStringList(rs, StringListPackMethod.Concatenated, CharSet.Ansi, intSz))
|
|
{
|
|
var ptr = sa.DangerousGetHandle();
|
|
Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero));
|
|
var se = ptr.ToStringEnum(CharSet.Ansi, intSz, sa.Size);
|
|
Assert.That(se, Is.EquivalentTo(rs));
|
|
Assert.That(() => ptr.ToStringEnum(CharSet.Ansi, intSz, sa.Size - 5).ToArray(), Throws.TypeOf<InsufficientMemoryException>());
|
|
Assert.That(() => ptr.ToStringEnum(CharSet.Ansi, intSz, sa.Size - 1).ToArray(), Throws.TypeOf<InsufficientMemoryException>());
|
|
}
|
|
using (var sa = SafeHGlobalHandle.CreateFromStringList(rs, StringListPackMethod.Concatenated, CharSet.Unicode, intSz))
|
|
{
|
|
var ptr = sa.DangerousGetHandle();
|
|
Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero));
|
|
var se = ptr.ToStringEnum(CharSet.Unicode, intSz, sa.Size);
|
|
Assert.That(se, Is.EquivalentTo(rs));
|
|
Assert.That(() => ptr.ToStringEnum(CharSet.Unicode, intSz, sa.Size - 5).ToArray(), Throws.TypeOf<InsufficientMemoryException>());
|
|
Assert.That(() => ptr.ToStringEnum(CharSet.Unicode, intSz, sa.Size - 1).ToArray(), Throws.TypeOf<InsufficientMemoryException>());
|
|
}
|
|
using (var sa = SafeHGlobalHandle.CreateFromStringList(null, StringListPackMethod.Concatenated, CharSet.Unicode, intSz))
|
|
{
|
|
var ptr = sa.DangerousGetHandle();
|
|
Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero));
|
|
var se = ptr.ToStringEnum(CharSet.Unicode, intSz, sa.Size);
|
|
Assert.That(se, Is.Empty);
|
|
Assert.That(() => ptr.ToStringEnum(CharSet.Unicode, intSz, intSz).Count(), Throws.TypeOf<InsufficientMemoryException>());
|
|
Assert.That(() => ptr.ToStringEnum(CharSet.Unicode, intSz, sa.Size - 1).Count(), Throws.TypeOf<InsufficientMemoryException>());
|
|
}
|
|
Assert.That(IntPtr.Zero.ToStringEnum(CharSet.Unicode, intSz), Is.Empty);
|
|
}
|
|
|
|
[Test()]
|
|
public void ToStringEnumTest1()
|
|
{
|
|
var rs = new[] { "str1", "str2", null, "", "str3" };
|
|
using (var sa = SafeHGlobalHandle.CreateFromStringList(rs, StringListPackMethod.Packed, CharSet.Ansi, intSz))
|
|
{
|
|
var ptr = sa.DangerousGetHandle();
|
|
Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero));
|
|
var se = ptr.ToStringEnum(rs.Length, CharSet.Ansi, intSz);
|
|
Assert.That(se, Is.EquivalentTo(rs));
|
|
}
|
|
using (var sa = SafeHGlobalHandle.CreateFromStringList(rs, StringListPackMethod.Packed, CharSet.Unicode, intSz))
|
|
{
|
|
var ptr = sa.DangerousGetHandle();
|
|
Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero));
|
|
var se = ptr.ToStringEnum(rs.Length, CharSet.Unicode, intSz);
|
|
Assert.That(se, Is.EquivalentTo(rs));
|
|
}
|
|
using (var sa = SafeHGlobalHandle.CreateFromStringList(null, StringListPackMethod.Packed, CharSet.Unicode, intSz))
|
|
{
|
|
var ptr = sa.DangerousGetHandle();
|
|
Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero));
|
|
var se = ptr.ToStringEnum(0, CharSet.Unicode, intSz);
|
|
Assert.That(se, Is.Empty);
|
|
}
|
|
Assert.That(IntPtr.Zero.ToStringEnum(0, CharSet.Unicode, intSz), Is.Empty);
|
|
}
|
|
|
|
[TestCase("Some string value")]
|
|
[TestCase("")]
|
|
[TestCase((string)null)]
|
|
public void ToInsecureStringTest(string sval)
|
|
{
|
|
var ss = sval.ToSecureString();
|
|
if (sval != null)
|
|
{
|
|
Assert.That(ss, Is.Not.Null);
|
|
Assert.That(ss.Length, Is.EqualTo(sval.Length));
|
|
var s = ss.ToInsecureString();
|
|
Assert.That(s, Is.EqualTo(sval));
|
|
}
|
|
else
|
|
{
|
|
Assert.That(ss, Is.Null);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void ToInsecureStringTest()
|
|
{
|
|
Assert.That(IntPtr.Zero.ToSecureString(4), Is.Null);
|
|
Assert.That(((System.Security.SecureString)null).ToInsecureString(), Is.Null);
|
|
}
|
|
|
|
[TestCase("Some string value")]
|
|
[TestCase("")]
|
|
[TestCase((string)null)]
|
|
public void ToSecureStringTest(string sval)
|
|
{
|
|
var ms = new SafeCoTaskMemString(sval);
|
|
var ss = ms.DangerousGetHandle().ToSecureString();
|
|
if (sval != null)
|
|
{
|
|
Assert.That(ss, Is.Not.Null);
|
|
Assert.That(ss.Length, Is.EqualTo(sval.Length));
|
|
var s = ss.ToInsecureString();
|
|
Assert.That(s, Is.EqualTo(sval));
|
|
|
|
if (sval.Length > 1)
|
|
{
|
|
ss = ms.DangerousGetHandle().ToSecureString(1);
|
|
Assert.That(ss, Is.Not.Null);
|
|
Assert.That(ss.Length, Is.EqualTo(1));
|
|
s = ss.ToInsecureString();
|
|
Assert.That(s, Is.EqualTo(sval.Substring(0, 1)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Assert.That(ss, Is.Null);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public unsafe void AsUnmanagedArrayPointerTest()
|
|
{
|
|
var h = new SafeHGlobalHandle(Marshal.SizeOf(typeof(RECT)) * 2 + intSz);
|
|
var rs = new[] { new RECT(0, 1, 2, 3), new RECT(10, 11, 12, 13) };
|
|
((IntPtr)h).Write(rs, intSz, h.Size);
|
|
|
|
RECT* r = h.DangerousGetHandle().AsUnmanagedArrayPointer<RECT>(rs.Length, intSz, h.Size);
|
|
Assert.That(r[1].left, Is.EqualTo(10));
|
|
Assert.That(r[1].top, Is.EqualTo(11));
|
|
Assert.That(r[1].right, Is.EqualTo(12));
|
|
Assert.That(r[1].bottom, Is.EqualTo(13));
|
|
}
|
|
|
|
[Test]
|
|
public void WriteObjectTest()
|
|
{
|
|
using var mem = new SafeHGlobalHandle(4096);
|
|
var h = mem.DangerousGetHandle();
|
|
|
|
// null
|
|
Assert.That(h.Write((object)null), Is.EqualTo(0));
|
|
|
|
// bytes
|
|
Assert.That(h.Write((object)new byte[] { 1, 2, 4, 5 }), Is.EqualTo(4));
|
|
|
|
// marshaled
|
|
//Assert.That(h.Write(), ResultIs.Successful);
|
|
|
|
// string
|
|
Assert.That(h.Write((object)"abcde"), Is.EqualTo(12));
|
|
|
|
// blitted
|
|
Assert.That(h.Write((object)1234L), Is.EqualTo(8));
|
|
Assert.That(h.Write((object)Guid.NewGuid()), Is.EqualTo(16));
|
|
Assert.That(h.Write((object)OSPlatform.Windows), Is.EqualTo(4));
|
|
|
|
// string enum
|
|
Assert.That(h.Write((object)new[] { "abcde", "abcde" }), Is.EqualTo(26));
|
|
|
|
// array
|
|
Assert.That(h.Write((object)new[] { 1234, 1234 }), Is.EqualTo(8));
|
|
|
|
// ienum
|
|
Assert.That(h.Write((object)new List<int>() { 1234, 1234 }), Is.EqualTo(8));
|
|
|
|
// iserial
|
|
Assert.That(h.Write((object)DateTime.Now), Is.EqualTo(78));
|
|
}
|
|
}
|
|
} |