diff --git a/tests/ImageSharp.Tests/Image/ImageFrameTests.cs b/tests/ImageSharp.Tests/Image/ImageFrameTests.cs index 344ebac95b..9e3aed2b0a 100644 --- a/tests/ImageSharp.Tests/Image/ImageFrameTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageFrameTests.cs @@ -4,6 +4,7 @@ using System; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.Memory; using Xunit; namespace SixLabors.ImageSharp.Tests @@ -16,10 +17,7 @@ namespace SixLabors.ImageSharp.Tests private void LimitBufferCapacity(int bufferCapacityInBytes) { - // TODO: Create a test-only MemoryAllocator for this -#pragma warning disable CS0618 // 'ArrayPoolMemoryAllocator' is obsolete - var allocator = ArrayPoolMemoryAllocator.CreateDefault(); -#pragma warning restore CS0618 + var allocator = new TestMemoryAllocator(); allocator.BufferCapacityInBytes = bufferCapacityInBytes; this.configuration.MemoryAllocator = allocator; } diff --git a/tests/ImageSharp.Tests/Image/ImageTests.cs b/tests/ImageSharp.Tests/Image/ImageTests.cs index 7d6963a048..4f68453a9f 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.cs @@ -97,15 +97,8 @@ namespace SixLabors.ImageSharp.Tests { private readonly Configuration configuration = Configuration.CreateDefaultInstance(); - private void LimitBufferCapacity(int bufferCapacityInBytes) - { - // TODO: Create a test-only MemoryAllocator for this -#pragma warning disable CS0618 // 'ArrayPoolMemoryAllocator' is obsolete - var allocator = ArrayPoolMemoryAllocator.CreateDefault(); -#pragma warning restore CS0618 - allocator.BufferCapacityInBytes = bufferCapacityInBytes; - this.configuration.MemoryAllocator = allocator; - } + private void LimitBufferCapacity(int bufferCapacityInBytes) => + this.configuration.MemoryAllocator = new TestMemoryAllocator { BufferCapacityInBytes = bufferCapacityInBytes }; [Theory] [InlineData(false)] diff --git a/tests/ImageSharp.Tests/Memory/Allocators/ArrayPoolMemoryAllocatorTests.cs b/tests/ImageSharp.Tests/Memory/Allocators/ArrayPoolMemoryAllocatorTests.cs deleted file mode 100644 index 909617bac4..0000000000 --- a/tests/ImageSharp.Tests/Memory/Allocators/ArrayPoolMemoryAllocatorTests.cs +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Buffers; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Microsoft.DotNet.RemoteExecutor; -using SixLabors.ImageSharp.Memory; -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Memory.Allocators -{ -#pragma warning disable CS0618 - public class ArrayPoolMemoryAllocatorTests - { - private const int MaxPooledBufferSizeInBytes = 2048; - - private const int PoolSelectorThresholdInBytes = MaxPooledBufferSizeInBytes / 2; - - /// - /// Gets the SUT for in-process tests. - /// - private MemoryAllocatorFixture LocalFixture { get; } = new MemoryAllocatorFixture(); - - /// - /// Gets the SUT for tests executed by , - /// recreated in each external process. - /// - private static MemoryAllocatorFixture StaticFixture { get; } = new MemoryAllocatorFixture(); - - public class BufferTests : BufferTestSuite - { - public BufferTests() - : base(new ArrayPoolMemoryAllocator(MaxPooledBufferSizeInBytes, PoolSelectorThresholdInBytes)) - { - } - } - - public class Constructor - { - [Fact] - public void WhenBothParametersPassedByUser() - { - var mgr = new ArrayPoolMemoryAllocator(1111, 666); - Assert.Equal(1111, mgr.MaxPoolSizeInBytes); - Assert.Equal(666, mgr.PoolSelectorThresholdInBytes); - } - - [Fact] - public void WhenPassedOnly_MaxPooledBufferSizeInBytes_SmallerThresholdValueIsAutoCalculated() - { - var mgr = new ArrayPoolMemoryAllocator(5000); - Assert.Equal(5000, mgr.MaxPoolSizeInBytes); - Assert.True(mgr.PoolSelectorThresholdInBytes < mgr.MaxPoolSizeInBytes); - } - - [Fact] - public void When_PoolSelectorThresholdInBytes_IsGreaterThan_MaxPooledBufferSizeInBytes_ExceptionIsThrown() - => Assert.ThrowsAny(() => new ArrayPoolMemoryAllocator(100, 200)); - } - - [Theory] - [InlineData(32)] - [InlineData(512)] - [InlineData(MaxPooledBufferSizeInBytes - 1)] - public void SmallBuffersArePooled_OfByte(int size) => Assert.True(this.LocalFixture.CheckIsRentingPooledBuffer(size)); - - [Theory] - [InlineData(128 * 1024 * 1024)] - [InlineData(MaxPooledBufferSizeInBytes + 1)] - public void LargeBuffersAreNotPooled_OfByte(int size) - { - static void RunTest(string sizeStr) - { - int size = int.Parse(sizeStr); - StaticFixture.CheckIsRentingPooledBuffer(size); - } - - RemoteExecutor.Invoke(RunTest, size.ToString()).Dispose(); - } - - [Fact] - public unsafe void SmallBuffersArePooled_OfBigValueType() - { - int count = (MaxPooledBufferSizeInBytes / sizeof(LargeStruct)) - 1; - - Assert.True(this.LocalFixture.CheckIsRentingPooledBuffer(count)); - } - - [Fact] - public unsafe void LaregeBuffersAreNotPooled_OfBigValueType() - { - int count = (MaxPooledBufferSizeInBytes / sizeof(LargeStruct)) + 1; - - Assert.False(this.LocalFixture.CheckIsRentingPooledBuffer(count)); - } - - [Theory] - [InlineData(AllocationOptions.None)] - [InlineData(AllocationOptions.Clean)] - public void CleaningRequests_AreControlledByAllocationParameter_Clean(AllocationOptions options) - { - MemoryAllocator memoryAllocator = this.LocalFixture.MemoryAllocator; - using (IMemoryOwner firstAlloc = memoryAllocator.Allocate(42)) - { - BufferExtensions.GetSpan(firstAlloc).Fill(666); - } - - using (IMemoryOwner secondAlloc = memoryAllocator.Allocate(42, options)) - { - int expected = options == AllocationOptions.Clean ? 0 : 666; - Assert.Equal(expected, BufferExtensions.GetSpan(secondAlloc)[0]); - } - } - - [Fact] - public unsafe void Allocate_MemoryIsPinnableMultipleTimes() - { - ArrayPoolMemoryAllocator allocator = this.LocalFixture.MemoryAllocator; - using IMemoryOwner memoryOwner = allocator.Allocate(100); - - using (MemoryHandle pin = memoryOwner.Memory.Pin()) - { - Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer); - } - - using (MemoryHandle pin = memoryOwner.Memory.Pin()) - { - Assert.NotEqual(IntPtr.Zero, (IntPtr)pin.Pointer); - } - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ReleaseRetainedResources_ReplacesInnerArrayPool(bool keepBufferAlive) - { - MemoryAllocator memoryAllocator = this.LocalFixture.MemoryAllocator; - IMemoryOwner buffer = memoryAllocator.Allocate(32); - ref int ptrToPrev0 = ref MemoryMarshal.GetReference(BufferExtensions.GetSpan(buffer)); - - if (!keepBufferAlive) - { - buffer.Dispose(); - } - - memoryAllocator.ReleaseRetainedResources(); - - buffer = memoryAllocator.Allocate(32); - - Assert.False(Unsafe.AreSame(ref ptrToPrev0, ref BufferExtensions.GetReference(buffer))); - } - - [Fact] - public void ReleaseRetainedResources_DisposingPreviouslyAllocatedBuffer_IsAllowed() - { - MemoryAllocator memoryAllocator = this.LocalFixture.MemoryAllocator; - IMemoryOwner buffer = memoryAllocator.Allocate(32); - memoryAllocator.ReleaseRetainedResources(); - buffer.Dispose(); - } - - [Fact] - public void AllocationOverLargeArrayThreshold_UsesDifferentPool() - { - static void RunTest() - { - const int ArrayLengthThreshold = PoolSelectorThresholdInBytes / sizeof(int); - - IMemoryOwner small = StaticFixture.MemoryAllocator.Allocate(ArrayLengthThreshold - 1); - ref int ptr2Small = ref BufferExtensions.GetReference(small); - small.Dispose(); - - IMemoryOwner large = StaticFixture.MemoryAllocator.Allocate(ArrayLengthThreshold + 1); - - Assert.False(Unsafe.AreSame(ref ptr2Small, ref BufferExtensions.GetReference(large))); - } - - RemoteExecutor.Invoke(RunTest).Dispose(); - } - - [Fact] - public void CreateWithAggressivePooling() - { - static void RunTest() - { - StaticFixture.MemoryAllocator = ArrayPoolMemoryAllocator.CreateWithAggressivePooling(); - Assert.True(StaticFixture.CheckIsRentingPooledBuffer(4096 * 4096)); - } - - RemoteExecutor.Invoke(RunTest).Dispose(); - } - - [Fact] - public void CreateDefault() - { - static void RunTest() - { - StaticFixture.MemoryAllocator = ArrayPoolMemoryAllocator.CreateDefault(); - - Assert.False(StaticFixture.CheckIsRentingPooledBuffer(2 * 4096 * 4096)); - Assert.True(StaticFixture.CheckIsRentingPooledBuffer(2048 * 2048)); - } - - RemoteExecutor.Invoke(RunTest).Dispose(); - } - - [Fact] - public void CreateWithModeratePooling() - { - static void RunTest() - { - StaticFixture.MemoryAllocator = ArrayPoolMemoryAllocator.CreateWithModeratePooling(); - Assert.False(StaticFixture.CheckIsRentingPooledBuffer(2048 * 2048)); - Assert.True(StaticFixture.CheckIsRentingPooledBuffer(1024 * 16)); - } - - RemoteExecutor.Invoke(RunTest).Dispose(); - } - - [Theory] - [InlineData(-1)] - [InlineData(-111)] - public void Allocate_Negative_Throws_ArgumentOutOfRangeException(int length) - { - ArgumentOutOfRangeException ex = Assert.Throws(() => - this.LocalFixture.MemoryAllocator.Allocate(length)); - Assert.Equal("length", ex.ParamName); - } - - [Fact] - public void AllocateZero() - { - using IMemoryOwner buffer = this.LocalFixture.MemoryAllocator.Allocate(0); - Assert.Equal(0, buffer.Memory.Length); - } - - private class MemoryAllocatorFixture - { - public ArrayPoolMemoryAllocator MemoryAllocator { get; set; } = - new ArrayPoolMemoryAllocator(MaxPooledBufferSizeInBytes, PoolSelectorThresholdInBytes); - - /// - /// Rent a buffer -> return it -> re-rent -> verify if it's span points to the previous location. - /// - public bool CheckIsRentingPooledBuffer(int length) - where T : struct - { - IMemoryOwner buffer = this.MemoryAllocator.Allocate(length); - ref T ptrToPrevPosition0 = ref BufferExtensions.GetReference(buffer); - buffer.Dispose(); - - buffer = this.MemoryAllocator.Allocate(length); - bool sameBuffers = Unsafe.AreSame(ref ptrToPrevPosition0, ref BufferExtensions.GetReference(buffer)); - buffer.Dispose(); - - return sameBuffers; - } - } - - [StructLayout(LayoutKind.Sequential)] - private struct SmallStruct - { - private readonly uint dummy; - } - - private const int SizeOfLargeStruct = MaxPooledBufferSizeInBytes / 5; - - [StructLayout(LayoutKind.Explicit, Size = SizeOfLargeStruct)] - private struct LargeStruct - { - } - } -#pragma warning restore CS0618 -} diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs index 4b27360099..e2e7d73bc6 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs @@ -24,18 +24,17 @@ namespace SixLabors.ImageSharp.Tests // are shared between PixelTypes.Color & PixelTypes.Rgba32 private class Key : IEquatable { - private readonly Tuple commonValues; + private readonly Tuple commonValues; private readonly Dictionary decoderParameters; - public Key(PixelTypes pixelType, string filePath, int allocatorBufferCapacity, IImageDecoder customDecoder) + public Key(PixelTypes pixelType, string filePath, IImageDecoder customDecoder) { Type customType = customDecoder?.GetType(); - this.commonValues = new Tuple( + this.commonValues = new Tuple( pixelType, filePath, - customType, - allocatorBufferCapacity); + customType); this.decoderParameters = GetDecoderParameters(customDecoder); } @@ -153,20 +152,13 @@ namespace SixLabors.ImageSharp.Tests { Guard.NotNull(decoder, nameof(decoder)); - if (!TestEnvironment.Is64BitProcess) + // Do not cache with 64 bits or if image has been created with non-default MemoryAllocator + if (!TestEnvironment.Is64BitProcess || this.Configuration.MemoryAllocator != MemoryAllocator.Default) { return this.LoadImage(decoder); } - int bufferCapacity = -1; -#pragma warning disable CS0618 // 'ArrayPoolMemoryAllocator' is obsolete - if (this.Configuration.MemoryAllocator is ArrayPoolMemoryAllocator arrayPoolMemoryAllocator) -#pragma warning restore CS0618 - { - bufferCapacity = arrayPoolMemoryAllocator.BufferCapacityInBytes; - } - - var key = new Key(this.PixelType, this.FilePath, bufferCapacity, decoder); + var key = new Key(this.PixelType, this.FilePath, decoder); Image cachedImage = Cache.GetOrAdd(key, _ => this.LoadImage(decoder)); diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs index a30cdb4c54..700c40b726 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs @@ -21,17 +21,11 @@ namespace SixLabors.ImageSharp.Tests public abstract partial class TestImageProvider : ITestImageProvider, IXunitSerializable where TPixel : unmanaged, IPixel { - public TestImageProvider() - { - this.Configuration = Configuration.CreateDefaultInstance(); - this.Configuration.MemoryAllocator = Configuration.Default.MemoryAllocator; - } - public PixelTypes PixelType { get; private set; } = typeof(TPixel).GetPixelType(); public virtual string SourceFileOrDescription => string.Empty; - public Configuration Configuration { get; set; } + public Configuration Configuration { get; set; } = Configuration.CreateDefaultInstance(); /// /// Gets the utility instance to provide information about the test image & manage input/output. diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index d6c62645a7..719e529466 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -12,6 +12,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; +using SixLabors.ImageSharp.Tests.Memory; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; @@ -692,10 +693,7 @@ namespace SixLabors.ImageSharp.Tests this TestImageProvider provider) where TPixel : unmanaged, IPixel { - // TODO: Use a test-only allocator for this. -#pragma warning disable CS0618 // 'ArrayPoolMemoryAllocator' is obsolete - var allocator = ArrayPoolMemoryAllocator.CreateDefault(); -#pragma warning restore + var allocator = new TestMemoryAllocator(); provider.Configuration.MemoryAllocator = allocator; return new AllocatorBufferCapacityConfigurator(allocator, Unsafe.SizeOf()); } @@ -781,10 +779,10 @@ namespace SixLabors.ImageSharp.Tests internal class AllocatorBufferCapacityConfigurator { #pragma warning disable CS0618 // 'ArrayPoolMemoryAllocator' is obsolete - private readonly ArrayPoolMemoryAllocator allocator; + private readonly TestMemoryAllocator allocator; private readonly int pixelSizeInBytes; - public AllocatorBufferCapacityConfigurator(ArrayPoolMemoryAllocator allocator, int pixelSizeInBytes) + public AllocatorBufferCapacityConfigurator(TestMemoryAllocator allocator, int pixelSizeInBytes) { this.allocator = allocator; this.pixelSizeInBytes = pixelSizeInBytes; diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index f3b321f306..e24fb7624f 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -12,6 +12,7 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.ImageSharp.Tests.Memory; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; @@ -165,10 +166,7 @@ namespace SixLabors.ImageSharp.Tests int width = expected.Width; expected.Mutate(process); - // TODO: Use a test-only allocator for this -#pragma warning disable CS0618 // 'ArrayPoolMemoryAllocator' is obsolete - var allocator = ArrayPoolMemoryAllocator.CreateDefault(); -#pragma warning restore CS0618 + var allocator = new TestMemoryAllocator(); provider.Configuration.MemoryAllocator = allocator; allocator.BufferCapacityInBytes = bufferCapacityInPixelRows * width * Unsafe.SizeOf();