diff --git a/eng/helix/content/RunTests/TestRunner.cs b/eng/helix/content/RunTests/TestRunner.cs index c5f48c8975..8f103ae940 100644 --- a/eng/helix/content/RunTests/TestRunner.cs +++ b/eng/helix/content/RunTests/TestRunner.cs @@ -98,7 +98,7 @@ namespace RunTests Directory.CreateDirectory(appRuntimePath); Console.WriteLine($"Set ASPNET_RUNTIME_PATH: {appRuntimePath}"); EnvironmentVariables.Add("ASPNET_RUNTIME_PATH", appRuntimePath); - Console.WriteLine($"Found AspNetRuntime: {Options.AspNetRuntime}, extracting *.txt,json,dll to {appRuntimePath}"); + Console.WriteLine($"Found AspNetRuntime: {Options.AspNetRuntime}, extracting *.txt,json,dll,xml to {appRuntimePath}"); using (var archive = ZipFile.OpenRead(Options.AspNetRuntime)) { foreach (var entry in archive.Entries) @@ -106,7 +106,8 @@ namespace RunTests // These are the only extensions that end up in the shared fx directory if (entry.Name.EndsWith(".txt", StringComparison.OrdinalIgnoreCase) || entry.Name.EndsWith(".json", StringComparison.OrdinalIgnoreCase) || - entry.Name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) + entry.Name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || + entry.Name.EndsWith(".xml", StringComparison.OrdinalIgnoreCase)) { entry.ExtractToFile(Path.Combine(appRuntimePath, entry.Name), overwrite: true); } diff --git a/eng/tools/RepoTasks/CreateFrameworkListFile.cs b/eng/tools/RepoTasks/CreateFrameworkListFile.cs index 19fb2bb18e..0ac46a87c1 100644 --- a/eng/tools/RepoTasks/CreateFrameworkListFile.cs +++ b/eng/tools/RepoTasks/CreateFrameworkListFile.cs @@ -23,10 +23,6 @@ namespace RepoTasks [Required] public string TargetFile { get; set; } - public string ManagedRoot { get; set; } = ""; - - public string NativeRoot { get; set; } = ""; - /// /// Extra attributes to place on the root node. /// @@ -53,7 +49,8 @@ namespace RepoTasks AssemblyName = FileUtilities.GetAssemblyName(item.ItemSpec), FileVersion = FileUtilities.GetFileVersion(item.ItemSpec), IsNative = item.GetMetadata("IsNativeImage") == "true", - IsSymbolFile = item.GetMetadata("IsSymbolFile") == "true" + IsSymbolFile = item.GetMetadata("IsSymbolFile") == "true", + PackagePath = item.GetMetadata("PackagePath") }) .Where(f => !f.IsSymbolFile && @@ -65,7 +62,7 @@ namespace RepoTasks new XAttribute("Type", f.IsNative ? "Native" : "Managed"), new XAttribute( "Path", - Path.Combine(f.IsNative ? NativeRoot : ManagedRoot, f.Filename).Replace('\\', '/'))); + Path.Combine(f.PackagePath, f.Filename).Replace('\\', '/'))); if (f.AssemblyName != null) { diff --git a/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj b/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj index 950bf61449..2e10f9ff36 100644 --- a/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj +++ b/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj @@ -109,9 +109,6 @@ This package is an internal implementation of the .NET Core SDK and is not meant $(AssetTargetFallback);native,Version=0.0 - RuntimeList.xml - $(ArtifactsObjDir)$(FrameworkListFileName) - $(TargetArchitecture) Win32 @@ -156,6 +153,9 @@ This package is an internal implementation of the .NET Core SDK and is not meant $(RedistSharedFrameworkLayoutRoot)$(SharedRuntimeSubPath) $(LocalDotNetRoot)$(SharedRuntimeSubPath) + RuntimeList.xml + $(SharedFxLayoutTargetDir)$(FrameworkListFileName) + $(InternalInstallerBaseName)-$(PackageVersion)-$(TargetRuntimeIdentifier)$(ArchiveExtension) $(InstallersOutputPath)$(InternalArchiveOutputFileName) $(RuntimeInstallerBaseName)-$(PackageVersion)-$(TargetRuntimeIdentifier)$(ArchiveExtension) @@ -531,11 +531,17 @@ This package is an internal implementation of the .NET Core SDK and is not meant DependsOnTargets="_ResolveSharedFrameworkContent" BeforeTargets="_GetPackageFiles" Condition="'$(ManifestsPackagePath)' != ''"> + + + + $(NativeAssetsPackagePath) + $(ManagedAssetsPackagePath) + + + diff --git a/src/Framework/test/SharedFxTests.cs b/src/Framework/test/SharedFxTests.cs index 52d89ea938..227c53140c 100644 --- a/src/Framework/test/SharedFxTests.cs +++ b/src/Framework/test/SharedFxTests.cs @@ -4,10 +4,12 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using System.Xml.Linq; using Newtonsoft.Json.Linq; using Xunit; using Xunit.Abstractions; @@ -209,5 +211,105 @@ namespace Microsoft.AspNetCore Assert.Equal(TestData.GetRepositoryCommit(), lines[0]); Assert.Equal(TestData.GetTestDataValue("RuntimePackageVersion"), lines[1]); } + + [Fact] + public void RuntimeListListsContainsCorrectEntries() + { + var runtimeListPath = Path.Combine(_sharedFxRoot, "RuntimeList.xml"); + var expectedAssemblies = TestData.GetSharedFxDependencies() + .Split(';', StringSplitOptions.RemoveEmptyEntries) + .ToHashSet(); + + AssertEx.FileExists(runtimeListPath); + + var runtimeListDoc = XDocument.Load(runtimeListPath); + var runtimeListEntries = runtimeListDoc.Root.Descendants(); + + _output.WriteLine("==== file contents ===="); + _output.WriteLine(string.Join('\n', runtimeListEntries.Select(i => i.Attribute("Path").Value).OrderBy(i => i))); + _output.WriteLine("==== expected assemblies ===="); + _output.WriteLine(string.Join('\n', expectedAssemblies.OrderBy(i => i))); + + var actualAssemblies = runtimeListEntries + .Select(i => + { + var filePath = i.Attribute("Path").Value; + var fileParts = filePath.Split('/'); + var fileName = fileParts[fileParts.Length - 1]; + return fileName.EndsWith(".dll", StringComparison.Ordinal) + ? fileName.Substring(0, fileName.Length - 4) + : fileName; + }) + .ToHashSet(); + + var missing = expectedAssemblies.Except(actualAssemblies); + var unexpected = actualAssemblies.Except(expectedAssemblies); + + _output.WriteLine("==== missing assemblies from the runtime list ===="); + _output.WriteLine(string.Join('\n', missing)); + _output.WriteLine("==== unexpected assemblies in the runtime list ===="); + _output.WriteLine(string.Join('\n', unexpected)); + + Assert.Empty(missing); + Assert.Empty(unexpected); + + Assert.All(runtimeListEntries, i => + { + var assemblyType = i.Attribute("Type").Value; + var assemblyPath = i.Attribute("Path").Value; + var fileVersion = i.Attribute("FileVersion").Value; + + if (assemblyType.Equals("Managed")) + { + var assemblyVersion = i.Attribute("AssemblyVersion").Value; + Assert.True(Version.TryParse(assemblyVersion, out _), $"{assemblyPath} has assembly version {assemblyVersion}. Assembly version must be convertable to System.Version"); + } + + Assert.True(Version.TryParse(fileVersion, out _), $"{assemblyPath} has file version {fileVersion}. File version must be convertable to System.Version"); + }); + } + + [Fact] + public void RuntimeListListsContainsCorrectPaths() + { + var runtimePath = Environment.GetEnvironmentVariable("ASPNET_RUNTIME_PATH"); + if (string.IsNullOrEmpty(runtimePath)) + { + return; + } + + var runtimeListPath = Path.Combine(_sharedFxRoot, "RuntimeList.xml"); + + AssertEx.FileExists(runtimeListPath); + + var runtimeListDoc = XDocument.Load(runtimeListPath); + var runtimeListEntries = runtimeListDoc.Root.Descendants(); + + var sharedFxPath = Path.Combine(Environment.GetEnvironmentVariable("HELIX_WORKITEM_ROOT"), ("Microsoft.AspNetCore.App.Runtime.win-x64." + TestData.GetSharedFxVersion() + ".nupkg")); + + ZipArchive archive = ZipFile.OpenRead(sharedFxPath); + + var actualPaths = archive.Entries + .Where(i => i.FullName.EndsWith(".dll")) + .Select(i => i.FullName).ToHashSet(); + + var expectedPaths = runtimeListEntries.Select(i => i.Attribute("Path").Value).ToHashSet(); + + _output.WriteLine("==== package contents ===="); + _output.WriteLine(string.Join('\n', actualPaths.OrderBy(i => i))); + _output.WriteLine("==== expected assemblies ===="); + _output.WriteLine(string.Join('\n', expectedPaths.OrderBy(i => i))); + + var missing = expectedPaths.Except(actualPaths); + var unexpected = actualPaths.Except(expectedPaths); + + _output.WriteLine("==== missing assemblies from the runtime list ===="); + _output.WriteLine(string.Join('\n', missing)); + _output.WriteLine("==== unexpected assemblies in the runtime list ===="); + _output.WriteLine(string.Join('\n', unexpected)); + + Assert.Empty(missing); + Assert.Empty(unexpected); + } } } diff --git a/src/Framework/test/TargetingPackTests.cs b/src/Framework/test/TargetingPackTests.cs index 6266e6f3d8..8d9f02524e 100644 --- a/src/Framework/test/TargetingPackTests.cs +++ b/src/Framework/test/TargetingPackTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Reflection; using System.Reflection.Metadata; @@ -313,14 +314,14 @@ namespace Microsoft.AspNetCore var frameworkListEntries = frameworkListDoc.Root.Descendants(); _output.WriteLine("==== file contents ===="); - _output.WriteLine(string.Join('\n', frameworkListEntries.Select(i => i.Attribute("Path").Value).OrderBy(i => i))); + _output.WriteLine(string.Join('\n', frameworkListEntries.Select(i => i.Attribute("AssemblyName").Value).OrderBy(i => i))); _output.WriteLine("==== expected assemblies ===="); _output.WriteLine(string.Join('\n', expectedAssemblies.OrderBy(i => i))); var actualAssemblies = frameworkListEntries .Select(i => { - var fileName = i.Attribute("Path").Value; + var fileName = i.Attribute("AssemblyName").Value; return fileName.EndsWith(".dll", StringComparison.Ordinal) ? fileName.Substring(0, fileName.Length - 4) : fileName; @@ -348,5 +349,47 @@ namespace Microsoft.AspNetCore Assert.True(Version.TryParse(fileVersion, out _), $"{assemblyPath} has file version {fileVersion}. File version must be convertable to System.Version"); }); } + + [Fact] + public void FrameworkListListsContainsCorrectPaths() + { + if (!_isTargetingPackBuilding || string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix"))) + { + return; + } + + var frameworkListPath = Path.Combine(_targetingPackRoot, "data", "FrameworkList.xml"); + + AssertEx.FileExists(frameworkListPath); + + var frameworkListDoc = XDocument.Load(frameworkListPath); + var frameworkListEntries = frameworkListDoc.Root.Descendants(); + + var targetingPackPath = Path.Combine(Environment.GetEnvironmentVariable("HELIX_WORKITEM_ROOT"), ("Microsoft.AspNetCore.App.Ref." + TestData.GetSharedFxVersion() + ".nupkg")); + + ZipArchive archive = ZipFile.OpenRead(targetingPackPath); + + var actualPaths = archive.Entries + .Where(i => i.FullName.EndsWith(".dll")) + .Select(i => i.FullName).ToHashSet(); + + var expectedPaths = frameworkListEntries.Select(i => i.Attribute("Path").Value).ToHashSet(); + + _output.WriteLine("==== package contents ===="); + _output.WriteLine(string.Join('\n', actualPaths.OrderBy(i => i))); + _output.WriteLine("==== expected assemblies ===="); + _output.WriteLine(string.Join('\n', expectedPaths.OrderBy(i => i))); + + var missing = expectedPaths.Except(actualPaths); + var unexpected = actualPaths.Except(expectedPaths); + + _output.WriteLine("==== missing assemblies from the runtime list ===="); + _output.WriteLine(string.Join('\n', missing)); + _output.WriteLine("==== unexpected assemblies in the runtime list ===="); + _output.WriteLine(string.Join('\n', unexpected)); + + Assert.Empty(missing); + Assert.Empty(unexpected); + } } }