Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,285 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Net.Http.Formatting;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using System.Web.Http.ModelBinding.Binders;
using System.Web.Http.Routing;
using System.Web.Http.ValueProviders;
using System.Web.Http.ValueProviders.Providers;
using Microsoft.TestCommon;
using Moq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing
{
public class FormattingUtilitiesTest
{
[Theory]
[TestDataSet(typeof(CommonUnitTestDataSets), "RefTypeTestDataCollection")]
public void ValueToString_Formats(Type variationType, object testData)
{
// Arrange
string expected = Convert.ToString(testData, CultureInfo.CurrentCulture);
// Act
string actual = FormattingUtilities.ValueToString(testData, CultureInfo.CurrentCulture);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ValueToString_Formats_Null_Value()
{
// Arrange & Act
string actual = FormattingUtilities.ValueToString(null, CultureInfo.CurrentCulture);
// Assert
Assert.Equal("null", actual);
}
[Fact]
public void ActionArgumentsToString_Formats()
{
// Arrange
Dictionary<string, object> arguments = new Dictionary<string, object>()
{
{"p1", 1},
{"p2", true}
};
string expected = String.Format("p1={0}, p2={1}",
FormattingUtilities.ValueToString(arguments["p1"], CultureInfo.CurrentCulture),
FormattingUtilities.ValueToString(arguments["p2"], CultureInfo.CurrentCulture));
// Act
string actual = FormattingUtilities.ActionArgumentsToString(arguments);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ActionDescriptorToString_Formats()
{
// Arrange
Mock<HttpParameterDescriptor> paramDescriptor1 = new Mock<HttpParameterDescriptor>() { CallBase = true };
paramDescriptor1.Setup(p => p.ParameterName).Returns("p1");
paramDescriptor1.Setup(p => p.ParameterType).Returns(typeof(int));
Mock<HttpParameterDescriptor> paramDescriptor2 = new Mock<HttpParameterDescriptor>() { CallBase = true };
paramDescriptor2.Setup(p => p.ParameterName).Returns("p2");
paramDescriptor2.Setup(p => p.ParameterType).Returns(typeof(bool));
Collection<HttpParameterDescriptor> parameterCollection = new Collection<HttpParameterDescriptor>(
new HttpParameterDescriptor[] { paramDescriptor1.Object, paramDescriptor2.Object });
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(parameterCollection);
mockActionDescriptor.Setup(a => a.ActionName).Returns("SampleAction");
string expected = String.Format("SampleAction({0} p1, {1} p2)", typeof(int).Name, typeof(bool).Name);
// Act
string actual = FormattingUtilities.ActionDescriptorToString(mockActionDescriptor.Object);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ActionInvokeToString_Formats()
{
// Arrange
Dictionary<string, object> arguments = new Dictionary<string, object>()
{
{"p1", 1},
{"p2", true}
};
string expected = String.Format("SampleAction(p1={0}, p2={1})",
FormattingUtilities.ValueToString(arguments["p1"], CultureInfo.CurrentCulture),
FormattingUtilities.ValueToString(arguments["p2"], CultureInfo.CurrentCulture));
// Act
string actual = FormattingUtilities.ActionInvokeToString("SampleAction", arguments);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ActionInvokeToString_With_ActionContext_Formats()
{
// Arrange
Mock<HttpParameterDescriptor> paramDescriptor1 = new Mock<HttpParameterDescriptor>() { CallBase = true };
paramDescriptor1.Setup(p => p.ParameterName).Returns("p1");
paramDescriptor1.Setup(p => p.ParameterType).Returns(typeof(int));
Mock<HttpParameterDescriptor> paramDescriptor2 = new Mock<HttpParameterDescriptor>() { CallBase = true };
paramDescriptor2.Setup(p => p.ParameterName).Returns("p2");
paramDescriptor2.Setup(p => p.ParameterType).Returns(typeof(bool));
Collection<HttpParameterDescriptor> parameterCollection = new Collection<HttpParameterDescriptor>(
new HttpParameterDescriptor[] { paramDescriptor1.Object, paramDescriptor2.Object });
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(parameterCollection);
mockActionDescriptor.Setup(a => a.ActionName).Returns("SampleAction");
HttpActionContext actionContext =
ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
actionContext.ActionArguments["p1"] = 1;
actionContext.ActionArguments["p2"] = true;
string expected = String.Format("SampleAction(p1={0}, p2={1})",
FormattingUtilities.ValueToString(actionContext.ActionArguments["p1"], CultureInfo.CurrentCulture),
FormattingUtilities.ValueToString(actionContext.ActionArguments["p2"], CultureInfo.CurrentCulture));
// Act
string actual = FormattingUtilities.ActionInvokeToString(actionContext);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void FormattersToString_Formats()
{
// Arrange
MediaTypeFormatterCollection formatters = new MediaTypeFormatterCollection();
string expected = String.Join(", ", formatters.Select<MediaTypeFormatter, string>((f) => f.GetType().Name));
// Act
string actual = FormattingUtilities.FormattersToString(formatters);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ModelBinderToString_Formats()
{
// Arrange
ModelBinderProvider provider = new SimpleModelBinderProvider(typeof (int), () => null);
string expected = typeof (SimpleModelBinderProvider).Name;
// Act
string actual = FormattingUtilities.ModelBinderToString(provider);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ModelBinderToString_With_CompositeModelBinder_Formats()
{
// Arrange
ModelBinderProvider innerProvider1 = new SimpleModelBinderProvider(typeof(int), () => null);
ModelBinderProvider innerProvider2 = new ArrayModelBinderProvider();
CompositeModelBinderProvider compositeProvider = new CompositeModelBinderProvider(new ModelBinderProvider[] { innerProvider1, innerProvider2 });
string expected = String.Format(
"{0}({1}, {2})",
typeof(CompositeModelBinderProvider).Name,
typeof(SimpleModelBinderProvider).Name,
typeof(ArrayModelBinderProvider).Name);
// Act
string actual = FormattingUtilities.ModelBinderToString(compositeProvider);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ValueProviderToString_Formats()
{
// Arrange
IValueProvider provider = new ElementalValueProvider("unused", 1, CultureInfo.CurrentCulture);
string expected = typeof(ElementalValueProvider).Name;
// Act
string actual = FormattingUtilities.ValueProviderToString(provider);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ValueProviderToString_With_CompositeProvider_Formats()
{
// Arrange
List<IValueProvider> providers = new List<IValueProvider>()
{
new ElementalValueProvider("unused", 1, CultureInfo.CurrentCulture),
new NameValueCollectionValueProvider(() => null, CultureInfo.CurrentCulture)
};
CompositeValueProvider compositeProvider = new CompositeValueProvider(providers);
string expected = String.Format(
"{0}({1}, {2})",
typeof(CompositeValueProvider).Name,
typeof(ElementalValueProvider).Name,
typeof(NameValueCollectionValueProvider).Name);
// Act
string actual = FormattingUtilities.ValueProviderToString(compositeProvider);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void RouteToString_Formats()
{
// Arrange
Dictionary<string, object> routeDictionary = new Dictionary<string, object>()
{
{"r1", "c1"},
{"r2", "c2"}
};
Mock<IHttpRouteData> mockRouteData = new Mock<IHttpRouteData>() { CallBase = true};
mockRouteData.Setup(r => r.Values).Returns(routeDictionary);
string expected = "r1:c1,r2:c2";
// Act
string actual = FormattingUtilities.RouteToString(mockRouteData.Object);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ModelStateToString_Formats_With_Valid_ModelState()
{
// Arrange
ModelStateDictionary modelState = new ModelStateDictionary();
string expected = String.Empty;
// Act
string actual = FormattingUtilities.ModelStateToString(modelState);
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void ModelStateToString_Formats_With_InValid_ModelState()
{
// Arrange
ModelStateDictionary modelState = new ModelStateDictionary();
modelState.AddModelError("p1", "is bad");
string expected = "p1: is bad";
// Act
string actual = FormattingUtilities.ModelStateToString(modelState);
// Assert
Assert.Equal(expected, actual);
}
}
}

View File

@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing
{
public class HttpRequestMessageExtensionsTest
{
[Fact]
public void GetCorrelationId_Returns_Valid_Guid()
{
// Arrange
HttpRequestMessage request = new HttpRequestMessage();
// Act
Guid guid1 = request.GetCorrelationId();
Guid guid2 = request.GetCorrelationId();
// Assert
Assert.Equal(guid1, guid2);
Assert.NotEqual(guid1, Guid.Empty);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Net.Http;
namespace System.Web.Http.Tracing
{
/// <summary>
/// Test spy used internally to capture <see cref="TraceRecord"/>s.
/// </summary>
internal class TestTraceWriter : ITraceWriter
{
private List<TraceRecord> _traceRecords = new List<TraceRecord>();
public IList<TraceRecord> Traces { get { return _traceRecords; } }
public bool IsEnabled(string category, TraceLevel level)
{
return true;
}
public void Trace(HttpRequestMessage request, string category, TraceLevel level, Action<TraceRecord> traceAction)
{
TraceRecord traceRecord = new TraceRecord(request, category, level);
traceAction(traceRecord);
lock (_traceRecords)
{
_traceRecords.Add(traceRecord);
}
}
}
}

View File

@@ -0,0 +1,139 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Http.Tracing.Tracers;
using Moq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing
{
public class TraceManagerTest
{
[Fact]
public void TraceManager_Is_In_Default_ServiceResolver()
{
// Arrange
HttpConfiguration config = new HttpConfiguration();
// Act
ITraceManager traceManager = config.Services.GetService(typeof (ITraceManager)) as ITraceManager;
// Assert
Assert.IsType<TraceManager>(traceManager);
}
[Theory]
[InlineData(typeof(IHttpControllerSelector))]
[InlineData(typeof(IHttpControllerActivator))]
[InlineData(typeof(IHttpActionSelector))]
[InlineData(typeof(IHttpActionInvoker))]
[InlineData(typeof(IActionValueBinder))]
[InlineData(typeof(IContentNegotiator))]
public void Initialize_Does_Not_Alter_Configuration_When_No_TraceWriter_Present(Type serviceType)
{
// Arrange
HttpConfiguration config = new HttpConfiguration();
object defaultService = config.Services.GetService(serviceType);
// Act
new TraceManager().Initialize(config);
// Assert
Assert.Same(defaultService.GetType(), config.Services.GetService(serviceType).GetType());
}
[Theory]
[InlineData(typeof(IHttpControllerSelector))]
[InlineData(typeof(IHttpControllerActivator))]
[InlineData(typeof(IHttpActionSelector))]
[InlineData(typeof(IHttpActionInvoker))]
[InlineData(typeof(IActionValueBinder))]
[InlineData(typeof(IContentNegotiator))]
public void Initialize_Alters_Configuration_When_TraceWriter_Present(Type serviceType)
{
// Arrange
HttpConfiguration config = new HttpConfiguration();
Mock<ITraceWriter> traceWriter = new Mock<ITraceWriter>() { CallBase = true };
config.Services.Replace(typeof(ITraceWriter), traceWriter.Object);
object defaultService = config.Services.GetService(serviceType);
// Act
new TraceManager().Initialize(config);
// Assert
Assert.NotSame(defaultService.GetType(), config.Services.GetService(serviceType).GetType());
}
[Fact]
public void Initialize_Does_Not_Alter_MessageHandlers_When_No_TraceWriter_Present()
{
// Arrange
HttpConfiguration config = new HttpConfiguration();
Mock<DelegatingHandler> mockHandler = new Mock<DelegatingHandler>() { CallBase = true };
config.MessageHandlers.Add(mockHandler.Object);
// Act
new TraceManager().Initialize(config);
// Assert
Assert.Equal(config.MessageHandlers[config.MessageHandlers.Count - 1].GetType(), mockHandler.Object.GetType());
}
[Fact]
public void Initialize_Alters_MessageHandlers_WhenTraceWriter_Present()
{
// Arrange
HttpConfiguration config = new HttpConfiguration();
Mock<ITraceWriter> traceWriter = new Mock<ITraceWriter>() { CallBase = true };
config.Services.Replace(typeof(ITraceWriter), traceWriter.Object);
Mock<DelegatingHandler> mockHandler = new Mock<DelegatingHandler>() { CallBase = true };
config.MessageHandlers.Add(mockHandler.Object);
// Act
new TraceManager().Initialize(config);
// Assert
Assert.IsAssignableFrom<RequestMessageHandlerTracer>(config.MessageHandlers[config.MessageHandlers.Count - 1]);
Assert.IsAssignableFrom<MessageHandlerTracer>(config.MessageHandlers[config.MessageHandlers.Count - 2]);
}
[Fact]
public void Initialize_Does_Not_Alter_MediaTypeFormatters_When_No_TraceWriter_Present()
{
// Arrange
HttpConfiguration config = new HttpConfiguration();
// Act
new TraceManager().Initialize(config);
// Assert
foreach (var formatter in config.Formatters)
{
Assert.False(typeof(IFormatterTracer).IsAssignableFrom(formatter.GetType()));
}
}
[Fact]
public void Initialize_Alters_MediaTypeFormatters_WhenTraceWriter_Present()
{
// Arrange
HttpConfiguration config = new HttpConfiguration();
Mock<ITraceWriter> traceWriter = new Mock<ITraceWriter>() { CallBase = true };
config.Services.Replace(typeof(ITraceWriter), traceWriter.Object);
// Act
new TraceManager().Initialize(config);
// Assert
foreach (var formatter in config.Formatters)
{
Assert.IsAssignableFrom<IFormatterTracer>(formatter);
}
}
}
}

View File

@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
namespace System.Web.Http.Tracing
{
/// <summary>
/// Comparer class to allow xUnit asserts for <see cref="TraceRecord"/>.
/// </summary>
class TraceRecordComparer : IEqualityComparer<TraceRecord>
{
public bool Equals(TraceRecord x, TraceRecord y)
{
if (!String.Equals(x.Category, y.Category) ||
x.Level != y.Level ||
x.Kind != y.Kind ||
!Object.ReferenceEquals(x.Request, y.Request))
return false;
// The following must match only if they are present on 'x' -- the expected value
if (x.Exception != null && !Object.ReferenceEquals(x.Exception, y.Exception))
return false;
if (!String.IsNullOrEmpty(x.Message) && !String.Equals(x.Message, y.Message))
return false;
if (!String.IsNullOrEmpty(x.Operation) && !String.Equals(x.Operation, y.Operation))
return false;
if (!String.IsNullOrEmpty(x.Operator) && !String.Equals(x.Operator, y.Operator))
return false;
return true;
}
public int GetHashCode(TraceRecord obj)
{
return obj.GetHashCode();
}
}
}

View File

@@ -0,0 +1,110 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class ActionFilterAttributeTracerTest
{
[Fact]
public void ExecuteActionFilterAsync_Traces_Executing_And_Executed()
{
// Arrange
Mock<ActionFilterAttribute> mockAttr = new Mock<ActionFilterAttribute>() { CallBase = true };
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() {CallBase = true};
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
TestTraceWriter traceWriter = new TestTraceWriter();
ActionFilterAttributeTracer tracer = new ActionFilterAttributeTracer(mockAttr.Object, traceWriter);
Func<Task<HttpResponseMessage>> continuation =
() => TaskHelpers.FromResult<HttpResponseMessage>(new HttpResponseMessage());
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ActionExecuting" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "ActionExecuting" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ActionExecuted" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "ActionExecuted" }
};
// Act
Task<HttpResponseMessage> task = ((IActionFilter) tracer).ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);
task.Wait();
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteActionFilterAsync_Faults_And_Traces_When_OnExecuting_Faults()
{
// Arrange
Mock<ActionFilterAttribute> mockAttr = new Mock<ActionFilterAttribute>() { CallBase = true };
InvalidOperationException exception = new InvalidOperationException("test");
mockAttr.Setup(a => a.OnActionExecuting(It.IsAny<HttpActionContext>())).Throws(exception);
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
TestTraceWriter traceWriter = new TestTraceWriter();
ActionFilterAttributeTracer tracer = new ActionFilterAttributeTracer(mockAttr.Object, traceWriter);
Func<Task<HttpResponseMessage>> continuation =
() => TaskHelpers.FromResult<HttpResponseMessage>(new HttpResponseMessage());
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ActionExecuting" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "ActionExecuting" }
};
// Act
Task<HttpResponseMessage> task = ((IActionFilter)tracer).ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);
// Assert
Exception thrown = Assert.Throws<InvalidOperationException>(() => task.Wait());
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteActionFilterAsync_Faults_And_Traces_When_OnExecuted_Faults()
{
// Arrange
Mock<ActionFilterAttribute> mockAttr = new Mock<ActionFilterAttribute>() { CallBase = true };
InvalidOperationException exception = new InvalidOperationException("test");
mockAttr.Setup(a => a.OnActionExecuted(It.IsAny<HttpActionExecutedContext>())).Throws(exception);
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
TestTraceWriter traceWriter = new TestTraceWriter();
ActionFilterAttributeTracer tracer = new ActionFilterAttributeTracer(mockAttr.Object, traceWriter);
Func<Task<HttpResponseMessage>> continuation =
() => TaskHelpers.FromResult<HttpResponseMessage>(new HttpResponseMessage());
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ActionExecuting" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "ActionExecuting" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ActionExecuted" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "ActionExecuted" }
};
// Act
Task<HttpResponseMessage> task = ((IActionFilter)tracer).ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);
// Assert
Exception thrown = Assert.Throws<InvalidOperationException>(() => task.Wait());
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[3].Exception);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
}
}

View File

@@ -0,0 +1,84 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class ActionFilterTracerTest
{
[Fact]
public void ExecuteActionAsync_Traces_ExecuteActionFilterAsync()
{
// Arrange
HttpResponseMessage response = new HttpResponseMessage();
Mock<IActionFilter> mockFilter = new Mock<IActionFilter>() { CallBase = true };
mockFilter.Setup(
f =>
f.ExecuteActionFilterAsync(It.IsAny<HttpActionContext>(), It.IsAny<CancellationToken>(),
It.IsAny<Func<Task<HttpResponseMessage>>>())).Returns(
TaskHelpers.FromResult<HttpResponseMessage>(response));
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
TestTraceWriter traceWriter = new TestTraceWriter();
ActionFilterTracer tracer = new ActionFilterTracer(mockFilter.Object, traceWriter);
Func<Task<HttpResponseMessage>> continuation =
() => TaskHelpers.FromResult<HttpResponseMessage>(new HttpResponseMessage());
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteActionFilterAsync" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "ExecuteActionFilterAsync" },
};
// Act
Task<HttpResponseMessage> task = ((IActionFilter)tracer).ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);
task.Wait();
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteActionAsync_Faults_And_Traces_When_Inner_Faults()
{
// Arrange
InvalidOperationException exception = new InvalidOperationException("test");
Mock<IActionFilter> mockFilter = new Mock<IActionFilter>() { CallBase = true };
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>(null);
tcs.TrySetException(exception);
mockFilter.Setup(f => f.ExecuteActionFilterAsync(It.IsAny<HttpActionContext>(), It.IsAny<CancellationToken>(),
It.IsAny<Func<Task<HttpResponseMessage>>>())).Returns(tcs.Task);
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
TestTraceWriter traceWriter = new TestTraceWriter();
ActionFilterTracer tracer = new ActionFilterTracer(mockFilter.Object, traceWriter);
Func<Task<HttpResponseMessage>> continuation =
() => TaskHelpers.FromResult<HttpResponseMessage>(new HttpResponseMessage());
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteActionFilterAsync" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "ExecuteActionFilterAsync" },
};
// Act
Task<HttpResponseMessage> task = ((IActionFilter)tracer).ExecuteActionFilterAsync(actionContext, CancellationToken.None, continuation);
// Assert
Exception thrown = Assert.Throws<InvalidOperationException>(() => task.Wait());
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.Same(exception, traceWriter.Traces[1].Exception);
}
}
}

View File

@@ -0,0 +1,102 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class ActionValueBinderTracerTest
{
[Fact]
public void GetBinding_Returns_HttpActionBindingTracer()
{
// Arrange
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
Mock<HttpParameterDescriptor> mockParameterDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
Mock<HttpParameterBinding> mockParameterBinding = new Mock<HttpParameterBinding>(mockParameterDescriptor.Object) { CallBase = true };
HttpActionBinding actionBinding = new HttpActionBinding(mockActionDescriptor.Object, new HttpParameterBinding[] { mockParameterBinding.Object });
HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "controller", typeof(ApiController));
HttpControllerContext controllerContext = ContextUtil.CreateControllerContext(request: new HttpRequestMessage());
controllerContext.ControllerDescriptor = controllerDescriptor;
Mock<IActionValueBinder> mockBinder = new Mock<IActionValueBinder>() { CallBase = true };
mockBinder.Setup(b => b.GetBinding(It.IsAny<HttpActionDescriptor>())).Returns(actionBinding);
ActionValueBinderTracer tracer = new ActionValueBinderTracer(mockBinder.Object, new TestTraceWriter());
// Act
HttpActionBinding actualBinding = ((IActionValueBinder)tracer).GetBinding(mockActionDescriptor.Object);
// Assert
Assert.IsType<HttpActionBindingTracer>(actualBinding);
Assert.Same(mockActionDescriptor.Object, actualBinding.ActionDescriptor);
}
[Fact]
public void GetBinding_Invokes_Inner_And_Returns_ActionBinder_With_Tracing_HttpParameterBinding()
{
// Arrange
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
Mock<HttpParameterDescriptor> mockParameterDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
Mock<HttpParameterBinding> mockParameterBinding = new Mock<HttpParameterBinding>(mockParameterDescriptor.Object) { CallBase = true };
HttpActionBinding actionBinding = new HttpActionBinding(mockActionDescriptor.Object, new HttpParameterBinding[] { mockParameterBinding.Object });
HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "controller", typeof(ApiController));
HttpControllerContext controllerContext = ContextUtil.CreateControllerContext(request: new HttpRequestMessage());
controllerContext.ControllerDescriptor = controllerDescriptor;
Mock<IActionValueBinder> mockBinder = new Mock<IActionValueBinder>() {CallBase = true};
mockBinder.Setup(b => b.GetBinding(It.IsAny<HttpActionDescriptor>())).Returns(actionBinding);
ActionValueBinderTracer tracer = new ActionValueBinderTracer(mockBinder.Object, new TestTraceWriter());
// Act
HttpActionBinding actualBinding = ((IActionValueBinder) tracer).GetBinding(mockActionDescriptor.Object);
// Assert
Assert.IsAssignableFrom<HttpParameterBindingTracer>(actualBinding.ParameterBindings[0]);
}
[Fact]
public void GetBinding_Invokes_Inner_And_Returns_ActionBinder_With_Tracing_FormatterParameterBinding()
{
// Arrange
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
Mock<HttpParameterDescriptor> mockParameterDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
Mock<FormatterParameterBinding> mockParameterBinding = new Mock<FormatterParameterBinding>(mockParameterDescriptor.Object, new MediaTypeFormatterCollection(), null) { CallBase = true };
HttpActionBinding actionBinding = new HttpActionBinding(mockActionDescriptor.Object, new HttpParameterBinding[] { mockParameterBinding.Object });
HttpControllerDescriptor controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "controller", typeof(ApiController));
HttpControllerContext controllerContext = ContextUtil.CreateControllerContext(request: new HttpRequestMessage());
controllerContext.ControllerDescriptor = controllerDescriptor;
Mock<IActionValueBinder> mockBinder = new Mock<IActionValueBinder>() { CallBase = true };
mockBinder.Setup(b => b.GetBinding(It.IsAny<HttpActionDescriptor>())).Returns(actionBinding);
ActionValueBinderTracer tracer = new ActionValueBinderTracer(mockBinder.Object, new TestTraceWriter());
// Act
HttpActionBinding actualBinding = ((IActionValueBinder)tracer).GetBinding(mockActionDescriptor.Object);
// Assert
Assert.IsAssignableFrom<FormatterParameterBindingTracer>(actualBinding.ParameterBindings[0]);
}
}
}

View File

@@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class AuthorizationFilterAttributeTracerTest
{
[Fact]
public void ExecuteAuthorizationFilterAsync_Traces()
{
// Arrange
Mock<AuthorizationFilterAttribute> mockAttr = new Mock<AuthorizationFilterAttribute>() { CallBase = true };
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
Func<Task<HttpResponseMessage>> continuation = () => TaskHelpers.FromResult<HttpResponseMessage>(new HttpResponseMessage());
TestTraceWriter traceWriter = new TestTraceWriter();
AuthorizationFilterAttributeTracer tracer = new AuthorizationFilterAttributeTracer(mockAttr.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "OnAuthorization" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "OnAuthorization" },
};
// Act
Task task = ((IAuthorizationFilter)tracer).ExecuteAuthorizationFilterAsync(actionContext, CancellationToken.None, continuation);
task.Wait();
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteAuthorizationFilterAsync_Throws_And_Traces_When_Inner_OnException_Throws()
{
// Arrange
Mock<AuthorizationFilterAttribute> mockAttr = new Mock<AuthorizationFilterAttribute>() { CallBase = true };
InvalidOperationException exception = new InvalidOperationException("test");
mockAttr.Setup(a => a.OnAuthorization(It.IsAny<HttpActionContext>())).Throws(exception);
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
Func<Task<HttpResponseMessage>> continuation = () => TaskHelpers.FromResult<HttpResponseMessage>(new HttpResponseMessage());
TestTraceWriter traceWriter = new TestTraceWriter();
AuthorizationFilterAttributeTracer tracer = new AuthorizationFilterAttributeTracer(mockAttr.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "OnAuthorization" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "OnAuthorization" }
};
// Act
Exception thrown =
Assert.Throws<InvalidOperationException>(
() => ((IAuthorizationFilter)tracer).ExecuteAuthorizationFilterAsync(actionContext, CancellationToken.None, continuation).Wait());
// Assert
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
}
}

