diff --git a/src/MusicStore/Startup.cs b/src/MusicStore/Startup.cs index 5f087c1d79..e78599007a 100644 --- a/src/MusicStore/Startup.cs +++ b/src/MusicStore/Startup.cs @@ -16,17 +16,14 @@ namespace MusicStore { public void Configure(IBuilder app) { - /* Adding IConfiguration as a service in the IoC to avoid instantiating Configuration again. - * Below code demonstrates usage of multiple configuration sources. For instance a setting say 'setting1' is found in both the registered sources, - * then the later source will win. By this way a Local config can be overridden by a different setting while deployed remotely. - */ + //Below code demonstrates usage of multiple configuration sources. For instance a setting say 'setting1' is found in both the registered sources, + //then the later source will win. By this way a Local config can be overridden by a different setting while deployed remotely. var configuration = new Configuration(); configuration.AddJsonFile("LocalConfig.json"); configuration.AddEnvironmentVariables(); //All environment variables in the process's context flow in as configuration values. - /* Error page middleware displays a nice formatted HTML page for any unhandled exceptions in the request pipeline. - * Note: ErrorPageOptions.ShowAll to be used only at development time. Not recommended for production. - */ + //Error page middleware displays a nice formatted HTML page for any unhandled exceptions in the request pipeline. + //Note: ErrorPageOptions.ShowAll to be used only at development time. Not recommended for production. app.UseErrorPage(ErrorPageOptions.ShowAll); app.UseServices(services => @@ -87,8 +84,8 @@ namespace MusicStore app.UseMvc(routes => { routes.MapRoute( - name: "areaRoute", - template: "{area:exists}/{controller}/{action}", + name: "areaRoute", + template: "{area:exists}/{controller}/{action}", defaults: new { action = "Index" }); routes.MapRoute( diff --git a/src/MusicStore/project.json b/src/MusicStore/project.json index 3fc574b830..ac33f12227 100644 --- a/src/MusicStore/project.json +++ b/src/MusicStore/project.json @@ -4,6 +4,7 @@ ], "description": "Music store application on K", "version": "1.0.0-*", + "compilationOptions": { "warningsAsErrors": true }, "dependencies": { "Kestrel": "1.0.0-*", "Microsoft.AspNet.Server.IIS": "1.0.0-*", @@ -16,7 +17,7 @@ "Microsoft.AspNet.StaticFiles": "1.0.0-*", "EntityFramework.SqlServer": "7.0.0-*", /*For Mono*/ - "EntityFramework.InMemory": "7.0.0-*", + "EntityFramework.InMemory": "7.0.0-*", "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*", "Microsoft.Framework.OptionsModel": "1.0.0-*" }, @@ -29,4 +30,4 @@ "net451": { }, "aspnetcore50": { } } -} +} \ No newline at end of file diff --git a/test/E2ETests/DeploymentUtility.cs b/test/E2ETests/DeploymentUtility.cs index 79c37ef1bc..d1e29262c9 100644 --- a/test/E2ETests/DeploymentUtility.cs +++ b/test/E2ETests/DeploymentUtility.cs @@ -91,6 +91,14 @@ namespace E2ETests private static Process StartMonoHost(ServerType hostType, string applicationPath) { + //Mono needs this as GetFullPath does not work if it has \ + applicationPath = Path.GetFullPath(applicationPath.Replace('\\', '/')); + + //Mono does not have a way to pass in a --appbase switch. So it will be an environment variable. + //https://github.com/aspnet/KRuntime/issues/580 + Environment.SetEnvironmentVariable("APP_BASE", applicationPath); + Console.WriteLine("Setting the APP_BASE to {0}", applicationPath); + var path = Environment.GetEnvironmentVariable("PATH"); var kreBin = path.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries).Where(c => c.Contains("KRE-mono45")).FirstOrDefault(); @@ -103,13 +111,12 @@ namespace E2ETests var klrMonoManaged = Path.Combine(kreBin, "klr.mono.managed.dll"); var applicationHost = Path.Combine(kreBin, "Microsoft.Framework.ApplicationHost"); - Console.WriteLine(string.Format("Executing command: {0} {1} --appbase {2} {3} {4}", monoPath, klrMonoManaged, applicationPath, applicationHost, hostType.ToString())); + Console.WriteLine(string.Format("Executing command: {0} {1} {3} {4}", monoPath, klrMonoManaged, applicationPath, applicationHost, hostType.ToString())); - //https://github.com/aspnet/KRuntime/issues/580 var startInfo = new ProcessStartInfo { FileName = monoPath, - Arguments = string.Format("{0} --appbase {1} {2} {3}", klrMonoManaged, applicationPath, applicationHost, hostType.ToString()), + Arguments = string.Format("{0} {1} {2}", klrMonoManaged, applicationHost, hostType.ToString()), UseShellExecute = true, CreateNoWindow = true }; @@ -118,6 +125,8 @@ namespace E2ETests Console.WriteLine("Started {0}. Process Id : {1}", hostProcess.MainModule.FileName, hostProcess.Id); Thread.Sleep(5 * 1000); + //Clear the appbase so that it does not create issues with successive runs + Environment.SetEnvironmentVariable("APP_BASE", string.Empty); return hostProcess; } @@ -159,7 +168,7 @@ namespace E2ETests { Console.WriteLine("Started {0}. Process Id : {1}", hostProcess.MainModule.FileName, hostProcess.Id); } - catch (Win32Exception ex) + catch (Win32Exception) { Console.WriteLine("Cannot access 64 bit modules from a 32 bit process"); } @@ -230,5 +239,33 @@ namespace E2ETests dbWatch.Dispose(); } } + + public static void CleanUpApplication(Process hostProcess, string musicStoreDbName) + { + if (hostProcess != null && !hostProcess.HasExited) + { + //Shutdown the host process + hostProcess.Kill(); + hostProcess.WaitForExit(5 * 1000); + if (!hostProcess.HasExited) + { + Console.WriteLine("Unable to terminate the host process with process Id '{0}", hostProcess.Id); + } + else + { + Console.WriteLine("Successfully terminated host process with process Id '{0}'", hostProcess.Id); + } + } + else + { + Console.WriteLine("Host process already exited or never started successfully."); + } + + if (!Helpers.RunningOnMono) + { + //Mono uses InMemoryStore + DbUtils.DropDatabase(musicStoreDbName); + } + } } } \ No newline at end of file diff --git a/test/E2ETests/Helpers.cs b/test/E2ETests/Helpers.cs new file mode 100644 index 0000000000..f2b971b4a6 --- /dev/null +++ b/test/E2ETests/Helpers.cs @@ -0,0 +1,15 @@ +using System; + +namespace E2ETests +{ + public class Helpers + { + public static bool RunningOnMono + { + get + { + return Type.GetType("Mono.Runtime") != null; + } + } + } +} \ No newline at end of file diff --git a/test/E2ETests/Scenarios.cs b/test/E2ETests/Scenarios.cs new file mode 100644 index 0000000000..301874e08c --- /dev/null +++ b/test/E2ETests/Scenarios.cs @@ -0,0 +1,389 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using Xunit; + +namespace E2ETests +{ + public partial class SmokeTests + { + private void VerifyStaticContentServed() + { + Console.WriteLine("Validating if static contents are served.."); + Console.WriteLine("Fetching favicon.ico.."); + var response = httpClient.GetAsync("favicon.ico").Result; + ThrowIfResponseStatusNotOk(response); + Console.WriteLine("Etag received: {0}", response.Headers.ETag.Tag); + Console.WriteLine("Etag received: {0}", response.Headers.ETag.IsWeak); + + //Check if you receive a NotModified on sending an etag + Console.WriteLine("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(); + Console.WriteLine("Successfully received a NotModified status"); + + Console.WriteLine("Fetching /Content/bootstrap.css.."); + response = httpClient.GetAsync("Content/bootstrap.css").Result; + ThrowIfResponseStatusNotOk(response); + Console.WriteLine("Verified static contents are served successfully"); + } + + private void VerifyHomePage(HttpResponseMessage response, string responseContent) + { + Console.WriteLine("Home page content : {0}", responseContent); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + ValidateLayoutPage(responseContent); + Assert.Contains("Home Page – MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("Register", responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("Login", responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("mvcmusicstore.codeplex.com", responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("/Images/home-showcase.png", responseContent, StringComparison.OrdinalIgnoreCase); + Console.WriteLine("Application initialization successful."); + } + + private void ValidateLayoutPage(string responseContent) + { + Assert.Contains("ASP.NET MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("
  • Home
  • ", responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("Store ", responseContent, StringComparison.OrdinalIgnoreCase); + Assert.Contains("