diff --git a/src/ImageSharp.Web/DependencyInjection/ImageSharpCoreBuilderExtensions.cs b/src/ImageSharp.Web/DependencyInjection/ImageSharpCoreBuilderExtensions.cs index a56d4a90..6c6f8ab4 100644 --- a/src/ImageSharp.Web/DependencyInjection/ImageSharpCoreBuilderExtensions.cs +++ b/src/ImageSharp.Web/DependencyInjection/ImageSharpCoreBuilderExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Linq; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -164,7 +165,16 @@ public static IImageSharpBuilder AddProvider(this IImageSharpBuilder public static IImageSharpBuilder RemoveProvider(this IImageSharpBuilder builder) where TProvider : class, IImageProvider { - builder.Services.Remove(ServiceDescriptor.Singleton()); + ServiceDescriptor descriptor = builder.Services.FirstOrDefault(x => + x.ServiceType == typeof(IImageProvider) + && x.Lifetime == ServiceLifetime.Singleton + && x.ImplementationType == typeof(TProvider)); + + if (descriptor != null) + { + builder.Services.Remove(descriptor); + } + return builder; } @@ -204,7 +214,16 @@ public static IImageSharpBuilder AddProcessor(this IImageSharpBuilde public static IImageSharpBuilder RemoveProcessor(this IImageSharpBuilder builder) where TProcessor : class, IImageWebProcessor { - builder.Services.Remove(ServiceDescriptor.Singleton()); + ServiceDescriptor descriptor = builder.Services.FirstOrDefault(x => + x.ServiceType == typeof(IImageWebProcessor) + && x.Lifetime == ServiceLifetime.Singleton + && x.ImplementationType == typeof(TProcessor)); + + if (descriptor != null) + { + builder.Services.Remove(descriptor); + } + return builder; } diff --git a/tests/ImageSharp.Web.Tests/Actions/ActionTests.cs b/tests/ImageSharp.Web.Tests/Actions/ActionTests.cs index a70a719a..d63b9524 100644 --- a/tests/ImageSharp.Web.Tests/Actions/ActionTests.cs +++ b/tests/ImageSharp.Web.Tests/Actions/ActionTests.cs @@ -51,9 +51,11 @@ void OnParseCommands(ImageCommandContext context) complete = true; } - TestServer server = ImageSharpTestServer.CreateWithActions(OnParseCommands); + using (TestServer server = ImageSharpTestServer.CreateWithActions(OnParseCommands)) + { + await server.CreateClient().GetAsync(url + "?width=20").ConfigureAwait(false); + } - await server.CreateClient().GetAsync(url + "?width=20").ConfigureAwait(false); Assert.True(complete); } @@ -69,9 +71,10 @@ void OnBeforeSave(FormattedImage image) complete = true; } - TestServer server = ImageSharpTestServer.CreateWithActions(null, OnBeforeSave); - - await server.CreateClient().GetAsync(ImageSharpTestServer.PhysicalTestImage + "?width=20").ConfigureAwait(false); + using (TestServer server = ImageSharpTestServer.CreateWithActions(null, OnBeforeSave)) + { + await server.CreateClient().GetAsync(ImageSharpTestServer.PhysicalTestImage + "?width=20").ConfigureAwait(false); + } Assert.True(complete); } @@ -88,9 +91,10 @@ void OnProcessed(ImageProcessingContext context) complete = true; } - TestServer server = ImageSharpTestServer.CreateWithActions(null, null, OnProcessed); - - await server.CreateClient().GetAsync(ImageSharpTestServer.PhysicalTestImage + "?width=20").ConfigureAwait(false); + using (TestServer server = ImageSharpTestServer.CreateWithActions(null, null, OnProcessed)) + { + await server.CreateClient().GetAsync(ImageSharpTestServer.PhysicalTestImage + "?width=20").ConfigureAwait(false); + } Assert.True(complete); } @@ -105,9 +109,10 @@ void OnPrepareResponse(HttpContext context) complete = true; } - TestServer server = ImageSharpTestServer.CreateWithActions(null, null, null, OnPrepareResponse); - - await server.CreateClient().GetAsync(ImageSharpTestServer.PhysicalTestImage + "?width=20").ConfigureAwait(false); + using (TestServer server = ImageSharpTestServer.CreateWithActions(null, null, null, OnPrepareResponse)) + { + await server.CreateClient().GetAsync(ImageSharpTestServer.PhysicalTestImage + "?width=20").ConfigureAwait(false); + } Assert.True(complete); } } diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockImageProvider.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/MockImageProvider.cs new file mode 100644 index 00000000..74a55008 --- /dev/null +++ b/tests/ImageSharp.Web.Tests/DependencyInjection/MockImageProvider.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Http; +using SixLabors.ImageSharp.Web.Providers; +using SixLabors.ImageSharp.Web.Resolvers; +using System; +using System.Threading.Tasks; + +namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection +{ + public class MockImageProvider : IImageProvider + { + public Func Match { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + public Task GetAsync(HttpContext context) => throw new NotImplementedException(); + + public bool IsValidRequest(HttpContext context) => throw new NotImplementedException(); + } +} diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/MockWebProcessor.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/MockWebProcessor.cs new file mode 100644 index 00000000..985b98d7 --- /dev/null +++ b/tests/ImageSharp.Web.Tests/DependencyInjection/MockWebProcessor.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.Logging; +using SixLabors.ImageSharp.Web.Processors; +using System; +using System.Collections.Generic; + +namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection +{ + public class MockWebProcessor : IImageWebProcessor + { + public IEnumerable Commands => throw new NotImplementedException(); + + public FormattedImage Process(FormattedImage image, ILogger logger, IDictionary commands) => throw new NotImplementedException(); + } +} diff --git a/tests/ImageSharp.Web.Tests/DependencyInjection/ServiceRegistrationExtensionsTests.cs b/tests/ImageSharp.Web.Tests/DependencyInjection/ServiceRegistrationExtensionsTests.cs new file mode 100644 index 00000000..4f19971c --- /dev/null +++ b/tests/ImageSharp.Web.Tests/DependencyInjection/ServiceRegistrationExtensionsTests.cs @@ -0,0 +1,51 @@ +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using SixLabors.ImageSharp.Web.DependencyInjection; +using System; +using Xunit; + +namespace SixLabors.ImageSharp.Web.Tests.DependencyInjection +{ + public class ServiceRegistrationExtensionsTests + { + [Fact] + public void CanAddRemoveImageProviders() + { + void RemoveServices(IServiceCollection services) + { + var builder = services.AddImageSharp() + .AddProvider(); + + Assert.Contains(services, x => x.ImplementationType == typeof(MockImageProvider)); + + builder.RemoveProvider(); + + Assert.DoesNotContain(services, x => x.ImplementationType == typeof(MockImageProvider)); + } + + using (TestServer server = ImageSharpTestServer.Create(ImageSharpTestServer.DefaultConfig, RemoveServices)) + { + } + } + + [Fact] + public void CanAddRemoveImageProcessors() + { + void RemoveServices(IServiceCollection services) + { + var builder = services.AddImageSharp() + .AddProcessor(); + + Assert.Contains(services, x => x.ImplementationType == typeof(MockWebProcessor)); + + builder.RemoveProcessor(); + + Assert.DoesNotContain(services, x => x.ImplementationType == typeof(MockWebProcessor)); + } + + using (TestServer server = ImageSharpTestServer.Create(ImageSharpTestServer.DefaultConfig, RemoveServices)) + { + } + } + } +} diff --git a/tests/ImageSharp.Web.Tests/ImageSharpTestServer.cs b/tests/ImageSharp.Web.Tests/ImageSharpTestServer.cs index 5f143c6f..f19c5b23 100644 --- a/tests/ImageSharp.Web.Tests/ImageSharpTestServer.cs +++ b/tests/ImageSharp.Web.Tests/ImageSharpTestServer.cs @@ -122,26 +122,50 @@ void DefaultConfigureServices(IServiceCollection services) private static void InitializeAzureStorage(TestServer server) { - // Upload an image to the Azure Test Storage; - var storageAccount = CloudStorageAccount.Parse(AzureConnectionString); - CloudBlobClient client = storageAccount.CreateCloudBlobClient(); - CloudBlobContainer container = client.GetContainerReference(AzureContainerName); - - if (!container.Exists()) + try { - container.Create(); - container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob }); - } + // Upload an image to the Azure Test Storage; + var storageAccount = CloudStorageAccount.Parse(AzureConnectionString); + CloudBlobClient client = storageAccount.CreateCloudBlobClient(); + CloudBlobContainer container = client.GetContainerReference(AzureContainerName); - IHostingEnvironment environment = server.Host.Services.GetRequiredService(); - CloudBlockBlob blob = container.GetBlockBlobReference(ImagePath); - if (!blob.Exists()) - { - IFileInfo file = environment.WebRootFileProvider.GetFileInfo(ImagePath); - using (System.IO.Stream stream = file.CreateReadStream()) + if (!container.Exists()) { - blob.UploadFromStream(stream); + container.Create(); + container.SetPermissions(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob }); } + + IHostingEnvironment environment = server.Host.Services.GetRequiredService(); + CloudBlockBlob blob = container.GetBlockBlobReference(ImagePath); + if (!blob.Exists()) + { + IFileInfo file = environment.WebRootFileProvider.GetFileInfo(ImagePath); + using (System.IO.Stream stream = file.CreateReadStream()) + { + blob.UploadFromStream(stream); + } + } + } + catch (StorageException) + { + // On Appveyor "Exists" appears to fail and the following exception is thrown. + // I cannot replicate this locally via Visual Studio Test Explorer or "dotnet test". + // + // Failed CanAddRemoveImageProcessors + // Error Message: + // Microsoft.Azure.Storage.StorageException : The specified container already exists. + // Stack Trace: + // at Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteAsync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext, CancellationToken token) + // at Microsoft.Azure.Storage.Core.Executor.Executor.<> c__DisplayClass0_0`1.< ExecuteSync > b__0() + // at Microsoft.Azure.Storage.Core.Util.CommonUtility.RunWithoutSynchronizationContext[T](Func`1 actionToRun) + // at Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) + // at Microsoft.Azure.Storage.Blob.CloudBlobContainer.Create(BlobContainerPublicAccessType accessType, BlobRequestOptions requestOptions, OperationContext operationContext) + // at Microsoft.Azure.Storage.Blob.CloudBlobContainer.Create(BlobRequestOptions requestOptions, OperationContext operationContext) + // at SixLabors.ImageSharp.Web.Tests.ImageSharpTestServer.InitializeAzureStorage(TestServer server) in C:\projects\imagesharp - web\tests\ImageSharp.Web.Tests\ImageSharpTestServer.cs:line 143 + // at SixLabors.ImageSharp.Web.Tests.ImageSharpTestServer.Create(Action`1 configureApp, Action`1 configureServices) + // in C:\projects\imagesharp - web\tests\ImageSharp.Web.Tests\ImageSharpTestServer.cs:line 123 + // at SixLabors.ImageSharp.Web.Tests.DependencyInjection.ServiceRegistrationExtensionsTests.CanAddRemoveImageProcessors() + // in C:\projects\imagesharp - web\tests\ImageSharp.Web.Tests\DependencyInjection\ServiceRegistrationExtensionsTests.cs:line 46 } }