View File

@@ -0,0 +1,78 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class AuthorizationFilterTracerTest
{
[Fact]
public void ExecuteAuthorizationFilterAsync_Traces()
{
// Arrange
HttpResponseMessage response = new HttpResponseMessage();
Mock<IAuthorizationFilter> mockFilter = new Mock<IAuthorizationFilter>() { CallBase = true };
mockFilter.Setup(f => f.ExecuteAuthorizationFilterAsync(It.IsAny<HttpActionContext>(), It.IsAny<CancellationToken>(), It.IsAny<Func<Task<HttpResponseMessage>>>())).Returns(TaskHelpers.FromResult(response));
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
Func<Task<HttpResponseMessage>> continuation = () => TaskHelpers.FromResult<HttpResponseMessage>(new HttpResponseMessage());
TestTraceWriter traceWriter = new TestTraceWriter();
AuthorizationFilterTracer tracer = new AuthorizationFilterTracer(mockFilter.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteAuthorizationFilterAsync" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "ExecuteAuthorizationFilterAsync" },
};
// Act
Task task = ((IAuthorizationFilter)tracer).ExecuteAuthorizationFilterAsync(actionContext, CancellationToken.None, continuation);
task.Wait();
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteAuthorizationFilterAsync_Faults_And_Traces_When_Inner_Faults()
{
// Arrange
Mock<IAuthorizationFilter> mockAttr = new Mock<IAuthorizationFilter>() { CallBase = true };
HttpResponseMessage response = new HttpResponseMessage();
InvalidOperationException exception = new InvalidOperationException("test");
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>(response);
tcs.TrySetException(exception);
mockAttr.Setup(a => a.ExecuteAuthorizationFilterAsync(It.IsAny<HttpActionContext>(), It.IsAny<CancellationToken>(), It.IsAny<Func<Task<HttpResponseMessage>>>())).Returns(tcs.Task);
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionContext actionContext = ContextUtil.CreateActionContext(actionDescriptor: mockActionDescriptor.Object);
Func<Task<HttpResponseMessage>> continuation = () => TaskHelpers.FromResult<HttpResponseMessage>(response);
TestTraceWriter traceWriter = new TestTraceWriter();
AuthorizationFilterTracer tracer = new AuthorizationFilterTracer(mockAttr.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteAuthorizationFilterAsync" },
new TraceRecord(actionContext.Request, TraceCategories.FiltersCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "ExecuteAuthorizationFilterAsync" }
};
// Act & Assert
Task task = ((IAuthorizationFilter)tracer).ExecuteAuthorizationFilterAsync(actionContext, CancellationToken.None, continuation);
Exception thrown = Assert.Throws<InvalidOperationException>(() => task.Wait());
// Assert
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
}
}

View File

@@ -0,0 +1,192 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class ContentNegotiatorTracerTest
{
private readonly HttpRequestMessage _request = new HttpRequestMessage();
private readonly Mock<IContentNegotiator> _mockNegotiator = new Mock<IContentNegotiator>();
private readonly ContentNegotiatorTracer _tracer;
private readonly TestTraceWriter _traceWriter = new TestTraceWriter();
public ContentNegotiatorTracerTest()
{
_tracer = new ContentNegotiatorTracer(_mockNegotiator.Object, _traceWriter);
}
[Fact]
public void Negotiate_Calls_Inner_Negotiate()
{
// Act
((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]);
// Assert
_mockNegotiator.Verify(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>()), Times.Once());
}
[Fact]
public void Negotiate_Returns_Inner_MediaType()
{
// Arrange
MediaTypeHeaderValue expectedMediaType = new MediaTypeHeaderValue("application/xml");
_mockNegotiator.Setup(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>())).Returns(
new ContentNegotiationResult(new JsonMediaTypeFormatter(), expectedMediaType));
// Act
var result = ((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]);
// Assert
Assert.Same(expectedMediaType, result.MediaType);
}
[Fact]
public void Negotiate_Returns_Wrapped_Inner_XmlFormatter()
{
// Arrange
MediaTypeFormatter expectedFormatter = new XmlMediaTypeFormatter();
_mockNegotiator.Setup(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>())).Returns(
new ContentNegotiationResult(expectedFormatter, null));
// Act
var result = ((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]);
// Assert
Assert.IsType<XmlMediaTypeFormatterTracer>(result.Formatter);
}
[Fact]
public void Negotiate_Returns_Wrapped_Inner_JsonFormatter()
{
// Arrange
MediaTypeFormatter expectedFormatter = new JsonMediaTypeFormatter();
_mockNegotiator.Setup(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>())).Returns(
new ContentNegotiationResult(expectedFormatter, null));
// Act
var result = ((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]);
// Assert
Assert.IsType<JsonMediaTypeFormatterTracer>(result.Formatter);
}
[Fact]
public void Negotiate_Returns_Wrapped_Inner_FormUrlEncodedFormatter()
{
// Arrange
MediaTypeFormatter expectedFormatter = new FormUrlEncodedMediaTypeFormatter();
_mockNegotiator.Setup(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>())).Returns(
new ContentNegotiationResult(expectedFormatter, null));
// Act
var result = ((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]);
// Assert
Assert.IsType<FormUrlEncodedMediaTypeFormatterTracer>(result.Formatter);
}
[Fact]
public void Negotiate_Returns_Null_Inner_Formatter()
{
// Arrange
_mockNegotiator.Setup(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>())).Returns(
value: null);
// Act
var result = ((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]);
// Assert
Assert.Null(result);
}
[Fact]
public void Negotiate_Traces_BeginEnd()
{
// Arrange
MediaTypeFormatter expectedFormatter = new XmlMediaTypeFormatter();
_mockNegotiator.Setup(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>())).Returns(
new ContentNegotiationResult(expectedFormatter, null));
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_request, TraceCategories.FormattingCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_request, TraceCategories.FormattingCategory, TraceLevel.Info) { Kind = TraceKind.End }
};
// Act
((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]);
// Assert
Assert.Equal<TraceRecord>(expectedTraces, _traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void Negotiate_Throws_When_Inner_Throws()
{
// Arrange
MediaTypeFormatter expectedFormatter = new XmlMediaTypeFormatter();
InvalidOperationException expectedException = new InvalidOperationException("test");
_mockNegotiator.Setup(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>())).Throws(expectedException);
// Act & Assert
InvalidOperationException actualException = Assert.Throws<InvalidOperationException>(() => ((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]));
// Assert
Assert.Same(expectedException, actualException);
}
[Fact]
public void Negotiate_Traces_BeginEnd_When_Inner_Throws()
{
// Arrange
MediaTypeFormatter expectedFormatter = new XmlMediaTypeFormatter();
InvalidOperationException expectedException = new InvalidOperationException("test");
_mockNegotiator.Setup(
n =>
n.Negotiate(It.IsAny<Type>(), It.IsAny<HttpRequestMessage>(),
It.IsAny<IEnumerable<MediaTypeFormatter>>())).Throws(expectedException);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_request, TraceCategories.FormattingCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_request, TraceCategories.FormattingCategory, TraceLevel.Error) { Kind = TraceKind.End }
};
// Act & Assert
Assert.Throws<InvalidOperationException>(() => ((IContentNegotiator)_tracer).Negotiate(typeof(int), _request, new MediaTypeFormatter[0]));
// Assert
Assert.Equal<TraceRecord>(expectedTraces, _traceWriter.Traces, new TraceRecordComparer());
Assert.Same(expectedException, _traceWriter.Traces[1].Exception);
}
}
}

