Permalink
Browse files

Make the tests rock solid.

- Stop app pool before cleanup of a site so all locked files are released.
- Added helper class or polling waits.
- Make tests clean up after themselves.
  • Loading branch information...
1 parent 5a38b35 commit be81cccc588cc2ef84fcaf6951e90717ddf88b61 @davidfowl davidfowl committed Jan 21, 2012
View
307 Kudu.FunctionalTests/GitDeploymentTests.cs
@@ -3,7 +3,6 @@
using System.Net;
using System.Net.Http;
using Kudu.Core.Deployment;
-using Kudu.Core.SourceControl.Git;
using Kudu.FunctionalTests.Infrastructure;
using Xunit;
@@ -18,20 +17,22 @@ public void PushSimpleRepoShouldDeploy()
string repositoryName = "Bakery2";
string appName = "PushSimpleRepoShouldDeploy";
string verificationText = "Welcome to Fourth Coffee!";
- string originRepo = Git.CreateLocalRepository(repositoryName);
- ApplicationManager.Run(appName, appManager =>
+ using (Git.CreateLocalRepository(repositoryName))
{
- // Act
- appManager.GitDeploy(repositoryName);
- string response = GetResponseBody(appManager.SiteUrl);
- var results = appManager.DeploymentManager.GetResults().ToList();
-
- // Assert
- Assert.Equal(1, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
- Assert.True(response.Contains(verificationText));
- });
+ ApplicationManager.Run(appName, appManager =>
+ {
+ // Act
+ appManager.GitDeploy(repositoryName);
+ string response = GetResponseBody(appManager.SiteUrl);
+ var results = appManager.DeploymentManager.GetResults().ToList();
+
+ // Assert
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ Assert.True(response.Contains(verificationText));
+ });
+ }
}
[Fact]
@@ -41,20 +42,21 @@ public void PushRepoWithMultipleProjectsShouldDeploy()
string repositoryName = "Mvc3Application";
string appName = "PushRepoWithMultipleProjectsShouldDeploy";
string verificationText = "Welcome to ASP.NET MVC! - Change1";
- string originRepo = Git.CreateLocalRepository(repositoryName);
-
- ApplicationManager.Run(appName, appManager =>
+ using (Git.CreateLocalRepository(repositoryName))
{
- // Act
- appManager.GitDeploy(repositoryName);
- string response = GetResponseBody(appManager.SiteUrl);
- var results = appManager.DeploymentManager.GetResults().ToList();
-
- // Assert
- Assert.Equal(1, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
- Assert.True(response.Contains(verificationText));
- });
+ ApplicationManager.Run(appName, appManager =>
+ {
+ // Act
+ appManager.GitDeploy(repositoryName);
+ string response = GetResponseBody(appManager.SiteUrl);
+ var results = appManager.DeploymentManager.GetResults().ToList();
+
+ // Assert
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ Assert.True(response.Contains(verificationText));
+ });
+ }
}
[Fact(Skip = "Issue #11")]
@@ -64,20 +66,22 @@ public void PushRepoWithProjectAndNoSolutionShouldDeploy()
string repositoryName = "Mvc3Application_NoSolution";
string appName = "PushRepoWithProjectAndNoSolutionShouldDeploy";
string verificationText = "Kudu Deployment Testing: Mvc3Application_NoSolution";
- string originRepo = Git.CreateLocalRepository(repositoryName);
- ApplicationManager.Run(appName, appManager =>
+ using (Git.CreateLocalRepository(repositoryName))
{
- // Act
- appManager.GitDeploy(repositoryName);
- string response = GetResponseBody(appManager.SiteUrl);
- var results = appManager.DeploymentManager.GetResults().ToList();
-
- // Assert
- Assert.Equal(1, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
- Assert.True(response.Contains(verificationText));
- });
+ ApplicationManager.Run(appName, appManager =>
+ {
+ // Act
+ appManager.GitDeploy(repositoryName);
+ string response = GetResponseBody(appManager.SiteUrl);
+ var results = appManager.DeploymentManager.GetResults().ToList();
+
+ // Assert
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ Assert.True(response.Contains(verificationText));
+ });
+ }
}
[Fact]
@@ -87,42 +91,46 @@ public void PushAppChangesShouldTriggerBuild()
string repositoryName = "Mvc3Application";
string appName = "PushAppChangesShouldTriggerBuild";
string verificationText = "Welcome to ASP.NET MVC!";
- string originRepo = Git.CreateLocalRepository(repositoryName);
- ApplicationManager.Run(appName, appManager =>
+ using (Git.CreateLocalRepository(repositoryName))
{
- // Act
- appManager.GitDeploy(repositoryName);
- Git.Revert(repositoryName);
- appManager.GitDeploy(repositoryName);
- string response = GetResponseBody(appManager.SiteUrl);
- var results = appManager.DeploymentManager.GetResults().ToList();
-
- // Assert
- Assert.Equal(2, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
- Assert.True(response.Contains(verificationText));
- });
+ ApplicationManager.Run(appName, appManager =>
+ {
+ // Act
+ appManager.GitDeploy(repositoryName);
+ Git.Revert(repositoryName);
+ appManager.GitDeploy(repositoryName);
+ string response = GetResponseBody(appManager.SiteUrl);
+ var results = appManager.DeploymentManager.GetResults().ToList();
+
+ // Assert
+ Assert.Equal(2, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ Assert.True(response.Contains(verificationText));
+ });
+ }
}
[Fact]
public void NodeExpressApplication()
{
string repositoryName = "Express-Template";
string cloneUrl = "https://github.com/davidebbo/Express-Template.git";
- string originRepo = Git.Clone(repositoryName, cloneUrl);
- ApplicationManager.Run(repositoryName, appManager =>
+ using (Git.Clone(repositoryName, cloneUrl))
{
- // Act
- appManager.GitDeploy(repositoryName);
+ ApplicationManager.Run(repositoryName, appManager =>
+ {
+ // Act
+ appManager.GitDeploy(repositoryName);
- var results = appManager.DeploymentManager.GetResults().ToList();
+ var results = appManager.DeploymentManager.GetResults().ToList();
- // Assert
- Assert.Equal(1, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
- });
+ // Assert
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ });
+ }
}
[Fact]
@@ -131,27 +139,29 @@ public void DeletesToRepositoryArePropagatedForWaps()
string repositoryName = "Mvc3Application";
string appName = "DeletesToRepositoryArePropagatedForWaps";
string verificationText = "Welcome to ASP.NET MVC!";
- string originRepo = Git.CreateLocalRepository(repositoryName);
- ApplicationManager.Run(appName, appManager =>
+ using (var repo = Git.CreateLocalRepository(repositoryName))
{
- string deletePath = Path.Combine(originRepo, @"Mvc3Application\Scripts\jquery-1.5.1.js");
- string projectPath = Path.Combine(originRepo, @"Mvc3Application\Mvc3Application.csproj");
-
- // Act
- appManager.GitDeploy(repositoryName);
- File.Delete(deletePath);
- File.WriteAllText(projectPath, File.ReadAllText(projectPath).Replace(@"<Content Include=""Scripts\jquery-1.5.1.js"" />", ""));
- Git.Commit(repositoryName, "Deleted all scripts");
- appManager.GitDeploy(repositoryName);
- string response = GetResponseBody(appManager.SiteUrl);
- var results = appManager.DeploymentManager.GetResults().ToList();
-
- // Assert
- Assert.Equal(2, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
- Assert.True(response.Contains(verificationText));
- });
+ ApplicationManager.Run(appName, appManager =>
+ {
+ string deletePath = Path.Combine(repo.PhysicalPath, @"Mvc3Application\Scripts\jquery-1.5.1.js");
+ string projectPath = Path.Combine(repo.PhysicalPath, @"Mvc3Application\Mvc3Application.csproj");
+
+ // Act
+ appManager.GitDeploy(repositoryName);
+ File.Delete(deletePath);
+ File.WriteAllText(projectPath, File.ReadAllText(projectPath).Replace(@"<Content Include=""Scripts\jquery-1.5.1.js"" />", ""));
+ Git.Commit(repositoryName, "Deleted all scripts");
+ appManager.GitDeploy(repositoryName);
+ string response = GetResponseBody(appManager.SiteUrl);
+ var results = appManager.DeploymentManager.GetResults().ToList();
+
+ // Assert
+ Assert.Equal(2, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ Assert.True(response.Contains(verificationText));
+ });
+ }
}
[Fact]
@@ -160,91 +170,96 @@ public void DeletesToRepositoryArePropagatedForNonWaps()
string repositoryName = "Bakery2";
string appName = "DeletesToRepositoryArePropagatedForNonWaps";
string verificationText = "Welcome to Fourth Coffee!";
- string originRepo = Git.CreateLocalRepository(repositoryName);
-
- ApplicationManager.Run(appName, appManager =>
+ using (var repo = Git.CreateLocalRepository(repositoryName))
{
- string deletePath = Path.Combine(originRepo, @"Styles");
-
- // Act
- appManager.GitDeploy(repositoryName);
- Directory.Delete(deletePath, recursive: true);
- Git.Commit(repositoryName, "Deleted all styles");
- appManager.GitDeploy(repositoryName);
- string response = GetResponseBody(appManager.SiteUrl);
- var results = appManager.DeploymentManager.GetResults().ToList();
-
- // Assert
- Assert.Equal(2, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
- Assert.True(response.Contains(verificationText));
- });
+ ApplicationManager.Run(appName, appManager =>
+ {
+ string deletePath = Path.Combine(repo.PhysicalPath, @"Styles");
+
+ // Act
+ appManager.GitDeploy(repositoryName);
+ Directory.Delete(deletePath, recursive: true);
+ Git.Commit(repositoryName, "Deleted all styles");
+ appManager.GitDeploy(repositoryName);
+ string response = GetResponseBody(appManager.SiteUrl);
+ var results = appManager.DeploymentManager.GetResults().ToList();
+
+ // Assert
+ Assert.Equal(2, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ Assert.True(response.Contains(verificationText));
+ });
+ }
}
[Fact]
public void GoingBackInTimeDeploysOldFiles()
{
string repositoryName = "Bakery2";
string appName = "GoingBackInTimeDeploysOldFiles";
- string originRepo = Git.CreateLocalRepository(repositoryName);
- var repository = new GitExeRepository(originRepo);
- string originalCommitId = repository.CurrentId;
-
- ApplicationManager.Run(appName, appManager =>
+ using (var repo = Git.CreateLocalRepository(repositoryName))
{
- // Deploy the app
- appManager.GitDeploy(repositoryName);
-
- string response = GetResponseBody(appManager.SiteUrl);
- var results = appManager.DeploymentManager.GetResults().ToList();
- Assert.Equal(1, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
-
- // Add a file
- File.WriteAllText(Path.Combine(originRepo, "hello.txt"), "Wow");
- Git.Commit(repositoryName, "Added hello.txt");
- string helloUrl = appManager.SiteUrl + "/hello.txt";
+ string originalCommitId = repo.CurrentId;
- // Deploy those changes
- appManager.GitDeploy(repositoryName);
-
- response = GetResponseBody(helloUrl);
- results = appManager.DeploymentManager.GetResults().ToList();
- Assert.Equal(2, results.Count);
- Assert.Equal(DeployStatus.Success, results[1].Status);
- Assert.Equal("Wow", response);
-
- appManager.DeploymentManager.WaitForDeployment(() =>
+ ApplicationManager.Run(appName, appManager =>
{
- // Go back to the first deployment
- appManager.DeploymentManager.Deploy(originalCommitId);
+ // Deploy the app
+ appManager.GitDeploy(repositoryName);
+
+ string response = GetResponseBody(appManager.SiteUrl);
+ var results = appManager.DeploymentManager.GetResults().ToList();
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+
+ // Add a file
+ File.WriteAllText(Path.Combine(repo.PhysicalPath, "hello.txt"), "Wow");
+ Git.Commit(repositoryName, "Added hello.txt");
+ string helloUrl = appManager.SiteUrl + "/hello.txt";
+
+ // Deploy those changes
+ appManager.GitDeploy(repositoryName);
+
+ response = GetResponseBody(helloUrl);
+ results = appManager.DeploymentManager.GetResults().ToList();
+ Assert.Equal(2, results.Count);
+ Assert.Equal(DeployStatus.Success, results[1].Status);
+ Assert.Equal("Wow", response);
+
+ appManager.DeploymentManager.WaitForDeployment(() =>
+ {
+ // Go back to the first deployment
+ appManager.DeploymentManager.Deploy(originalCommitId);
+ });
+
+ results = appManager.DeploymentManager.GetResults().ToList();
+
+ Assert.Equal(HttpStatusCode.NotFound, GetResponse(helloUrl).StatusCode);
+ Assert.Equal(2, results.Count);
});
-
- results = appManager.DeploymentManager.GetResults().ToList();
-
- Assert.Equal(HttpStatusCode.NotFound, GetResponse(helloUrl).StatusCode);
- Assert.Equal(2, results.Count);
- });
+ }
}
[Fact]
public void HiddenFilesAndFoldersAreDeployed()
{
string repositoryName = "HiddenFoldersAndFiles";
string appName = "HiddenFilesAndFoldersAreDeployed";
- string originRepo = Git.Clone(repositoryName, "https://github.com/KuduApps/HiddenFoldersAndFiles.git");
-
- var appManager = ApplicationManager.CreateApplication(appName);
-
- // Act
- appManager.GitDeploy(repositoryName);
- string response = GetResponseBody(appManager.SiteUrl);
- var results = appManager.DeploymentManager.GetResults().ToList();
-
- // Assert
- Assert.Equal(1, results.Count);
- Assert.Equal(DeployStatus.Success, results[0].Status);
- Assert.True(response.Contains("Hello World"));
+ string cloneUrl = "https://github.com/KuduApps/HiddenFoldersAndFiles.git";
+ using (Git.Clone(repositoryName, cloneUrl))
+ {
+ ApplicationManager.Run(appName, appManager =>
+ {
+ // Act
+ appManager.GitDeploy(repositoryName);
+ string response = GetResponseBody(appManager.SiteUrl);
+ var results = appManager.DeploymentManager.GetResults().ToList();
+
+ // Assert
+ Assert.Equal(1, results.Count);
+ Assert.Equal(DeployStatus.Success, results[0].Status);
+ Assert.True(response.Contains("Hello World"));
+ });
+ }
}
private string GetResponseBody(string url)
View
46 Kudu.FunctionalTests/Infrastructure/Git.cs
@@ -2,6 +2,7 @@
using System.Diagnostics;
using System.IO;
using Kudu.Core.Infrastructure;
+using Kudu.Core.SourceControl.Git;
using Kudu.Web.Infrastructure;
using SystemEnvironment = System.Environment;
@@ -51,27 +52,27 @@ public static void Add(string repositoryName, string path)
gitExe.Execute("add \"{0}\"", path);
}
- public static string Clone(string repositoryName, string source)
+ public static TestRepository Clone(string repositoryName, string source)
{
// Make sure the directory is empty
- string repositoryPath = Path.Combine(PathHelper.LocalRepositoriesDir, repositoryName);
+ string repositoryPath = GetRepositoryPath(repositoryName);
FileSystemHelpers.DeleteDirectorySafe(repositoryPath);
Executable gitExe = GetGitExe(repositoryName);
gitExe.Execute("clone \"{0}\" .", source);
- return Path.Combine(PathHelper.LocalRepositoriesDir, repositoryName);
+ return new TestRepository(repositoryName);
}
- public static string CreateLocalRepository(string repositoryName)
+ public static TestRepository CreateLocalRepository(string repositoryName)
{
// Get the path to the repository
string zippedPath = Path.Combine(PathHelper.ZippedRepositoriesDir, repositoryName + ".zip");
// Unzip it
Utils.Unzip(zippedPath, PathHelper.LocalRepositoriesDir);
- return GetRepositoryPath(repositoryName);
+ return new TestRepository(repositoryName);
}
public static string GetRepositoryPath(string repositoryName)
@@ -94,12 +95,45 @@ private static string ResolveGitPath()
private static Executable GetGitExe(string repositoryName)
{
- string repositoryPath = Path.Combine(PathHelper.LocalRepositoriesDir, repositoryName);
+ string repositoryPath = GetRepositoryPath(repositoryName);
FileSystemHelpers.EnsureDirectory(repositoryPath);
return new Executable(ResolveGitPath(), repositoryPath);
}
+ public class TestRepository : IDisposable
+ {
+ private readonly string _physicalPath;
+ private readonly GitExeRepository _repository;
+
+ public TestRepository(string repositoryName)
+ {
+ _physicalPath = GetRepositoryPath(repositoryName);
+ _repository = new GitExeRepository(_physicalPath);
+ }
+
+
+ public string CurrentId
+ {
+ get
+ {
+ return _repository.CurrentId;
+ }
+ }
+
+ public string PhysicalPath
+ {
+ get
+ {
+ return _physicalPath;
+ }
+ }
+
+ public void Dispose()
+ {
+ FileSystemHelpers.DeleteDirectorySafe(PhysicalPath);
+ }
+ }
}
}
View
45 Kudu.SiteManagement/IISExtensions.cs
@@ -0,0 +1,45 @@
+using IIS = Microsoft.Web.Administration;
+
+namespace Kudu.SiteManagement
+{
+ public static class IISExtensions
+ {
+ public static void StartAndWait(this IIS.Site site)
+ {
+ var wait = new PollingWait(() => site.Start(), () => site.State == IIS.ObjectState.Started);
+
+ wait.Invoke();
+ }
+
+ public static void StopAndWait(this IIS.Site site)
+ {
+ var wait = new PollingWait(() => site.Stop(), () => site.State == IIS.ObjectState.Stopped);
+
+ wait.Invoke();
+ }
+
+ public static void StartAndWait(this IIS.ApplicationPool appPool)
+ {
+ var wait = new PollingWait(() => appPool.Start(), () => appPool.State == IIS.ObjectState.Started);
+
+ wait.Invoke();
+ }
+
+ public static void StopAndWait(this IIS.ApplicationPool appPool)
+ {
+ var wait = new PollingWait(() => appPool.Stop(), () => appPool.State == IIS.ObjectState.Stopped);
+
+ wait.Invoke();
+ }
+
+ public static void WaitForState(this IIS.ApplicationPool appPool, IIS.ObjectState state)
+ {
+ new PollingWait(() => { }, () => appPool.State == state).Invoke();
+ }
+
+ public static void WaitForState(this IIS.Site site, IIS.ObjectState state)
+ {
+ new PollingWait(() => { }, () => site.State == state).Invoke();
+ }
+ }
+}
View
2 Kudu.SiteManagement/Kudu.SiteManagement.csproj
@@ -58,8 +58,10 @@
<Link>FileSystemHelpers.cs</Link>
</Compile>
<Compile Include="DefaultPathResolver.cs" />
+ <Compile Include="IISExtensions.cs" />
<Compile Include="IPathResolver.cs" />
<Compile Include="ISiteManager.cs" />
+ <Compile Include="PollingWait.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Site.cs" />
<Compile Include="SiteManager.cs" />
View
42 Kudu.SiteManagement/PollingWait.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Threading;
+
+namespace Kudu.SiteManagement
+{
+ internal class PollingWait
+ {
+ private readonly Action _action;
+ private readonly Func<bool> _isComplete;
+
+ public PollingWait(Action action, Func<bool> isComplete)
+ {
+ _action = action;
+ _isComplete = isComplete;
+ }
+
+ public bool IsComplete
+ {
+ get
+ {
+ try
+ {
+ return _isComplete();
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+ public void Invoke()
+ {
+ _action();
+
+ while (!IsComplete)
+ {
+ Thread.Sleep(500);
+ }
+ }
+ }
+}
View
27 Kudu.SiteManagement/SiteManager.cs
@@ -1,9 +1,9 @@
using System;
using System.IO;
+using System.Net.NetworkInformation;
using System.Threading;
using Kudu.Core.Infrastructure;
using IIS = Microsoft.Web.Administration;
-using System.Net.NetworkInformation;
namespace Kudu.SiteManagement
{
@@ -75,13 +75,11 @@ public bool TryCreateDeveloperSite(string applicationName, out string siteUrl)
// Ensure the directory is created
FileSystemHelpers.EnsureDirectory(webRoot);
-
// Map a path called app to the site root under the service site
MapServiceSitePath(iis, applicationName, Constants.MappedDevSite, siteRoot);
iis.CommitChanges();
- Thread.Sleep(1000);
siteUrl = String.Format("http://localhost:{0}/", sitePort);
return true;
@@ -95,20 +93,32 @@ public void DeleteSite(string applicationName)
{
var iis = new IIS.ServerManager();
+ var kuduPool = EnsureKuduAppPool(iis);
+
DeleteSite(iis, GetLiveSite(applicationName));
DeleteSite(iis, GetDevSite(applicationName));
// Don't delete the physical files for the service site
DeleteSite(iis, GetServiceSite(applicationName), deletePhysicalFiles: false);
+ iis.CommitChanges();
+
string appPath = _pathResolver.GetApplicationPath(applicationName);
var sitePath = _pathResolver.GetLiveSitePath(applicationName);
var devPath = _pathResolver.GetDeveloperApplicationPath(applicationName);
- DeleteSafe(sitePath);
- DeleteSafe(devPath);
- DeleteSafe(appPath);
+ try
+ {
+ kuduPool.StopAndWait();
+
+ DeleteSafe(sitePath);
+ DeleteSafe(devPath);
+ DeleteSafe(appPath);
+ }
+ finally
+ {
+ kuduPool.StartAndWait();
+ }
- iis.CommitChanges();
}
public void SetDeveloperSiteWebRoot(string applicationName, string siteRoot)
@@ -158,6 +168,7 @@ private static IIS.ApplicationPool EnsureKuduAppPool(IIS.ServerManager iis)
kuduAppPool.ManagedPipelineMode = IIS.ManagedPipelineMode.Integrated;
kuduAppPool.ManagedRuntimeVersion = "v4.0";
kuduAppPool.AutoStart = true;
+ kuduAppPool.WaitForState(IIS.ObjectState.Started);
}
return kuduAppPool;
@@ -217,7 +228,7 @@ private void DeleteSite(IIS.ServerManager iis, string siteName, bool deletePhysi
var site = iis.Sites[siteName];
if (site != null)
{
- site.Stop();
+ site.StopAndWait();
if (deletePhysicalFiles)
{
string physicalPath = site.Applications[0].VirtualDirectories[0].PhysicalPath;

0 comments on commit be81ccc

Please sign in to comment.