mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Fix unit test memory leak
Shutdown ASP.NET AppDomains after running each SpecFlow scenario. --HG-- branch : dev
This commit is contained in:
@@ -14,10 +14,10 @@ using HtmlAgilityPack;
|
|||||||
using log4net.Appender;
|
using log4net.Appender;
|
||||||
using log4net.Core;
|
using log4net.Core;
|
||||||
using log4net.Repository;
|
using log4net.Repository;
|
||||||
|
using NUnit.Framework;
|
||||||
using Orchard.Specs.Hosting;
|
using Orchard.Specs.Hosting;
|
||||||
using Orchard.Specs.Util;
|
using Orchard.Specs.Util;
|
||||||
using TechTalk.SpecFlow;
|
using TechTalk.SpecFlow;
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Orchard.Specs.Bindings {
|
namespace Orchard.Specs.Bindings {
|
||||||
[Binding]
|
[Binding]
|
||||||
@@ -27,6 +27,9 @@ namespace Orchard.Specs.Bindings {
|
|||||||
private HtmlDocument _doc;
|
private HtmlDocument _doc;
|
||||||
private MessageSink _messages;
|
private MessageSink _messages;
|
||||||
|
|
||||||
|
public WebAppHosting() {
|
||||||
|
}
|
||||||
|
|
||||||
public WebHost Host {
|
public WebHost Host {
|
||||||
get { return _webHost; }
|
get { return _webHost; }
|
||||||
}
|
}
|
||||||
@@ -36,6 +39,14 @@ namespace Orchard.Specs.Bindings {
|
|||||||
set { _details = value; }
|
set { _details = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AfterScenario]
|
||||||
|
public void AfterScenario() {
|
||||||
|
if (_webHost != null) {
|
||||||
|
_webHost.Dispose();
|
||||||
|
_webHost = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Given(@"I have a clean site")]
|
[Given(@"I have a clean site")]
|
||||||
public void GivenIHaveACleanSite() {
|
public void GivenIHaveACleanSite() {
|
||||||
GivenIHaveACleanSiteBasedOn("Orchard.Web");
|
GivenIHaveACleanSiteBasedOn("Orchard.Web");
|
||||||
|
@@ -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) {
|
public void CopyExtension(string extensionFolder, string extensionName) {
|
||||||
var sourceModule = _orchardWebPath.Combine(extensionFolder).Combine(extensionName);
|
var sourceModule = _orchardWebPath.Combine(extensionFolder).Combine(extensionName);
|
||||||
var targetModule = _tempSite.Combine(extensionFolder).Combine(extensionName);
|
var targetModule = _tempSite.Combine(extensionFolder).Combine(extensionName);
|
||||||
@@ -73,6 +80,5 @@ namespace Orchard.Specs.Hosting {
|
|||||||
fieldInfo.SetValue(to, value);
|
fieldInfo.SetValue(to, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Web.Hosting;
|
||||||
|
|
||||||
namespace Orchard.Specs.Hosting {
|
namespace Orchard.Specs.Hosting {
|
||||||
public class WebHostAgent : MarshalByRefObject
|
public class WebHostAgent : MarshalByRefObject
|
||||||
@@ -8,5 +9,9 @@ namespace Orchard.Specs.Hosting {
|
|||||||
shuttle.Delegate();
|
shuttle.Delegate();
|
||||||
return shuttle;
|
return shuttle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Shutdown() {
|
||||||
|
HostingEnvironment.InitiateShutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -284,9 +284,6 @@
|
|||||||
<Name>Orchard</Name>
|
<Name>Orchard</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<WCFMetadata Include="Service References\" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Hosting\Simple.Web\Content\Static.txt">
|
<Content Include="Hosting\Simple.Web\Content\Static.txt">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
11
src/Tools/Orchard/ApplicationObject.cs
Normal file
11
src/Tools/Orchard/ApplicationObject.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
@@ -18,7 +18,7 @@ namespace Orchard.Host {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Stop(bool immediate) {
|
public void Stop(bool immediate) {
|
||||||
//TODO
|
HostingEnvironment.UnregisterObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int RunCommand(TextReader input, TextWriter output, Logger logger, OrchardParameters args) {
|
public int RunCommand(TextReader input, TextWriter output, Logger logger, OrchardParameters args) {
|
||||||
|
@@ -71,6 +71,7 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="ApplicationObject.cs" />
|
||||||
<Compile Include="Logger.cs" />
|
<Compile Include="Logger.cs" />
|
||||||
<Compile Include="OrchardHost.cs" />
|
<Compile Include="OrchardHost.cs" />
|
||||||
<Compile Include="Parameters\ICommandParametersParser.cs" />
|
<Compile Include="Parameters\ICommandParametersParser.cs" />
|
||||||
@@ -104,7 +105,9 @@
|
|||||||
</BootstrapperPackage>
|
</BootstrapperPackage>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.config" />
|
<None Include="app.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
@@ -7,6 +7,7 @@ using System.Web;
|
|||||||
using System.Web.Hosting;
|
using System.Web.Hosting;
|
||||||
using Orchard.Host;
|
using Orchard.Host;
|
||||||
using Orchard.Parameters;
|
using Orchard.Parameters;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Orchard {
|
namespace Orchard {
|
||||||
class OrchardHost {
|
class OrchardHost {
|
||||||
@@ -77,13 +78,23 @@ namespace Orchard {
|
|||||||
var orchardDirectory = GetOrchardDirectory(_arguments.WorkingDirectory);
|
var orchardDirectory = GetOrchardDirectory(_arguments.WorkingDirectory);
|
||||||
LogInfo("Orchard root directory: \"{0}\"", orchardDirectory.FullName);
|
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...");
|
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...");
|
LogInfo("Executing command in ASP.NET AppDomain...");
|
||||||
var result = Execute(host);
|
var result = Execute(host);
|
||||||
LogInfo("Return code for command: {0}", result);
|
LogInfo("Return code for command: {0}", result);
|
||||||
|
|
||||||
|
LogInfo("Shutting down ASP.NET AppDomain...");
|
||||||
|
appManager.ShutdownApplication(appObject.ApplicationId);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,14 +193,13 @@ namespace Orchard {
|
|||||||
string.Format("Directory \"{0}\" doesn't seem to contain an Orchard installation", new DirectoryInfo(directory).FullName));
|
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
|
// this creates worker app domain in a way that host doesn't need to be in GAC or bin
|
||||||
// using BuildManagerHost via private reflection
|
// using BuildManagerHost via private reflection
|
||||||
string uniqueAppString = string.Concat(virtualPath, physicalPath).ToLowerInvariant();
|
string uniqueAppString = string.Concat(virtualPath, physicalPath).ToLowerInvariant();
|
||||||
string appId = (uniqueAppString.GetHashCode()).ToString("x", CultureInfo.InvariantCulture);
|
string appId = (uniqueAppString.GetHashCode()).ToString("x", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
// create BuildManagerHost in the worker app domain
|
// create BuildManagerHost in the worker app domain
|
||||||
var appManager = ApplicationManager.GetApplicationManager();
|
|
||||||
var buildManagerHostType = typeof(HttpRuntime).Assembly.GetType("System.Web.Compilation.BuildManagerHost");
|
var buildManagerHostType = typeof(HttpRuntime).Assembly.GetType("System.Web.Compilation.BuildManagerHost");
|
||||||
var buildManagerHost = appManager.CreateObject(appId, buildManagerHostType, virtualPath, physicalPath, false);
|
var buildManagerHost = appManager.CreateObject(appId, buildManagerHostType, virtualPath, physicalPath, false);
|
||||||
|
|
||||||
@@ -202,7 +212,9 @@ namespace Orchard {
|
|||||||
new object[] { hostType.Assembly.FullName, hostType.Assembly.Location });
|
new object[] { hostType.Assembly.FullName, hostType.Assembly.Location });
|
||||||
|
|
||||||
// create Host in the worker app domain
|
// 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) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user