Browse Source

add some tests for CopyTo

af/octree-no-pixelmap
Anton Firszov 6 years ago
parent
commit
302c06b3a6
  1. 20
      src/ImageSharp/Memory/DiscontiguousBuffers/IMemoryGroup{T}.cs
  2. 3
      src/ImageSharp/Memory/DiscontiguousBuffers/InvalidMemoryOperationException.cs
  3. 16
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs
  4. 24
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs
  5. 7
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs
  6. 7
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs
  7. 39
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs
  8. 120
      tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupIndex.cs
  9. 64
      tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupIndexTests.cs
  10. 119
      tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.Allocate.cs
  11. 45
      tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.CopyTo.cs
  12. 148
      tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.cs

20
src/ImageSharp/Memory/DiscontiguousBuffers/IMemoryGroup{T}.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
@ -12,10 +15,23 @@ namespace SixLabors.ImageSharp.Memory
where T : struct
{
/// <summary>
/// Gets the number of elements per contiguous sub-block.
/// Gets the number of elements per contiguous sub-buffer preceding the last buffer.
/// The last buffer is allowed to be smaller.
/// </summary>
public int BufferLength { get; }
/// <summary>
/// Gets the aggregate number of elements in the group.
/// </summary>
public int BufferSize { get; }
public long TotalLength { get; }
/// <summary>
/// Gets a value indicating whether the group has been invalidated.
/// </summary>
/// <remarks>
/// Invalidation usually occurs when an image processor capable to alter the image dimensions replaces
/// the image buffers internally.
/// </remarks>
bool IsValid { get; }
}
}

3
src/ImageSharp/Memory/DiscontiguousBuffers/InvalidMemoryOperationException.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.Memory

16
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs

@ -0,0 +1,16 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.Memory
{
internal static class MemoryGroupExtensions
{
public static void CopyTo<T>(this IMemoryGroup<T> source, IMemoryGroup<T> target)
where T : struct
{
throw new NotImplementedException();
}
}
}

