📷 A modern, cross-platform, 2D Graphics library for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

167 lines
5.3 KiB

// ReSharper disable ObjectCreationAsStatement
// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests.Common
{
using System;
using System.Runtime.CompilerServices;
using Xunit;
public unsafe class ArrayPointerTests
{
public struct Foo
{
public int A;
public double B;
internal static Foo[] CreateArray(int size)
{
Foo[] result = new Foo[size];
for (int i = 0; i < size; i++)
{
result[i] = new Foo() { A = i, B = i };
}
return result;
}
}
[Fact]
public void ConstructWithoutOffset()
{
Foo[] array = Foo.CreateArray(3);
fixed (Foo* p = array)
{
// Act:
ArrayPointer<Foo> ap = new ArrayPointer<Foo>(array, p);
// Assert:
Assert.Equal(array, ap.Array);
Assert.Equal((IntPtr)p, ap.PointerAtOffset);
}
}
[Fact]
public void ConstructWithOffset()
{
Foo[] array = Foo.CreateArray(3);
int offset = 2;
fixed (Foo* p = array)
{
// Act:
ArrayPointer<Foo> ap = new ArrayPointer<Foo>(array, p, offset);
// Assert:
Assert.Equal(array, ap.Array);
Assert.Equal(offset, ap.Offset);
Assert.Equal((IntPtr)(p+offset), ap.PointerAtOffset);
}
}
[Fact]
public void Slice()
{
Foo[] array = Foo.CreateArray(5);
int offset0 = 2;
int offset1 = 2;
int totalOffset = offset0 + offset1;
fixed (Foo* p = array)
{
ArrayPointer<Foo> ap = new ArrayPointer<Foo>(array, p, offset0);
// Act:
ap = ap.Slice(offset1);
// Assert:
Assert.Equal(array, ap.Array);
Assert.Equal(totalOffset, ap.Offset);
Assert.Equal((IntPtr)(p + totalOffset), ap.PointerAtOffset);
}
}
public class Copy
{
[Theory]
[InlineData(4)]
[InlineData(1500)]
public void GenericToOwnType(int count)
{
Foo[] source = Foo.CreateArray(count + 2);
Foo[] dest = new Foo[count + 5];
fixed (Foo* pSource = source)
fixed (Foo* pDest = dest)
{
ArrayPointer<Foo> apSource = new ArrayPointer<Foo>(source, pSource);
ArrayPointer<Foo> apDest = new ArrayPointer<Foo>(dest, pDest);
ArrayPointer.Copy(apSource, apDest, count);
}
Assert.Equal(source[0], dest[0]);
Assert.Equal(source[count-1], dest[count-1]);
Assert.NotEqual(source[count], dest[count]);
}
[Theory]
[InlineData(4)]
[InlineData(1500)]
public void GenericToBytes(int count)
{
int destCount = count * sizeof(Foo);
Foo[] source = Foo.CreateArray(count + 2);
byte[] dest = new byte[destCount + sizeof(Foo) + 1];
fixed (Foo* pSource = source)
fixed (byte* pDest = dest)
{
ArrayPointer<Foo> apSource = new ArrayPointer<Foo>(source, pSource);
ArrayPointer<byte> apDest = new ArrayPointer<byte>(dest, pDest);
ArrayPointer.Copy(apSource, apDest, count);
}
Assert.True(ElementsAreEqual(source, dest, 0));
Assert.True(ElementsAreEqual(source, dest, count - 1));
Assert.False(ElementsAreEqual(source, dest, count));
}
[Theory]
[InlineData(4)]
[InlineData(1500)]
public void BytesToGeneric(int count)
{
int destCount = count * sizeof(Foo);
byte[] source = new byte[destCount + sizeof(Foo) + 1];
Foo[] dest = Foo.CreateArray(count + 2);
fixed(byte* pSource = source)
fixed (Foo* pDest = dest)
{
ArrayPointer<byte> apSource = new ArrayPointer<byte>(source, pSource);
ArrayPointer<Foo> apDest = new ArrayPointer<Foo>(dest, pDest);
ArrayPointer.Copy(apSource, apDest, count);
}
Assert.True(ElementsAreEqual(dest, source, 0));
Assert.True(ElementsAreEqual(dest, source, count - 1));
Assert.False(ElementsAreEqual(dest, source, count));
}
private static bool ElementsAreEqual(Foo[] array, byte[] rawArray, int index)
{
fixed (Foo* pArray = array)
fixed (byte* pRaw = rawArray)
{
Foo* pCasted = (Foo*)pRaw;
Foo val1 = pArray[index];
Foo val2 = pCasted[index];
return val1.Equals(val2);
}
}
}
}
}