View File

@@ -0,0 +1,76 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class ExceptionFilterAttributeTracerTest
{
[Fact]
public void ExecuteExceptionFilterAsync_Traces()
{
// Arrange
HttpRequestMessage request = new HttpRequestMessage();
HttpResponseMessage response = new HttpResponseMessage();
Mock<ExceptionFilterAttribute> mockAttr = new Mock<ExceptionFilterAttribute>() { CallBase = true };
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionExecutedContext actionExecutedContext = ContextUtil.GetActionExecutedContext(request, response);
TestTraceWriter traceWriter = new TestTraceWriter();
ExceptionFilterAttributeTracer tracer = new ExceptionFilterAttributeTracer(mockAttr.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "OnException" },
new TraceRecord(request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "OnException" },
};
// Act
Task task = ((IExceptionFilter)tracer).ExecuteExceptionFilterAsync(actionExecutedContext, CancellationToken.None);
task.Wait();
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteExceptionFilterAsync_Throws_And_Traces_When_Inner_OnException_Throws()
{
// Arrange
HttpRequestMessage request = new HttpRequestMessage();
HttpResponseMessage response = new HttpResponseMessage();
Mock<ExceptionFilterAttribute> mockAttr = new Mock<ExceptionFilterAttribute>() { CallBase = true };
InvalidOperationException exception = new InvalidOperationException("test");
mockAttr.Setup(a => a.OnException(It.IsAny<HttpActionExecutedContext>())).Throws(exception);
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
HttpActionExecutedContext actionExecutedContext = ContextUtil.GetActionExecutedContext(request, response);
TestTraceWriter traceWriter = new TestTraceWriter();
ExceptionFilterAttributeTracer tracer = new ExceptionFilterAttributeTracer(mockAttr.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "OnException" },
new TraceRecord(request, TraceCategories.FiltersCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "OnException" }
};
// Act
Exception thrown =
Assert.Throws<InvalidOperationException>(
() => ((IExceptionFilter) tracer).ExecuteExceptionFilterAsync(actionExecutedContext, CancellationToken.None));
// Assert
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
}
}

View File

@@ -0,0 +1,73 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Filters;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class ExceptionFilterTracerTest
{
[Fact]
public void ExecuteExceptionFilterAsync_Traces()
{
// Arrange
HttpRequestMessage request = new HttpRequestMessage();
HttpResponseMessage response = new HttpResponseMessage();
Mock<IExceptionFilter> mockFilter = new Mock<IExceptionFilter>() { CallBase = true };
mockFilter.Setup(
f => f.ExecuteExceptionFilterAsync(It.IsAny<HttpActionExecutedContext>(), It.IsAny<CancellationToken>())).
Returns(TaskHelpers.Completed());
HttpActionExecutedContext actionExecutedContext = ContextUtil.GetActionExecutedContext(request, response);
TestTraceWriter traceWriter = new TestTraceWriter();
ExceptionFilterTracer tracer = new ExceptionFilterTracer(mockFilter.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteExceptionFilterAsync" },
new TraceRecord(request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "ExecuteExceptionFilterAsync" },
};
// Act
Task task = ((IExceptionFilter)tracer).ExecuteExceptionFilterAsync(actionExecutedContext, CancellationToken.None);
task.Wait();
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteExceptionFilterAsync_Faults_And_Traces_When_Inner_Faults()
{
// Arrange
HttpRequestMessage request = new HttpRequestMessage();
HttpResponseMessage response = new HttpResponseMessage();
Mock<IExceptionFilter> mockFilter = new Mock<IExceptionFilter>() { CallBase = true };
InvalidOperationException exception = new InvalidOperationException("test");
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(null);
tcs.TrySetException(exception);
mockFilter.Setup(a => a.ExecuteExceptionFilterAsync(It.IsAny<HttpActionExecutedContext>(), It.IsAny<CancellationToken>())).Returns(tcs.Task);
HttpActionExecutedContext actionExecutedContext = ContextUtil.GetActionExecutedContext(request, response);
TestTraceWriter traceWriter = new TestTraceWriter();
ExceptionFilterTracer tracer = new ExceptionFilterTracer(mockFilter.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(request, TraceCategories.FiltersCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteExceptionFilterAsync" },
new TraceRecord(request, TraceCategories.FiltersCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "ExecuteExceptionFilterAsync" }
};
// Act
Task task = ((IExceptionFilter)tracer).ExecuteExceptionFilterAsync(actionExecutedContext, CancellationToken.None);
// Assert
Exception thrown = Assert.Throws<InvalidOperationException>(() => task.Wait());
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
}
}

View File

@@ -0,0 +1,276 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class FilterTracerTest
{
[Fact]
public void CreateFilterTracers_IFilter_With_IFilter_Returns_Single_Wrapped_IFilter()
{
// Arrange
Mock<IFilter> mockFilter = new Mock<IFilter>();
// Act
IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<FilterTracer>(wrappedFilters[0]);
}
[Fact]
public void CreateFilterTracers_IFilter_With_IActionFilter_Returns_Single_Wrapped_IActionFilter()
{
// Arrange
Mock<IActionFilter> mockFilter = new Mock<IActionFilter>();
// Act
IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<ActionFilterTracer>(wrappedFilters[0]);
}
[Fact]
public void CreateFilterTracers_IFilter_With_IExceptionFilter_Returns_Single_Wrapped_IExceptionFilter()
{
// Arrange
Mock<IExceptionFilter> mockFilter = new Mock<IExceptionFilter>();
// Act
IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<ExceptionFilterTracer>(wrappedFilters[0]);
}
[Fact]
public void CreateFilterTracers_IFilter_With_IAuthorizationFilter_Returns_Single_Wrapped_IAuthorizationFilter()
{
// Arrange
Mock<IAuthorizationFilter> mockFilter = new Mock<IAuthorizationFilter>();
// Act
IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<AuthorizationFilterTracer>(wrappedFilters[0]);
}
[Fact]
public void CreateFilterTracers_IFilter_With_ActionFilterAttribute_Returns_Single_Wrapped_Filter()
{
// Arrange
Mock<ActionFilterAttribute> mockFilter = new Mock<ActionFilterAttribute>();
// Act
IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<ActionFilterAttributeTracer>(wrappedFilters[0]);
}
[Fact]
public void CreateFilterTracers_IFilter_With_ExceptionFilterAttribute_Returns_Single_Wrapped_Filter()
{
// Arrange
Mock<ExceptionFilterAttribute> mockFilter = new Mock<ExceptionFilterAttribute>();
// Act
IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<ExceptionFilterAttributeTracer>(wrappedFilters[0]);
}
[Fact]
public void CreateFilterTracers_IFilter_With_AuthorizationFilterAttribute_Returns_Single_Wrapped_Filter()
{
// Arrange
Mock<AuthorizationFilterAttribute> mockFilter = new Mock<AuthorizationFilterAttribute>();
// Act
IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(mockFilter.Object, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<AuthorizationFilterAttributeTracer>(wrappedFilters[0]);
}
[Fact]
public void CreateFilterTracers_IFilter_With_All_Filter_Interfaces_Returns_3_Wrapped_Filters()
{
// Arrange
IFilter filter = new TestFilterAllBehaviors();
// Act
IFilter[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(3, wrappedFilters.Length);
Assert.Equal(1, wrappedFilters.OfType<ActionFilterTracer>().Count());
Assert.Equal(1, wrappedFilters.OfType<AuthorizationFilterTracer>().Count());
Assert.Equal(1, wrappedFilters.OfType<ExceptionFilterTracer>().Count());
}
[Fact]
public void CreateFilterTracers_With_IFilter_Returns_Single_Wrapped_IFilter()
{
// Arrange
Mock<IFilter> mockFilter = new Mock<IFilter>();
FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action);
// Act
FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<FilterTracer>(wrappedFilters[0].Instance);
}
[Fact]
public void CreateFilterTracers_With_IActionFilter_Returns_Single_Wrapped_IActionFilter()
{
// Arrange
Mock<IActionFilter> mockFilter = new Mock<IActionFilter>();
FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action);
// Act
FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<ActionFilterTracer>(wrappedFilters[0].Instance);
}
[Fact]
public void CreateFilterTracers_With_IExceptionFilter_Returns_Single_Wrapped_IExceptionFilter()
{
// Arrange
Mock<IExceptionFilter> mockFilter = new Mock<IExceptionFilter>();
FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action);
// Act
FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<ExceptionFilterTracer>(wrappedFilters[0].Instance);
}
[Fact]
public void CreateFilterTracers_With_IAuthorizationFilter_Returns_Single_Wrapped_IAuthorizationFilter()
{
// Arrange
Mock<IAuthorizationFilter> mockFilter = new Mock<IAuthorizationFilter>();
FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action);
// Act
FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<AuthorizationFilterTracer>(wrappedFilters[0].Instance);
}
[Fact]
public void CreateFilterTracers_With_ActionFilterAttribute_Returns_2_Wrapped_Filters()
{
// Arrange
Mock<ActionFilterAttribute> mockFilter = new Mock<ActionFilterAttribute>();
FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action);
// Act
FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<ActionFilterAttributeTracer>(wrappedFilters[0].Instance);
}
[Fact]
public void CreateFilterTracers_With_ExceptionFilterAttribute_Returns_2_Wrapped_Filters()
{
// Arrange
Mock<ExceptionFilterAttribute> mockFilter = new Mock<ExceptionFilterAttribute>();
FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action);
// Act
FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<ExceptionFilterAttributeTracer>(wrappedFilters[0].Instance);
}
[Fact]
public void CreateFilterTracers_With_AuthorizationFilterAttribute_Returns_2_Wrapped_Filters()
{
// Arrange
Mock<AuthorizationFilterAttribute> mockFilter = new Mock<AuthorizationFilterAttribute>();
FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Action);
// Act
FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(1, wrappedFilters.Length);
Assert.IsType<AuthorizationFilterAttributeTracer>(wrappedFilters[0].Instance); ;
}
[Fact]
public void CreateFilterTracers_With_All_Filter_Interfaces_Returns_3_Wrapped_Filters()
{
// Arrange
FilterInfo filter = new FilterInfo(new TestFilterAllBehaviors(), FilterScope.Action);
// Act
FilterInfo[] wrappedFilters = FilterTracer.CreateFilterTracers(filter, new TestTraceWriter()).ToArray();
// Assert
Assert.Equal(3, wrappedFilters.Length);
Assert.Equal(1, wrappedFilters.Where(f => f.Instance.GetType() == typeof(ActionFilterTracer)).Count());
Assert.Equal(1, wrappedFilters.Where(f => f.Instance.GetType() == typeof(AuthorizationFilterTracer)).Count());
Assert.Equal(1, wrappedFilters.Where(f => f.Instance.GetType() == typeof(ExceptionFilterTracer)).Count());
}
// Test filter class that exposes all filter behaviors will cause separate filters for each
class TestFilterAllBehaviors : IActionFilter, IExceptionFilter, IAuthorizationFilter
{
Task<Net.Http.HttpResponseMessage> IActionFilter.ExecuteActionFilterAsync(Controllers.HttpActionContext actionContext, Threading.CancellationToken cancellationToken, Func<Threading.Tasks.Task<Net.Http.HttpResponseMessage>> continuation)
{
throw new NotImplementedException();
}
bool IFilter.AllowMultiple
{
get { throw new NotImplementedException(); }
}
Task IExceptionFilter.ExecuteExceptionFilterAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
Task<HttpResponseMessage> IAuthorizationFilter.ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<Net.Http.HttpResponseMessage>> continuation)
{
throw new NotImplementedException();
}
}
}
}

View File

@@ -0,0 +1,130 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Metadata;
using System.Web.Http.Metadata.Providers;
using System.Web.Http.ModelBinding;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class FormatterParameterBindingTracerTest
{
/// <summary>
/// This test verifies that our <see cref="FormatterParameterBindingTracer"/>
/// intercepts the async bind request and redirects it to use tracing formatters
/// correlated to the request.
/// </summary>
[Fact]
public void ExecuteBindingAsync_Traces_And_Invokes_Inner_ReadAsync()
{
// Arrange
Mock<HttpParameterDescriptor> mockParamDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
mockParamDescriptor.Setup(d => d.ParameterName).Returns("paramName");
mockParamDescriptor.Setup(d => d.ParameterType).Returns(typeof (string));
FormatterParameterBinding binding = new FormatterParameterBinding(mockParamDescriptor.Object, new MediaTypeFormatterCollection(), null);
TestTraceWriter traceWriter = new TestTraceWriter();
FormatterParameterBindingTracer tracer = new FormatterParameterBindingTracer(binding, traceWriter);
HttpActionContext actionContext = ContextUtil.CreateActionContext();
actionContext.Request.Content = new StringContent("true");
actionContext.Request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
ModelMetadataProvider metadataProvider = new EmptyModelMetadataProvider();
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteBindingAsync" },
new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info) { Kind = TraceKind.End, Operation = "ExecuteBindingAsync" }
};
// Act
Task task = tracer.ExecuteBindingAsync(metadataProvider, actionContext, CancellationToken.None);
task.Wait();
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.Equal("True", actionContext.ActionArguments["paramName"]);
}
[Fact]
public void ExecuteBindingAsync_Traces_And_Throws_When_Inner_Throws()
{
// Arrange
Mock<HttpParameterDescriptor> mockParamDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
mockParamDescriptor.Setup(d => d.ParameterName).Returns("paramName");
mockParamDescriptor.Setup(d => d.ParameterType).Returns(typeof(string));
Mock<FormatterParameterBinding> mockBinding = new Mock<FormatterParameterBinding>(mockParamDescriptor.Object, new MediaTypeFormatterCollection(), null) { CallBase = true };
InvalidOperationException exception = new InvalidOperationException("test");
mockBinding.Setup(
b =>
b.ExecuteBindingAsync(It.IsAny<ModelMetadataProvider>(), It.IsAny<HttpActionContext>(),
It.IsAny<CancellationToken>())).Throws(exception);
TestTraceWriter traceWriter = new TestTraceWriter();
FormatterParameterBindingTracer tracer = new FormatterParameterBindingTracer(mockBinding.Object, traceWriter);
HttpActionContext actionContext = ContextUtil.CreateActionContext();
ModelMetadataProvider metadataProvider = new EmptyModelMetadataProvider();
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteBindingAsync" },
new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "ExecuteBindingAsync" }
};
// Act & Assert
Exception thrown = Assert.Throws<InvalidOperationException>(() => tracer.ExecuteBindingAsync(metadataProvider, actionContext, CancellationToken.None));
// Assert
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteBindingAsync_Traces_And_Faults_When_Inner_Faults()
{
// Arrange
Mock<HttpParameterDescriptor> mockParamDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
mockParamDescriptor.Setup(d => d.ParameterName).Returns("paramName");
mockParamDescriptor.Setup(d => d.ParameterType).Returns(typeof(string));
Mock<FormatterParameterBinding> mockBinding = new Mock<FormatterParameterBinding>(mockParamDescriptor.Object, new MediaTypeFormatterCollection(), null) { CallBase = true };
InvalidOperationException exception = new InvalidOperationException("test");
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
tcs.TrySetException(exception);
mockBinding.Setup(
b =>
b.ExecuteBindingAsync(It.IsAny<ModelMetadataProvider>(), It.IsAny<HttpActionContext>(),
It.IsAny<CancellationToken>())).Returns(tcs.Task);
TestTraceWriter traceWriter = new TestTraceWriter();
FormatterParameterBindingTracer tracer = new FormatterParameterBindingTracer(mockBinding.Object, traceWriter);
HttpActionContext actionContext = ContextUtil.CreateActionContext();
ModelMetadataProvider metadataProvider = new EmptyModelMetadataProvider();
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteBindingAsync" },
new TraceRecord(actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Error) { Kind = TraceKind.End, Operation = "ExecuteBindingAsync" }
};
// Act & Assert
Task task = tracer.ExecuteBindingAsync(metadataProvider, actionContext, CancellationToken.None);
// Assert
Exception thrown = Assert.Throws<InvalidOperationException>(() => task.Wait());
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
}
}

View File

@@ -0,0 +1,103 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class HttpActionBindingTracerTest
{
private Mock<HttpActionDescriptor> _mockActionDescriptor;
private Mock<HttpParameterDescriptor> _mockParameterDescriptor;
private Mock<HttpParameterBinding> _mockParameterBinding;
private HttpActionBinding _actionBinding;
private HttpActionContext _actionContext;
private HttpControllerContext _controllerContext;
private HttpControllerDescriptor _controllerDescriptor;
public HttpActionBindingTracerTest()
{
_mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
_mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
_mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
_mockParameterDescriptor = new Mock<HttpParameterDescriptor>() { CallBase = true };
_mockParameterBinding = new Mock<HttpParameterBinding>(_mockParameterDescriptor.Object) { CallBase = true };
_actionBinding = new HttpActionBinding(_mockActionDescriptor.Object, new HttpParameterBinding[] { _mockParameterBinding.Object });
_controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "controller", typeof(ApiController));
_controllerContext = ContextUtil.CreateControllerContext(request: new HttpRequestMessage());
_controllerContext.ControllerDescriptor = _controllerDescriptor;
_actionContext = ContextUtil.CreateActionContext(_controllerContext, actionDescriptor: _mockActionDescriptor.Object);
}
[Fact]
public void BindValuesAsync_Invokes_Inner_And_Traces()
{
// Arrange
bool wasInvoked = false;
Mock<HttpActionBinding> mockBinder = new Mock<HttpActionBinding>() { CallBase = true };
mockBinder.Setup(b => b.ExecuteBindingAsync(
It.IsAny<HttpActionContext>(),
It.IsAny<CancellationToken>())).
Callback(() => wasInvoked = true).Returns(TaskHelpers.Completed());
TestTraceWriter traceWriter = new TestTraceWriter();
HttpActionBindingTracer tracer = new HttpActionBindingTracer(mockBinder.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info) { Kind = TraceKind.End }
};
// Act
tracer.ExecuteBindingAsync(_actionContext, CancellationToken.None).Wait();
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.True(wasInvoked);
}
[Fact]
public void ExecuteBindingAsync_Faults_And_Traces_When_Inner_Faults()
{
// Arrange
InvalidOperationException exception = new InvalidOperationException();
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
tcs.TrySetException(exception);
Mock<HttpActionBinding> mockBinder = new Mock<HttpActionBinding>() { CallBase = true };
mockBinder.Setup(b => b.ExecuteBindingAsync(
It.IsAny<HttpActionContext>(),
It.IsAny<CancellationToken>())).
Returns(tcs.Task);
TestTraceWriter traceWriter = new TestTraceWriter();
HttpActionBindingTracer tracer = new HttpActionBindingTracer(mockBinder.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_actionContext.Request, TraceCategories.ModelBindingCategory, TraceLevel.Error) { Kind = TraceKind.End }
};
// Act
Task task = tracer.ExecuteBindingAsync(_actionContext, CancellationToken.None);
// Assert
Exception thrown = Assert.Throws<InvalidOperationException>(() => task.Wait());
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
}
}
}