24
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Collections;
@ -15,7 +18,8 @@ namespace SixLabors.ImageSharp.Memory
/// instance becomes invalid, throwing an exception on all operations.
/// </remarks>
/// <typeparam name="T">The element type.</typeparam>
internal class MemoryGroupView<T> : IMemoryGroup<T> where T : struct
internal class MemoryGroupView<T> : IMemoryGroup<T>
where T : struct
{
private readonly Memory.MemoryGroup<T> owner;
private readonly MemoryOwnerWrapper[] memoryWrappers;
@ -32,23 +36,25 @@ namespace SixLabors.ImageSharp.Memory
}
}
public IEnumerator<Memory<T>> GetEnumerator() => throw new NotImplementedException();
public int Count => this.owner.Count;
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
public int BufferLength => this.owner.BufferLength;
public long TotalLength => this.owner.TotalLength;
public int Count { get; }
public bool IsValid { get; internal set; }
public Memory<T> this[int index] => throw new NotImplementedException();
public int BufferSize => this.owner.BufferSize;
public IEnumerator<Memory<T>> GetEnumerator() => throw new NotImplementedException();
public bool IsValid { get; internal set; }
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
class MemoryOwnerWrapper : MemoryManager<T>
private class MemoryOwnerWrapper : MemoryManager<T>
{
private MemoryGroupView<T> view;
private readonly MemoryGroupView<T> view;
private int index;
private readonly int index;
public MemoryOwnerWrapper(MemoryGroupView<T> view, int index)
{

7
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
@ -10,8 +13,8 @@ namespace SixLabors.ImageSharp.Memory
{
private readonly ReadOnlyMemory<Memory<T>> source;
public Consumed(ReadOnlyMemory<Memory<T>> source, int bufferSize)
: base(bufferSize)
public Consumed(ReadOnlyMemory<Memory<T>> source, int bufferLength, long totalLength)
: base(bufferLength, totalLength)
{
this.source = source;
}

7
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Collections.Generic;
@ -12,8 +15,8 @@ namespace SixLabors.ImageSharp.Memory
{
private IMemoryOwner<T>[] memoryOwners;
public Owned(IMemoryOwner<T>[] memoryOwners, int bufferSize)
: base(bufferSize)
public Owned(IMemoryOwner<T>[] memoryOwners, int bufferLength, long totalLength)
: base(bufferLength, totalLength)
{
this.memoryOwners = memoryOwners;
}

39
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Collections;
@ -17,11 +20,17 @@ namespace SixLabors.ImageSharp.Memory
{
private static readonly int ElementSize = Unsafe.SizeOf<T>();
private MemoryGroup(int bufferSize) => this.BufferSize = bufferSize;
private MemoryGroup(int bufferLength, long totalLength)
{
this.BufferLength = bufferLength;
this.TotalLength = totalLength;
}
public abstract int Count { get; }
public int BufferSize { get; }
public int BufferLength { get; }
public long TotalLength { get; }
public bool IsValid { get; private set; } = true;
@ -51,18 +60,18 @@ namespace SixLabors.ImageSharp.Memory
}
int numberOfAlignedSegments = blockCapacityInElements / blockAlignment;
int bufferSize = numberOfAlignedSegments * blockAlignment;
if (totalLength > 0 && totalLength < bufferSize)
int bufferLength = numberOfAlignedSegments * blockAlignment;
if (totalLength > 0 && totalLength < bufferLength)
{
bufferSize = (int)totalLength;
bufferLength = (int)totalLength;
}
int sizeOfLastBuffer = (int)(totalLength % bufferSize);
long bufferCount = totalLength / bufferSize;
int sizeOfLastBuffer = (int)(totalLength % bufferLength);
long bufferCount = totalLength / bufferLength;
if (sizeOfLastBuffer == 0)
{
sizeOfLastBuffer = bufferSize;
sizeOfLastBuffer = bufferLength;
}
else
{
@ -72,7 +81,7 @@ namespace SixLabors.ImageSharp.Memory
var buffers = new IMemoryOwner<T>[bufferCount];
for (int i = 0; i < buffers.Length - 1; i++)
{
buffers[i] = allocator.Allocate<T>(bufferSize, allocationOptions);
buffers[i] = allocator.Allocate<T>(bufferLength, allocationOptions);
}
if (bufferCount > 0)
@ -80,28 +89,30 @@ namespace SixLabors.ImageSharp.Memory
buffers[^1] = allocator.Allocate<T>(sizeOfLastBuffer, allocationOptions);
}
return new Owned(buffers, bufferSize);
return new Owned(buffers, bufferLength, totalLength);
}
public static MemoryGroup<T> Wrap(params Memory<T>[] source) => Wrap(source.AsMemory());
public static MemoryGroup<T> Wrap(ReadOnlyMemory<Memory<T>> source)
{
int bufferSize = source.Length > 0 ? source.Span[0].Length : 0;
int bufferLength = source.Length > 0 ? source.Span[0].Length : 0;
for (int i = 1; i < source.Length - 1; i++)
{
if (source.Span[i].Length != bufferSize)
if (source.Span[i].Length != bufferLength)
{
throw new InvalidMemoryOperationException("Wrap: buffers should be uniformly sized!");
}
}
if (source.Length > 0 && source.Span[^1].Length > bufferSize)
if (source.Length > 0 && source.Span[^1].Length > bufferLength)
{
throw new InvalidMemoryOperationException("Wrap: the last buffer is too large!");
}
return new Consumed(source, bufferSize);
long totalLength = bufferLength > 0 ? ((long)bufferLength * (source.Length - 1)) + source.Span[^1].Length : 0;
return new Consumed(source, bufferLength, totalLength);
}
// Analogous to current MemorySource.SwapOrCopyContent()

120
tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupIndex.cs

@ -0,0 +1,120 @@
using System;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers
{
public struct MemoryGroupIndex : IEquatable<MemoryGroupIndex>
{
public override bool Equals(object obj) => obj is MemoryGroupIndex other && this.Equals(other);
public override int GetHashCode() => HashCode.Combine(this.BufferLength, this.BufferIndex, this.ElementIndex);
public int BufferLength { get; }
public int BufferIndex { get; }
public int ElementIndex { get; }
public MemoryGroupIndex(int bufferLength, int bufferIndex, int elementIndex)
{
this.BufferLength = bufferLength;
this.BufferIndex = bufferIndex;
this.ElementIndex = elementIndex;
}
public static MemoryGroupIndex operator +(MemoryGroupIndex idx, int val)
{
int nextElementIndex = idx.ElementIndex + val;
return new MemoryGroupIndex(
idx.BufferLength,
idx.BufferIndex + (nextElementIndex / idx.BufferLength),
nextElementIndex % idx.BufferLength);
}
public bool Equals(MemoryGroupIndex other)
{
if (this.BufferLength != other.BufferLength)
{
throw new InvalidOperationException();
}
return this.BufferIndex == other.BufferIndex && this.ElementIndex == other.ElementIndex;
}
public static bool operator ==(MemoryGroupIndex a, MemoryGroupIndex b) => a.Equals(b);
public static bool operator !=(MemoryGroupIndex a, MemoryGroupIndex b) => !a.Equals(b);
public static bool operator <(MemoryGroupIndex a, MemoryGroupIndex b)
{
if (a.BufferLength != b.BufferLength)
{
throw new InvalidOperationException();
}
if (a.BufferIndex < b.BufferIndex)
{
return true;
}
if (a.BufferIndex == b.BufferIndex)
{
return a.ElementIndex < b.ElementIndex;
}
return false;
}
public static bool operator >(MemoryGroupIndex a, MemoryGroupIndex b)
{
if (a.BufferLength != b.BufferLength)
{
throw new InvalidOperationException();
}
if (a.BufferIndex > b.BufferIndex)
{
return true;
}
if (a.BufferIndex == b.BufferIndex)
{
return a.ElementIndex > b.ElementIndex;
}
return false;
}
}
internal static class MemoryGroupIndexExtensions
{
public static T GetElementAt<T>(this MemoryGroup<T> group, MemoryGroupIndex idx)
where T : struct
{
return group[idx.BufferIndex].Span[idx.ElementIndex];
}
public static void SetElementAt<T>(this MemoryGroup<T> group, MemoryGroupIndex idx, T value)
where T : struct
{
group[idx.BufferIndex].Span[idx.ElementIndex] = value;
}
public static MemoryGroupIndex MinIndex<T>(this MemoryGroup<T> group)
where T : struct
{
return new MemoryGroupIndex(group.BufferLength, 0, 0);
}
public static MemoryGroupIndex MaxIndex<T>(this MemoryGroup<T> group)
where T : struct
{
if (group.Count == 0)
{
return new MemoryGroupIndex(group.BufferLength, 0, 0);
}
return new MemoryGroupIndex(group.BufferLength, group.Count - 1, group[^1].Length - 1);
}
}
}

64
tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupIndexTests.cs

@ -0,0 +1,64 @@
using Xunit;
namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers
{
public class MemoryGroupIndexTests
{
[Fact]
public void Equal()
{
var a = new MemoryGroupIndex(10, 1, 3);
var b = new MemoryGroupIndex(10, 1, 3);
Assert.True(a.Equals(b));
Assert.True(a == b);
Assert.False(a != b);
Assert.False(a < b);
Assert.False(a > b);
}
[Fact]
public void SmallerBufferIndex()
{
var a = new MemoryGroupIndex(10, 3, 3);
var b = new MemoryGroupIndex(10, 5, 3);
Assert.False(a == b);
Assert.True(a != b);
Assert.True(a < b);
Assert.False(a > b);
}
[Fact]
public void SmallerElementIndex()
{
var a = new MemoryGroupIndex(10, 3, 3);
var b = new MemoryGroupIndex(10, 3, 9);
Assert.False(a == b);
Assert.True(a != b);
Assert.True(a < b);
Assert.False(a > b);
}
[Fact]
public void Increment()
{
var a = new MemoryGroupIndex(10, 3, 3);
a += 1;
Assert.Equal(new MemoryGroupIndex(10, 3, 4), a);
}
[Fact]
public void Increment_OverflowBuffer()
{
var a = new MemoryGroupIndex(10, 5, 3);
var b = new MemoryGroupIndex(10, 5, 9);
a += 8;
b += 1;
Assert.Equal(new MemoryGroupIndex(10, 6, 1), a);
Assert.Equal(new MemoryGroupIndex(10, 6, 0), b);
}
}
}

119
tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.Allocate.cs

@ -0,0 +1,119 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System.Linq;
using SixLabors.ImageSharp.Memory;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers
{
public partial class MemoryGroupTests
{
public class Allocate : MemoryGroupTestsBase
{
#pragma warning disable SA1509
public static TheoryData<object, int, int, long, int, int, int> AllocateData =
new TheoryData<object, int, int, long, int, int, int>()
{
{ default(S5), 22, 4, 4, 1, 4, 4 },
{ default(S5), 22, 4, 7, 2, 4, 3 },
{ default(S5), 22, 4, 8, 2, 4, 4 },
{ default(S5), 22, 4, 21, 6, 4, 1 },
{ default(S5), 22, 4, 0, 0, 4, -1 },
{ default(S4), 50, 12, 12, 1, 12, 12 },
{ default(S4), 50, 7, 12, 2, 7, 5 },
{ default(S4), 50, 6, 12, 1, 12, 12 },
{ default(S4), 50, 5, 12, 2, 10, 2 },
{ default(S4), 50, 4, 12, 1, 12, 12 },
{ default(S4), 50, 3, 12, 1, 12, 12 },
{ default(S4), 50, 2, 12, 1, 12, 12 },
{ default(S4), 50, 1, 12, 1, 12, 12 },
{ default(S4), 50, 12, 13, 2, 12, 1 },
{ default(S4), 50, 7, 21, 3, 7, 7 },
{ default(S4), 50, 7, 23, 4, 7, 2 },
{ default(S4), 50, 6, 13, 2, 12, 1 },
{ default(short), 200, 50, 49, 1, 49, 49 },
{ default(short), 200, 50, 1, 1, 1, 1 },
{ default(byte), 1000, 512, 2047, 4, 512, 511 }
};
[Theory]
[MemberData(nameof(AllocateData))]
public void BufferSizesAreCorrect<T>(
T dummy,
int bufferCapacity,
int bufferAlignment,
long totalLength,
int expectedNumberOfBuffers,
int expectedBufferSize,
int expectedSizeOfLastBuffer)
where T : struct
{
this.MemoryAllocator.BufferCapacity = bufferCapacity;
// Act:
using var g = MemoryGroup<T>.Allocate(this.MemoryAllocator, totalLength, bufferAlignment);
// Assert:
Assert.Equal(expectedNumberOfBuffers, g.Count);
Assert.Equal(expectedBufferSize, g.BufferLength);
if (g.Count == 0)
{
return;
}
for (int i = 0; i < g.Count - 1; i++)
{
Assert.Equal(g[i].Length, expectedBufferSize);
}
Assert.Equal(g.Last().Length, expectedSizeOfLastBuffer);
}
[Fact]
public void WhenBlockAlignmentIsOverCapacity_Throws_InvalidMemoryOperationException()
{
this.MemoryAllocator.BufferCapacity = 84; // 42 * Int16
Assert.Throws<InvalidMemoryOperationException>(() =>
{
MemoryGroup<short>.Allocate(this.MemoryAllocator, 50, 43);
});
}
[Theory]
[InlineData(AllocationOptions.None)]
[InlineData(AllocationOptions.Clean)]
public void MemoryAllocatorIsUtilizedCorrectly(AllocationOptions allocationOptions)
{
this.MemoryAllocator.BufferCapacity = 200;
HashSet<int> bufferHashes;
int expectedBlockCount = 5;
using (var g = MemoryGroup<short>.Allocate(this.MemoryAllocator, 500, 100, allocationOptions))
{
IReadOnlyList<TestMemoryAllocator.AllocationRequest> allocationLog = this.MemoryAllocator.AllocationLog;
Assert.Equal(expectedBlockCount, allocationLog.Count);
bufferHashes = allocationLog.Select(l => l.HashCodeOfBuffer).ToHashSet();
Assert.Equal(expectedBlockCount, bufferHashes.Count);
Assert.Equal(0, this.MemoryAllocator.ReturnLog.Count);
for (int i = 0; i < expectedBlockCount; i++)
{
Assert.Equal(allocationOptions, allocationLog[i].AllocationOptions);
Assert.Equal(100, allocationLog[i].Length);
Assert.Equal(200, allocationLog[i].LengthInBytes);
}
}
Assert.Equal(expectedBlockCount, this.MemoryAllocator.ReturnLog.Count);
Assert.True(bufferHashes.SetEquals(this.MemoryAllocator.ReturnLog.Select(l => l.HashCodeOfBuffer)));
}
}
}
}

45
tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.CopyTo.cs

@ -0,0 +1,45 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Memory;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers
{
public partial class MemoryGroupTests
{
public class CopyTo : MemoryGroupTestsBase
{
public static readonly TheoryData<int, int, int, int> WhenSourceBufferIsShorterOrEqual_Data =
new TheoryData<int, int, int, int>()
{
{ 20, 5, 20, 4 },
{ 20, 4, 20, 5 },
{ 18, 6, 20, 5 },
{ 19, 10, 20, 10 },
{ 21, 10, 22, 2 },
{ 1, 5, 5, 4 },
};
[Theory]
[MemberData(nameof(WhenSourceBufferIsShorterOrEqual_Data))]
public void WhenSourceBufferIsShorterOrEqual(int srcTotal, int srcBufLen, int trgTotal, int trgBufLen)
{
using MemoryGroup<int> src = this.CreateTestGroup(srcTotal, srcBufLen, true);
using MemoryGroup<int> trg = this.CreateTestGroup(trgTotal, trgBufLen, false);
src.CopyTo(trg);
MemoryGroupIndex i = src.MinIndex();
MemoryGroupIndex j = trg.MinIndex();
for (; i < src.MaxIndex(); i += 1, j += 1)
{
int a = src.GetElementAt(i);
int b = src.GetElementAt(j);
Assert.Equal(a, b);
}
}
}
}
}

148
tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.cs

@ -1,128 +1,18 @@
using System.Collections.Generic;
using System.Linq;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using Xunit;
using Xunit.Sdk;
namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers
{
public class MemoryGroupTests
public partial class MemoryGroupTests : MemoryGroupTestsBase
{
private readonly TestMemoryAllocator memoryAllocator = new TestMemoryAllocator();
public class Allocate
{
private readonly TestMemoryAllocator memoryAllocator = new TestMemoryAllocator();
#pragma warning disable SA1509
public static TheoryData<object, int, int, long, int, int, int> AllocateData =
new TheoryData<object, int, int, long, int, int, int>()
{
{ default(S5), 22, 4, 4, 1, 4, 4 },
{ default(S5), 22, 4, 7, 2, 4, 3 },
{ default(S5), 22, 4, 8, 2, 4, 4 },
{ default(S5), 22, 4, 21, 6, 4, 1 },
{ default(S5), 22, 4, 0, 0, 4, -1 },
{ default(S4), 50, 12, 12, 1, 12, 12 },
{ default(S4), 50, 7, 12, 2, 7, 5 },
{ default(S4), 50, 6, 12, 1, 12, 12 },
{ default(S4), 50, 5, 12, 2, 10, 2 },
{ default(S4), 50, 4, 12, 1, 12, 12 },
{ default(S4), 50, 3, 12, 1, 12, 12 },
{ default(S4), 50, 2, 12, 1, 12, 12 },
{ default(S4), 50, 1, 12, 1, 12, 12 },
{ default(S4), 50, 12, 13, 2, 12, 1 },
{ default(S4), 50, 7, 21, 3, 7, 7 },
{ default(S4), 50, 7, 23, 4, 7, 2 },
{ default(S4), 50, 6, 13, 2, 12, 1 },
{ default(short), 200, 50, 49, 1, 49, 49 },
{ default(short), 200, 50, 1, 1, 1, 1 },
{ default(byte), 1000, 512, 2047, 4, 512, 511 }
};
[Theory]
[MemberData(nameof(AllocateData))]
public void BufferSizesAreCorrect<T>(
T dummy,
int bufferCapacity,
int bufferAlignment,
long totalLength,
int expectedNumberOfBuffers,
int expectedBufferSize,
int expectedSizeOfLastBuffer)
where T : struct
{
this.memoryAllocator.BufferCapacity = bufferCapacity;
// Act:
using var g = MemoryGroup<T>.Allocate(this.memoryAllocator, totalLength, bufferAlignment);
// Assert:
Assert.Equal(expectedNumberOfBuffers, g.Count);
Assert.Equal(expectedBufferSize, g.BufferSize);
if (g.Count == 0)
{
return;
}
for (int i = 0; i < g.Count - 1; i++)
{
Assert.Equal(g[i].Length, expectedBufferSize);
}
Assert.Equal(g.Last().Length, expectedSizeOfLastBuffer);
}
[Fact]
public void WhenBlockAlignmentIsOverCapacity_Throws_InvalidMemoryOperationException()
{
this.memoryAllocator.BufferCapacity = 84; // 42 * Int16
Assert.Throws<InvalidMemoryOperationException>(() =>
{
MemoryGroup<short>.Allocate(this.memoryAllocator, 50, 43);
});
}
[Theory]
[InlineData(AllocationOptions.None)]
[InlineData(AllocationOptions.Clean)]
public void MemoryAllocatorIsUtilizedCorrectly(AllocationOptions allocationOptions)
{
this.memoryAllocator.BufferCapacity = 200;
HashSet<int> bufferHashes;
int expectedBlockCount = 5;
using (var g = MemoryGroup<short>.Allocate(this.memoryAllocator, 500, 100, allocationOptions))
{
IReadOnlyList<TestMemoryAllocator.AllocationRequest> allocationLog = this.memoryAllocator.AllocationLog;
Assert.Equal(expectedBlockCount, allocationLog.Count);
bufferHashes = allocationLog.Select(l => l.HashCodeOfBuffer).ToHashSet();
Assert.Equal(expectedBlockCount, bufferHashes.Count);
Assert.Equal(0, this.memoryAllocator.ReturnLog.Count);
for (int i = 0; i < expectedBlockCount; i++)
{
Assert.Equal(allocationOptions, allocationLog[i].AllocationOptions);
Assert.Equal(100, allocationLog[i].Length);
Assert.Equal(200, allocationLog[i].LengthInBytes);
}
}
Assert.Equal(expectedBlockCount, this.memoryAllocator.ReturnLog.Count);
Assert.True(bufferHashes.SetEquals(this.memoryAllocator.ReturnLog.Select(l => l.HashCodeOfBuffer)));
}
}
[Fact]
public void IsValid_TrueAfterCreation()
{
using var g = MemoryGroup<byte>.Allocate(this.memoryAllocator, 10, 100);
using var g = MemoryGroup<byte>.Allocate(this.MemoryAllocator, 10, 100);
Assert.True(g.IsValid);
}
@ -130,12 +20,13 @@ namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers
[Fact]
public void IsValid_FalseAfterDisposal()
{
using var g = MemoryGroup<byte>.Allocate(this.memoryAllocator, 10, 100);
using var g = MemoryGroup<byte>.Allocate(this.MemoryAllocator, 10, 100);
g.Dispose();
Assert.False(g.IsValid);
}
[StructLayout(LayoutKind.Sequential, Size = 5)]
private struct S5
{
@ -148,4 +39,29 @@ namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers
public override string ToString() => "S4";
}
}
public abstract class MemoryGroupTestsBase
{
internal readonly TestMemoryAllocator MemoryAllocator = new TestMemoryAllocator();
internal MemoryGroup<int> CreateTestGroup(long totalLength, int bufferLength, bool fillSequence = false)
{
this.MemoryAllocator.BufferCapacity = bufferLength;
var g = MemoryGroup<int>.Allocate(this.MemoryAllocator, totalLength, bufferLength);
if (!fillSequence)
{
return g;
}
int j = 1;
for (MemoryGroupIndex i = g.MinIndex(); i < g.MaxIndex(); i += 1)
{
g.SetElementAt(i, j);
j++;
}
return g;
}
}
}

Loading…
Cancel
Save