Integrating routing work into project

Uncommenting old route collection publisher tests
Factoring wrapping handler into async and non-async cases
Adding [IContainerProvider] to datatokens at the time the routedata is matched

--HG--
branch : dev
This commit is contained in:
Louis DeJardin
2010-04-23 11:45:30 -07:00
parent ca222e60f7
commit 4b15c18ce0
3 changed files with 181 additions and 158 deletions

View File

@@ -1,109 +1,114 @@
//using System;
//using System.Linq;
//using System.Threading;
//using System.Web.Mvc;
//using System.Web.Routing;
//using NUnit.Framework;
//using Orchard.Mvc.Routes;
//using Orchard.Tests.Stubs;
using System;
using System.Linq;
using System.Threading;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
using NUnit.Framework;
using Orchard.Environment.Configuration;
using Orchard.Mvc.Routes;
using Orchard.Tests.Stubs;
using Orchard.Tests.Utility;
//namespace Orchard.Tests.Mvc {
// [TestFixture]
// public class RouteCollectionPublisherTests {
// static RouteDescriptor Desc(string name, string url) {
// return new RouteDescriptor {Name = name, Route = new Route(url, new MvcRouteHandler())};
// }
namespace Orchard.Tests.Mvc {
[TestFixture]
public class RouteCollectionPublisherTests {
private IContainer _container;
private RouteCollection _routes;
// //[Test]
// //public void PublisherShouldReplaceRoutes() {
static RouteDescriptor Desc(string name, string url) {
return new RouteDescriptor { Name = name, Route = new Route(url, new MvcRouteHandler()) };
}
// // var routes = new RouteCollection();
// // routes.MapRoute("foo", "{controller}");
[SetUp]
public void Init() {
_routes = new RouteCollection();
// // IRoutePublisher publisher = new RoutePublisher(routes, new StubContainerProvider(null, null));
// // publisher.Publish(new[] {Desc("barname", "bar"), Desc("quuxname", "quux")});
// // Assert.That(routes.Count(), Is.EqualTo(2));
// //}
// //[Test]
// //public void RoutesCanHaveNullOrEmptyNames() {
// // var routes = new RouteCollection();
// // routes.MapRoute("foo", "{controller}");
// // IRoutePublisher publisher = new RoutePublisher(routes, new StubContainerProvider(null, null));
// // publisher.Publish(new[] { Desc(null, "bar"), Desc(string.Empty, "quux") });
// // Assert.That(routes.Count(), Is.EqualTo(2));
// //}
// //[Test]
// //[ExpectedException(typeof(ArgumentException))]
// //public void SameNameTwiceCausesExplosion() {
// // var routes = new RouteCollection();
// // routes.MapRoute("foo", "{controller}");
// // IRoutePublisher publisher = new RoutePublisher(routes, new StubContainerProvider(null, null));
// // publisher.Publish(new[] {Desc("yarg", "bar"), Desc("yarg", "quux")});
// // Assert.That(routes.Count(), Is.EqualTo(2));
// //}
var builder = new ContainerBuilder();
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>();
builder.RegisterType<ShellRoute>().InstancePerDependency();
builder.Register(ctx => _routes);
builder.Register(ctx => new ShellSettings { Name = "Default" });
builder.RegisterAutoMocking();
_container = builder.Build();
}
// [Test]
// public void ExplosionLeavesOriginalRoutesIntact() {
// var routes = new RouteCollection();
// routes.MapRoute("foo", "{controller}");
[Test]
public void PublisherShouldAddRoutesThenReplaceTheOnesWhichWereAdded() {
_routes.MapRoute("foo", "{controller}");
// IRoutePublisher publisher = new RoutePublisher(routes, new StubContainerProvider(null, null));
// try {
// publisher.Publish(new[] { Desc("yarg", "bar"), Desc("yarg", "quux") });
// }
// catch (ArgumentException) {
// Assert.That(routes.Count(), Is.EqualTo(1));
// Assert.That(routes.OfType<Route>().Single().Url, Is.EqualTo("{controller}"));
// }
// }
var publisher = _container.Resolve<IRoutePublisher>();
publisher.Publish(new[] { Desc("barname", "bar"), Desc("quuxname", "quux") });
// [Test]
// public void RoutesArePaintedWithConainerProviderAsTheyAreApplied() {
// var routes = new RouteCollection();
// routes.MapRoute("foo", "{controller}");
Assert.That(_routes.Count(), Is.EqualTo(3));
// var containerProvider = new StubContainerProvider(null, null);
// IRoutePublisher publisher = new RoutePublisher(routes, containerProvider);
// publisher.Publish(new[] { Desc("barname", "bar"), Desc("quuxname", "quux") });
publisher.Publish(new[] { Desc("baazname", "baaz")});
// Assert.That(routes.OfType<Route>().Count(), Is.EqualTo(2));
// Assert.That(routes.OfType<Route>().SelectMany(r => r.DataTokens.Values).Count(), Is.EqualTo(2));
// Assert.That(routes.OfType<Route>().SelectMany(r => r.DataTokens.Values), Has.All.SameAs(containerProvider));
// }
Assert.That(_routes.Count(), Is.EqualTo(2));
}
// [Test]
// public void WriteBlocksWhileReadIsInEffect() {
// var routes = new RouteCollection();
// routes.MapRoute("foo", "{controller}");
[Test]
public void RoutesCanHaveNullOrEmptyNames() {
_routes.MapRoute("foo", "{controller}");
// var containerProvider = new StubContainerProvider(null, null);
// IRoutePublisher publisher = new RoutePublisher(routes, containerProvider);
var publisher = _container.Resolve<IRoutePublisher>();
publisher.Publish(new[] { Desc(null, "bar"), Desc(string.Empty, "quux") });
// var readLock = routes.GetReadLock();
Assert.That(_routes.Count(), Is.EqualTo(3));
}
// string where = "init";
// var action = new Action(() => {
// where = "before";
// publisher.Publish(new[] { Desc("barname", "bar"), Desc("quuxname", "quux") });
// where = "after";
// });
[Test]
[ExpectedException(typeof(ArgumentException))]
public void SameNameTwiceCausesExplosion() {
_routes.MapRoute("foo", "{controller}");
var publisher = _container.Resolve<IRoutePublisher>();
publisher.Publish(new[] { Desc("yarg", "bar"), Desc("yarg", "quux") });
Assert.That(_routes.Count(), Is.EqualTo(2));
}
[Test]
public void ExplosionLeavesOriginalRoutesIntact() {
_routes.MapRoute("foo", "{controller}");
var publisher = _container.Resolve<IRoutePublisher>();
try {
publisher.Publish(new[] { Desc("yarg", "bar"), Desc("yarg", "quux") });
}
catch (ArgumentException) {
Assert.That(_routes.Count(), Is.EqualTo(1));
Assert.That(_routes.OfType<Route>().Single().Url, Is.EqualTo("{controller}"));
}
}
[Test]
public void WriteBlocksWhileReadIsInEffect() {
_routes.MapRoute("foo", "{controller}");
var publisher = _container.Resolve<IRoutePublisher>();
var readLock = _routes.GetReadLock();
string where = "init";
var action = new Action(() => {
where = "before";
publisher.Publish(new[] { Desc("barname", "bar"), Desc("quuxname", "quux") });
where = "after";
});
Assert.That(where, Is.EqualTo("init"));
var async = action.BeginInvoke(null, null);
Thread.Sleep(75);
Assert.That(where, Is.EqualTo("before"));
readLock.Dispose();
Thread.Sleep(75);
Assert.That(where, Is.EqualTo("after"));
action.EndInvoke(async);
}
}
}
// Assert.That(where, Is.EqualTo("init"));
// var async = action.BeginInvoke(null, null);
// Thread.Sleep(75);
// Assert.That(where, Is.EqualTo("before"));
// readLock.Dispose();
// Thread.Sleep(75);
// Assert.That(where, Is.EqualTo("after"));
// action.EndInvoke(async);
// }
// }
//}

