Creating Microsoft.AspNetCore.Server.IISIntegration.Tools package

See #95
This commit is contained in:
moozzyk 2016-03-11 10:19:24 -08:00
parent 5442cbe6a5
commit 5c50ba0898
12 changed files with 740 additions and 1 deletions

View File

@ -30,6 +30,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server.IISIntegration.Tests", "test\Microsoft.AspNetCore.Server.IISIntegration.Tests\Microsoft.AspNetCore.Server.IISIntegration.Tests.xproj", "{4106DB10-E09F-480E-9CE6-B39235512EE6}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests", "test\Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests\Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests.xproj", "{D0FA003D-DE4C-480E-B4A4-BD38691B36AD}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.Server.IISIntegration.Tools", "src\Microsoft.AspNetCore.Server.IISIntegration.Tools\Microsoft.AspNetCore.Server.IISIntegration.Tools.xproj", "{B1BC61B7-BA1D-4100-A2E8-49D00CE2771D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -68,6 +72,14 @@ Global
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4106DB10-E09F-480E-9CE6-B39235512EE6}.Release|Any CPU.Build.0 = Release|Any CPU
{D0FA003D-DE4C-480E-B4A4-BD38691B36AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0FA003D-DE4C-480E-B4A4-BD38691B36AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0FA003D-DE4C-480E-B4A4-BD38691B36AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0FA003D-DE4C-480E-B4A4-BD38691B36AD}.Release|Any CPU.Build.0 = Release|Any CPU
{B1BC61B7-BA1D-4100-A2E8-49D00CE2771D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1BC61B7-BA1D-4100-A2E8-49D00CE2771D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1BC61B7-BA1D-4100-A2E8-49D00CE2771D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1BC61B7-BA1D-4100-A2E8-49D00CE2771D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -81,5 +93,7 @@ Global
{8B3446E8-E6A8-4591-AA63-A95837C6E97C} = {04B1EDB6-E967-4D25-89B9-E6F8304038CD}
{7F2F50C7-610F-4B69-B945-CA283511A587} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
{4106DB10-E09F-480E-9CE6-B39235512EE6} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
{D0FA003D-DE4C-480E-B4A4-BD38691B36AD} = {EF30B533-D715-421A-92B7-92FEF460AC9C}
{B1BC61B7-BA1D-4100-A2E8-49D00CE2771D} = {04B1EDB6-E967-4D25-89B9-E6F8304038CD}
EndGlobalSection
EndGlobal

View File

@ -6,7 +6,8 @@
"packages": {
"dotnet-publish-iis": { },
"Microsoft.AspNetCore.IISPlatformHandler": { },
"Microsoft.AspNetCore.Server.IISIntegration": { }
"Microsoft.AspNetCore.Server.IISIntegration": { },
"Microsoft.AspNetCore.Server.IISIntegration.Tools": { }
}
},
"Default": { // Rules to run for packages not listed in any other set.

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>b1bc61b7-ba1d-4100-a2e8-49d00ce2771d</ProjectGuid>
<RootNamespace>Microsoft.AspNetCore.Server.IISIntegration.Tools</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,58 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Tools.PublishIIS
{
public class Microsoft.AspNetCore.Server.IISIntegration.Tools
{
public static int Main(string[] args)
{
var app = new CommandLineApplication
{
Name = "dotnet publish-iis",
FullName = "Asp.Net IIS Publisher",
Description = "IIS Publisher for the Asp.Net web applications",
};
app.HelpOption("-h|--help");
var publishFolderOption = app.Option("--publish-folder|-p", "The path to the publish output folder", CommandOptionType.SingleValue);
var webRootOption = app.Option("--webroot|-w", "The name of webroot folder", CommandOptionType.SingleValue);
var projectPath = app.Argument("<PROJECT>", "The path to the project (project folder or project.json) being published. If empty the current directory is used.");
app.OnExecute(() =>
{
var publishFolder = publishFolderOption.Value();
if (publishFolder == null)
{
app.ShowHelp();
return 2;
}
Reporter.Output.WriteLine($"Configuring the following project for use with IIS: '{publishFolder}'");
var exitCode = new PublishIISCommand(publishFolder, projectPath.Value, webRootOption.Value()).Run();
Reporter.Output.WriteLine("Configuring project completed successfully");
return exitCode;
});
try
{
return app.Execute(args);
}
catch (Exception e)
{
Reporter.Error.WriteLine(e.Message.Red());
Reporter.Verbose.WriteLine(e.ToString().Yellow());
}
return 1;
}
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Reflection;
using System.Resources;
[assembly: AssemblyMetadata("Serviceable", "True")]
[assembly: NeutralResourcesLanguage("en-us")]
[assembly: AssemblyCompany("Microsoft Corporation.")]
[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")]
[assembly: AssemblyProduct("Microsoft ASP.NET Core")]

View File

@ -0,0 +1,119 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel;
using Microsoft.Extensions.Configuration;
namespace Microsoft.AspNetCore.Server.IISIntegration.Tools
{
public class PublishIISCommand
{
private readonly string _publishFolder;
private readonly string _projectPath;
private readonly string _webRoot;
public PublishIISCommand(string publishFolder, string projectPath, string webRoot)
{
_publishFolder = publishFolder;
_projectPath = projectPath;
_webRoot = webRoot;
}
public int Run()
{
var applicationBasePath = GetApplicationBasePath();
var webRoot = GetWebRoot(applicationBasePath);
XDocument webConfigXml = null;
var webRootDirectory = Path.Combine(_publishFolder, webRoot);
var webConfigPath = Path.Combine(webRootDirectory, "web.config");
if (File.Exists(webConfigPath))
{
Reporter.Output.WriteLine($"Updating web.config at '{webConfigPath}'");
try
{
webConfigXml = XDocument.Load(webConfigPath);
}
catch (XmlException) { }
}
else
{
if (!Directory.Exists(webRootDirectory))
{
Reporter.Output.WriteLine($"No webroot directory found. Creating '{webRootDirectory}'");
Directory.CreateDirectory(webRootDirectory);
}
Reporter.Output.WriteLine($"No web.config found. Creating '{webConfigPath}'");
}
var applicationName = GetApplicationName(applicationBasePath) + ".exe";
var transformedConfig = WebConfigTransform.Transform(webConfigXml, applicationName, ConfigureForAzure());
using (var f = new FileStream(webConfigPath, FileMode.Create))
{
transformedConfig.Save(f);
}
return 0;
}
private string GetApplicationBasePath()
{
if (!string.IsNullOrEmpty(_projectPath))
{
var fullProjectPath = Path.GetFullPath(_projectPath);
return Path.GetFileName(fullProjectPath) == "project.json"
? Path.GetDirectoryName(fullProjectPath)
: fullProjectPath;
}
return Directory.GetCurrentDirectory();
}
private string GetApplicationName(string applicationBasePath)
{
return ProjectReader.GetProject(Path.Combine(applicationBasePath, "project.json")).Name;
}
private string GetWebRoot(string applicationBasePath)
{
if (!string.IsNullOrEmpty(_webRoot))
{
return _webRoot;
}
var builder = new ConfigurationBuilder()
.AddJsonFile(Path.Combine(applicationBasePath, "hosting.json"), optional: true);
var webroot = builder.Build()["webroot"];
if (!string.IsNullOrEmpty(webroot))
{
return webroot;
}
if (Directory.Exists(Path.Combine(applicationBasePath, "wwwroot")))
{
return "wwwroot";
}
return string.Empty;
}
private static bool ConfigureForAzure()
{
var configureForAzureValue = Environment.GetEnvironmentVariable("DOTNET_CONFIGURE_AZURE");
return string.Equals(configureForAzureValue, "true", StringComparison.Ordinal) ||
string.Equals(configureForAzureValue, "1", StringComparison.Ordinal) ||
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"));
}
}
}

View File

@ -0,0 +1,104 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace Microsoft.AspNetCore.Server.IISIntegration.Tools
{
public static class WebConfigTransform
{
public static XDocument Transform(XDocument webConfig, string appName, bool configureForAzure)
{
const string HandlersElementName = "handlers";
const string httpPlatformElementName = "httpPlatform";
webConfig = webConfig == null || webConfig.Root.Name.LocalName != "configuration"
? XDocument.Parse("<configuration />")
: webConfig;
var webServerSection = GetOrCreateChild(webConfig.Root, "system.webServer");
TransformHandlers(GetOrCreateChild(webServerSection, HandlersElementName));
TransformHttpPlatform(GetOrCreateChild(webServerSection, httpPlatformElementName), appName, configureForAzure);
// make sure that the httpPlatform element is after handlers element
var httpPlatformElement = webServerSection.Element(HandlersElementName)
.ElementsBeforeSelf(httpPlatformElementName).SingleOrDefault();
if (httpPlatformElement != null)
{
httpPlatformElement.Remove();
webServerSection.Element(HandlersElementName).AddAfterSelf(httpPlatformElement);
}
return webConfig;
}
private static void TransformHandlers(XElement handlersElement)
{
var platformHandlerElement =
handlersElement.Elements("add")
.FirstOrDefault(e => string.Equals((string)e.Attribute("name"), "httpplatformhandler", StringComparison.OrdinalIgnoreCase));
if (platformHandlerElement == null)
{
platformHandlerElement = new XElement("add");
handlersElement.Add(platformHandlerElement);
}
platformHandlerElement.SetAttributeValue("name", "httpPlatformHandler");
SetAttributeValueIfEmpty(platformHandlerElement, "path", "*");
SetAttributeValueIfEmpty(platformHandlerElement, "verb", "*");
SetAttributeValueIfEmpty(platformHandlerElement, "modules", "httpPlatformHandler");
SetAttributeValueIfEmpty(platformHandlerElement, "resourceType", "Unspecified");
}
private static void TransformHttpPlatform(XElement httpPlatformElement, string appName, bool configureForAzure)
{
var appPath = Path.Combine(configureForAzure ? @"%home%\site" : "..", appName);
var logPath = Path.Combine(configureForAzure ? @"\\?\%home%\LogFiles" : @"..\logs", "stdout.log");
httpPlatformElement.SetAttributeValue("processPath", appPath);
SetAttributeValueIfEmpty(httpPlatformElement, "stdoutLogEnabled", "false");
SetAttributeValueIfEmpty(httpPlatformElement, "stdoutLogFile", logPath);
SetAttributeValueIfEmpty(httpPlatformElement, "startupTimeLimit", "3600");
AddApplicationBase(httpPlatformElement);
}
private static void AddApplicationBase(XElement httpPlatformElement)
{
const string appBaseKeyName = "ASPNET_APPLICATIONBASE";
var envVariables = GetOrCreateChild(httpPlatformElement, "environmentVariables");
var appBaseElement = envVariables.Elements("environmentVariable").SingleOrDefault(e =>
string.Equals((string)e.Attribute("name"), appBaseKeyName, StringComparison.CurrentCultureIgnoreCase));
if (appBaseElement == null)
{
appBaseElement = new XElement("environmentVariable", new XAttribute("name", appBaseKeyName));
envVariables.AddFirst(appBaseElement);
}
appBaseElement.SetAttributeValue("value", ".");
}
private static XElement GetOrCreateChild(XElement parent, string childName)
{
var childElement = parent.Element(childName);
if (childElement == null)
{
childElement = new XElement(childName);
parent.Add(childElement);
}
return childElement;
}
private static void SetAttributeValueIfEmpty(XElement element, string attributeName, string value)
{
element.SetAttributeValue(attributeName, (string)element.Attribute(attributeName) ?? value);
}
}
}

View File

@ -0,0 +1,23 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true,
"warningsAsErrors": true,
"keyFile": "../../tools/Key.snk",
"nowarn": [ "CS1591" ],
"xmlDoc": true
},
"dependencies": {
"NETStandard.Library": "1.0.0-*",
"Microsoft.Extensions.CommandLineUtils": "1.0.0-*",
"Microsoft.Extensions.Configuration.Json": "1.0.0-*",
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
"Microsoft.DotNet.Cli.Utils": "1.0.0-*"
},
"frameworks": {
"dnxcore50": {
}
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.24720" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.24720</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>d0fa003d-de4c-480e-b4a4-bd38691b36ad</ProjectGuid>
<RootNamespace>Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,153 @@
using Xunit;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System;
namespace Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests
{
public class PublishIISCommandFacts
{
private class Folders
{
public string TestRoot;
public string PublishOutput;
public string ProjectPath;
}
[Fact]
public void PublishIIS_uses_default_values_if_options_not_specified()
{
var webRoot = "wwwroot";
var folders = CreateTestDir("{}", webRoot);
new PublishIISCommand(folders.PublishOutput, folders.ProjectPath, null).Run();
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
.Descendants("httpPlatform").Attributes("processPath").Single();
Assert.Equal($@"..\projectDir.exe", processPath);
Directory.Delete(folders.TestRoot, recursive: true);
}
[Theory]
[InlineData("awesomeApp")]
[InlineData("awesome.App")]
public void PublishIIS_reads_application_name_from_project_json_if_exists(string projectName)
{
var webRoot = "wwwroot";
var folders = CreateTestDir($@"{{ ""name"": ""{projectName}"" }}", webRoot);
new PublishIISCommand(folders.PublishOutput, folders.ProjectPath, null).Run();
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
.Descendants("httpPlatform").Attributes("processPath").Single();
Assert.Equal($@"..\{projectName}.exe", processPath);
Directory.Delete(folders.TestRoot, recursive: true);
}
[Fact]
public void PublishIIS_uses_webroot_from_hosting_json()
{
var webRoot = "mywebroot";
var folders = CreateTestDir("{}", webRoot);
File.WriteAllText(Path.Combine(folders.ProjectPath, "hosting.json"), $"{{ \"webroot\": \"{webRoot}\"}}");
new PublishIISCommand(folders.PublishOutput, folders.ProjectPath, null).Run();
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
.Descendants("httpPlatform").Attributes("processPath").Single();
Assert.Equal(@"..\projectDir.exe", processPath);
Directory.Delete(folders.TestRoot, recursive: true);
}
[Fact]
public void PublishIIS_webroot_switch_takes_precedence_over_hosting_json()
{
var webRoot = "mywebroot";
var folders = CreateTestDir("{}", webRoot);
File.WriteAllText(Path.Combine(folders.ProjectPath, "hosting.json"), $"{{ \"webroot\": \"wwwroot\"}}");
new PublishIISCommand(folders.PublishOutput, folders.ProjectPath, webRoot).Run();
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
.Descendants("httpPlatform").Attributes("processPath").Single();
Assert.Equal(@"..\projectDir.exe", processPath);
Directory.Delete(folders.TestRoot, recursive: true);
}
[Theory]
[InlineData("projectDir")]
[InlineData("project.Dir")]
public void PublishIIS_accepts_path_to_project_json_as_project_path(string projectDir)
{
var webRoot = "wwwroot";
var folders = CreateTestDir("{}", webRoot, projectDir);
new PublishIISCommand(folders.PublishOutput, Path.Combine(folders.ProjectPath, "project.json"), null).Run();
var processPath = (string)GetPublishedWebConfig(folders.PublishOutput, webRoot)
.Descendants("httpPlatform").Attributes("processPath").Single();
Assert.Equal($@"..\{projectDir}.exe", processPath);
Directory.Delete(folders.TestRoot, recursive: true);
}
[Fact]
public void PublishIIS_modifies_existing_web_config()
{
var webRoot = "wwwroot";
var folders = CreateTestDir("{}", webRoot);
File.WriteAllText(Path.Combine(folders.PublishOutput, webRoot, "web.config"),
@"<configuration>
<system.webServer>
<handlers>
<add name=""httpPlatformHandler"" path=""*"" verb=""*"" modules=""httpPlatformHandler"" resourceType=""Unspecified""/>
</handlers>
<httpPlatform processPath=""%________%"" stdoutLogEnabled=""false"" startupTimeLimit=""1234""/>
</system.webServer>
</configuration>");
new PublishIISCommand(folders.PublishOutput, Path.Combine(folders.ProjectPath, "project.json"), null).Run();
var httpPlatformElement = GetPublishedWebConfig(folders.PublishOutput, webRoot)
.Descendants("httpPlatform").Single();
Assert.Equal(@"..\projectDir.exe", (string)httpPlatformElement.Attribute("processPath"));
Assert.Equal(@"1234", (string)httpPlatformElement.Attribute("startupTimeLimit"));
Directory.Delete(folders.TestRoot, recursive: true);
}
private XDocument GetPublishedWebConfig(string publishOut, string webRoot)
{
return XDocument.Load(Path.Combine(publishOut, webRoot, "web.config"));
}
private Folders CreateTestDir(string projectJson, string webRoot, string projectDir = "projectDir")
{
var testRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(testRoot);
var projectPath = Path.Combine(testRoot, projectDir);
Directory.CreateDirectory(projectPath);
Directory.CreateDirectory(Path.Combine(projectPath, webRoot));
File.WriteAllText(Path.Combine(projectPath, "project.json"), projectJson);
var publishOut = Path.Combine(testRoot, "publishOut");
Directory.CreateDirectory(publishOut);
Directory.CreateDirectory(Path.Combine(publishOut, webRoot));
return new Folders { TestRoot = testRoot, ProjectPath = projectPath, PublishOutput = publishOut };
}
}
}

View File

@ -0,0 +1,202 @@
using Xunit;
using System.Linq;
using System.Xml.Linq;
namespace Microsoft.AspNetCore.Server.IISIntegration.Tools.Tests
{
public class WebConfigTransformFacts
{
private XDocument WebConfigTemplate => XDocument.Parse(
@"<configuration>
<system.webServer>
<handlers>
<add name=""httpPlatformHandler"" path=""*"" verb=""*"" modules=""httpPlatformHandler"" resourceType=""Unspecified""/>
</handlers>
<httpPlatform processPath=""..\test.exe"" stdoutLogEnabled=""false"" stdoutLogFile=""..\logs\stdout.log"" startupTimeLimit=""3600"">
<environmentVariables>
<environmentVariable name=""ASPNET_APPLICATIONBASE"" value=""."" />
</environmentVariables>
</httpPlatform>
</system.webServer>
</configuration>");
[Fact]
public void WebConfigTransform_creates_new_config_if_one_does_not_exist()
{
Assert.True(XNode.DeepEquals(WebConfigTemplate,
WebConfigTransform.Transform(null, "test.exe", configureForAzure: false)));
}
[Fact]
public void WebConfigTransform_creates_new_config_if_one_has_unexpected_format()
{
Assert.True(XNode.DeepEquals(WebConfigTemplate,
WebConfigTransform.Transform(XDocument.Parse("<unexpected />"), "test.exe", configureForAzure: false)));
}
[Theory]
[InlineData(new object[] { new[] { "system.webServer" } })]
[InlineData(new object[] { new[] { "add" } })]
[InlineData(new object[] { new[] { "handlers" } })]
[InlineData(new object[] { new[] { "httpPlatform" } })]
[InlineData(new object[] { new[] { "environmentVariables" } })]
[InlineData(new object[] { new[] { "environmentVariable" } })]
[InlineData(new object[] { new[] { "handlers", "httpPlatform", "environmentVariables" } })]
public void WebConfigTransform_adds_missing_elements(string[] elementNames)
{
var input = WebConfigTemplate;
foreach (var elementName in elementNames)
{
input.Descendants(elementName).Remove();
}
Assert.True(XNode.DeepEquals(WebConfigTemplate,
WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)));
}
[Theory]
[InlineData("add", "path", "test")]
[InlineData("add", "verb", "test")]
[InlineData("add", "modules", "mods")]
[InlineData("add", "resourceType", "Either")]
[InlineData("httpPlatform", "stdoutLogEnabled", "true")]
[InlineData("httpPlatform", "startupTimeLimit", "1200")]
[InlineData("httpPlatform", "arguments", "arg1")]
[InlineData("httpPlatform", "stdoutLogFile", "logfile.log")]
public void WebConfigTransform_wont_override_custom_values(string elementName, string attributeName, string attributeValue)
{
var input = WebConfigTemplate;
input.Descendants(elementName).Single().SetAttributeValue(attributeName, attributeValue);
var output = WebConfigTransform.Transform(input, "test.exe", configureForAzure: false);
Assert.Equal(attributeValue, (string)output.Descendants(elementName).Single().Attribute(attributeName));
}
[Fact]
public void WebConfigTransform_overwrites_processPath()
{
var newProcessPath =
(string)WebConfigTransform.Transform(WebConfigTemplate, "app.exe", configureForAzure: false)
.Descendants("httpPlatform").Single().Attribute("processPath");
Assert.Equal(@"..\app.exe", newProcessPath);
}
[Fact]
public void WebConfigTransform_fixes_httpPlatformHandler_casing()
{
var input = WebConfigTemplate;
input.Descendants("add").Single().SetAttributeValue("name", "httpplatformhandler");
Assert.True(XNode.DeepEquals(WebConfigTemplate,
WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)));
}
[Fact]
public void WebConfigTransform_does_not_remove_children_of_httpPlatform_element()
{
var envVarElement =
new XElement("environmentVariable", new XAttribute("name", "ENVVAR"), new XAttribute("value", "123"));
var input = WebConfigTemplate;
input.Descendants("environmentVariable").Single().Add(envVarElement);
Assert.True(XNode.DeepEquals(envVarElement,
WebConfigTransform.Transform(input, "app.exe", configureForAzure: false)
.Descendants("environmentVariable").SingleOrDefault(e => (string)e.Attribute("name") == "ENVVAR")));
}
[Fact]
public void WebConfigTransform_adds_stdoutLogEnabled_if_attribute_is_missing()
{
var input = WebConfigTemplate;
input.Descendants("httpPlatform").Attributes("stdoutLogEnabled").Remove();
Assert.Equal(
"false",
(string)WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)
.Descendants().Attributes("stdoutLogEnabled").Single());
}
[Theory]
[InlineData(null)]
[InlineData("false")]
[InlineData("true")]
public void WebConfigTransform_adds_stdoutLogFile_if_attribute_is_missing(string stdoutLogFile)
{
var input = WebConfigTemplate;
var httpPlatformElement = input.Descendants("httpPlatform").Single();
httpPlatformElement.Attribute("stdoutLogEnabled").Remove();
if (stdoutLogFile != null)
{
httpPlatformElement.SetAttributeValue("stdoutLogEnabled", stdoutLogFile);
}
Assert.Equal(
@"..\logs\stdout.log",
(string)WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)
.Descendants().Attributes("stdoutLogFile").Single());
}
[Theory]
[InlineData(null)]
[InlineData("true")]
[InlineData("false")]
public void WebConfigTransform_does_not_change_existing_stdoutLogEnabled(string stdoutLogEnabledValue)
{
var input = WebConfigTemplate;
var httpPlatformElement = input.Descendants("httpPlatform").Single();
httpPlatformElement.SetAttributeValue("stdoutLogFile", "mylog.txt");
httpPlatformElement.Attributes("stdoutLogEnabled").Remove();
if (stdoutLogEnabledValue != null)
{
input.Descendants("httpPlatform").Single().SetAttributeValue("stdoutLogEnabled", stdoutLogEnabledValue);
}
Assert.Equal(
"mylog.txt",
(string)WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)
.Descendants().Attributes("stdoutLogFile").Single());
}
[Fact]
public void WebConfigTransform_correctly_configures_for_Azure()
{
var input = WebConfigTemplate;
input.Descendants("httpPlatform").Attributes().Remove();
var httPlatformElement = WebConfigTransform.Transform(input, "test.exe", configureForAzure: true)
.Descendants("httpPlatform").Single();
httPlatformElement.Elements().Remove();
Assert.True(XNode.DeepEquals(
XDocument.Parse(@"<httpPlatform processPath=""%home%\site\test.exe"" stdoutLogEnabled=""false""
stdoutLogFile=""\\?\%home%\LogFiles\stdout.log"" startupTimeLimit=""3600""/>").Root,
httPlatformElement));
}
[Fact]
public void WebConfigTransform_overrites_value_for_ASPNET_APPLICATIONBASE()
{
var input = WebConfigTemplate;
input.Descendants("environmentVariable").Single().SetAttributeValue("value", "abc");
Assert.True(XNode.DeepEquals(WebConfigTemplate,
WebConfigTransform.Transform(input, "test.exe", configureForAzure: false)));
}
private bool VerifyMissingElementCreated(params string[] elementNames)
{
var input = WebConfigTemplate;
foreach (var elementName in elementNames)
{
input.Descendants(elementName).Remove();
}
return XNode.DeepEquals(WebConfigTemplate,
WebConfigTransform.Transform(input, "test.exe", configureForAzure: false));
}
}
}

View File

@ -0,0 +1,16 @@
{
"dependencies": {
"xunit": "2.1.0",
"dotnet-publish-iis": "1.0.0-*",
"Microsoft.NETCore.Platforms": "1.0.1-*"
},
"frameworks": {
"dnxcore50": {
"imports": "portable-net451+win8",
"dependencies": {
"dotnet-test-xunit": "1.0.0-dev-*"
}
}
},
"testRunner": "xunit"
}