View File

@@ -0,0 +1,140 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class HttpActionDescriptorTracerTest
{
// This test verifies only one kind of filter is wrapped, proving
// the static FilterTracer.CreateFilterTracer was called from GetFilterPipeline.
// Deeper testing of FilterTracer.CreateFilterTracer is in FilterTracerTest.
[Fact]
public void GetFilterPipeline_Returns_Wrapped_Filters()
{
// Arrange
Mock<IFilter> mockFilter = new Mock<IFilter>();
FilterInfo filter = new FilterInfo(mockFilter.Object, FilterScope.Global);
Collection<FilterInfo> filterCollection = new Collection<FilterInfo>(new FilterInfo[] { filter });
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetFilterPipeline()).Returns(filterCollection);
HttpControllerContext controllerContext = ContextUtil.CreateControllerContext();
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "test", typeof(ApiController));
HttpActionDescriptorTracer tracer = new HttpActionDescriptorTracer(controllerContext, mockActionDescriptor.Object, new TestTraceWriter());
// Act
Collection<FilterInfo> wrappedFilterCollection = tracer.GetFilterPipeline();
// Assert
Assert.IsType<FilterTracer>(wrappedFilterCollection[0].Instance);
}
// This test verifies only one kind of filter is wrapped, proving
// the static FilterTracer.CreateFilterTracer was called from GetFilterPipeline.
// Deeper testing of FilterTracer.CreateFilterTracer is in FilterTracerTest.
[Fact]
public void GetFilters_Returns_Wrapped_IFilters()
{
// Arrange
Mock<IFilter> mockFilter = new Mock<IFilter>();
Collection<IFilter> filters = new Collection<IFilter>(new IFilter[] { mockFilter.Object });
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.GetFilters()).Returns(filters);
HttpControllerContext controllerContext = ContextUtil.CreateControllerContext();
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "test", typeof(ApiController));
HttpActionDescriptorTracer tracer = new HttpActionDescriptorTracer(controllerContext, mockActionDescriptor.Object, new TestTraceWriter());
// Act
IFilter[] wrappedFilters = tracer.GetFilters().ToArray();
// Assert
Assert.IsType<FilterTracer>(wrappedFilters[0]);
}
[Fact]
public void ExecuteAsync_Invokes_Inner_ExecuteAsync()
{
// Arrange
bool executeCalled = false;
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(
a => a.ExecuteAsync(It.IsAny<HttpControllerContext>(), It.IsAny<IDictionary<string, object>>())).Callback(() => executeCalled = true);
HttpControllerContext controllerContext = ContextUtil.CreateControllerContext();
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "test", typeof(ApiController));
IDictionary<string, object> arguments = new Dictionary<string, object>();
HttpActionDescriptorTracer tracer = new HttpActionDescriptorTracer(controllerContext, mockActionDescriptor.Object, new TestTraceWriter());
// Act
tracer.ExecuteAsync(controllerContext, arguments);
// Assert
Assert.True(executeCalled);
}
[Fact]
public void ExecuteAsync_Traces()
{
// Arrange
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
mockActionDescriptor.Setup(a => a.ExecuteAsync(It.IsAny<HttpControllerContext>(), It.IsAny<IDictionary<string, object>>()))
.Returns(TaskHelpers.FromResult<object>(null));
HttpControllerContext controllerContext = ContextUtil.CreateControllerContext();
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "test", typeof(ApiController));
IDictionary<string, object> arguments = new Dictionary<string, object>();
TestTraceWriter traceWriter = new TestTraceWriter();
HttpActionDescriptorTracer tracer = new HttpActionDescriptorTracer(controllerContext, mockActionDescriptor.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(controllerContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.Begin, Operation = "ExecuteAsync" },
new TraceRecord(controllerContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.End }
};
// Act
var result = tracer.ExecuteAsync(controllerContext, arguments);
// Assert
result.WaitUntilCompleted();
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void ExecuteAsync_Throws_What_Inner_Throws_And_Traces()
{
// Arrange
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
InvalidOperationException exception = new InvalidOperationException("test");
mockActionDescriptor.Setup(
a => a.ExecuteAsync(It.IsAny<HttpControllerContext>(), It.IsAny<IDictionary<string, object>>())).Throws(exception);
mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
HttpControllerContext controllerContext = ContextUtil.CreateControllerContext();
controllerContext.ControllerDescriptor = new HttpControllerDescriptor(controllerContext.Configuration, "test", typeof(ApiController));
IDictionary<string, object> arguments = new Dictionary<string, object>();
TestTraceWriter traceWriter = new TestTraceWriter();
HttpActionDescriptorTracer tracer = new HttpActionDescriptorTracer(controllerContext, mockActionDescriptor.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(controllerContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(controllerContext.Request, TraceCategories.ActionCategory, TraceLevel.Error) { Kind = TraceKind.End }
};
// Act & Assert
Assert.Throws<InvalidOperationException>(() => tracer.ExecuteAsync(controllerContext, arguments));
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.Same(exception, traceWriter.Traces[1].Exception);
}
}
}

View File