View File

@@ -24,6 +24,32 @@ namespace Orchard.Tests.Mvc.Routes {
private ShellSettings _settingsB;
private IContainer _rootContainer;
[SetUp]
public void Init() {
_settingsA = new ShellSettings { Name = "Alpha" };
_settingsB = new ShellSettings { Name = "Beta", };
_routes = new RouteCollection();
var rootBuilder = new ContainerBuilder();
rootBuilder.Register(ctx => _routes);
rootBuilder.RegisterType<ShellRoute>().InstancePerDependency();
rootBuilder.RegisterType<RunningShellTable>().As<IRunningShellTable>().SingleInstance();
_rootContainer = rootBuilder.Build();
_containerA = _rootContainer.BeginLifetimeScope(
builder => {
builder.Register(ctx => _settingsA);
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope();
});
_containerB = _rootContainer.BeginLifetimeScope(
builder => {
builder.Register(ctx => _settingsB);
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope();
});
}
[Test]
public void FactoryMethodWillCreateShellRoutes() {
var settings = new ShellSettings { Name = "Alpha" };
@@ -52,33 +78,9 @@ namespace Orchard.Tests.Mvc.Routes {
Assert.That(route2.Area, Is.EqualTo("Beta"));
}
private void Init() {
_settingsA = new ShellSettings {Name = "Alpha"};
_settingsB = new ShellSettings {Name = "Beta", };
_routes = new RouteCollection();
var rootBuilder = new ContainerBuilder();
rootBuilder.Register(ctx => _routes);
rootBuilder.RegisterType<ShellRoute>().InstancePerDependency();
rootBuilder.RegisterType<RunningShellTable>().As<IRunningShellTable>().SingleInstance();
_rootContainer = rootBuilder.Build();
_containerA = _rootContainer.BeginLifetimeScope(
builder => {
builder.Register(ctx => _settingsA);
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>();
});
_containerB = _rootContainer.BeginLifetimeScope(
builder => {
builder.Register(ctx => _settingsB);
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>();
});
}
[Test]
public void RoutePublisherReplacesOnlyNamedShellsRoutes() {
Init();
var routeA = new Route("foo", new MvcRouteHandler());
var routeB = new Route("bar", new MvcRouteHandler());
@@ -108,17 +110,18 @@ namespace Orchard.Tests.Mvc.Routes {
[Test]
public void MatchingRouteToActiveShellTableWillLimitTheAbilityToMatchRoutes() {
Init();
var routeFoo = new Route("foo", new MvcRouteHandler());
_settingsA.RequestUrlHost = "a.example.com";
_containerA.Resolve<IRoutePublisher>().Publish(
new[] {new RouteDescriptor {Priority = 0, Route = routeFoo}});
_rootContainer.Resolve<IRunningShellTable>().Add(_settingsA);
_settingsB.RequestUrlHost = "b.example.com";
_containerB.Resolve<IRoutePublisher>().Publish(
new[] {new RouteDescriptor {Priority = 0, Route = routeFoo}});
_rootContainer.Resolve<IRunningShellTable>().Add(_settingsB);
var httpContext = new StubHttpContext("~/foo");
var routeData = _routes.GetRouteData(httpContext);
@@ -129,16 +132,16 @@ namespace Orchard.Tests.Mvc.Routes {
Assert.That(routeDataA, Is.Not.Null);
Assert.That(routeDataA.DataTokens.ContainsKey("IContainerProvider"), Is.True);
var routeContainerProviderA = (IContainerProvider)routeDataA.DataTokens["IContainerProvider"];
Assert.That(routeContainerProviderA.ApplicationContainer.Resolve<IRouteProvider>(), Is.SameAs(_containerA.Resolve<IRouteProvider>()));
Assert.That(routeContainerProviderA.ApplicationContainer.Resolve<IRouteProvider>(), Is.Not.SameAs(_containerB.Resolve<IRouteProvider>()));
Assert.That(routeContainerProviderA.ApplicationContainer.Resolve<IRoutePublisher>(), Is.SameAs(_containerA.Resolve<IRoutePublisher>()));
Assert.That(routeContainerProviderA.ApplicationContainer.Resolve<IRoutePublisher>(), Is.Not.SameAs(_containerB.Resolve<IRoutePublisher>()));
var httpContextB = new StubHttpContext("~/foo", "b.example.com");
var routeDataB = _routes.GetRouteData(httpContextB);
Assert.That(routeDataB, Is.Not.Null);
Assert.That(routeDataB.DataTokens.ContainsKey("IContainerProvider"), Is.True);
var routeContainerProviderB = (IContainerProvider)routeDataA.DataTokens["IContainerProvider"];
Assert.That(routeContainerProviderB.ApplicationContainer.Resolve<IRouteProvider>(), Is.SameAs(_containerB.Resolve<IRouteProvider>()));
Assert.That(routeContainerProviderB.ApplicationContainer.Resolve<IRouteProvider>(), Is.Not.SameAs(_containerA.Resolve<IRouteProvider>()));
var routeContainerProviderB = (IContainerProvider)routeDataB.DataTokens["IContainerProvider"];
Assert.That(routeContainerProviderB.ApplicationContainer.Resolve<IRoutePublisher>(), Is.SameAs(_containerB.Resolve<IRoutePublisher>()));
Assert.That(routeContainerProviderB.ApplicationContainer.Resolve<IRoutePublisher>(), Is.Not.SameAs(_containerA.Resolve<IRoutePublisher>()));
}
}

View File

@@ -51,7 +51,9 @@ namespace Orchard.Mvc.Routes {
return null;
// otherwise paint wrap handler and return it
routeData.RouteHandler = new RouteHandler(_container, routeData.RouteHandler);
var containerProvider = new ContainerProvider(_container);
routeData.RouteHandler = new RouteHandler(containerProvider, routeData.RouteHandler);
routeData.DataTokens["IContainerProvider"] = containerProvider;
return routeData;
}
@@ -66,33 +68,49 @@ namespace Orchard.Mvc.Routes {
return virtualPath;
}
class ContainerProvider : IContainerProvider {
public ContainerProvider(IContainer applicationContainer) {
ApplicationContainer = applicationContainer;
}
public void BeginRequestLifetime() {
RequestLifetime = ApplicationContainer.BeginLifetimeScope("httpRequest");
}
public void EndRequestLifetime() {
RequestLifetime.Dispose();
RequestLifetime = null;
}
public IContainer ApplicationContainer { get; set; }
public ILifetimeScope RequestLifetime { get; set; }
}
class RouteHandler : IRouteHandler {
private readonly IContainer _container;
private readonly ContainerProvider _containerProvider;
private readonly IRouteHandler _routeHandler;
public RouteHandler(IContainer container, IRouteHandler routeHandler) {
_container = container;
public RouteHandler(ContainerProvider containerProvider, IRouteHandler routeHandler) {
_containerProvider = containerProvider;
_routeHandler = routeHandler;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
var httpHandler = _routeHandler.GetHttpHandler(requestContext);
return new HttpAsyncHandler(
_container,
requestContext,
(IHttpAsyncHandler)httpHandler);
if (httpHandler is IHttpAsyncHandler) {
return new HttpAsyncHandler(_containerProvider, (IHttpAsyncHandler)httpHandler);
}
return new HttpHandler(_containerProvider, httpHandler);
}
}
class HttpAsyncHandler : IHttpAsyncHandler, IRequiresSessionState, IContainerProvider {
private readonly RequestContext _requestContext;
private readonly IHttpAsyncHandler _httpAsyncHandler;
class HttpHandler : IHttpHandler, IRequiresSessionState {
protected readonly ContainerProvider _containerProvider;
private readonly IHttpHandler _httpHandler;
public HttpAsyncHandler(IContainer applicationContainer, RequestContext requestContext, IHttpAsyncHandler httpAsyncHandler) {
ApplicationContainer = applicationContainer;
_requestContext = requestContext;
_httpAsyncHandler = httpAsyncHandler;
public HttpHandler(ContainerProvider containerProvider, IHttpHandler httpHandler) {
_containerProvider = containerProvider;
_httpHandler = httpHandler;
}
public bool IsReusable {
@@ -100,22 +118,31 @@ namespace Orchard.Mvc.Routes {
}
public void ProcessRequest(HttpContext context) {
BeginRequestLifetime();
_containerProvider.BeginRequestLifetime();
try {
_httpAsyncHandler.ProcessRequest(context);
_httpHandler.ProcessRequest(context);
}
finally {
EndRequestLifetime();
_containerProvider.EndRequestLifetime();
}
}
}
class HttpAsyncHandler : HttpHandler, IHttpAsyncHandler {
private readonly IHttpAsyncHandler _httpAsyncHandler;
public HttpAsyncHandler(ContainerProvider containerProvider, IHttpAsyncHandler httpAsyncHandler)
: base(containerProvider, httpAsyncHandler) {
_httpAsyncHandler = httpAsyncHandler;
}
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) {
BeginRequestLifetime();
_containerProvider.BeginRequestLifetime();
try {
return _httpAsyncHandler.BeginProcessRequest(context, cb, extraData);
}
catch {
EndRequestLifetime();
_containerProvider.EndRequestLifetime();
throw;
}
}
@@ -125,22 +152,10 @@ namespace Orchard.Mvc.Routes {
_httpAsyncHandler.EndProcessRequest(result);
}
finally {
EndRequestLifetime();
_containerProvider.EndRequestLifetime();
}
}
public void BeginRequestLifetime() {
RequestLifetime = ApplicationContainer.BeginLifetimeScope("httpRequest");
_requestContext.RouteData.DataTokens["IContainerProvider"] = this;
}
public void EndRequestLifetime() {
_requestContext.RouteData.DataTokens.Remove("IContainerProvider");
RequestLifetime.Dispose();
}
public IContainer ApplicationContainer { get; set; }
public ILifetimeScope RequestLifetime { get; set; }
}
}
}