//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using ImageSharp.Formats;
using ImageSharp.PixelFormats;
using Moq;
using Xunit;
using Xunit.Abstractions;
public class TestImageProviderTests
{
public TestImageProviderTests(ITestOutputHelper output)
{
this.Output = output;
}
private ITestOutputHelper Output { get; }
[Theory]
[WithBlankImages(42, 666, PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.HalfSingle, "hello")]
public void Use_WithEmptyImageAttribute(TestImageProvider provider, string message)
where TPixel : struct, IPixel
{
Image img = provider.GetImage();
Assert.Equal(42, img.Width);
Assert.Equal(666, img.Height);
Assert.Equal("hello", message);
}
[Theory]
[WithBlankImages(42, 666, PixelTypes.All, "hello")]
public void Use_WithBlankImagesAttribute_WithAllPixelTypes(
TestImageProvider provider,
string message)
where TPixel : struct, IPixel
{
Image img = provider.GetImage();
Assert.Equal(42, img.Width);
Assert.Equal(666, img.Height);
Assert.Equal("hello", message);
}
[Theory]
[WithBlankImages(1, 1, PixelTypes.Rgba32, PixelTypes.Rgba32)]
[WithBlankImages(1, 1, PixelTypes.Alpha8, PixelTypes.Alpha8)]
[WithBlankImages(1, 1, PixelTypes.Rgba32, PixelTypes.Rgba32)]
public void PixelType_PropertyValueIsCorrect(TestImageProvider provider, PixelTypes expected)
where TPixel : struct, IPixel
{
Assert.Equal(expected, provider.PixelType);
}
[Theory]
[WithFile(TestImages.Bmp.Car, PixelTypes.All, 88)]
[WithFile(TestImages.Bmp.F, PixelTypes.All, 88)]
public void Use_WithFileAttribute(TestImageProvider provider, int yo)
where TPixel : struct, IPixel
{
Assert.NotNull(provider.Utility.SourceFileOrDescription);
Image img = provider.GetImage();
Assert.True(img.Width * img.Height > 0);
Assert.Equal(88, yo);
string fn = provider.Utility.GetTestOutputFileName("jpg");
this.Output.WriteLine(fn);
}
private class TestDecoder : IImageDecoder
{
public Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel
{
invocationCounts[this.callerName]++;
return new Image(42, 42);
}
// Couldn't make xUnit happy without this hackery:
private static ConcurrentDictionary invocationCounts = new ConcurrentDictionary();
private string callerName = null;
internal void InitCaller(string name)
{
this.callerName = name;
invocationCounts[name] = 0;
}
internal static int GetInvocationCount(string callerName) => invocationCounts[callerName];
private static readonly object Monitor = new object();
public static void DoTestThreadSafe(Action action)
{
lock (Monitor)
{
action();
}
}
}
[Theory]
[WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)]
public void GetImage_WithCustomParameterlessDecoder_ShouldUtilizeCache(TestImageProvider provider)
where TPixel : struct, IPixel
{
Assert.NotNull(provider.Utility.SourceFileOrDescription);
TestDecoder.DoTestThreadSafe(
() =>
{
string testName = nameof(this.GetImage_WithCustomParameterlessDecoder_ShouldUtilizeCache);
var decoder = new TestDecoder();
decoder.InitCaller(testName);
provider.GetImage(decoder);
Assert.Equal(1, TestDecoder.GetInvocationCount(testName));
provider.GetImage(decoder);
Assert.Equal(1, TestDecoder.GetInvocationCount(testName));
});
}
private class TestDecoderWithParameters : IImageDecoder
{
public string Param1 { get; set; }
public int Param2 { get; set; }
public Image Decode(Configuration configuration, Stream stream)
where TPixel : struct, IPixel
{
invocationCounts[this.callerName]++;
return new Image(42, 42);
}
private static ConcurrentDictionary invocationCounts = new ConcurrentDictionary();
private string callerName = null;
internal void InitCaller(string name)
{
this.callerName = name;
invocationCounts[name] = 0;
}
internal static int GetInvocationCount(string callerName) => invocationCounts[callerName];
private static readonly object Monitor = new object();
public static void DoTestThreadSafe(Action action)
{
lock (Monitor)
{
action();
}
}
}
[Theory]
[WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)]
public void GetImage_WithCustomParametricDecoder_ShouldUtilizeCache_WhenParametersAreEqual(TestImageProvider provider)
where TPixel : struct, IPixel
{
Assert.NotNull(provider.Utility.SourceFileOrDescription);
TestDecoderWithParameters.DoTestThreadSafe(
() =>
{
string testName =
nameof(this.GetImage_WithCustomParametricDecoder_ShouldUtilizeCache_WhenParametersAreEqual);
var decoder1 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 666 };
decoder1.InitCaller(testName);
var decoder2 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 666 };
decoder2.InitCaller(testName);
provider.GetImage(decoder1);
Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName));
provider.GetImage(decoder2);
Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName));
});
}
[Theory]
[WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)]
public void GetImage_WithCustomParametricDecoder_ShouldNotUtilizeCache_WhenParametersAreNotEqual(TestImageProvider provider)
where TPixel : struct, IPixel
{
Assert.NotNull(provider.Utility.SourceFileOrDescription);
TestDecoderWithParameters.DoTestThreadSafe(
() =>
{
string testName =
nameof(this.GetImage_WithCustomParametricDecoder_ShouldNotUtilizeCache_WhenParametersAreNotEqual);
var decoder1 = new TestDecoderWithParameters() { Param1 = "Lol", Param2 = 42 };
decoder1.InitCaller(testName);
var decoder2 = new TestDecoderWithParameters() { Param1 = "LoL", Param2 = 42 };
decoder2.InitCaller(testName);
provider.GetImage(decoder1);
Assert.Equal(1, TestDecoderWithParameters.GetInvocationCount(testName));
provider.GetImage(decoder2);
Assert.Equal(2, TestDecoderWithParameters.GetInvocationCount(testName));
});
}
public static string[] AllBmpFiles => TestImages.Bmp.All;
[Theory]
[WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32 | PixelTypes.Argb32)]
public void Use_WithFileCollection(TestImageProvider provider)
where TPixel : struct, IPixel
{
Assert.NotNull(provider.Utility.SourceFileOrDescription);
Image image = provider.GetImage();
provider.Utility.SaveTestOutputFile(image, "png");
}
[Theory]
[WithSolidFilledImages(10, 20, 255, 100, 50, 200, PixelTypes.Rgba32 | PixelTypes.Argb32)]
public void Use_WithSolidFilledImagesAttribute(TestImageProvider provider)
where TPixel : struct, IPixel
{
Image img = provider.GetImage();
Assert.Equal(10, img.Width);
Assert.Equal(20, img.Height);
byte[] colors = new byte[4];
using (PixelAccessor pixels = img.Lock())
{
for (int y = 0; y < pixels.Height; y++)
{
for (int x = 0; x < pixels.Width; x++)
{
pixels[x, y].ToXyzwBytes(colors, 0);
Assert.Equal(255, colors[0]);
Assert.Equal(100, colors[1]);
Assert.Equal(50, colors[2]);
Assert.Equal(200, colors[3]);
}
}
}
}
///
/// Need to us to create instance of when pixelType is StandardImageClass
///
///
///
///
public static Image CreateTestImage()
where TPixel : struct, IPixel
{
return new Image(3, 3);
}
[Theory]
[WithMemberFactory(nameof(CreateTestImage), PixelTypes.All)]
public void Use_WithMemberFactoryAttribute(TestImageProvider provider)
where TPixel : struct, IPixel
{
Image img = provider.GetImage();
Assert.Equal(3, img.Width);
if (provider.PixelType == PixelTypes.Rgba32)
{
Assert.IsType>(img);
}
}
public static readonly TheoryData