Browse Source

initail image operations tests

af/merge-core
Scott Williams 9 years ago
parent
commit
f017fdbf2f
  1. 26
      src/ImageSharp/ApplyProcessors.cs
  2. 7
      src/ImageSharp/Configuration.cs
  3. 38
      src/ImageSharp/IImageOperationsProvider.cs
  4. 2
      src/ImageSharp/IImageOperations{TPixel}.cs
  5. 5
      src/ImageSharp/Processing/DelegateImageProcessor.cs
  6. 4
      src/Shared/AssemblyInfo.Common.cs
  7. 25
      tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs
  8. 77
      tests/ImageSharp.Tests/FakeImageOperationsProvider.cs
  9. 120
      tests/ImageSharp.Tests/ImageOperationTests.cs

26
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<TPixel>(source);
IImageOperations<TPixel> 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<TPixel>(source);
IImageOperations<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(source);
operationsRunner.ApplyProcessors(operations);
}
@ -62,7 +62,7 @@ namespace ImageSharp
var generated = new Image<TPixel>(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<TPixel>(generated);
IImageOperations<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(generated);
operations(operationsRunner);
return generated;
}
@ -81,7 +81,7 @@ namespace ImageSharp
var generated = new Image<TPixel>(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<TPixel>(generated);
IImageOperations<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(generated);
operationsRunner.ApplyProcessors(operations);
return generated;
}
@ -96,5 +96,23 @@ namespace ImageSharp
public static IImageOperations<TPixel> Run<TPixel>(this IImageOperations<TPixel> source, Action<Image<TPixel>> operation)
where TPixel : struct, IPixel<TPixel>
=> source.ApplyProcessor(new DelegateImageProcessor<TPixel>(operation));
/// <summary>
/// Queues up a simple operation that provides access to the mutatable image.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image to rotate, flip, or both.</param>
/// <param name="operations">The operations to perform on the source.</param>
/// <returns>returns the current optinoatins class to allow chaining of oprations.</returns>
internal static IImageOperations<TPixel> ApplyProcessors<TPixel>(this IImageOperations<TPixel> source, params IImageProcessor<TPixel>[] operations)
where TPixel : struct, IPixel<TPixel>
{
foreach (IImageProcessor<TPixel> op in operations)
{
source = source.ApplyProcessor(op);
}
return source;
}
}
}

7
src/ImageSharp/Configuration.cs

@ -103,11 +103,16 @@ namespace ImageSharp
#if !NETSTANDARD1_1
/// <summary>
/// Gets or sets the fielsystem helper for accessing the local file system.
/// Gets or sets the filesystem helper for accessing the local file system.
/// </summary>
internal IFileSystem FileSystem { get; set; } = new LocalFileSystem();
#endif
/// <summary>
/// Gets or sets the image operations providers.
/// </summary>
internal IImageOperationsProvider ImageOperationsProvider { get; set; } = new DefaultImageOperationsProvider();
/// <summary>
/// Registers a new format provider.
/// </summary>

38
src/ImageSharp/IImageOperationsProvider.cs

