diff --git a/MusicStore.sln b/MusicStore.sln index c0d448f626..b267f652cc 100644 --- a/MusicStore.sln +++ b/MusicStore.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.22617.0 +VisualStudioVersion = 14.0.22803.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{44621553-AA7D-4893-8834-79582A7D8348}" EndProject @@ -28,6 +28,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Test", "test\Mus EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MusicStore.Spa.Test", "test\MusicStore.Spa.Test\MusicStore.Spa.Test.xproj", "{9D3326C4-1F12-4526-9F25-712A1463B3FA}" EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "DeploymentHelpers", "test\DeploymentHelpers\DeploymentHelpers.xproj", "{C98E54D3-F4C6-4D16-A5A6-E86A636A7311}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution 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|x86.ActiveCfg = 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 GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -124,5 +138,6 @@ Global {93891170-A8D5-46FD-A291-40F90CF258C2} = {B7B176B6-8D4D-4EF1-BBD2-DDA650C78FFF} {CA663205-77DE-4E55-B300-85594181B5A9} = {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 EndGlobal diff --git a/src/MusicStore/Startup.cs b/src/MusicStore/Startup.cs index 5aed990a29..2f1215786f 100644 --- a/src/MusicStore/Startup.cs +++ b/src/MusicStore/Startup.cs @@ -111,7 +111,7 @@ namespace MusicStore //The allowed values are Development,Staging and Production public void ConfigureDevelopment(IApplicationBuilder app, ILoggerFactory loggerFactory) { - loggerFactory.AddConsole(); + loggerFactory.AddConsole(minLevel: LogLevel.Warning); // StatusCode pages to gracefully handle status codes 400-599. app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage"); @@ -134,7 +134,7 @@ namespace MusicStore //The allowed values are Development,Staging and Production public void ConfigureStaging(IApplicationBuilder app, ILoggerFactory loggerFactory) { - loggerFactory.AddConsole(); + loggerFactory.AddConsole(minLevel: LogLevel.Warning); // StatusCode pages to gracefully handle status codes 400-599. app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage"); @@ -148,7 +148,7 @@ namespace MusicStore //The allowed values are Development,Staging and Production public void ConfigureProduction(IApplicationBuilder app, ILoggerFactory loggerFactory) { - loggerFactory.AddConsole(); + loggerFactory.AddConsole(minLevel: LogLevel.Warning); // StatusCode pages to gracefully handle status codes 400-599. app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage"); diff --git a/src/MusicStore/StartupNtlmAuthentication.cs b/src/MusicStore/StartupNtlmAuthentication.cs index 94fc6dc3e3..9b0f026784 100644 --- a/src/MusicStore/StartupNtlmAuthentication.cs +++ b/src/MusicStore/StartupNtlmAuthentication.cs @@ -82,7 +82,7 @@ namespace MusicStore public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { - loggerFactory.AddConsole(); + loggerFactory.AddConsole(minLevel: LogLevel.Warning); app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage"); diff --git a/src/MusicStore/StartupOpenIdConnect.cs b/src/MusicStore/StartupOpenIdConnect.cs index fbc05c6542..7e9d5b2cab 100644 --- a/src/MusicStore/StartupOpenIdConnect.cs +++ b/src/MusicStore/StartupOpenIdConnect.cs @@ -103,7 +103,7 @@ namespace MusicStore public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { - loggerFactory.AddConsole(); + loggerFactory.AddConsole(minLevel: LogLevel.Warning); app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage"); diff --git a/test/DeploymentHelpers/Common/DeploymentParameters.cs b/test/DeploymentHelpers/Common/DeploymentParameters.cs new file mode 100644 index 0000000000..849a144e72 --- /dev/null +++ b/test/DeploymentHelpers/Common/DeploymentParameters.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace DeploymentHelpers +{ + /// + /// Parameters to control application deployment. + /// + public class DeploymentParameters + { + /// + /// Creates an instance of . + /// + /// Source code location of the target location to be deployed. + /// Where to be deployed on. + /// Flavor of the clr to run against. + /// Architecture of the DNX to be used. + 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; } + + /// + /// Suggested base url for the deployed application. The final deployed url could be + /// different than this. Use for the + /// deployed url. + /// + 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; } + + /// + /// To publish the application before deployment. + /// + public bool PublishApplicationBeforeDeployment { get; set; } + + public string PublishedApplicationRootPath { get; set; } + + /// + /// Passes the --no-source option when publishing. + /// + public bool PublishWithNoSource { get; set; } + + public string DnxRuntime { get; set; } + + /// + /// Environment variables to be set before starting the host. + /// Not applicable for IIS Scenarios. + /// + public List> EnvironmentVariables { get; private set; } = new List>(); + + /// + /// For any application level cleanup to be invoked after performing host cleanup. + /// + public Action UserAdditionalCleanup { get; set; } + } +} \ No newline at end of file diff --git a/test/DeploymentHelpers/Common/DeploymentResult.cs b/test/DeploymentHelpers/Common/DeploymentResult.cs new file mode 100644 index 0000000000..25c2729905 --- /dev/null +++ b/test/DeploymentHelpers/Common/DeploymentResult.cs @@ -0,0 +1,24 @@ +namespace DeploymentHelpers +{ + /// + /// Result of a deployment. + /// + public class DeploymentResult + { + /// + /// Base Uri of the deployment application. + /// + public string ApplicationBaseUri { get; set; } + + /// + /// The web root folder where the application is hosted. This path can be different from the + /// original application source location if published before deployment. + /// + public string WebRootLocation { get; set; } + + /// + /// Original deployment parameters used for this deployment. + /// + public DeploymentParameters DeploymentParameters { get; set; } + } +} \ No newline at end of file diff --git a/test/E2ETests/Common/DotnetArchitecture.cs b/test/DeploymentHelpers/Common/DotnetArchitecture.cs similarity index 57% rename from test/E2ETests/Common/DotnetArchitecture.cs rename to test/DeploymentHelpers/Common/DotnetArchitecture.cs index 827e01de3a..e358d24783 100644 --- a/test/E2ETests/Common/DotnetArchitecture.cs +++ b/test/DeploymentHelpers/Common/DotnetArchitecture.cs @@ -1,8 +1,8 @@ -namespace E2ETests +namespace DeploymentHelpers { public enum RuntimeArchitecture { - amd64, + x64, x86 } } \ No newline at end of file diff --git a/test/DeploymentHelpers/Common/DotnetFlavor.cs b/test/DeploymentHelpers/Common/DotnetFlavor.cs new file mode 100644 index 0000000000..32447a57b6 --- /dev/null +++ b/test/DeploymentHelpers/Common/DotnetFlavor.cs @@ -0,0 +1,9 @@ +namespace DeploymentHelpers +{ + public enum RuntimeFlavor + { + clr, + coreclr, + mono + } +} diff --git a/test/DeploymentHelpers/Common/RetryHelper.cs b/test/DeploymentHelpers/Common/RetryHelper.cs new file mode 100644 index 0000000000..43aa02c0ed --- /dev/null +++ b/test/DeploymentHelpers/Common/RetryHelper.cs @@ -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 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. + } + } + } + } + } + } +} \ No newline at end of file diff --git a/test/E2ETests/Common/ServerType.cs b/test/DeploymentHelpers/Common/ServerType.cs similarity index 80% rename from test/E2ETests/Common/ServerType.cs rename to test/DeploymentHelpers/Common/ServerType.cs index ff2fa543b6..0cf6c0131e 100644 --- a/test/E2ETests/Common/ServerType.cs +++ b/test/DeploymentHelpers/Common/ServerType.cs @@ -1,4 +1,4 @@ -namespace E2ETests +namespace DeploymentHelpers { public enum ServerType { diff --git a/test/DeploymentHelpers/Deployers/ApplicationDeployer.cs b/test/DeploymentHelpers/Deployers/ApplicationDeployer.cs new file mode 100644 index 0000000000..b07d3b4f1c --- /dev/null +++ b/test/DeploymentHelpers/Deployers/ApplicationDeployer.cs @@ -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 +{ + /// + /// Abstract base class of all deplolyers with a back bone implementation of some of the common helpers. + /// + 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(); + } +} \ No newline at end of file diff --git a/test/DeploymentHelpers/Deployers/ApplicationDeployerFactory.cs b/test/DeploymentHelpers/Deployers/ApplicationDeployerFactory.cs new file mode 100644 index 0000000000..a6d9304382 --- /dev/null +++ b/test/DeploymentHelpers/Deployers/ApplicationDeployerFactory.cs @@ -0,0 +1,54 @@ +using System; +using Microsoft.Framework.Logging; + +namespace DeploymentHelpers +{ + /// + /// Factory to create an appropriate deployer based on . + /// + public class ApplicationDeployerFactory + { + /// + /// Creates a deployer instance based on settings in . + /// + /// + /// + /// + 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) + ); + } + } + } +} \ No newline at end of file diff --git a/test/DeploymentHelpers/Deployers/IApplicationDeployer.cs b/test/DeploymentHelpers/Deployers/IApplicationDeployer.cs new file mode 100644 index 0000000000..bf27c51e65 --- /dev/null +++ b/test/DeploymentHelpers/Deployers/IApplicationDeployer.cs @@ -0,0 +1,16 @@ +using System; + +namespace DeploymentHelpers +{ + /// + /// Common operations on an application deployer. + /// + public interface IApplicationDeployer : IDisposable + { + /// + /// Deploys the application to the target with specified . + /// + /// + DeploymentResult Deploy(); + } +} \ No newline at end of file diff --git a/test/DeploymentHelpers/Deployers/IISDeployer.cs b/test/DeploymentHelpers/Deployers/IISDeployer.cs new file mode 100644 index 0000000000..c10405be11 --- /dev/null +++ b/test/DeploymentHelpers/Deployers/IISDeployer.cs @@ -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 +{ + /// + /// Deployer for IIS (Both Helios and NativeModule). + /// + 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 \ No newline at end of file diff --git a/test/DeploymentHelpers/Deployers/IISExpressDeployer.cs b/test/DeploymentHelpers/Deployers/IISExpressDeployer.cs new file mode 100644 index 0000000000..2600e792fa --- /dev/null +++ b/test/DeploymentHelpers/Deployers/IISExpressDeployer.cs @@ -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 +{ + /// + /// Deployment helper for IISExpress. + /// + 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(); + } + } +} \ No newline at end of file diff --git a/test/DeploymentHelpers/Deployers/MonoDeployer.cs b/test/DeploymentHelpers/Deployers/MonoDeployer.cs new file mode 100644 index 0000000000..67bfbb65fa --- /dev/null +++ b/test/DeploymentHelpers/Deployers/MonoDeployer.cs @@ -0,0 +1,93 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Microsoft.Framework.Logging; + +namespace DeploymentHelpers +{ + /// + /// Deployer for Kestrel on Mono. + /// + 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(); + } + } +} \ No newline at end of file diff --git a/test/DeploymentHelpers/Deployers/SelfHostDeployer.cs b/test/DeploymentHelpers/Deployers/SelfHostDeployer.cs new file mode 100644 index 0000000000..ca35162a53 --- /dev/null +++ b/test/DeploymentHelpers/Deployers/SelfHostDeployer.cs @@ -0,0 +1,91 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Threading; +using Microsoft.Framework.Logging; + +namespace DeploymentHelpers +{ + /// + /// Deployer for WebListener and Kestrel. + /// + 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(); + } + } +} \ No newline at end of file diff --git a/test/DeploymentHelpers/DeploymentHelpers.xproj b/test/DeploymentHelpers/DeploymentHelpers.xproj new file mode 100644 index 0000000000..7209772a5b --- /dev/null +++ b/test/DeploymentHelpers/DeploymentHelpers.xproj @@ -0,0 +1,26 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + c98e54d3-f4c6-4d16-a5a6-e86a636a7311 + DeploymentHelpers + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + True + + + True + + + diff --git a/test/DeploymentHelpers/project.json b/test/DeploymentHelpers/project.json new file mode 100644 index 0000000000..3c4612fae9 --- /dev/null +++ b/test/DeploymentHelpers/project.json @@ -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-*" + } + } + } +} \ No newline at end of file diff --git a/test/E2ETests/xunit/SkipIfCurrentRuntimeIsCoreClr.cs b/test/DeploymentHelpers/xunit/SkipIfCurrentRuntimeIsCoreClr.cs similarity index 95% rename from test/E2ETests/xunit/SkipIfCurrentRuntimeIsCoreClr.cs rename to test/DeploymentHelpers/xunit/SkipIfCurrentRuntimeIsCoreClr.cs index 82e2533775..0e53655217 100644 --- a/test/E2ETests/xunit/SkipIfCurrentRuntimeIsCoreClr.cs +++ b/test/DeploymentHelpers/xunit/SkipIfCurrentRuntimeIsCoreClr.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using Microsoft.AspNet.Testing.xunit; -namespace E2ETests +namespace DeploymentHelpers { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class SkipIfCurrentRuntimeIsCoreClrAttribute : Attribute, ITestCondition diff --git a/test/E2ETests/xunit/SkipIfNativeModuleNotInstalledAttribute.cs b/test/DeploymentHelpers/xunit/SkipIfNativeModuleNotInstalledAttribute.cs similarity index 96% rename from test/E2ETests/xunit/SkipIfNativeModuleNotInstalledAttribute.cs rename to test/DeploymentHelpers/xunit/SkipIfNativeModuleNotInstalledAttribute.cs index 1196b613ec..e6e62c2330 100644 --- a/test/E2ETests/xunit/SkipIfNativeModuleNotInstalledAttribute.cs +++ b/test/DeploymentHelpers/xunit/SkipIfNativeModuleNotInstalledAttribute.cs @@ -1,7 +1,7 @@ using System; using Microsoft.AspNet.Testing.xunit; -namespace E2ETests +namespace DeploymentHelpers { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class SkipIfNativeModuleNotInstalledAttribute : Attribute, ITestCondition diff --git a/test/E2ETests/xunit/SkipOn32BitOSAttribute.cs b/test/DeploymentHelpers/xunit/SkipOn32BitOSAttribute.cs similarity index 95% rename from test/E2ETests/xunit/SkipOn32BitOSAttribute.cs rename to test/DeploymentHelpers/xunit/SkipOn32BitOSAttribute.cs index 1a6cf49b73..f0b0c324f0 100644 --- a/test/E2ETests/xunit/SkipOn32BitOSAttribute.cs +++ b/test/DeploymentHelpers/xunit/SkipOn32BitOSAttribute.cs @@ -2,7 +2,7 @@ using System.IO; using Microsoft.AspNet.Testing.xunit; -namespace E2ETests +namespace DeploymentHelpers { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class SkipOn32BitOSAttribute : Attribute, ITestCondition diff --git a/test/E2ETests/Common/DeploymentUtility.cs b/test/E2ETests/Common/DeploymentUtility.cs deleted file mode 100644 index 1aeab11de7..0000000000 --- a/test/E2ETests/Common/DeploymentUtility.cs +++ /dev/null @@ -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); - } - } - } - } -} \ No newline at end of file diff --git a/test/E2ETests/Common/DotnetFlavor.cs b/test/E2ETests/Common/DotnetFlavor.cs deleted file mode 100644 index 44e9dffbe2..0000000000 --- a/test/E2ETests/Common/DotnetFlavor.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace E2ETests -{ - public enum RuntimeFlavor - { - DesktopClr, - CoreClr, - Mono - } -} diff --git a/test/E2ETests/Common/Helpers.cs b/test/E2ETests/Common/Helpers.cs index 913289bc81..4ce2ac6c08 100644 --- a/test/E2ETests/Common/Helpers.cs +++ b/test/E2ETests/Common/Helpers.cs @@ -1,7 +1,8 @@ using System; +using System.IO; using System.Net; using System.Net.Http; -using System.Threading; +using DeploymentHelpers; using Microsoft.Framework.Logging; 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 - { - logger.LogWarning("Retry count {retryCount}..", retry + 1); - retryBlock(); - break; //Went through successfully - } - 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. - } - } + // 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\"}"); } } + + 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"); + } } } \ No newline at end of file diff --git a/test/E2ETests/Common/IISApplication.cs b/test/E2ETests/Common/IISApplication.cs deleted file mode 100644 index d74c15e5d8..0000000000 --- a/test/E2ETests/Common/IISApplication.cs +++ /dev/null @@ -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 diff --git a/test/E2ETests/Common/IISExpressHelper.cs b/test/E2ETests/Common/IISExpressHelper.cs deleted file mode 100644 index ee9d164bda..0000000000 --- a/test/E2ETests/Common/IISExpressHelper.cs +++ /dev/null @@ -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); - } - } - } -} \ No newline at end of file diff --git a/test/E2ETests/Common/StartParameters.cs b/test/E2ETests/Common/StartParameters.cs deleted file mode 100644 index 14a85f8143..0000000000 --- a/test/E2ETests/Common/StartParameters.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace E2ETests -{ - /// - /// Summary description for StartParameters - /// - 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 - } -} diff --git a/test/E2ETests/Implementation/FacebookLoginScenarios.cs b/test/E2ETests/Implementation/FacebookLoginScenarios.cs index c44e66e5b9..788ea92add 100644 --- a/test/E2ETests/Implementation/FacebookLoginScenarios.cs +++ b/test/E2ETests/Implementation/FacebookLoginScenarios.cs @@ -9,15 +9,15 @@ using Xunit; namespace E2ETests { - public partial class SmokeTests + public partial class Validator { - private void LoginWithFacebook() + public void LoginWithFacebook() { _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; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; _logger.LogInformation("Signing in with Facebook account"); var formParameters = new List> @@ -33,16 +33,16 @@ namespace E2ETests var queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query)); Assert.Equal("code", queryItems["response_type"]); Assert.Equal("[AppId]", queryItems["client_id"]); - Assert.Equal(_applicationBaseUrl + "signin-facebook", queryItems["redirect_uri"]); + Assert.Equal(_deploymentResult.ApplicationBaseUri + "signin-facebook", queryItems["redirect_uri"]); Assert.Equal("email,read_friendlists,user_checkins", queryItems["scope"]); Assert.Equal("ValidStateData", queryItems["state"]); Assert.Equal("custom", queryItems["custom_redirect_uri"]); //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. _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; responseContent = response.Content.ReadAsStringAsync().Result; @@ -58,15 +58,15 @@ namespace E2ETests //Post a message to the Facebook middleware response = _httpClient.GetAsync("signin-facebook?code=ValidCode&state=ValidStateData").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; //Correlation cookie not getting cleared after successful signin? 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); formParameters = new List> @@ -77,14 +77,14 @@ namespace E2ETests content = new FormUrlEncodedContent(formParameters.ToArray()); response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains(string.Format("Hello {0}!", "AspnetvnextTest@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); //Verify cookie sent - Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); - Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin")); + Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); + 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("Verifying if the middleware notifications were fired"); diff --git a/test/E2ETests/Implementation/GoogleLoginScenarios.cs b/test/E2ETests/Implementation/GoogleLoginScenarios.cs index b97d1772c5..17b322ca48 100644 --- a/test/E2ETests/Implementation/GoogleLoginScenarios.cs +++ b/test/E2ETests/Implementation/GoogleLoginScenarios.cs @@ -9,15 +9,15 @@ using Xunit; namespace E2ETests { - public partial class SmokeTests + public partial class Validator { - private void LoginWithGoogle() + public void LoginWithGoogle() { _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; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; _logger.LogInformation("Signing in with Google account"); var formParameters = new List> @@ -34,16 +34,16 @@ namespace E2ETests Assert.Equal("code", queryItems["response_type"]); Assert.Equal("offline", queryItems["access_type"]); Assert.Equal("[ClientId]", queryItems["client_id"]); - Assert.Equal(_applicationBaseUrl + "signin-google", queryItems["redirect_uri"]); + Assert.Equal(_deploymentResult.ApplicationBaseUri + "signin-google", queryItems["redirect_uri"]); Assert.Equal("openid profile email", queryItems["scope"]); Assert.Equal("ValidStateData", queryItems["state"]); Assert.Equal("custom", queryItems["custom_redirect_uri"]); //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. _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; responseContent = response.Content.ReadAsStringAsync().Result; @@ -59,15 +59,15 @@ namespace E2ETests //Post a message to the Google middleware response = _httpClient.GetAsync("signin-google?code=ValidCode&state=ValidStateData").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; //Correlation cookie not getting cleared after successful signin? 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); formParameters = new List> @@ -78,14 +78,14 @@ namespace E2ETests content = new FormUrlEncodedContent(formParameters.ToArray()); response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains(string.Format("Hello {0}!", "AspnetvnextTest@gmail.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); //Verify cookie sent - Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); - Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin")); + Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); + 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("Verifying if the middleware notifications were fired"); diff --git a/test/E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs b/test/E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs index 9c96167dd5..2d08228bd8 100644 --- a/test/E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs +++ b/test/E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs @@ -9,15 +9,15 @@ using Xunit; namespace E2ETests { - public partial class SmokeTests + public partial class Validator { - private void LoginWithMicrosoftAccount() + public void LoginWithMicrosoftAccount() { _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; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; _logger.LogInformation("Signing in with Microsoft account"); var formParameters = new List> @@ -33,17 +33,17 @@ namespace E2ETests var queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query)); Assert.Equal("code", queryItems["response_type"]); Assert.Equal("[ClientId]", queryItems["client_id"]); - Assert.Equal(_applicationBaseUrl + "signin-microsoft", queryItems["redirect_uri"]); + Assert.Equal(_deploymentResult.ApplicationBaseUri + "signin-microsoft", queryItems["redirect_uri"]); Assert.Equal("wl.basic wl.signin", queryItems["scope"]); Assert.Equal("ValidStateData", queryItems["state"]); Assert.Equal("custom", queryItems["custom_redirect_uri"]); //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. _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; responseContent = response.Content.ReadAsStringAsync().Result; @@ -59,15 +59,15 @@ namespace E2ETests //Post a message to the MicrosoftAccount middleware response = _httpClient.GetAsync("signin-microsoft?code=ValidCode&state=ValidStateData").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; //Correlation cookie not getting cleared after successful signin? 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> { @@ -77,14 +77,14 @@ namespace E2ETests content = new FormUrlEncodedContent(formParameters.ToArray()); response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains(string.Format("Hello {0}!", "microsoft@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); //Verify cookie sent - Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); - Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin")); + Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); + 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("Verifying if the middleware notifications were fired"); diff --git a/test/E2ETests/Implementation/OpenIdConnectLoginScenarios.cs b/test/E2ETests/Implementation/OpenIdConnectLoginScenarios.cs index f190622c42..94e3d8794b 100644 --- a/test/E2ETests/Implementation/OpenIdConnectLoginScenarios.cs +++ b/test/E2ETests/Implementation/OpenIdConnectLoginScenarios.cs @@ -9,15 +9,15 @@ using Xunit; namespace E2ETests { - public partial class SmokeTests + public partial class Validator { - private void LoginWithOpenIdConnect() + public void LoginWithOpenIdConnect() { _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; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; _logger.LogInformation("Signing in with OpenIdConnect account"); var formParameters = new List> @@ -37,12 +37,12 @@ namespace E2ETests Assert.Equal("openid profile", queryItems["scope"]); Assert.Equal("OpenIdConnect.AuthenticationProperties=ValidStateData", queryItems["state"]); 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. _httpClientHandler = new HttpClientHandler() { AllowAutoRedirect = true }; - _httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) }; - _httpClientHandler.CookieContainer.Add(new Uri(_applicationBaseUrl), new Cookie(".AspNet.OpenIdConnect.Nonce.protectedString", "N")); + _httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) }; + _httpClientHandler.CookieContainer.Add(new Uri(_deploymentResult.ApplicationBaseUri), new Cookie(".AspNet.OpenIdConnect.Nonce.protectedString", "N")); //Post a message to the OpenIdConnect middleware var token = new List> @@ -54,9 +54,9 @@ namespace E2ETests }; response = _httpClient.PostAsync(string.Empty, new FormUrlEncodedContent(token.ToArray())).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); 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> { @@ -66,14 +66,14 @@ namespace E2ETests content = new FormUrlEncodedContent(formParameters.ToArray()); response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains(string.Format("Hello {0}!", "User3@aspnettest.onmicrosoft.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); //Verify cookie sent - Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); - Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin")); + Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); + 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("Verifying if the middleware notifications were fired"); @@ -85,7 +85,7 @@ namespace E2ETests _logger.LogInformation("Verifying the OpenIdConnect logout flow.."); response = _httpClient.GetAsync(string.Empty).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; ValidateLayoutPage(responseContent); formParameters = new List> @@ -96,16 +96,16 @@ namespace E2ETests content = new FormUrlEncodedContent(formParameters.ToArray()); // Need a non-redirecting handler var handler = new HttpClientHandler() { AllowAutoRedirect = false }; - handler.CookieContainer.Add(new Uri(_applicationBaseUrl), _httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl))); - _httpClient = new HttpClient(handler) { BaseAddress = new Uri(_applicationBaseUrl) }; + handler.CookieContainer.Add(new Uri(_deploymentResult.ApplicationBaseUri), _httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri))); + _httpClient = new HttpClient(handler) { BaseAddress = new Uri(_deploymentResult.ApplicationBaseUri) }; 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( "https://login.windows.net/4afbc689-805b-48cf-a24c-d4aa3248a248/oauth2/logout", response.Headers.Location.AbsoluteUri.Replace(response.Headers.Location.Query, string.Empty)); queryItems = new ReadableStringCollection(QueryHelpers.ParseQuery(response.Headers.Location.Query)); - Assert.Equal(_applicationBaseUrl + "Account/Login", queryItems["post_logout_redirect_uri"]); + Assert.Equal(_deploymentResult.ApplicationBaseUri + "Account/Login", queryItems["post_logout_redirect_uri"]); } } } \ No newline at end of file diff --git a/test/E2ETests/Implementation/TwitterLoginScenarios.cs b/test/E2ETests/Implementation/TwitterLoginScenarios.cs index d1879a870d..3c9663bb23 100644 --- a/test/E2ETests/Implementation/TwitterLoginScenarios.cs +++ b/test/E2ETests/Implementation/TwitterLoginScenarios.cs @@ -12,15 +12,15 @@ namespace E2ETests /// /// Summary description for TwitterLoginScenarios /// - public partial class SmokeTests + public partial class Validator { - private void LoginWithTwitter() + public void LoginWithTwitter() { _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; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; _logger.LogInformation("Signing in with Twitter account"); var formParameters = new List> @@ -37,11 +37,11 @@ namespace E2ETests Assert.Equal("custom", queryItems["custom_redirect_uri"]); Assert.Equal("valid_oauth_token", queryItems["oauth_token"]); //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. _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; responseContent = response.Content.ReadAsStringAsync().Result; @@ -57,15 +57,15 @@ namespace E2ETests //Post a message to the Facebook middleware 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; //Check correlation cookie not getting cleared after successful signin 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. //Assert.Contains("AspnetvnextTest@gmail.com", responseContent, StringComparison.OrdinalIgnoreCase); @@ -77,14 +77,14 @@ namespace E2ETests content = new FormUrlEncodedContent(formParameters.ToArray()); response = _httpClient.PostAsync("Account/ExternalLoginConfirmation", content).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains(string.Format("Hello {0}!", "twitter@test.com"), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); //Verify cookie sent - Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); - Assert.Null(_httpClientHandler.CookieContainer.GetCookies(new Uri(_applicationBaseUrl)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.ExternalLogin")); + Assert.NotNull(_httpClientHandler.CookieContainer.GetCookies(new Uri(_deploymentResult.ApplicationBaseUri)).GetCookieWithName(".AspNet.Microsoft.AspNet.Identity.Application")); + 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("Verifying if the middleware notifications were fired"); diff --git a/test/E2ETests/Implementation/Scenarios.cs b/test/E2ETests/Implementation/Validator.cs similarity index 77% rename from test/E2ETests/Implementation/Scenarios.cs rename to test/E2ETests/Implementation/Validator.cs index 72dd1a5ab3..a6b8a45a4b 100644 --- a/test/E2ETests/Implementation/Scenarios.cs +++ b/test/E2ETests/Implementation/Validator.cs @@ -4,45 +4,46 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Threading; +using DeploymentHelpers; using Microsoft.AspNet.SignalR.Client; using Microsoft.Framework.Logging; using Xunit; 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.."); - _logger.LogInformation("Fetching favicon.ico.."); - var response = _httpClient.GetAsync("favicon.ico").Result; - ThrowIfResponseStatusNotOk(response); - _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"); + _httpClient = httpClient; + _httpClientHandler = httpClientHandler; + _logger = logger; + _deploymentResult = deploymentResult; } - 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. - //_logger.WriteVerbose("Home page content : {0}", responseContent); + var responseContent = response.Content.ReadAsStringAsync().Result; + + 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); ValidateLayoutPage(responseContent); - Assert.Contains(PrefixBaseAddress("Home Page – ASP.NET MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase); if (!useNtlmAuthentication) @@ -57,24 +58,77 @@ namespace E2ETests _logger.LogInformation("Application initialization successful."); _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. - ThrowIfResponseStatusNotOk(runtimeResponse); + //Helpers.ThrowIfResponseStatusNotOk(runtimeResponse, _logger); } - var runtimeInfo = runtimeResponse.Content.ReadAsStringAsync().Result; - _logger.LogInformation(runtimeInfo); + //var runtimeInfo = runtimeResponse.Content.ReadAsStringAsync().Result; + //_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("
  • Home
  • ", _deploymentResult.DeploymentParameters.ServerType), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains(Helpers.PrefixBaseAddress("Store ", _deploymentResult.DeploymentParameters.ServerType), responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("
      ", responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("
    • ", 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(_deploymentResult.ApplicationBaseUri + "Admin/StoreManager/", response.RequestMessage.RequestUri.AbsoluteUri); + _logger.LogInformation("Successfully acccessed the store inventory"); } private string PrefixBaseAddress(string url) { #if DNX451 - url = (_startParameters.ServerType == ServerType.IISNativeModule || - _startParameters.ServerType == ServerType.IIS) ? - string.Format(url, _startParameters.IISApplication.VirtualDirectoryName) : + url = (_deploymentResult.DeploymentParameters.ServerType == ServerType.IISNativeModule || + _deploymentResult.DeploymentParameters.ServerType == ServerType.IIS) ? + string.Format(url, new Uri(_deploymentResult.ApplicationBaseUri).Segments[1].TrimEnd('/')) : string.Format(url, string.Empty); #else url = string.Format(url, string.Empty); @@ -83,43 +137,24 @@ namespace E2ETests return url.Replace("//", "/").Replace("%2F%2F", "%2F").Replace("%2F/", "%2F"); } - private void ValidateLayoutPage(string responseContent) - { - Assert.Contains("ASP.NET MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase); - Assert.Contains(PrefixBaseAddress("
    • Home
    • "), responseContent, StringComparison.OrdinalIgnoreCase); - Assert.Contains(PrefixBaseAddress("Store "), responseContent, StringComparison.OrdinalIgnoreCase); - Assert.Contains("
        ", responseContent, StringComparison.OrdinalIgnoreCase); - Assert.Contains("
      • ", responseContent, StringComparison.OrdinalIgnoreCase); - } - - private void AccessStoreWithoutPermissions(string email = null) + public void AccessStoreWithoutPermissions(string email = null) { _logger.LogInformation("Trying to access StoreManager that needs ManageStore claim with the current user : {email}", email ?? "Anonymous"); var response = _httpClient.GetAsync("Admin/StoreManager/").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; ValidateLayoutPage(responseContent); Assert.Contains("Log in – ASP.NET MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("

        Use a local account to log in.

        ", responseContent, StringComparison.OrdinalIgnoreCase); - Assert.Equal(_applicationBaseUrl + PrefixBaseAddress("Account/Login?ReturnUrl=%2F{0}%2FAdmin%2FStoreManager%2F"), response.RequestMessage.RequestUri.AbsoluteUri); + Assert.Equal(_deploymentResult.ApplicationBaseUri + PrefixBaseAddress("Account/Login?ReturnUrl=%2F{0}%2FAdmin%2FStoreManager%2F"), response.RequestMessage.RequestUri.AbsoluteUri); _logger.LogInformation("Redirected to login page as expected."); } - private void AccessStoreWithPermissions() - { - _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(_applicationBaseUrl + "Admin/StoreManager/", response.RequestMessage.RequestUri.AbsoluteUri); - _logger.LogInformation("Successfully acccessed the store inventory"); - } - - private void RegisterUserWithNonMatchingPasswords() + public void RegisterUserWithNonMatchingPasswords() { _logger.LogInformation("Trying to create user with not matching password and confirm password"); var response = _httpClient.GetAsync("Account/Register").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; ValidateLayoutPage(responseContent); @@ -136,15 +171,15 @@ namespace E2ETests var content = new FormUrlEncodedContent(formParameters.ToArray()); response = _httpClient.PostAsync("Account/Register", content).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("
        • The password and confirmation password do not match.
        • ", responseContent, StringComparison.OrdinalIgnoreCase); _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; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; ValidateLayoutPage(responseContent); @@ -163,24 +198,24 @@ namespace E2ETests responseContent = response.Content.ReadAsStringAsync().Result; //Account verification - Assert.Equal(_applicationBaseUrl + "Account/Register", response.RequestMessage.RequestUri.AbsoluteUri); + Assert.Equal(_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); var startIndex = responseContent.IndexOf("[[link]]", startIndex); var confirmUrl = responseContent.Substring(startIndex, endIndex - startIndex); confirmUrl = WebUtility.HtmlDecode(confirmUrl); response = _httpClient.GetAsync(confirmUrl).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains("Thank you for confirming your email.", responseContent, StringComparison.OrdinalIgnoreCase); return generatedEmail; } - private void RegisterExistingUser(string email) + public void RegisterExistingUser(string email) { _logger.LogInformation("Trying to register a user with name '{email}' again", email); var response = _httpClient.GetAsync("Account/Register").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; _logger.LogInformation("Creating a new user with name '{email}'", email); var formParameters = new List> @@ -198,11 +233,11 @@ namespace E2ETests _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); var response = _httpClient.GetAsync(string.Empty).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; ValidateLayoutPage(responseContent); var formParameters = new List> @@ -222,21 +257,21 @@ namespace E2ETests Assert.Contains("www.github.com/aspnet/MusicStore", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("/Images/home-showcase.png", responseContent, StringComparison.OrdinalIgnoreCase); //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); } else { //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(); - _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; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; _logger.LogInformation("Signing in with user '{email}'", email); var formParameters = new List> @@ -251,14 +286,14 @@ namespace E2ETests responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains("
          • Invalid login attempt.
          • ", responseContent, StringComparison.OrdinalIgnoreCase); //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."); } - private void SignInWithUser(string email, string password) + public void SignInWithUser(string email, string password) { var response = _httpClient.GetAsync("Account/Login").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; _logger.LogInformation("Signing in with user '{email}'", email); var formParameters = new List> @@ -274,14 +309,14 @@ namespace E2ETests Assert.Contains(string.Format("Hello {0}!", email), responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Log off", responseContent, StringComparison.OrdinalIgnoreCase); //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); } - private void ChangePassword(string email) + public void ChangePassword(string email) { var response = _httpClient.GetAsync("Manage/ChangePassword").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; var formParameters = new List> { @@ -295,17 +330,17 @@ namespace E2ETests response = _httpClient.PostAsync("Manage/ChangePassword", content).Result; responseContent = response.Content.ReadAsStringAsync().Result; 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); } - private string CreateAlbum() + public string CreateAlbum() { var albumName = Guid.NewGuid().ToString().Replace("-", string.Empty).Substring(0, 12); #if DNX451 string dataFromHub = null; var OnReceivedEvent = new AutoResetEvent(false); - var hubConnection = new HubConnection(_applicationBaseUrl + "SignalR"); + var hubConnection = new HubConnection(_deploymentResult.ApplicationBaseUri + "SignalR"); hubConnection.Received += (data) => { _logger.LogVerbose("Data received by SignalR client: {receivedData}", data); @@ -318,7 +353,7 @@ namespace E2ETests #endif _logger.LogInformation("Trying to create an album with name '{album}'", albumName); var response = _httpClient.GetAsync("Admin/StoreManager/create").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; var formParameters = new List> { @@ -333,7 +368,7 @@ namespace E2ETests var content = new FormUrlEncodedContent(formParameters.ToArray()); response = _httpClient.PostAsync("Admin/StoreManager/create", content).Result; responseContent = response.Content.ReadAsStringAsync().Result; - Assert.Equal(_applicationBaseUrl + "Admin/StoreManager", response.RequestMessage.RequestUri.AbsoluteUri); + Assert.Equal(_deploymentResult.ApplicationBaseUri + "Admin/StoreManager", response.RequestMessage.RequestUri.AbsoluteUri); Assert.Contains(albumName, responseContent); #if DNX451 _logger.LogInformation("Waiting for the SignalR client to receive album created announcement"); @@ -345,20 +380,20 @@ namespace E2ETests return albumName; } - private string FetchAlbumIdFromName(string albumName) + public string FetchAlbumIdFromName(string albumName) { // Run some CORS validation. _logger.LogInformation("Fetching the album id of '{album}'", albumName); _httpClient.DefaultRequestHeaders.Add("Origin", "http://notpermitteddomain.com"); var response = _httpClient.GetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); IEnumerable values; Assert.False(response.Headers.TryGetValues("Access-Control-Allow-Origin", out values)); _httpClient.DefaultRequestHeaders.Remove("Origin"); _httpClient.DefaultRequestHeaders.Add("Origin", "http://example.com"); 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()); _httpClient.DefaultRequestHeaders.Remove("Origin"); @@ -367,11 +402,11 @@ namespace E2ETests 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); 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; Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("http://myapp/testurl", responseContent, StringComparison.OrdinalIgnoreCase); @@ -379,42 +414,42 @@ namespace E2ETests Assert.Contains(PrefixBaseAddress("Back to List"), responseContent, StringComparison.OrdinalIgnoreCase); } - private void VerifyStatusCodePages() + public void VerifyStatusCodePages() { _logger.LogInformation("Getting details of a non-existing album with Id '-1'"); var response = _httpClient.GetAsync("Admin/StoreManager/Details?id=-1").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains("Item not found.", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Equal(PrefixBaseAddress("/{0}/Home/StatusCodePage"), response.RequestMessage.RequestUri.AbsolutePath); } // 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); var response = _httpClient.GetAsync(string.Format("Store/Details/{0}", albumId)).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; 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); var response = _httpClient.GetAsync(string.Format("ShoppingCart/AddToCart?id={0}", albumId)).Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains(albumName, responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("", responseContent, StringComparison.OrdinalIgnoreCase); _logger.LogInformation("Verified that album is added to cart"); } - private void CheckOutCartItems() + public void CheckOutCartItems() { _logger.LogInformation("Checking out the cart contents..."); var response = _httpClient.GetAsync("Checkout/AddressAndPayment").Result; - ThrowIfResponseStatusNotOk(response); + Helpers.ThrowIfResponseStatusNotOk(response, _logger); var responseContent = response.Content.ReadAsStringAsync().Result; var formParameters = new List> @@ -436,10 +471,10 @@ namespace E2ETests response = _httpClient.PostAsync("Checkout/AddressAndPayment", content).Result; responseContent = response.Content.ReadAsStringAsync().Result; Assert.Contains("

            Checkout Complete

            ", 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); @@ -450,21 +485,12 @@ namespace E2ETests var content = new FormUrlEncodedContent(formParameters.ToArray()); 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); response = _httpClient.GetAsync(string.Format("Admin/StoreManager/GetAlbumIdFromName?albumName={0}", albumName)).Result; Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); _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)); - } - } } } \ No newline at end of file diff --git a/test/E2ETests/NtlmAuthentation.config b/test/E2ETests/NtlmAuthentation.config index 4a8bf5d9e3..d14f5fc1f2 100644 --- a/test/E2ETests/NtlmAuthentation.config +++ b/test/E2ETests/NtlmAuthentation.config @@ -159,7 +159,7 @@ - + diff --git a/test/E2ETests/NtlmAuthentationTest.cs b/test/E2ETests/NtlmAuthentationTest.cs index 6429e493ba..4555637c74 100644 --- a/test/E2ETests/NtlmAuthentationTest.cs +++ b/test/E2ETests/NtlmAuthentationTest.cs @@ -1,89 +1,93 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net.Http; +using DeploymentHelpers; using Microsoft.AspNet.Testing.xunit; using Microsoft.Framework.Logging; using Xunit; namespace E2ETests { - public partial class SmokeTests + // Uses ports ranging 5050 - 5060. + public class NtlmAuthenticationTests { [ConditionalTheory, Trait("E2Etests", "E2Etests")] [OSSkipCondition(OperatingSystems.Unix | OperatingSystems.MacOSX)] - [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5001/")] - [InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.amd64, "http://localhost:5001/")] - [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5002/")] + [InlineData(ServerType.IISExpress, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5050/")] + [InlineData(ServerType.IISExpress, RuntimeFlavor.clr, RuntimeArchitecture.x64, "http://localhost:5051/")] + [InlineData(ServerType.WebListener, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5052/")] 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); - _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, - RuntimeFlavor = runtimeFlavor, - RuntimeArchitecture = architecture, + ApplicationBaseUriHint = applicationBaseUrl, EnvironmentName = "NtlmAuthentication", //Will pick the Start class named 'StartupNtlmAuthentication' 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(); - var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty); + // Override the connection strings using environment based configuration + deploymentParameters.EnvironmentVariables + .Add(new KeyValuePair("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; - try + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger)) { - hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger); - - _httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; - _httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(applicationBaseUrl) }; + var deploymentResult = deployer.Deploy(); + var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; + var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; 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. - Helpers.Retry(() => + // Request to base address and check if various parts of the body are rendered & measure the cold startup time. + RetryHelper.RetryRequest(() => { - response = _httpClient.GetAsync(string.Empty).Result; - responseContent = response.Content.ReadAsStringAsync().Result; - _logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds); - }, logger: _logger); + response = httpClient.GetAsync(string.Empty).Result; + return response; + }, 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 - Assert.Contains( - string.Format("{0}\\{1}", Environment.GetEnvironmentVariable("USERDOMAIN"), Environment.GetEnvironmentVariable("USERNAME")), - responseContent, StringComparison.OrdinalIgnoreCase); + var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); + validator.VerifyNtlmHomePage(response); //Should be able to access the store as the Startup adds necessary permissions for the current user - AccessStoreWithPermissions(); + validator.AccessStoreWithPermissions(); 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; } - finally - { - if (!testSuccessful) - { - _logger.LogError("Some tests failed. Proceeding with cleanup."); - } - DeploymentUtility.CleanUpApplication(_startParameters, hostProcess, musicStoreDbName, _logger); + if (!testSuccessful) + { + logger.LogError("Some tests failed."); } } } diff --git a/test/E2ETests/OpenIdConnectTests.cs b/test/E2ETests/OpenIdConnectTests.cs index 527d4c1c93..e88f52de7c 100644 --- a/test/E2ETests/OpenIdConnectTests.cs +++ b/test/E2ETests/OpenIdConnectTests.cs @@ -1,18 +1,21 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Net.Http; +using DeploymentHelpers; using Microsoft.AspNet.Testing.xunit; using Microsoft.Framework.Logging; using Xunit; namespace E2ETests { - public partial class SmokeTests + // Uses ports ranging 5040 - 5049. + public class OpenIdConnectTests { [ConditionalTheory, Trait("E2Etests", "E2Etests")] [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/")] - [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5001/")] + [InlineData(ServerType.IISExpress, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5040/")] + [InlineData(ServerType.IISExpress, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5041/")] public void OpenIdConnect_OnX86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl) { OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationBaseUrl); @@ -20,80 +23,80 @@ namespace E2ETests [ConditionalTheory, Trait("E2Etests", "E2Etests")] [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) { 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")) - { - _logger.LogInformation("Variation Details : HostType = {hostType}, DonetFlavor = {flavor}, Architecture = {arch}, applicationBaseUrl = {appBase}", - serverType, donetFlavor, architecture, applicationBaseUrl); + var logger = new LoggerFactory() + .AddConsole() + .CreateLogger(string.Format("OpenId:{0}:{1}:{2}", serverType, runtimeFlavor, architecture)); - _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, - RuntimeFlavor = donetFlavor, - RuntimeArchitecture = architecture, - EnvironmentName = "OpenIdConnectTesting" + ApplicationBaseUriHint = applicationBaseUrl, + EnvironmentName = "OpenIdConnectTesting", + UserAdditionalCleanup = parameters => + { + if (!Helpers.RunningOnMono) + { + // Mono uses InMemoryStore + DbUtils.DropDatabase(musicStoreDbName, logger); + } + } }; - var stopwatch = Stopwatch.StartNew(); - var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty); + // Override the connection strings using environment based configuration + deploymentParameters.EnvironmentVariables + .Add(new KeyValuePair("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; - try + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger)) { - hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger); -#if DNX451 - if (serverType == ServerType.IISNativeModule || serverType == ServerType.IIS) - { - // Accomodate the vdir name. - _applicationBaseUrl += _startParameters.IISApplication.VirtualDirectoryName + "/"; - } -#endif - _httpClientHandler = new HttpClientHandler(); - _httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) }; + var deploymentResult = deployer.Deploy(); + var httpClientHandler = new HttpClientHandler(); + var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; 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. - Helpers.Retry(() => + // Request to base address and check if various parts of the body are rendered & measure the cold startup time. + RetryHelper.RetryRequest(() => { - response = _httpClient.GetAsync(string.Empty).Result; - responseContent = response.Content.ReadAsStringAsync().Result; - _logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds); - }, logger: _logger); + response = httpClient.GetAsync(string.Empty).Result; + return response; + }, 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. - LoginWithOpenIdConnect(); + validator.LoginWithOpenIdConnect(); 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; } - finally - { - if (!testSuccessful) - { - _logger.LogError("Some tests failed. Proceeding with cleanup."); - } - DeploymentUtility.CleanUpApplication(_startParameters, hostProcess, musicStoreDbName, _logger); + if (!testSuccessful) + { + logger.LogError("Some tests failed."); } } } diff --git a/test/E2ETests/PublishAndRunTests.cs b/test/E2ETests/PublishAndRunTests.cs index 4c1f5f976b..c543c522fc 100644 --- a/test/E2ETests/PublishAndRunTests.cs +++ b/test/E2ETests/PublishAndRunTests.cs @@ -1,115 +1,133 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net.Http; +using DeploymentHelpers; using Microsoft.AspNet.Testing.xunit; using Microsoft.Framework.Logging; using Xunit; namespace E2ETests { - public partial class SmokeTests + // Uses ports ranging 5025 - 5039. + public class PublishAndRunTests_OnX64 { [ConditionalTheory, Trait("E2Etests", "E2Etests")] [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/", false)] - [InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/", true)] + [InlineData(ServerType.WebListener, RuntimeFlavor.clr, RuntimeArchitecture.x64, "http://localhost:5025/", false)] + //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) { - 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")] [FrameworkSkipCondition(RuntimeFrameworks.DotNet)] - [InlineData(ServerType.Kestrel, RuntimeFlavor.Mono, RuntimeArchitecture.x86, "http://localhost:5004/", false)] - [InlineData(ServerType.Kestrel, RuntimeFlavor.Mono, RuntimeArchitecture.x86, "http://localhost:5004/", true)] + [InlineData(ServerType.Kestrel, RuntimeFlavor.mono, RuntimeArchitecture.x86, "http://localhost:5029/", false)] + [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) { - 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")] - [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [InlineData(ServerType.WebListener, RuntimeFlavor.DesktopClr, RuntimeArchitecture.amd64, "http://localhost:5002/", false)] - //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) + public class PublishAndRunTests + { + public void Publish_And_Run_Tests(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); - _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, - RuntimeFlavor = runtimeFlavor, - RuntimeArchitecture = architecture, - PublishApplicationBeforeStart = true, - PublishWithNoSource = noSource + ApplicationBaseUriHint = applicationBaseUrl, + PublishApplicationBeforeDeployment = true, + PublishWithNoSource = noSource, + UserAdditionalCleanup = parameters => + { + if (!Helpers.RunningOnMono) + { + // Mono uses InMemoryStore + DbUtils.DropDatabase(musicStoreDbName, logger); + } + } }; - var stopwatch = Stopwatch.StartNew(); - var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty); + // Override the connection strings using environment based configuration + deploymentParameters.EnvironmentVariables + .Add(new KeyValuePair("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; - try + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger)) { - hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger); - - _httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; - _httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(applicationBaseUrl) }; + var deploymentResult = deployer.Deploy(); + var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; + var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; 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. - //Add retry logic since tests are flaky on mono due to connection issues - Helpers.Retry(() => + // 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 + RetryHelper.RetryRequest(() => { - response = _httpClient.GetAsync(string.Empty).Result; - responseContent = response.Content.ReadAsStringAsync().Result; - _logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds); - }, logger: _logger); + response = httpClient.GetAsync(string.Empty).Result; + return response; + }, logger: logger); - VerifyHomePage(response, responseContent, true); + logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds); - //Static files are served? - VerifyStaticContentServed(); + var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); + validator.VerifyHomePage(response); + + // Static files are served? + validator.VerifyStaticContentServed(); 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."); } } 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; } - finally - { - if (!testSuccessful) - { - _logger.LogError("Some tests failed. Proceeding with cleanup."); - } - DeploymentUtility.CleanUpApplication(_startParameters, hostProcess, musicStoreDbName, _logger); + if (!testSuccessful) + { + logger.LogError("Some tests failed."); } } } diff --git a/test/E2ETests/SmokeTests.cs b/test/E2ETests/SmokeTests.cs index c3bd7acb0f..e0c5658f4a 100644 --- a/test/E2ETests/SmokeTests.cs +++ b/test/E2ETests/SmokeTests.cs @@ -1,238 +1,260 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.Net.Http; +using DeploymentHelpers; using Microsoft.AspNet.Testing.xunit; using Microsoft.Framework.Logging; using Xunit; 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(); - } - [ConditionalTheory, Trait("E2Etests", "E2Etests")] [FrameworkSkipCondition(RuntimeFrameworks.Mono)] - [InlineData(ServerType.IISExpress, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5001/")] - [InlineData(ServerType.WebListener, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5002/")] - [InlineData(ServerType.Kestrel, RuntimeFlavor.DesktopClr, RuntimeArchitecture.x86, "http://localhost:5004/")] - [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5001/")] - [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) + [InlineData(ServerType.IISExpress, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5001/")] + [InlineData(ServerType.WebListener, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5002/")] + [InlineData(ServerType.Kestrel, RuntimeFlavor.clr, RuntimeArchitecture.x86, "http://localhost:5003/")] + public void SmokeTestSuite_OnX86_clr(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")] [FrameworkSkipCondition(RuntimeFrameworks.Mono)] [SkipOn32BitOS] - [InlineData(ServerType.WebListener, RuntimeFlavor.DesktopClr, RuntimeArchitecture.amd64, "http://localhost:5002/")] - [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5001/")] - [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5004/")] - public void SmokeTestSuite_OnAMD64(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl) + [InlineData(ServerType.WebListener, RuntimeFlavor.clr, RuntimeArchitecture.x64, "http://localhost:5007/")] + [InlineData(ServerType.IISExpress, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5008/")] + [InlineData(ServerType.Kestrel, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5009/")] + 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")] [FrameworkSkipCondition(RuntimeFrameworks.DotNet)] - [InlineData(ServerType.Kestrel, RuntimeFlavor.Mono, RuntimeArchitecture.x86, "http://localhost:5004/")] - public void SmokeTestSuite_OnMono(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl) + [InlineData(ServerType.Kestrel, RuntimeFlavor.mono, RuntimeArchitecture.x86, "http://localhost:5010/")] + 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] [FrameworkSkipCondition(RuntimeFrameworks.Mono)] [OSSkipCondition(OperatingSystems.Win7And2008R2 | OperatingSystems.MacOSX | OperatingSystems.Unix)] [SkipIfCurrentRuntimeIsCoreClr] - [InlineData(ServerType.IISNativeModule, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5005/")] - public void SmokeTestSuite_On_NativeModule_X86(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl) + [InlineData(ServerType.IISNativeModule, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5011/")] + 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] [FrameworkSkipCondition(RuntimeFrameworks.Mono)] [OSSkipCondition(OperatingSystems.Win7And2008R2 | OperatingSystems.MacOSX | OperatingSystems.Unix)] [SkipOn32BitOS] [SkipIfCurrentRuntimeIsCoreClr] - [InlineData(ServerType.IISNativeModule, RuntimeFlavor.CoreClr, RuntimeArchitecture.amd64, "http://localhost:5005/")] - public void SmokeTestSuite_On_NativeModule_AMD64(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl) + [InlineData(ServerType.IISNativeModule, RuntimeFlavor.coreclr, RuntimeArchitecture.x64, "http://localhost:5012/")] + 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)] [OSSkipCondition(OperatingSystems.MacOSX | OperatingSystems.Unix)] [SkipIfCurrentRuntimeIsCoreClr] - [InlineData(ServerType.IIS, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5005/")] - public void SmokeTestSuite_On_IIS_X86(ServerType serverType, RuntimeFlavor donetFlavor, RuntimeArchitecture architecture, string applicationBaseUrl) + [InlineData(ServerType.IIS, RuntimeFlavor.coreclr, RuntimeArchitecture.x86, "http://localhost:5013/")] + 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); - _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, - RuntimeFlavor = donetFlavor, - RuntimeArchitecture = architecture, - EnvironmentName = "SocialTesting" + ApplicationBaseUriHint = applicationBaseUrl, + EnvironmentName = "SocialTesting", + UserAdditionalCleanup = parameters => + { + if (!Helpers.RunningOnMono) + { + // Mono uses InMemoryStore + DbUtils.DropDatabase(musicStoreDbName, logger); + } + } }; - var stopwatch = Stopwatch.StartNew(); - var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty); + // Override the connection strings using environment based configuration + deploymentParameters.EnvironmentVariables + .Add(new KeyValuePair("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; - try + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger)) { - hostProcess = DeploymentUtility.StartApplication(_startParameters, _logger); -#if DNX451 - if (serverType == ServerType.IISNativeModule || serverType == ServerType.IIS) - { - // Accomodate the vdir name. - _applicationBaseUrl += _startParameters.IISApplication.VirtualDirectoryName + "/"; - } -#endif - _httpClientHandler = new HttpClientHandler(); - _httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(_applicationBaseUrl) }; + var deploymentResult = deployer.Deploy(); + Helpers.SetInMemoryStoreForIIS(deploymentParameters, logger); + + var httpClientHandler = new HttpClientHandler(); + var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; 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. - Helpers.Retry(() => + // Request to base address and check if various parts of the body are rendered & measure the cold startup time. + RetryHelper.RetryRequest(() => { - response = _httpClient.GetAsync(string.Empty).Result; - responseContent = response.Content.ReadAsStringAsync().Result; - _logger.LogInformation("[Time]: Approximate time taken for application initialization : '{t}' seconds", stopwatch.Elapsed.TotalSeconds); - }, logger: _logger); + response = httpClient.GetAsync(string.Empty).Result; + return response; + }, 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 - VerifyStaticContentServed(); + var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); - //Making a request to a protected resource should automatically redirect to login page - AccessStoreWithoutPermissions(); + validator.VerifyHomePage(response); - //Register a user - Negative scenario where the Password & ConfirmPassword do not match - RegisterUserWithNonMatchingPasswords(); + // Verify the static file middleware can serve static content. + validator.VerifyStaticContentServed(); - //Register a valid user - var generatedEmail = RegisterValidUser(); + // Making a request to a protected resource should automatically redirect to login page. + 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. - RegisterExistingUser(generatedEmail); + // Register a valid user. + var generatedEmail = validator.RegisterValidUser(); - //Logout from this user session - This should take back to the home page - SignOutUser(generatedEmail); + validator.SignInWithUser(generatedEmail, "Password~1"); - //Sign in scenarios: Invalid password - Expected an invalid user name password error. - SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1"); + // Register a user - Negative scenario : Trying to register a user name that's already registered. + validator.RegisterExistingUser(generatedEmail); - //Sign in scenarios: Valid user name & password. - SignInWithUser(generatedEmail, "Password~1"); + // Logout from this user session - This should take back to the home page + validator.SignOutUser(generatedEmail); - //Change password scenario - ChangePassword(generatedEmail); + // Sign in scenarios: Invalid password - Expected an invalid user name password error. + validator.SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1"); - //SignIn with old password and verify old password is not allowed and new password is allowed - SignOutUser(generatedEmail); - SignInWithInvalidPassword(generatedEmail, "Password~1"); - SignInWithUser(generatedEmail, "Password~2"); + // Sign in scenarios: Valid user name & password. + validator.SignInWithUser(generatedEmail, "Password~1"); - //Making a request to a protected resource that this user does not have access to - should automatically redirect to login page again - AccessStoreWithoutPermissions(generatedEmail); + // Change password scenario + validator.ChangePassword(generatedEmail); - //Logout from this user session - This should take back to the home page - SignOutUser(generatedEmail); + // SignIn with old password and verify old password is not allowed and new password is allowed + validator.SignOutUser(generatedEmail); + validator.SignInWithInvalidPassword(generatedEmail, "Password~1"); + validator.SignInWithUser(generatedEmail, "Password~2"); - //Login as an admin user - SignInWithUser("Administrator@test.com", "YouShouldChangeThisPassword1!"); + // Making a request to a protected resource that this user does not have access to - should automatically redirect to login page again + validator.AccessStoreWithoutPermissions(generatedEmail); - //Now navigating to the store manager should work fine as this user has the necessary permission to administer the store. - AccessStoreWithPermissions(); + // Logout from this user session - This should take back to the home page + validator.SignOutUser(generatedEmail); - //Create an album - var albumName = CreateAlbum(); - var albumId = FetchAlbumIdFromName(albumName); + // Login as an admin user + validator.SignInWithUser("Administrator@test.com", "YouShouldChangeThisPassword1!"); - //Get details of the album - VerifyAlbumDetails(albumId, albumName); + // Now navigating to the store manager should work fine as this user has the necessary permission to administer the store. + validator.AccessStoreWithPermissions(); - //Verify status code pages acts on non-existing items. - VerifyStatusCodePages(); + // Create an album + var albumName = validator.CreateAlbum(); + var albumId = validator.FetchAlbumIdFromName(albumName); - //Get the non-admin view of the album. - GetAlbumDetailsFromStore(albumId, albumName); + // Get details of the album + validator.VerifyAlbumDetails(albumId, albumName); - //Add an album to cart and checkout the same - AddAlbumToCart(albumId, albumName); - CheckOutCartItems(); + // Verify status code pages acts on non-existing items. + validator.VerifyStatusCodePages(); - //Delete the album from store - DeleteAlbum(albumId, albumName); + // Get the non-admin view of the album. + validator.GetAlbumDetailsFromStore(albumId, albumName); - //Logout from this user session - This should take back to the home page - SignOutUser("Administrator"); + // Add an album to cart and checkout the same + validator.AddAlbumToCart(albumId, albumName); + validator.CheckOutCartItems(); - //Google login - LoginWithGoogle(); + // Delete the album from store + validator.DeleteAlbum(albumId, albumName); - //Facebook login - LoginWithFacebook(); + // Logout from this user session - This should take back to the home page + validator.SignOutUser("Administrator"); - //Twitter login - LoginWithTwitter(); + // Google login + validator.LoginWithGoogle(); - //MicrosoftAccountLogin - LoginWithMicrosoftAccount(); + // Facebook login + validator.LoginWithFacebook(); + + // Twitter login + validator.LoginWithTwitter(); + + // MicrosoftAccountLogin + validator.LoginWithMicrosoftAccount(); 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; } - finally - { - if (!testSuccessful) - { - _logger.LogError("Some tests failed. Proceeding with cleanup."); - } - DeploymentUtility.CleanUpApplication(_startParameters, hostProcess, musicStoreDbName, _logger); + if (!testSuccessful) + { + logger.LogError("Some tests failed."); } } } diff --git a/test/E2ETests/compiler/shared/Mocks/StartupOpenIdConnectTesting.cs b/test/E2ETests/compiler/shared/Mocks/StartupOpenIdConnectTesting.cs index 1032729aab..806e3628a7 100644 --- a/test/E2ETests/compiler/shared/Mocks/StartupOpenIdConnectTesting.cs +++ b/test/E2ETests/compiler/shared/Mocks/StartupOpenIdConnectTesting.cs @@ -109,7 +109,7 @@ namespace MusicStore public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { - loggerFactory.AddConsole(); + loggerFactory.AddConsole(minLevel: LogLevel.Warning); app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage"); diff --git a/test/E2ETests/compiler/shared/Mocks/StartupSocialTesting.cs b/test/E2ETests/compiler/shared/Mocks/StartupSocialTesting.cs index 7185bb65ea..b2c34bfcac 100644 --- a/test/E2ETests/compiler/shared/Mocks/StartupSocialTesting.cs +++ b/test/E2ETests/compiler/shared/Mocks/StartupSocialTesting.cs @@ -163,7 +163,7 @@ namespace MusicStore public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { - loggerFactory.AddConsole(); + loggerFactory.AddConsole(minLevel: LogLevel.Warning); app.UseStatusCodePagesWithRedirects("~/Home/StatusCodePage"); diff --git a/test/E2ETests/project.json b/test/E2ETests/project.json index 9670466a47..8edb93559f 100644 --- a/test/E2ETests/project.json +++ b/test/E2ETests/project.json @@ -6,13 +6,12 @@ "test": "xunit.runner.aspnet" }, "dependencies": { + "DeploymentHelpers": "1.0.0-*", + "Microsoft.AspNet.Http.Core": "1.0.0-*", "Microsoft.AspNet.Server.IIS": "1.0.0-*", "Microsoft.AspNet.SignalR.Client": "2.1.1", - "Microsoft.AspNet.Testing": "1.0.0-*", "Microsoft.AspNet.WebUtilities": "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-*" }, "frameworks": { @@ -24,4 +23,4 @@ } } } -} +} \ No newline at end of file