@@ -0,0 +1,227 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class HttpActionInvokerTracerTest
{
private HttpActionContext _actionContext;
private ApiController _apiController;
public HttpActionInvokerTracerTest()
{
UsersController controller = new UsersController();
_apiController = controller;
Func<HttpResponseMessage> actionMethod = controller.Get;
_actionContext = ContextUtil.CreateActionContext(
ContextUtil.CreateControllerContext(instance: _apiController),
new ReflectedHttpActionDescriptor { MethodInfo = actionMethod.Method });
HttpRequestMessage request = new HttpRequestMessage();
_actionContext.ControllerContext.Request = request;
}
[Fact]
public void InvokeActionAsync_Calls_ActionDescriptor_ExecuteAsync()
{
// Arrange
Mock<HttpActionDescriptor> mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
mockActionDescriptor.Setup(a => a.ActionName).Returns("mockAction");
mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
mockActionDescriptor.Setup(a => a.ReturnType).Returns(typeof(void));
mockActionDescriptor.Setup(a => a.ResultConverter).Returns(new VoidResultConverter());
bool executeWasCalled = false;
mockActionDescriptor.Setup(a => a.ExecuteAsync(It.IsAny<HttpControllerContext>(), It.IsAny<IDictionary<string, object>>()))
.Returns(() => TaskHelpers.FromResult<object>(null))
.Callback(() => { executeWasCalled = true; });
HttpActionContext context = ContextUtil.CreateActionContext(
ContextUtil.CreateControllerContext(instance: _apiController),
mockActionDescriptor.Object);
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(new ApiControllerActionInvoker(), new TestTraceWriter());
// Act
((IHttpActionInvoker)tracer).InvokeActionAsync(context, CancellationToken.None).Wait();
// Assert
Assert.True(executeWasCalled);
}
[Fact]
public void InvokeActionAsync_Traces_Begin_And_End_Info()
{
// Arrange
TestTraceWriter traceWriter = new TestTraceWriter();
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(new ApiControllerActionInvoker(), traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.End }
};
// Act
Task task = ((IHttpActionInvoker)tracer).InvokeActionAsync(_actionContext, CancellationToken.None);
task.Wait();
// Assert
Assert.Equal(2, traceWriter.Traces.Count);
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void InvokeActionAsync_Returns_Cancelled_Inner_Task()
{
// Arrange
CancellationTokenSource cancellationSource = new CancellationTokenSource();
cancellationSource.Cancel();
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(new ApiControllerActionInvoker(), new TestTraceWriter());
// Act
var response = ((IHttpActionInvoker)tracer).InvokeActionAsync(_actionContext, cancellationSource.Token);
// Assert
Assert.Throws<TaskCanceledException>(() => { response.Wait(); });
Assert.Equal<TaskStatus>(TaskStatus.Canceled, response.Status);
}
[Fact]
public void InvokeActionAsync_Traces_Cancelled_Inner_Task()
{
// Arrange
TestTraceWriter traceWriter = new TestTraceWriter();
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(new ApiControllerActionInvoker(), traceWriter);
CancellationTokenSource cancellationSource = new CancellationTokenSource();
cancellationSource.Cancel();
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Warn) { Kind = TraceKind.End }
};
// Act
var response = ((IHttpActionInvoker)tracer).InvokeActionAsync(_actionContext, cancellationSource.Token);
// Assert
Assert.Throws<TaskCanceledException>(() => { response.Wait(); });
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
}
[Fact]
public void InvokeActionAsync_Returns_Faulted_Inner_Task()
{
// Arrange
Mock<ApiControllerActionInvoker> mockActionInvoker = new Mock<ApiControllerActionInvoker>() { CallBase = true };
InvalidOperationException expectedException = new InvalidOperationException("test message");
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>(null);
tcs.TrySetException(expectedException);
mockActionInvoker.Setup(
a => a.InvokeActionAsync(It.IsAny<HttpActionContext>(), It.IsAny<CancellationToken>())).Returns(tcs.Task);
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(mockActionInvoker.Object, new TestTraceWriter());
// Act
var response = ((IHttpActionInvoker)tracer).InvokeActionAsync(_actionContext, CancellationToken.None);
// Assert
Assert.Throws<InvalidOperationException>(() => response.Wait());
Assert.Equal<TaskStatus>(TaskStatus.Faulted, response.Status);
Assert.Equal(expectedException.Message, response.Exception.GetBaseException().Message);
}
[Fact]
public void InvokeActionAsync_Traces_Faulted_Inner_Task()
{
// Arrange
Mock<ApiControllerActionInvoker> mockActionInvoker = new Mock<ApiControllerActionInvoker>() { CallBase = true };
InvalidOperationException expectedException = new InvalidOperationException("test message");
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>(null);
tcs.TrySetException(expectedException);
mockActionInvoker.Setup(
a => a.InvokeActionAsync(It.IsAny<HttpActionContext>(), It.IsAny<CancellationToken>())).Returns(tcs.Task);
TestTraceWriter traceWriter = new TestTraceWriter();
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(mockActionInvoker.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Error) { Kind = TraceKind.End }
};
// Act
var response = ((IHttpActionInvoker)tracer).InvokeActionAsync(_actionContext, CancellationToken.None);
// Assert
Assert.Throws<InvalidOperationException>(() => response.Wait());
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.Equal(expectedException, traceWriter.Traces[1].Exception);
}
[Fact]
public void InvokeActionAsync_Throws_When_ActionContext_Is_Null()
{
// Arrange
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(new ApiControllerActionInvoker(), new TestTraceWriter());
// Act & Assert
Assert.ThrowsArgumentNull(
() => ((IHttpActionInvoker)tracer).InvokeActionAsync(null, CancellationToken.None),
"actionContext");
}
[Fact]
public void InvokeActionAsync_Throws_Exception_Thrown_From_Inner()
{
// Arrange
InvalidOperationException expectedException = new InvalidOperationException("test message");
Mock<ApiControllerActionInvoker> mockActionInvoker = new Mock<ApiControllerActionInvoker>() {CallBase = true};
mockActionInvoker.Setup(
a => a.InvokeActionAsync(It.IsAny<HttpActionContext>(), It.IsAny<CancellationToken>())).Throws(expectedException);
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(mockActionInvoker.Object, new TestTraceWriter());
// Act & Assert
InvalidOperationException thrownException = Assert.Throws<InvalidOperationException>(
() => ((IHttpActionInvoker)tracer).InvokeActionAsync(_actionContext, CancellationToken.None)
);
// Assert
Assert.Equal(expectedException, thrownException);
}
[Fact]
public void InvokeActionAsync_Traces_Exception_Thrown_From_Inner()
{
// Arrange
InvalidOperationException expectedException = new InvalidOperationException("test message");
Mock<ApiControllerActionInvoker> mockActionInvoker = new Mock<ApiControllerActionInvoker>() { CallBase = true };
mockActionInvoker.Setup(
a => a.InvokeActionAsync(It.IsAny<HttpActionContext>(), It.IsAny<CancellationToken>())).Throws(expectedException);
TestTraceWriter traceWriter = new TestTraceWriter();
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(mockActionInvoker.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Error) { Kind = TraceKind.End }
};
// Act & Assert
Assert.Throws<InvalidOperationException>(
() => ((IHttpActionInvoker)tracer).InvokeActionAsync(_actionContext, CancellationToken.None)
);
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.Equal(expectedException, traceWriter.Traces[1].Exception);
}
}
}

View File

@@ -0,0 +1,82 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Web.Http.Controllers;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Http.Tracing.Tracers
{
public class HttpActionSelectorTracerTest
{
private Mock<HttpActionDescriptor> _mockActionDescriptor;
private HttpActionContext _actionContext;
private HttpControllerContext _controllerContext;
private HttpControllerDescriptor _controllerDescriptor;
public HttpActionSelectorTracerTest()
{
_mockActionDescriptor = new Mock<HttpActionDescriptor>() { CallBase = true };
_mockActionDescriptor.Setup(a => a.ActionName).Returns("test");
_mockActionDescriptor.Setup(a => a.GetParameters()).Returns(new Collection<HttpParameterDescriptor>(new HttpParameterDescriptor[0]));
_controllerDescriptor = new HttpControllerDescriptor(new HttpConfiguration(), "controller", typeof(ApiController));
_controllerContext = ContextUtil.CreateControllerContext(request: new HttpRequestMessage());
_controllerContext.ControllerDescriptor = _controllerDescriptor;
_actionContext = ContextUtil.CreateActionContext(_controllerContext, actionDescriptor: _mockActionDescriptor.Object);
}
[Fact]
public void SelectAction_Traces_And_Returns_ActionDescriptor_Tracer()
{
// Arrange
TestTraceWriter traceWriter = new TestTraceWriter();
Mock<IHttpActionSelector> mockSelector = new Mock<IHttpActionSelector>();
mockSelector.Setup(s => s.SelectAction(_controllerContext)).Returns(_mockActionDescriptor.Object);
HttpActionSelectorTracer tracer = new HttpActionSelectorTracer(mockSelector.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.End }
};
// Act
HttpActionDescriptor selectedActionDescriptor = ((IHttpActionSelector)tracer).SelectAction(_controllerContext);
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.IsAssignableFrom<HttpActionDescriptorTracer>(selectedActionDescriptor);
}
[Fact]
public void SelectAction_Traces_And_Throws_Exception_Thrown_From_Inner()
{
// Arrange
TestTraceWriter traceWriter = new TestTraceWriter();
Mock<IHttpActionSelector> mockSelector = new Mock<IHttpActionSelector>();
InvalidOperationException exception = new InvalidOperationException();
mockSelector.Setup(s => s.SelectAction(_controllerContext)).Throws(exception);
HttpActionSelectorTracer tracer = new HttpActionSelectorTracer(mockSelector.Object, traceWriter);
TraceRecord[] expectedTraces = new TraceRecord[]
{
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Info) { Kind = TraceKind.Begin },
new TraceRecord(_actionContext.Request, TraceCategories.ActionCategory, TraceLevel.Error) { Kind = TraceKind.End }
};
// Act
Exception thrown = Assert.Throws<InvalidOperationException>(() => ((IHttpActionSelector)tracer).SelectAction(_controllerContext));
// Assert
Assert.Equal<TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
Assert.Same(exception, thrown);
Assert.Same(exception, traceWriter.Traces[1].Exception);
}
}
}

Some files were not shown because too many files have changed in this diff Show More