aspnetcore/test/Microsoft.AspNetCore.Mvc.Co.../Internal/ControllerActionInvokerCach...

216 lines
7.7 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Internal
{
public class ControllerActionInvokerCacheTest
{
[Fact]
public void GetFilters_CachesAllFilters()
{
// Arrange
var services = CreateServices();
var cache = CreateCache(new DefaultFilterProvider());
var action = new ControllerActionDescriptor()
{
FilterDescriptors = new[]
{
new FilterDescriptor(new TestFilter(), FilterScope.Action),
new FilterDescriptor(new TestFilter(), FilterScope.Action),
},
MethodInfo = typeof(ControllerActionInvokerCache).GetMethod(
nameof(ControllerActionInvokerCache.GetControllerActionMethodExecutor)),
ControllerTypeInfo = typeof(ControllerActionInvokerCache).GetTypeInfo()
};
var context = new ControllerContext(new ActionContext(
new DefaultHttpContext(),
new RouteData(),
action));
// Act - 1
var filters1 = cache.GetFilters(context);
// Assert - 1
Assert.Collection(
filters1,
f => Assert.Same(action.FilterDescriptors[0].Filter, f), // Copied by provider
f => Assert.Same(action.FilterDescriptors[1].Filter, f)); // Copied by provider
// Act - 2
var filters2 = cache.GetFilters(context);
Assert.Same(filters1, filters2);
Assert.Collection(
filters2,
f => Assert.Same(action.FilterDescriptors[0].Filter, f), // Cached
f => Assert.Same(action.FilterDescriptors[1].Filter, f)); // Cached
}
[Fact]
public void GetFilters_CachesFilterFromFactory()
{
// Arrange
var services = CreateServices();
var cache = CreateCache(new DefaultFilterProvider());
var action = new ControllerActionDescriptor()
{
FilterDescriptors = new[]
{
new FilterDescriptor(new TestFilterFactory() { IsReusable = true }, FilterScope.Action),
new FilterDescriptor(new TestFilter(), FilterScope.Action),
},
MethodInfo = typeof(ControllerActionInvokerCache).GetMethod(
nameof(ControllerActionInvokerCache.GetControllerActionMethodExecutor)),
ControllerTypeInfo = typeof(ControllerActionInvokerCache).GetTypeInfo()
};
var context = new ControllerContext(new ActionContext(
new DefaultHttpContext(),
new RouteData(),
action));
// Act - 1
var filters1 = cache.GetFilters(context);
// Assert - 1
Assert.Collection(
filters1,
f => Assert.NotSame(action.FilterDescriptors[0].Filter, f), // Created by factory
f => Assert.Same(action.FilterDescriptors[1].Filter, f)); // Copied by provider
// Act - 2
var filters2 = cache.GetFilters(context);
Assert.Same(filters1, filters2);
Assert.Collection(
filters2,
f => Assert.Same(filters1[0], f), // Cached
f => Assert.Same(filters1[1], f)); // Cached
}
[Fact]
public void GetFilters_DoesNotCacheFiltersWithIsReusableFalse()
{
// Arrange
var services = CreateServices();
var cache = CreateCache(new DefaultFilterProvider());
var action = new ControllerActionDescriptor()
{
FilterDescriptors = new[]
{
new FilterDescriptor(new TestFilterFactory() { IsReusable = false }, FilterScope.Action),
new FilterDescriptor(new TestFilter(), FilterScope.Action),
},
MethodInfo = typeof(ControllerActionInvokerCache).GetMethod(
nameof(ControllerActionInvokerCache.GetControllerActionMethodExecutor)),
ControllerTypeInfo = typeof(ControllerActionInvokerCache).GetTypeInfo()
};
var context = new ControllerContext(new ActionContext(
new DefaultHttpContext(),
new RouteData(),
action));
// Act - 1
var filters1 = cache.GetFilters(context);
// Assert - 1
Assert.Collection(
filters1,
f => Assert.NotSame(action.FilterDescriptors[0].Filter, f), // Created by factory
f => Assert.Same(action.FilterDescriptors[1].Filter, f)); // Copied by provider
// Act - 2
var filters2 = cache.GetFilters(context);
Assert.NotSame(filters1, filters2);
Assert.Collection(
filters2,
f => Assert.NotSame(filters1[0], f), // Created by factory (again)
f => Assert.Same(filters1[1], f)); // Cached
}
[Fact]
public void GetControllerActionMethodExecutor_CachesExecutor()
{
// Arrange
var services = CreateServices();
var cache = CreateCache(new DefaultFilterProvider());
var action = new ControllerActionDescriptor()
{
FilterDescriptors = new[]
{
new FilterDescriptor(new TestFilterFactory() { IsReusable = false }, FilterScope.Action),
new FilterDescriptor(new TestFilter(), FilterScope.Action),
},
MethodInfo = typeof(ControllerActionInvokerCache).GetMethod(
nameof(ControllerActionInvokerCache.GetControllerActionMethodExecutor)),
ControllerTypeInfo = typeof(ControllerActionInvokerCache).GetTypeInfo()
};
var context = new ControllerContext(
new ActionContext(new DefaultHttpContext(),
new RouteData(),
action));
// Act - 1
var executor1 = cache.GetControllerActionMethodExecutor(context);
Assert.NotNull(executor1);
var filters1 = cache.GetFilters(context);
Assert.NotNull(filters1);
// Act - 2
var executor2 = cache.GetControllerActionMethodExecutor(context);
Assert.Same(executor1, executor2);
}
private class TestFilter : IFilterMetadata
{
}
private class TestFilterFactory : IFilterFactory
{
public bool IsReusable { get; set; }
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return new TestFilter();
}
}
private static IServiceProvider CreateServices()
{
return new ServiceCollection().BuildServiceProvider();
}
private static ControllerActionInvokerCache CreateCache(params IFilterProvider[] providers)
{
var services = CreateServices();
var descriptorProvider = new ActionDescriptorCollectionProvider(services);
return new ControllerActionInvokerCache(descriptorProvider, providers);
}
}
}