Refactoring ILogger, see aspnet/Logging#3

This commit is contained in:
SonjaKhan 2014-10-06 13:56:23 -07:00
parent 3ff9d6e8a0
commit 2a8ac595d8
11 changed files with 330 additions and 207 deletions

View File

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.22013.1 VisualStudioVersion = 14.0.22115.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0E966C37-7334-4D96-AAF6-9F49FBD166E3}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0E966C37-7334-4D96-AAF6-9F49FBD166E3}"
EndProject EndProject

View File

@ -7,9 +7,9 @@ namespace Microsoft.AspNet.Routing.Logging
{ {
internal static class LoggerExtensions internal static class LoggerExtensions
{ {
public static bool WriteValues([NotNull] this ILogger logger, object values) public static void WriteValues([NotNull] this ILogger logger, object values)
{ {
return logger.WriteCore( logger.Write(
eventType: TraceType.Information, eventType: TraceType.Information,
eventId: 0, eventId: 0,
state: values, state: values,

View File

@ -14,14 +14,14 @@ namespace Microsoft.AspNet.Routing
public class ConstraintMatcherTest public class ConstraintMatcherTest
{ {
#if ASPNET50 #if ASPNET50
private const string _name = "name";
[Fact] [Fact]
public void MatchUrlGeneration_DoesNotLogData() public void MatchUrlGeneration_DoesNotLogData()
{ {
// Arrange // Arrange
var name = "name";
var sink = new TestSink(); var sink = new TestSink();
var logger = new TestLogger(name, sink); var logger = new TestLogger(_name, sink, enabled: true);
var routeValueDictionary = new RouteValueDictionary(new { a = "value", b = "value" }); var routeValueDictionary = new RouteValueDictionary(new { a = "value", b = "value" });
var constraints = new Dictionary<string, IRouteConstraint> var constraints = new Dictionary<string, IRouteConstraint>
@ -41,62 +41,40 @@ namespace Microsoft.AspNet.Routing
// Assert // Assert
// There are no BeginScopes called. // There are no BeginScopes called.
Assert.Equal(0, sink.Scopes.Count); Assert.Empty(sink.Scopes);
// There are no WriteCores called. // There are no WriteCores called.
Assert.Equal(0, sink.Writes.Count); Assert.Empty(sink.Writes);
} }
[Fact] [Fact]
public void MatchFail_LogsCorrectData() public void MatchFail_LogsCorrectData()
{ {
// Arrange // Arrange & Act
var name = "name";
var sink = new TestSink();
var logger = new TestLogger(name, sink);
var routeValueDictionary = new RouteValueDictionary(new { a = "value", b = "value" });
var constraints = new Dictionary<string, IRouteConstraint> var constraints = new Dictionary<string, IRouteConstraint>
{ {
{"a", new PassConstraint()}, {"a", new PassConstraint()},
{"b", new FailConstraint()} {"b", new FailConstraint()}
}; };
var sink = SetUpMatch(constraints, true);
// Act
RouteConstraintMatcher.Match(
constraints: constraints,
routeValues: routeValueDictionary,
httpContext: new Mock<HttpContext>().Object,
route: new Mock<IRouter>().Object,
routeDirection: RouteDirection.IncomingRequest,
logger: logger);
// Assert // Assert
// There are no begin scopes called. // There are no begin scopes called.
Assert.Equal(0, sink.Scopes.Count); Assert.Empty(sink.Scopes);
// There are two records for IsEnabled and two for WriteCore. // There are two records for WriteCore.
Assert.Equal(4, sink.Writes.Count); Assert.Equal(2, sink.Writes.Count);
var enabled = sink.Writes[0]; var write = sink.Writes[0];
Assert.Equal(name, enabled.LoggerName); Assert.Equal(_name, write.LoggerName);
Assert.Null(enabled.State);
var write = sink.Writes[1];
Assert.Equal(name, write.LoggerName);
var values = Assert.IsType<RouteConstraintMatcherMatchValues>(write.State); var values = Assert.IsType<RouteConstraintMatcherMatchValues>(write.State);
Assert.Equal("RouteConstraintMatcher.Match", values.Name); Assert.Equal("RouteConstraintMatcher.Match", values.Name);
Assert.Equal("a", values.ConstraintKey); Assert.Equal("a", values.ConstraintKey);
Assert.Equal(constraints["a"], values.Constraint); Assert.Equal(constraints["a"], values.Constraint);
Assert.Equal(true, values.Matched); Assert.Equal(true, values.Matched);
enabled = sink.Writes[2]; write = sink.Writes[1];
Assert.Equal(name, enabled.LoggerName); Assert.Equal(_name, write.LoggerName);
Assert.Null(enabled.State);
write = sink.Writes[3];
Assert.Equal(name, write.LoggerName);
values = Assert.IsType<RouteConstraintMatcherMatchValues>(write.State); values = Assert.IsType<RouteConstraintMatcherMatchValues>(write.State);
Assert.Equal("RouteConstraintMatcher.Match", values.Name); Assert.Equal("RouteConstraintMatcher.Match", values.Name);
Assert.Equal("b", values.ConstraintKey); Assert.Equal("b", values.ConstraintKey);
@ -104,56 +82,53 @@ namespace Microsoft.AspNet.Routing
Assert.Equal(false, values.Matched); Assert.Equal(false, values.Matched);
} }
[Fact]
public void MatchFail_DisabledLoggerDoesNotLog()
{
// Arrange & Act
var constraints = new Dictionary<string, IRouteConstraint>
{
{"a", new PassConstraint()},
{"b", new FailConstraint()}
};
var sink = SetUpMatch(constraints, false);
// Assert
// There are no begin scopes called.
Assert.Empty(sink.Scopes);
// Logger is disabled so it should not write
Assert.Empty(sink.Writes);
}
[Fact] [Fact]
public void MatchSuccess_LogsCorrectData() public void MatchSuccess_LogsCorrectData()
{ {
// Arrange // Arrange & Act
var name = "name";
var sink = new TestSink();
var logger = new TestLogger(name, sink);
var routeValueDictionary = new RouteValueDictionary(new { a = "value", b = "value" });
var constraints = new Dictionary<string, IRouteConstraint> var constraints = new Dictionary<string, IRouteConstraint>
{ {
{"a", new PassConstraint()}, {"a", new PassConstraint()},
{"b", new PassConstraint()} {"b", new PassConstraint()}
}; };
var sink = SetUpMatch(constraints, true);
// Act
RouteConstraintMatcher.Match(
constraints: constraints,
routeValues: routeValueDictionary,
httpContext: new Mock<HttpContext>().Object,
route: new Mock<IRouter>().Object,
routeDirection: RouteDirection.IncomingRequest,
logger: logger);
// Assert // Assert
// There are no begin scopes called. // There are no begin scopes called.
Assert.Equal(0, sink.Scopes.Count); Assert.Empty(sink.Scopes);
// There are two records for IsEnabled and two for WriteCore. // There are two records WriteCore.
Assert.Equal(4, sink.Writes.Count); Assert.Equal(2, sink.Writes.Count);
var enabled = sink.Writes[0]; var write = sink.Writes[0];
Assert.Equal(name, enabled.LoggerName); Assert.Equal(_name, write.LoggerName);
Assert.Null(enabled.State);
var write = sink.Writes[1];
Assert.Equal(name, write.LoggerName);
var values = Assert.IsType<RouteConstraintMatcherMatchValues>(write.State); var values = Assert.IsType<RouteConstraintMatcherMatchValues>(write.State);
Assert.Equal("RouteConstraintMatcher.Match", values.Name); Assert.Equal("RouteConstraintMatcher.Match", values.Name);
Assert.Equal("a", values.ConstraintKey); Assert.Equal("a", values.ConstraintKey);
Assert.Equal(constraints["a"], values.Constraint); Assert.Equal(constraints["a"], values.Constraint);
Assert.Equal(true, values.Matched); Assert.Equal(true, values.Matched);
enabled = sink.Writes[2]; write = sink.Writes[1];
Assert.Equal(name, enabled.LoggerName); Assert.Equal(_name, write.LoggerName);
Assert.Null(enabled.State);
write = sink.Writes[3];
Assert.Equal(name, write.LoggerName);
values = Assert.IsType<RouteConstraintMatcherMatchValues>(write.State); values = Assert.IsType<RouteConstraintMatcherMatchValues>(write.State);
Assert.Equal("RouteConstraintMatcher.Match", values.Name); Assert.Equal("RouteConstraintMatcher.Match", values.Name);
Assert.Equal("b", values.ConstraintKey); Assert.Equal("b", values.ConstraintKey);
@ -161,6 +136,25 @@ namespace Microsoft.AspNet.Routing
Assert.Equal(true, values.Matched); Assert.Equal(true, values.Matched);
} }
[Fact]
public void MatchSuccess_DisabledLoggerDoesNotLog()
{
// Arrange & Act
var constraints = new Dictionary<string, IRouteConstraint>
{
{"a", new PassConstraint()},
{"b", new PassConstraint()}
};
var sink = SetUpMatch(constraints, false);
// Assert
// There are no begin scopes called.
Assert.Empty(sink.Scopes);
// Disabled Logger should not write
Assert.Empty(sink.Writes);
}
[Fact] [Fact]
public void ReturnsTrueOnValidConstraints() public void ReturnsTrueOnValidConstraints()
{ {
@ -272,6 +266,25 @@ namespace Microsoft.AspNet.Routing
routeDirection: RouteDirection.IncomingRequest, routeDirection: RouteDirection.IncomingRequest,
logger: NullLogger.Instance)); logger: NullLogger.Instance));
} }
private TestSink SetUpMatch(Dictionary<string, IRouteConstraint> constraints, bool enabled)
{
// Arrange
var sink = new TestSink();
var logger = new TestLogger(_name, sink, enabled);
var routeValueDictionary = new RouteValueDictionary(new { a = "value", b = "value" });
// Act
RouteConstraintMatcher.Match(
constraints: constraints,
routeValues: routeValueDictionary,
httpContext: new Mock<HttpContext>().Object,
route: new Mock<IRouter>().Object,
routeDirection: RouteDirection.IncomingRequest,
logger: logger);
return sink;
}
#endif #endif
private class PassConstraint : IRouteConstraint private class PassConstraint : IRouteConstraint

View File

@ -15,7 +15,11 @@ namespace Microsoft.AspNet.Routing
return NullDisposable.Instance; return NullDisposable.Instance;
} }
public bool WriteCore(TraceType eventType, int eventId, object state, Exception exception, Func<object, Exception, string> formatter) public void Write(TraceType eventType, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
{
}
public bool IsEnabled(TraceType eventType)
{ {
return false; return false;
} }

View File

@ -11,12 +11,14 @@ namespace Microsoft.AspNet.Routing
private object _scope; private object _scope;
private TestSink _sink; private TestSink _sink;
private string _name; private string _name;
private bool _enabled;
public TestLogger(string name, TestSink sink) public TestLogger(string name, TestSink sink, bool enabled)
{ {
_sink = sink; _sink = sink;
_name = name; _name = name;
} _enabled = enabled;
}
public string Name { get; set; } public string Name { get; set; }
@ -33,9 +35,9 @@ namespace Microsoft.AspNet.Routing
return NullDisposable.Instance; return NullDisposable.Instance;
} }
public bool WriteCore(TraceType eventType, int eventId, object state, Exception exception, Func<object, Exception, string> formatter) public void Write(TraceType eventType, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
{ {
_sink.Write(new WriteCoreContext() _sink.Write(new WriteContext()
{ {
EventType = eventType, EventType = eventType,
EventId = eventId, EventId = eventId,
@ -45,8 +47,11 @@ namespace Microsoft.AspNet.Routing
LoggerName = _name, LoggerName = _name,
Scope = _scope Scope = _scope
}); });
}
return true; public bool IsEnabled(TraceType eventType)
{
return _enabled;
} }
} }
} }

