You've already forked linux-packaging-mono
acceptance-tests
data
debian
docs
external
Newtonsoft.Json
api-doc-tools
api-snapshot
aspnetwebstack
packages
src
test
Microsoft.TestCommon
Microsoft.Web.Helpers.Test
Microsoft.Web.Http.Data.Test
Microsoft.Web.Mvc.Test
Microsoft.Web.WebPages.OAuth.Test
SPA.Test
System.Json.Test.Integration
System.Json.Test.Unit
System.Net.Http.Formatting.Test.Integration
System.Net.Http.Formatting.Test.Unit
System.Web.Helpers.Test
System.Web.Http.Integration.Test
System.Web.Http.SelfHost.Test
System.Web.Http.Test
System.Web.Http.WebHost.Test
System.Web.Mvc.Test
Ajax
Async
Test
AsyncActionDescriptorTest.cs
AsyncActionMethodSelectorTest.cs
AsyncControllerActionInvokerTest.cs
AsyncManagerTest.cs
AsyncResultWrapperTest.cs
AsyncUtilTest.cs
MockAsyncResult.cs
OperationCounterTest.cs
ReflectedAsyncActionDescriptorTest.cs
ReflectedAsyncControllerDescriptorTest.cs
SignalContainer.cs
SimpleAsyncResultTest.cs
SingleEntryGateTest.cs
SynchronizationContextUtilTest.cs
SynchronousOperationExceptionTest.cs
TaskAsyncActionDescriptorTest.cs
TaskWrapperAsyncResultTest.cs
TriggerListenerTest.cs
ExpressionUtil
Html
Properties
Razor
Test
Util
System.Web.Mvc.Test.csproj
packages.config
System.Web.Razor.Test
System.Web.WebPages.Administration.Test
System.Web.WebPages.Deployment.Test
System.Web.WebPages.Razor.Test
System.Web.WebPages.Test
WebMatrix.Data.Test
WebMatrix.WebData.Test
Settings.StyleCop
tools
.gitattributes
.gitignore
License.txt
README.md
Runtime.msbuild
Runtime.sln
Runtime.xunit
Settings.StyleCop
build.cmd
binary-reference-assemblies
bockbuild
boringssl
cecil
cecil-legacy
corefx
corert
ikdasm
ikvm
linker
nuget-buildtasks
nunit-lite
roslyn-binaries
rx
xunit-binaries
ikvm-native
libgc
llvm
m4
man
mcs
mono
msvc
po
runtime
samples
scripts
support
tools
COPYING.LIB
LICENSE
Makefile.am
Makefile.in
NEWS
README.md
acinclude.m4
aclocal.m4
autogen.sh
code_of_conduct.md
compile
config.guess
config.h.in
config.rpath
config.sub
configure.REMOVED.git-id
configure.ac.REMOVED.git-id
depcomp
install-sh
ltmain.sh.REMOVED.git-id
missing
mkinstalldirs
mono-uninstalled.pc.in
test-driver
winconfig.h
380 lines
14 KiB
C#
380 lines
14 KiB
C#
![]() |
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
|
|||
|
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Reflection;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using Moq;
|
|||
|
using Xunit;
|
|||
|
using Assert = Microsoft.TestCommon.AssertEx;
|
|||
|
|
|||
|
namespace System.Web.Mvc.Async.Test
|
|||
|
{
|
|||
|
public class AsyncActionMethodSelectorTest
|
|||
|
{
|
|||
|
[Fact]
|
|||
|
public void AliasedMethodsProperty()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
|
|||
|
// Act
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Assert
|
|||
|
Assert.Equal(3, selector.AliasedMethods.Length);
|
|||
|
|
|||
|
List<MethodInfo> sortedAliasedMethods = selector.AliasedMethods.OrderBy(methodInfo => methodInfo.Name).ToList();
|
|||
|
Assert.Equal("Bar", sortedAliasedMethods[0].Name);
|
|||
|
Assert.Equal("FooRenamed", sortedAliasedMethods[1].Name);
|
|||
|
Assert.Equal("Renamed", sortedAliasedMethods[2].Name);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void ControllerTypeProperty()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act & Assert
|
|||
|
Assert.Same(controllerType, selector.ControllerType);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindAction_DoesNotMatchAsyncMethod()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act
|
|||
|
ActionDescriptorCreator creator = selector.FindAction(null, "EventPatternAsync");
|
|||
|
|
|||
|
// Assert
|
|||
|
Assert.Null(creator);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindAction_DoesNotMatchCompletedMethod()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act
|
|||
|
ActionDescriptorCreator creator = selector.FindAction(null, "EventPatternCompleted");
|
|||
|
|
|||
|
// Assert
|
|||
|
Assert.Null(creator);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindAction_ReturnsMatchingMethodIfOneMethodMatches()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(SelectionAttributeController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act
|
|||
|
ActionDescriptorCreator creator = selector.FindAction(null, "OneMatch");
|
|||
|
ActionDescriptor actionDescriptor = creator("someName", new Mock<ControllerDescriptor>().Object);
|
|||
|
|
|||
|
// Assert
|
|||
|
var castActionDescriptor = Assert.IsType<ReflectedActionDescriptor>(actionDescriptor);
|
|||
|
Assert.Equal("OneMatch", castActionDescriptor.MethodInfo.Name);
|
|||
|
Assert.Equal(typeof(string), castActionDescriptor.MethodInfo.GetParameters()[0].ParameterType);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindAction_ReturnsMethodWithActionSelectionAttributeIfMultipleMethodsMatchRequest()
|
|||
|
{
|
|||
|
// DevDiv Bugs 212062: If multiple action methods match a request, we should match only the methods with an
|
|||
|
// [ActionMethod] attribute since we assume those methods are more specific.
|
|||
|
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(SelectionAttributeController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act
|
|||
|
ActionDescriptorCreator creator = selector.FindAction(null, "ShouldMatchMethodWithSelectionAttribute");
|
|||
|
ActionDescriptor actionDescriptor = creator("someName", new Mock<ControllerDescriptor>().Object);
|
|||
|
|
|||
|
// Assert
|
|||
|
var castActionDescriptor = Assert.IsType<ReflectedActionDescriptor>(actionDescriptor);
|
|||
|
Assert.Equal("MethodHasSelectionAttribute1", castActionDescriptor.MethodInfo.Name);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindAction_ReturnsNullIfNoMethodMatches()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(SelectionAttributeController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act
|
|||
|
ActionDescriptorCreator creator = selector.FindAction(null, "ZeroMatch");
|
|||
|
|
|||
|
// Assert
|
|||
|
Assert.Null(creator);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindAction_ThrowsIfMultipleMethodsMatch()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(SelectionAttributeController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act & veriy
|
|||
|
Assert.Throws<AmbiguousMatchException>(
|
|||
|
delegate { selector.FindAction(null, "TwoMatch"); },
|
|||
|
@"The current request for action 'TwoMatch' on controller type 'SelectionAttributeController' is ambiguous between the following action methods:
|
|||
|
Void TwoMatch2() on type System.Web.Mvc.Async.Test.AsyncActionMethodSelectorTest+SelectionAttributeController
|
|||
|
Void TwoMatch() on type System.Web.Mvc.Async.Test.AsyncActionMethodSelectorTest+SelectionAttributeController");
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindActionMethod_Asynchronous()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act
|
|||
|
ActionDescriptorCreator creator = selector.FindAction(null, "EventPattern");
|
|||
|
ActionDescriptor actionDescriptor = creator("someName", new Mock<ControllerDescriptor>().Object);
|
|||
|
|
|||
|
// Assert
|
|||
|
var castActionDescriptor = Assert.IsType<ReflectedAsyncActionDescriptor>(actionDescriptor);
|
|||
|
Assert.Equal("EventPatternAsync", castActionDescriptor.AsyncMethodInfo.Name);
|
|||
|
Assert.Equal("EventPatternCompleted", castActionDescriptor.CompletedMethodInfo.Name);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindActionMethod_Task()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act
|
|||
|
ActionDescriptorCreator creator = selector.FindAction(null, "TaskPattern");
|
|||
|
ActionDescriptor actionDescriptor = creator("someName", new Mock<ControllerDescriptor>().Object);
|
|||
|
|
|||
|
// Assert
|
|||
|
var castActionDescriptor = Assert.IsType<TaskAsyncActionDescriptor>(actionDescriptor);
|
|||
|
Assert.Equal("TaskPattern", castActionDescriptor.TaskMethodInfo.Name);
|
|||
|
Assert.Equal(typeof(Task), castActionDescriptor.TaskMethodInfo.ReturnType);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindActionMethod_GenericTask()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act
|
|||
|
ActionDescriptorCreator creator = selector.FindAction(null, "GenericTaskPattern");
|
|||
|
ActionDescriptor actionDescriptor = creator("someName", new Mock<ControllerDescriptor>().Object);
|
|||
|
|
|||
|
// Assert
|
|||
|
var castActionDescriptor = Assert.IsType<TaskAsyncActionDescriptor>(actionDescriptor);
|
|||
|
Assert.Equal("GenericTaskPattern", castActionDescriptor.TaskMethodInfo.Name);
|
|||
|
Assert.Equal(typeof(Task<string>), castActionDescriptor.TaskMethodInfo.ReturnType);
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindActionMethod_Asynchronous_ThrowsIfCompletionMethodNotFound()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act & assert
|
|||
|
Assert.Throws<InvalidOperationException>(
|
|||
|
delegate { ActionDescriptorCreator creator = selector.FindAction(null, "EventPatternWithoutCompletionMethod"); },
|
|||
|
@"Could not locate a method named 'EventPatternWithoutCompletionMethodCompleted' on controller type System.Web.Mvc.Async.Test.AsyncActionMethodSelectorTest+MethodLocatorController.");
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void FindActionMethod_Asynchronous_ThrowsIfMultipleCompletedMethodsMatched()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Act & assert
|
|||
|
Assert.Throws<AmbiguousMatchException>(
|
|||
|
delegate { ActionDescriptorCreator creator = selector.FindAction(null, "EventPatternAmbiguous"); },
|
|||
|
@"Lookup for method 'EventPatternAmbiguousCompleted' on controller type 'MethodLocatorController' failed because of an ambiguity between the following methods:
|
|||
|
Void EventPatternAmbiguousCompleted(Int32) on type System.Web.Mvc.Async.Test.AsyncActionMethodSelectorTest+MethodLocatorController
|
|||
|
Void EventPatternAmbiguousCompleted(System.String) on type System.Web.Mvc.Async.Test.AsyncActionMethodSelectorTest+MethodLocatorController");
|
|||
|
}
|
|||
|
|
|||
|
[Fact]
|
|||
|
public void NonAliasedMethodsProperty()
|
|||
|
{
|
|||
|
// Arrange
|
|||
|
Type controllerType = typeof(MethodLocatorController);
|
|||
|
|
|||
|
// Act
|
|||
|
AsyncActionMethodSelector selector = new AsyncActionMethodSelector(controllerType);
|
|||
|
|
|||
|
// Assert
|
|||
|
Assert.Equal(6, selector.NonAliasedMethods.Count);
|
|||
|
|
|||
|
List<MethodInfo> sortedMethods = selector.NonAliasedMethods["foo"].OrderBy(methodInfo => methodInfo.GetParameters().Length).ToList();
|
|||
|
Assert.Equal("Foo", sortedMethods[0].Name);
|
|||
|
Assert.Empty(sortedMethods[0].GetParameters());
|
|||
|
Assert.Equal("Foo", sortedMethods[1].Name);
|
|||
|
Assert.Equal(typeof(string), sortedMethods[1].GetParameters()[0].ParameterType);
|
|||
|
|
|||
|
Assert.Equal(1, selector.NonAliasedMethods["EventPattern"].Count());
|
|||
|
Assert.Equal("EventPatternAsync", selector.NonAliasedMethods["EventPattern"].First().Name);
|
|||
|
Assert.Equal(1, selector.NonAliasedMethods["EventPatternAmbiguous"].Count());
|
|||
|
Assert.Equal("EventPatternAmbiguousAsync", selector.NonAliasedMethods["EventPatternAmbiguous"].First().Name);
|
|||
|
Assert.Equal(1, selector.NonAliasedMethods["EventPatternWithoutCompletionMethod"].Count());
|
|||
|
Assert.Equal("EventPatternWithoutCompletionMethodAsync", selector.NonAliasedMethods["EventPatternWithoutCompletionMethod"].First().Name);
|
|||
|
|
|||
|
Assert.Equal(1, selector.NonAliasedMethods["TaskPattern"].Count());
|
|||
|
Assert.Equal("TaskPattern", selector.NonAliasedMethods["TaskPattern"].First().Name);
|
|||
|
Assert.Equal(1, selector.NonAliasedMethods["GenericTaskPattern"].Count());
|
|||
|
Assert.Equal("GenericTaskPattern", selector.NonAliasedMethods["GenericTaskPattern"].First().Name);
|
|||
|
}
|
|||
|
|
|||
|
private class MethodLocatorController : Controller
|
|||
|
{
|
|||
|
public void Foo()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void Foo(string s)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
[ActionName("Foo")]
|
|||
|
public void FooRenamed()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
[ActionName("Bar")]
|
|||
|
public void Bar()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
[ActionName("PrivateVoid")]
|
|||
|
private void PrivateVoid()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
protected void ProtectedVoidAction()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public static void StaticMethod()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void EventPatternAsync()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void EventPatternCompleted()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void EventPatternWithoutCompletionMethodAsync()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void EventPatternAmbiguousAsync()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void EventPatternAmbiguousCompleted(int i)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void EventPatternAmbiguousCompleted(string s)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public Task TaskPattern()
|
|||
|
{
|
|||
|
return Task.Factory.StartNew(() => "foo");
|
|||
|
}
|
|||
|
|
|||
|
public Task<string> GenericTaskPattern()
|
|||
|
{
|
|||
|
return Task.Factory.StartNew(() => "foo");
|
|||
|
}
|
|||
|
|
|||
|
[ActionName("RenamedCompleted")]
|
|||
|
public void Renamed()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
// ensure that methods inheriting from Controller or a base class are not matched
|
|||
|
[ActionName("Blah")]
|
|||
|
protected override void ExecuteCore()
|
|||
|
{
|
|||
|
throw new NotImplementedException();
|
|||
|
}
|
|||
|
|
|||
|
public string StringProperty { get; set; }
|
|||
|
|
|||
|
#pragma warning disable 0067
|
|||
|
public event EventHandler<EventArgs> SomeEvent;
|
|||
|
#pragma warning restore 0067
|
|||
|
}
|
|||
|
|
|||
|
private class SelectionAttributeController : Controller
|
|||
|
{
|
|||
|
[Match(false)]
|
|||
|
public void OneMatch()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void OneMatch(string s)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public void TwoMatch()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
[ActionName("TwoMatch")]
|
|||
|
public void TwoMatch2()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
[Match(true), ActionName("ShouldMatchMethodWithSelectionAttribute")]
|
|||
|
public void MethodHasSelectionAttribute1()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
[ActionName("ShouldMatchMethodWithSelectionAttribute")]
|
|||
|
public void MethodDoesNotHaveSelectionAttribute1()
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
private class MatchAttribute : ActionMethodSelectorAttribute
|
|||
|
{
|
|||
|
private bool _match;
|
|||
|
|
|||
|
public MatchAttribute(bool match)
|
|||
|
{
|
|||
|
_match = match;
|
|||
|
}
|
|||
|
|
|||
|
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
|
|||
|
{
|
|||
|
return _match;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|