Fix unit test memory leak

Shutdown ASP.NET AppDomains after running each SpecFlow scenario.

--HG--
branch : dev
This commit is contained in:
Renaud Paquay
2010-05-22 17:50:18 -07:00
parent ef34e58ed5
commit 01c7e29db2
8 changed files with 57 additions and 12 deletions

View File

@@ -14,10 +14,10 @@ using HtmlAgilityPack;
using log4net.Appender;
using log4net.Core;
using log4net.Repository;
using NUnit.Framework;
using Orchard.Specs.Hosting;
using Orchard.Specs.Util;
using TechTalk.SpecFlow;
using NUnit.Framework;
namespace Orchard.Specs.Bindings {
[Binding]
@@ -27,6 +27,9 @@ namespace Orchard.Specs.Bindings {
private HtmlDocument _doc;
private MessageSink _messages;
public WebAppHosting() {
}
public WebHost Host {
get { return _webHost; }
}
@@ -36,6 +39,14 @@ namespace Orchard.Specs.Bindings {
set { _details = value; }
}
[AfterScenario]
public void AfterScenario() {
if (_webHost != null) {
_webHost.Dispose();
_webHost = null;
}
}
[Given(@"I have a clean site")]
public void GivenIHaveACleanSite() {
GivenIHaveACleanSiteBasedOn("Orchard.Web");

View File

@@ -44,6 +44,13 @@ namespace Orchard.Specs.Hosting {
}
public void Dispose() {
if (_webHostAgent != null) {
_webHostAgent.Shutdown();
_webHostAgent = null;
}
}
public void CopyExtension(string extensionFolder, string extensionName) {
var sourceModule = _orchardWebPath.Combine(extensionFolder).Combine(extensionName);
var targetModule = _tempSite.Combine(extensionFolder).Combine(extensionName);
@@ -73,6 +80,5 @@ namespace Orchard.Specs.Hosting {
fieldInfo.SetValue(to, value);
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Web.Hosting;
namespace Orchard.Specs.Hosting {
public class WebHostAgent : MarshalByRefObject
@@ -8,5 +9,9 @@ namespace Orchard.Specs.Hosting {
shuttle.Delegate();
return shuttle;
}
public void Shutdown() {
HostingEnvironment.InitiateShutdown();
}
}
}
}

View File

@@ -284,9 +284,6 @@
<Name>Orchard</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<ItemGroup>
<Content Include="Hosting\Simple.Web\Content\Static.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Orchard {
public class ApplicationObject {
public string ApplicationId { get; set; }
public object ObjectInstance { get; set; }
}
}

View File

@@ -18,7 +18,7 @@ namespace Orchard.Host {
}
public void Stop(bool immediate) {
//TODO
HostingEnvironment.UnregisterObject(this);
}
public int RunCommand(TextReader input, TextWriter output, Logger logger, OrchardParameters args) {

View File

@@ -71,6 +71,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ApplicationObject.cs" />
<Compile Include="Logger.cs" />
<Compile Include="OrchardHost.cs" />
<Compile Include="Parameters\ICommandParametersParser.cs" />
@@ -104,7 +105,9 @@
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="app.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -7,6 +7,7 @@ using System.Web;
using System.Web.Hosting;
using Orchard.Host;
using Orchard.Parameters;
using System.Threading;
namespace Orchard {
class OrchardHost {
@@ -77,13 +78,23 @@ namespace Orchard {
var orchardDirectory = GetOrchardDirectory(_arguments.WorkingDirectory);
LogInfo("Orchard root directory: \"{0}\"", orchardDirectory.FullName);
return CreateHostAndExecute(orchardDirectory);
}
private int CreateHostAndExecute(DirectoryInfo orchardDirectory) {
var appManager = ApplicationManager.GetApplicationManager();
LogInfo("Creating ASP.NET AppDomain for command agent...");
var host = (CommandHost)CreateWorkerAppDomainWithHost(_arguments.VirtualPath, orchardDirectory.FullName, typeof(CommandHost));
var appObject = CreateWorkerAppDomainWithHost(appManager, _arguments.VirtualPath, orchardDirectory.FullName, typeof(CommandHost));
var host = (CommandHost)appObject.ObjectInstance;
LogInfo("Executing command in ASP.NET AppDomain...");
var result = Execute(host);
LogInfo("Return code for command: {0}", result);
LogInfo("Shutting down ASP.NET AppDomain...");
appManager.ShutdownApplication(appObject.ApplicationId);
return result;
}
@@ -182,14 +193,13 @@ namespace Orchard {
string.Format("Directory \"{0}\" doesn't seem to contain an Orchard installation", new DirectoryInfo(directory).FullName));
}
private static object CreateWorkerAppDomainWithHost(string virtualPath, string physicalPath, Type hostType) {
private static ApplicationObject CreateWorkerAppDomainWithHost(ApplicationManager appManager, string virtualPath, string physicalPath, Type hostType) {
// this creates worker app domain in a way that host doesn't need to be in GAC or bin
// using BuildManagerHost via private reflection
string uniqueAppString = string.Concat(virtualPath, physicalPath).ToLowerInvariant();
string appId = (uniqueAppString.GetHashCode()).ToString("x", CultureInfo.InvariantCulture);
// create BuildManagerHost in the worker app domain
var appManager = ApplicationManager.GetApplicationManager();
var buildManagerHostType = typeof(HttpRuntime).Assembly.GetType("System.Web.Compilation.BuildManagerHost");
var buildManagerHost = appManager.CreateObject(appId, buildManagerHostType, virtualPath, physicalPath, false);
@@ -202,7 +212,9 @@ namespace Orchard {
new object[] { hostType.Assembly.FullName, hostType.Assembly.Location });
// create Host in the worker app domain
return appManager.CreateObject(appId, hostType, virtualPath, physicalPath, false);
return new ApplicationObject {
ApplicationId = appId,
ObjectInstance = appManager.CreateObject(appId, hostType, virtualPath, physicalPath, false) };
}
}
}