View File

@ -8,15 +8,17 @@ namespace Microsoft.AspNet.Routing
public class TestLoggerFactory : ILoggerFactory public class TestLoggerFactory : ILoggerFactory
{ {
private TestSink _sink; private TestSink _sink;
private bool _enabled;
public TestLoggerFactory(TestSink sink) public TestLoggerFactory(TestSink sink, bool enabled)
{ {
_sink = sink; _sink = sink;
_enabled = enabled;
} }
public ILogger Create(string name) public ILogger Create(string name)
{ {
return new TestLogger(name, _sink); return new TestLogger(name, _sink, _enabled);
} }
public void AddProvider(ILoggerProvider provider) public void AddProvider(ILoggerProvider provider)

View File

@ -9,25 +9,25 @@ namespace Microsoft.AspNet.Routing
public class TestSink public class TestSink
{ {
public TestSink( public TestSink(
Func<WriteCoreContext, bool> writeEnabled = null, Func<WriteContext, bool> writeEnabled = null,
Func<BeginScopeContext, bool> beginEnabled = null) Func<BeginScopeContext, bool> beginEnabled = null)
{ {
WriteEnabled = writeEnabled; WriteEnabled = writeEnabled;
BeginEnabled = beginEnabled; BeginEnabled = beginEnabled;
Scopes = new List<BeginScopeContext>(); Scopes = new List<BeginScopeContext>();
Writes = new List<WriteCoreContext>(); Writes = new List<WriteContext>();
} }
public Func<WriteCoreContext, bool> WriteEnabled { get; set; } public Func<WriteContext, bool> WriteEnabled { get; set; }
public Func<BeginScopeContext, bool> BeginEnabled { get; set; } public Func<BeginScopeContext, bool> BeginEnabled { get; set; }
public List<BeginScopeContext> Scopes { get; set; } public List<BeginScopeContext> Scopes { get; set; }
public List<WriteCoreContext> Writes { get; set; } public List<WriteContext> Writes { get; set; }
public void Write(WriteCoreContext context) public void Write(WriteContext context)
{ {
if (WriteEnabled == null || WriteEnabled(context)) if (WriteEnabled == null || WriteEnabled(context))
{ {
@ -43,7 +43,7 @@ namespace Microsoft.AspNet.Routing
} }
} }
public static bool EnableWithTypeName<T>(WriteCoreContext context) public static bool EnableWithTypeName<T>(WriteContext context)
{ {
return context.LoggerName.Equals(typeof(T).FullName); return context.LoggerName.Equals(typeof(T).FullName);
} }

View File

@ -6,7 +6,7 @@ using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Routing namespace Microsoft.AspNet.Routing
{ {
public class WriteCoreContext public class WriteContext
{ {
public TraceType EventType { get; set; } public TraceType EventType { get; set; }

View File

@ -19,36 +19,18 @@ namespace Microsoft.AspNet.Routing
[Fact] [Fact]
public async Task RouteAsync_LogsCorrectValuesWhenHandled() public async Task RouteAsync_LogsCorrectValuesWhenHandled()
{ {
// Arrange // Arrange & Act
var sink = new TestSink( var sink = await SetUp(enabled: true, handled: true);
TestSink.EnableWithTypeName<RouteCollection>,
TestSink.EnableWithTypeName<RouteCollection>);
var loggerFactory = new TestLoggerFactory(sink);
var routes = new RouteCollection();
var route = CreateRoute(accept: true);
routes.Add(route.Object);
var context = CreateRouteContext("/Cool", loggerFactory);
// Act
await routes.RouteAsync(context);
// Assert // Assert
Assert.Equal(1, sink.Scopes.Count); Assert.Single(sink.Scopes);
var scope = sink.Scopes[0]; var scope = sink.Scopes[0];
Assert.Equal(typeof(RouteCollection).FullName, scope.LoggerName); Assert.Equal(typeof(RouteCollection).FullName, scope.LoggerName);
Assert.Equal("RouteCollection.RouteAsync", scope.Scope); Assert.Equal("RouteCollection.RouteAsync", scope.Scope);
// There is a record for IsEnabled and one for WriteCore. Assert.Single(sink.Writes);
Assert.Equal(2, sink.Writes.Count);
var enabled = sink.Writes[0]; var write = sink.Writes[0];
Assert.Equal(typeof(RouteCollection).FullName, enabled.LoggerName);
Assert.Equal("RouteCollection.RouteAsync", enabled.Scope);
Assert.Null(enabled.State);
var write = sink.Writes[1];
Assert.Equal(typeof(RouteCollection).FullName, write.LoggerName); Assert.Equal(typeof(RouteCollection).FullName, write.LoggerName);
Assert.Equal("RouteCollection.RouteAsync", write.Scope); Assert.Equal("RouteCollection.RouteAsync", write.Scope);
var values = Assert.IsType<RouteCollectionRouteAsyncValues>(write.State); var values = Assert.IsType<RouteCollectionRouteAsyncValues>(write.State);
@ -58,38 +40,36 @@ namespace Microsoft.AspNet.Routing
} }
[Fact] [Fact]
public async Task RouteAsync_LogsCorrectValuesWhenNotHandled() public async Task RouteAsync_DoesNotLogWhenDisabledAndHandled()
{ {
// Arrange // Arrange & Act
var sink = new TestSink( var sink = await SetUp(enabled: false, handled: true);
TestSink.EnableWithTypeName<RouteCollection>,
TestSink.EnableWithTypeName<RouteCollection>);
var loggerFactory = new TestLoggerFactory(sink);
var routes = new RouteCollection();
var route = CreateRoute(accept: false);
routes.Add(route.Object);
var context = CreateRouteContext("/Cool", loggerFactory);
// Act
await routes.RouteAsync(context);
// Assert // Assert
Assert.Equal(1, sink.Scopes.Count); Assert.Single(sink.Scopes);
var scope = sink.Scopes[0];
Assert.Equal(typeof(RouteCollection).FullName, scope.LoggerName);
Assert.Equal("RouteCollection.RouteAsync", scope.Scope);
Assert.Empty(sink.Writes);
}
[Fact]
public async Task RouteAsync_LogsCorrectValuesWhenNotHandled()
{
// Arrange & Act
var sink = await SetUp(enabled: true, handled: false);
// Assert
Assert.Single(sink.Scopes);
var scope = sink.Scopes[0]; var scope = sink.Scopes[0];
Assert.Equal(typeof(RouteCollection).FullName, scope.LoggerName); Assert.Equal(typeof(RouteCollection).FullName, scope.LoggerName);
Assert.Equal("RouteCollection.RouteAsync", scope.Scope); Assert.Equal("RouteCollection.RouteAsync", scope.Scope);
// There is a record for IsEnabled and one for WriteCore. // There is a record for IsEnabled and one for WriteCore.
Assert.Equal(2, sink.Writes.Count); Assert.Single(sink.Writes);
var enabled = sink.Writes[0]; var write = sink.Writes[0];
Assert.Equal(typeof(RouteCollection).FullName, enabled.LoggerName);
Assert.Equal("RouteCollection.RouteAsync", enabled.Scope);
Assert.Null(enabled.State);
var write = sink.Writes[1];
Assert.Equal(typeof(RouteCollection).FullName, write.LoggerName); Assert.Equal(typeof(RouteCollection).FullName, write.LoggerName);
Assert.Equal("RouteCollection.RouteAsync", write.Scope); Assert.Equal("RouteCollection.RouteAsync", write.Scope);
var values = Assert.IsType<RouteCollectionRouteAsyncValues>(write.State); var values = Assert.IsType<RouteCollectionRouteAsyncValues>(write.State);
@ -98,6 +78,21 @@ namespace Microsoft.AspNet.Routing
Assert.Equal(false, values.Handled); Assert.Equal(false, values.Handled);
} }
[Fact]
public async Task RouteAsync_DoesNotLogWhenDisabledAndNotHandled()
{
// Arrange & Act
var sink = await SetUp(enabled: false, handled: false);
// Assert
Assert.Single(sink.Scopes);
var scope = sink.Scopes[0];
Assert.Equal(typeof(RouteCollection).FullName, scope.LoggerName);
Assert.Equal("RouteCollection.RouteAsync", scope.Scope);
Assert.Empty(sink.Writes);
}
[Fact] [Fact]
public async Task RouteAsync_FirstMatches() public async Task RouteAsync_FirstMatches()
{ {
@ -228,6 +223,26 @@ namespace Microsoft.AspNet.Routing
Assert.Equal("The supplied route name 'ambiguousRoute' is ambiguous and matched more than one route.", ex.Message); Assert.Equal("The supplied route name 'ambiguousRoute' is ambiguous and matched more than one route.", ex.Message);
} }
private static async Task<TestSink> SetUp(bool enabled, bool handled)
{
// Arrange
var sink = new TestSink(
TestSink.EnableWithTypeName<RouteCollection>,
TestSink.EnableWithTypeName<RouteCollection>);
var loggerFactory = new TestLoggerFactory(sink, enabled);
var routes = new RouteCollection();
var route = CreateRoute(accept: handled);
routes.Add(route.Object);
var context = CreateRouteContext("/Cool", loggerFactory);
// Act
await routes.RouteAsync(context);
return sink;
}
private static RouteCollection GetRouteCollectionWithNamedRoutes(IEnumerable<string> routeNames) private static RouteCollection GetRouteCollectionWithNamedRoutes(IEnumerable<string> routeNames)
{ {
var routes = new RouteCollection(); var routes = new RouteCollection();

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Routing
var sink = new TestSink( var sink = new TestSink(
TestSink.EnableWithTypeName<RouterMiddleware>, TestSink.EnableWithTypeName<RouterMiddleware>,
TestSink.EnableWithTypeName<RouterMiddleware>); TestSink.EnableWithTypeName<RouterMiddleware>);
var loggerFactory = new TestLoggerFactory(sink); var loggerFactory = new TestLoggerFactory(sink, enabled: true);
var mockContext = new Mock<HttpContext>(MockBehavior.Strict); var mockContext = new Mock<HttpContext>(MockBehavior.Strict);
mockContext.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory))) mockContext.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
@ -43,20 +43,14 @@ namespace Microsoft.AspNet.Routing
await middleware.Invoke(mockContext.Object); await middleware.Invoke(mockContext.Object);
// Assert // Assert
Assert.Equal(1, sink.Scopes.Count); Assert.Single(sink.Scopes);
var scope = sink.Scopes[0]; var scope = sink.Scopes[0];
Assert.Equal(typeof(RouterMiddleware).FullName, scope.LoggerName); Assert.Equal(typeof(RouterMiddleware).FullName, scope.LoggerName);
Assert.Equal("RouterMiddleware.Invoke", scope.Scope); Assert.Equal("RouterMiddleware.Invoke", scope.Scope);
// There is a record for IsEnabled and one for WriteCore. Assert.Single(sink.Writes);
Assert.Equal(2, sink.Writes.Count);
var enabled = sink.Writes[0]; var write = sink.Writes[0];
Assert.Equal(typeof(RouterMiddleware).FullName, enabled.LoggerName);
Assert.Equal("RouterMiddleware.Invoke", enabled.Scope);
Assert.Null(enabled.State);
var write = sink.Writes[1];
Assert.Equal(typeof(RouterMiddleware).FullName, write.LoggerName); Assert.Equal(typeof(RouterMiddleware).FullName, write.LoggerName);
Assert.Equal("RouterMiddleware.Invoke", write.Scope); Assert.Equal("RouterMiddleware.Invoke", write.Scope);
var values = Assert.IsType<RouterMiddlewareInvokeValues>(write.State); var values = Assert.IsType<RouterMiddlewareInvokeValues>(write.State);
@ -64,6 +58,41 @@ namespace Microsoft.AspNet.Routing
Assert.Equal(false, values.Handled); Assert.Equal(false, values.Handled);
} }
[Fact]
public async void Invoke_DoesNotLogWhenDisabledAndNotHandled()
{
// Arrange
var isHandled = false;
var sink = new TestSink(
TestSink.EnableWithTypeName<RouterMiddleware>,
TestSink.EnableWithTypeName<RouterMiddleware>);
var loggerFactory = new TestLoggerFactory(sink, enabled: false);
var mockContext = new Mock<HttpContext>(MockBehavior.Strict);
mockContext.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
.Returns(loggerFactory);
RequestDelegate next = (c) =>
{
return Task.FromResult<object>(null);
};
var router = new TestRouter(isHandled);
var middleware = new RouterMiddleware(next, router);
// Act
await middleware.Invoke(mockContext.Object);
// Assert
Assert.Single(sink.Scopes);
var scope = sink.Scopes[0];
Assert.Equal(typeof(RouterMiddleware).FullName, scope.LoggerName);
Assert.Equal("RouterMiddleware.Invoke", scope.Scope);
Assert.Empty(sink.Writes);
}
[Fact] [Fact]
public async void Invoke_LogsCorrectValuesWhenHandled() public async void Invoke_LogsCorrectValuesWhenHandled()
{ {
@ -73,7 +102,7 @@ namespace Microsoft.AspNet.Routing
var sink = new TestSink( var sink = new TestSink(
TestSink.EnableWithTypeName<RouterMiddleware>, TestSink.EnableWithTypeName<RouterMiddleware>,
TestSink.EnableWithTypeName<RouterMiddleware>); TestSink.EnableWithTypeName<RouterMiddleware>);
var loggerFactory = new TestLoggerFactory(sink); var loggerFactory = new TestLoggerFactory(sink, enabled: true);
var mockContext = new Mock<HttpContext>(MockBehavior.Strict); var mockContext = new Mock<HttpContext>(MockBehavior.Strict);
mockContext.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory))) mockContext.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
@ -92,20 +121,14 @@ namespace Microsoft.AspNet.Routing
// Assert // Assert
// exists a BeginScope, verify contents // exists a BeginScope, verify contents
Assert.Equal(1, sink.Scopes.Count); Assert.Single(sink.Scopes);
var scope = sink.Scopes[0]; var scope = sink.Scopes[0];
Assert.Equal(typeof(RouterMiddleware).FullName, scope.LoggerName); Assert.Equal(typeof(RouterMiddleware).FullName, scope.LoggerName);
Assert.Equal("RouterMiddleware.Invoke", scope.Scope); Assert.Equal("RouterMiddleware.Invoke", scope.Scope);
// There is a record for IsEnabled and one for WriteCore. Assert.Single(sink.Writes);
Assert.Equal(2, sink.Writes.Count);
var enabled = sink.Writes[0]; var write = sink.Writes[0];
Assert.Equal(typeof(RouterMiddleware).FullName, enabled.LoggerName);
Assert.Equal("RouterMiddleware.Invoke", enabled.Scope);
Assert.Null(enabled.State);
var write = sink.Writes[1];
Assert.Equal(typeof(RouterMiddleware).FullName, write.LoggerName); Assert.Equal(typeof(RouterMiddleware).FullName, write.LoggerName);
Assert.Equal("RouterMiddleware.Invoke", write.Scope); Assert.Equal("RouterMiddleware.Invoke", write.Scope);
Assert.Equal(typeof(RouterMiddlewareInvokeValues), write.State.GetType()); Assert.Equal(typeof(RouterMiddlewareInvokeValues), write.State.GetType());
@ -113,6 +136,42 @@ namespace Microsoft.AspNet.Routing
Assert.Equal("RouterMiddleware.Invoke", values.Name); Assert.Equal("RouterMiddleware.Invoke", values.Name);
Assert.Equal(true, values.Handled); Assert.Equal(true, values.Handled);
} }
[Fact]
public async void Invoke_DoesNotLogWhenDisabledAndHandled()
{
// Arrange
var isHandled = true;
var sink = new TestSink(
TestSink.EnableWithTypeName<RouterMiddleware>,
TestSink.EnableWithTypeName<RouterMiddleware>);
var loggerFactory = new TestLoggerFactory(sink, enabled: false);
var mockContext = new Mock<HttpContext>(MockBehavior.Strict);
mockContext.Setup(m => m.RequestServices.GetService(typeof(ILoggerFactory)))
.Returns(loggerFactory);
RequestDelegate next = (c) =>
{
return Task.FromResult<object>(null);
};
var router = new TestRouter(isHandled);
var middleware = new RouterMiddleware(next, router);
// Act
await middleware.Invoke(mockContext.Object);
// Assert
// exists a BeginScope, verify contents
Assert.Single(sink.Scopes);
var scope = sink.Scopes[0];
Assert.Equal(typeof(RouterMiddleware).FullName, scope.LoggerName);
Assert.Equal("RouterMiddleware.Invoke", scope.Scope);
Assert.Empty(sink.Writes);
}
#endif #endif
private class TestRouter : IRouter private class TestRouter : IRouter

View File

@ -20,38 +20,40 @@ namespace Microsoft.AspNet.Routing.Template
{ {
private static IInlineConstraintResolver _inlineConstraintResolver = GetInlineConstraintResolver(); private static IInlineConstraintResolver _inlineConstraintResolver = GetInlineConstraintResolver();
[Fact] private async Task<Tuple<TestSink, RouteContext>> SetUp(bool enabled, string template, string requestPath)
public async Task RouteAsync_MatchSuccess_LogsCorrectValues()
{ {
// Arrange
var sink = new TestSink( var sink = new TestSink(
TestSink.EnableWithTypeName<TemplateRoute>, TestSink.EnableWithTypeName<TemplateRoute>,
TestSink.EnableWithTypeName<TemplateRoute>); TestSink.EnableWithTypeName<TemplateRoute>);
var loggerFactory = new TestLoggerFactory(sink); var loggerFactory = new TestLoggerFactory(sink, enabled);
var template = "{controller}/{action}";
var route = CreateRoute(template); var route = CreateRoute(template);
var context = CreateRouteContext("/Home/Index", loggerFactory); var context = CreateRouteContext(requestPath, loggerFactory);
// Act // Act
await route.RouteAsync(context); await route.RouteAsync(context);
return Tuple.Create(sink, context);
}
[Fact]
public async Task RouteAsync_MatchSuccess_LogsCorrectValues()
{
// Arrange & Act
var template = "{controller}/{action}";
var result = await SetUp(true, template, "/Home/Index");
var sink = result.Item1;
var context = result.Item2;
// Assert // Assert
Assert.Equal(1, sink.Scopes.Count); Assert.Equal(1, sink.Scopes.Count);
var scope = sink.Scopes[0]; var scope = sink.Scopes[0];
Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName); Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", scope.Scope); Assert.Equal("TemplateRoute.RouteAsync", scope.Scope);
// There is a record for IsEnabled and one for WriteCore. Assert.Equal(1, sink.Writes.Count);
Assert.Equal(2, sink.Writes.Count);
var enabled = sink.Writes[0]; var write = sink.Writes[0];
Assert.Equal(typeof(TemplateRoute).FullName, enabled.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", enabled.Scope);
Assert.Null(enabled.State);
var write = sink.Writes[1];
Assert.Equal(typeof(TemplateRoute).FullName, write.LoggerName); Assert.Equal(typeof(TemplateRoute).FullName, write.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", write.Scope); Assert.Equal("TemplateRoute.RouteAsync", write.Scope);
@ -69,21 +71,12 @@ namespace Microsoft.AspNet.Routing.Template
} }
[Fact] [Fact]
public async Task RouteAsync_MatchFailOnValues_LogsCorrectValues() public async Task RouteAsync_MatchSuccess_DoesNotLogWhenDisabled()
{ {
// Arrange // Arrange & Act
var sink = new TestSink(
TestSink.EnableWithTypeName<TemplateRoute>,
TestSink.EnableWithTypeName<TemplateRoute>);
var loggerFactory = new TestLoggerFactory(sink);
var template = "{controller}/{action}"; var template = "{controller}/{action}";
var result = await SetUp(false, template, "/Home/Index");
var route = CreateRoute(template); var sink = result.Item1;
var context = CreateRouteContext("/Home/Index/Failure", loggerFactory);
// Act
await route.RouteAsync(context);
// Assert // Assert
Assert.Equal(1, sink.Scopes.Count); Assert.Equal(1, sink.Scopes.Count);
@ -91,15 +84,27 @@ namespace Microsoft.AspNet.Routing.Template
Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName); Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", scope.Scope); Assert.Equal("TemplateRoute.RouteAsync", scope.Scope);
// There is a record for IsEnabled and one for WriteCore. Assert.Equal(0, sink.Writes.Count);
Assert.Equal(2, sink.Writes.Count); }
var enabled = sink.Writes[0]; [Fact]
Assert.Equal(typeof(TemplateRoute).FullName, enabled.LoggerName); public async Task RouteAsync_MatchFailOnValues_LogsCorrectValues()
Assert.Equal("TemplateRoute.RouteAsync", enabled.Scope); {
Assert.Null(enabled.State); // Arrange & Act
var template = "{controller}/{action}";
var result = await SetUp(true, template, "/Home/Index/Failure");
var sink = result.Item1;
var context = result.Item2;
var write = sink.Writes[1]; // Assert
Assert.Equal(1, sink.Scopes.Count);
var scope = sink.Scopes[0];
Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", scope.Scope);
Assert.Equal(1, sink.Writes.Count);
var write = sink.Writes[0];
Assert.Equal(typeof(TemplateRoute).FullName, write.LoggerName); Assert.Equal(typeof(TemplateRoute).FullName, write.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", write.Scope); Assert.Equal("TemplateRoute.RouteAsync", write.Scope);
var values = Assert.IsType<TemplateRouteRouteAsyncValues>(write.State); var values = Assert.IsType<TemplateRouteRouteAsyncValues>(write.State);
@ -115,21 +120,12 @@ namespace Microsoft.AspNet.Routing.Template
} }
[Fact] [Fact]
public async Task RouteAsync_MatchFailOnConstraints_LogsCorrectValues() public async Task RouteAsync_MatchFailOnValues_DoesNotLogWhenDisabled()
{ {
// Arrange // Arrange
var sink = new TestSink( var template = "{controller}/{action}";
TestSink.EnableWithTypeName<TemplateRoute>, var result = await SetUp(false, template, "/Home/Index/Failure");
TestSink.EnableWithTypeName<TemplateRoute>); var sink = result.Item1;
var loggerFactory = new TestLoggerFactory(sink);
var template = "{controller}/{action}/{id:int}";
var route = CreateRoute(template);
var context = CreateRouteContext("/Home/Index/Failure", loggerFactory);
// Act
await route.RouteAsync(context);
// Assert // Assert
Assert.Equal(1, sink.Scopes.Count); Assert.Equal(1, sink.Scopes.Count);
@ -137,15 +133,27 @@ namespace Microsoft.AspNet.Routing.Template
Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName); Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", scope.Scope); Assert.Equal("TemplateRoute.RouteAsync", scope.Scope);
// There is a record for IsEnabled and one for WriteCore. Assert.Equal(0, sink.Writes.Count);
Assert.Equal(2, sink.Writes.Count); }
var enabled = sink.Writes[0]; [Fact]
Assert.Equal(typeof(TemplateRoute).FullName, enabled.LoggerName); public async Task RouteAsync_MatchFailOnConstraints_LogsCorrectValues()
Assert.Equal("TemplateRoute.RouteAsync", enabled.Scope); {
Assert.Null(enabled.State); // Arrange & Act
var template = "{controller}/{action}/{id:int}";
var result = await SetUp(true, template, "/Home/Index/Failure");
var sink = result.Item1;
var context = result.Item2;
var write = sink.Writes[1]; // Assert
Assert.Equal(1, sink.Scopes.Count);
var scope = sink.Scopes[0];
Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", scope.Scope);
Assert.Equal(1, sink.Writes.Count);
var write = sink.Writes[0];
Assert.Equal(typeof(TemplateRoute).FullName, write.LoggerName); Assert.Equal(typeof(TemplateRoute).FullName, write.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", write.Scope); Assert.Equal("TemplateRoute.RouteAsync", write.Scope);
var values = Assert.IsType<TemplateRouteRouteAsyncValues>(write.State); var values = Assert.IsType<TemplateRouteRouteAsyncValues>(write.State);
@ -160,6 +168,23 @@ namespace Microsoft.AspNet.Routing.Template
Assert.Equal(context.IsHandled, values.Handled); Assert.Equal(context.IsHandled, values.Handled);
} }
[Fact]
public async Task RouteAsync_MatchFailOnConstraints_DoesNotLogWhenDisabled()
{
// Arrange & Act
var template = "{controller}/{action}/{id:int}";
var result = await SetUp(false, template, "/Home/Index/Failure");
var sink = result.Item1;
// Assert
Assert.Equal(1, sink.Scopes.Count);
var scope = sink.Scopes[0];
Assert.Equal(typeof(TemplateRoute).FullName, scope.LoggerName);
Assert.Equal("TemplateRoute.RouteAsync", scope.Scope);
Assert.Equal(0, sink.Writes.Count);
}
#region Route Matching #region Route Matching
// PathString in HttpAbstractions guarantees a leading slash - so no value in testing other cases. // PathString in HttpAbstractions guarantees a leading slash - so no value in testing other cases.