@ -0,0 +1,38 @@
// <copyright file="IImageOperationsProvider.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents an interface that will create IImageOperations
/// </summary>
internal interface IImageOperationsProvider
{
/// <summary>
/// Called during Mutate operations to generate the imageoperations provider.
/// </summary>
/// <typeparam name="TPixel">The pixel format</typeparam>
/// <param name="source">The source image.</param>
/// <returns>A new IImageOPeration</returns>
IImageOperations<TPixel> CreateMutator<TPixel>(Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>;
}
/// <summary>
/// The default implmentation of IImageOperationsProvider
/// </summary>
internal class DefaultImageOperationsProvider : IImageOperationsProvider
{
/// <inheritdoc/>
public IImageOperations<TPixel> CreateMutator<TPixel>(Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
{
return new ImageOperations<TPixel>(source);
}
}
}

2
src/ImageSharp/IImageOperations{TPixel}.cs

@ -12,7 +12,7 @@ namespace ImageSharp
using SixLabors.Primitives;
/// <summary>
/// The static collection of all the default image formats
/// An interface to queue up image operations.
/// </summary>
/// <typeparam name="TPixel">The pixel format</typeparam>
public interface IImageOperations<TPixel>

5
src/ImageSharp/Processing/DelegateImageProcessor.cs

@ -29,6 +29,11 @@ namespace ImageSharp.Processing
this.action = action;
}
/// <summary>
/// Gets the action that will be applied to the image.
/// </summary>
internal Action<Image<TPixel>> Action => this.action;
/// <inheritdoc/>
protected override void BeforeImageApply(Image<TPixel> source, Rectangle sourceRectangle)
{

4
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")]
[assembly: InternalsVisibleTo("ImageSharp.Sandbox46")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

25
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<Rgba32> operations;
public BaseImageOperationsExtensionTest()
{
this.operations = new FakeImageOperationsProvider.FakeImageOperations<Rgba32>(null);
}
public T Verify<T>(int index = 0)
{
var operation = this.operations.applied[index];
return Assert.IsType<T>(operation.Processor);
}
}
}

77
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<object> ImageOperators = new List<object>();
public bool HasCreated<TPixel>(Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
{
return Created(source).Any();
}
public IEnumerable<FakeImageOperations<TPixel>> Created<TPixel>(Image<TPixel> source) where TPixel : struct, IPixel<TPixel>
{
return this.ImageOperators.OfType<FakeImageOperations<TPixel>>()
.Where(x => x.source == source);
}
public IEnumerable<FakeImageOperations<TPixel>.AppliedOpperation> AppliedOperations<TPixel>(Image<TPixel> source) where TPixel : struct, IPixel<TPixel>
{
return Created(source)
.SelectMany(x => x.applied);
}
public IImageOperations<TPixel> CreateMutator<TPixel>(Image<TPixel> source) where TPixel : struct, IPixel<TPixel>
{
var op = new FakeImageOperations<TPixel>(source);
this.ImageOperators.Add(op);
return op;
}
public class FakeImageOperations<TPixel> : IImageOperations<TPixel>
where TPixel : struct, IPixel<TPixel>
{
public Image<TPixel> source;
public List<AppliedOpperation> applied = new List<AppliedOpperation>();
public FakeImageOperations(Image<TPixel> source)
{
this.source = source;
}
public IImageOperations<TPixel> ApplyProcessor(IImageProcessor<TPixel> processor, Rectangle rectangle)
{
applied.Add(new AppliedOpperation
{
Processor = processor,
Rectangle = rectangle
});
return this;
}
public IImageOperations<TPixel> ApplyProcessor(IImageProcessor<TPixel> processor)
{
applied.Add(new AppliedOpperation
{
Processor = processor
});
return this;
}
public struct AppliedOpperation
{
public Rectangle? Rectangle { get; set; }
public IImageProcessor<TPixel> Processor { get; set; }
}
}
}
}

120
tests/ImageSharp.Tests/ImageOperationTests.cs

@ -0,0 +1,120 @@
// <copyright file="ConfigurationTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
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;
/// <summary>
/// Tests the configuration class.
/// </summary>
public class ImageOperationTests : IDisposable
{
private readonly Image<Rgba32> image;
private readonly FakeImageOperationsProvider provider;
private readonly IImageProcessor<Rgba32> processor;
public Configuration Configuration { get; private set; }
public ImageOperationTests()
{
this.provider = new FakeImageOperationsProvider();
this.processor = new Mock<IImageProcessor<Rgba32>>().Object;
this.image = new Image<Rgba32>(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<Rgba32>(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<Image<Rgba32>> action = (i) => { };
this.operations.Run(action);
DelegateImageProcessor<Rgba32> processor = this.Verify<DelegateImageProcessor<Rgba32>>();
Assert.Equal(action, processor.Action);
}
}
}
Loading…
Cancel
Save