diff --git a/src/Microsoft.DotNet.PackageTesting.Tests/GetCompatibilePackageTargetFrameworksTests.cs b/src/Microsoft.DotNet.PackageTesting.Tests/GetCompatibilePackageTargetFrameworksTests.cs index 10b0c3bbd42..949b15ceccc 100644 --- a/src/Microsoft.DotNet.PackageTesting.Tests/GetCompatibilePackageTargetFrameworksTests.cs +++ b/src/Microsoft.DotNet.PackageTesting.Tests/GetCompatibilePackageTargetFrameworksTests.cs @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using NuGet.Frameworks; using System.Collections.Generic; +using NuGet.Frameworks; using Xunit; namespace Microsoft.DotNet.PackageTesting.Tests @@ -11,34 +11,132 @@ public class GetCompatibilePackageTargetFrameworksTests { public GetCompatibilePackageTargetFrameworksTests() { - GetCompatiblePackageTargetFrameworks.Initialize(); + GetCompatiblePackageTargetFrameworks.Initialize("netcoreapp3.1;net5.0;net6.0;net461;net462;net471;net472;netstandard2.0;netstandard2.1"); } - public static IEnumerable PackageTFMData => new List + public static IEnumerable PackageTfmData => new List { // single target framework in package - new object[] { new List { FrameworkConstants.CommonFrameworks.NetStandard20}, new List { FrameworkConstants.CommonFrameworks.NetStandard20, FrameworkConstants.CommonFrameworks.NetCoreApp20, FrameworkConstants.CommonFrameworks.Net463, FrameworkConstants.CommonFrameworks.Net461, FrameworkConstants.CommonFrameworks.Net462} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetCoreApp20}, new List { FrameworkConstants.CommonFrameworks.NetCoreApp20} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetCoreApp21}, new List { FrameworkConstants.CommonFrameworks.NetCoreApp21} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.Net461}, new List { FrameworkConstants.CommonFrameworks.Net461} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.Net45}, new List { FrameworkConstants.CommonFrameworks.Net45} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetCoreApp30}, new List { FrameworkConstants.CommonFrameworks.NetCoreApp30} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetCoreApp31}, new List { FrameworkConstants.CommonFrameworks.NetCoreApp31} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetStandard21}, new List { FrameworkConstants.CommonFrameworks.NetStandard21, FrameworkConstants.CommonFrameworks.NetCoreApp30 } }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetStandard12}, new List { FrameworkConstants.CommonFrameworks.NetStandard12, FrameworkConstants.CommonFrameworks.Net451 } }, - - // two target frameworks in package - new object[] { new List { FrameworkConstants.CommonFrameworks.NetStandard20, FrameworkConstants.CommonFrameworks.Net461}, new List { FrameworkConstants.CommonFrameworks.NetStandard20, FrameworkConstants.CommonFrameworks.NetCoreApp20, FrameworkConstants.CommonFrameworks.Net463, FrameworkConstants.CommonFrameworks.Net461, FrameworkConstants.CommonFrameworks.Net462} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetStandard20, FrameworkConstants.CommonFrameworks.NetCoreApp30}, new List { FrameworkConstants.CommonFrameworks.NetStandard20, FrameworkConstants.CommonFrameworks.NetCoreApp30, FrameworkConstants.CommonFrameworks.NetCoreApp20, FrameworkConstants.CommonFrameworks.Net463, FrameworkConstants.CommonFrameworks.Net461, FrameworkConstants.CommonFrameworks.Net462} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetCoreApp30, FrameworkConstants.CommonFrameworks.Net461}, new List { FrameworkConstants.CommonFrameworks.NetCoreApp30, FrameworkConstants.CommonFrameworks.Net461} }, - new object[] { new List { FrameworkConstants.CommonFrameworks.NetCoreApp30, FrameworkConstants.CommonFrameworks.Net50}, new List { FrameworkConstants.CommonFrameworks.NetCoreApp30, FrameworkConstants.CommonFrameworks.Net50} }, + new object[] + { + new List + { + @"lib/netstandard2.0/TestPackage.dll" + }, + new List + { + FrameworkConstants.CommonFrameworks.NetStandard20, + FrameworkConstants.CommonFrameworks.Net461, + FrameworkConstants.CommonFrameworks.Net462, + FrameworkConstants.CommonFrameworks.NetCoreApp31 + } + }, + new object[] + { + new List + { + @"runtimes/win/lib/netstandard2.0/TestPackage.dll", + }, + new List + { + FrameworkConstants.CommonFrameworks.NetStandard20, + FrameworkConstants.CommonFrameworks.Net461, + FrameworkConstants.CommonFrameworks.Net462, + FrameworkConstants.CommonFrameworks.NetCoreApp31 + } + }, + new object[] + { + new List + { + @"lib/net5.0/TestPackage.dll", + @"runtimes/win/lib/netstandard2.0/TestPackage.dll" + }, + new List + { + FrameworkConstants.CommonFrameworks.NetStandard20, + FrameworkConstants.CommonFrameworks.Net461, + FrameworkConstants.CommonFrameworks.Net462, + FrameworkConstants.CommonFrameworks.NetCoreApp31, + FrameworkConstants.CommonFrameworks.Net50 + } + }, + new object[] + { + new List + { + @"lib/netcoreapp3.1/TestPackage.dll" + }, + new List + { + FrameworkConstants.CommonFrameworks.NetCoreApp31 + } + }, + new object[] + { + new List + { + @"lib/netcoreapp3.1/TestPackage.dll", + @"lib/net461/TestPackage.dll" + }, + new List + { + FrameworkConstants.CommonFrameworks.NetCoreApp31, + FrameworkConstants.CommonFrameworks.Net461 + } + }, + new object[] + { + new List + { + @"runtimes/unix/lib/netcoreapp3.1/TestPackage.dll", + @"runtimes/win/lib/netstandard2.0/TestPackage.dll" + }, + new List + { + FrameworkConstants.CommonFrameworks.NetCoreApp31, + FrameworkConstants.CommonFrameworks.NetStandard20, + FrameworkConstants.CommonFrameworks.Net461, + FrameworkConstants.CommonFrameworks.Net462 + } + }, + new object[] + { + new List + { + @"lib/net5.0/TestPackage.dll", + @"lib/net472/TestPackage.dll", + @"runtimes/win/lib/netstandard2.0/TestPackage.dll" + }, + new List + { + FrameworkConstants.CommonFrameworks.NetStandard20, + FrameworkConstants.CommonFrameworks.Net461, + FrameworkConstants.CommonFrameworks.Net462, + NuGetFramework.Parse("net472"), + FrameworkConstants.CommonFrameworks.NetCoreApp31, + FrameworkConstants.CommonFrameworks.Net50 + } + }, + new object[] + { + new List + { + @"lib/net461/TestPackage.dll" + }, + new List + { + FrameworkConstants.CommonFrameworks.Net461, + } + }, }; [Theory] - [MemberData(nameof(PackageTFMData))] - public void GetCompatibleFrameworks(List packageFrameworks, List expectedTestFrameworks) + [MemberData(nameof(PackageTfmData))] + public void GetCompatibleFrameworks(List filePaths, List expectedTestFrameworks) { - List actualTestFrameworks = GetCompatiblePackageTargetFrameworks.GetTestFrameworks(packageFrameworks); + Package package = new("TestPackage", "1.0.0", filePaths); + IEnumerable actualTestFrameworks = GetCompatiblePackageTargetFrameworks.GetTestFrameworks(package, "netcoreapp3.1"); CollectionsEqual(expectedTestFrameworks, actualTestFrameworks); } diff --git a/src/Microsoft.DotNet.PackageTesting.Tests/Microsoft.DotNet.PackageTesting.Tests.csproj b/src/Microsoft.DotNet.PackageTesting.Tests/Microsoft.DotNet.PackageTesting.Tests.csproj index 21973221994..fb54391f150 100644 --- a/src/Microsoft.DotNet.PackageTesting.Tests/Microsoft.DotNet.PackageTesting.Tests.csproj +++ b/src/Microsoft.DotNet.PackageTesting.Tests/Microsoft.DotNet.PackageTesting.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1;net472 @@ -8,6 +8,7 @@ + diff --git a/src/Microsoft.DotNet.PackageTesting/GetCompatiblePackageTargetFrameworks.cs b/src/Microsoft.DotNet.PackageTesting/GetCompatiblePackageTargetFrameworks.cs index 2fee0d7edfc..ff00124037e 100644 --- a/src/Microsoft.DotNet.PackageTesting/GetCompatiblePackageTargetFrameworks.cs +++ b/src/Microsoft.DotNet.PackageTesting/GetCompatiblePackageTargetFrameworks.cs @@ -19,6 +19,9 @@ public class GetCompatiblePackageTargetFrameworks : BuildTask [Required] public string[] PackagePaths { get; set; } + [Required] + public string SupportedTestFrameworks { get; set; } + [Output] public ITaskItem[] TestProjects { get; set; } @@ -28,16 +31,17 @@ public override bool Execute() List testProjects = new List(); try { - Initialize(); + Initialize(SupportedTestFrameworks); + string minDotnetTargetFramework = allTargetFrameworks.Where(t => t.Framework == ".NETCoreApp").OrderBy(t => t.Version).FirstOrDefault()?.GetShortFolderName(); + foreach (var packagePath in PackagePaths) { Package package = NupkgParser.CreatePackageObject(packagePath); - List packageTargetFrameworks = package.PackageAssets.Select(asset => asset.TargetFramework).Where(tfm => tfm != null).Distinct().ToList(); - List frameworksToTest = GetTestFrameworks(packageTargetFrameworks); - testProjects.AddRange(CreateItemFromTestFramework(package.PackageId, package.Version, frameworksToTest, GetRidsFromPackage(package))); + IEnumerable testFrameworks = GetTestFrameworks(package, minDotnetTargetFramework); + testProjects.AddRange(CreateItemFromTestFramework(package.PackageId, package.Version, testFrameworks)); } - + // Removing empty items. TestProjects = testProjects.Where(tfm => tfm.ItemSpec != "").ToArray(); } @@ -45,56 +49,37 @@ public override bool Execute() { Log.LogErrorFromException(e, showStackTrace: false); } - + return result && !Log.HasLoggedErrors; } - public static List GetTestFrameworks(List packageTargetFrameworks) + public static IEnumerable GetTestFrameworks(Package package, string minDotnetTargetFramework) { - List frameworksToTest = new List(); + List frameworksToTest= new List(); + IEnumerable packageTargetFrameworks = package.FrameworksInPackage; // Testing the package installation on all tfms linked with package targetframeworks. foreach (var item in packageTargetFrameworks) { if (packageTfmMapping.ContainsKey(item)) - frameworksToTest.AddRange(packageTfmMapping[item].ToList()); + frameworksToTest.AddRange(packageTfmMapping[item]); + // Adding the frameworks in the packages to the test matrix. + frameworksToTest.Add(item); } - // Pruning the test matrix by removing the frameworks we dont want to test. - frameworksToTest = frameworksToTest.Where(tfm => allTargetFrameworks.Contains(tfm)).ToList(); + if (!string.IsNullOrEmpty(minDotnetTargetFramework) && frameworksToTest.Any(t => t.Framework == ".NETStandard")) + frameworksToTest.Add(NuGetFramework.Parse(minDotnetTargetFramework)); - // Adding the frameworks in the packages to the test matrix; - frameworksToTest.AddRange(packageTargetFrameworks); - frameworksToTest = frameworksToTest.Distinct().ToList(); - return frameworksToTest; + return frameworksToTest.Where(tfm => allTargetFrameworks.Contains(tfm)).Distinct(); } - public static void Initialize() + public static void Initialize(string targetFrameworks) { // Defining the set of known frameworks that we care to test - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetCoreApp20); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetCoreApp21); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetCoreApp30); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetCoreApp31); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.Net50); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.Net45); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.Net451); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.Net452); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.Net46); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.Net461); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.Net462); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.Net463); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard10); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard11); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard12); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard13); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard14); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard15); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard16); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard17); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard20); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.NetStandard21); - allTargetFrameworks.Add(FrameworkConstants.CommonFrameworks.UAP10); + foreach (var tfm in targetFrameworks.Split(';')) + { + allTargetFrameworks.Add(NuGetFramework.Parse(tfm)); + } // creating a map framework in package => frameworks to test based on default compatibilty mapping. foreach (var item in DefaultFrameworkMappings.Instance.CompatibilityMappings) @@ -111,8 +96,8 @@ public static void Initialize() } } } - - public List CreateItemFromTestFramework(string packageId, string version, List testFrameworks, string rids) + + public List CreateItemFromTestFramework(string packageId, string version, IEnumerable testFrameworks) { List testprojects = new List(); foreach (var framework in testFrameworks) @@ -121,42 +106,10 @@ public List CreateItemFromTestFramework(string packageId, string vers supportedPackage.SetMetadata("Version", version); supportedPackage.SetMetadata("TargetFramework", framework.ToString()); supportedPackage.SetMetadata("TargetFrameworkShort", framework.GetShortFolderName()); - - if (!String.IsNullOrEmpty(rids)) - { - supportedPackage.SetMetadata("RuntimeIdentifiers", rids); - } testprojects.Add(supportedPackage); } return testprojects; } - - public string GetRidsFromPackage(Package package) - { - List rids = new List(); - foreach (var item in package.PackageAssets) - { - if (item.AssetType == AssetType.RuntimeAsset) - { - string testRid = item.Rid; - string testArch = testRid == "browser" ? "-wasm" : "-x64"; - if (testRid == "unix") - { - if (!rids.Contains("linux" + testArch)) - rids.Add("linux" + testArch); - - if (!rids.Contains("osx" + testArch)) - rids.Add("osx" + testArch); - } - else - { - if (!rids.Contains(testRid + testArch)) - rids.Add(testRid + testArch); - } - } - } - return string.Join(";", rids); - } - } + } } diff --git a/src/Microsoft.DotNet.PackageTesting/NupkgParser.cs b/src/Microsoft.DotNet.PackageTesting/NupkgParser.cs index bb1881c1657..9832e3f592a 100644 --- a/src/Microsoft.DotNet.PackageTesting/NupkgParser.cs +++ b/src/Microsoft.DotNet.PackageTesting/NupkgParser.cs @@ -1,11 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using NuGet.Frameworks; -using NuGet.Packaging; -using NuGet.Packaging.Core; -using System.Collections.Generic; using System.Linq; +using NuGet.Packaging; namespace Microsoft.DotNet.PackageTesting { @@ -13,52 +10,13 @@ public class NupkgParser { public static Package CreatePackageObject(string packagePath) { - List packageAssets = new List(); - Dictionary> packageDependencies = new Dictionary>(); - PackageArchiveReader nupkgReader = new PackageArchiveReader(packagePath); NuspecReader nuspecReader = nupkgReader.NuspecReader; string packageId = nuspecReader.GetId(); string version = nuspecReader.GetVersion().ToString(); - IEnumerable dependencyGroups = nuspecReader.GetDependencyGroups(); - - foreach (var item in dependencyGroups) - { - packageDependencies.Add(item.TargetFramework, item.Packages.ToList()); - } - - var files = nupkgReader.GetFiles().ToList().Where(t => t.EndsWith(".dll")).Where(t => t.Contains(packageId + ".dll")); - foreach (var file in files) - { - packageAssets.Add(ExtractAssetFromFile(file)); - } - - return new Package(packageId, version, packageAssets, packageDependencies); - } - - public static PackageAsset ExtractAssetFromFile(string filePath) - { - PackageAsset asset = null; - if (filePath.StartsWith("ref")) - { - var stringParts = filePath.Split('/'); - asset = new PackageAsset(NuGetFramework.Parse(stringParts[1]), null, filePath, AssetType.RefAsset); - } - else if (filePath.StartsWith("lib")) - { - var stringParts = filePath.Split('/'); - asset = new PackageAsset(NuGetFramework.Parse(stringParts[1]), null, filePath, AssetType.LibAsset); - - } - else if (filePath.StartsWith("runtimes")) - { - var stringParts = filePath.Split('/'); - NuGetFramework framework = stringParts.Length > 3 ? NuGetFramework.Parse(stringParts[3]) : null; - asset = new PackageAsset(framework, stringParts[1], filePath, AssetType.RuntimeAsset); - } - return asset; + return new Package(packageId, version, nupkgReader.GetFiles()?.Where(t => t.EndsWith(packageId + ".dll"))); } } } diff --git a/src/Microsoft.DotNet.PackageTesting/Package.cs b/src/Microsoft.DotNet.PackageTesting/Package.cs index 1e4b7b291e9..8574dea2e3a 100644 --- a/src/Microsoft.DotNet.PackageTesting/Package.cs +++ b/src/Microsoft.DotNet.PackageTesting/Package.cs @@ -1,24 +1,37 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using NuGet.Frameworks; -using NuGet.Packaging.Core; using System.Collections.Generic; +using System.Linq; +using NuGet.Client; +using NuGet.ContentModel; +using NuGet.Frameworks; namespace Microsoft.DotNet.PackageTesting { public class Package { - public List PackageAssets { get; set; } - public string PackageId { get; set; } - public string Version { get; set; } - public Dictionary> PackageDependencies { get; set; } - public Package(string packageId, string version, List packageAssets, Dictionary> packageDependencies) + public Package(string packageId, string version, IEnumerable packageAssetPaths) { PackageId = packageId; Version = version; - PackageAssets = packageAssets; - PackageDependencies = packageDependencies; + + ContentItemCollection packageAssets = new(); + packageAssets.Load(packageAssetPaths); + ManagedCodeConventions conventions = new ManagedCodeConventions(null); + + IEnumerable RefAssets = packageAssets.FindItems(conventions.Patterns.CompileRefAssemblies); + IEnumerable LibAssets = packageAssets.FindItems(conventions.Patterns.CompileLibAssemblies); + IEnumerable CompileAssets = RefAssets.Any() ? RefAssets : LibAssets; + List FrameworksInPackageList = CompileAssets.Select(t => (NuGetFramework)t.Properties["tfm"]).ToList(); + + IEnumerable RuntimeAssets = packageAssets.FindItems(conventions.Patterns.RuntimeAssemblies); + FrameworksInPackageList.AddRange(RuntimeAssets.Select(t => (NuGetFramework)t.Properties["tfm"]).Distinct()); + FrameworksInPackage = FrameworksInPackageList.Distinct(); } + + public string PackageId { get; set; } + public string Version { get; set; } + public IEnumerable FrameworksInPackage { get; private set; } } } diff --git a/src/Microsoft.DotNet.PackageTesting/PackageAsset.cs b/src/Microsoft.DotNet.PackageTesting/PackageAsset.cs deleted file mode 100644 index 825a4dad481..00000000000 --- a/src/Microsoft.DotNet.PackageTesting/PackageAsset.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using NuGet.Frameworks; - -namespace Microsoft.DotNet.PackageTesting -{ - public class PackageAsset - { - public NuGetFramework TargetFramework { get; set; } - public string Rid { get; set; } - public string PackagePath { get; set; } - public AssetType AssetType { get; set; } - - public PackageAsset(NuGetFramework targetFramework, string runtimeIdentifier, string packagePath, AssetType assetType) - { - TargetFramework = targetFramework; - Rid = runtimeIdentifier; - PackagePath = packagePath; - AssetType = assetType; - } - } - - public enum AssetType - { - RefAsset = 0, - LibAsset = 1, - RuntimeAsset = 2 - } -} diff --git a/src/Microsoft.DotNet.PackageTesting/build/Microsoft.DotNet.PackageTesting.props b/src/Microsoft.DotNet.PackageTesting/build/Microsoft.DotNet.PackageTesting.props index 052e1689aa2..5ecea08caeb 100644 --- a/src/Microsoft.DotNet.PackageTesting/build/Microsoft.DotNet.PackageTesting.props +++ b/src/Microsoft.DotNet.PackageTesting/build/Microsoft.DotNet.PackageTesting.props @@ -3,4 +3,23 @@ $(MSBuildThisFileDirectory)..\tools\net472\Microsoft.DotNet.PackageTesting.dll $(MSBuildThisFileDirectory)..\tools\netcoreapp3.1\Microsoft.DotNet.PackageTesting.dll + + + + + + + + + + + + + + + + + + +