From c83fd8951a166aac364fde375343cb9fe78e5603 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 17 Jun 2020 17:06:04 -0700 Subject: [PATCH] Add sharedfx and targeting pack tests (#23045) * Add test for assembly versions * Add test for framework list * Add some hardcoded lists for sharedfx and targeting pack content --- .../Microsoft.AspNetCore.App.UnitTests.csproj | 2 +- src/Framework/test/SharedFxTests.cs | 27 +- src/Framework/test/TargetingPackTests.cs | 112 +++++++- src/Framework/test/TestData.cs | 271 ++++++++++++++++++ 4 files changed, 406 insertions(+), 6 deletions(-) diff --git a/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj b/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj index 4d5dfd947b..2d55f9cd50 100644 --- a/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj +++ b/src/Framework/test/Microsoft.AspNetCore.App.UnitTests.csproj @@ -87,7 +87,7 @@ <_Parameter1>TargetingPackDependencies - <_Parameter2>@(_TargetingPackDependencies) + <_Parameter2>@(_TargetingPackDependencies->'%(FileName)') i))); + _output.WriteLine("==== expected assemblies ===="); + _output.WriteLine(string.Join('\n', TestData.ListedSharedFxAssemblies.OrderBy(i => i))); + + var missing = TestData.ListedSharedFxAssemblies.Except(actualAssemblies); + var unexpected = actualAssemblies.Except(TestData.ListedSharedFxAssemblies); + + _output.WriteLine("==== missing assemblies from the framework ===="); + _output.WriteLine(string.Join('\n', missing)); + _output.WriteLine("==== unexpected assemblies in the framework ===="); + _output.WriteLine(string.Join('\n', unexpected)); + + Assert.Empty(missing); + Assert.Empty(unexpected); + } + [Fact] public void SharedFrameworkContainsExpectedFiles() { diff --git a/src/Framework/test/TargetingPackTests.cs b/src/Framework/test/TargetingPackTests.cs index cea9ca9c67..e6e3c57faf 100644 --- a/src/Framework/test/TargetingPackTests.cs +++ b/src/Framework/test/TargetingPackTests.cs @@ -9,7 +9,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; -using Newtonsoft.Json.Linq; +using System.Xml.Linq; using Xunit; using Xunit.Abstractions; @@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore public class TargetingPackTests { private readonly string _expectedRid; + private readonly string _targetingPackTfm; private readonly string _targetingPackRoot; private readonly ITestOutputHelper _output; private readonly bool _isTargetingPackBuilding; @@ -26,12 +27,62 @@ namespace Microsoft.AspNetCore { _output = output; _expectedRid = TestData.GetSharedFxRuntimeIdentifier(); - _targetingPackRoot = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix")) + _targetingPackTfm = "net" + TestData.GetSharedFxVersion().Substring(0, 3); + _targetingPackRoot = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("helix")) ? Path.Combine(TestData.GetTestDataValue("TargetingPackLayoutRoot"), "packs", "Microsoft.AspNetCore.App.Ref", TestData.GetTestDataValue("TargetingPackVersion")) : Path.Combine(Environment.GetEnvironmentVariable("HELIX_WORKITEM_ROOT"), "Microsoft.AspNetCore.App.Ref"); _isTargetingPackBuilding = bool.Parse(TestData.GetTestDataValue("IsTargetingPackBuilding")); } + [Fact] + public void TargetingPackContainsListedAssemblies() + { + var actualAssemblies = Directory.GetFiles(Path.Combine(_targetingPackRoot, "ref", _targetingPackTfm), "*.dll") + .Select(Path.GetFileNameWithoutExtension) + .ToHashSet(); + + _output.WriteLine("==== actual assemblies ===="); + _output.WriteLine(string.Join('\n', actualAssemblies.OrderBy(i => i))); + _output.WriteLine("==== expected assemblies ===="); + _output.WriteLine(string.Join('\n', TestData.ListedTargetingPackAssemblies.OrderBy(i => i))); + + var missing = TestData.ListedTargetingPackAssemblies.Except(actualAssemblies); + var unexpected = actualAssemblies.Except(TestData.ListedTargetingPackAssemblies); + + _output.WriteLine("==== missing assemblies from the framework ===="); + _output.WriteLine(string.Join('\n', missing)); + _output.WriteLine("==== unexpected assemblies in the framework ===="); + _output.WriteLine(string.Join('\n', unexpected)); + + Assert.Empty(missing); + Assert.Empty(unexpected); + } + + [Fact] + public void AssembliesHavePatchVersion0() + { + if (!_isTargetingPackBuilding) + { + return; + } + + IEnumerable dlls = Directory.GetFiles(Path.Combine(_targetingPackRoot, "ref", _targetingPackTfm), "*.dll", SearchOption.AllDirectories); + Assert.NotEmpty(dlls); + + Assert.All(dlls, path => + { + var assemblyName = AssemblyName.GetAssemblyName(path); + using var fileStream = File.OpenRead(path); + using var peReader = new PEReader(fileStream, PEStreamOptions.Default); + var reader = peReader.GetMetadataReader(MetadataReaderOptions.Default); + var assemblyDefinition = reader.GetAssemblyDefinition(); + + Assert.True( + assemblyDefinition.Version.Revision == 0 && assemblyDefinition.Version.Build == 0, + $"{path} has version {assemblyDefinition.Version} should have a 0.0 revision number and build number version, e.g. major.minor.0.0"); + }); + } + [Fact] public void PackageOverridesContainsCorrectEntries() { @@ -75,7 +126,6 @@ namespace Microsoft.AspNetCore } } - [Fact] public void AssembliesAreReferenceAssemblies() { @@ -177,5 +227,61 @@ namespace Microsoft.AspNetCore Assert.True(Version.TryParse(parts[3], out _), "File version must be convertable to System.Version"); }); } + + [Fact] + public void FrameworkListListsContainsCorrectEntries() + { + if (!_isTargetingPackBuilding) + { + return; + } + + var frameworkListPath = Path.Combine(_targetingPackRoot, "data", "FrameworkList.xml"); + var expectedAssemblies = TestData.GetTargetingPackDependencies() + .Split(';', StringSplitOptions.RemoveEmptyEntries) + .ToHashSet(); + expectedAssemblies.Remove("aspnetcorev2_inprocess"); + + AssertEx.FileExists(frameworkListPath); + + var frameworkListDoc = XDocument.Load(frameworkListPath); + 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("==== expected assemblies ===="); + _output.WriteLine(string.Join('\n', expectedAssemblies.OrderBy(i => i))); + + var actualAssemblies = frameworkListEntries + .Select(i => + { + var fileName = i.Attribute("Path").Value; + 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 framework list ===="); + _output.WriteLine(string.Join('\n', missing)); + _output.WriteLine("==== unexpected assemblies in the framework list ===="); + _output.WriteLine(string.Join('\n', unexpected)); + + Assert.Empty(missing); + Assert.Empty(unexpected); + + Assert.All(frameworkListEntries, i => + { + var assemblyPath = i.Attribute("Path").Value; + var assemblyVersion = i.Attribute("AssemblyVersion").Value; + var fileVersion = i.Attribute("FileVersion").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"); + }); + } } } diff --git a/src/Framework/test/TestData.cs b/src/Framework/test/TestData.cs index c4ca50360f..9e6551ba6a 100644 --- a/src/Framework/test/TestData.cs +++ b/src/Framework/test/TestData.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -9,6 +10,276 @@ namespace Microsoft.AspNetCore { public class TestData { + public static HashSet ListedSharedFxAssemblies = new HashSet + { + "aspnetcorev2_inprocess", + "Microsoft.AspNetCore", + "Microsoft.AspNetCore.Antiforgery", + "Microsoft.AspNetCore.Authentication", + "Microsoft.AspNetCore.Authentication.Abstractions", + "Microsoft.AspNetCore.Authentication.Cookies", + "Microsoft.AspNetCore.Authentication.Core", + "Microsoft.AspNetCore.Authentication.OAuth", + "Microsoft.AspNetCore.Authorization", + "Microsoft.AspNetCore.Authorization.Policy", + "Microsoft.AspNetCore.Components", + "Microsoft.AspNetCore.Components.Authorization", + "Microsoft.AspNetCore.Components.Forms", + "Microsoft.AspNetCore.Components.Server", + "Microsoft.AspNetCore.Components.Web", + "Microsoft.AspNetCore.Connections.Abstractions", + "Microsoft.AspNetCore.CookiePolicy", + "Microsoft.AspNetCore.Cors", + "Microsoft.AspNetCore.Cryptography.Internal", + "Microsoft.AspNetCore.Cryptography.KeyDerivation", + "Microsoft.AspNetCore.DataProtection", + "Microsoft.AspNetCore.DataProtection.Abstractions", + "Microsoft.AspNetCore.DataProtection.Extensions", + "Microsoft.AspNetCore.Diagnostics", + "Microsoft.AspNetCore.Diagnostics.Abstractions", + "Microsoft.AspNetCore.Diagnostics.HealthChecks", + "Microsoft.AspNetCore.HostFiltering", + "Microsoft.AspNetCore.Hosting", + "Microsoft.AspNetCore.Hosting.Abstractions", + "Microsoft.AspNetCore.Hosting.Server.Abstractions", + "Microsoft.AspNetCore.Html.Abstractions", + "Microsoft.AspNetCore.Http", + "Microsoft.AspNetCore.Http.Abstractions", + "Microsoft.AspNetCore.Http.Connections", + "Microsoft.AspNetCore.Http.Connections.Common", + "Microsoft.AspNetCore.Http.Extensions", + "Microsoft.AspNetCore.Http.Features", + "Microsoft.AspNetCore.HttpOverrides", + "Microsoft.AspNetCore.HttpsPolicy", + "Microsoft.AspNetCore.Identity", + "Microsoft.AspNetCore.Localization", + "Microsoft.AspNetCore.Localization.Routing", + "Microsoft.AspNetCore.Metadata", + "Microsoft.AspNetCore.Mvc", + "Microsoft.AspNetCore.Mvc.Abstractions", + "Microsoft.AspNetCore.Mvc.ApiExplorer", + "Microsoft.AspNetCore.Mvc.Core", + "Microsoft.AspNetCore.Mvc.Cors", + "Microsoft.AspNetCore.Mvc.DataAnnotations", + "Microsoft.AspNetCore.Mvc.Formatters.Json", + "Microsoft.AspNetCore.Mvc.Formatters.Xml", + "Microsoft.AspNetCore.Mvc.Localization", + "Microsoft.AspNetCore.Mvc.Razor", + "Microsoft.AspNetCore.Mvc.RazorPages", + "Microsoft.AspNetCore.Mvc.TagHelpers", + "Microsoft.AspNetCore.Mvc.ViewFeatures", + "Microsoft.AspNetCore.Razor", + "Microsoft.AspNetCore.Razor.Runtime", + "Microsoft.AspNetCore.ResponseCaching", + "Microsoft.AspNetCore.ResponseCaching.Abstractions", + "Microsoft.AspNetCore.ResponseCompression", + "Microsoft.AspNetCore.Rewrite", + "Microsoft.AspNetCore.Routing", + "Microsoft.AspNetCore.Routing.Abstractions", + "Microsoft.AspNetCore.Server.HttpSys", + "Microsoft.AspNetCore.Server.IIS", + "Microsoft.AspNetCore.Server.IISIntegration", + "Microsoft.AspNetCore.Server.Kestrel", + "Microsoft.AspNetCore.Server.Kestrel.Core", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", + "Microsoft.AspNetCore.Session", + "Microsoft.AspNetCore.SignalR", + "Microsoft.AspNetCore.SignalR.Common", + "Microsoft.AspNetCore.SignalR.Core", + "Microsoft.AspNetCore.SignalR.Protocols.Json", + "Microsoft.AspNetCore.StaticFiles", + "Microsoft.AspNetCore.WebSockets", + "Microsoft.AspNetCore.WebUtilities", + "Microsoft.Extensions.Caching.Abstractions", + "Microsoft.Extensions.Caching.Memory", + "Microsoft.Extensions.Configuration", + "Microsoft.Extensions.Configuration.Abstractions", + "Microsoft.Extensions.Configuration.Binder", + "Microsoft.Extensions.Configuration.CommandLine", + "Microsoft.Extensions.Configuration.EnvironmentVariables", + "Microsoft.Extensions.Configuration.FileExtensions", + "Microsoft.Extensions.Configuration.Ini", + "Microsoft.Extensions.Configuration.Json", + "Microsoft.Extensions.Configuration.KeyPerFile", + "Microsoft.Extensions.Configuration.UserSecrets", + "Microsoft.Extensions.Configuration.Xml", + "Microsoft.Extensions.DependencyInjection", + "Microsoft.Extensions.DependencyInjection.Abstractions", + "Microsoft.Extensions.Diagnostics.HealthChecks", + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", + "Microsoft.Extensions.FileProviders.Abstractions", + "Microsoft.Extensions.FileProviders.Composite", + "Microsoft.Extensions.FileProviders.Embedded", + "Microsoft.Extensions.FileProviders.Physical", + "Microsoft.Extensions.FileSystemGlobbing", + "Microsoft.Extensions.Hosting", + "Microsoft.Extensions.Hosting.Abstractions", + "Microsoft.Extensions.Http", + "Microsoft.Extensions.Identity.Core", + "Microsoft.Extensions.Identity.Stores", + "Microsoft.Extensions.Localization", + "Microsoft.Extensions.Localization.Abstractions", + "Microsoft.Extensions.Logging", + "Microsoft.Extensions.Logging.Abstractions", + "Microsoft.Extensions.Logging.Configuration", + "Microsoft.Extensions.Logging.Console", + "Microsoft.Extensions.Logging.Debug", + "Microsoft.Extensions.Logging.EventLog", + "Microsoft.Extensions.Logging.EventSource", + "Microsoft.Extensions.Logging.TraceSource", + "Microsoft.Extensions.ObjectPool", + "Microsoft.Extensions.Options", + "Microsoft.Extensions.Options.ConfigurationExtensions", + "Microsoft.Extensions.Options.DataAnnotations", + "Microsoft.Extensions.Primitives", + "Microsoft.Extensions.WebEncoders", + "Microsoft.JSInterop", + "Microsoft.Net.Http.Headers", + "Microsoft.Win32.SystemEvents", + "System.Diagnostics.EventLog", + "System.Drawing.Common", + "System.IO.Pipelines", + "System.Security.Cryptography.Pkcs", + "System.Security.Cryptography.Xml", + "System.Security.Permissions", + "System.Windows.Extensions" + }; + + public static HashSet ListedTargetingPackAssemblies = new HashSet + { + "Microsoft.AspNetCore", + "Microsoft.AspNetCore.Antiforgery", + "Microsoft.AspNetCore.Authentication", + "Microsoft.AspNetCore.Authentication.Abstractions", + "Microsoft.AspNetCore.Authentication.Cookies", + "Microsoft.AspNetCore.Authentication.Core", + "Microsoft.AspNetCore.Authentication.OAuth", + "Microsoft.AspNetCore.Authorization", + "Microsoft.AspNetCore.Authorization.Policy", + "Microsoft.AspNetCore.Components", + "Microsoft.AspNetCore.Components.Authorization", + "Microsoft.AspNetCore.Components.Forms", + "Microsoft.AspNetCore.Components.Server", + "Microsoft.AspNetCore.Components.Web", + "Microsoft.AspNetCore.Connections.Abstractions", + "Microsoft.AspNetCore.CookiePolicy", + "Microsoft.AspNetCore.Cors", + "Microsoft.AspNetCore.Cryptography.Internal", + "Microsoft.AspNetCore.Cryptography.KeyDerivation", + "Microsoft.AspNetCore.DataProtection", + "Microsoft.AspNetCore.DataProtection.Abstractions", + "Microsoft.AspNetCore.DataProtection.Extensions", + "Microsoft.AspNetCore.Diagnostics", + "Microsoft.AspNetCore.Diagnostics.Abstractions", + "Microsoft.AspNetCore.Diagnostics.HealthChecks", + "Microsoft.AspNetCore.HostFiltering", + "Microsoft.AspNetCore.Hosting", + "Microsoft.AspNetCore.Hosting.Abstractions", + "Microsoft.AspNetCore.Hosting.Server.Abstractions", + "Microsoft.AspNetCore.Html.Abstractions", + "Microsoft.AspNetCore.Http", + "Microsoft.AspNetCore.Http.Abstractions", + "Microsoft.AspNetCore.Http.Connections", + "Microsoft.AspNetCore.Http.Connections.Common", + "Microsoft.AspNetCore.Http.Extensions", + "Microsoft.AspNetCore.Http.Features", + "Microsoft.AspNetCore.HttpOverrides", + "Microsoft.AspNetCore.HttpsPolicy", + "Microsoft.AspNetCore.Identity", + "Microsoft.AspNetCore.Localization", + "Microsoft.AspNetCore.Localization.Routing", + "Microsoft.AspNetCore.Metadata", + "Microsoft.AspNetCore.Mvc", + "Microsoft.AspNetCore.Mvc.Abstractions", + "Microsoft.AspNetCore.Mvc.ApiExplorer", + "Microsoft.AspNetCore.Mvc.Core", + "Microsoft.AspNetCore.Mvc.Cors", + "Microsoft.AspNetCore.Mvc.DataAnnotations", + "Microsoft.AspNetCore.Mvc.Formatters.Json", + "Microsoft.AspNetCore.Mvc.Formatters.Xml", + "Microsoft.AspNetCore.Mvc.Localization", + "Microsoft.AspNetCore.Mvc.Razor", + "Microsoft.AspNetCore.Mvc.RazorPages", + "Microsoft.AspNetCore.Mvc.TagHelpers", + "Microsoft.AspNetCore.Mvc.ViewFeatures", + "Microsoft.AspNetCore.Razor", + "Microsoft.AspNetCore.Razor.Runtime", + "Microsoft.AspNetCore.ResponseCaching", + "Microsoft.AspNetCore.ResponseCaching.Abstractions", + "Microsoft.AspNetCore.ResponseCompression", + "Microsoft.AspNetCore.Rewrite", + "Microsoft.AspNetCore.Routing", + "Microsoft.AspNetCore.Routing.Abstractions", + "Microsoft.AspNetCore.Server.HttpSys", + "Microsoft.AspNetCore.Server.IIS", + "Microsoft.AspNetCore.Server.IISIntegration", + "Microsoft.AspNetCore.Server.Kestrel", + "Microsoft.AspNetCore.Server.Kestrel.Core", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", + "Microsoft.AspNetCore.Session", + "Microsoft.AspNetCore.SignalR", + "Microsoft.AspNetCore.SignalR.Common", + "Microsoft.AspNetCore.SignalR.Core", + "Microsoft.AspNetCore.SignalR.Protocols.Json", + "Microsoft.AspNetCore.StaticFiles", + "Microsoft.AspNetCore.WebSockets", + "Microsoft.AspNetCore.WebUtilities", + "Microsoft.Extensions.Caching.Abstractions", + "Microsoft.Extensions.Caching.Memory", + "Microsoft.Extensions.Configuration", + "Microsoft.Extensions.Configuration.Abstractions", + "Microsoft.Extensions.Configuration.Binder", + "Microsoft.Extensions.Configuration.CommandLine", + "Microsoft.Extensions.Configuration.EnvironmentVariables", + "Microsoft.Extensions.Configuration.FileExtensions", + "Microsoft.Extensions.Configuration.Ini", + "Microsoft.Extensions.Configuration.Json", + "Microsoft.Extensions.Configuration.KeyPerFile", + "Microsoft.Extensions.Configuration.UserSecrets", + "Microsoft.Extensions.Configuration.Xml", + "Microsoft.Extensions.DependencyInjection", + "Microsoft.Extensions.DependencyInjection.Abstractions", + "Microsoft.Extensions.Diagnostics.HealthChecks", + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", + "Microsoft.Extensions.FileProviders.Abstractions", + "Microsoft.Extensions.FileProviders.Composite", + "Microsoft.Extensions.FileProviders.Embedded", + "Microsoft.Extensions.FileProviders.Physical", + "Microsoft.Extensions.FileSystemGlobbing", + "Microsoft.Extensions.Hosting", + "Microsoft.Extensions.Hosting.Abstractions", + "Microsoft.Extensions.Http", + "Microsoft.Extensions.Identity.Core", + "Microsoft.Extensions.Identity.Stores", + "Microsoft.Extensions.Localization", + "Microsoft.Extensions.Localization.Abstractions", + "Microsoft.Extensions.Logging", + "Microsoft.Extensions.Logging.Abstractions", + "Microsoft.Extensions.Logging.Configuration", + "Microsoft.Extensions.Logging.Console", + "Microsoft.Extensions.Logging.Debug", + "Microsoft.Extensions.Logging.EventLog", + "Microsoft.Extensions.Logging.EventSource", + "Microsoft.Extensions.Logging.TraceSource", + "Microsoft.Extensions.ObjectPool", + "Microsoft.Extensions.Options", + "Microsoft.Extensions.Options.ConfigurationExtensions", + "Microsoft.Extensions.Options.DataAnnotations", + "Microsoft.Extensions.Primitives", + "Microsoft.Extensions.WebEncoders", + "Microsoft.JSInterop", + "Microsoft.Net.Http.Headers", + "Microsoft.Win32.Registry", + "System.Diagnostics.EventLog", + "System.IO.Pipelines", + "System.Security.AccessControl", + "System.Security.Cryptography.Cng", + "System.Security.Cryptography.Xml", + "System.Security.Permissions", + "System.Security.Principal.Windows", + "System.Windows.Extensions" + }; + public static string GetSharedFxVersion() => GetTestDataValue("SharedFxVersion"); public static string GetMicrosoftNETCoreAppPackageVersion() => GetTestDataValue("MicrosoftNETCoreAppRuntimeVersion");