|
|
|
@ -1,5 +1,6 @@ |
|
|
|
// ReSharper disable ObjectCreationAsStatement
|
|
|
|
// ReSharper disable InconsistentNaming
|
|
|
|
|
|
|
|
namespace ImageSharp.Tests.Common |
|
|
|
{ |
|
|
|
using System; |
|
|
|
@ -8,9 +9,20 @@ namespace ImageSharp.Tests.Common |
|
|
|
using Xunit; |
|
|
|
|
|
|
|
using static TestStructs; |
|
|
|
|
|
|
|
|
|
|
|
public unsafe class BufferSpanTests |
|
|
|
{ |
|
|
|
// ReSharper disable once ClassNeverInstantiated.Local
|
|
|
|
private class Assert : Xunit.Assert |
|
|
|
{ |
|
|
|
public static void SameRefs<T1, T2>(ref T1 a, ref T2 b) |
|
|
|
{ |
|
|
|
ref T1 bb = ref Unsafe.As<T2, T1>(ref b); |
|
|
|
|
|
|
|
True(Unsafe.AreSame(ref a, ref bb), "References are not same!"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void AsBytes() |
|
|
|
{ |
|
|
|
@ -19,10 +31,10 @@ namespace ImageSharp.Tests.Common |
|
|
|
using (PinnedBuffer<Foo> colorBuf = new PinnedBuffer<Foo>(fooz)) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> orig = colorBuf.Slice(1); |
|
|
|
BufferSpan<byte> asBytes = (BufferSpan < byte > )orig; |
|
|
|
BufferSpan<byte> asBytes = (BufferSpan<byte>)orig; |
|
|
|
|
|
|
|
Assert.Equal(asBytes.Start, sizeof(Foo)); |
|
|
|
Assert.Equal(orig.PointerAtOffset, asBytes.PointerAtOffset); |
|
|
|
Assert.SameRefs(ref orig.DangerousGetPinnableReference(), ref asBytes.DangerousGetPinnableReference()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -32,16 +44,14 @@ namespace ImageSharp.Tests.Common |
|
|
|
public void Basic() |
|
|
|
{ |
|
|
|
Foo[] array = Foo.CreateArray(3); |
|
|
|
fixed (Foo* p = array) |
|
|
|
{ |
|
|
|
// Act:
|
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, p); |
|
|
|
|
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal((IntPtr)p, span.PointerAtOffset); |
|
|
|
Assert.Equal(3, span.Length); |
|
|
|
} |
|
|
|
// Act:
|
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array); |
|
|
|
|
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(3, span.Length); |
|
|
|
Assert.SameRefs(ref array[0], ref span.DangerousGetPinnableReference()); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
@ -49,17 +59,15 @@ namespace ImageSharp.Tests.Common |
|
|
|
{ |
|
|
|
Foo[] array = Foo.CreateArray(4); |
|
|
|
int start = 2; |
|
|
|
fixed (Foo* p = array) |
|
|
|
{ |
|
|
|
// Act:
|
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, p, start); |
|
|
|
|
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(start, span.Start); |
|
|
|
Assert.Equal((IntPtr)(p + start), span.PointerAtOffset); |
|
|
|
Assert.Equal(array.Length - start, span.Length); |
|
|
|
} |
|
|
|
|
|
|
|
// Act:
|
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, start); |
|
|
|
|
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(start, span.Start); |
|
|
|
Assert.SameRefs(ref array[start], ref span.DangerousGetPinnableReference()); |
|
|
|
Assert.Equal(array.Length - start, span.Length); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
@ -68,17 +76,14 @@ namespace ImageSharp.Tests.Common |
|
|
|
Foo[] array = Foo.CreateArray(10); |
|
|
|
int start = 2; |
|
|
|
int length = 3; |
|
|
|
fixed (Foo* p = array) |
|
|
|
{ |
|
|
|
// Act:
|
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, p, start, length); |
|
|
|
|
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(start, span.Start); |
|
|
|
Assert.Equal((IntPtr)(p + start), span.PointerAtOffset); |
|
|
|
Assert.Equal(length, span.Length); |
|
|
|
} |
|
|
|
// Act:
|
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, start, length); |
|
|
|
|
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(start, span.Start); |
|
|
|
Assert.SameRefs(ref array[start], ref span.DangerousGetPinnableReference()); |
|
|
|
Assert.Equal(length, span.Length); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -92,19 +97,16 @@ namespace ImageSharp.Tests.Common |
|
|
|
int start1 = 2; |
|
|
|
int totalOffset = start0 + start1; |
|
|
|
|
|
|
|
fixed (Foo* p = array) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, p, start0); |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, start0); |
|
|
|
|
|
|
|
// Act:
|
|
|
|
span = span.Slice(start1); |
|
|
|
// Act:
|
|
|
|
span = span.Slice(start1); |
|
|
|
|
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(totalOffset, span.Start); |
|
|
|
Assert.Equal((IntPtr)(p + totalOffset), span.PointerAtOffset); |
|
|
|
Assert.Equal(array.Length - totalOffset, span.Length); |
|
|
|
} |
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(totalOffset, span.Start); |
|
|
|
Assert.SameRefs(ref array[totalOffset], ref span.DangerousGetPinnableReference()); |
|
|
|
Assert.Equal(array.Length - totalOffset, span.Length); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
@ -116,24 +118,19 @@ namespace ImageSharp.Tests.Common |
|
|
|
int totalOffset = start0 + start1; |
|
|
|
int sliceLength = 3; |
|
|
|
|
|
|
|
fixed (Foo* p = array) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, p, start0); |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(array, start0); |
|
|
|
|
|
|
|
// Act:
|
|
|
|
span = span.Slice(start1, sliceLength); |
|
|
|
// Act:
|
|
|
|
span = span.Slice(start1, sliceLength); |
|
|
|
|
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(totalOffset, span.Start); |
|
|
|
Assert.Equal((IntPtr)(p + totalOffset), span.PointerAtOffset); |
|
|
|
Assert.Equal(sliceLength, span.Length); |
|
|
|
} |
|
|
|
// Assert:
|
|
|
|
Assert.Equal(array, span.Array); |
|
|
|
Assert.Equal(totalOffset, span.Start); |
|
|
|
Assert.SameRefs(ref array[totalOffset], ref span.DangerousGetPinnableReference()); |
|
|
|
Assert.Equal(sliceLength, span.Length); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[Theory] |
|
|
|
[InlineData(4)] |
|
|
|
[InlineData(1500)] |
|
|
|
@ -142,21 +139,17 @@ namespace ImageSharp.Tests.Common |
|
|
|
Foo[] array = Foo.CreateArray(count + 42); |
|
|
|
|
|
|
|
int offset = 2; |
|
|
|
fixed (Foo* p = array) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> ap = new BufferSpan<Foo>(array, p, offset); |
|
|
|
BufferSpan<Foo> ap = new BufferSpan<Foo>(array, offset); |
|
|
|
|
|
|
|
// Act:
|
|
|
|
ap.Clear(count); |
|
|
|
// Act:
|
|
|
|
ap.Clear(count); |
|
|
|
|
|
|
|
Assert.NotEqual(default(Foo), array[offset-1]); |
|
|
|
Assert.Equal(default(Foo), array[offset]); |
|
|
|
Assert.Equal(default(Foo), array[offset + count-1]); |
|
|
|
Assert.NotEqual(default(Foo), array[offset + count]); |
|
|
|
} |
|
|
|
Assert.NotEqual(default(Foo), array[offset - 1]); |
|
|
|
Assert.Equal(default(Foo), array[offset]); |
|
|
|
Assert.Equal(default(Foo), array[offset + count - 1]); |
|
|
|
Assert.NotEqual(default(Foo), array[offset + count]); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public class Indexer |
|
|
|
{ |
|
|
|
public static readonly TheoryData<int, int, int> IndexerData = |
|
|
|
@ -175,14 +168,11 @@ namespace ImageSharp.Tests.Common |
|
|
|
public void Read(int length, int start, int index) |
|
|
|
{ |
|
|
|
Foo[] a = Foo.CreateArray(length); |
|
|
|
fixed (Foo* p = a) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(a, p, start); |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(a, start); |
|
|
|
|
|
|
|
Foo element = span[index]; |
|
|
|
Foo element = span[index]; |
|
|
|
|
|
|
|
Assert.Equal(a[start + index], element); |
|
|
|
} |
|
|
|
Assert.Equal(a[start + index], element); |
|
|
|
} |
|
|
|
|
|
|
|
[Theory] |
|
|
|
@ -190,14 +180,11 @@ namespace ImageSharp.Tests.Common |
|
|
|
public void Write(int length, int start, int index) |
|
|
|
{ |
|
|
|
Foo[] a = Foo.CreateArray(length); |
|
|
|
fixed (Foo* p = a) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(a, p, start); |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(a, start); |
|
|
|
|
|
|
|
span[index] = new Foo(666, 666); |
|
|
|
span[index] = new Foo(666, 666); |
|
|
|
|
|
|
|
Assert.Equal(new Foo(666, 666), a[start + index]); |
|
|
|
} |
|
|
|
Assert.Equal(new Foo(666, 666), a[start + index]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -208,13 +195,10 @@ namespace ImageSharp.Tests.Common |
|
|
|
public void DangerousGetPinnableReference(int start, int length) |
|
|
|
{ |
|
|
|
Foo[] a = Foo.CreateArray(length); |
|
|
|
fixed (Foo* p = a) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(a, p, start); |
|
|
|
ref Foo r = ref span.DangerousGetPinnableReference(); |
|
|
|
BufferSpan<Foo> span = new BufferSpan<Foo>(a, start); |
|
|
|
ref Foo r = ref span.DangerousGetPinnableReference(); |
|
|
|
|
|
|
|
Assert.True(Unsafe.AreSame(ref a[start], ref r)); |
|
|
|
} |
|
|
|
Assert.True(Unsafe.AreSame(ref a[start], ref r)); |
|
|
|
} |
|
|
|
|
|
|
|
public class Copy |
|
|
|
@ -253,14 +237,10 @@ namespace ImageSharp.Tests.Common |
|
|
|
Foo[] source = Foo.CreateArray(count + 2); |
|
|
|
Foo[] dest = new Foo[count + 5]; |
|
|
|
|
|
|
|
fixed (Foo* pSource = source) |
|
|
|
fixed (Foo* pDest = dest) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> apSource = new BufferSpan<Foo>(source, pSource, 1); |
|
|
|
BufferSpan<Foo> apDest = new BufferSpan<Foo>(dest, pDest, 1); |
|
|
|
BufferSpan<Foo> apSource = new BufferSpan<Foo>(source, 1); |
|
|
|
BufferSpan<Foo> apDest = new BufferSpan<Foo>(dest, 1); |
|
|
|
|
|
|
|
BufferSpan.Copy(apSource, apDest, count-1); |
|
|
|
} |
|
|
|
BufferSpan.Copy(apSource, apDest, count - 1); |
|
|
|
|
|
|
|
AssertNotDefault(source, 1); |
|
|
|
AssertNotDefault(dest, 1); |
|
|
|
@ -268,7 +248,7 @@ namespace ImageSharp.Tests.Common |
|
|
|
Assert.NotEqual(source[0], dest[0]); |
|
|
|
Assert.Equal(source[1], dest[1]); |
|
|
|
Assert.Equal(source[2], dest[2]); |
|
|
|
Assert.Equal(source[count-1], dest[count-1]); |
|
|
|
Assert.Equal(source[count - 1], dest[count - 1]); |
|
|
|
Assert.NotEqual(source[count], dest[count]); |
|
|
|
} |
|
|
|
|
|
|
|
@ -280,14 +260,10 @@ namespace ImageSharp.Tests.Common |
|
|
|
AlignedFoo[] source = AlignedFoo.CreateArray(count + 2); |
|
|
|
AlignedFoo[] dest = new AlignedFoo[count + 5]; |
|
|
|
|
|
|
|
fixed (AlignedFoo* pSource = source) |
|
|
|
fixed (AlignedFoo* pDest = dest) |
|
|
|
{ |
|
|
|
BufferSpan<AlignedFoo> apSource = new BufferSpan<AlignedFoo>(source, pSource, 1); |
|
|
|
BufferSpan<AlignedFoo> apDest = new BufferSpan<AlignedFoo>(dest, pDest, 1); |
|
|
|
BufferSpan<AlignedFoo> apSource = new BufferSpan<AlignedFoo>(source, 1); |
|
|
|
BufferSpan<AlignedFoo> apDest = new BufferSpan<AlignedFoo>(dest, 1); |
|
|
|
|
|
|
|
BufferSpan.Copy(apSource, apDest, count - 1); |
|
|
|
} |
|
|
|
BufferSpan.Copy(apSource, apDest, count - 1); |
|
|
|
|
|
|
|
AssertNotDefault(source, 1); |
|
|
|
AssertNotDefault(dest, 1); |
|
|
|
@ -304,17 +280,13 @@ namespace ImageSharp.Tests.Common |
|
|
|
[InlineData(1500)] |
|
|
|
public void IntToInt(int count) |
|
|
|
{ |
|
|
|
int[] source = CreateTestInts(count+2); |
|
|
|
int[] source = CreateTestInts(count + 2); |
|
|
|
int[] dest = new int[count + 5]; |
|
|
|
|
|
|
|
fixed (int* pSource = source) |
|
|
|
fixed (int* pDest = dest) |
|
|
|
{ |
|
|
|
BufferSpan<int> apSource = new BufferSpan<int>(source, pSource, 1); |
|
|
|
BufferSpan<int> apDest = new BufferSpan<int>(dest, pDest, 1); |
|
|
|
BufferSpan<int> apSource = new BufferSpan<int>(source, 1); |
|
|
|
BufferSpan<int> apDest = new BufferSpan<int>(dest, 1); |
|
|
|
|
|
|
|
BufferSpan.Copy(apSource, apDest, count -1); |
|
|
|
} |
|
|
|
BufferSpan.Copy(apSource, apDest, count - 1); |
|
|
|
|
|
|
|
AssertNotDefault(source, 1); |
|
|
|
AssertNotDefault(dest, 1); |
|
|
|
@ -332,17 +304,13 @@ namespace ImageSharp.Tests.Common |
|
|
|
public void GenericToBytes(int count) |
|
|
|
{ |
|
|
|
int destCount = count * sizeof(Foo); |
|
|
|
Foo[] source = Foo.CreateArray(count+2); |
|
|
|
byte[] dest = new byte[destCount + sizeof(Foo)*2]; |
|
|
|
Foo[] source = Foo.CreateArray(count + 2); |
|
|
|
byte[] dest = new byte[destCount + sizeof(Foo) * 2]; |
|
|
|
|
|
|
|
fixed (Foo* pSource = source) |
|
|
|
fixed (byte* pDest = dest) |
|
|
|
{ |
|
|
|
BufferSpan<Foo> apSource = new BufferSpan<Foo>(source, pSource, 1); |
|
|
|
BufferSpan<byte> apDest = new BufferSpan<byte>(dest, pDest, sizeof(Foo)); |
|
|
|
BufferSpan<Foo> apSource = new BufferSpan<Foo>(source, 1); |
|
|
|
BufferSpan<byte> apDest = new BufferSpan<byte>(dest, sizeof(Foo)); |
|
|
|
|
|
|
|
BufferSpan.Copy(apSource, apDest, count - 1); |
|
|
|
} |
|
|
|
BufferSpan.Copy(apSource, apDest, count - 1); |
|
|
|
|
|
|
|
AssertNotDefault(source, 1); |
|
|
|
|
|
|
|
@ -362,14 +330,10 @@ namespace ImageSharp.Tests.Common |
|
|
|
AlignedFoo[] source = AlignedFoo.CreateArray(count + 2); |
|
|
|
byte[] dest = new byte[destCount + sizeof(AlignedFoo) * 2]; |
|
|
|
|
|
|
|
fixed (AlignedFoo* pSource = source) |
|
|
|
fixed (byte* pDest = dest) |
|
|
|
{ |
|
|
|
BufferSpan<AlignedFoo> apSource = new BufferSpan<AlignedFoo>(source, pSource, 1); |
|
|
|
BufferSpan<byte> apDest = new BufferSpan<byte>(dest, pDest, sizeof(AlignedFoo)); |
|
|
|
BufferSpan<AlignedFoo> apSource = new BufferSpan<AlignedFoo>(source, 1); |
|
|
|
BufferSpan<byte> apDest = new BufferSpan<byte>(dest, sizeof(AlignedFoo)); |
|
|
|
|
|
|
|
BufferSpan.Copy(apSource, apDest, count - 1); |
|
|
|
} |
|
|
|
BufferSpan.Copy(apSource, apDest, count - 1); |
|
|
|
|
|
|
|
AssertNotDefault(source, 1); |
|
|
|
|
|
|
|
@ -386,17 +350,13 @@ namespace ImageSharp.Tests.Common |
|
|
|
public void IntToBytes(int count) |
|
|
|
{ |
|
|
|
int destCount = count * sizeof(int); |
|
|
|
int[] source = CreateTestInts(count+2); |
|
|
|
int[] source = CreateTestInts(count + 2); |
|
|
|
byte[] dest = new byte[destCount + sizeof(int) + 1]; |
|
|
|
|
|
|
|
fixed (int* pSource = source) |
|
|
|
fixed (byte* pDest = dest) |
|
|
|
{ |
|
|
|
BufferSpan<int> apSource = new BufferSpan<int>(source, pSource); |
|
|
|
BufferSpan<byte> apDest = new BufferSpan<byte>(dest, pDest); |
|
|
|
BufferSpan<int> apSource = new BufferSpan<int>(source); |
|
|
|
BufferSpan<byte> apDest = new BufferSpan<byte>(dest); |
|
|
|
|
|
|
|
BufferSpan.Copy(apSource, apDest, count); |
|
|
|
} |
|
|
|
BufferSpan.Copy(apSource, apDest, count); |
|
|
|
|
|
|
|
AssertNotDefault(source, 1); |
|
|
|
|
|
|
|
@ -413,15 +373,11 @@ namespace ImageSharp.Tests.Common |
|
|
|
int srcCount = count * sizeof(Foo); |
|
|
|
byte[] source = CreateTestBytes(srcCount); |
|
|
|
Foo[] dest = new Foo[count + 2]; |
|
|
|
|
|
|
|
fixed(byte* pSource = source) |
|
|
|
fixed (Foo* pDest = dest) |
|
|
|
{ |
|
|
|
BufferSpan<byte> apSource = new BufferSpan<byte>(source, pSource); |
|
|
|
BufferSpan<Foo> apDest = new BufferSpan<Foo>(dest, pDest); |
|
|
|
|
|
|
|
BufferSpan.Copy(apSource, apDest, count); |
|
|
|
} |
|
|
|
BufferSpan<byte> apSource = new BufferSpan<byte>(source); |
|
|
|
BufferSpan<Foo> apDest = new BufferSpan<Foo>(dest); |
|
|
|
|
|
|
|
BufferSpan.Copy(apSource, apDest, count); |
|
|
|
|
|
|
|
AssertNotDefault(source, sizeof(Foo) + 1); |
|
|
|
AssertNotDefault(dest, 1); |
|
|
|
@ -438,7 +394,7 @@ namespace ImageSharp.Tests.Common |
|
|
|
Color[] colors = { new Color(0, 1, 2, 3), new Color(4, 5, 6, 7), new Color(8, 9, 10, 11), }; |
|
|
|
|
|
|
|
using (PinnedBuffer<Color> colorBuf = new PinnedBuffer<Color>(colors)) |
|
|
|
using (PinnedBuffer<byte> byteBuf = new PinnedBuffer<byte>(colors.Length*4)) |
|
|
|
using (PinnedBuffer<byte> byteBuf = new PinnedBuffer<byte>(colors.Length * 4)) |
|
|
|
{ |
|
|
|
BufferSpan.Copy<Color>(colorBuf, byteBuf, colorBuf.Length); |
|
|
|
|
|
|
|
@ -451,7 +407,6 @@ namespace ImageSharp.Tests.Common |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
internal static bool ElementsAreEqual(Foo[] array, byte[] rawArray, int index) |
|
|
|
{ |
|
|
|
fixed (Foo* pArray = array) |
|
|
|
|