Add module load location check (#94)
This commit is contained in:
parent
c9c21d2ce9
commit
5e3a7922fe
|
|
@ -9,12 +9,12 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="Templates\*.*" CopyToOutputDirectory="PreserveNewest" />
|
||||
<ContentWithTargetPath Include="NuGet.config.template" CopyToOutputDirectory="PreserveNewest" TargetPath="NuGet.config"/>
|
||||
<ContentWithTargetPath Include="global.json.template" CopyToOutputDirectory="PreserveNewest" TargetPath="global.json"/>
|
||||
<ContentWithTargetPath Include="NuGet.config.template" CopyToOutputDirectory="PreserveNewest" TargetPath="NuGet.config" />
|
||||
<ContentWithTargetPath Include="global.json.template" CopyToOutputDirectory="PreserveNewest" TargetPath="global.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting" Version="$(AspNetIntegrationTestingVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(AspNetCoreVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Process.Sources" Version="$(AspNetCoreVersion)" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
// 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.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
|
||||
{
|
||||
public class PathUtilities
|
||||
{
|
||||
public static string[] GetStoreModules(string dotnetPath)
|
||||
{
|
||||
var dotnetHome = Path.GetDirectoryName(dotnetPath);
|
||||
return new DirectoryInfo(Path.Combine(dotnetHome, "store", "x64", "netcoreapp2.0"))
|
||||
.GetDirectories()
|
||||
.Select(d => d.Name)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static string[] GetSharedRuntimeAssemblies(string dotnetPath)
|
||||
{
|
||||
var dotnetHome = Path.GetDirectoryName(dotnetPath);
|
||||
return new DirectoryInfo(Path.Combine(dotnetHome, "shared", "Microsoft.NETCore.App"))
|
||||
.GetDirectories()
|
||||
.Single()
|
||||
.GetFiles("*.dll")
|
||||
.Select(f => f.Name)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static string GetBundledAspNetCoreVersion(string dotnetPath)
|
||||
{
|
||||
var dotnetHome = Path.GetDirectoryName(dotnetPath);
|
||||
return new DirectoryInfo(Path.Combine(dotnetHome, "store", "x64", "netcoreapp2.0", "microsoft.aspnetcore"))
|
||||
.GetDirectories()
|
||||
.Single()
|
||||
.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,10 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
|
|
@ -17,6 +19,10 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
|
|||
[Collection("Azure")]
|
||||
public class TemplateFunctionalTests
|
||||
{
|
||||
private const string RuntimeInformationMiddlewareType = "Microsoft.AspNetCore.AzureAppServices.FunctionalTests.RuntimeInformationMiddleware";
|
||||
|
||||
private const string RuntimeInformationMiddlewareFile = "Templates\\RuntimeInformationMiddleware.cs";
|
||||
|
||||
readonly AzureFixture _fixture;
|
||||
|
||||
private readonly ITestOutputHelper _outputHelper;
|
||||
|
|
@ -43,6 +49,8 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
|
|||
|
||||
await dotnet.ExecuteAndAssertAsync("new " + template);
|
||||
|
||||
InjectMiddlware(testDirectory, RuntimeInformationMiddlewareType, RuntimeInformationMiddlewareFile);
|
||||
|
||||
await site.BuildPublishProfileAsync(testDirectory.FullName);
|
||||
|
||||
await dotnet.ExecuteAndAssertAsync("publish /p:PublishProfile=Profile");
|
||||
|
|
@ -52,6 +60,12 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
|
|||
var getResult = await httpClient.GetAsync("/");
|
||||
getResult.EnsureSuccessStatusCode();
|
||||
Assert.Contains(expected, await getResult.Content.ReadAsStringAsync());
|
||||
|
||||
getResult = await httpClient.GetAsync("/runtimeInfo");
|
||||
getResult.EnsureSuccessStatusCode();
|
||||
|
||||
var runtimeInfo = JsonConvert.DeserializeObject<RuntimeInfo>(await getResult.Content.ReadAsStringAsync());
|
||||
ValidateRuntimeInfo(runtimeInfo, dotnet.Command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -80,6 +94,8 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
|
|||
|
||||
await dotnet.ExecuteAndAssertAsync("new " + template);
|
||||
|
||||
InjectMiddlware(testDirectory, RuntimeInformationMiddlewareType, RuntimeInformationMiddlewareFile);
|
||||
|
||||
FixAspNetCoreVersion(testDirectory, dotnet.Command);
|
||||
|
||||
await dotnet.ExecuteAndAssertAsync("restore");
|
||||
|
|
@ -93,23 +109,58 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
|
|||
var getResult = await httpClient.GetAsync("/");
|
||||
getResult.EnsureSuccessStatusCode();
|
||||
Assert.Contains(expected, await getResult.Content.ReadAsStringAsync());
|
||||
|
||||
getResult = await httpClient.GetAsync("/runtimeInfo");
|
||||
getResult.EnsureSuccessStatusCode();
|
||||
|
||||
var runtimeInfo = JsonConvert.DeserializeObject<RuntimeInfo>(await getResult.Content.ReadAsStringAsync());
|
||||
ValidateRuntimeInfo(runtimeInfo, dotnet.Command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ValidateRuntimeInfo(RuntimeInfo runtimeInfo, string dotnetPath)
|
||||
{
|
||||
var storeModules = PathUtilities.GetStoreModules(dotnetPath);
|
||||
|
||||
var runtimeModules = PathUtilities.GetSharedRuntimeAssemblies(dotnetPath);
|
||||
|
||||
foreach (var runtimeInfoModule in runtimeInfo.Modules)
|
||||
{
|
||||
if (storeModules.Any(f => runtimeInfoModule.ModuleName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)))
|
||||
{
|
||||
Assert.Contains("store\\x86\\netcoreapp2.0\\", runtimeInfoModule.FileName);
|
||||
}
|
||||
|
||||
// Native modules would prefer to be loaded from windows folder, skip them
|
||||
if (runtimeModules.Any(f => runtimeInfoModule.ModuleName.StartsWith(f, StringComparison.InvariantCultureIgnoreCase)) &&
|
||||
runtimeInfoModule.FileName.IndexOf("windows\\system32", StringComparison.InvariantCultureIgnoreCase) == -1)
|
||||
{
|
||||
Assert.Contains("shared\\Microsoft.NETCore.App\\", runtimeInfoModule.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void InjectMiddlware(DirectoryInfo projectRoot, string typeName, string fileName)
|
||||
{
|
||||
// Copy implementation file to project directory
|
||||
var implementationFile = Path.Combine(Directory.GetCurrentDirectory(), fileName);
|
||||
var destinationImplementationFile = Path.Combine(projectRoot.FullName, Path.GetFileName(fileName));
|
||||
File.Copy(implementationFile, destinationImplementationFile, true);
|
||||
|
||||
// Register middleware in Startup.cs/Configure
|
||||
var startupFile = Path.Combine(projectRoot.FullName, "Startup.cs");
|
||||
var startupText = File.ReadAllText(startupFile);
|
||||
startupText = Regex.Replace(startupText, "public void Configure\\([^{]+{", match => match.Value + $" app.UseMiddleware<{typeName}>();");
|
||||
File.WriteAllText(startupFile, startupText);
|
||||
}
|
||||
|
||||
private static void FixAspNetCoreVersion(DirectoryInfo testDirectory, string dotnetPath)
|
||||
{
|
||||
// TODO: Temporary workaround for broken templates in latest CLI
|
||||
|
||||
// Detect what version of aspnet core was shipped with this CLI installation
|
||||
var aspnetCoreVersion =
|
||||
new DirectoryInfo(
|
||||
Path.Combine(
|
||||
Path.GetDirectoryName(dotnetPath),
|
||||
"store", "x64", "netcoreapp2.0", "microsoft.aspnetcore"))
|
||||
.GetDirectories()
|
||||
.Single()
|
||||
.Name;
|
||||
var aspnetCoreVersion = PathUtilities.GetBundledAspNetCoreVersion(dotnetPath);
|
||||
|
||||
var csproj = testDirectory.GetFiles("*.csproj").Single().FullName;
|
||||
var projectContents = XDocument.Load(csproj);
|
||||
|
|
@ -149,14 +200,14 @@ namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
|
|||
|
||||
private TestCommand DotNet(TestLogger logger, DirectoryInfo workingDirectory, string sufix)
|
||||
{
|
||||
return new TestCommand(GetDotnetPath(sufix))
|
||||
return new TestCommand(GetDotNetPath(sufix))
|
||||
{
|
||||
Logger = logger,
|
||||
WorkingDirectory = workingDirectory.FullName
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetDotnetPath(string sufix)
|
||||
private static string GetDotNetPath(string sufix)
|
||||
{
|
||||
var current = new DirectoryInfo(Directory.GetCurrentDirectory());
|
||||
while (current != null)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
// 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.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.AzureAppServices.FunctionalTests
|
||||
{
|
||||
public class ModuleInfo
|
||||
{
|
||||
public string FileName { get; set; }
|
||||
public string ModuleName { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string InformationalVersion { get; set; }
|
||||
}
|
||||
|
||||
public class RuntimeInfo
|
||||
{
|
||||
public IDictionary Environment { get; set; }
|
||||
public IList<ModuleInfo> Modules { get; set; }
|
||||
}
|
||||
|
||||
class RuntimeInformationMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public RuntimeInformationMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
{
|
||||
if (context.Request.Path == "/runtimeInfo")
|
||||
{
|
||||
await context.Response.WriteAsync(
|
||||
JsonConvert.SerializeObject(
|
||||
new RuntimeInfo
|
||||
{
|
||||
Environment = Environment.GetEnvironmentVariables(),
|
||||
Modules = Process.GetCurrentProcess().Modules.OfType<ProcessModule>().Select(m =>
|
||||
{
|
||||
Assembly assembly = null;
|
||||
try
|
||||
{
|
||||
assembly = Assembly.Load(Path.GetFileNameWithoutExtension(m.ModuleName));
|
||||
}
|
||||
catch { }
|
||||
|
||||
return new ModuleInfo
|
||||
{
|
||||
FileName = m.FileName,
|
||||
ModuleName = m.ModuleName,
|
||||
Version = assembly?.GetName().Version.ToString(),
|
||||
InformationalVersion = assembly?.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion
|
||||
};
|
||||
}).ToList()
|
||||
}));
|
||||
return;
|
||||
}
|
||||
// Call the next delegate/middleware in the pipeline
|
||||
await _next(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue