// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.Reflection; using Castle.Core.Internal; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests; /// /// Provides instances for parametric unit tests. /// /// The pixel format of the image. public abstract partial class TestImageProvider : ITestImageProvider, IXunitSerializable where TPixel : unmanaged, IPixel { public PixelTypes PixelType { get; private set; } = typeof(TPixel).GetPixelType(); public virtual string SourceFileOrDescription => string.Empty; public Configuration Configuration { get; set; } = Configuration.CreateDefaultInstance(); /// /// Gets the utility instance to provide information about the test image & manage input/output. /// public ImagingTestCaseUtility Utility { get; private set; } public string TypeName { get; private set; } public string MethodName { get; private set; } public string OutputSubfolderName { get; private set; } public static TestImageProvider BasicTestPattern( int width, int height, MethodInfo testMethod = null, PixelTypes pixelTypeOverride = PixelTypes.Undefined) => new BasicTestPatternProvider(width, height).Init(testMethod, pixelTypeOverride); public static TestImageProvider TestPattern( int width, int height, MethodInfo testMethod = null, PixelTypes pixelTypeOverride = PixelTypes.Undefined) => new TestPatternProvider(width, height).Init(testMethod, pixelTypeOverride); public static TestImageProvider Blank( int width, int height, MethodInfo testMethod = null, PixelTypes pixelTypeOverride = PixelTypes.Undefined) => new BlankProvider(width, height).Init(testMethod, pixelTypeOverride); public static TestImageProvider File( string filePath, MethodInfo testMethod = null, PixelTypes pixelTypeOverride = PixelTypes.Undefined) => new FileProvider(filePath).Init(testMethod, pixelTypeOverride); public static TestImageProvider Lambda( string declaringTypeName, string methodName, MethodInfo testMethod = null, PixelTypes pixelTypeOverride = PixelTypes.Undefined) => new MemberMethodProvider(declaringTypeName, methodName).Init(testMethod, pixelTypeOverride); public static TestImageProvider Solid( int width, int height, byte r, byte g, byte b, byte a = 255, MethodInfo testMethod = null, PixelTypes pixelTypeOverride = PixelTypes.Undefined) => new SolidProvider(width, height, r, g, b, a).Init(testMethod, pixelTypeOverride); /// /// Returns an instance to the test case with the necessary traits. /// /// A test image. public abstract Image GetImage(); public Image GetImage(IImageDecoder decoder) => this.GetImage(decoder, new DecoderOptions()); public Task> GetImageAsync(IImageDecoder decoder) => this.GetImageAsync(decoder, new DecoderOptions()); public virtual Image GetImage(IImageDecoder decoder, DecoderOptions options) => throw new NotSupportedException($"Decoder specific GetImage() is not supported with {this.GetType().Name}!"); public virtual Task> GetImageAsync(IImageDecoder decoder, DecoderOptions options) => throw new NotSupportedException($"Decoder specific GetImageAsync() is not supported with {this.GetType().Name}!"); public virtual Image GetImage(ISpecializedImageDecoder decoder, T options) where T : class, ISpecializedDecoderOptions, new() => throw new NotSupportedException($"Decoder specific GetImage() is not supported with {this.GetType().Name}!"); public virtual Task> GetImageAsync(ISpecializedImageDecoder decoder, T options) where T : class, ISpecializedDecoderOptions, new() => throw new NotSupportedException($"Decoder specific GetImageAsync() is not supported with {this.GetType().Name}!"); /// /// Returns an instance to the test case with the necessary traits. /// /// The operation to apply to the image before returning. /// A test image. public Image GetImage(Action operationsToApply) { Image img = this.GetImage(); img.Mutate(operationsToApply); return img; } public virtual void Deserialize(IXunitSerializationInfo info) { PixelTypes pixelType = info.GetValue("PixelType"); string typeName = info.GetValue("TypeName"); string methodName = info.GetValue("MethodName"); string outputSubfolderName = info.GetValue("OutputSubfolderName"); this.Init(typeName, methodName, outputSubfolderName, pixelType); } public virtual void Serialize(IXunitSerializationInfo info) { info.AddValue("PixelType", this.PixelType); info.AddValue("TypeName", this.TypeName); info.AddValue("MethodName", this.MethodName); info.AddValue("OutputSubfolderName", this.OutputSubfolderName); } protected TestImageProvider Init( string typeName, string methodName, string outputSubfolderName, PixelTypes pixelTypeOverride) { if (pixelTypeOverride != PixelTypes.Undefined) { this.PixelType = pixelTypeOverride; } this.TypeName = typeName; this.MethodName = methodName; this.OutputSubfolderName = outputSubfolderName; this.Utility = new ImagingTestCaseUtility { SourceFileOrDescription = this.SourceFileOrDescription, PixelTypeName = this.PixelType.ToString() }; if (methodName != null) { this.Utility.Init(typeName, methodName, outputSubfolderName); } return this; } protected TestImageProvider Init(MethodInfo testMethod, PixelTypes pixelTypeOverride) { string subfolder = testMethod?.DeclaringType.GetAttribute()?.Subfolder ?? string.Empty; return this.Init(testMethod?.DeclaringType.Name, testMethod?.Name, subfolder, pixelTypeOverride); } public override string ToString() => $"{this.SourceFileOrDescription}[{this.PixelType}]"; }