// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using Xunit; namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers { public partial class MemoryGroupTests { public class SwapOrCopyContent : MemoryGroupTestsBase { [Fact] public void WhenBothAreMemoryOwners_ShouldSwap() { this.MemoryAllocator.BufferCapacityInBytes = sizeof(int) * 50; using MemoryGroup a = this.MemoryAllocator.AllocateGroup(100, 50); using MemoryGroup b = this.MemoryAllocator.AllocateGroup(120, 50); Memory a0 = a[0]; Memory a1 = a[1]; Memory b0 = b[0]; Memory b1 = b[1]; bool swap = MemoryGroup.SwapOrCopyContent(a, b); Assert.True(swap); Assert.Equal(b0, a[0]); Assert.Equal(b1, a[1]); Assert.Equal(a0, b[0]); Assert.Equal(a1, b[1]); Assert.NotEqual(a[0], b[0]); } [Fact] public void WhenBothAreMemoryOwners_ShouldReplaceViews() { using MemoryGroup a = this.MemoryAllocator.AllocateGroup(100, 100); using MemoryGroup b = this.MemoryAllocator.AllocateGroup(120, 100); a[0].Span[42] = 1; b[0].Span[33] = 2; MemoryGroupView aView0 = a.View; MemoryGroupView bView0 = b.View; MemoryGroup.SwapOrCopyContent(a, b); Assert.False(aView0.IsValid); Assert.False(bView0.IsValid); Assert.ThrowsAny(() => _ = aView0[0].Span); Assert.ThrowsAny(() => _ = bView0[0].Span); Assert.True(a.View.IsValid); Assert.True(b.View.IsValid); Assert.Equal(2, a.View[0].Span[33]); Assert.Equal(1, b.View[0].Span[42]); } [Theory] [InlineData(false)] [InlineData(true)] public void WhenDestIsNotAllocated_SameSize_ShouldCopy(bool sourceIsAllocated) { var data = new Rgba32[21]; var color = new Rgba32(1, 2, 3, 4); using var destOwner = new TestMemoryManager(data); using var dest = MemoryGroup.Wrap(destOwner.Memory); using MemoryGroup source = this.MemoryAllocator.AllocateGroup(21, 30); source[0].Span[10] = color; // Act: bool swap = MemoryGroup.SwapOrCopyContent(dest, source); // Assert: Assert.False(swap); Assert.Equal(color, dest[0].Span[10]); Assert.NotEqual(source[0], dest[0]); } [Theory] [InlineData(false)] [InlineData(true)] public void WhenDestIsNotMemoryOwner_DifferentSize_Throws(bool sourceIsOwner) { var data = new Rgba32[21]; var color = new Rgba32(1, 2, 3, 4); using var destOwner = new TestMemoryManager(data); var dest = MemoryGroup.Wrap(destOwner.Memory); using MemoryGroup source = this.MemoryAllocator.AllocateGroup(22, 30); source[0].Span[10] = color; // Act: Assert.ThrowsAny(() => MemoryGroup.SwapOrCopyContent(dest, source)); Assert.Equal(color, source[0].Span[10]); Assert.NotEqual(color, dest[0].Span[10]); } } } }