Move deployment helpers out of the test project.
This commit is contained in:
parent
dcac97fe3b
commit
29ef86fad3
|
|
@ -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.22617.0
|
VisualStudioVersion = 14.0.22803.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{44621553-AA7D-4893-8834-79582A7D8348}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{44621553-AA7D-4893-8834-79582A7D8348}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -28,6 +28,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Test", "test\Mus
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Spa.Test", "test\MusicStore.Spa.Test\MusicStore.Spa.Test.xproj", "{9D3326C4-1F12-4526-9F25-712A1463B3FA}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Spa.Test", "test\MusicStore.Spa.Test\MusicStore.Spa.Test.xproj", "{9D3326C4-1F12-4526-9F25-712A1463B3FA}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "DeploymentHelpers", "test\DeploymentHelpers\DeploymentHelpers.xproj", "{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -112,6 +114,18 @@ Global
|
||||||
{9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
{9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|x86.ActiveCfg = Release|Any CPU
|
{9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|x86.Build.0 = Release|Any CPU
|
{9D3326C4-1F12-4526-9F25-712A1463B3FA}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -124,5 +138,6 @@ Global
|
||||||
{93891170-A8D5-46FD-A291-40F90CF258C2} = {B7B176B6-8D4D-4EF1-BBD2-DDA650C78FFF}
|
{93891170-A8D5-46FD-A291-40F90CF258C2} = {B7B176B6-8D4D-4EF1-BBD2-DDA650C78FFF}
|
||||||
{CA663205-77DE-4E55-B300-85594181B5A9} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06}
|
{CA663205-77DE-4E55-B300-85594181B5A9} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06}
|
||||||
{9D3326C4-1F12-4526-9F25-712A1463B3FA} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06}
|
{9D3326C4-1F12-4526-9F25-712A1463B3FA} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06}
|
||||||
|
{C98E54D3-F4C6-4D16-A5A6-E86A636A7311} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ namespace MusicStore
|
||||||
//The allowed values are Development,Staging and Production
|
//The allowed values are Development,Staging and Production
|
||||||
public void ConfigureDevelopment(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void ConfigureDevelopment(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
|
||||||
|
|
||||||
// StatusCode pages to gracefully handle status codes 400-599.
|
// StatusCode pages to gracefully handle status codes 400-599.
|
||||||
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
||||||
|
|
@ -134,7 +134,7 @@ namespace MusicStore
|
||||||
//The allowed values are Development,Staging and Production
|
//The allowed values are Development,Staging and Production
|
||||||
public void ConfigureStaging(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void ConfigureStaging(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
|
||||||
|
|
||||||
// StatusCode pages to gracefully handle status codes 400-599.
|
// StatusCode pages to gracefully handle status codes 400-599.
|
||||||
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
||||||
|
|
@ -148,7 +148,7 @@ namespace MusicStore
|
||||||
//The allowed values are Development,Staging and Production
|
//The allowed values are Development,Staging and Production
|
||||||
public void ConfigureProduction(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void ConfigureProduction(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
|
||||||
|
|
||||||
// StatusCode pages to gracefully handle status codes 400-599.
|
// StatusCode pages to gracefully handle status codes 400-599.
|
||||||
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ namespace MusicStore
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
|
||||||
|
|
||||||
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ namespace MusicStore
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
|
||||||
|
|
||||||
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Parameters to control application deployment.
|
||||||
|
/// </summary>
|
||||||
|
public class DeploymentParameters
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of <see cref="DeploymentParameters"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="applicationPath">Source code location of the target location to be deployed.</param>
|
||||||
|
/// <param name="serverType">Where to be deployed on.</param>
|
||||||
|
/// <param name="runtimeFlavor">Flavor of the clr to run against.</param>
|
||||||
|
/// <param name="runtimeArchitecture">Architecture of the DNX to be used.</param>
|
||||||
|
public DeploymentParameters(
|
||||||
|
string applicationPath,
|
||||||
|
ServerType serverType,
|
||||||
|
RuntimeFlavor runtimeFlavor,
|
||||||
|
RuntimeArchitecture runtimeArchitecture)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(applicationPath))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Value cannot be null.", "applicationPath");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(applicationPath))
|
||||||
|
{
|
||||||
|
throw new DirectoryNotFoundException(string.Format("Application path {0} does not exist.", applicationPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationPath = applicationPath;
|
||||||
|
ServerType = serverType;
|
||||||
|
RuntimeFlavor = runtimeFlavor;
|
||||||
|
RuntimeArchitecture = runtimeArchitecture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerType ServerType { get; private set; }
|
||||||
|
|
||||||
|
public RuntimeFlavor RuntimeFlavor { get; private set; }
|
||||||
|
|
||||||
|
public RuntimeArchitecture RuntimeArchitecture { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Suggested base url for the deployed application. The final deployed url could be
|
||||||
|
/// different than this. Use <see cref="DeploymentResult.ApplicationBaseUri"/> for the
|
||||||
|
/// deployed url.
|
||||||
|
/// </summary>
|
||||||
|
public string ApplicationBaseUriHint { get; set; }
|
||||||
|
|
||||||
|
public string EnvironmentName { get; set; }
|
||||||
|
|
||||||
|
public string ApplicationHostConfigTemplateContent { get; set; }
|
||||||
|
|
||||||
|
public string ApplicationHostConfigLocation { get; set; }
|
||||||
|
|
||||||
|
public string SiteName { get; set; }
|
||||||
|
|
||||||
|
public string ApplicationPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// To publish the application before deployment.
|
||||||
|
/// </summary>
|
||||||
|
public bool PublishApplicationBeforeDeployment { get; set; }
|
||||||
|
|
||||||
|
public string PublishedApplicationRootPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Passes the --no-source option when publishing.
|
||||||
|
/// </summary>
|
||||||
|
public bool PublishWithNoSource { get; set; }
|
||||||
|
|
||||||
|
public string DnxRuntime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Environment variables to be set before starting the host.
|
||||||
|
/// Not applicable for IIS Scenarios.
|
||||||
|
/// </summary>
|
||||||
|
public List<KeyValuePair<string, string>> EnvironmentVariables { get; private set; } = new List<KeyValuePair<string, string>>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For any application level cleanup to be invoked after performing host cleanup.
|
||||||
|
/// </summary>
|
||||||
|
public Action<DeploymentParameters> UserAdditionalCleanup { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Result of a deployment.
|
||||||
|
/// </summary>
|
||||||
|
public class DeploymentResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base Uri of the deployment application.
|
||||||
|
/// </summary>
|
||||||
|
public string ApplicationBaseUri { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The web root folder where the application is hosted. This path can be different from the
|
||||||
|
/// original application source location if published before deployment.
|
||||||
|
/// </summary>
|
||||||
|
public string WebRootLocation { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Original deployment parameters used for this deployment.
|
||||||
|
/// </summary>
|
||||||
|
public DeploymentParameters DeploymentParameters { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
namespace E2ETests
|
namespace DeploymentHelpers
|
||||||
{
|
{
|
||||||
public enum RuntimeArchitecture
|
public enum RuntimeArchitecture
|
||||||
{
|
{
|
||||||
amd64,
|
x64,
|
||||||
x86
|
x86
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
public enum RuntimeFlavor
|
||||||
|
{
|
||||||
|
clr,
|
||||||
|
coreclr,
|
||||||
|
mono
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
public class RetryHelper
|
||||||
|
{
|
||||||
|
public static void RetryRequest(Func<HttpResponseMessage> retryBlock, ILogger logger, int retryCount = 12)
|
||||||
|
{
|
||||||
|
for (int retry = 0; retry < retryCount; retry++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.LogWarning("Retry count {retryCount}..", retry + 1);
|
||||||
|
var response = retryBlock();
|
||||||
|
|
||||||
|
if (response.StatusCode == HttpStatusCode.ServiceUnavailable)
|
||||||
|
{
|
||||||
|
// Automatically retry on 503. May be application is still booting.
|
||||||
|
logger.LogWarning("Retrying a service unavailable error.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break; //Went through successfully
|
||||||
|
}
|
||||||
|
catch (AggregateException exception)
|
||||||
|
{
|
||||||
|
if (retry == retryCount - 1)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (exception.InnerException is HttpRequestException
|
||||||
|
#if DNX451
|
||||||
|
|| exception.InnerException is System.Net.WebException
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
logger.LogWarning("Failed to complete the request : {0}.", exception.Message);
|
||||||
|
Thread.Sleep(7 * 1000); //Wait for a while before retry.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
namespace E2ETests
|
namespace DeploymentHelpers
|
||||||
{
|
{
|
||||||
public enum ServerType
|
public enum ServerType
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Abstract base class of all deplolyers with a back bone implementation of some of the common helpers.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ApplicationDeployer : IApplicationDeployer
|
||||||
|
{
|
||||||
|
protected string ChosenRuntimePath { get; set; }
|
||||||
|
|
||||||
|
protected string ChosenRuntimeName { get; set; }
|
||||||
|
|
||||||
|
protected DeploymentParameters DeploymentParameters { get; private set; }
|
||||||
|
|
||||||
|
protected ILogger Logger { get; private set; }
|
||||||
|
|
||||||
|
public abstract DeploymentResult Deploy();
|
||||||
|
|
||||||
|
public ApplicationDeployer(
|
||||||
|
DeploymentParameters deploymentParameters,
|
||||||
|
ILogger logger)
|
||||||
|
{
|
||||||
|
DeploymentParameters = deploymentParameters;
|
||||||
|
Logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string PopulateChosenRuntimeInformation()
|
||||||
|
{
|
||||||
|
var runtimePath = Process.GetCurrentProcess().MainModule.FileName;
|
||||||
|
Logger.LogInformation(string.Empty);
|
||||||
|
Logger.LogInformation("Current runtime path is : {0}", runtimePath);
|
||||||
|
|
||||||
|
var replaceStr = new StringBuilder().
|
||||||
|
Append("dnx").
|
||||||
|
Append((DeploymentParameters.RuntimeFlavor == RuntimeFlavor.coreclr) ? "-coreclr" : "-clr").
|
||||||
|
Append("-win").
|
||||||
|
Append((DeploymentParameters.RuntimeArchitecture == RuntimeArchitecture.x86) ? "-x86" : "-x64").
|
||||||
|
ToString();
|
||||||
|
|
||||||
|
runtimePath = Regex.Replace(runtimePath, "dnx-(clr|coreclr)-win-(x86|x64)", replaceStr, RegexOptions.IgnoreCase);
|
||||||
|
ChosenRuntimePath = Path.GetDirectoryName(runtimePath);
|
||||||
|
|
||||||
|
var runtimeDirectoryInfo = new DirectoryInfo(ChosenRuntimePath);
|
||||||
|
if (!runtimeDirectoryInfo.Exists)
|
||||||
|
{
|
||||||
|
throw new Exception(
|
||||||
|
string.Format("Requested runtime at location '{0}' does not exist. Please make sure it is installed before running test.",
|
||||||
|
runtimeDirectoryInfo.FullName));
|
||||||
|
}
|
||||||
|
|
||||||
|
ChosenRuntimeName = runtimeDirectoryInfo.Parent.Name;
|
||||||
|
Logger.LogInformation(string.Empty);
|
||||||
|
Logger.LogInformation("Changing to use runtime : {runtimeName}", ChosenRuntimeName);
|
||||||
|
return ChosenRuntimeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DnuPublish(string publishRoot = null)
|
||||||
|
{
|
||||||
|
DeploymentParameters.PublishedApplicationRootPath = Path.Combine(publishRoot ?? Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||||
|
|
||||||
|
var parameters =
|
||||||
|
string.Format(
|
||||||
|
"publish {0} -o {1} --runtime {2} {3}",
|
||||||
|
DeploymentParameters.ApplicationPath,
|
||||||
|
DeploymentParameters.PublishedApplicationRootPath,
|
||||||
|
DeploymentParameters.DnxRuntime,
|
||||||
|
DeploymentParameters.PublishWithNoSource ? "--no-source" : string.Empty);
|
||||||
|
|
||||||
|
Logger.LogInformation("Executing command dnu {args}", parameters);
|
||||||
|
|
||||||
|
var startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = Path.Combine(ChosenRuntimePath, "dnu.cmd"),
|
||||||
|
Arguments = parameters,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var hostProcess = Process.Start(startInfo);
|
||||||
|
hostProcess.WaitForExit(60 * 1000);
|
||||||
|
|
||||||
|
DeploymentParameters.ApplicationPath =
|
||||||
|
(DeploymentParameters.ServerType == ServerType.IISExpress ||
|
||||||
|
DeploymentParameters.ServerType == ServerType.IISNativeModule ||
|
||||||
|
DeploymentParameters.ServerType == ServerType.IIS) ?
|
||||||
|
Path.Combine(DeploymentParameters.PublishedApplicationRootPath, "wwwroot") :
|
||||||
|
Path.Combine(DeploymentParameters.PublishedApplicationRootPath, "approot", "src", "MusicStore");
|
||||||
|
|
||||||
|
Logger.LogInformation("dnu publish finished with exit code : {exitCode}", hostProcess.ExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void CleanPublishedOutput()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// We've originally published the application in a temp folder. We need to delete it.
|
||||||
|
Directory.Delete(DeploymentParameters.PublishedApplicationRootPath, true);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Failed to delete directory : {error}", exception.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ShutDownIfAnyHostProcess(Process hostProcess)
|
||||||
|
{
|
||||||
|
if (hostProcess != null && !hostProcess.HasExited)
|
||||||
|
{
|
||||||
|
// Shutdown the host process.
|
||||||
|
hostProcess.Kill();
|
||||||
|
hostProcess.WaitForExit(5 * 1000);
|
||||||
|
if (!hostProcess.HasExited)
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Unable to terminate the host process with process Id '{processId}", hostProcess.Id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Successfully terminated host process with process Id '{processId}'", hostProcess.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Host process already exited or never started successfully.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AddEnvironmentVariablesToProcess(ProcessStartInfo startInfo)
|
||||||
|
{
|
||||||
|
var environment =
|
||||||
|
#if DNX451
|
||||||
|
startInfo.EnvironmentVariables;
|
||||||
|
#elif DNXCORE50
|
||||||
|
startInfo.Environment;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
environment.Add("ASPNET_ENV", DeploymentParameters.EnvironmentName);
|
||||||
|
|
||||||
|
// Work around for https://github.com/aspnet/dnx/issues/1515
|
||||||
|
environment.Add("DNX_PACKAGES", string.Empty);
|
||||||
|
environment.Remove("DNX_DEFAULT_LIB");
|
||||||
|
|
||||||
|
foreach (var environmentVariable in DeploymentParameters.EnvironmentVariables)
|
||||||
|
{
|
||||||
|
environment.Add(environmentVariable.Key, environmentVariable.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void InvokeUserApplicationCleanup()
|
||||||
|
{
|
||||||
|
if (DeploymentParameters.UserAdditionalCleanup != null)
|
||||||
|
{
|
||||||
|
// User cleanup.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DeploymentParameters.UserAdditionalCleanup(DeploymentParameters);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Logger.LogWarning("User cleanup code failed with exception : {exception}", exception.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Factory to create an appropriate deployer based on <see cref="DeploymentParameters"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class ApplicationDeployerFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a deployer instance based on settings in <see cref="DeploymentParameters"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deploymentParameters"></param>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IApplicationDeployer Create(DeploymentParameters deploymentParameters, ILogger logger)
|
||||||
|
{
|
||||||
|
if (deploymentParameters == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(deploymentParameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logger == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(logger));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deploymentParameters.RuntimeFlavor == RuntimeFlavor.mono)
|
||||||
|
{
|
||||||
|
return new MonoDeployer(deploymentParameters, logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (deploymentParameters.ServerType)
|
||||||
|
{
|
||||||
|
case ServerType.IISExpress:
|
||||||
|
return new IISExpressDeployer(deploymentParameters, logger);
|
||||||
|
#if DNX451
|
||||||
|
case ServerType.IIS:
|
||||||
|
case ServerType.IISNativeModule:
|
||||||
|
return new IISDeployer(deploymentParameters, logger);
|
||||||
|
#endif
|
||||||
|
case ServerType.WebListener:
|
||||||
|
case ServerType.Kestrel:
|
||||||
|
return new SelfHostDeployer(deploymentParameters, logger);
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException(
|
||||||
|
string.Format("Found no deployers suitable for server type '{0}' with the current runtime.",
|
||||||
|
deploymentParameters.ServerType)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Common operations on an application deployer.
|
||||||
|
/// </summary>
|
||||||
|
public interface IApplicationDeployer : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Deploys the application to the target with specified <see cref="DeploymentParameters"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
DeploymentResult Deploy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
#if DNX451
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Xml;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
|
using Microsoft.Web.Administration;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Deployer for IIS (Both Helios and NativeModule).
|
||||||
|
/// </summary>
|
||||||
|
public class IISDeployer : ApplicationDeployer
|
||||||
|
{
|
||||||
|
private IISApplication _application;
|
||||||
|
|
||||||
|
public IISDeployer(DeploymentParameters startParameters, ILogger logger)
|
||||||
|
: base(startParameters, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DeploymentResult Deploy()
|
||||||
|
{
|
||||||
|
// Only supports publish and run on IIS.
|
||||||
|
DeploymentParameters.PublishApplicationBeforeDeployment = true;
|
||||||
|
|
||||||
|
_application = new IISApplication(DeploymentParameters, Logger);
|
||||||
|
|
||||||
|
DeploymentParameters.DnxRuntime = PopulateChosenRuntimeInformation();
|
||||||
|
|
||||||
|
// Publish to IIS root\application folder.
|
||||||
|
DnuPublish(publishRoot: _application.WebSiteRootFolder);
|
||||||
|
|
||||||
|
// Drop an ini file instead of setting environment variable.
|
||||||
|
SetAspEnvironmentWithIni();
|
||||||
|
|
||||||
|
// Setup the IIS Application.
|
||||||
|
if (DeploymentParameters.ServerType == ServerType.IISNativeModule)
|
||||||
|
{
|
||||||
|
TurnRammFarOnNativeModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
_application.Deploy();
|
||||||
|
Logger.LogInformation("Successfully finished IIS application directory setup.");
|
||||||
|
|
||||||
|
Thread.Sleep(1 * 1000);
|
||||||
|
|
||||||
|
return new DeploymentResult
|
||||||
|
{
|
||||||
|
WebRootLocation = DeploymentParameters.ApplicationPath,
|
||||||
|
DeploymentParameters = DeploymentParameters,
|
||||||
|
// Accomodate the vdir name.
|
||||||
|
ApplicationBaseUri = new UriBuilder(Uri.UriSchemeHttp, "localhost", _application.Port, _application.VirtualDirectoryName).Uri.AbsoluteUri + "/"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAspEnvironmentWithIni()
|
||||||
|
{
|
||||||
|
// Drop a Microsoft.AspNet.Hosting.ini with ASPNET_ENV information.
|
||||||
|
Logger.LogInformation("Creating Microsoft.AspNet.Hosting.ini file with ASPNET_ENV.");
|
||||||
|
var iniFile = Path.Combine(DeploymentParameters.ApplicationPath, "Microsoft.AspNet.Hosting.ini");
|
||||||
|
File.WriteAllText(iniFile, string.Format("ASPNET_ENV={0}", DeploymentParameters.EnvironmentName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TurnRammFarOnNativeModule()
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Turning runAllManagedModulesForAllRequests=true in web.config for native module.");
|
||||||
|
var webConfig = Path.Combine(DeploymentParameters.ApplicationPath, "web.config");
|
||||||
|
var configuration = new XmlDocument();
|
||||||
|
configuration.LoadXml(File.ReadAllText(webConfig));
|
||||||
|
|
||||||
|
// https://github.com/aspnet/Helios/issues/77
|
||||||
|
var rammfarAttribute = configuration.CreateAttribute("runAllManagedModulesForAllRequests");
|
||||||
|
rammfarAttribute.Value = "true";
|
||||||
|
var modulesNode = configuration.CreateElement("modules");
|
||||||
|
modulesNode.Attributes.Append(rammfarAttribute);
|
||||||
|
var systemWebServerNode = configuration.CreateElement("system.webServer");
|
||||||
|
systemWebServerNode.AppendChild(modulesNode);
|
||||||
|
configuration.SelectSingleNode("//configuration").AppendChild(systemWebServerNode);
|
||||||
|
configuration.Save(webConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
if (_application != null)
|
||||||
|
{
|
||||||
|
_application.StopAndDeleteAppPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
CleanPublishedOutput();
|
||||||
|
InvokeUserApplicationCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class IISApplication
|
||||||
|
{
|
||||||
|
private const string WEBSITE_NAME = "TestWebSite";
|
||||||
|
private const string NATIVE_MODULE_MANAGED_RUNTIME_VERSION = "vCoreFX";
|
||||||
|
|
||||||
|
private readonly ServerManager _serverManager = new ServerManager();
|
||||||
|
private readonly DeploymentParameters _startParameters;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private ApplicationPool _applicationPool;
|
||||||
|
private Application _application;
|
||||||
|
|
||||||
|
public string VirtualDirectoryName { get; set; }
|
||||||
|
|
||||||
|
public string WebSiteRootFolder
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Path.Combine(
|
||||||
|
Environment.GetEnvironmentVariable("SystemDrive") + @"\",
|
||||||
|
"inetpub",
|
||||||
|
"TestWebSite");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Port
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Uri(_startParameters.ApplicationBaseUriHint).Port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IISApplication(DeploymentParameters startParameters, ILogger logger)
|
||||||
|
{
|
||||||
|
_startParameters = startParameters;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Deploy()
|
||||||
|
{
|
||||||
|
VirtualDirectoryName = new DirectoryInfo(_startParameters.ApplicationPath).Parent.Name;
|
||||||
|
_applicationPool = CreateAppPool(VirtualDirectoryName);
|
||||||
|
_application = Website.Applications.Add("/" + VirtualDirectoryName, _startParameters.ApplicationPath);
|
||||||
|
_application.ApplicationPoolName = _applicationPool.Name;
|
||||||
|
_serverManager.CommitChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Site _website;
|
||||||
|
private Site Website
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
_website = _serverManager.Sites.Where(s => s.Name == WEBSITE_NAME).FirstOrDefault();
|
||||||
|
if (_website == null)
|
||||||
|
{
|
||||||
|
_website = _serverManager.Sites.Add(WEBSITE_NAME, WebSiteRootFolder, Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _website;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApplicationPool CreateAppPool(string appPoolName)
|
||||||
|
{
|
||||||
|
var applicationPool = _serverManager.ApplicationPools.Add(appPoolName);
|
||||||
|
if (_startParameters.ServerType == ServerType.IISNativeModule)
|
||||||
|
{
|
||||||
|
// Not assigning a runtime version will choose v4.0 default.
|
||||||
|
applicationPool.ManagedRuntimeVersion = NATIVE_MODULE_MANAGED_RUNTIME_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationPool.Enable32BitAppOnWin64 = (_startParameters.RuntimeArchitecture == RuntimeArchitecture.x86);
|
||||||
|
_logger.LogInformation("Created {bit} application pool '{name}' with runtime version '{runtime}'.",
|
||||||
|
_startParameters.RuntimeArchitecture, applicationPool.Name,
|
||||||
|
applicationPool.ManagedRuntimeVersion ?? "default");
|
||||||
|
return applicationPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopAndDeleteAppPool()
|
||||||
|
{
|
||||||
|
if (_applicationPool != null)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Stopping application pool '{name}' and deleting application.", _applicationPool.Name);
|
||||||
|
_applicationPool.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the application from website.
|
||||||
|
if (_application != null)
|
||||||
|
{
|
||||||
|
_application = Website.Applications.Where(a => a.Path == _application.Path).FirstOrDefault();
|
||||||
|
Website.Applications.Remove(_application);
|
||||||
|
_serverManager.ApplicationPools.Remove(_serverManager.ApplicationPools[_applicationPool.Name]);
|
||||||
|
_serverManager.CommitChanges();
|
||||||
|
_logger.LogInformation("Successfully stopped application pool '{name}' and deleted application from IIS.", _applicationPool.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
|
using Microsoft.Framework.Runtime;
|
||||||
|
using Microsoft.Framework.Runtime.Infrastructure;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Deployment helper for IISExpress.
|
||||||
|
/// </summary>
|
||||||
|
public class IISExpressDeployer : ApplicationDeployer
|
||||||
|
{
|
||||||
|
private Process _hostProcess;
|
||||||
|
|
||||||
|
public IISExpressDeployer(DeploymentParameters deploymentParameters, ILogger logger)
|
||||||
|
: base(deploymentParameters, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DeploymentResult Deploy()
|
||||||
|
{
|
||||||
|
DeploymentParameters.DnxRuntime = PopulateChosenRuntimeInformation();
|
||||||
|
|
||||||
|
if (DeploymentParameters.PublishApplicationBeforeDeployment)
|
||||||
|
{
|
||||||
|
DnuPublish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch the host process.
|
||||||
|
_hostProcess = StartHeliosHost();
|
||||||
|
|
||||||
|
return new DeploymentResult
|
||||||
|
{
|
||||||
|
WebRootLocation = DeploymentParameters.ApplicationPath,
|
||||||
|
DeploymentParameters = DeploymentParameters,
|
||||||
|
// Right now this works only for urls like http://localhost:5001/. Does not work for http://localhost:5001/subpath.
|
||||||
|
ApplicationBaseUri = DeploymentParameters.ApplicationBaseUriHint
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Process StartHeliosHost()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(DeploymentParameters.ApplicationHostConfigTemplateContent))
|
||||||
|
{
|
||||||
|
// Pass on the applicationhost.config to iis express. With this don't need to pass in the /path /port switches as they are in the applicationHost.config
|
||||||
|
// We take a copy of the original specified applicationHost.Config to prevent modifying the one in the repo.
|
||||||
|
|
||||||
|
DeploymentParameters.ApplicationHostConfigTemplateContent =
|
||||||
|
DeploymentParameters.ApplicationHostConfigTemplateContent
|
||||||
|
.Replace("[ApplicationPhysicalPath]", Path.Combine(DeploymentParameters.ApplicationPath, "wwwroot"))
|
||||||
|
.Replace("[PORT]", new Uri(DeploymentParameters.ApplicationBaseUriHint).Port.ToString());
|
||||||
|
|
||||||
|
DeploymentParameters.ApplicationHostConfigLocation = Path.GetTempFileName();
|
||||||
|
|
||||||
|
File.WriteAllText(DeploymentParameters.ApplicationHostConfigLocation,
|
||||||
|
DeploymentParameters.ApplicationHostConfigTemplateContent.Replace("[ApplicationPhysicalPath]", DeploymentParameters.ApplicationPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DeploymentParameters.PublishApplicationBeforeDeployment)
|
||||||
|
{
|
||||||
|
CopyAspNetLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
var webroot = DeploymentParameters.ApplicationPath;
|
||||||
|
if (!webroot.EndsWith("wwwroot"))
|
||||||
|
{
|
||||||
|
webroot = Path.Combine(webroot, "wwwroot");
|
||||||
|
}
|
||||||
|
|
||||||
|
var parameters = string.IsNullOrWhiteSpace(DeploymentParameters.ApplicationHostConfigLocation) ?
|
||||||
|
string.Format("/port:{0} /path:\"{1}\"", new Uri(DeploymentParameters.ApplicationBaseUriHint).Port, webroot) :
|
||||||
|
string.Format("/site:{0} /config:{1}", DeploymentParameters.SiteName, DeploymentParameters.ApplicationHostConfigLocation);
|
||||||
|
|
||||||
|
var iisExpressPath = GetIISExpressPath();
|
||||||
|
|
||||||
|
Logger.LogInformation("Executing command : {iisExpress} {args}", iisExpressPath, parameters);
|
||||||
|
|
||||||
|
var startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = iisExpressPath,
|
||||||
|
Arguments = parameters,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = false
|
||||||
|
};
|
||||||
|
|
||||||
|
AddEnvironmentVariablesToProcess(startInfo);
|
||||||
|
|
||||||
|
// IIS express figures out the DNX from %PATH%.
|
||||||
|
#if DNX451
|
||||||
|
startInfo.EnvironmentVariables["PATH"] = ChosenRuntimePath + ";" + startInfo.EnvironmentVariables["PATH"];
|
||||||
|
#elif DNXCORE50
|
||||||
|
startInfo.Environment["PATH"] = ChosenRuntimePath + ";" + startInfo.Environment["PATH"];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Process hostProcess = Process.Start(startInfo);
|
||||||
|
Logger.LogInformation("Started iisexpress. Process Id : {processId}", hostProcess.Id);
|
||||||
|
|
||||||
|
return hostProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CopyAspNetLoader()
|
||||||
|
{
|
||||||
|
var libraryManager = (ILibraryManager)CallContextServiceLocator.Locator.ServiceProvider.GetService(typeof(ILibraryManager));
|
||||||
|
var interopLibrary = libraryManager.GetLibraryInformation("Microsoft.AspNet.Loader.IIS.Interop");
|
||||||
|
|
||||||
|
if (interopLibrary == null)
|
||||||
|
{
|
||||||
|
throw new Exception(
|
||||||
|
string.Format("Include Microsoft.AspNet.Server.IIS package in your project.json to deploy in {0}.",
|
||||||
|
ServerType.IISExpress));
|
||||||
|
}
|
||||||
|
|
||||||
|
var aspNetLoaderSrcPath = Path.Combine(interopLibrary.Path, "tools", "AspNet.Loader.dll");
|
||||||
|
var aspNetLoaderDestPath = Path.Combine(DeploymentParameters.ApplicationPath, "wwwroot", "bin", "AspNet.Loader.dll");
|
||||||
|
|
||||||
|
// Create bin directory if it does not exist.
|
||||||
|
Directory.CreateDirectory(new DirectoryInfo(aspNetLoaderDestPath).Parent.FullName);
|
||||||
|
|
||||||
|
if (!File.Exists(aspNetLoaderDestPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Copy(aspNetLoaderSrcPath, aspNetLoaderDestPath);
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
// Ignore file already exists exception. Sometimes multiple tests might try
|
||||||
|
// doing the same and one of them wins.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetIISExpressPath()
|
||||||
|
{
|
||||||
|
// Get path to program files
|
||||||
|
var iisExpressPath = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "IIS Express", "iisexpress.exe");
|
||||||
|
|
||||||
|
// Get path to 64 bit of IIS Express
|
||||||
|
if (DeploymentParameters.RuntimeArchitecture == RuntimeArchitecture.x64)
|
||||||
|
{
|
||||||
|
iisExpressPath = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"), "IIS Express", "iisexpress.exe");
|
||||||
|
|
||||||
|
// If process is 32 bit, the path points to x86. Replace path to point to x64
|
||||||
|
iisExpressPath = IntPtr.Size == 8 ? iisExpressPath : iisExpressPath.Replace(" (x86)", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(iisExpressPath))
|
||||||
|
{
|
||||||
|
throw new Exception("Unable to find IISExpress on the machine");
|
||||||
|
}
|
||||||
|
|
||||||
|
return iisExpressPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
ShutDownIfAnyHostProcess(_hostProcess);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(DeploymentParameters.ApplicationHostConfigLocation)
|
||||||
|
&& File.Exists(DeploymentParameters.ApplicationHostConfigLocation))
|
||||||
|
{
|
||||||
|
// Delete the temp applicationHostConfig that we created.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(DeploymentParameters.ApplicationHostConfigLocation);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
// Ignore delete failures - just write a log.
|
||||||
|
Logger.LogWarning("Failed to delete '{config}'. Exception : {exception}", DeploymentParameters.ApplicationHostConfigLocation, exception.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeploymentParameters.PublishApplicationBeforeDeployment)
|
||||||
|
{
|
||||||
|
CleanPublishedOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
InvokeUserApplicationCleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Deployer for Kestrel on Mono.
|
||||||
|
/// </summary>
|
||||||
|
public class MonoDeployer : ApplicationDeployer
|
||||||
|
{
|
||||||
|
private Process _hostProcess;
|
||||||
|
|
||||||
|
public MonoDeployer(DeploymentParameters deploymentParameters, ILogger logger)
|
||||||
|
: base(deploymentParameters, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DeploymentResult Deploy()
|
||||||
|
{
|
||||||
|
var path = Environment.GetEnvironmentVariable("PATH");
|
||||||
|
var runtimeBin = path.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries).
|
||||||
|
Where(c => c.Contains("dnx-mono")).FirstOrDefault();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(runtimeBin))
|
||||||
|
{
|
||||||
|
throw new Exception("Runtime not detected on the machine.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeploymentParameters.PublishApplicationBeforeDeployment)
|
||||||
|
{
|
||||||
|
// We use full path to runtime to pack.
|
||||||
|
DeploymentParameters.DnxRuntime = new DirectoryInfo(runtimeBin).Parent.FullName;
|
||||||
|
DnuPublish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch the host process.
|
||||||
|
_hostProcess = StartMonoHost();
|
||||||
|
|
||||||
|
return new DeploymentResult
|
||||||
|
{
|
||||||
|
WebRootLocation = DeploymentParameters.ApplicationPath,
|
||||||
|
DeploymentParameters = DeploymentParameters,
|
||||||
|
ApplicationBaseUri = DeploymentParameters.ApplicationBaseUriHint
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Process StartMonoHost()
|
||||||
|
{
|
||||||
|
if (DeploymentParameters.ServerType != ServerType.Kestrel)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("kestrel is the only valid ServerType for Mono");
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.LogInformation("Executing command: dnx \"{appPath}\" kestrel --server.urls {url}",
|
||||||
|
DeploymentParameters.ApplicationPath, DeploymentParameters.ApplicationBaseUriHint);
|
||||||
|
|
||||||
|
var startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "dnx",
|
||||||
|
Arguments = string.Format("\"{0}\" kestrel --server.urls {1}", DeploymentParameters.ApplicationPath, DeploymentParameters.ApplicationBaseUriHint),
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
RedirectStandardInput = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var hostProcess = Process.Start(startInfo);
|
||||||
|
Logger.LogInformation("Started {0}. Process Id : {1}", hostProcess.MainModule.FileName, hostProcess.Id);
|
||||||
|
|
||||||
|
if (hostProcess.HasExited)
|
||||||
|
{
|
||||||
|
Logger.LogError("Host process {processName} exited with code {exitCode} or failed to start.", startInfo.FileName, hostProcess.ExitCode);
|
||||||
|
throw new Exception("Failed to start host");
|
||||||
|
}
|
||||||
|
|
||||||
|
return hostProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
ShutDownIfAnyHostProcess(_hostProcess);
|
||||||
|
|
||||||
|
if (DeploymentParameters.PublishApplicationBeforeDeployment)
|
||||||
|
{
|
||||||
|
CleanPublishedOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
InvokeUserApplicationCleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.Framework.Logging;
|
||||||
|
|
||||||
|
namespace DeploymentHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Deployer for WebListener and Kestrel.
|
||||||
|
/// </summary>
|
||||||
|
public class SelfHostDeployer : ApplicationDeployer
|
||||||
|
{
|
||||||
|
private Process _hostProcess;
|
||||||
|
|
||||||
|
public SelfHostDeployer(DeploymentParameters deploymentParameters, ILogger logger)
|
||||||
|
: base(deploymentParameters, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override DeploymentResult Deploy()
|
||||||
|
{
|
||||||
|
DeploymentParameters.DnxRuntime = PopulateChosenRuntimeInformation();
|
||||||
|
|
||||||
|
if (DeploymentParameters.PublishApplicationBeforeDeployment)
|
||||||
|
{
|
||||||
|
DnuPublish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Launch the host process.
|
||||||
|
_hostProcess = StartSelfHost();
|
||||||
|
|
||||||
|
return new DeploymentResult
|
||||||
|
{
|
||||||
|
WebRootLocation = DeploymentParameters.ApplicationPath,
|
||||||
|
DeploymentParameters = DeploymentParameters,
|
||||||
|
ApplicationBaseUri = DeploymentParameters.ApplicationBaseUriHint
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private Process StartSelfHost()
|
||||||
|
{
|
||||||
|
var commandName = DeploymentParameters.ServerType == ServerType.WebListener ? "web" : "kestrel";
|
||||||
|
Logger.LogInformation("Executing dnx.exe {appPath} {command} --server.urls {url}", DeploymentParameters.ApplicationPath, commandName, DeploymentParameters.ApplicationBaseUriHint);
|
||||||
|
|
||||||
|
var startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = Path.Combine(ChosenRuntimePath, "dnx.exe"),
|
||||||
|
Arguments = string.Format("\"{0}\" {1} --server.urls {2}", DeploymentParameters.ApplicationPath, commandName, DeploymentParameters.ApplicationBaseUriHint),
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
AddEnvironmentVariablesToProcess(startInfo);
|
||||||
|
var hostProcess = Process.Start(startInfo);
|
||||||
|
|
||||||
|
//Sometimes reading MainModule returns null if called immediately after starting process.
|
||||||
|
Thread.Sleep(1 * 1000);
|
||||||
|
|
||||||
|
if (hostProcess.HasExited)
|
||||||
|
{
|
||||||
|
Logger.LogError("Host process {processName} exited with code {exitCode} or failed to start.", startInfo.FileName, hostProcess.ExitCode);
|
||||||
|
throw new Exception("Failed to start host");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Started {fileName}. Process Id : {processId}", hostProcess.MainModule.FileName, hostProcess.Id);
|
||||||
|
}
|
||||||
|
catch (Win32Exception)
|
||||||
|
{
|
||||||
|
// Ignore.
|
||||||
|
}
|
||||||
|
|
||||||
|
return hostProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
ShutDownIfAnyHostProcess(_hostProcess);
|
||||||
|
|
||||||
|
if (DeploymentParameters.PublishApplicationBeforeDeployment)
|
||||||
|
{
|
||||||
|
CleanPublishedOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
InvokeUserApplicationCleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>c98e54d3-f4c6-4d16-a5a6-e86a636a7311</ProjectGuid>
|
||||||
|
<RootNamespace>DeploymentHelpers</RootNamespace>
|
||||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<ProduceOutputsOnBuild>True</ProduceOutputsOnBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"description": "Helpers to deploy applications to IIS Express, IIS, WebListener and Kestrel.",
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||||
|
"Microsoft.Framework.Logging.Interfaces": "1.0.0-*",
|
||||||
|
"Microsoft.Framework.Runtime.Interfaces": "1.0.0-*"
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"dnx451": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Web.Administration": "7.0.0"
|
||||||
|
},
|
||||||
|
"frameworkAssemblies": {
|
||||||
|
"System.Net.Http": "",
|
||||||
|
"System.Xml": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dnxcore50": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.Win32.Primitives": "4.0.0-beta-*",
|
||||||
|
"System.Diagnostics.Process": "4.0.0-beta-*",
|
||||||
|
"System.IO.FileSystem": "4.0.0-*",
|
||||||
|
"System.Net.Http": "4.0.0-beta-*",
|
||||||
|
"System.Runtime.Extensions": "4.0.10-beta-*",
|
||||||
|
"System.Text.RegularExpressions": "4.0.10-beta-*",
|
||||||
|
"System.Threading": "4.0.10-beta-*",
|
||||||
|
"System.Threading.Thread": "4.0.0-*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Microsoft.AspNet.Testing.xunit;
|
using Microsoft.AspNet.Testing.xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace DeploymentHelpers
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||||
public class SkipIfCurrentRuntimeIsCoreClrAttribute : Attribute, ITestCondition
|
public class SkipIfCurrentRuntimeIsCoreClrAttribute : Attribute, ITestCondition
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNet.Testing.xunit;
|
using Microsoft.AspNet.Testing.xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace DeploymentHelpers
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||||
public class SkipIfNativeModuleNotInstalledAttribute : Attribute, ITestCondition
|
public class SkipIfNativeModuleNotInstalledAttribute : Attribute, ITestCondition
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.AspNet.Testing.xunit;
|
using Microsoft.AspNet.Testing.xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace DeploymentHelpers
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
|
||||||
public class SkipOn32BitOSAttribute : Attribute, ITestCondition
|
public class SkipOn32BitOSAttribute : Attribute, ITestCondition
|
||||||
|
|
@ -1,427 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Xml;
|
|
||||||
using Microsoft.Framework.Logging;
|
|
||||||
|
|
||||||
namespace E2ETests
|
|
||||||
{
|
|
||||||
internal class DeploymentUtility
|
|
||||||
{
|
|
||||||
private static string APP_RELATIVE_PATH = Path.Combine("..", "..", "src", "MusicStore");
|
|
||||||
|
|
||||||
public static Process StartApplication(StartParameters startParameters, ILogger logger)
|
|
||||||
{
|
|
||||||
startParameters.ApplicationPath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), APP_RELATIVE_PATH));
|
|
||||||
|
|
||||||
//To avoid the DNX_DEFAULT_LIB of the test process flowing into Helios, set it to empty
|
|
||||||
var backupRuntimeDefaultLibPath = Environment.GetEnvironmentVariable("DNX_DEFAULT_LIB");
|
|
||||||
Environment.SetEnvironmentVariable("DNX_DEFAULT_LIB", string.Empty);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(startParameters.EnvironmentName))
|
|
||||||
{
|
|
||||||
if (startParameters.ServerType != ServerType.IISNativeModule &&
|
|
||||||
startParameters.ServerType != ServerType.IIS)
|
|
||||||
{
|
|
||||||
// To choose an environment based Startup.
|
|
||||||
Environment.SetEnvironmentVariable("ASPNET_ENV", startParameters.EnvironmentName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Cannot override with environment in case of IIS. Publish and write a Microsoft.AspNet.Hosting.ini file.
|
|
||||||
startParameters.PublishApplicationBeforeStart = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process hostProcess = null;
|
|
||||||
|
|
||||||
if (startParameters.RuntimeFlavor == RuntimeFlavor.Mono)
|
|
||||||
{
|
|
||||||
hostProcess = StartMonoHost(startParameters, logger);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Tweak the %PATH% to the point to the right RUNTIMEFLAVOR
|
|
||||||
startParameters.Runtime = SwitchPathToRuntimeFlavor(startParameters.RuntimeFlavor, startParameters.RuntimeArchitecture, logger);
|
|
||||||
|
|
||||||
//Reason to do pack here instead of in a common place is use the right runtime to do the packing. Previous line switches to use the right runtime.
|
|
||||||
if (startParameters.PublishApplicationBeforeStart)
|
|
||||||
{
|
|
||||||
#if DNX451
|
|
||||||
if (startParameters.ServerType == ServerType.IISNativeModule ||
|
|
||||||
startParameters.ServerType == ServerType.IIS)
|
|
||||||
{
|
|
||||||
// Publish to IIS root\application folder.
|
|
||||||
DnuPublish(startParameters, logger, Path.Combine(Environment.GetEnvironmentVariable("SystemDrive") + @"\", @"inetpub\wwwroot"));
|
|
||||||
|
|
||||||
// Drop a Microsoft.AspNet.Hosting.ini with ASPNET_ENV information.
|
|
||||||
logger.LogInformation("Creating Microsoft.AspNet.Hosting.ini file with ASPNET_ENV.");
|
|
||||||
var iniFile = Path.Combine(startParameters.ApplicationPath, "Microsoft.AspNet.Hosting.ini");
|
|
||||||
File.WriteAllText(iniFile, string.Format("ASPNET_ENV={0}", startParameters.EnvironmentName));
|
|
||||||
|
|
||||||
// Can't use localdb with IIS. Setting an override to use InMemoryStore.
|
|
||||||
logger.LogInformation("Creating configoverride.json file to override default config.");
|
|
||||||
var overrideConfig = Path.Combine(startParameters.ApplicationPath, "..", "approot", "src", "MusicStore", "configoverride.json");
|
|
||||||
overrideConfig = Path.GetFullPath(overrideConfig);
|
|
||||||
File.WriteAllText(overrideConfig, "{\"UseInMemoryStore\": \"true\"}");
|
|
||||||
|
|
||||||
if (startParameters.ServerType == ServerType.IISNativeModule)
|
|
||||||
{
|
|
||||||
logger.LogInformation("Turning runAllManagedModulesForAllRequests=true in web.config.");
|
|
||||||
// Set runAllManagedModulesForAllRequests=true
|
|
||||||
var webConfig = Path.Combine(startParameters.ApplicationPath, "web.config");
|
|
||||||
var configuration = new XmlDocument();
|
|
||||||
configuration.LoadXml(File.ReadAllText(webConfig));
|
|
||||||
|
|
||||||
// https://github.com/aspnet/Helios/issues/77
|
|
||||||
var rammfarAttribute = configuration.CreateAttribute("runAllManagedModulesForAllRequests");
|
|
||||||
rammfarAttribute.Value = "true";
|
|
||||||
var modulesNode = configuration.CreateElement("modules");
|
|
||||||
modulesNode.Attributes.Append(rammfarAttribute);
|
|
||||||
var systemWebServerNode = configuration.CreateElement("system.webServer");
|
|
||||||
systemWebServerNode.AppendChild(modulesNode);
|
|
||||||
configuration.SelectSingleNode("//configuration").AppendChild(systemWebServerNode);
|
|
||||||
configuration.Save(webConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.LogInformation("Successfully finished IIS application directory setup.");
|
|
||||||
|
|
||||||
Thread.Sleep(1 * 1000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
DnuPublish(startParameters, logger);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DNX451
|
|
||||||
if (startParameters.ServerType == ServerType.IISNativeModule ||
|
|
||||||
startParameters.ServerType == ServerType.IIS)
|
|
||||||
{
|
|
||||||
startParameters.IISApplication = new IISApplication(startParameters, logger);
|
|
||||||
startParameters.IISApplication.SetupApplication();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (startParameters.ServerType == ServerType.IISExpress)
|
|
||||||
{
|
|
||||||
hostProcess = StartHeliosHost(startParameters, logger);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hostProcess = StartSelfHost(startParameters, logger);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Restore the DNX_DEFAULT_LIB after starting the host process
|
|
||||||
Environment.SetEnvironmentVariable("DNX_DEFAULT_LIB", backupRuntimeDefaultLibPath);
|
|
||||||
Environment.SetEnvironmentVariable("ASPNET_ENV", string.Empty);
|
|
||||||
return hostProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Process StartMonoHost(StartParameters startParameters, ILogger logger)
|
|
||||||
{
|
|
||||||
var path = Environment.GetEnvironmentVariable("PATH");
|
|
||||||
var runtimeBin = path.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries).
|
|
||||||
Where(c => c.Contains("dnx-mono")).FirstOrDefault();
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(runtimeBin))
|
|
||||||
{
|
|
||||||
throw new Exception("Runtime not detected on the machine.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startParameters.PublishApplicationBeforeStart)
|
|
||||||
{
|
|
||||||
// We use full path to runtime to pack.
|
|
||||||
startParameters.Runtime = new DirectoryInfo(runtimeBin).Parent.FullName;
|
|
||||||
DnuPublish(startParameters, logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Mono now supports --appbase
|
|
||||||
logger.LogInformation("Setting the --appbase to {0}", startParameters.ApplicationPath);
|
|
||||||
|
|
||||||
var bootstrapper = "dnx";
|
|
||||||
|
|
||||||
var commandName = startParameters.ServerType == ServerType.Kestrel ? "kestrel" : string.Empty;
|
|
||||||
logger.LogInformation("Executing command: {dnx} \"{appPath}\" {command}", bootstrapper, startParameters.ApplicationPath, commandName);
|
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = bootstrapper,
|
|
||||||
Arguments = string.Format("\"{0}\" {1}", startParameters.ApplicationPath, commandName),
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
RedirectStandardInput = true
|
|
||||||
};
|
|
||||||
|
|
||||||
var hostProcess = Process.Start(startInfo);
|
|
||||||
logger.LogInformation("Started {0}. Process Id : {1}", hostProcess.MainModule.FileName, hostProcess.Id);
|
|
||||||
|
|
||||||
if (hostProcess.HasExited)
|
|
||||||
{
|
|
||||||
logger.LogError("Host process {processName} exited with code {exitCode} or failed to start.", startInfo.FileName, hostProcess.ExitCode);
|
|
||||||
throw new Exception("Failed to start host");
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Process StartHeliosHost(StartParameters startParameters, ILogger logger)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(startParameters.ApplicationHostConfigTemplateContent))
|
|
||||||
{
|
|
||||||
startParameters.ApplicationHostConfigTemplateContent =
|
|
||||||
startParameters.ApplicationHostConfigTemplateContent.Replace("[ApplicationPhysicalPath]", Path.Combine(startParameters.ApplicationPath, "wwwroot"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!startParameters.PublishApplicationBeforeStart)
|
|
||||||
{
|
|
||||||
IISExpressHelper.CopyAspNetLoader(startParameters.ApplicationPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(startParameters.ApplicationHostConfigTemplateContent))
|
|
||||||
{
|
|
||||||
//Pass on the applicationhost.config to iis express. With this don't need to pass in the /path /port switches as they are in the applicationHost.config
|
|
||||||
//We take a copy of the original specified applicationHost.Config to prevent modifying the one in the repo.
|
|
||||||
|
|
||||||
var tempApplicationHostConfig = Path.GetTempFileName();
|
|
||||||
File.WriteAllText(tempApplicationHostConfig, startParameters.ApplicationHostConfigTemplateContent.Replace("[ApplicationPhysicalPath]", startParameters.ApplicationPath));
|
|
||||||
startParameters.ApplicationHostConfigLocation = tempApplicationHostConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
var webroot = startParameters.ApplicationPath;
|
|
||||||
if (!webroot.EndsWith("wwwroot"))
|
|
||||||
{
|
|
||||||
webroot = Path.Combine(webroot, "wwwroot");
|
|
||||||
}
|
|
||||||
|
|
||||||
var parameters = string.IsNullOrWhiteSpace(startParameters.ApplicationHostConfigLocation) ?
|
|
||||||
string.Format("/port:5001 /path:\"{0}\"", webroot) :
|
|
||||||
string.Format("/site:{0} /config:{1}", startParameters.SiteName, startParameters.ApplicationHostConfigLocation);
|
|
||||||
|
|
||||||
var iisExpressPath = IISExpressHelper.GetPath(startParameters.RuntimeArchitecture);
|
|
||||||
|
|
||||||
logger.LogInformation("Executing command : {iisExpress} {args}", iisExpressPath, parameters);
|
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = iisExpressPath,
|
|
||||||
Arguments = parameters,
|
|
||||||
UseShellExecute = true,
|
|
||||||
CreateNoWindow = true
|
|
||||||
};
|
|
||||||
|
|
||||||
// Work around for https://github.com/aspnet/dnx/issues/1515
|
|
||||||
string backup_Dnx_Packages = string.Empty;
|
|
||||||
if (startParameters.PublishWithNoSource)
|
|
||||||
{
|
|
||||||
backup_Dnx_Packages = Environment.GetEnvironmentVariable("DNX_PACKAGES");
|
|
||||||
Environment.SetEnvironmentVariable("DNX_PACKAGES", string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
var hostProcess = Process.Start(startInfo);
|
|
||||||
logger.LogInformation("Started iisexpress. Process Id : {processId}", hostProcess.Id);
|
|
||||||
|
|
||||||
if (startParameters.PublishWithNoSource)
|
|
||||||
{
|
|
||||||
// Roll back the change.
|
|
||||||
Environment.SetEnvironmentVariable("DNX_PACKAGES", backup_Dnx_Packages);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Process StartSelfHost(StartParameters startParameters, ILogger logger)
|
|
||||||
{
|
|
||||||
var commandName = startParameters.ServerType == ServerType.WebListener ? "web" : "kestrel";
|
|
||||||
logger.LogInformation("Executing dnx.exe --appbase {appPath} \"Microsoft.Framework.ApplicationHost\" {command}", startParameters.ApplicationPath, commandName);
|
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = "dnx.exe",
|
|
||||||
Arguments = string.Format("--appbase \"{0}\" \"Microsoft.Framework.ApplicationHost\" {1}", startParameters.ApplicationPath, commandName),
|
|
||||||
UseShellExecute = true,
|
|
||||||
CreateNoWindow = true
|
|
||||||
};
|
|
||||||
|
|
||||||
// Work around for https://github.com/aspnet/dnx/issues/1515
|
|
||||||
string backup_Dnx_Packages = string.Empty;
|
|
||||||
if (startParameters.PublishWithNoSource)
|
|
||||||
{
|
|
||||||
backup_Dnx_Packages = Environment.GetEnvironmentVariable("DNX_PACKAGES");
|
|
||||||
Environment.SetEnvironmentVariable("DNX_PACKAGES", string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
var hostProcess = Process.Start(startInfo);
|
|
||||||
|
|
||||||
if (startParameters.PublishWithNoSource)
|
|
||||||
{
|
|
||||||
// Roll back the change.
|
|
||||||
Environment.SetEnvironmentVariable("DNX_PACKAGES", backup_Dnx_Packages);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sometimes reading MainModule returns null if called immediately after starting process.
|
|
||||||
Thread.Sleep(1 * 1000);
|
|
||||||
|
|
||||||
if (hostProcess.HasExited)
|
|
||||||
{
|
|
||||||
logger.LogError("Host process {processName} exited with code {exitCode} or failed to start.", startInfo.FileName, hostProcess.ExitCode);
|
|
||||||
throw new Exception("Failed to start host");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
logger.LogInformation("Started {fileName}. Process Id : {processId}", hostProcess.MainModule.FileName, hostProcess.Id);
|
|
||||||
}
|
|
||||||
catch (Win32Exception win32Exception)
|
|
||||||
{
|
|
||||||
logger.LogWarning("Cannot access 64 bit modules from a 32 bit process. Failed with following message : {error}", win32Exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string SwitchPathToRuntimeFlavor(RuntimeFlavor runtimeFlavor, RuntimeArchitecture runtimeArchitecture, ILogger logger)
|
|
||||||
{
|
|
||||||
var runtimePath = Process.GetCurrentProcess().MainModule.FileName;
|
|
||||||
logger.LogInformation(string.Empty);
|
|
||||||
logger.LogInformation("Current runtime path is : {0}", runtimePath);
|
|
||||||
|
|
||||||
var replaceStr = new StringBuilder().
|
|
||||||
Append("dnx").
|
|
||||||
Append((runtimeFlavor == RuntimeFlavor.CoreClr) ? "-coreclr" : "-clr").
|
|
||||||
Append("-win").
|
|
||||||
Append((runtimeArchitecture == RuntimeArchitecture.x86) ? "-x86" : "-x64").
|
|
||||||
ToString();
|
|
||||||
|
|
||||||
runtimePath = Regex.Replace(runtimePath, "dnx-(clr|coreclr)-win-(x86|x64)", replaceStr, RegexOptions.IgnoreCase);
|
|
||||||
runtimePath = Path.GetDirectoryName(runtimePath);
|
|
||||||
|
|
||||||
// Tweak the %PATH% to the point to the right RUNTIMEFLAVOR.
|
|
||||||
Environment.SetEnvironmentVariable("PATH", runtimePath + ";" + Environment.GetEnvironmentVariable("PATH"));
|
|
||||||
|
|
||||||
var runtimeDirectoryInfo = new DirectoryInfo(runtimePath);
|
|
||||||
if (!runtimeDirectoryInfo.Exists)
|
|
||||||
{
|
|
||||||
throw new Exception(
|
|
||||||
string.Format("Requested runtime at location '{0}' does not exist. Please make sure it is installed before running test.",
|
|
||||||
runtimeDirectoryInfo.FullName));
|
|
||||||
}
|
|
||||||
|
|
||||||
var runtimeName = runtimeDirectoryInfo.Parent.Name;
|
|
||||||
logger.LogInformation(string.Empty);
|
|
||||||
logger.LogInformation("Changing to use runtime : {runtimeName}", runtimeName);
|
|
||||||
return runtimeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DnuPublish(StartParameters startParameters, ILogger logger, string publishRoot = null)
|
|
||||||
{
|
|
||||||
startParameters.PublishedApplicationRootPath = Path.Combine(publishRoot ?? Path.GetTempPath(), Guid.NewGuid().ToString());
|
|
||||||
|
|
||||||
var parameters =
|
|
||||||
string.Format(
|
|
||||||
"publish {0} -o {1} --runtime {2} {3}",
|
|
||||||
startParameters.ApplicationPath,
|
|
||||||
startParameters.PublishedApplicationRootPath,
|
|
||||||
startParameters.Runtime,
|
|
||||||
startParameters.PublishWithNoSource ? "--no-source" : string.Empty);
|
|
||||||
|
|
||||||
logger.LogInformation("Executing command dnu {args}", parameters);
|
|
||||||
|
|
||||||
var startInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = "dnu",
|
|
||||||
Arguments = parameters,
|
|
||||||
UseShellExecute = true,
|
|
||||||
CreateNoWindow = true
|
|
||||||
};
|
|
||||||
|
|
||||||
var hostProcess = Process.Start(startInfo);
|
|
||||||
hostProcess.WaitForExit(60 * 1000);
|
|
||||||
|
|
||||||
startParameters.ApplicationPath =
|
|
||||||
(startParameters.ServerType == ServerType.IISExpress ||
|
|
||||||
startParameters.ServerType == ServerType.IISNativeModule ||
|
|
||||||
startParameters.ServerType == ServerType.IIS) ?
|
|
||||||
Path.Combine(startParameters.PublishedApplicationRootPath, "wwwroot") :
|
|
||||||
Path.Combine(startParameters.PublishedApplicationRootPath, "approot", "src", "MusicStore");
|
|
||||||
|
|
||||||
logger.LogInformation("dnu publish finished with exit code : {exitCode}", hostProcess.ExitCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void CleanUpApplication(StartParameters startParameters, Process hostProcess, string musicStoreDbName, ILogger logger)
|
|
||||||
{
|
|
||||||
if (startParameters.ServerType == ServerType.IISNativeModule ||
|
|
||||||
startParameters.ServerType == ServerType.IIS)
|
|
||||||
{
|
|
||||||
#if DNX451
|
|
||||||
// Stop & delete the application pool.
|
|
||||||
if (startParameters.IISApplication != null)
|
|
||||||
{
|
|
||||||
startParameters.IISApplication.StopAndDeleteAppPool();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if (hostProcess != null && !hostProcess.HasExited)
|
|
||||||
{
|
|
||||||
//Shutdown the host process
|
|
||||||
hostProcess.Kill();
|
|
||||||
hostProcess.WaitForExit(5 * 1000);
|
|
||||||
if (!hostProcess.HasExited)
|
|
||||||
{
|
|
||||||
logger.LogWarning("Unable to terminate the host process with process Id '{processId}", hostProcess.Id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogInformation("Successfully terminated host process with process Id '{processId}'", hostProcess.Id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogWarning("Host process already exited or never started successfully.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Helpers.RunningOnMono)
|
|
||||||
{
|
|
||||||
//Mono uses InMemoryStore
|
|
||||||
DbUtils.DropDatabase(musicStoreDbName, logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(startParameters.ApplicationHostConfigLocation))
|
|
||||||
{
|
|
||||||
//Delete the temp applicationHostConfig that we created
|
|
||||||
if (File.Exists(startParameters.ApplicationHostConfigLocation))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.Delete(startParameters.ApplicationHostConfigLocation);
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
//Ignore delete failures - just write a log
|
|
||||||
logger.LogWarning("Failed to delete '{config}'. Exception : {exception}", startParameters.ApplicationHostConfigLocation, exception.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startParameters.PublishApplicationBeforeStart)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//We've originally published the application in a temp folder. We need to delete it.
|
|
||||||
Directory.Delete(startParameters.PublishedApplicationRootPath, true);
|
|
||||||
}
|
|
||||||
catch (Exception exception)
|
|
||||||
{
|
|
||||||
logger.LogWarning("Failed to delete directory : {error}", exception.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
namespace E2ETests
|
|
||||||
{
|
|
||||||
public enum RuntimeFlavor
|
|
||||||
{
|
|
||||||
DesktopClr,
|
|
||||||
CoreClr,
|
|
||||||
Mono
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using DeploymentHelpers;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
|
|
@ -16,29 +17,44 @@ namespace E2ETests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Retry(Action retryBlock, ILogger logger, int retryCount = 7)
|
public static string GetApplicationPath()
|
||||||
{
|
{
|
||||||
for (int retry = 0; retry < retryCount; retry++)
|
return Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "..", "..", "src", "MusicStore"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetInMemoryStoreForIIS(DeploymentParameters startParameters, ILogger logger)
|
||||||
|
{
|
||||||
|
if (startParameters.ServerType == ServerType.IIS
|
||||||
|
|| startParameters.ServerType == ServerType.IISNativeModule)
|
||||||
{
|
{
|
||||||
try
|
// Can't use localdb with IIS. Setting an override to use InMemoryStore.
|
||||||
{
|
logger.LogInformation("Creating configoverride.json file to override default config.");
|
||||||
logger.LogWarning("Retry count {retryCount}..", retry + 1);
|
var overrideConfig = Path.Combine(startParameters.ApplicationPath, "..", "approot", "src", "MusicStore", "configoverride.json");
|
||||||
retryBlock();
|
overrideConfig = Path.GetFullPath(overrideConfig);
|
||||||
break; //Went through successfully
|
File.WriteAllText(overrideConfig, "{\"UseInMemoryStore\": \"true\"}");
|
||||||
}
|
|
||||||
catch (AggregateException exception)
|
|
||||||
{
|
|
||||||
if (exception.InnerException is HttpRequestException
|
|
||||||
#if DNX451
|
|
||||||
|| exception.InnerException is WebException
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
logger.LogWarning("Failed to complete the request : {0}.", exception.Message);
|
|
||||||
Thread.Sleep(7 * 1000); //Wait for a while before retry.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void ThrowIfResponseStatusNotOk(HttpResponseMessage response, ILogger _logger)
|
||||||
|
{
|
||||||
|
if (response.StatusCode != HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
_logger.LogError(response.Content.ReadAsStringAsync().Result);
|
||||||
|
throw new Exception(string.Format("Received the above response with status code : {0}", response.StatusCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string PrefixBaseAddress(string url, ServerType serverType, string vDirName = null)
|
||||||
|
{
|
||||||
|
#if DNX451
|
||||||
|
url = (serverType == ServerType.IISNativeModule || serverType == ServerType.IIS) ?
|
||||||
|
string.Format(url, vDirName) :
|
||||||
|
string.Format(url, string.Empty);
|
||||||
|
#else
|
||||||
|
url = string.Format(url, string.Empty);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return url.Replace("//", "/").Replace("%2F%2F", "%2F").Replace("%2F/", "%2F");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
#if DNX451
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.Framework.Logging;
|
|
||||||
using Microsoft.Web.Administration;
|
|
||||||
|
|
||||||
namespace E2ETests
|
|
||||||
{
|
|
||||||
public class IISApplication
|
|
||||||
{
|
|
||||||
private const string WEBSITE_NAME = "MusicStore";
|
|
||||||
private const string NATIVE_MODULE_MANAGED_RUNTIME_VERSION = "vCoreFX";
|
|
||||||
|
|
||||||
private readonly ServerManager _serverManager = new ServerManager();
|
|
||||||
private readonly StartParameters _startParameters;
|
|
||||||
private readonly ILogger _logger;
|
|
||||||
private ApplicationPool _applicationPool;
|
|
||||||
private Application _application;
|
|
||||||
|
|
||||||
public string VirtualDirectoryName { get; set; }
|
|
||||||
|
|
||||||
public IISApplication(StartParameters startParameters, ILogger logger)
|
|
||||||
{
|
|
||||||
_startParameters = startParameters;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetupApplication()
|
|
||||||
{
|
|
||||||
VirtualDirectoryName = new DirectoryInfo(_startParameters.ApplicationPath).Parent.Name;
|
|
||||||
_applicationPool = CreateAppPool(VirtualDirectoryName);
|
|
||||||
_application = Website.Applications.Add("/" + VirtualDirectoryName, _startParameters.ApplicationPath);
|
|
||||||
_application.ApplicationPoolName = _applicationPool.Name;
|
|
||||||
_serverManager.CommitChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Site _website;
|
|
||||||
private Site Website
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
_website = _serverManager.Sites.Where(s => s.Name == WEBSITE_NAME).FirstOrDefault();
|
|
||||||
if (_website == null)
|
|
||||||
{
|
|
||||||
_website = _serverManager.Sites.Add(WEBSITE_NAME, Path.Combine(Environment.GetEnvironmentVariable("SystemDrive") + @"\", @"inetpub\wwwroot"), 5005);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _website;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ApplicationPool CreateAppPool(string appPoolName)
|
|
||||||
{
|
|
||||||
var applicationPool = _serverManager.ApplicationPools.Add(appPoolName);
|
|
||||||
if (_startParameters.ServerType == ServerType.IISNativeModule)
|
|
||||||
{
|
|
||||||
// Not assigning a runtime version will choose v4.0 default.
|
|
||||||
applicationPool.ManagedRuntimeVersion = NATIVE_MODULE_MANAGED_RUNTIME_VERSION;
|
|
||||||
}
|
|
||||||
applicationPool.Enable32BitAppOnWin64 = (_startParameters.RuntimeArchitecture == RuntimeArchitecture.x86);
|
|
||||||
_logger.LogInformation("Created {bit} application pool '{name}' with runtime version '{runtime}'.",
|
|
||||||
_startParameters.RuntimeArchitecture, applicationPool.Name,
|
|
||||||
applicationPool.ManagedRuntimeVersion ?? "default");
|
|
||||||
return applicationPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void StopAndDeleteAppPool()
|
|
||||||
{
|
|
||||||
_logger.LogInformation("Stopping application pool '{name}' and deleting application.", _applicationPool.Name);
|
|
||||||
_applicationPool.Stop();
|
|
||||||
// Remove the application from website.
|
|
||||||
_application = Website.Applications.Where(a => a.Path == _application.Path).FirstOrDefault();
|
|
||||||
Website.Applications.Remove(_application);
|
|
||||||
_serverManager.ApplicationPools.Remove(_serverManager.ApplicationPools[_applicationPool.Name]);
|
|
||||||
_serverManager.CommitChanges();
|
|
||||||
_logger.LogInformation("Successfully stopped application pool '{name}' and deleted application from IIS.", _applicationPool.Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using Microsoft.Framework.Runtime;
|
|
||||||
using Microsoft.Framework.Runtime.Infrastructure;
|
|
||||||
|
|
||||||
namespace E2ETests
|
|
||||||
{
|
|
||||||
public class IISExpressHelper
|
|
||||||
{
|
|
||||||
public static string GetPath(RuntimeArchitecture architecture)
|
|
||||||
{
|
|
||||||
// Get path to program files
|
|
||||||
var iisExpressPath = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "IIS Express", "iisexpress.exe");
|
|
||||||
|
|
||||||
// Get path to 64 bit of IIS Express
|
|
||||||
if (architecture == RuntimeArchitecture.amd64)
|
|
||||||
{
|
|
||||||
iisExpressPath = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"), "IIS Express", "iisexpress.exe");
|
|
||||||
|
|
||||||
// If process is 32 bit, the path points to x86. Replace path to point to x64
|
|
||||||
iisExpressPath = IntPtr.Size == 8 ? iisExpressPath : iisExpressPath.Replace(" (x86)", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!File.Exists(iisExpressPath))
|
|
||||||
{
|
|
||||||
throw new Exception("Unable to find IISExpress on the machine");
|
|
||||||
}
|
|
||||||
|
|
||||||
return iisExpressPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void CopyAspNetLoader(string applicationPath)
|
|
||||||
{
|
|
||||||
var libraryManager = (ILibraryManager)CallContextServiceLocator.Locator.ServiceProvider.GetService(typeof(ILibraryManager));
|
|
||||||
var interopLibrary = libraryManager.GetLibraryInformation("Microsoft.AspNet.Loader.IIS.Interop");
|
|
||||||
|
|
||||||
var aspNetLoaderSrcPath = Path.Combine(interopLibrary.Path, "tools", "AspNet.Loader.dll");
|
|
||||||
var aspNetLoaderDestPath = Path.Combine(applicationPath, "wwwroot", "bin", "AspNet.Loader.dll");
|
|
||||||
|
|
||||||
// Create bin directory if it does not exist.
|
|
||||||
Directory.CreateDirectory(new DirectoryInfo(aspNetLoaderDestPath).Parent.FullName);
|
|
||||||
|
|
||||||
if (!File.Exists(aspNetLoaderDestPath))
|
|
||||||
{
|
|
||||||
File.Copy(aspNetLoaderSrcPath, aspNetLoaderDestPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
namespace E2ETests
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Summary description for StartParameters
|
|
||||||
/// </summary>
|
|
||||||
public class StartParameters
|
|
||||||
{
|
|
||||||
public ServerType ServerType { get; set; }
|
|
||||||
|
|
||||||
public RuntimeFlavor RuntimeFlavor { get; set; }
|
|
||||||
|
|
||||||
public RuntimeArchitecture RuntimeArchitecture { get; set; }
|
|
||||||
|
|
||||||
public string EnvironmentName { get; set; }
|
|
||||||
|
|
||||||
public string ApplicationHostConfigTemplateContent { get; set; }
|
|
||||||
|
|
||||||
public string ApplicationHostConfigLocation { get; set; }
|
|
||||||
|
|
||||||
public string SiteName { get; set; }
|
|
||||||
|
|
||||||
public string ApplicationPath { get; set; }
|
|
||||||
|
|
||||||
public bool PublishApplicationBeforeStart { get; set; }
|
|
||||||
|
|
||||||
public string PublishedApplicationRootPath { get; set; }
|
|
||||||
|
|
||||||
public bool PublishWithNoSource { get; set; }
|
|
||||||
|
|
||||||
public string Runtime { get; set; }
|
|
||||||
|
|
||||||
#if DNX451
|
|
||||||
public IISApplication IISApplication { get; set; }
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -9,15 +9,15 @@ using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
public partial class Validator
|
||||||
{
|
{
|
||||||
private void LoginWithFacebook()
|
public void LoginWithFacebook()
|
||||||
{
|
{
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
var response = _httpClient.GetAsync("Account/Login").Result;
|
var response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation("Signing in with Facebook account");
|
_logger.LogInformation("Signing in with Facebook account");
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -33,16 +33,16 @@ namespace E2ETests
|
||||||
var queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query));
|
var queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query));
|
||||||
Assert.Equal<string>("code", queryItems["response_type"]);
|
Assert.Equal<string>("code", queryItems["response_type"]);
|
||||||
Assert.Equal<string>("[AppId]", queryItems["client_id"]);
|
Assert.Equal<string>("[AppId]", queryItems["client_id"]);
|
||||||
Assert.Equal<string>(_applicationBaseUrl + "signin-facebook", queryItems["redirect_uri"]);
|
Assert.Equal<string>(_deploymentResult.ApplicationBaseUri + "signin-facebook", queryItems["redirect_uri"]);
|
||||||
Assert.Equal<string>("email,read_friendlists,user_checkins", queryItems["scope"]);
|
Assert.Equal<string>("email,read_friendlists,user_checkins", queryItems["scope"]);
|
||||||
Assert.Equal<string>("ValidStateData", queryItems["state"]);
|
Assert.Equal<string>("ValidStateData", queryItems["state"]);
|
||||||
Assert.Equal<string>("custom", queryItems["custom_redirect_uri"]);
|
Assert.Equal<string>("custom", queryItems["custom_redirect_uri"]);
|
||||||
//Check for the correlation cookie
|
//Check for the correlation cookie
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Correlation.Facebook"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Correlation.Facebook"));
|
||||||
|
|
||||||
//This is just to generate a correlation cookie. Previous step would generate this cookie, but we have reset the handler now.
|
//This is just to generate a correlation cookie. Previous step would generate this cookie, but we have reset the handler now.
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
response = _httpClient.GetAsync("Account/Login").Result;
|
response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
@ -58,15 +58,15 @@ namespace E2ETests
|
||||||
|
|
||||||
//Post a message to the Facebook middleware
|
//Post a message to the Facebook middleware
|
||||||
response = _httpClient.GetAsync("signin-facebook?code=ValidCode&state=ValidStateData").Result;
|
response = _httpClient.GetAsync("signin-facebook?code=ValidCode&state=ValidStateData").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
//Correlation cookie not getting cleared after successful signin?
|
//Correlation cookie not getting cleared after successful signin?
|
||||||
if (!Helpers.RunningOnMono)
|
if (!Helpers.RunningOnMono)
|
||||||
{
|
{
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Correlation.Facebook"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Correlation.Facebook"));
|
||||||
}
|
}
|
||||||
Assert.Equal(_applicationBaseUrl + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
Assert.Equal(_deploymentResult.ApplicationBaseUri + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
Assert.Contains("AspnetvnextTest@test.com", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("AspnetvnextTest@test.com", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
formParameters = new List<KeyValuePair<string, string>>
|
formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -77,14 +77,14 @@ namespace E2ETests
|
||||||
|
|
||||||
content = new FormUrlEncodedContent(formParameters.ToArray());
|
content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
Assert.Contains(string.Format("Hello {0}!", "AspnetvnextTest@test.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(string.Format("Hello {0}!", "AspnetvnextTest@test.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
//Verify cookie sent
|
//Verify cookie sent
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
||||||
_logger.LogInformation("Successfully signed in with user '{email}'", "AspnetvnextTest@test.com");
|
_logger.LogInformation("Successfully signed in with user '{email}'", "AspnetvnextTest@test.com");
|
||||||
|
|
||||||
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,15 @@ using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
public partial class Validator
|
||||||
{
|
{
|
||||||
private void LoginWithGoogle()
|
public void LoginWithGoogle()
|
||||||
{
|
{
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
var response = _httpClient.GetAsync("Account/Login").Result;
|
var response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation("Signing in with Google account");
|
_logger.LogInformation("Signing in with Google account");
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -34,16 +34,16 @@ namespace E2ETests
|
||||||
Assert.Equal<string>("code", queryItems["response_type"]);
|
Assert.Equal<string>("code", queryItems["response_type"]);
|
||||||
Assert.Equal<string>("offline", queryItems["access_type"]);
|
Assert.Equal<string>("offline", queryItems["access_type"]);
|
||||||
Assert.Equal<string>("[ClientId]", queryItems["client_id"]);
|
Assert.Equal<string>("[ClientId]", queryItems["client_id"]);
|
||||||
Assert.Equal<string>(_applicationBaseUrl + "signin-google", queryItems["redirect_uri"]);
|
Assert.Equal<string>(_deploymentResult.ApplicationBaseUri + "signin-google", queryItems["redirect_uri"]);
|
||||||
Assert.Equal<string>("openid profile email", queryItems["scope"]);
|
Assert.Equal<string>("openid profile email", queryItems["scope"]);
|
||||||
Assert.Equal<string>("ValidStateData", queryItems["state"]);
|
Assert.Equal<string>("ValidStateData", queryItems["state"]);
|
||||||
Assert.Equal<string>("custom", queryItems["custom_redirect_uri"]);
|
Assert.Equal<string>("custom", queryItems["custom_redirect_uri"]);
|
||||||
//Check for the correlation cookie
|
//Check for the correlation cookie
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Correlation.Google"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Correlation.Google"));
|
||||||
|
|
||||||
//This is just to generate a correlation cookie. Previous step would generate this cookie, but we have reset the handler now.
|
//This is just to generate a correlation cookie. Previous step would generate this cookie, but we have reset the handler now.
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
response = _httpClient.GetAsync("Account/Login").Result;
|
response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
@ -59,15 +59,15 @@ namespace E2ETests
|
||||||
|
|
||||||
//Post a message to the Google middleware
|
//Post a message to the Google middleware
|
||||||
response = _httpClient.GetAsync("signin-google?code=ValidCode&state=ValidStateData").Result;
|
response = _httpClient.GetAsync("signin-google?code=ValidCode&state=ValidStateData").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
//Correlation cookie not getting cleared after successful signin?
|
//Correlation cookie not getting cleared after successful signin?
|
||||||
if (!Helpers.RunningOnMono)
|
if (!Helpers.RunningOnMono)
|
||||||
{
|
{
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Correlation.Google"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Correlation.Google"));
|
||||||
}
|
}
|
||||||
Assert.Equal(_applicationBaseUrl + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
Assert.Equal(_deploymentResult.ApplicationBaseUri + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
Assert.Contains("AspnetvnextTest@gmail.com", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("AspnetvnextTest@gmail.com", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
formParameters = new List<KeyValuePair<string, string>>
|
formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -78,14 +78,14 @@ namespace E2ETests
|
||||||
|
|
||||||
content = new FormUrlEncodedContent(formParameters.ToArray());
|
content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
Assert.Contains(string.Format("Hello {0}!", "AspnetvnextTest@gmail.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(string.Format("Hello {0}!", "AspnetvnextTest@gmail.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
//Verify cookie sent
|
//Verify cookie sent
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
||||||
_logger.LogInformation("Successfully signed in with user '{email}'", "AspnetvnextTest@gmail.com");
|
_logger.LogInformation("Successfully signed in with user '{email}'", "AspnetvnextTest@gmail.com");
|
||||||
|
|
||||||
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,15 @@ using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
public partial class Validator
|
||||||
{
|
{
|
||||||
private void LoginWithMicrosoftAccount()
|
public void LoginWithMicrosoftAccount()
|
||||||
{
|
{
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
var response = _httpClient.GetAsync("Account/Login").Result;
|
var response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation("Signing in with Microsoft account");
|
_logger.LogInformation("Signing in with Microsoft account");
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -33,17 +33,17 @@ namespace E2ETests
|
||||||
var queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query));
|
var queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query));
|
||||||
Assert.Equal<string>("code", queryItems["response_type"]);
|
Assert.Equal<string>("code", queryItems["response_type"]);
|
||||||
Assert.Equal<string>("[ClientId]", queryItems["client_id"]);
|
Assert.Equal<string>("[ClientId]", queryItems["client_id"]);
|
||||||
Assert.Equal<string>(_applicationBaseUrl + "signin-microsoft", queryItems["redirect_uri"]);
|
Assert.Equal<string>(_deploymentResult.ApplicationBaseUri + "signin-microsoft", queryItems["redirect_uri"]);
|
||||||
Assert.Equal<string>("wl.basic wl.signin", queryItems["scope"]);
|
Assert.Equal<string>("wl.basic wl.signin", queryItems["scope"]);
|
||||||
Assert.Equal<string>("ValidStateData", queryItems["state"]);
|
Assert.Equal<string>("ValidStateData", queryItems["state"]);
|
||||||
Assert.Equal<string>("custom", queryItems["custom_redirect_uri"]);
|
Assert.Equal<string>("custom", queryItems["custom_redirect_uri"]);
|
||||||
|
|
||||||
//Check for the correlation cookie
|
//Check for the correlation cookie
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Correlation.Microsoft"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Correlation.Microsoft"));
|
||||||
|
|
||||||
//This is just to generate a correlation cookie. Previous step would generate this cookie, but we have reset the handler now.
|
//This is just to generate a correlation cookie. Previous step would generate this cookie, but we have reset the handler now.
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
response = _httpClient.GetAsync("Account/Login").Result;
|
response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
@ -59,15 +59,15 @@ namespace E2ETests
|
||||||
|
|
||||||
//Post a message to the MicrosoftAccount middleware
|
//Post a message to the MicrosoftAccount middleware
|
||||||
response = _httpClient.GetAsync("signin-microsoft?code=ValidCode&state=ValidStateData").Result;
|
response = _httpClient.GetAsync("signin-microsoft?code=ValidCode&state=ValidStateData").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
//Correlation cookie not getting cleared after successful signin?
|
//Correlation cookie not getting cleared after successful signin?
|
||||||
if (!Helpers.RunningOnMono)
|
if (!Helpers.RunningOnMono)
|
||||||
{
|
{
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Correlation.Microsoft"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Correlation.Microsoft"));
|
||||||
}
|
}
|
||||||
Assert.Equal(_applicationBaseUrl + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
Assert.Equal(_deploymentResult.ApplicationBaseUri + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
|
|
||||||
formParameters = new List<KeyValuePair<string, string>>
|
formParameters = new List<KeyValuePair<string, string>>
|
||||||
{
|
{
|
||||||
|
|
@ -77,14 +77,14 @@ namespace E2ETests
|
||||||
|
|
||||||
content = new FormUrlEncodedContent(formParameters.ToArray());
|
content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
Assert.Contains(string.Format("Hello {0}!", "microsoft@test.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(string.Format("Hello {0}!", "microsoft@test.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
//Verify cookie sent
|
//Verify cookie sent
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
||||||
_logger.LogInformation("Successfully signed in with user '{email}'", "microsoft@test.com");
|
_logger.LogInformation("Successfully signed in with user '{email}'", "microsoft@test.com");
|
||||||
|
|
||||||
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
||||||
|
|
|
||||||
|
|
@ -9,15 +9,15 @@ using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
public partial class Validator
|
||||||
{
|
{
|
||||||
private void LoginWithOpenIdConnect()
|
public void LoginWithOpenIdConnect()
|
||||||
{
|
{
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
var response = _httpClient.GetAsync("Account/Login").Result;
|
var response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation("Signing in with OpenIdConnect account");
|
_logger.LogInformation("Signing in with OpenIdConnect account");
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -37,12 +37,12 @@ namespace E2ETests
|
||||||
Assert.Equal<string>("openid profile", queryItems["scope"]);
|
Assert.Equal<string>("openid profile", queryItems["scope"]);
|
||||||
Assert.Equal<string>("OpenIdConnect.AuthenticationProperties=ValidStateData", queryItems["state"]);
|
Assert.Equal<string>("OpenIdConnect.AuthenticationProperties=ValidStateData", queryItems["state"]);
|
||||||
Assert.NotNull(queryItems["nonce"]);
|
Assert.NotNull(queryItems["nonce"]);
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.OpenIdConnect.Nonce.protectedString"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.OpenIdConnect.Nonce.protectedString"));
|
||||||
|
|
||||||
// This is just enable the auto-redirect.
|
// This is just enable the auto-redirect.
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
_httpClientHandler.CookieContainer.Add(new Uri(_applicationBaseUrl), new Cookie(".AspNet.OpenIdConnect.Nonce.protectedString", "N"));
|
_httpClientHandler.CookieContainer.Add(new Uri(_deploymentResult.ApplicationBaseUri), new Cookie(".AspNet.OpenIdConnect.Nonce.protectedString", "N"));
|
||||||
|
|
||||||
//Post a message to the OpenIdConnect middleware
|
//Post a message to the OpenIdConnect middleware
|
||||||
var token = new List<KeyValuePair<string, string>>
|
var token = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -54,9 +54,9 @@ namespace E2ETests
|
||||||
};
|
};
|
||||||
|
|
||||||
response = _httpClient.PostAsync(string.Empty, new FormUrlEncodedContent(token.ToArray())).Result;
|
response = _httpClient.PostAsync(string.Empty, new FormUrlEncodedContent(token.ToArray())).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Equal(_applicationBaseUrl + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
Assert.Equal(_deploymentResult.ApplicationBaseUri + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
|
|
||||||
formParameters = new List<KeyValuePair<string, string>>
|
formParameters = new List<KeyValuePair<string, string>>
|
||||||
{
|
{
|
||||||
|
|
@ -66,14 +66,14 @@ namespace E2ETests
|
||||||
|
|
||||||
content = new FormUrlEncodedContent(formParameters.ToArray());
|
content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
Assert.Contains(string.Format("Hello {0}!", "User3@aspnettest.onmicrosoft.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(string.Format("Hello {0}!", "User3@aspnettest.onmicrosoft.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
//Verify cookie sent
|
//Verify cookie sent
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
||||||
_logger.LogInformation("Successfully signed in with user '{email}'", "User3@aspnettest.onmicrosoft.com");
|
_logger.LogInformation("Successfully signed in with user '{email}'", "User3@aspnettest.onmicrosoft.com");
|
||||||
|
|
||||||
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
||||||
|
|
@ -85,7 +85,7 @@ namespace E2ETests
|
||||||
|
|
||||||
_logger.LogInformation("Verifying the OpenIdConnect logout flow..");
|
_logger.LogInformation("Verifying the OpenIdConnect logout flow..");
|
||||||
response = _httpClient.GetAsync(string.Empty).Result;
|
response = _httpClient.GetAsync(string.Empty).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
ValidateLayoutPage(responseContent);
|
ValidateLayoutPage(responseContent);
|
||||||
formParameters = new List<KeyValuePair<string, string>>
|
formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -96,16 +96,16 @@ namespace E2ETests
|
||||||
content = new FormUrlEncodedContent(formParameters.ToArray());
|
content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
// Need a non-redirecting handler
|
// Need a non-redirecting handler
|
||||||
var handler = new HttpClientHandler() { AllowAutoRedirect = false };
|
var handler = new HttpClientHandler() { AllowAutoRedirect = false };
|
||||||
handler.CookieContainer.Add(new Uri(_applicationBaseUrl), _httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)));
|
handler.CookieContainer.Add(new Uri(_deploymentResult.ApplicationBaseUri), _httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)));
|
||||||
_httpClient = new HttpClient(handler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(handler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
response = _httpClient.PostAsync("Account/LogOff", content).Result;
|
response = _httpClient.PostAsync("Account/LogOff", content).Result;
|
||||||
Assert.Null(handler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.Null(handler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
Assert.Equal<string>(
|
Assert.Equal<string>(
|
||||||
"https://login.windows.net/4afbc689-805b-48cf-a24c-d4aa3248a248/oauth2/logout",
|
"https://login.windows.net/4afbc689-805b-48cf-a24c-d4aa3248a248/oauth2/logout",
|
||||||
response.Headers.Location.AbsoluteUri.Replace(response.Headers.Location.Query, string.Empty));
|
response.Headers.Location.AbsoluteUri.Replace(response.Headers.Location.Query, string.Empty));
|
||||||
queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query));
|
queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query));
|
||||||
Assert.Equal<string>(_applicationBaseUrl + "Account/Login", queryItems["post_logout_redirect_uri"]);
|
Assert.Equal<string>(_deploymentResult.ApplicationBaseUri + "Account/Login", queryItems["post_logout_redirect_uri"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,15 +12,15 @@ namespace E2ETests
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Summary description for TwitterLoginScenarios
|
/// Summary description for TwitterLoginScenarios
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class SmokeTests
|
public partial class Validator
|
||||||
{
|
{
|
||||||
private void LoginWithTwitter()
|
public void LoginWithTwitter()
|
||||||
{
|
{
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = false };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
var response = _httpClient.GetAsync("Account/Login").Result;
|
var response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation("Signing in with Twitter account");
|
_logger.LogInformation("Signing in with Twitter account");
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -37,11 +37,11 @@ namespace E2ETests
|
||||||
Assert.Equal<string>("custom", queryItems["custom_redirect_uri"]);
|
Assert.Equal<string>("custom", queryItems["custom_redirect_uri"]);
|
||||||
Assert.Equal<string>("valid_oauth_token", queryItems["oauth_token"]);
|
Assert.Equal<string>("valid_oauth_token", queryItems["oauth_token"]);
|
||||||
//Check for the correlation cookie
|
//Check for the correlation cookie
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl))["__TwitterState"]);
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri))["__TwitterState"]);
|
||||||
|
|
||||||
//This is just to generate a correlation cookie. Previous step would generate this cookie, but we have reset the handler now.
|
//This is just to generate a correlation cookie. Previous step would generate this cookie, but we have reset the handler now.
|
||||||
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
_httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
|
|
||||||
response = _httpClient.GetAsync("Account/Login").Result;
|
response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
@ -57,15 +57,15 @@ namespace E2ETests
|
||||||
|
|
||||||
//Post a message to the Facebook middleware
|
//Post a message to the Facebook middleware
|
||||||
response = _httpClient.GetAsync("signin-twitter?oauth_token=valid_oauth_token&oauth_verifier=valid_oauth_verifier").Result;
|
response = _httpClient.GetAsync("signin-twitter?oauth_token=valid_oauth_token&oauth_verifier=valid_oauth_verifier").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
//Check correlation cookie not getting cleared after successful signin
|
//Check correlation cookie not getting cleared after successful signin
|
||||||
if (!Helpers.RunningOnMono)
|
if (!Helpers.RunningOnMono)
|
||||||
{
|
{
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl))["__TwitterState"]);
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri))["__TwitterState"]);
|
||||||
}
|
}
|
||||||
Assert.Equal(_applicationBaseUrl + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
Assert.Equal(_deploymentResult.ApplicationBaseUri + "Account/ExternalLoginCallback?ReturnUrl=%2F", response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
//Twitter does not give back the email claim for some reason.
|
//Twitter does not give back the email claim for some reason.
|
||||||
//Assert.Contains("AspnetvnextTest@gmail.com", responseContent, StringComparison.OrdinalIgnoreCase);
|
//Assert.Contains("AspnetvnextTest@gmail.com", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
|
@ -77,14 +77,14 @@ namespace E2ETests
|
||||||
|
|
||||||
content = new FormUrlEncodedContent(formParameters.ToArray());
|
content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
Assert.Contains(string.Format("Hello {0}!", "twitter@test.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(string.Format("Hello {0}!", "twitter@test.com"), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
//Verify cookie sent
|
//Verify cookie sent
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin"));
|
||||||
_logger.LogInformation("Successfully signed in with user '{email}'", "twitter@test.com");
|
_logger.LogInformation("Successfully signed in with user '{email}'", "twitter@test.com");
|
||||||
|
|
||||||
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
_logger.LogInformation("Verifying if the middleware notifications were fired");
|
||||||
|
|
|
||||||
|
|
@ -4,45 +4,46 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using DeploymentHelpers;
|
||||||
using Microsoft.AspNet.SignalR.Client;
|
using Microsoft.AspNet.SignalR.Client;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
public partial class Validator
|
||||||
{
|
{
|
||||||
private void VerifyStaticContentServed()
|
private HttpClient _httpClient;
|
||||||
|
private HttpClientHandler _httpClientHandler;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly DeploymentResult _deploymentResult;
|
||||||
|
|
||||||
|
public Validator(
|
||||||
|
HttpClient httpClient,
|
||||||
|
HttpClientHandler httpClientHandler,
|
||||||
|
ILogger logger,
|
||||||
|
DeploymentResult deploymentResult)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Validating if static contents are served..");
|
_httpClient = httpClient;
|
||||||
_logger.LogInformation("Fetching favicon.ico..");
|
_httpClientHandler = httpClientHandler;
|
||||||
var response = _httpClient.GetAsync("favicon.ico").Result;
|
_logger = logger;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
_deploymentResult = deploymentResult;
|
||||||
_logger.LogInformation("Etag received: {etag}", response.Headers.ETag.Tag);
|
|
||||||
|
|
||||||
//Check if you receive a NotModified on sending an etag
|
|
||||||
_logger.LogInformation("Sending an IfNoneMatch header with e-tag");
|
|
||||||
_httpClient.DefaultRequestHeaders.IfNoneMatch.Add(response.Headers.ETag);
|
|
||||||
response = _httpClient.GetAsync("favicon.ico").Result;
|
|
||||||
Assert.Equal(HttpStatusCode.NotModified, response.StatusCode);
|
|
||||||
_httpClient.DefaultRequestHeaders.IfNoneMatch.Clear();
|
|
||||||
_logger.LogInformation("Successfully received a NotModified status");
|
|
||||||
|
|
||||||
_logger.LogInformation("Fetching /Content/bootstrap.css..");
|
|
||||||
response = _httpClient.GetAsync("Content/bootstrap.css").Result;
|
|
||||||
ThrowIfResponseStatusNotOk(response);
|
|
||||||
_logger.LogInformation("Verified static contents are served successfully");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VerifyHomePage(HttpResponseMessage response, string responseContent, bool useNtlmAuthentication = false)
|
public void VerifyHomePage(
|
||||||
|
HttpResponseMessage response,
|
||||||
|
bool useNtlmAuthentication = false)
|
||||||
{
|
{
|
||||||
// This seems to not print anything if the successive Assert fails.
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
//_logger.WriteVerbose("Home page content : {0}", responseContent);
|
|
||||||
|
if (response.StatusCode != HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Home page content : {0}", responseContent);
|
||||||
|
}
|
||||||
|
|
||||||
Console.WriteLine("Home page content : {0}", responseContent);
|
|
||||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
ValidateLayoutPage(responseContent);
|
ValidateLayoutPage(responseContent);
|
||||||
Assert.Contains(PrefixBaseAddress("<a href=\"/{0}/Store/Details/"), responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(Helpers.PrefixBaseAddress("<a href=\"/{0}/Store/Details/", _deploymentResult.DeploymentParameters.ServerType), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("<title>Home Page – ASP.NET MVC Music Store</title>", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("<title>Home Page – ASP.NET MVC Music Store</title>", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
if (!useNtlmAuthentication)
|
if (!useNtlmAuthentication)
|
||||||
|
|
@ -57,24 +58,77 @@ namespace E2ETests
|
||||||
_logger.LogInformation("Application initialization successful.");
|
_logger.LogInformation("Application initialization successful.");
|
||||||
|
|
||||||
_logger.LogInformation("Application runtime information");
|
_logger.LogInformation("Application runtime information");
|
||||||
var runtimeResponse = _httpClient.GetAsync("runtimeinfo").Result;
|
//var runtimeResponse = _httpClient.GetAsync("runtimeinfo").Result;
|
||||||
|
|
||||||
if (_startParameters.RuntimeFlavor != RuntimeFlavor.CoreClr)
|
// https://github.com/aspnet/Diagnostics/issues/108
|
||||||
|
if (_deploymentResult.DeploymentParameters.RuntimeFlavor != RuntimeFlavor.coreclr)
|
||||||
{
|
{
|
||||||
// Runtime info middleware broken on coreclr.
|
//Helpers.ThrowIfResponseStatusNotOk(runtimeResponse, _logger);
|
||||||
ThrowIfResponseStatusNotOk(runtimeResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var runtimeInfo = runtimeResponse.Content.ReadAsStringAsync().Result;
|
//var runtimeInfo = runtimeResponse.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation(runtimeInfo);
|
//_logger.LogInformation(runtimeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void VerifyNtlmHomePage(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
VerifyHomePage(response, useNtlmAuthentication: true);
|
||||||
|
|
||||||
|
var homePageContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
|
//Check if the user name appears in the page
|
||||||
|
Assert.Contains(
|
||||||
|
string.Format("{0}\\{1}", Environment.GetEnvironmentVariable("USERDOMAIN"), Environment.GetEnvironmentVariable("USERNAME")),
|
||||||
|
homePageContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ValidateLayoutPage(string responseContent)
|
||||||
|
{
|
||||||
|
Assert.Contains("ASP.NET MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
Assert.Contains(Helpers.PrefixBaseAddress("<li><a href=\"/{0}\">Home</a></li>", _deploymentResult.DeploymentParameters.ServerType), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
Assert.Contains(Helpers.PrefixBaseAddress("<a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"/{0}/Store\">Store <b class=\"caret\"></b></a>", _deploymentResult.DeploymentParameters.ServerType), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
Assert.Contains("<ul class=\"dropdown-menu\">", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
Assert.Contains("<li class=\"divider\"></li>", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void VerifyStaticContentServed()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Validating if static contents are served..");
|
||||||
|
_logger.LogInformation("Fetching favicon.ico..");
|
||||||
|
var response = _httpClient.GetAsync("favicon.ico").Result;
|
||||||
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
|
_logger.LogInformation("Etag received: {etag}", response.Headers.ETag.Tag);
|
||||||
|
|
||||||
|
//Check if you receive a NotModified on sending an etag
|
||||||
|
_logger.LogInformation("Sending an IfNoneMatch header with e-tag");
|
||||||
|
_httpClient.DefaultRequestHeaders.IfNoneMatch.Add(response.Headers.ETag);
|
||||||
|
response = _httpClient.GetAsync("favicon.ico").Result;
|
||||||
|
Assert.Equal(HttpStatusCode.NotModified, response.StatusCode);
|
||||||
|
_httpClient.DefaultRequestHeaders.IfNoneMatch.Clear();
|
||||||
|
_logger.LogInformation("Successfully received a NotModified status");
|
||||||
|
|
||||||
|
_logger.LogInformation("Fetching /Content/bootstrap.css..");
|
||||||
|
response = _httpClient.GetAsync("Content/bootstrap.css").Result;
|
||||||
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
|
_logger.LogInformation("Verified static contents are served successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AccessStoreWithPermissions()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Trying to access the store inventory..");
|
||||||
|
var response = _httpClient.GetAsync("Admin/StoreManager/").Result;
|
||||||
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
Assert.Equal<string>(_deploymentResult.ApplicationBaseUri + "Admin/StoreManager/", response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
|
_logger.LogInformation("Successfully acccessed the store inventory");
|
||||||
}
|
}
|
||||||
|
|
||||||
private string PrefixBaseAddress(string url)
|
private string PrefixBaseAddress(string url)
|
||||||
{
|
{
|
||||||
#if DNX451
|
#if DNX451
|
||||||
url = (_startParameters.ServerType == ServerType.IISNativeModule ||
|
url = (_deploymentResult.DeploymentParameters.ServerType == ServerType.IISNativeModule ||
|
||||||
_startParameters.ServerType == ServerType.IIS) ?
|
_deploymentResult.DeploymentParameters.ServerType == ServerType.IIS) ?
|
||||||
string.Format(url, _startParameters.IISApplication.VirtualDirectoryName) :
|
string.Format(url, new Uri(_deploymentResult.ApplicationBaseUri).Segments[1].TrimEnd('/')) :
|
||||||
string.Format(url, string.Empty);
|
string.Format(url, string.Empty);
|
||||||
#else
|
#else
|
||||||
url = string.Format(url, string.Empty);
|
url = string.Format(url, string.Empty);
|
||||||
|
|
@ -83,43 +137,24 @@ namespace E2ETests
|
||||||
return url.Replace("//", "/").Replace("%2F%2F", "%2F").Replace("%2F/", "%2F");
|
return url.Replace("//", "/").Replace("%2F%2F", "%2F").Replace("%2F/", "%2F");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateLayoutPage(string responseContent)
|
public void AccessStoreWithoutPermissions(string email = null)
|
||||||
{
|
|
||||||
Assert.Contains("ASP.NET MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase);
|
|
||||||
Assert.Contains(PrefixBaseAddress("<li><a href=\"/{0}\">Home</a></li>"), responseContent, StringComparison.OrdinalIgnoreCase);
|
|
||||||
Assert.Contains(PrefixBaseAddress("<a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"/{0}/Store\">Store <b class=\"caret\"></b></a>"), responseContent, StringComparison.OrdinalIgnoreCase);
|
|
||||||
Assert.Contains("<ul class=\"dropdown-menu\">", responseContent, StringComparison.OrdinalIgnoreCase);
|
|
||||||
Assert.Contains("<li class=\"divider\"></li>", responseContent, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AccessStoreWithoutPermissions(string email = null)
|
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Trying to access StoreManager that needs ManageStore claim with the current user : {email}", email ?? "Anonymous");
|
_logger.LogInformation("Trying to access StoreManager that needs ManageStore claim with the current user : {email}", email ?? "Anonymous");
|
||||||
var response = _httpClient.GetAsync("Admin/StoreManager/").Result;
|
var response = _httpClient.GetAsync("Admin/StoreManager/").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
ValidateLayoutPage(responseContent);
|
ValidateLayoutPage(responseContent);
|
||||||
Assert.Contains("<title>Log in – ASP.NET MVC Music Store</title>", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("<title>Log in – ASP.NET MVC Music Store</title>", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("<h4>Use a local account to log in.</h4>", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("<h4>Use a local account to log in.</h4>", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Equal<string>(_applicationBaseUrl + PrefixBaseAddress("Account/Login?ReturnUrl=%2F{0}%2FAdmin%2FStoreManager%2F"), response.RequestMessage.RequestUri.AbsoluteUri);
|
Assert.Equal<string>(_deploymentResult.ApplicationBaseUri + PrefixBaseAddress("Account/Login?ReturnUrl=%2F{0}%2FAdmin%2FStoreManager%2F"), response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
_logger.LogInformation("Redirected to login page as expected.");
|
_logger.LogInformation("Redirected to login page as expected.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AccessStoreWithPermissions()
|
public void RegisterUserWithNonMatchingPasswords()
|
||||||
{
|
|
||||||
_logger.LogInformation("Trying to access the store inventory..");
|
|
||||||
var response = _httpClient.GetAsync("Admin/StoreManager/").Result;
|
|
||||||
ThrowIfResponseStatusNotOk(response);
|
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
|
||||||
Assert.Equal<string>(_applicationBaseUrl + "Admin/StoreManager/", response.RequestMessage.RequestUri.AbsoluteUri);
|
|
||||||
_logger.LogInformation("Successfully acccessed the store inventory");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegisterUserWithNonMatchingPasswords()
|
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Trying to create user with not matching password and confirm password");
|
_logger.LogInformation("Trying to create user with not matching password and confirm password");
|
||||||
var response = _httpClient.GetAsync("Account/Register").Result;
|
var response = _httpClient.GetAsync("Account/Register").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
ValidateLayoutPage(responseContent);
|
ValidateLayoutPage(responseContent);
|
||||||
|
|
||||||
|
|
@ -136,15 +171,15 @@ namespace E2ETests
|
||||||
var content = new FormUrlEncodedContent(formParameters.ToArray());
|
var content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
response = _httpClient.PostAsync("Account/Register", content).Result;
|
response = _httpClient.PostAsync("Account/Register", content).Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
Assert.Contains("<div class=\"text-danger validation-summary-errors\" data-valmsg-summary=\"true\"><ul><li>The password and confirmation password do not match.</li>", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("<div class=\"text-danger validation-summary-errors\" data-valmsg-summary=\"true\"><ul><li>The password and confirmation password do not match.</li>", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
_logger.LogInformation("Server side model validator rejected the user '{email}''s registration as passwords do not match.", generatedEmail);
|
_logger.LogInformation("Server side model validator rejected the user '{email}''s registration as passwords do not match.", generatedEmail);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string RegisterValidUser()
|
public string RegisterValidUser()
|
||||||
{
|
{
|
||||||
var response = _httpClient.GetAsync("Account/Register").Result;
|
var response = _httpClient.GetAsync("Account/Register").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
ValidateLayoutPage(responseContent);
|
ValidateLayoutPage(responseContent);
|
||||||
|
|
||||||
|
|
@ -163,24 +198,24 @@ namespace E2ETests
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
//Account verification
|
//Account verification
|
||||||
Assert.Equal<string>(_applicationBaseUrl + "Account/Register", response.RequestMessage.RequestUri.AbsoluteUri);
|
Assert.Equal<string>(_deploymentResult.ApplicationBaseUri + "Account/Register", response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
Assert.Contains("For DEMO only: You can click this link to confirm the email:", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("For DEMO only: You can click this link to confirm the email:", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
var startIndex = responseContent.IndexOf("[[<a href=\"", 0) + "[[<a href=\"".Length;
|
var startIndex = responseContent.IndexOf("[[<a href=\"", 0) + "[[<a href=\"".Length;
|
||||||
var endIndex = responseContent.IndexOf("\">link</a>]]", startIndex);
|
var endIndex = responseContent.IndexOf("\">link</a>]]", startIndex);
|
||||||
var confirmUrl = responseContent.Substring(startIndex, endIndex - startIndex);
|
var confirmUrl = responseContent.Substring(startIndex, endIndex - startIndex);
|
||||||
confirmUrl = WebUtility.HtmlDecode(confirmUrl);
|
confirmUrl = WebUtility.HtmlDecode(confirmUrl);
|
||||||
response = _httpClient.GetAsync(confirmUrl).Result;
|
response = _httpClient.GetAsync(confirmUrl).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Contains("Thank you for confirming your email.", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Thank you for confirming your email.", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
return generatedEmail;
|
return generatedEmail;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterExistingUser(string email)
|
public void RegisterExistingUser(string email)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Trying to register a user with name '{email}' again", email);
|
_logger.LogInformation("Trying to register a user with name '{email}' again", email);
|
||||||
var response = _httpClient.GetAsync("Account/Register").Result;
|
var response = _httpClient.GetAsync("Account/Register").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation("Creating a new user with name '{email}'", email);
|
_logger.LogInformation("Creating a new user with name '{email}'", email);
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -198,11 +233,11 @@ namespace E2ETests
|
||||||
_logger.LogInformation("Identity threw a valid exception that user '{email}' already exists in the system", email);
|
_logger.LogInformation("Identity threw a valid exception that user '{email}' already exists in the system", email);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SignOutUser(string email)
|
public void SignOutUser(string email)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Signing out from '{email}''s session", email);
|
_logger.LogInformation("Signing out from '{email}''s session", email);
|
||||||
var response = _httpClient.GetAsync(string.Empty).Result;
|
var response = _httpClient.GetAsync(string.Empty).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
ValidateLayoutPage(responseContent);
|
ValidateLayoutPage(responseContent);
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -222,21 +257,21 @@ namespace E2ETests
|
||||||
Assert.Contains("www.github.com/aspnet/MusicStore", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("www.github.com/aspnet/MusicStore", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("/Images/home-showcase.png", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("/Images/home-showcase.png", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
//Verify cookie cleared on logout
|
//Verify cookie cleared on logout
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
_logger.LogInformation("Successfully signed out of '{email}''s session", email);
|
_logger.LogInformation("Successfully signed out of '{email}''s session", email);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Bug in Mono - on logout the cookie is not cleared in the cookie container and not redirected. Work around by reinstantiating the httpClient.
|
//Bug in Mono - on logout the cookie is not cleared in the cookie container and not redirected. Work around by reinstantiating the httpClient.
|
||||||
_httpClientHandler = new HttpClientHandler();
|
_httpClientHandler = new HttpClientHandler();
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SignInWithInvalidPassword(string email, string invalidPassword)
|
public void SignInWithInvalidPassword(string email, string invalidPassword)
|
||||||
{
|
{
|
||||||
var response = _httpClient.GetAsync("Account/Login").Result;
|
var response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation("Signing in with user '{email}'", email);
|
_logger.LogInformation("Signing in with user '{email}'", email);
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -251,14 +286,14 @@ namespace E2ETests
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Contains("<div class=\"text-danger validation-summary-errors\" data-valmsg-summary=\"true\"><ul><li>Invalid login attempt.</li>", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("<div class=\"text-danger validation-summary-errors\" data-valmsg-summary=\"true\"><ul><li>Invalid login attempt.</li>", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
//Verify cookie not sent
|
//Verify cookie not sent
|
||||||
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
_logger.LogInformation("Identity successfully prevented an invalid user login.");
|
_logger.LogInformation("Identity successfully prevented an invalid user login.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SignInWithUser(string email, string password)
|
public void SignInWithUser(string email, string password)
|
||||||
{
|
{
|
||||||
var response = _httpClient.GetAsync("Account/Login").Result;
|
var response = _httpClient.GetAsync("Account/Login").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
_logger.LogInformation("Signing in with user '{email}'", email);
|
_logger.LogInformation("Signing in with user '{email}'", email);
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -274,14 +309,14 @@ namespace E2ETests
|
||||||
Assert.Contains(string.Format("Hello {0}!", email), responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(string.Format("Hello {0}!", email), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
//Verify cookie sent
|
//Verify cookie sent
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
_logger.LogInformation("Successfully signed in with user '{email}'", email);
|
_logger.LogInformation("Successfully signed in with user '{email}'", email);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ChangePassword(string email)
|
public void ChangePassword(string email)
|
||||||
{
|
{
|
||||||
var response = _httpClient.GetAsync("Manage/ChangePassword").Result;
|
var response = _httpClient.GetAsync("Manage/ChangePassword").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
{
|
{
|
||||||
|
|
@ -295,17 +330,17 @@ namespace E2ETests
|
||||||
response = _httpClient.PostAsync("Manage/ChangePassword", content).Result;
|
response = _httpClient.PostAsync("Manage/ChangePassword", content).Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Contains("Your password has been changed.", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Your password has been changed.", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application"));
|
||||||
_logger.LogInformation("Successfully changed the password for user '{email}'", email);
|
_logger.LogInformation("Successfully changed the password for user '{email}'", email);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateAlbum()
|
public string CreateAlbum()
|
||||||
{
|
{
|
||||||
var albumName = Guid.NewGuid().ToString().Replace("-", string.Empty).Substring(0, 12);
|
var albumName = Guid.NewGuid().ToString().Replace("-", string.Empty).Substring(0, 12);
|
||||||
#if DNX451
|
#if DNX451
|
||||||
string dataFromHub = null;
|
string dataFromHub = null;
|
||||||
var OnReceivedEvent = new AutoResetEvent(false);
|
var OnReceivedEvent = new AutoResetEvent(false);
|
||||||
var hubConnection = new HubConnection(_applicationBaseUrl + "SignalR");
|
var hubConnection = new HubConnection(_deploymentResult.ApplicationBaseUri + "SignalR");
|
||||||
hubConnection.Received += (data) =>
|
hubConnection.Received += (data) =>
|
||||||
{
|
{
|
||||||
_logger.LogVerbose("Data received by SignalR client: {receivedData}", data);
|
_logger.LogVerbose("Data received by SignalR client: {receivedData}", data);
|
||||||
|
|
@ -318,7 +353,7 @@ namespace E2ETests
|
||||||
#endif
|
#endif
|
||||||
_logger.LogInformation("Trying to create an album with name '{album}'", albumName);
|
_logger.LogInformation("Trying to create an album with name '{album}'", albumName);
|
||||||
var response = _httpClient.GetAsync("Admin/StoreManager/create").Result;
|
var response = _httpClient.GetAsync("Admin/StoreManager/create").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
{
|
{
|
||||||
|
|
@ -333,7 +368,7 @@ namespace E2ETests
|
||||||
var content = new FormUrlEncodedContent(formParameters.ToArray());
|
var content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
response = _httpClient.PostAsync("Admin/StoreManager/create", content).Result;
|
response = _httpClient.PostAsync("Admin/StoreManager/create", content).Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Equal<string>(_applicationBaseUrl + "Admin/StoreManager", response.RequestMessage.RequestUri.AbsoluteUri);
|
Assert.Equal<string>(_deploymentResult.ApplicationBaseUri + "Admin/StoreManager", response.RequestMessage.RequestUri.AbsoluteUri);
|
||||||
Assert.Contains(albumName, responseContent);
|
Assert.Contains(albumName, responseContent);
|
||||||
#if DNX451
|
#if DNX451
|
||||||
_logger.LogInformation("Waiting for the SignalR client to receive album created announcement");
|
_logger.LogInformation("Waiting for the SignalR client to receive album created announcement");
|
||||||
|
|
@ -345,20 +380,20 @@ namespace E2ETests
|
||||||
return albumName;
|
return albumName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string FetchAlbumIdFromName(string albumName)
|
public string FetchAlbumIdFromName(string albumName)
|
||||||
{
|
{
|
||||||
// Run some CORS validation.
|
// Run some CORS validation.
|
||||||
_logger.LogInformation("Fetching the album id of '{album}'", albumName);
|
_logger.LogInformation("Fetching the album id of '{album}'", albumName);
|
||||||
_httpClient.DefaultRequestHeaders.Add("Origin", "http://notpermitteddomain.com");
|
_httpClient.DefaultRequestHeaders.Add("Origin", "http://notpermitteddomain.com");
|
||||||
var response = _httpClient.GetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)).Result;
|
var response = _httpClient.GetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
IEnumerable<string> values;
|
IEnumerable<string> values;
|
||||||
Assert.False(response.Headers.TryGetValues("Access-Control-Allow-Origin", out values));
|
Assert.False(response.Headers.TryGetValues("Access-Control-Allow-Origin", out values));
|
||||||
|
|
||||||
_httpClient.DefaultRequestHeaders.Remove("Origin");
|
_httpClient.DefaultRequestHeaders.Remove("Origin");
|
||||||
_httpClient.DefaultRequestHeaders.Add("Origin", "http://example.com");
|
_httpClient.DefaultRequestHeaders.Add("Origin", "http://example.com");
|
||||||
response = _httpClient.GetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)).Result;
|
response = _httpClient.GetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
Assert.Equal("http://example.com", response.Headers.GetValues("Access-Control-Allow-Origin").First());
|
Assert.Equal("http://example.com", response.Headers.GetValues("Access-Control-Allow-Origin").First());
|
||||||
_httpClient.DefaultRequestHeaders.Remove("Origin");
|
_httpClient.DefaultRequestHeaders.Remove("Origin");
|
||||||
|
|
||||||
|
|
@ -367,11 +402,11 @@ namespace E2ETests
|
||||||
return albumId;
|
return albumId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VerifyAlbumDetails(string albumId, string albumName)
|
public void VerifyAlbumDetails(string albumId, string albumName)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Getting details of album with Id '{id}'", albumId);
|
_logger.LogInformation("Getting details of album with Id '{id}'", albumId);
|
||||||
var response = _httpClient.GetAsync(string.Format("Admin/StoreManager/Details?id={0}", albumId)).Result;
|
var response = _httpClient.GetAsync(string.Format("Admin/StoreManager/Details?id={0}", albumId)).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("http://myapp/testurl", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("http://myapp/testurl", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
@ -379,42 +414,42 @@ namespace E2ETests
|
||||||
Assert.Contains(PrefixBaseAddress("<a href=\"/{0}/Admin/StoreManager\">Back to List</a>"), responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(PrefixBaseAddress("<a href=\"/{0}/Admin/StoreManager\">Back to List</a>"), responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VerifyStatusCodePages()
|
public void VerifyStatusCodePages()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Getting details of a non-existing album with Id '-1'");
|
_logger.LogInformation("Getting details of a non-existing album with Id '-1'");
|
||||||
var response = _httpClient.GetAsync("Admin/StoreManager/Details?id=-1").Result;
|
var response = _httpClient.GetAsync("Admin/StoreManager/Details?id=-1").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Contains("Item not found.", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("Item not found.", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Equal(PrefixBaseAddress("/{0}/Home/StatusCodePage"), response.RequestMessage.RequestUri.AbsolutePath);
|
Assert.Equal(PrefixBaseAddress("/{0}/Home/StatusCodePage"), response.RequestMessage.RequestUri.AbsolutePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This gets the view that non-admin users get to see.
|
// This gets the view that non-admin users get to see.
|
||||||
private void GetAlbumDetailsFromStore(string albumId, string albumName)
|
public void GetAlbumDetailsFromStore(string albumId, string albumName)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Getting details of album with Id '{id}'", albumId);
|
_logger.LogInformation("Getting details of album with Id '{id}'", albumId);
|
||||||
var response = _httpClient.GetAsync(string.Format("Store/Details/{0}", albumId)).Result;
|
var response = _httpClient.GetAsync(string.Format("Store/Details/{0}", albumId)).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddAlbumToCart(string albumId, string albumName)
|
public void AddAlbumToCart(string albumId, string albumName)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Adding album id '{albumId}' to the cart", albumId);
|
_logger.LogInformation("Adding album id '{albumId}' to the cart", albumId);
|
||||||
var response = _httpClient.GetAsync(string.Format("ShoppingCart/AddToCart?id={0}", albumId)).Result;
|
var response = _httpClient.GetAsync(string.Format("ShoppingCart/AddToCart?id={0}", albumId)).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.Contains("<span class=\"glyphicon glyphicon glyphicon-shopping-cart\"></span>", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("<span class=\"glyphicon glyphicon glyphicon-shopping-cart\"></span>", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
_logger.LogInformation("Verified that album is added to cart");
|
_logger.LogInformation("Verified that album is added to cart");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CheckOutCartItems()
|
public void CheckOutCartItems()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Checking out the cart contents...");
|
_logger.LogInformation("Checking out the cart contents...");
|
||||||
var response = _httpClient.GetAsync("Checkout/AddressAndPayment").Result;
|
var response = _httpClient.GetAsync("Checkout/AddressAndPayment").Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
|
||||||
var formParameters = new List<KeyValuePair<string, string>>
|
var formParameters = new List<KeyValuePair<string, string>>
|
||||||
|
|
@ -436,10 +471,10 @@ namespace E2ETests
|
||||||
response = _httpClient.PostAsync("Checkout/AddressAndPayment", content).Result;
|
response = _httpClient.PostAsync("Checkout/AddressAndPayment", content).Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
Assert.Contains("<h2>Checkout Complete</h2>", responseContent, StringComparison.OrdinalIgnoreCase);
|
Assert.Contains("<h2>Checkout Complete</h2>", responseContent, StringComparison.OrdinalIgnoreCase);
|
||||||
Assert.StartsWith(_applicationBaseUrl + "Checkout/Complete/", response.RequestMessage.RequestUri.AbsoluteUri, StringComparison.OrdinalIgnoreCase);
|
Assert.StartsWith(_deploymentResult.ApplicationBaseUri + "Checkout/Complete/", response.RequestMessage.RequestUri.AbsoluteUri, StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeleteAlbum(string albumId, string albumName)
|
public void DeleteAlbum(string albumId, string albumName)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Deleting album '{album}' from the store..", albumName);
|
_logger.LogInformation("Deleting album '{album}' from the store..", albumName);
|
||||||
|
|
||||||
|
|
@ -450,21 +485,12 @@ namespace E2ETests
|
||||||
|
|
||||||
var content = new FormUrlEncodedContent(formParameters.ToArray());
|
var content = new FormUrlEncodedContent(formParameters.ToArray());
|
||||||
var response = _httpClient.PostAsync("Admin/StoreManager/RemoveAlbum", content).Result;
|
var response = _httpClient.PostAsync("Admin/StoreManager/RemoveAlbum", content).Result;
|
||||||
ThrowIfResponseStatusNotOk(response);
|
Helpers.ThrowIfResponseStatusNotOk(response, _logger);
|
||||||
|
|
||||||
_logger.LogInformation("Verifying if the album '{album}' is deleted from store", albumName);
|
_logger.LogInformation("Verifying if the album '{album}' is deleted from store", albumName);
|
||||||
response = _httpClient.GetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)).Result;
|
response = _httpClient.GetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)).Result;
|
||||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||||
_logger.LogInformation("Album '{album}' with id '{Id}' is successfully deleted from the store.", albumName, albumId);
|
_logger.LogInformation("Album '{album}' with id '{Id}' is successfully deleted from the store.", albumName, albumId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThrowIfResponseStatusNotOk(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
if (response.StatusCode != HttpStatusCode.OK)
|
|
||||||
{
|
|
||||||
_logger.LogError(response.Content.ReadAsStringAsync().Result);
|
|
||||||
throw new Exception(string.Format("Received the above response with status code : {0}", response.StatusCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +159,7 @@
|
||||||
<virtualDirectory path="/" physicalPath="[ApplicationPhysicalPath]" />
|
<virtualDirectory path="/" physicalPath="[ApplicationPhysicalPath]" />
|
||||||
</application>
|
</application>
|
||||||
<bindings>
|
<bindings>
|
||||||
<binding protocol="http" bindingInformation=":5001:localhost" />
|
<binding protocol="http" bindingInformation=":[PORT]:localhost" />
|
||||||
</bindings>
|
</bindings>
|
||||||
</site>
|
</site>
|
||||||
<siteDefaults>
|
<siteDefaults>
|
||||||
|
|
|
||||||
|
|
@ -1,89 +1,93 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using DeploymentHelpers;
|
||||||
using Microsoft.AspNet.Testing.xunit;
|
using Microsoft.AspNet.Testing.xunit;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
// Uses ports ranging 5050 - 5060.
|
||||||
|
public class NtlmAuthenticationTests
|
||||||
{
|
{
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
[OSSkipCondition(OperatingSystems.Unix | OperatingSystems.MacOSX)]
|
[OSSkipCondition(OperatingSystems.Unix | OperatingSystems.MacOSX)]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5001/")]
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5050/")]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.amd64, "http://localhost:5001/")]
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.clr, RuntimeArchitecture.x64, "http://localhost:5051/")]
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5002/")]
|
[InlineData(ServerType.WebListener, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5052/")]
|
||||||
public void NtlmAuthenticationTest(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public void NtlmAuthenticationTest(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
using (_logger.BeginScope("NtlmAuthenticationTest"))
|
var logger = new LoggerFactory()
|
||||||
|
.AddConsole()
|
||||||
|
.CreateLogger(string.Format("Ntlm:{0}:{1}:{2}", serverType, runtimeFlavor, architecture));
|
||||||
|
|
||||||
|
using (logger.BeginScope("NtlmAuthenticationTest"))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Variation Details : HostType = {hostType}, RuntimeFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}",
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
logger.LogInformation("Variation Details : HostType = {hostType}, RuntimeFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}",
|
||||||
serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
|
|
||||||
_startParameters = new StartParameters
|
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
||||||
|
var connectionString = string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName);
|
||||||
|
logger.LogInformation("Pointing MusicStore DB to '{connString}'", connectionString);
|
||||||
|
|
||||||
|
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(), serverType, runtimeFlavor, architecture)
|
||||||
{
|
{
|
||||||
ServerType = serverType,
|
ApplicationBaseUriHint = applicationBaseUrl,
|
||||||
RuntimeFlavor = runtimeFlavor,
|
|
||||||
RuntimeArchitecture = architecture,
|
|
||||||
EnvironmentName = "NtlmAuthentication", //Will pick the Start class named 'StartupNtlmAuthentication'
|
EnvironmentName = "NtlmAuthentication", //Will pick the Start class named 'StartupNtlmAuthentication'
|
||||||
ApplicationHostConfigTemplateContent = (serverType == ServerType.IISExpress) ? File.ReadAllText("NtlmAuthentation.config") : null,
|
ApplicationHostConfigTemplateContent = (serverType == ServerType.IISExpress) ? File.ReadAllText("NtlmAuthentation.config") : null,
|
||||||
SiteName = "MusicStoreNtlmAuthentication" //This is configured in the NtlmAuthentication.config
|
SiteName = "MusicStoreNtlmAuthentication", //This is configured in the NtlmAuthentication.config
|
||||||
|
UserAdditionalCleanup = parameters =>
|
||||||
|
{
|
||||||
|
if (!Helpers.RunningOnMono)
|
||||||
|
{
|
||||||
|
// Mono uses InMemoryStore
|
||||||
|
DbUtils.DropDatabase(musicStoreDbName, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var stopwatch = Stopwatch.StartNew();
|
// Override the connection strings using environment based configuration
|
||||||
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
deploymentParameters.EnvironmentVariables
|
||||||
|
.Add(new KeyValuePair<string, string>("SQLAZURECONNSTR_DefaultConnection", connectionString));
|
||||||
|
|
||||||
_logger.LogInformation("Pointing MusicStore DB to '{connString}'", string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName));
|
|
||||||
|
|
||||||
//Override the connection strings using environment based configuration
|
|
||||||
Environment.SetEnvironmentVariable("SQLAZURECONNSTR_DefaultConnection", string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName));
|
|
||||||
|
|
||||||
_applicationBaseUrl = applicationBaseUrl;
|
|
||||||
Process hostProcess = null;
|
|
||||||
bool testSuccessful = false;
|
bool testSuccessful = false;
|
||||||
|
|
||||||
try
|
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger))
|
||||||
{
|
{
|
||||||
hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger);
|
var deploymentResult = deployer.Deploy();
|
||||||
|
var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
|
||||||
_httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
|
var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(applicationBaseUrl) };
|
|
||||||
|
|
||||||
HttpResponseMessage response = null;
|
HttpResponseMessage response = null;
|
||||||
string responseContent = null;
|
|
||||||
|
|
||||||
//Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
||||||
Helpers.Retry(() =>
|
RetryHelper.RetryRequest(() =>
|
||||||
{
|
{
|
||||||
response = _httpClient.GetAsync(string.Empty).Result;
|
response = httpClient.GetAsync(string.Empty).Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
return response;
|
||||||
_logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
}, logger: logger);
|
||||||
}, logger: _logger);
|
|
||||||
|
|
||||||
VerifyHomePage(response, responseContent, true);
|
logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
||||||
|
|
||||||
//Check if the user name appears in the page
|
var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult);
|
||||||
Assert.Contains(
|
validator.VerifyNtlmHomePage(response);
|
||||||
string.Format("{0}\\{1}", Environment.GetEnvironmentVariable("USERDOMAIN"), Environment.GetEnvironmentVariable("USERNAME")),
|
|
||||||
responseContent, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
//Should be able to access the store as the Startup adds necessary permissions for the current user
|
//Should be able to access the store as the Startup adds necessary permissions for the current user
|
||||||
AccessStoreWithPermissions();
|
validator.AccessStoreWithPermissions();
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
_logger.LogInformation("[Time]: Total time taken for this test variation '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
logger.LogInformation("[Time]: Total time taken for this test variation '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
||||||
testSuccessful = true;
|
testSuccessful = true;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!testSuccessful)
|
|
||||||
{
|
|
||||||
_logger.LogError("Some tests failed. Proceeding with cleanup.");
|
|
||||||
}
|
|
||||||
|
|
||||||
DeploymentUtility.CleanUpApplication(_startParameters, hostProcess, musicStoreDbName, _logger);
|
if (!testSuccessful)
|
||||||
|
{
|
||||||
|
logger.LogError("Some tests failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using DeploymentHelpers;
|
||||||
using Microsoft.AspNet.Testing.xunit;
|
using Microsoft.AspNet.Testing.xunit;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
// Uses ports ranging 5040 - 5049.
|
||||||
|
public class OpenIdConnectTests
|
||||||
{
|
{
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/")]
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5040/")]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5001/")]
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5041/")]
|
||||||
public void OpenIdConnect_OnX86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public void OpenIdConnect_OnX86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
|
|
@ -20,80 +23,80 @@ namespace E2ETests
|
||||||
|
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.DotNet)]
|
[FrameworkSkipCondition(RuntimeFrameworks.DotNet)]
|
||||||
[InlineData(ServerType.Kestrel, RuntimeFlavor.Mono, RuntimeArchitecture.x86, "http://localhost:5004/")]
|
[InlineData(ServerType.Kestrel, RuntimeFlavor.mono, RuntimeArchitecture.x86, "http://localhost:5042/")]
|
||||||
public void OpenIdConnect_OnMono(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public void OpenIdConnect_OnMono(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OpenIdConnectTestSuite(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
private void OpenIdConnectTestSuite(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
using (_logger.BeginScope("OpenIdConnectTestSuite"))
|
var logger = new LoggerFactory()
|
||||||
{
|
.AddConsole()
|
||||||
_logger.LogInformation("Variation Details : HostType = {hostType}, DonetFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}",
|
.CreateLogger(string.Format("OpenId:{0}:{1}:{2}", serverType, runtimeFlavor, architecture));
|
||||||
serverType, donetFlavor, architecture, applicationBaseUrl);
|
|
||||||
|
|
||||||
_startParameters = new StartParameters
|
using (logger.BeginScope("OpenIdConnectTestSuite"))
|
||||||
|
{
|
||||||
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
logger.LogInformation("Variation Details : HostType = {hostType}, DonetFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}",
|
||||||
|
serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
|
|
||||||
|
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
||||||
|
var connectionString = string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName);
|
||||||
|
logger.LogInformation("Pointing MusicStore DB to '{connString}'", connectionString);
|
||||||
|
|
||||||
|
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(), serverType, runtimeFlavor, architecture)
|
||||||
{
|
{
|
||||||
ServerType = serverType,
|
ApplicationBaseUriHint = applicationBaseUrl,
|
||||||
RuntimeFlavor = donetFlavor,
|
EnvironmentName = "OpenIdConnectTesting",
|
||||||
RuntimeArchitecture = architecture,
|
UserAdditionalCleanup = parameters =>
|
||||||
EnvironmentName = "OpenIdConnectTesting"
|
{
|
||||||
|
if (!Helpers.RunningOnMono)
|
||||||
|
{
|
||||||
|
// Mono uses InMemoryStore
|
||||||
|
DbUtils.DropDatabase(musicStoreDbName, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var stopwatch = Stopwatch.StartNew();
|
// Override the connection strings using environment based configuration
|
||||||
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
deploymentParameters.EnvironmentVariables
|
||||||
|
.Add(new KeyValuePair<string, string>("SQLAZURECONNSTR_DefaultConnection", connectionString));
|
||||||
|
|
||||||
_logger.LogInformation("Pointing MusicStore DB to '{connString}'", string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName));
|
|
||||||
|
|
||||||
//Override the connection strings using environment based configuration
|
|
||||||
Environment.SetEnvironmentVariable("SQLAZURECONNSTR_DefaultConnection", string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName));
|
|
||||||
|
|
||||||
_applicationBaseUrl = applicationBaseUrl;
|
|
||||||
Process hostProcess = null;
|
|
||||||
bool testSuccessful = false;
|
bool testSuccessful = false;
|
||||||
|
|
||||||
try
|
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger))
|
||||||
{
|
{
|
||||||
hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger);
|
var deploymentResult = deployer.Deploy();
|
||||||
#if DNX451
|
var httpClientHandler = new HttpClientHandler();
|
||||||
if (serverType == ServerType.IISNativeModule || serverType == ServerType.IIS)
|
var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
|
||||||
{
|
|
||||||
// Accomodate the vdir name.
|
|
||||||
_applicationBaseUrl += _startParameters.IISApplication.VirtualDirectoryName + "/";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_httpClientHandler = new HttpClientHandler();
|
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
|
||||||
|
|
||||||
HttpResponseMessage response = null;
|
HttpResponseMessage response = null;
|
||||||
string responseContent = null;
|
|
||||||
|
|
||||||
//Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
||||||
Helpers.Retry(() =>
|
RetryHelper.RetryRequest(() =>
|
||||||
{
|
{
|
||||||
response = _httpClient.GetAsync(string.Empty).Result;
|
response = httpClient.GetAsync(string.Empty).Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
return response;
|
||||||
_logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
}, logger: logger);
|
||||||
}, logger: _logger);
|
|
||||||
|
|
||||||
VerifyHomePage(response, responseContent);
|
logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
||||||
|
|
||||||
|
var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult);
|
||||||
|
validator.VerifyHomePage(response);
|
||||||
|
|
||||||
// OpenIdConnect login.
|
// OpenIdConnect login.
|
||||||
LoginWithOpenIdConnect();
|
validator.LoginWithOpenIdConnect();
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
_logger.LogInformation("[Time]: Total time taken for this test variation '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
logger.LogInformation("[Time]: Total time taken for this test variation '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
||||||
testSuccessful = true;
|
testSuccessful = true;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!testSuccessful)
|
|
||||||
{
|
|
||||||
_logger.LogError("Some tests failed. Proceeding with cleanup.");
|
|
||||||
}
|
|
||||||
|
|
||||||
DeploymentUtility.CleanUpApplication(_startParameters, hostProcess, musicStoreDbName, _logger);
|
if (!testSuccessful)
|
||||||
|
{
|
||||||
|
logger.LogError("Some tests failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,115 +1,133 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using DeploymentHelpers;
|
||||||
using Microsoft.AspNet.Testing.xunit;
|
using Microsoft.AspNet.Testing.xunit;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
// Uses ports ranging 5025 - 5039.
|
||||||
|
public class PublishAndRunTests_OnX64
|
||||||
{
|
{
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/", false)]
|
[InlineData(ServerType.WebListener, RuntimeFlavor.clr, RuntimeArchitecture.x64, "http://localhost:5025/", false)]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/", true)]
|
//https://github.com/aspnet/KRuntime/issues/642
|
||||||
|
//[InlineData(ServerType.Helios, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5026/")]
|
||||||
|
public void Publish_And_Run_Tests_On_AMD64(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, bool noSource)
|
||||||
|
{
|
||||||
|
var testRunner = new PublishAndRunTests();
|
||||||
|
testRunner.Publish_And_Run_Tests(serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PublishAndRunTests_OnX86
|
||||||
|
{
|
||||||
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5027/", false)]
|
||||||
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5028/", true)]
|
||||||
public void Publish_And_Run_Tests_On_X86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, bool noSource)
|
public void Publish_And_Run_Tests_On_X86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, bool noSource)
|
||||||
{
|
{
|
||||||
Publish_And_Run_Tests(serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
|
var testRunner = new PublishAndRunTests();
|
||||||
|
testRunner.Publish_And_Run_Tests(serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.DotNet)]
|
[FrameworkSkipCondition(RuntimeFrameworks.DotNet)]
|
||||||
[InlineData(ServerType.Kestrel, RuntimeFlavor.Mono, RuntimeArchitecture.x86, "http://localhost:5004/", false)]
|
[InlineData(ServerType.Kestrel, RuntimeFlavor.mono, RuntimeArchitecture.x86, "http://localhost:5029/", false)]
|
||||||
[InlineData(ServerType.Kestrel, RuntimeFlavor.Mono, RuntimeArchitecture.x86, "http://localhost:5004/", true)]
|
[InlineData(ServerType.Kestrel, RuntimeFlavor.mono, RuntimeArchitecture.x86, "http://localhost:5030/", true)]
|
||||||
public void Publish_And_Run_Tests_On_Mono(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, bool noSource)
|
public void Publish_And_Run_Tests_On_Mono(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, bool noSource)
|
||||||
{
|
{
|
||||||
Publish_And_Run_Tests(serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
|
var testRunner = new PublishAndRunTests();
|
||||||
|
testRunner.Publish_And_Run_Tests(serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
public class PublishAndRunTests
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
{
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.DesktopClr, RuntimeArchitecture.amd64, "http://localhost:5002/", false)]
|
public void Publish_And_Run_Tests(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, bool noSource)
|
||||||
//https://github.com/aspnet/KRuntime/issues/642
|
|
||||||
//[InlineData(ServerType.Helios, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5001/")]
|
|
||||||
public void Publish_And_Run_Tests_On_AMD64(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, bool noSource)
|
|
||||||
{
|
{
|
||||||
Publish_And_Run_Tests(serverType, runtimeFlavor, architecture, applicationBaseUrl, noSource);
|
var logger = new LoggerFactory()
|
||||||
}
|
.AddConsole()
|
||||||
|
.CreateLogger(string.Format("Publish:{0}:{1}:{2}:{3}", serverType, runtimeFlavor, architecture, noSource));
|
||||||
|
|
||||||
private void Publish_And_Run_Tests(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, bool noSource)
|
using (logger.BeginScope("Publish_And_Run_Tests"))
|
||||||
{
|
|
||||||
using (_logger.BeginScope("Publish_And_Run_Tests"))
|
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Variation Details : HostType = {hostType}, RuntimeFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}",
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
logger.LogInformation("Variation Details : HostType = {hostType}, RuntimeFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}",
|
||||||
serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
|
|
||||||
_startParameters = new StartParameters
|
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
||||||
|
var connectionString = string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName);
|
||||||
|
logger.LogInformation("Pointing MusicStore DB to '{connString}'", connectionString);
|
||||||
|
|
||||||
|
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(), serverType, runtimeFlavor, architecture)
|
||||||
{
|
{
|
||||||
ServerType = serverType,
|
ApplicationBaseUriHint = applicationBaseUrl,
|
||||||
RuntimeFlavor = runtimeFlavor,
|
PublishApplicationBeforeDeployment = true,
|
||||||
RuntimeArchitecture = architecture,
|
PublishWithNoSource = noSource,
|
||||||
PublishApplicationBeforeStart = true,
|
UserAdditionalCleanup = parameters =>
|
||||||
PublishWithNoSource = noSource
|
{
|
||||||
|
if (!Helpers.RunningOnMono)
|
||||||
|
{
|
||||||
|
// Mono uses InMemoryStore
|
||||||
|
DbUtils.DropDatabase(musicStoreDbName, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var stopwatch = Stopwatch.StartNew();
|
// Override the connection strings using environment based configuration
|
||||||
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
deploymentParameters.EnvironmentVariables
|
||||||
|
.Add(new KeyValuePair<string, string>("SQLAZURECONNSTR_DefaultConnection", connectionString));
|
||||||
|
|
||||||
_logger.LogInformation("Pointing MusicStore DB to '{connString}'", string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName));
|
|
||||||
|
|
||||||
//Override the connection strings using environment based configuration
|
|
||||||
Environment.SetEnvironmentVariable("SQLAZURECONNSTR_DefaultConnection", string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName));
|
|
||||||
|
|
||||||
_applicationBaseUrl = applicationBaseUrl;
|
|
||||||
Process hostProcess = null;
|
|
||||||
bool testSuccessful = false;
|
bool testSuccessful = false;
|
||||||
|
|
||||||
try
|
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger))
|
||||||
{
|
{
|
||||||
hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger);
|
var deploymentResult = deployer.Deploy();
|
||||||
|
var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
|
||||||
_httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
|
var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(applicationBaseUrl) };
|
|
||||||
|
|
||||||
HttpResponseMessage response = null;
|
HttpResponseMessage response = null;
|
||||||
string responseContent = null;
|
|
||||||
|
|
||||||
//Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
||||||
//Add retry logic since tests are flaky on mono due to connection issues
|
// Add retry logic since tests are flaky on mono due to connection issues
|
||||||
Helpers.Retry(() =>
|
RetryHelper.RetryRequest(() =>
|
||||||
{
|
{
|
||||||
response = _httpClient.GetAsync(string.Empty).Result;
|
response = httpClient.GetAsync(string.Empty).Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
return response;
|
||||||
_logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
}, logger: logger);
|
||||||
}, logger: _logger);
|
|
||||||
|
|
||||||
VerifyHomePage(response, responseContent, true);
|
logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
||||||
|
|
||||||
//Static files are served?
|
var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult);
|
||||||
VerifyStaticContentServed();
|
validator.VerifyHomePage(response);
|
||||||
|
|
||||||
|
// Static files are served?
|
||||||
|
validator.VerifyStaticContentServed();
|
||||||
|
|
||||||
if (serverType != ServerType.IISExpress)
|
if (serverType != ServerType.IISExpress)
|
||||||
{
|
{
|
||||||
if (Directory.GetFiles(_startParameters.ApplicationPath, "*.cmd", SearchOption.TopDirectoryOnly).Length > 0)
|
if (Directory.GetFiles(deploymentParameters.ApplicationPath, "*.cmd", SearchOption.TopDirectoryOnly).Length > 0)
|
||||||
{
|
{
|
||||||
throw new Exception("publishExclude parameter values are not honored.");
|
throw new Exception("publishExclude parameter values are not honored.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
_logger.LogInformation("[Time]: Total time taken for this test variation '{t}' seconds.", stopwatch.Elapsed.TotalSeconds);
|
logger.LogInformation("[Time]: Total time taken for this test variation '{t}' seconds.", stopwatch.Elapsed.TotalSeconds);
|
||||||
testSuccessful = true;
|
testSuccessful = true;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!testSuccessful)
|
|
||||||
{
|
|
||||||
_logger.LogError("Some tests failed. Proceeding with cleanup.");
|
|
||||||
}
|
|
||||||
|
|
||||||
DeploymentUtility.CleanUpApplication(_startParameters, hostProcess, musicStoreDbName, _logger);
|
if (!testSuccessful)
|
||||||
|
{
|
||||||
|
logger.LogError("Some tests failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,238 +1,260 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using DeploymentHelpers;
|
||||||
using Microsoft.AspNet.Testing.xunit;
|
using Microsoft.AspNet.Testing.xunit;
|
||||||
using Microsoft.Framework.Logging;
|
using Microsoft.Framework.Logging;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace E2ETests
|
namespace E2ETests
|
||||||
{
|
{
|
||||||
public partial class SmokeTests
|
// Uses ports ranging 5001 - 5025.
|
||||||
|
public class SmokeTests_X86_Clr
|
||||||
{
|
{
|
||||||
private string _applicationBaseUrl;
|
|
||||||
private HttpClient _httpClient;
|
|
||||||
private HttpClientHandler _httpClientHandler;
|
|
||||||
private StartParameters _startParameters;
|
|
||||||
private readonly ILogger _logger;
|
|
||||||
|
|
||||||
public SmokeTests()
|
|
||||||
{
|
|
||||||
var loggerFactory = new LoggerFactory();
|
|
||||||
loggerFactory.AddConsole();
|
|
||||||
_logger = loggerFactory.CreateLogger<SmokeTests>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/")]
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5001/")]
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5002/")]
|
[InlineData(ServerType.WebListener, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5002/")]
|
||||||
[InlineData(ServerType.Kestrel, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5004/")]
|
[InlineData(ServerType.Kestrel, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5003/")]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5001/")]
|
public void SmokeTestSuite_OnX86_clr(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5002/")]
|
|
||||||
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5004/")]
|
|
||||||
public void SmokeTestSuite_OnX86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
|
||||||
{
|
{
|
||||||
SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
var smokeTestRunner = new SmokeTests();
|
||||||
|
smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SmokeTests_X86_Coreclr
|
||||||
|
{
|
||||||
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5004/")]
|
||||||
|
[InlineData(ServerType.WebListener, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5005/")]
|
||||||
|
[InlineData(ServerType.Kestrel, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5006/")]
|
||||||
|
public void SmokeTestSuite_OnX86_coreclr(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
|
{
|
||||||
|
var smokeTestRunner = new SmokeTests();
|
||||||
|
smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SmokeTests_X64
|
||||||
|
{
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[SkipOn32BitOS]
|
[SkipOn32BitOS]
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.DesktopClr, RuntimeArchitecture.amd64, "http://localhost:5002/")]
|
[InlineData(ServerType.WebListener, RuntimeFlavor.clr, RuntimeArchitecture.x64, "http://localhost:5007/")]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5001/")]
|
[InlineData(ServerType.IISExpress, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5008/")]
|
||||||
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5004/")]
|
[InlineData(ServerType.Kestrel, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5009/")]
|
||||||
public void SmokeTestSuite_OnAMD64(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public void SmokeTestSuite_OnAMD64(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
SmokeTestSuite(serverType, donetFlavor, architecture, applicationBaseUrl);
|
var smokeTestRunner = new SmokeTests();
|
||||||
|
smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SmokeTests_OnMono
|
||||||
|
{
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.DotNet)]
|
[FrameworkSkipCondition(RuntimeFrameworks.DotNet)]
|
||||||
[InlineData(ServerType.Kestrel, RuntimeFlavor.Mono, RuntimeArchitecture.x86, "http://localhost:5004/")]
|
[InlineData(ServerType.Kestrel, RuntimeFlavor.mono, RuntimeArchitecture.x86, "http://localhost:5010/")]
|
||||||
public void SmokeTestSuite_OnMono(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public void SmokeTestSuite_OnMono(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
SmokeTestSuite(serverType, donetFlavor, architecture, applicationBaseUrl);
|
var smokeTestRunner = new SmokeTests();
|
||||||
|
smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
public class SmokeTests_OnIIS
|
||||||
|
{
|
||||||
|
[ConditionalTheory(Skip = "IIS based tests not enabled"), Trait("E2Etests", "E2Etests")]
|
||||||
[SkipIfNativeModuleNotInstalled]
|
[SkipIfNativeModuleNotInstalled]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[OSSkipCondition(OperatingSystems.Win7And2008R2 | OperatingSystems.MacOSX | OperatingSystems.Unix)]
|
[OSSkipCondition(OperatingSystems.Win7And2008R2 | OperatingSystems.MacOSX | OperatingSystems.Unix)]
|
||||||
[SkipIfCurrentRuntimeIsCoreClr]
|
[SkipIfCurrentRuntimeIsCoreClr]
|
||||||
[InlineData(ServerType.IISNativeModule, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5005/")]
|
[InlineData(ServerType.IISNativeModule, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5011/")]
|
||||||
public void SmokeTestSuite_On_NativeModule_X86(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public void SmokeTestSuite_On_NativeModule_X86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
SmokeTestSuite(serverType, donetFlavor, architecture, applicationBaseUrl);
|
var smokeTestRunner = new SmokeTests();
|
||||||
|
smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory(Skip = "IIS based tests not enabled"), Trait("E2Etests", "E2Etests")]
|
||||||
[SkipIfNativeModuleNotInstalled]
|
[SkipIfNativeModuleNotInstalled]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[OSSkipCondition(OperatingSystems.Win7And2008R2 | OperatingSystems.MacOSX | OperatingSystems.Unix)]
|
[OSSkipCondition(OperatingSystems.Win7And2008R2 | OperatingSystems.MacOSX | OperatingSystems.Unix)]
|
||||||
[SkipOn32BitOS]
|
[SkipOn32BitOS]
|
||||||
[SkipIfCurrentRuntimeIsCoreClr]
|
[SkipIfCurrentRuntimeIsCoreClr]
|
||||||
[InlineData(ServerType.IISNativeModule, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5005/")]
|
[InlineData(ServerType.IISNativeModule, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5012/")]
|
||||||
public void SmokeTestSuite_On_NativeModule_AMD64(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public void SmokeTestSuite_On_NativeModule_AMD64(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
SmokeTestSuite(serverType, donetFlavor, architecture, applicationBaseUrl);
|
var smokeTestRunner = new SmokeTests();
|
||||||
|
smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ConditionalTheory, Trait("E2Etests", "E2Etests")]
|
[ConditionalTheory(Skip = "IIS based tests not enabled"), Trait("E2Etests", "E2Etests")]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||||
[OSSkipCondition(OperatingSystems.MacOSX | OperatingSystems.Unix)]
|
[OSSkipCondition(OperatingSystems.MacOSX | OperatingSystems.Unix)]
|
||||||
[SkipIfCurrentRuntimeIsCoreClr]
|
[SkipIfCurrentRuntimeIsCoreClr]
|
||||||
[InlineData(ServerType.IIS, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5005/")]
|
[InlineData(ServerType.IIS, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5013/")]
|
||||||
public void SmokeTestSuite_On_IIS_X86(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public void SmokeTestSuite_On_IIS_X86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
SmokeTestSuite(serverType, donetFlavor, architecture, applicationBaseUrl);
|
var smokeTestRunner = new SmokeTests();
|
||||||
|
smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SmokeTestSuite(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
public class SmokeTests
|
||||||
|
{
|
||||||
|
public void SmokeTestSuite(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl)
|
||||||
{
|
{
|
||||||
using (_logger.BeginScope("SmokeTestSuite"))
|
var logger = new LoggerFactory()
|
||||||
|
.AddConsole()
|
||||||
|
.CreateLogger(string.Format("Smoke:{0}:{1}:{2}", serverType, donetFlavor, architecture));
|
||||||
|
|
||||||
|
using (logger.BeginScope("SmokeTestSuite"))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Variation Details : HostType = {hostType}, DonetFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}",
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
logger.LogInformation("Variation Details : HostType = {hostType}, DonetFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}",
|
||||||
serverType, donetFlavor, architecture, applicationBaseUrl);
|
serverType, donetFlavor, architecture, applicationBaseUrl);
|
||||||
|
|
||||||
_startParameters = new StartParameters
|
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
||||||
|
var connectionString = string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName);
|
||||||
|
logger.LogInformation("Pointing MusicStore DB to '{connString}'", connectionString);
|
||||||
|
|
||||||
|
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(), serverType, donetFlavor, architecture)
|
||||||
{
|
{
|
||||||
ServerType = serverType,
|
ApplicationBaseUriHint = applicationBaseUrl,
|
||||||
RuntimeFlavor = donetFlavor,
|
EnvironmentName = "SocialTesting",
|
||||||
RuntimeArchitecture = architecture,
|
UserAdditionalCleanup = parameters =>
|
||||||
EnvironmentName = "SocialTesting"
|
{
|
||||||
|
if (!Helpers.RunningOnMono)
|
||||||
|
{
|
||||||
|
// Mono uses InMemoryStore
|
||||||
|
DbUtils.DropDatabase(musicStoreDbName, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var stopwatch = Stopwatch.StartNew();
|
// Override the connection strings using environment based configuration
|
||||||
var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty);
|
deploymentParameters.EnvironmentVariables
|
||||||
|
.Add(new KeyValuePair<string, string>("SQLAZURECONNSTR_DefaultConnection", connectionString));
|
||||||
|
|
||||||
_logger.LogInformation("Pointing MusicStore DB to '{connString}'", string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName));
|
|
||||||
|
|
||||||
//Override the connection strings using environment based configuration
|
|
||||||
Environment.SetEnvironmentVariable("SQLAZURECONNSTR_DefaultConnection", string.Format(DbUtils.CONNECTION_STRING_FORMAT, musicStoreDbName));
|
|
||||||
|
|
||||||
_applicationBaseUrl = applicationBaseUrl;
|
|
||||||
Process hostProcess = null;
|
|
||||||
bool testSuccessful = false;
|
bool testSuccessful = false;
|
||||||
|
|
||||||
try
|
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger))
|
||||||
{
|
{
|
||||||
hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger);
|
var deploymentResult = deployer.Deploy();
|
||||||
#if DNX451
|
Helpers.SetInMemoryStoreForIIS(deploymentParameters, logger);
|
||||||
if (serverType == ServerType.IISNativeModule || serverType == ServerType.IIS)
|
|
||||||
{
|
var httpClientHandler = new HttpClientHandler();
|
||||||
// Accomodate the vdir name.
|
var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
|
||||||
_applicationBaseUrl += _startParameters.IISApplication.VirtualDirectoryName + "/";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_httpClientHandler = new HttpClientHandler();
|
|
||||||
_httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) };
|
|
||||||
|
|
||||||
HttpResponseMessage response = null;
|
HttpResponseMessage response = null;
|
||||||
string responseContent = null;
|
|
||||||
|
|
||||||
//Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
||||||
Helpers.Retry(() =>
|
RetryHelper.RetryRequest(() =>
|
||||||
{
|
{
|
||||||
response = _httpClient.GetAsync(string.Empty).Result;
|
response = httpClient.GetAsync(string.Empty).Result;
|
||||||
responseContent = response.Content.ReadAsStringAsync().Result;
|
return response;
|
||||||
_logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
}, logger: logger);
|
||||||
}, logger: _logger);
|
|
||||||
|
|
||||||
VerifyHomePage(response, responseContent);
|
logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
||||||
|
|
||||||
//Verify the static file middleware can serve static content
|
var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult);
|
||||||
VerifyStaticContentServed();
|
|
||||||
|
|
||||||
//Making a request to a protected resource should automatically redirect to login page
|
validator.VerifyHomePage(response);
|
||||||
AccessStoreWithoutPermissions();
|
|
||||||
|
|
||||||
//Register a user - Negative scenario where the Password & ConfirmPassword do not match
|
// Verify the static file middleware can serve static content.
|
||||||
RegisterUserWithNonMatchingPasswords();
|
validator.VerifyStaticContentServed();
|
||||||
|
|
||||||
//Register a valid user
|
// Making a request to a protected resource should automatically redirect to login page.
|
||||||
var generatedEmail = RegisterValidUser();
|
validator.AccessStoreWithoutPermissions();
|
||||||
|
|
||||||
SignInWithUser(generatedEmail, "Password~1");
|
// Register a user - Negative scenario where the Password & ConfirmPassword do not match.
|
||||||
|
validator.RegisterUserWithNonMatchingPasswords();
|
||||||
|
|
||||||
//Register a user - Negative scenario : Trying to register a user name that's already registered.
|
// Register a valid user.
|
||||||
RegisterExistingUser(generatedEmail);
|
var generatedEmail = validator.RegisterValidUser();
|
||||||
|
|
||||||
//Logout from this user session - This should take back to the home page
|
validator.SignInWithUser(generatedEmail, "Password~1");
|
||||||
SignOutUser(generatedEmail);
|
|
||||||
|
|
||||||
//Sign in scenarios: Invalid password - Expected an invalid user name password error.
|
// Register a user - Negative scenario : Trying to register a user name that's already registered.
|
||||||
SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1");
|
validator.RegisterExistingUser(generatedEmail);
|
||||||
|
|
||||||
//Sign in scenarios: Valid user name & password.
|
// Logout from this user session - This should take back to the home page
|
||||||
SignInWithUser(generatedEmail, "Password~1");
|
validator.SignOutUser(generatedEmail);
|
||||||
|
|
||||||
//Change password scenario
|
// Sign in scenarios: Invalid password - Expected an invalid user name password error.
|
||||||
ChangePassword(generatedEmail);
|
validator.SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1");
|
||||||
|
|
||||||
//SignIn with old password and verify old password is not allowed and new password is allowed
|
// Sign in scenarios: Valid user name & password.
|
||||||
SignOutUser(generatedEmail);
|
validator.SignInWithUser(generatedEmail, "Password~1");
|
||||||
SignInWithInvalidPassword(generatedEmail, "Password~1");
|
|
||||||
SignInWithUser(generatedEmail, "Password~2");
|
|
||||||
|
|
||||||
//Making a request to a protected resource that this user does not have access to - should automatically redirect to login page again
|
// Change password scenario
|
||||||
AccessStoreWithoutPermissions(generatedEmail);
|
validator.ChangePassword(generatedEmail);
|
||||||
|
|
||||||
//Logout from this user session - This should take back to the home page
|
// SignIn with old password and verify old password is not allowed and new password is allowed
|
||||||
SignOutUser(generatedEmail);
|
validator.SignOutUser(generatedEmail);
|
||||||
|
validator.SignInWithInvalidPassword(generatedEmail, "Password~1");
|
||||||
|
validator.SignInWithUser(generatedEmail, "Password~2");
|
||||||
|
|
||||||
//Login as an admin user
|
// Making a request to a protected resource that this user does not have access to - should automatically redirect to login page again
|
||||||
SignInWithUser("Administrator@test.com", "YouShouldChangeThisPassword1!");
|
validator.AccessStoreWithoutPermissions(generatedEmail);
|
||||||
|
|
||||||
//Now navigating to the store manager should work fine as this user has the necessary permission to administer the store.
|
// Logout from this user session - This should take back to the home page
|
||||||
AccessStoreWithPermissions();
|
validator.SignOutUser(generatedEmail);
|
||||||
|
|
||||||
//Create an album
|
// Login as an admin user
|
||||||
var albumName = CreateAlbum();
|
validator.SignInWithUser("Administrator@test.com", "YouShouldChangeThisPassword1!");
|
||||||
var albumId = FetchAlbumIdFromName(albumName);
|
|
||||||
|
|
||||||
//Get details of the album
|
// Now navigating to the store manager should work fine as this user has the necessary permission to administer the store.
|
||||||
VerifyAlbumDetails(albumId, albumName);
|
validator.AccessStoreWithPermissions();
|
||||||
|
|
||||||
//Verify status code pages acts on non-existing items.
|
// Create an album
|
||||||
VerifyStatusCodePages();
|
var albumName = validator.CreateAlbum();
|
||||||
|
var albumId = validator.FetchAlbumIdFromName(albumName);
|
||||||
|
|
||||||
//Get the non-admin view of the album.
|
// Get details of the album
|
||||||
GetAlbumDetailsFromStore(albumId, albumName);
|
validator.VerifyAlbumDetails(albumId, albumName);
|
||||||
|
|
||||||
//Add an album to cart and checkout the same
|
// Verify status code pages acts on non-existing items.
|
||||||
AddAlbumToCart(albumId, albumName);
|
validator.VerifyStatusCodePages();
|
||||||
CheckOutCartItems();
|
|
||||||
|
|
||||||
//Delete the album from store
|
// Get the non-admin view of the album.
|
||||||
DeleteAlbum(albumId, albumName);
|
validator.GetAlbumDetailsFromStore(albumId, albumName);
|
||||||
|
|
||||||
//Logout from this user session - This should take back to the home page
|
// Add an album to cart and checkout the same
|
||||||
SignOutUser("Administrator");
|
validator.AddAlbumToCart(albumId, albumName);
|
||||||
|
validator.CheckOutCartItems();
|
||||||
|
|
||||||
//Google login
|
// Delete the album from store
|
||||||
LoginWithGoogle();
|
validator.DeleteAlbum(albumId, albumName);
|
||||||
|
|
||||||
//Facebook login
|
// Logout from this user session - This should take back to the home page
|
||||||
LoginWithFacebook();
|
validator.SignOutUser("Administrator");
|
||||||
|
|
||||||
//Twitter login
|
// Google login
|
||||||
LoginWithTwitter();
|
validator.LoginWithGoogle();
|
||||||
|
|
||||||
//MicrosoftAccountLogin
|
// Facebook login
|
||||||
LoginWithMicrosoftAccount();
|
validator.LoginWithFacebook();
|
||||||
|
|
||||||
|
// Twitter login
|
||||||
|
validator.LoginWithTwitter();
|
||||||
|
|
||||||
|
// MicrosoftAccountLogin
|
||||||
|
validator.LoginWithMicrosoftAccount();
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
_logger.LogInformation("[Time]: Total time taken for this test variation '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
logger.LogInformation("[Time]: Total time taken for this test variation '{t}' seconds", stopwatch.Elapsed.TotalSeconds);
|
||||||
testSuccessful = true;
|
testSuccessful = true;
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (!testSuccessful)
|
|
||||||
{
|
|
||||||
_logger.LogError("Some tests failed. Proceeding with cleanup.");
|
|
||||||
}
|
|
||||||
|
|
||||||
DeploymentUtility.CleanUpApplication(_startParameters, hostProcess, musicStoreDbName, _logger);
|
if (!testSuccessful)
|
||||||
|
{
|
||||||
|
logger.LogError("Some tests failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ namespace MusicStore
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
|
||||||
|
|
||||||
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ namespace MusicStore
|
||||||
|
|
||||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole(minLevel: LogLevel.Warning);
|
||||||
|
|
||||||
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,12 @@
|
||||||
"test": "xunit.runner.aspnet"
|
"test": "xunit.runner.aspnet"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"DeploymentHelpers": "1.0.0-*",
|
||||||
|
"Microsoft.AspNet.Http.Core": "1.0.0-*",
|
||||||
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
|
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
|
||||||
"Microsoft.AspNet.SignalR.Client": "2.1.1",
|
"Microsoft.AspNet.SignalR.Client": "2.1.1",
|
||||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
|
||||||
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
|
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
|
||||||
"Microsoft.Framework.Logging.Console": "1.0.0-*",
|
"Microsoft.Framework.Logging.Console": "1.0.0-*",
|
||||||
"Microsoft.Framework.Runtime.Interfaces": "1.0.0-*",
|
|
||||||
"Microsoft.Web.Administration": "7.0.0",
|
|
||||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
|
|
@ -24,4 +23,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue