From 5875022a0d6615974a3f3775ea18f7a6b41cb972 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 1 Jul 2017 13:56:58 +0200 Subject: [PATCH 1/3] updated xunit to 2.3.0-beta3-build3705, fixed errors reported by xunit analyzer --- .../ImageSharp.Sandbox46.csproj | 2 +- .../Colorspaces/ColorSpaceEqualityTests.cs | 17 +++++++++-------- .../Image/PixelAccessorTests.cs | 16 ++++++++-------- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 4 ++-- .../PixelFormats/ColorDefinitionTests.cs | 13 ++++++++++++- 5 files changed, 32 insertions(+), 20 deletions(-) diff --git a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj index ae17f3698..b9124afc6 100644 --- a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj +++ b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj @@ -18,7 +18,7 @@ - + diff --git a/tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs b/tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs index 2a5462b40..da58ddcda 100644 --- a/tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs +++ b/tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs @@ -3,6 +3,7 @@ // Licensed under the Apache License, Version 2.0. // +// ReSharper disable InconsistentNaming namespace ImageSharp.Tests.Colorspaces { using System; @@ -141,7 +142,7 @@ namespace ImageSharp.Tests.Colorspaces [Theory] [MemberData(nameof(EmptyData))] - public void Equality(IColorVector color) + public void Vector_Equals_WhenTrue(IColorVector color) { // Act bool equal = color.Vector.Equals(Vector3.Zero); @@ -152,7 +153,7 @@ namespace ImageSharp.Tests.Colorspaces [Theory] [MemberData(nameof(EqualityData))] - public void Equality(object first, object second, Type type) + public void Equals_WhenTrue(object first, object second, Type type) { // Act bool equal = first.Equals(second); @@ -165,7 +166,7 @@ namespace ImageSharp.Tests.Colorspaces [MemberData(nameof(NotEqualityDataNulls))] [MemberData(nameof(NotEqualityDataDifferentObjects))] [MemberData(nameof(NotEqualityData))] - public void NotEquality(object first, object second, Type type) + public void Equals_WhenFalse(object first, object second, Type type) { // Act bool equal = first.Equals(second); @@ -176,7 +177,7 @@ namespace ImageSharp.Tests.Colorspaces [Theory] [MemberData(nameof(EqualityData))] - public void HashCodeEqual(object first, object second, Type type) + public void GetHashCode_WhenEqual(object first, object second, Type type) { // Act bool equal = first.GetHashCode() == second.GetHashCode(); @@ -187,7 +188,7 @@ namespace ImageSharp.Tests.Colorspaces [Theory] [MemberData(nameof(NotEqualityDataDifferentObjects))] - public void HashCodeNotEqual(object first, object second, Type type) + public void GetHashCode_WhenNotEqual(object first, object second, Type type) { // Act bool equal = first.GetHashCode() == second.GetHashCode(); @@ -198,7 +199,7 @@ namespace ImageSharp.Tests.Colorspaces [Theory] [MemberData(nameof(EqualityData))] - public void EqualityObject(object first, object second, Type type) + public void GenericEquals_WhenTrue(object first, object second, Type type) { // Arrange // Cast to the known object types, this is so that we can hit the @@ -216,7 +217,7 @@ namespace ImageSharp.Tests.Colorspaces [Theory] [MemberData(nameof(NotEqualityData))] - public void NotEqualityObject(object first, object second, Type type) + public void GenericEquals_WhenFalse(object first, object second, Type type) { // Arrange // Cast to the known object types, this is so that we can hit the @@ -253,7 +254,7 @@ namespace ImageSharp.Tests.Colorspaces [Theory] [MemberData(nameof(NotEqualityData))] - public void NotEqualityOperator(object first, object second, Type type) + public void Operator_WhenTrue(object first, object second, Type type) { // Arrange // Cast to the known object types, this is so that we can hit the diff --git a/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs b/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs index b59023340..0eeb468f0 100644 --- a/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs +++ b/tests/ImageSharp.Tests/Image/PixelAccessorTests.cs @@ -113,7 +113,7 @@ namespace ImageSharp.Tests { using (Image image = new Image(1, 1)) { - CopyFromZYX(image); + CopyFromZYXImpl(image); } } @@ -122,7 +122,7 @@ namespace ImageSharp.Tests { using (Image image = new Image(1, 1)) { - CopyFromZYXW(image); + CopyFromZYXWImpl(image); } } @@ -131,7 +131,7 @@ namespace ImageSharp.Tests { using (Image image = new Image(1, 1)) { - CopyToZYX(image); + CopyToZYXImpl(image); } } @@ -140,11 +140,11 @@ namespace ImageSharp.Tests { using (Image image = new Image(1, 1)) { - CopyToZYXW(image); + CopyToZYXWImpl(image); } } - private static void CopyFromZYX(Image image) + private static void CopyFromZYXImpl(Image image) where TPixel : struct, IPixel { using (PixelAccessor pixels = image.Lock()) @@ -171,7 +171,7 @@ namespace ImageSharp.Tests } } - private static void CopyFromZYXW(Image image) + private static void CopyFromZYXWImpl(Image image) where TPixel : struct, IPixel { using (PixelAccessor pixels = image.Lock()) @@ -199,7 +199,7 @@ namespace ImageSharp.Tests } } - private static void CopyToZYX(Image image) + private static void CopyToZYXImpl(Image image) where TPixel : struct, IPixel { using (PixelAccessor pixels = image.Lock()) @@ -221,7 +221,7 @@ namespace ImageSharp.Tests } } - private static void CopyToZYXW(Image image) + private static void CopyToZYXWImpl(Image image) where TPixel : struct, IPixel { using (PixelAccessor pixels = image.Lock()) diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 9f3beb9e8..b0429d9ed 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs b/tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs index 7e5af9297..db5b4a4c9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs @@ -15,7 +15,18 @@ namespace ImageSharp.Tests public class ColorDefinitionTests { - public static IEnumerable ColorNames => typeof(NamedColors).GetTypeInfo().GetFields().Select(x => new[] { x.Name }); + public static TheoryData ColorNames + { + get + { + var result = new TheoryData(); + foreach (string name in typeof(NamedColors).GetTypeInfo().GetFields().Select(x => x.Name )) + { + result.Add(name); + } + return result; + } + } [Theory] [MemberData(nameof(ColorNames))] From 9460065c08b030a2ce79c15302485e7298069632 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Thu, 6 Jul 2017 20:52:11 +0200 Subject: [PATCH 2/3] Also support non ushort values of ExifTag.Orientation (Fixes #271). --- .../Processing/Transforms/AutoOrient.cs | 12 ++++++- .../Processing/Transforms/AutoOrientTests.cs | 35 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Processing/Transforms/AutoOrient.cs b/src/ImageSharp/Processing/Transforms/AutoOrient.cs index 07e5d5bc9..7e7c66460 100644 --- a/src/ImageSharp/Processing/Transforms/AutoOrient.cs +++ b/src/ImageSharp/Processing/Transforms/AutoOrient.cs @@ -5,6 +5,7 @@ namespace ImageSharp { + using System; using ImageSharp.PixelFormats; using ImageSharp.Processing; @@ -77,7 +78,16 @@ namespace ImageSharp return Orientation.Unknown; } - var orientation = (Orientation)value.Value; + Orientation orientation; + if (value.DataType == ExifDataType.Short) + { + orientation = (Orientation)value.Value; + } + else + { + orientation = (Orientation)Convert.ToUInt16(value.Value); + source.MetaData.ExifProfile.RemoveValue(ExifTag.Orientation); + } source.MetaData.ExifProfile.SetValue(ExifTag.Orientation, (ushort)Orientation.TopLeft); diff --git a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs index 7bc0c8bb5..0646dc937 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs @@ -5,6 +5,7 @@ namespace ImageSharp.Tests.Processing.Transforms { + using System; using ImageSharp.PixelFormats; using ImageSharp.Processing; @@ -28,6 +29,16 @@ namespace ImageSharp.Tests.Processing.Transforms { RotateType.Rotate90, FlipType.None, 8 }, }; + public static readonly TheoryData InvalidOrientationValues + = new TheoryData + { + { ExifDataType.Byte, new byte[] { 1 } }, + { ExifDataType.SignedByte, new byte[] { 2 } }, + { ExifDataType.SignedShort, BitConverter.GetBytes((short) 3) }, + { ExifDataType.Long, BitConverter.GetBytes((uint) 4) }, + { ExifDataType.SignedLong, BitConverter.GetBytes((int) 5) } + }; + [Theory] [WithFileCollection(nameof(FlipFiles), nameof(OrientationValues), DefaultPixelType)] public void ImageShouldAutoRotate(TestImageProvider provider, RotateType rotateType, FlipType flipType, ushort orientation) @@ -44,5 +55,29 @@ namespace ImageSharp.Tests.Processing.Transforms .DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "2_after"), Extensions.Bmp); } } + + [Theory] + [WithFileCollection(nameof(FlipFiles), nameof(InvalidOrientationValues), DefaultPixelType)] + public void ImageShouldAutoRotateInvalidValues(TestImageProvider provider, ExifDataType dataType, byte[] orientation) + where TPixel : struct, IPixel + { + var profile = new ExifProfile(); + profile.SetValue(ExifTag.JPEGTables, orientation); + + byte[] bytes = profile.ToByteArray(); + // Change the tag into ExifTag.Orientation + bytes[16] = 18; + bytes[17] = 1; + // Change the data type + bytes[18] = (byte)dataType; + // Change the number of components + bytes[20] = 1; + + using (Image image = provider.GetImage()) + { + image.MetaData.ExifProfile = new ExifProfile(bytes); + image.AutoOrient(); + } + } } } \ No newline at end of file From f017fdbf2f2e7f9b68a064a46319a4a263e18e63 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 11 Jul 2017 18:44:16 +0100 Subject: [PATCH 3/3] initail image operations tests --- src/ImageSharp/ApplyProcessors.cs | 26 +++- src/ImageSharp/Configuration.cs | 7 +- src/ImageSharp/IImageOperationsProvider.cs | 38 ++++++ src/ImageSharp/IImageOperations{TPixel}.cs | 2 +- .../Processing/DelegateImageProcessor.cs | 5 + src/Shared/AssemblyInfo.Common.cs | 4 +- .../BaseImageOperationsExtensionTest.cs | 25 ++++ .../FakeImageOperationsProvider.cs | 77 +++++++++++ tests/ImageSharp.Tests/ImageOperationTests.cs | 120 ++++++++++++++++++ 9 files changed, 297 insertions(+), 7 deletions(-) create mode 100644 src/ImageSharp/IImageOperationsProvider.cs create mode 100644 tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs create mode 100644 tests/ImageSharp.Tests/FakeImageOperationsProvider.cs create mode 100644 tests/ImageSharp.Tests/ImageOperationTests.cs diff --git a/src/ImageSharp/ApplyProcessors.cs b/src/ImageSharp/ApplyProcessors.cs index a092b789b..d625b1c24 100644 --- a/src/ImageSharp/ApplyProcessors.cs +++ b/src/ImageSharp/ApplyProcessors.cs @@ -28,7 +28,7 @@ namespace ImageSharp Guard.NotNull(operations, nameof(operations)); // TODO: add parameter to Configuration to configure how this is created, create an IImageOperationsFactory that cna be used to switch this out with a fake for testing - var operationsRunner = new ImageOperations(source); + IImageOperations operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(source); operations(operationsRunner); } @@ -44,7 +44,7 @@ namespace ImageSharp Guard.NotNull(operations, nameof(operations)); // TODO: add parameter to Configuration to configure how this is created, create an IImageOperationsFactory that cna be used to switch this out with a fake for testing - var operationsRunner = new ImageOperations(source); + IImageOperations operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(source); operationsRunner.ApplyProcessors(operations); } @@ -62,7 +62,7 @@ namespace ImageSharp var generated = new Image(source); // TODO: add parameter to Configuration to configure how this is created, create an IImageOperationsFactory that cna be used to switch this out with a fake for testing - var operationsRunner = new ImageOperations(generated); + IImageOperations operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(generated); operations(operationsRunner); return generated; } @@ -81,7 +81,7 @@ namespace ImageSharp var generated = new Image(source); // TODO: add parameter to Configuration to configure how this is created, create an IImageOperationsFactory that cna be used to switch this out with a fake for testing - var operationsRunner = new ImageOperations(generated); + IImageOperations operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(generated); operationsRunner.ApplyProcessors(operations); return generated; } @@ -96,5 +96,23 @@ namespace ImageSharp public static IImageOperations Run(this IImageOperations source, Action> operation) where TPixel : struct, IPixel => source.ApplyProcessor(new DelegateImageProcessor(operation)); + + /// + /// Queues up a simple operation that provides access to the mutatable image. + /// + /// The pixel format. + /// The image to rotate, flip, or both. + /// The operations to perform on the source. + /// returns the current optinoatins class to allow chaining of oprations. + internal static IImageOperations ApplyProcessors(this IImageOperations source, params IImageProcessor[] operations) + where TPixel : struct, IPixel + { + foreach (IImageProcessor op in operations) + { + source = source.ApplyProcessor(op); + } + + return source; + } } } diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs index 226d45132..834019633 100644 --- a/src/ImageSharp/Configuration.cs +++ b/src/ImageSharp/Configuration.cs @@ -103,11 +103,16 @@ namespace ImageSharp #if !NETSTANDARD1_1 /// - /// Gets or sets the fielsystem helper for accessing the local file system. + /// Gets or sets the filesystem helper for accessing the local file system. /// internal IFileSystem FileSystem { get; set; } = new LocalFileSystem(); #endif + /// + /// Gets or sets the image operations providers. + /// + internal IImageOperationsProvider ImageOperationsProvider { get; set; } = new DefaultImageOperationsProvider(); + /// /// Registers a new format provider. /// diff --git a/src/ImageSharp/IImageOperationsProvider.cs b/src/ImageSharp/IImageOperationsProvider.cs new file mode 100644 index 000000000..475c63265 --- /dev/null +++ b/src/ImageSharp/IImageOperationsProvider.cs @@ -0,0 +1,38 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using ImageSharp.PixelFormats; + + /// + /// Represents an interface that will create IImageOperations + /// + internal interface IImageOperationsProvider + { + /// + /// Called during Mutate operations to generate the imageoperations provider. + /// + /// The pixel format + /// The source image. + /// A new IImageOPeration + IImageOperations CreateMutator(Image source) + where TPixel : struct, IPixel; + } + + /// + /// The default implmentation of IImageOperationsProvider + /// + internal class DefaultImageOperationsProvider : IImageOperationsProvider + { + /// + public IImageOperations CreateMutator(Image source) + where TPixel : struct, IPixel + { + return new ImageOperations(source); + } + } +} diff --git a/src/ImageSharp/IImageOperations{TPixel}.cs b/src/ImageSharp/IImageOperations{TPixel}.cs index a176c0e28..349cef7f3 100644 --- a/src/ImageSharp/IImageOperations{TPixel}.cs +++ b/src/ImageSharp/IImageOperations{TPixel}.cs @@ -12,7 +12,7 @@ namespace ImageSharp using SixLabors.Primitives; /// - /// The static collection of all the default image formats + /// An interface to queue up image operations. /// /// The pixel format public interface IImageOperations diff --git a/src/ImageSharp/Processing/DelegateImageProcessor.cs b/src/ImageSharp/Processing/DelegateImageProcessor.cs index e1d1060c6..5fbb84114 100644 --- a/src/ImageSharp/Processing/DelegateImageProcessor.cs +++ b/src/ImageSharp/Processing/DelegateImageProcessor.cs @@ -29,6 +29,11 @@ namespace ImageSharp.Processing this.action = action; } + /// + /// Gets the action that will be applied to the image. + /// + internal Action> Action => this.action; + /// protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) { diff --git a/src/Shared/AssemblyInfo.Common.cs b/src/Shared/AssemblyInfo.Common.cs index 252ef3eae..c2aa13de2 100644 --- a/src/Shared/AssemblyInfo.Common.cs +++ b/src/Shared/AssemblyInfo.Common.cs @@ -37,4 +37,6 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("ImageSharp.Drawing")] [assembly: InternalsVisibleTo("ImageSharp.Benchmarks")] [assembly: InternalsVisibleTo("ImageSharp.Tests")] -[assembly: InternalsVisibleTo("ImageSharp.Sandbox46")] \ No newline at end of file +[assembly: InternalsVisibleTo("ImageSharp.Sandbox46")] + +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] \ No newline at end of file diff --git a/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs b/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs new file mode 100644 index 000000000..d6bea7108 --- /dev/null +++ b/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using ImageSharp.Processing; +using Xunit; + +namespace ImageSharp.Tests +{ + public abstract class BaseImageOperationsExtensionTest + { + protected readonly FakeImageOperationsProvider.FakeImageOperations operations; + + public BaseImageOperationsExtensionTest() + { + this.operations = new FakeImageOperationsProvider.FakeImageOperations(null); + } + + public T Verify(int index = 0) + { + var operation = this.operations.applied[index]; + + return Assert.IsType(operation.Processor); + } + } +} diff --git a/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs b/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs new file mode 100644 index 000000000..b9a1d80a2 --- /dev/null +++ b/tests/ImageSharp.Tests/FakeImageOperationsProvider.cs @@ -0,0 +1,77 @@ +namespace ImageSharp.Tests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using ImageSharp.PixelFormats; + using ImageSharp.Processing; + using SixLabors.Primitives; + + public class FakeImageOperationsProvider : IImageOperationsProvider + { + private List ImageOperators = new List(); + + public bool HasCreated(Image source) + where TPixel : struct, IPixel + { + return Created(source).Any(); + } + public IEnumerable> Created(Image source) where TPixel : struct, IPixel + { + return this.ImageOperators.OfType>() + .Where(x => x.source == source); + } + + public IEnumerable.AppliedOpperation> AppliedOperations(Image source) where TPixel : struct, IPixel + { + return Created(source) + .SelectMany(x => x.applied); + } + + public IImageOperations CreateMutator(Image source) where TPixel : struct, IPixel + { + var op = new FakeImageOperations(source); + this.ImageOperators.Add(op); + return op; + } + + + public class FakeImageOperations : IImageOperations + where TPixel : struct, IPixel + { + public Image source; + + public List applied = new List(); + + public FakeImageOperations(Image source) + { + this.source = source; + } + + public IImageOperations ApplyProcessor(IImageProcessor processor, Rectangle rectangle) + { + applied.Add(new AppliedOpperation + { + Processor = processor, + Rectangle = rectangle + }); + return this; + } + + public IImageOperations ApplyProcessor(IImageProcessor processor) + { + applied.Add(new AppliedOpperation + { + Processor = processor + }); + return this; + } + public struct AppliedOpperation + { + public Rectangle? Rectangle { get; set; } + public IImageProcessor Processor { get; set; } + } + } + } +} diff --git a/tests/ImageSharp.Tests/ImageOperationTests.cs b/tests/ImageSharp.Tests/ImageOperationTests.cs new file mode 100644 index 000000000..61bb18e76 --- /dev/null +++ b/tests/ImageSharp.Tests/ImageOperationTests.cs @@ -0,0 +1,120 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + + using ImageSharp.Formats; + using ImageSharp.IO; + using ImageSharp.PixelFormats; + using ImageSharp.Processing; + using Moq; + using SixLabors.Primitives; + using Xunit; + + /// + /// Tests the configuration class. + /// + public class ImageOperationTests : IDisposable + { + private readonly Image image; + private readonly FakeImageOperationsProvider provider; + private readonly IImageProcessor processor; + + public Configuration Configuration { get; private set; } + + public ImageOperationTests() + { + this.provider = new FakeImageOperationsProvider(); + this.processor = new Mock>().Object; + this.image = new Image(new Configuration() + { + ImageOperationsProvider = this.provider + }, 1, 1); + } + + [Fact] + public void MutateCallsImageOperationsProvider_Func_OriginalImage() + { + this.image.Mutate(x => x.ApplyProcessor(this.processor)); + + Assert.True(this.provider.HasCreated(this.image)); + Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x=>x.Processor)); + } + + [Fact] + public void MutateCallsImageOperationsProvider_ListOfProcessors_OriginalImage() + { + this.image.Mutate(this.processor); + + Assert.True(this.provider.HasCreated(this.image)); + Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor)); + } + + [Fact] + public void CloneCallsImageOperationsProvider_Func_WithDuplicateImage() + { + var returned = this.image.Clone(x => x.ApplyProcessor(this.processor)); + + Assert.True(this.provider.HasCreated(returned)); + Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.Processor)); + } + + [Fact] + public void CloneCallsImageOperationsProvider_ListOfProcessors_WithDuplicateImage() + { + var returned = this.image.Clone(this.processor); + + Assert.True(this.provider.HasCreated(returned)); + Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.Processor)); + } + + [Fact] + public void CloneCallsImageOperationsProvider_Func_NotOnOrigional() + { + var returned = this.image.Clone(x => x.ApplyProcessor(this.processor)); + Assert.False(this.provider.HasCreated(this.image)); + Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor)); + } + + [Fact] + public void CloneCallsImageOperationsProvider_ListOfProcessors_NotOnOrigional() + { + var returned = this.image.Clone(this.processor); + Assert.False(this.provider.HasCreated(this.image)); + Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor)); + } + + [Fact] + public void ApplyProcessors_ListOfProcessors_AppliesALlProcessorsToOperation() + { + var operations = new FakeImageOperationsProvider.FakeImageOperations(null); + operations.ApplyProcessors(this.processor); + Assert.Contains(this.processor, operations.applied.Select(x => x.Processor)); + } + + public void Dispose() + { + this.image.Dispose(); + } + } + + public class RunImageOperation : BaseImageOperationsExtensionTest + { + [Fact] + public void Run_CreatedDelegateProcessor() + { + Action> action = (i) => { }; + this.operations.Run(action); + + DelegateImageProcessor processor = this.Verify>(); + Assert.Equal(action, processor.Action); + } + } +} \ No newline at end of file