diff --git a/nuget/helpers/lib/NuGetUpdater/Directory.Packages.props b/nuget/helpers/lib/NuGetUpdater/Directory.Packages.props index 836db8d9255..43aa3e0739f 100644 --- a/nuget/helpers/lib/NuGetUpdater/Directory.Packages.props +++ b/nuget/helpers/lib/NuGetUpdater/Directory.Packages.props @@ -13,6 +13,8 @@ + + diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs index 048626a2871..673f97d4fc5 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs @@ -1,8 +1,9 @@ -using System.Collections.Immutable; using System.Text; using NuGetUpdater.Core; +using NuGetUpdater.Core.Test; using NuGetUpdater.Core.Test.Discover; +using NuGetUpdater.Core.Test.Update; using Xunit; @@ -19,81 +20,87 @@ public async Task WithSolution() { string solutionPath = "path/to/solution.sln"; await RunAsync(path => - [ - "discover", - "--repo-root", - path, - "--workspace", - path, - ], - new[] - { - (solutionPath, """ - Microsoft Visual Studio Solution File, Format Version 12.00 - # Visual Studio 14 - VisualStudioVersion = 14.0.22705.0 - MinimumVisualStudioVersion = 10.0.40219.1 - Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "my", "my.csproj", "{782E0C0A-10D3-444D-9640-263D03D2B20C}" - EndProject - Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - EndGlobal - """), - ("path/to/my.csproj", """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """), - ("path/to/packages.config", """ - - - - """) - }, - expectedResult: new() - { - FilePath = "", - Projects = [ - new() - { - FilePath = "path/to/my.csproj", - TargetFrameworks = ["net45"], - ReferencedProjectPaths = [], - ExpectedDependencyCount = 2, // Should we ignore Microsoft.NET.ReferenceAssemblies? - Dependencies = [ - new("Newtonsoft.Json", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]), - ], - Properties = [ - new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"), - ], - } - ] - }); + [ + "discover", + "--repo-root", + path, + "--workspace", + path, + ], + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + ], + initialFiles: + new[] + { + (solutionPath, """ + Microsoft Visual Studio Solution File, Format Version 12.00 + # Visual Studio 14 + VisualStudioVersion = 14.0.22705.0 + MinimumVisualStudioVersion = 10.0.40219.1 + Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "my", "my.csproj", "{782E0C0A-10D3-444D-9640-263D03D2B20C}" + EndProject + Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {782E0C0A-10D3-444D-9640-263D03D2B20C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {782E0C0A-10D3-444D-9640-263D03D2B20C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + EndGlobal + """), + ("path/to/my.csproj", """ + + + + v4.5 + + + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + """), + ("path/to/packages.config", """ + + + + """) + }, + expectedResult: new() + { + FilePath = "", + Projects = [ + new() + { + FilePath = "path/to/my.csproj", + TargetFrameworks = ["net45"], + ReferencedProjectPaths = [], + ExpectedDependencyCount = 2, + Dependencies = [ + new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]), + ], + Properties = [ + new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"), + ], + } + ] + } + ); } [Fact] @@ -101,58 +108,64 @@ public async Task WithProject() { var projectPath = "path/to/my.csproj"; await RunAsync(path => - [ - "discover", - "--repo-root", - path, - "--workspace", - path, - ], - new[] - { - (projectPath, """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """), - ("path/to/packages.config", """ - - - - """) - }, - expectedResult: new() - { - FilePath = "", - Projects = [ - new() - { - FilePath = projectPath, - TargetFrameworks = ["net45"], - ReferencedProjectPaths = [], - ExpectedDependencyCount = 2, // Should we ignore Microsoft.NET.ReferenceAssemblies? - Dependencies = [ - new("Newtonsoft.Json", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]) - ], - Properties = [ - new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"), - ], - } - ] - }); + [ + "discover", + "--repo-root", + path, + "--workspace", + path, + ], + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + ], + initialFiles: + new[] + { + (projectPath, """ + + + + v4.5 + + + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + """), + ("path/to/packages.config", """ + + + + """) + }, + expectedResult: new() + { + FilePath = "", + Projects = [ + new() + { + FilePath = projectPath, + TargetFrameworks = ["net45"], + ReferencedProjectPaths = [], + ExpectedDependencyCount = 2, + Dependencies = [ + new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]) + ], + Properties = [ + new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"), + ], + } + ] + } + ); } [Fact] @@ -160,58 +173,64 @@ public async Task WithDirectory() { var workspacePath = "path/to/"; await RunAsync(path => - [ - "discover", - "--repo-root", - path, - "--workspace", - Path.Combine(path, workspacePath), - ], - new[] - { - ("path/to/my.csproj", """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """), - ("path/to/packages.config", """ - - - - """) - }, - expectedResult: new() - { - FilePath = workspacePath, - Projects = [ - new() - { - FilePath = "my.csproj", - TargetFrameworks = ["net45"], - ReferencedProjectPaths = [], - ExpectedDependencyCount = 2, // Should we ignore Microsoft.NET.ReferenceAssemblies? - Dependencies = [ - new("Newtonsoft.Json", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]) - ], - Properties = [ - new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"), - ], - } - ] - }); + [ + "discover", + "--repo-root", + path, + "--workspace", + Path.Combine(path, workspacePath), + ], + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + ], + initialFiles: + new[] + { + ("path/to/my.csproj", """ + + + + v4.5 + + + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + """), + ("path/to/packages.config", """ + + + + """) + }, + expectedResult: new() + { + FilePath = workspacePath, + Projects = [ + new() + { + FilePath = "my.csproj", + TargetFrameworks = ["net45"], + ReferencedProjectPaths = [], + ExpectedDependencyCount = 2, + Dependencies = [ + new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]) + ], + Properties = [ + new("TargetFrameworkVersion", "v4.5", "path/to/my.csproj"), + ], + } + ] + } + ); } [Fact] @@ -288,7 +307,8 @@ public async Task WithDuplicateDependenciesOfDifferentTypes() private static async Task RunAsync( Func getArgs, TestFile[] initialFiles, - ExpectedWorkspaceDiscoveryResult expectedResult) + ExpectedWorkspaceDiscoveryResult expectedResult, + MockNuGetPackage[]? packages = null) { var actualResult = await RunDiscoveryAsync(initialFiles, async path => { @@ -302,6 +322,7 @@ public async Task WithDuplicateDependenciesOfDifferentTypes() try { + await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, path); var args = getArgs(path); var result = await Program.Main(args); if (result != 0) diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs index 42199f092cb..4f4a3ee2ce0 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs @@ -1,7 +1,4 @@ -using System; -using System.IO; using System.Text; -using System.Threading.Tasks; using NuGetUpdater.Core; using NuGetUpdater.Core.Test; @@ -26,12 +23,18 @@ public async Task WithSolution() "--solution-or-project", Path.Combine(path, "path/to/solution.sln"), "--dependency", - "Newtonsoft.Json", + "Some.package", "--new-version", "13.0.1", "--previous-version", "7.0.1", ], + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], + initialFiles: [ ("path/to/solution.sln", """ Microsoft Visual Studio Solution File, Format Version 12.00 @@ -66,8 +69,8 @@ public async Task WithSolution() - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll True @@ -76,10 +79,11 @@ public async Task WithSolution() """), ("path/to/packages.config", """ - + """) ], + expectedFiles: [ ("path/to/my.csproj", """ @@ -91,8 +95,8 @@ public async Task WithSolution() - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll True @@ -102,10 +106,11 @@ public async Task WithSolution() ("path/to/packages.config", """ - + """) - ]); + ] + ); } [Fact] @@ -119,13 +124,19 @@ public async Task WithProject() "--solution-or-project", Path.Combine(path, "path/to/my.csproj"), "--dependency", - "Newtonsoft.Json", + "Some.Package", "--new-version", "13.0.1", "--previous-version", "7.0.1", "--verbose" ], + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], + initialFiles: [ ("path/to/my.csproj", """ @@ -137,8 +148,8 @@ public async Task WithProject() - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll True @@ -147,10 +158,11 @@ public async Task WithProject() """), ("path/to/packages.config", """ - + """) ], + expectedFiles: [ ("path/to/my.csproj", """ @@ -162,8 +174,8 @@ public async Task WithProject() - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll True @@ -173,10 +185,11 @@ public async Task WithProject() ("path/to/packages.config", """ - + """) - ]); + ] + ); } [Fact] @@ -190,13 +203,18 @@ public async Task WithDirsProjAndDirectoryBuildPropsThatIsOutOfDirectoryButStill "--solution-or-project", $"{path}/some-dir/dirs.proj", "--dependency", - "NuGet.Versioning", + "Some.Package", "--new-version", "6.6.1", "--previous-version", "6.1.0", "--verbose" ], + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "6.1.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "6.6.1", "net8.0"), + ], initialFiles: [ ("some-dir/dirs.proj", """ @@ -211,12 +229,12 @@ public async Task WithDirsProjAndDirectoryBuildPropsThatIsOutOfDirectoryButStill Exe - net6.0 + net8.0 enable enable - + """), @@ -224,12 +242,12 @@ public async Task WithDirsProjAndDirectoryBuildPropsThatIsOutOfDirectoryButStill Exe - net6.0 + net8.0 enable enable - + """), @@ -237,7 +255,7 @@ public async Task WithDirsProjAndDirectoryBuildPropsThatIsOutOfDirectoryButStill - + @@ -258,12 +276,12 @@ public async Task WithDirsProjAndDirectoryBuildPropsThatIsOutOfDirectoryButStill Exe - net6.0 + net8.0 enable enable - + """), @@ -271,12 +289,12 @@ public async Task WithDirsProjAndDirectoryBuildPropsThatIsOutOfDirectoryButStill Exe - net6.0 + net8.0 enable enable - + """), @@ -284,7 +302,7 @@ public async Task WithDirsProjAndDirectoryBuildPropsThatIsOutOfDirectoryButStill - + @@ -303,6 +321,14 @@ public async Task UpdaterDoesNotUseRepoGlobalJsonForMSBuildTasks(string? working // test this, it must be tested in a new process where MSBuild has not been loaded yet and the runner tool // must be started with its working directory at the test repo's root. using var tempDir = new TemporaryDirectory(); + + MockNuGetPackage[] testPackages = + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ]; + await MockNuGetPackagesInDirectory(testPackages, tempDir.DirectoryPath); + var globalJsonPath = Path.Join(tempDir.DirectoryPath, "global.json"); var srcGlobalJsonPath = Path.Join(tempDir.DirectoryPath, "src", "global.json"); string globalJsonContent = """ @@ -322,20 +348,21 @@ public async Task UpdaterDoesNotUseRepoGlobalJsonForMSBuildTasks(string? working net8.0 - + """); - var executableName = $"NuGetUpdater.Cli{(Environment.OSVersion.Platform == PlatformID.Win32NT ? ".exe" : "")}"; + var executableName = Path.Join(Path.GetDirectoryName(GetType().Assembly.Location), "NuGetUpdater.Cli.dll"); var executableArgs = string.Join(" ", [ + executableName, "update", "--repo-root", tempDir.DirectoryPath, "--solution-or-project", projectPath, "--dependency", - "Newtonsoft.Json", + "Some.Package", "--new-version", "13.0.1", "--previous-version", @@ -350,7 +377,7 @@ public async Task UpdaterDoesNotUseRepoGlobalJsonForMSBuildTasks(string? working workingDirectory = Path.Join(workingDirectory, workingDirectoryPath); } - var (exitCode, output, error) = await ProcessEx.RunAsync(executableName, executableArgs, workingDirectory: workingDirectory); + var (exitCode, output, error) = await ProcessEx.RunAsync("dotnet", executableArgs, workingDirectory: workingDirectory); Assert.True(exitCode == 0, $"Error running update on unsupported SDK.\nSTDOUT:\n{output}\nSTDERR:\n{error}"); // verify project update @@ -366,7 +393,7 @@ public async Task UpdaterDoesNotUseRepoGlobalJsonForMSBuildTasks(string? working Assert.Contains("99.99.99", updatedGlobalJsonContents); } - private static async Task Run(Func getArgs, (string Path, string Content)[] initialFiles, (string, string)[] expectedFiles) + private static async Task Run(Func getArgs, (string Path, string Content)[] initialFiles, (string, string)[] expectedFiles, MockNuGetPackage[]? packages = null) { var actualFiles = await RunUpdate(initialFiles, async path => { @@ -380,6 +407,7 @@ private static async Task Run(Func getArgs, (string Path, stri try { + await MockNuGetPackagesInDirectory(packages, path); var args = getArgs(path); var result = await Program.Main(args); if (result != 0) diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs index 4ddcbbde273..0f811bf28ac 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs @@ -3,9 +3,11 @@ using System.Text.Json; using NuGetUpdater.Core.Discover; +using NuGetUpdater.Core.Test.Update; using NuGetUpdater.Core.Test.Utilities; using Xunit; +using Xunit.Sdk; namespace NuGetUpdater.Core.Test.Discover; @@ -16,10 +18,13 @@ public class DiscoveryWorkerTestBase protected static async Task TestDiscoveryAsync( string workspacePath, TestFile[] files, - ExpectedWorkspaceDiscoveryResult expectedResult) + ExpectedWorkspaceDiscoveryResult expectedResult, + MockNuGetPackage[]? packages = null) { var actualResult = await RunDiscoveryAsync(files, async directoryPath => { + await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, directoryPath); + var worker = new DiscoveryWorker(new Logger(verbose: true)); await worker.RunAsync(directoryPath, workspacePath, DiscoveryWorker.DiscoveryResultFileName); }); diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs index ce0cffdda4c..b2dafa70e61 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs @@ -10,6 +10,7 @@ public class DotNetToolsJson : DiscoveryWorkerTestBase public async Task DiscoversDependencies() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ (".config/dotnet-tools.json", """ @@ -45,13 +46,15 @@ public async Task DiscoversDependencies() ] }, ExpectedProjectCount = 0, - }); + } + ); } [Fact] public async Task ReportsFailure() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ (".config/dotnet-tools.json", """ @@ -85,7 +88,8 @@ public async Task ReportsFailure() ExpectedDependencyCount = 0, }, ExpectedProjectCount = 0, - }); + } + ); } } } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs index dd0b0ee8bac..fafb99d7ec2 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs @@ -10,6 +10,7 @@ public class GlobalJson : DiscoveryWorkerTestBase public async Task DiscoversDependencies() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ ("global.json", """ @@ -35,13 +36,15 @@ public async Task DiscoversDependencies() ] }, ExpectedProjectCount = 0, - }); + } + ); } [Fact] public async Task ReportsFailure() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ ("global.json", """ @@ -65,7 +68,8 @@ public async Task ReportsFailure() ExpectedDependencyCount = 0, }, ExpectedProjectCount = 0, - }); + } + ); } } } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs index a0dcab83d5f..e6adca58bee 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs @@ -1,5 +1,3 @@ -using System.Collections.Immutable; - using Xunit; namespace NuGetUpdater.Core.Test.Discover; @@ -12,20 +10,18 @@ public class PackagesConfig : DiscoveryWorkerTestBase public async Task DiscoversDependencies() { await TestDiscoveryAsync( + packages: + [ + MockNuGetPackage.CreateSimplePackage("Package.A", "1.0.0", "net46"), + MockNuGetPackage.CreateSimplePackage("Package.B", "2.0.0", "net46"), + ], workspacePath: "", files: [ ("packages.config", """ - - - - - - - - - + + """), ("myproj.csproj", """ @@ -49,19 +45,13 @@ public async Task DiscoversDependencies() TargetFrameworks = ["net46"], Dependencies = [ new("Microsoft.NETFramework.ReferenceAssemblies", "1.0.3", DependencyType.Unknown, TargetFrameworks: ["net46"], IsTransitive: true), - new("Microsoft.CodeDom.Providers.DotNetCompilerPlatform", "1.0.0", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), - new("Microsoft.Net.Compilers", "1.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), - new("Microsoft.Web.Infrastructure", "1.0.0.0", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), - new("Microsoft.Web.Xdt", "2.1.1", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), - new("Newtonsoft.Json", "8.0.3", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), - new("NuGet.Core", "2.11.1", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), - new("NuGet.Server", "2.11.2", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), - new("RouteMagic", "1.3", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), - new("WebActivatorEx", "2.1.0", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), + new("Package.A", "1.0.0", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), + new("Package.B", "2.0.0", DependencyType.PackagesConfig, TargetFrameworks: ["net46"]), ], } ], - }); + } + ); } } } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs index a578baf3d6a..0f7971f0e47 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs @@ -10,29 +10,27 @@ public class Projects : DiscoveryWorkerTestBase public async Task ReturnsPackageReferencesMissingVersions() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ ("myproj.csproj", """ Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. - netstandard1.6;net462 + net7.0;net8.0 - - - - - - 4.3.0 + + + - - + + """) @@ -44,44 +42,43 @@ public async Task ReturnsPackageReferencesMissingVersions() new() { FilePath = "myproj.csproj", - ExpectedDependencyCount = 52, + ExpectedDependencyCount = 3, Dependencies = [ - new("Microsoft.Extensions.DependencyModel", "1.1.1", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("Microsoft.AspNetCore.App", "", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("Microsoft.NET.Test.Sdk", "", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk), - new("Microsoft.Extensions.PlatformAbstractions", "1.1.0", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("System.Collections.Specialized", "4.3.0", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), + new("Package.A", "1.1.1", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), + new("Package.B", "", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), ], Properties = [ new("Description", "Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications.", "myproj.csproj"), - new("TargetFrameworks", "netstandard1.6;net462", "myproj.csproj"), + new("TargetFrameworks", "net7.0;net8.0", "myproj.csproj"), ], - TargetFrameworks = ["net462", "netstandard1.6"], + TargetFrameworks = ["net7.0", "net8.0"], ReferencedProjectPaths = [], } ], - }); + } + ); } [Fact] public async Task WithDirectoryPackagesProps() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ ("myproj.csproj", """ Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. - netstandard1.6;net462 + net7.0;net8.0 - + @@ -89,7 +86,7 @@ public async Task WithDirectoryPackagesProps() 4.3.0 - + @@ -115,21 +112,21 @@ public async Task WithDirectoryPackagesProps() new() { FilePath = "myproj.csproj", - ExpectedDependencyCount = 52, + ExpectedDependencyCount = 6, Dependencies = [ - new("Microsoft.Extensions.DependencyModel", "1.1.1", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("Microsoft.AspNetCore.App", "", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("Microsoft.NET.Test.Sdk", "", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), + new("Microsoft.Extensions.DependencyModel", "1.1.1", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), + new("Microsoft.AspNetCore.App", "", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), + new("Microsoft.NET.Test.Sdk", "", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk), - new("Microsoft.Extensions.PlatformAbstractions", "1.1.0", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("System.Collections.Specialized", "4.3.0", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), + new("Microsoft.Extensions.PlatformAbstractions", "1.1.0", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), + new("System.Collections.Specialized", "4.3.0", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), ], Properties = [ new("Description", "Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications.", "myproj.csproj"), new("ManagePackageVersionsCentrally", "true", "Directory.Packages.props"), - new("TargetFrameworks", "netstandard1.6;net462", "myproj.csproj"), + new("TargetFrameworks", "net7.0;net8.0", "myproj.csproj"), ], - TargetFrameworks = ["net462", "netstandard1.6"], + TargetFrameworks = ["net7.0", "net8.0"], }, ], DirectoryPackagesProps = new() @@ -143,13 +140,15 @@ public async Task WithDirectoryPackagesProps() new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk), ], }, - }); + } + ); } [Fact] public async Task WithDirectoryBuildPropsAndTargets() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ ("project.csproj", """ @@ -157,7 +156,7 @@ public async Task WithDirectoryBuildPropsAndTargets() Exe - net6.0 + net7.0 enable enable @@ -195,16 +194,16 @@ public async Task WithDirectoryBuildPropsAndTargets() FilePath = "project.csproj", ExpectedDependencyCount = 3, Dependencies = [ - new("NuGet.Versioning", "6.1.0", DependencyType.PackageReference, TargetFrameworks: ["net6.0"], IsDirect: false), - new("Microsoft.CodeAnalysis.Analyzers", "3.3.0", DependencyType.PackageReference, TargetFrameworks: ["net6.0"], IsDirect: false), + new("NuGet.Versioning", "6.1.0", DependencyType.PackageReference, TargetFrameworks: ["net7.0"], IsDirect: false), + new("Microsoft.CodeAnalysis.Analyzers", "3.3.0", DependencyType.PackageReference, TargetFrameworks: ["net7.0"], IsDirect: false), ], Properties = [ new("ImplicitUsings", "enable", "project.csproj"), new("Nullable", "enable", "project.csproj"), new("OutputType", "Exe", "project.csproj"), - new("TargetFramework", "net6.0", "project.csproj"), + new("TargetFramework", "net7.0", "project.csproj"), ], - TargetFrameworks = ["net6.0"], + TargetFrameworks = ["net7.0"], }, new() { @@ -227,7 +226,8 @@ public async Task WithDirectoryBuildPropsAndTargets() TargetFrameworks = [], }, ], - }); + } + ); } [Fact] @@ -247,20 +247,24 @@ public async Task WithPackagesProps() Environment.SetEnvironmentVariable("NUGET_HTTP_CACHE_PATH", tempNuGetHttpCacheDirectory); await TestDiscoveryAsync( + packages: + [ + MockNuGetPackage.CentralPackageVersionsPackage, + ], workspacePath: "", files: [ ("myproj.csproj", """ Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. - netstandard1.6;net462 + net7.0;net8.0 - + @@ -268,7 +272,7 @@ public async Task WithPackagesProps() 4.3.0 - + @@ -294,25 +298,25 @@ public async Task WithPackagesProps() expectedResult: new() { FilePath = "", - ExpectedProjectCount = 3, + ExpectedProjectCount = 5, Projects = [ new() { FilePath = "myproj.csproj", - ExpectedDependencyCount = 58, + ExpectedDependencyCount = 12, Dependencies = [ - new("Microsoft.Extensions.DependencyModel", "1.1.1", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("Microsoft.AspNetCore.App", "", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("Microsoft.NET.Test.Sdk", "", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), + new("Microsoft.Extensions.DependencyModel", "1.1.1", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), + new("Microsoft.AspNetCore.App", "", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), + new("Microsoft.NET.Test.Sdk", "", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk), - new("Microsoft.Extensions.PlatformAbstractions", "1.1.0", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), - new("System.Collections.Specialized", "4.3.0", DependencyType.PackageReference, TargetFrameworks: ["net462", "netstandard1.6"], IsDirect: true), + new("Microsoft.Extensions.PlatformAbstractions", "1.1.0", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), + new("System.Collections.Specialized", "4.3.0", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), ], Properties = [ new("Description", "Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications.", "myproj.csproj"), - new("TargetFrameworks", "netstandard1.6;net462", "myproj.csproj"), + new("TargetFrameworks", "net7.0;net8.0", "myproj.csproj"), ], - TargetFrameworks = ["net462", "netstandard1.6"], + TargetFrameworks = ["net7.0", "net8.0"], }, new() { @@ -327,7 +331,8 @@ public async Task WithPackagesProps() ], }, ], - }); + } + ); } finally { @@ -341,6 +346,7 @@ public async Task WithPackagesProps() public async Task ReturnsDependenciesThatCannotBeEvaluated() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ ("myproj.csproj", """ @@ -374,7 +380,8 @@ public async Task ReturnsDependenciesThatCannotBeEvaluated() ReferencedProjectPaths = [], } ], - }); + } + ); } [Fact] @@ -382,6 +389,7 @@ public async Task ReturnsDependenciesThatCannotBeEvaluated() public async Task NoDependenciesReturnedIfNoTargetFrameworkCanBeResolved() { await TestDiscoveryAsync( + packages: [], workspacePath: "", files: [ ("myproj.csproj", """ @@ -399,23 +407,29 @@ public async Task NoDependenciesReturnedIfNoTargetFrameworkCanBeResolved() { FilePath = "", Projects = [] - }); + } + ); } [Fact] public async Task DiscoverReportsTransitivePackageVersionsWithFourPartsForMultipleTargetFrameworks() { await TestDiscoveryAsync( + packages: + [ + new("Some.Package", "1.2.3.4", Files: [("lib/net7.0/Some.Package.dll", Array.Empty()), ("lib/net8.0/Some.Package.dll", Array.Empty())], DependencyGroups: [(null, [("Transitive.Dependency", "5.6.7.8")])]), + new("Transitive.Dependency", "5.6.7.8", Files: [("lib/net7.0/Transitive.Dependency.dll", Array.Empty()), ("lib/net8.0/Transitive.Dependency.dll", Array.Empty())]), + ], workspacePath: "", files: [ ("myproj.csproj", """ - netstandard2.0;net8.0 + net7.0;net8.0 - + """) @@ -427,19 +441,15 @@ public async Task DiscoverReportsTransitivePackageVersionsWithFourPartsForMultip new() { FilePath = "myproj.csproj", + ExpectedDependencyCount = 3, Dependencies = [ - new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk), - new("AWSSDK.S3", "3.7.307.29", DependencyType.PackageReference, TargetFrameworks: ["net8.0", "netstandard2.0"], IsDirect: true), - new("AWSSDK.Core", "3.7.303.27", DependencyType.Unknown, TargetFrameworks: ["net8.0", "netstandard2.0"], IsTransitive: true), - new("Microsoft.Bcl.AsyncInterfaces", "1.1.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("NETStandard.Library", "2.0.3", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.CompilerServices.Unsafe", "4.5.2", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Threading.Tasks.Extensions", "4.5.2", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), + new("Some.Package", "1.2.3.4", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true), + new("Transitive.Dependency", "5.6.7.8", DependencyType.Unknown, TargetFrameworks: ["net7.0", "net8.0"], IsTransitive: true), ], Properties = [ - new("TargetFrameworks", "netstandard2.0;net8.0", "myproj.csproj"), + new("TargetFrameworks", "net7.0;net8.0", "myproj.csproj"), ], - TargetFrameworks = ["net8.0", "netstandard2.0"], + TargetFrameworks = ["net7.0", "net8.0"], ReferencedProjectPaths = [], } ], diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs index 9351ca51aea..cd5f982fee1 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs @@ -11,18 +11,22 @@ public partial class DiscoveryWorkerTests : DiscoveryWorkerTestBase public async Task TestProjectFiles(string projectPath) { await TestDiscoveryAsync( + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + ], workspacePath: "src", files: new[] { (projectPath, """ - netstandard2.0 - 9.0.1 + net8.0 + 9.0.1 - + """) @@ -34,16 +38,16 @@ public async Task TestProjectFiles(string projectPath) new() { FilePath = Path.GetFileName(projectPath), - TargetFrameworks = ["netstandard2.0"], + TargetFrameworks = ["net8.0"], ReferencedProjectPaths = [], - ExpectedDependencyCount = 19, + ExpectedDependencyCount = 2, Dependencies = [ new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk), - new("Newtonsoft.Json", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["netstandard2.0"], IsDirect: true) + new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true) ], Properties = [ - new("NewtonsoftJsonPackageVersion", "9.0.1", projectPath), - new("TargetFramework", "netstandard2.0", projectPath), + new("SomePackageVersion", "9.0.1", projectPath), + new("TargetFramework", "net8.0", projectPath), ] } ] @@ -56,6 +60,10 @@ public async Task TestPackageConfig() { var projectPath = "src/project.csproj"; await TestDiscoveryAsync( + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + ], workspacePath: "", files: new[] { @@ -69,8 +77,8 @@ public async Task TestPackageConfig() - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll True @@ -79,7 +87,7 @@ public async Task TestPackageConfig() """), ("src/packages.config", """ - + """), }, @@ -92,9 +100,10 @@ public async Task TestPackageConfig() FilePath = projectPath, TargetFrameworks = ["net45"], ReferencedProjectPaths = [], - ExpectedDependencyCount = 2, // Should we ignore Microsoft.NET.ReferenceAssemblies? + ExpectedDependencyCount = 2, Dependencies = [ - new("Newtonsoft.Json", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]) + new("Microsoft.NETFramework.ReferenceAssemblies", "1.0.3", DependencyType.Unknown, TargetFrameworks: ["net45"], IsTransitive: true), + new("Some.Package", "7.0.1", DependencyType.PackagesConfig, TargetFrameworks: ["net45"]), ], Properties = [ new("TargetFrameworkVersion", "v4.5", projectPath), @@ -110,17 +119,21 @@ public async Task TestProps() { var projectPath = "src/project.csproj"; await TestDiscoveryAsync( + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + ], workspacePath: "", files: new[] { (projectPath, """ - netstandard2.0 + net8.0 - + """), @@ -128,11 +141,11 @@ public async Task TestProps() true - 9.0.1 + 9.0.1 - + """) @@ -144,17 +157,17 @@ public async Task TestProps() new() { FilePath = projectPath, - TargetFrameworks = ["netstandard2.0"], + TargetFrameworks = ["net8.0"], ReferencedProjectPaths = [], - ExpectedDependencyCount = 19, + ExpectedDependencyCount = 2, Dependencies = [ new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk), - new("Newtonsoft.Json", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["netstandard2.0"], IsDirect: true) + new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net8.0"], IsDirect: true) ], Properties = [ new("ManagePackageVersionsCentrally", "true", "Directory.Packages.props"), - new("NewtonsoftJsonPackageVersion", "9.0.1", "Directory.Packages.props"), - new("TargetFramework", "netstandard2.0", projectPath), + new("SomePackageVersion", "9.0.1", "Directory.Packages.props"), + new("TargetFramework", "net8.0", projectPath), ] } ], @@ -162,7 +175,7 @@ public async Task TestProps() { FilePath = "Directory.Packages.props", Dependencies = [ - new("Newtonsoft.Json", "9.0.1", DependencyType.PackageVersion, IsDirect: true) + new("Some.Package", "9.0.1", DependencyType.PackageVersion, IsDirect: true) ], } } @@ -174,17 +187,21 @@ public async Task TestRepo() { var solutionPath = "solution.sln"; await TestDiscoveryAsync( + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + ], workspacePath: "", files: new[] { ("src/project.csproj", """ - netstandard2.0;net6.0 + net7.0;net8.0 - + """), @@ -192,11 +209,11 @@ public async Task TestRepo() true - 9.0.1 + 9.0.1 - + """), @@ -263,16 +280,16 @@ public async Task TestRepo() new() { FilePath = "src/project.csproj", - TargetFrameworks = ["net6.0", "netstandard2.0"], - ExpectedDependencyCount = 19, + TargetFrameworks = ["net7.0", "net8.0"], + ExpectedDependencyCount = 2, Dependencies = [ new("Microsoft.NET.Sdk", null, DependencyType.MSBuildSdk), - new("Newtonsoft.Json", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net6.0", "netstandard2.0"], IsDirect: true) + new("Some.Package", "9.0.1", DependencyType.PackageReference, TargetFrameworks: ["net7.0", "net8.0"], IsDirect: true) ], Properties = [ new("ManagePackageVersionsCentrally", "true", "Directory.Packages.props"), - new("NewtonsoftJsonPackageVersion", "9.0.1", "Directory.Packages.props"), - new("TargetFrameworks", "netstandard2.0;net6.0", "src/project.csproj"), + new("SomePackageVersion", "9.0.1", "Directory.Packages.props"), + new("TargetFrameworks", "net7.0;net8.0", "src/project.csproj"), ] } ], @@ -280,7 +297,7 @@ public async Task TestRepo() { FilePath = "Directory.Packages.props", Dependencies = [ - new("Newtonsoft.Json", "9.0.1", DependencyType.PackageVersion, IsDirect: true) + new("Some.Package", "9.0.1", DependencyType.PackageVersion, IsDirect: true) ], }, GlobalJson = new() diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs new file mode 100644 index 00000000000..d5dce346346 --- /dev/null +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs @@ -0,0 +1,419 @@ +using System.IO.Compression; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json.Nodes; +using System.Text.RegularExpressions; +using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Emit; + +namespace NuGetUpdater.Core.Test +{ + public record MockNuGetPackage( + string Id, + string Version, + XElement[]? AdditionalMetadata = null, + (string? TargetFramework, (string Id, string Version)[] Packages)[]? DependencyGroups = null, + (string Path, byte[] Content)[]? Files = null) + { + private static readonly XNamespace Namespace = "http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"; + private static readonly XmlWriterSettings WriterSettings = new() + { + Encoding = Encoding.UTF8, + Indent = true, + }; + + private XDocument? _nuspec; + private Stream? _stream; + + public void WriteToDirectory(string localPackageSourcePath) + { + string cachePath = Path.Join(localPackageSourcePath, "_nupkg_cache"); + string nupkgPath = Path.Join(cachePath, $"{Id}.{Version}.nupkg"); + Directory.CreateDirectory(cachePath); + Stream stream = GetZipStream(); + using (FileStream fileStream = new(nupkgPath, FileMode.Create)) + { + stream.CopyTo(fileStream); + } + + // add the package to the local feed; this is equivalent to running + // nuget add -source + // but running that in-process locks the files, so we have to do it manually + // the end result is 4 files: + // .nupkg.metadata // a JSON object with the package's content hash and some other fields + // ..nupkg // the package itself + // ..nupkg.sha512 // the SHA512 hash of the package + // .nuspec // the package's nuspec file + string expandedPath = Path.Join(localPackageSourcePath, Id.ToLowerInvariant(), Version); + Directory.CreateDirectory(expandedPath); + File.Copy(nupkgPath, Path.Join(expandedPath, $"{Id}.{Version}.nupkg".ToLowerInvariant())); + using XmlWriter writer = XmlWriter.Create(Path.Join(expandedPath, $"{Id}.nuspec".ToLowerInvariant()), WriterSettings); + GetNuspec().WriteTo(writer); + using SHA512 sha512 = SHA512.Create(); + byte[] hash = sha512.ComputeHash(File.ReadAllBytes(nupkgPath)); + string hashString = Convert.ToBase64String(hash); + File.WriteAllText(Path.Join(expandedPath, $"{Id}.{Version}.nupkg.sha512".ToLowerInvariant()), hashString); + JsonObject metadata = new() + { + ["version"] = 2, + ["contentHash"] = hashString, + ["source"] = null, + }; + File.WriteAllText(Path.Join(expandedPath, ".nupkg.metadata"), metadata.ToString()); + } + + /// + /// Creates a mock NuGet package with a single assembly in the appropriate `lib/` directory. The assembly will + /// be empty. + /// + public static MockNuGetPackage CreateSimplePackage(string id, string version, string targetFramework, (string? TargetFramework, (string Id, string Version)[] Packages)[]? dependencyGroups = null) + { + return new( + id, + version, + AdditionalMetadata: null, + DependencyGroups: dependencyGroups, + Files: + [ + ($"lib/{targetFramework}/{id}.dll", Array.Empty()) + ] + ); + } + + /// + /// Creates a mock NuGet package with a single assembly in the appropriate `lib/` directory. The assembly will + /// contain the appropriate `AssemblyVersion` attribute and nothing else. + /// + public static MockNuGetPackage CreatePackageWithAssembly(string id, string version, string targetFramework, string assemblyVersion, (string? TargetFramework, (string Id, string Version)[] Packages)[]? dependencyGroups = null) + { + return new( + id, + version, + AdditionalMetadata: null, + DependencyGroups: dependencyGroups, + Files: + [ + ($"lib/{targetFramework}/{id}.dll", CreateAssembly(id, assemblyVersion)) + ] + ); + } + + /// + /// Creates a mock NuGet package with empty analyzer assemblies for both C# and VB. + /// + public static MockNuGetPackage CreateAnalyzerPackage(string id, string version, (string? TargetFramework, (string Id, string Version)[] Packages)[]? dependencyGroups = null) + { + return new( + id, + version, + AdditionalMetadata: + [ + new XElement("developmentDependency", "true"), + ], + DependencyGroups: dependencyGroups, + Files: + [ + ($"analyzers/dotnet/cs/{id}.dll", Array.Empty()), + ($"analyzers/dotnet/vb/{id}.dll", Array.Empty()), + ] + ); + } + + public static MockNuGetPackage CreateDotNetToolPackage(string id, string version, string targetFramework) + { + return new( + id, + version, + AdditionalMetadata: + [ + new XElement("packageTypes", + new XElement("packageType", + new XAttribute("name", "DotnetTool") + ) + ) + ], + Files: + [ + ($"tools/{targetFramework}/any/DotnetToolSettings.xml", Encoding.UTF8.GetBytes($""" + + + + + + """)), + ($"tools/{targetFramework}/any/{id}.dll", Array.Empty()), + ] + ); + } + + public static MockNuGetPackage CreateMSBuildSdkPackage(string id, string version, string? sdkPropsContent = null, string? sdkTargetsContent = null) + { + sdkPropsContent ??= """ + + + """; + sdkTargetsContent ??= """ + + + """; + return new( + id, + version, + AdditionalMetadata: + [ + new XElement("packageTypes", + new XElement("packageType", + new XAttribute("name", "MSBuildSdk") + ) + ) + ], + Files: + [ + ("Sdk/Sdk.props", Encoding.UTF8.GetBytes(sdkPropsContent)), + ("Sdk/Sdk.targets", Encoding.UTF8.GetBytes(sdkTargetsContent)), + ] + ); + } + + private XDocument GetNuspec() + { + if (_nuspec is null) + { + _nuspec = new XDocument( + new XElement(Namespace + "package", + new XElement(Namespace + "metadata", + new XElement(Namespace + "id", Id), + new XElement(Namespace + "version", Version), + new XElement(Namespace + "authors", "MockNuGetPackage"), + new XElement(Namespace + "description", "Mock NuGet package"), + AdditionalMetadata?.Select(a => WithNamespace(a, Namespace)), + new XElement(Namespace + "dependencies", + // dependencies with no target framework + DependencyGroups?.Where(g => g.TargetFramework is null).SelectMany(g => + g.Packages.Select(p => + new XElement(Namespace + "dependency", + new XAttribute("id", p.Id), + new XAttribute("version", p.Version) + ) + ) + ), + // dependencies with a target framework + DependencyGroups?.Where(g => g.TargetFramework is not null).Select(g => + new XElement(Namespace + "group", + new XAttribute("targetFramework", g.TargetFramework!), + g.Packages.Select(p => + new XElement(Namespace + "dependency", + new XAttribute("id", p.Id), + new XAttribute("version", p.Version) + ) + ) + ) + ) + ) + ) + ) + ); + } + + return _nuspec; + } + + private static XElement WithNamespace(XElement element, XNamespace ns) + { + return new XElement(ns + element.Name.LocalName, + element.Attributes(), + element.Nodes().Select(n => + { + if (n is XElement e) + { + return WithNamespace(e, ns); + } + + return n; + }) + ); + } + + private Stream GetZipStream() + { + if (_stream is null) + { + XDocument nuspec = GetNuspec(); + _stream = new MemoryStream(); + using ZipArchive zip = new(_stream, ZipArchiveMode.Create, leaveOpen: true); + ZipArchiveEntry nuspecEntry = zip.CreateEntry($"{Id}.nuspec"); + using (Stream contentStream = nuspecEntry.Open()) + using (XmlWriter writer = XmlWriter.Create(contentStream, WriterSettings)) + { + nuspec.WriteTo(writer); + } + + foreach (var file in Files ?? []) + { + ZipArchiveEntry fileEntry = zip.CreateEntry(file.Path); + using Stream contentStream = fileEntry.Open(); + contentStream.Write(file.Content, 0, file.Content.Length); + } + } + + _stream.Seek(0, SeekOrigin.Begin); + return _stream; + } + + private static byte[] CreateAssembly(string assemblyName, string assemblyVersion) + { + CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary); + CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, options: compilationOptions) + .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) + .AddSyntaxTrees(CSharpSyntaxTree.ParseText($"[assembly: System.Reflection.AssemblyVersionAttribute(\"{assemblyVersion}\")]")); + MemoryStream assemblyStream = new(); + EmitResult emitResult = compilation.Emit(assemblyStream); + if (!emitResult.Success) + { + throw new Exception($"Unable to create test assembly:\n\t{string.Join("\n\t", emitResult.Diagnostics.ToString())}"); + } + + return assemblyStream.ToArray(); + } + + // some well-known packages + public static MockNuGetPackage CentralPackageVersionsPackage => + CreateMSBuildSdkPackage( + "Microsoft.Build.CentralPackageVersions", + "2.1.3", + sdkTargetsContent: """ + + + + $([MSBuild]::GetPathOfFileAbove('Packages.props', $(MSBuildProjectDirectory))) + + + + """ + ); + + private static readonly Lazy BundledVersionsPropsPath = new(() => + { + // we need to find the file `Microsoft.NETCoreSdk.BundledVersions.props` in the SDK directory + + DirectoryInfo projectDir = Directory.CreateTempSubdirectory("bundled_versions_props_path_discovery_"); + try + { + // get the sdk version + string projectPath = Path.Combine(projectDir.FullName, "project.csproj"); + File.WriteAllText(projectPath, """ + + + + + + """ + ); + var (exitCode, stdout, stderr) = ProcessEx.RunAsync("dotnet", $"msbuild {projectPath} /t:_ReportCurrentSdkVersion").Result; + if (exitCode != 0) + { + throw new Exception($"Failed to report the current SDK version:\n{stdout}\n{stderr}"); + } + + MatchCollection matches = Regex.Matches(stdout, "_CurrentSdkVersion=(?.*)$", RegexOptions.Multiline); + if (matches.Count == 0) + { + throw new Exception($"Failed to find the current SDK version in the output:\n{stdout}"); + } + + string sdkVersionString = matches.First().Groups["SdkVersion"].Value.Trim(); + + // find the actual SDK directory + string privateCoreLibPath = typeof(object).Assembly.Location; // e.g., C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.4\System.Private.CoreLib.dll + string sdkDirectory = Path.Combine(Path.GetDirectoryName(privateCoreLibPath)!, "..", "..", "..", "sdk", sdkVersionString); // e.g., C:\Program Files\dotnet\sdk\8.0.204 + string bundledVersionsPropsPath = Path.Combine(sdkDirectory, "Microsoft.NETCoreSdk.BundledVersions.props"); + FileInfo normalizedPath = new(bundledVersionsPropsPath); + return normalizedPath.FullName; + } + finally + { + projectDir.Delete(recursive: true); + } + }); + + private static readonly Dictionary WellKnownPackages = new(); + public static MockNuGetPackage WellKnownReferencePackage(string packageName, string targetFramework, (string Path, byte[] Content)[]? files = null) + { + string key = $"{packageName}/{targetFramework}"; + if (!WellKnownPackages.ContainsKey(key)) + { + // for the current SDK, the file `Microsoft.NETCoreSdk.BundledVersions.props` contains the version of the + // `Microsoft.WindowsDesktop.App.Ref` package that will be needed to build, so we find it by TFM + XDocument propsDocument = XDocument.Load(BundledVersionsPropsPath.Value); + XElement? matchingFrameworkElement = propsDocument.XPathSelectElement( + $""" + /Project/ItemGroup/KnownFrameworkReference + [ + @Include='{packageName}' and + @TargetingPackName='{packageName}.Ref' and + @TargetFramework='{targetFramework}' + ] + """); + if (matchingFrameworkElement is null) + { + throw new Exception($"Unable to find {packageName}.Ref version for target framework '{targetFramework}'"); + } + + string expectedVersion = matchingFrameworkElement.Attribute("TargetingPackVersion")!.Value; + return new( + $"{packageName}.Ref", + expectedVersion, + AdditionalMetadata: + [ + new XElement("packageTypes", + new XElement("packageType", + new XAttribute("name", "DotnetPlatform") + ) + ) + ], + Files: files + ); + } + + return WellKnownPackages[key]; + } + + public static MockNuGetPackage[] CommonPackages { get; } = + [ + CreateSimplePackage("NETStandard.Library", "2.0.3", "netstandard2.0"), + new MockNuGetPackage("Microsoft.NETFramework.ReferenceAssemblies", "1.0.3"), + WellKnownReferencePackage("Microsoft.AspNetCore.App", "net6.0"), + WellKnownReferencePackage("Microsoft.AspNetCore.App", "net7.0"), + WellKnownReferencePackage("Microsoft.AspNetCore.App", "net8.0"), + WellKnownReferencePackage("Microsoft.NETCore.App", "net6.0", + [ + ("data/FrameworkList.xml", Encoding.UTF8.GetBytes(""" + + + """)) + ]), + WellKnownReferencePackage("Microsoft.NETCore.App", "net7.0", + [ + ("data/FrameworkList.xml", Encoding.UTF8.GetBytes(""" + + + """)) + ]), + WellKnownReferencePackage("Microsoft.NETCore.App", "net8.0", + [ + ("data/FrameworkList.xml", Encoding.UTF8.GetBytes(""" + + + """)) + ]), + WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net6.0"), + WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net7.0"), + WellKnownReferencePackage("Microsoft.WindowsDesktop.App", "net8.0"), + ]; + } +} diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj index 62a33812dd6..b17566b7f37 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/NuGetUpdater.Core.Test.csproj @@ -12,6 +12,7 @@ + diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs index dcf40e207c7..9397fb8a999 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs @@ -1,8 +1,3 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - using Xunit; namespace NuGetUpdater.Core.Test.Update; @@ -20,11 +15,12 @@ public abstract class UpdateWorkerTestBase : TestBase string projectContents, bool isTransitive = false, TestFile[]? additionalFiles = null, + MockNuGetPackage[]? packages = null, string projectFilePath = "test-project.csproj") { return useSolution - ? TestNoChangeforSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], isTransitive, additionalFiles) - : TestNoChangeforProject(dependencyName, oldVersion, newVersion, projectContents, isTransitive, additionalFiles, projectFilePath); + ? TestNoChangeforSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], isTransitive, additionalFiles, packages) + : TestNoChangeforProject(dependencyName, oldVersion, newVersion, projectContents, isTransitive, additionalFiles, packages, projectFilePath); } protected static Task TestUpdate( @@ -37,11 +33,12 @@ public abstract class UpdateWorkerTestBase : TestBase bool isTransitive = false, TestFile[]? additionalFiles = null, TestFile[]? additionalFilesExpected = null, + MockNuGetPackage[]? packages = null, string projectFilePath = "test-project.csproj") { return useSolution - ? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], projectFilesExpected: [(projectFilePath, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected) - : TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile: (projectFilePath, projectContents), expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected); + ? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [(projectFilePath, projectContents)], projectFilesExpected: [(projectFilePath, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected, packages) + : TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile: (projectFilePath, projectContents), expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected, packages); } protected static Task TestUpdate( @@ -53,11 +50,12 @@ public abstract class UpdateWorkerTestBase : TestBase string expectedProjectContents, bool isTransitive = false, TestFile[]? additionalFiles = null, - TestFile[]? additionalFilesExpected = null) + TestFile[]? additionalFilesExpected = null, + MockNuGetPackage[]? packages = null) { return useSolution - ? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [projectFile], projectFilesExpected: [(projectFile.Path, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected) - : TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile, expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected); + ? TestUpdateForSolution(dependencyName, oldVersion, newVersion, projectFiles: [projectFile], projectFilesExpected: [(projectFile.Path, expectedProjectContents)], isTransitive, additionalFiles, additionalFilesExpected, packages) + : TestUpdateForProject(dependencyName, oldVersion, newVersion, projectFile, expectedProjectContents, isTransitive, additionalFiles, additionalFilesExpected, packages); } protected static Task TestNoChangeforProject( @@ -67,6 +65,7 @@ public abstract class UpdateWorkerTestBase : TestBase string projectContents, bool isTransitive = false, TestFile[]? additionalFiles = null, + MockNuGetPackage[]? packages = null, string projectFilePath = "test-project.csproj") => TestUpdateForProject( dependencyName, @@ -76,7 +75,8 @@ public abstract class UpdateWorkerTestBase : TestBase expectedProjectContents: projectContents, isTransitive, additionalFiles, - additionalFilesExpected: additionalFiles); + additionalFilesExpected: additionalFiles, + packages: packages); protected static Task TestUpdateForProject( string dependencyName, @@ -87,6 +87,7 @@ public abstract class UpdateWorkerTestBase : TestBase bool isTransitive = false, TestFile[]? additionalFiles = null, TestFile[]? additionalFilesExpected = null, + MockNuGetPackage[]? packages = null, string projectFilePath = "test-project.csproj") => TestUpdateForProject( dependencyName, @@ -96,7 +97,8 @@ public abstract class UpdateWorkerTestBase : TestBase expectedProjectContents, isTransitive, additionalFiles, - additionalFilesExpected); + additionalFilesExpected, + packages); protected static async Task TestUpdateForProject( string dependencyName, @@ -106,21 +108,36 @@ public abstract class UpdateWorkerTestBase : TestBase string expectedProjectContents, bool isTransitive = false, TestFile[]? additionalFiles = null, - TestFile[]? additionalFilesExpected = null) + TestFile[]? additionalFilesExpected = null, + MockNuGetPackage[]? packages = null) { additionalFiles ??= []; additionalFilesExpected ??= []; + var placeFilesInSrc = packages is not null; + var projectFilePath = projectFile.Path; var testFiles = new[] { projectFile }.Concat(additionalFiles).ToArray(); + if (placeFilesInSrc) + { + testFiles = testFiles.Select(f => ($"src/{f.Path}", f.Content)).ToArray(); + } var actualResult = await RunUpdate(testFiles, async temporaryDirectory => { + await MockNuGetPackagesInDirectory(packages, temporaryDirectory); + + // run update var worker = new UpdaterWorker(new Logger(verbose: true)); - await worker.RunAsync(temporaryDirectory, projectFilePath, dependencyName, oldVersion, newVersion, isTransitive); + var projectPath = placeFilesInSrc ? $"src/{projectFilePath}" : projectFilePath; + await worker.RunAsync(temporaryDirectory, projectPath, dependencyName, oldVersion, newVersion, isTransitive); }); var expectedResult = additionalFilesExpected.Prepend((projectFilePath, expectedProjectContents)).ToArray(); + if (placeFilesInSrc) + { + expectedResult = expectedResult.Select(er => ($"src/{er.Item1}", er.Item2)).ToArray(); + } AssertContainsFiles(expectedResult, actualResult); } @@ -131,7 +148,8 @@ public abstract class UpdateWorkerTestBase : TestBase string newVersion, TestFile[] projectFiles, bool isTransitive = false, - TestFile[]? additionalFiles = null) + TestFile[]? additionalFiles = null, + MockNuGetPackage[]? packages = null) => TestUpdateForSolution( dependencyName, oldVersion, @@ -140,7 +158,8 @@ public abstract class UpdateWorkerTestBase : TestBase projectFilesExpected: projectFiles, isTransitive, additionalFiles, - additionalFilesExpected: additionalFiles); + additionalFilesExpected: additionalFiles, + packages: packages); protected static async Task TestUpdateForSolution( string dependencyName, @@ -150,7 +169,8 @@ public abstract class UpdateWorkerTestBase : TestBase TestFile[] projectFilesExpected, bool isTransitive = false, TestFile[]? additionalFiles = null, - TestFile[]? additionalFilesExpected = null) + TestFile[]? additionalFilesExpected = null, + MockNuGetPackage[]? packages = null) { additionalFiles ??= []; additionalFilesExpected ??= []; @@ -191,6 +211,8 @@ public abstract class UpdateWorkerTestBase : TestBase var actualResult = await RunUpdate(testFiles, async temporaryDirectory => { + await MockNuGetPackagesInDirectory(packages, temporaryDirectory); + var slnPath = Path.Combine(temporaryDirectory, slnName); var worker = new UpdaterWorker(new Logger(verbose: true)); await worker.RunAsync(temporaryDirectory, slnPath, dependencyName, oldVersion, newVersion, isTransitive); @@ -201,6 +223,42 @@ public abstract class UpdateWorkerTestBase : TestBase AssertContainsFiles(expectedResult, actualResult); } + public static async Task MockNuGetPackagesInDirectory(MockNuGetPackage[]? packages, string temporaryDirectory) + { + if (packages is not null) + { + string localFeedPath = Path.Join(temporaryDirectory, "local-feed"); + Directory.CreateDirectory(localFeedPath); + MockNuGetPackage[] allPackages = packages.Concat(MockNuGetPackage.CommonPackages).ToArray(); + + // write all packages to disk + foreach (MockNuGetPackage package in allPackages) + { + package.WriteToDirectory(localFeedPath); + } + + // override various nuget locations + foreach (var envName in new[] { "NUGET_PACKAGES", "NUGET_HTTP_CACHE_PATH", "NUGET_SCRATCH", "NUGET_PLUGINS_CACHE_PATH" }) + { + string dir = Path.Join(temporaryDirectory, envName); + Directory.CreateDirectory(dir); + Environment.SetEnvironmentVariable(envName, dir); + } + + // ensure only the test feed is used + await File.WriteAllTextAsync(Path.Join(temporaryDirectory, "NuGet.Config"), $""" + + + + + + + + """ + ); + } + } + protected static async Task RunUpdate(TestFile[] files, Func action) { // write initial files diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs index eae8cb5edd5..c1ec4aad1cc 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DirsProj.cs @@ -1,7 +1,3 @@ -using System.IO; -using System.Linq; -using System.Threading.Tasks; - using Xunit; namespace NuGetUpdater.Core.Test.Update; @@ -13,94 +9,111 @@ public class DirsProj : UpdateWorkerTestBase [Fact] public async Task UpdateSingleDependencyInDirsProj() { - await TestUpdateForDirsProj("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForDirsProj("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - + - - - + + + - - """, + + """, additionalFiles: [ ("src/test-project.csproj", """ - netstandard2.0 + net8.0 - + """) ], // expected expectedProjectContents: """ - + - - - + + + - - """, + + """, additionalFilesExpected: [ ("src/test-project.csproj", """ - netstandard2.0 + net8.0 - + """) - ]); + ] + ); } [Fact] public async Task Update_MissingFileDoesNotThrow() { - await TestUpdateForDirsProj("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForDirsProj("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], projectContents: """ - - - - - - """, + + + + + + """, expectedProjectContents: """ - - - - - - """, - additionalFiles: []); + + + + + + """, + additionalFiles: [] + ); } [Fact] public async Task UpdateSingleDependencyInNestedDirsProj() { - await TestUpdateForDirsProj("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForDirsProj("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - + - - - + + + - - """, + + """, additionalFiles: [ ("src/dirs.proj", @@ -117,25 +130,25 @@ public async Task UpdateSingleDependencyInNestedDirsProj() """ - netstandard2.0 + net8.0 - + """) ], // expected expectedProjectContents: """ - + - - - + + + - - """, + + """, additionalFilesExpected: [ ("src/dirs.proj", @@ -152,31 +165,37 @@ public async Task UpdateSingleDependencyInNestedDirsProj() """ - netstandard2.0 + net8.0 - + """) - ]); + ] + ); } [Fact] public async Task UpdateSingleDependencyInNestedDirsProjUsingWildcard() { - await TestUpdateForDirsProj("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForDirsProj("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - + - - - + + + - - """, + + """, additionalFiles: [ ("src/dirs.proj", @@ -193,25 +212,25 @@ public async Task UpdateSingleDependencyInNestedDirsProjUsingWildcard() """ - netstandard2.0 + net8.0 - + """) ], // expected expectedProjectContents: """ - + - - - + + + - - """, + + """, additionalFilesExpected: [ ("src/dirs.proj", @@ -228,31 +247,37 @@ public async Task UpdateSingleDependencyInNestedDirsProjUsingWildcard() """ - netstandard2.0 + net8.0 - + """) - ]); + ] + ); } [Fact] public async Task UpdateSingleDependencyInNestedDirsProjUsingRecursiveWildcard() { - await TestUpdateForDirsProj("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForDirsProj("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - + - - - + + + - - """, + + """, additionalFiles: [ ("src/dirs.proj", @@ -269,25 +294,25 @@ public async Task UpdateSingleDependencyInNestedDirsProjUsingRecursiveWildcard() """ - netstandard2.0 + net8.0 - + """) ], // expected expectedProjectContents: """ - + - - - + + + - - """, + + """, additionalFilesExpected: [ ("src/dirs.proj", @@ -304,15 +329,16 @@ public async Task UpdateSingleDependencyInNestedDirsProjUsingRecursiveWildcard() """ - netstandard2.0 + net8.0 - + """) - ]); + ] + ); } static async Task TestUpdateForDirsProj( @@ -323,7 +349,8 @@ public async Task UpdateSingleDependencyInNestedDirsProjUsingRecursiveWildcard() string expectedProjectContents, bool isTransitive = false, (string Path, string Content)[]? additionalFiles = null, - (string Path, string Content)[]? additionalFilesExpected = null) + (string Path, string Content)[]? additionalFilesExpected = null, + MockNuGetPackage[]? packages = null) { additionalFiles ??= []; additionalFilesExpected ??= []; @@ -334,6 +361,8 @@ public async Task UpdateSingleDependencyInNestedDirsProjUsingRecursiveWildcard() var actualResult = await RunUpdate(testFiles, async (temporaryDirectory) => { + await MockNuGetPackagesInDirectory(packages, temporaryDirectory); + var projectPath = Path.Combine(temporaryDirectory, projectFileName); var worker = new UpdaterWorker(new Logger(verbose: true)); await worker.RunAsync(temporaryDirectory, projectPath, dependencyName, oldVersion, newVersion, isTransitive); diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs index d6ec89a4510..09c4cb1aa52 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.DotNetTools.cs @@ -1,5 +1,3 @@ -using System.Threading.Tasks; - using Xunit; namespace NuGetUpdater.Core.Test.Update; @@ -11,37 +9,51 @@ public class DotNetTools : UpdateWorkerTestBase [Fact] public async Task NoChangeWhenDotNetToolsJsonNotFound() { - await TestNoChangeforProject("Microsoft.BotSay", "1.0.0", "1.1.0", + await TestNoChangeforProject("Some.DotNet.Tool", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.0.0", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.1.0", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """); + + + + + """ + ); } [Fact] public async Task NoChangeWhenDependencyNotFound() { - await TestNoChangeforProject("Microsoft.BotSay", "1.0.0", "1.1.0", + await TestNoChangeforProject("Some.DotNet.Tool", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.0.0", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.1.0", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some-Other-Tool", "2.0.0", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ (".config/dotnet-tools.json", """ @@ -49,35 +61,43 @@ public async Task NoChangeWhenDependencyNotFound() "version": 1, "isRoot": true, "tools": { - "dotnetsay": { - "version": "2.1.3", + "some-other-tool": { + "version": "2.0.0", "commands": [ - "dotnetsay" + "some-other-tool" ] } } } """) - ]); + ] + ); } [Fact] public async Task NoChangeWhenDotNetToolsJsonInUnexpectedLocation() { - await TestNoChangeforProject("Microsoft.BotSay", "1.0.0", "1.1.0", + await TestNoChangeforProject("Some.DotNet.Tool", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.0.0", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.1.0", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some-Other-Tool", "2.0.0", "net8.0"), + ], // initial projectFilePath: "src/project/project.csproj", projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ ("eng/.config/dotnet-tools.json", """ @@ -85,34 +105,41 @@ public async Task NoChangeWhenDotNetToolsJsonInUnexpectedLocation() "version": 1, "isRoot": true, "tools": { - "dotnetsay": { - "version": "2.1.3", + "some-other-tool": { + "version": "2.0.0", "commands": [ - "dotnetsay" + "some-other-tool" ] } } } """) - ]); + ] + ); } [Fact] - public async Task UpdateSingleDependencyInDirsProj() + public async Task UpdateSingleDependency() { - await TestUpdateForProject("Microsoft.BotSay", "1.0.0", "1.1.0", + await TestUpdateForProject("Some.DotNet.Tool", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.0.0", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.1.0", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ (".config/dotnet-tools.json", """ @@ -120,16 +147,16 @@ public async Task UpdateSingleDependencyInDirsProj() "version": 1, "isRoot": true, "tools": { - "microsoft.botsay": { + "some.dotnet.tool": { "version": "1.0.0", "commands": [ - "botsay" + "some.dotnet.tool" ] }, - "dotnetsay": { + "some-other-tool": { "version": "2.1.3", "commands": [ - "dotnetsay" + "some-other-tool" ] } } @@ -138,16 +165,16 @@ public async Task UpdateSingleDependencyInDirsProj() ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ (".config/dotnet-tools.json", """ @@ -155,40 +182,47 @@ public async Task UpdateSingleDependencyInDirsProj() "version": 1, "isRoot": true, "tools": { - "microsoft.botsay": { + "some.dotnet.tool": { "version": "1.1.0", "commands": [ - "botsay" + "some.dotnet.tool" ] }, - "dotnetsay": { + "some-other-tool": { "version": "2.1.3", "commands": [ - "dotnetsay" + "some-other-tool" ] } } } """) - ]); + ] + ); } [Fact] public async Task UpdateSingleDependencyWithComments() { - await TestUpdateForProject("Microsoft.BotSay", "1.0.0", "1.1.0", + await TestUpdateForProject("Some.DotNet.Tool", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.0.0", "net8.0"), + MockNuGetPackage.CreateDotNetToolPackage("Some.DotNet.Tool", "1.1.0", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ (".config/dotnet-tools.json", """ @@ -197,17 +231,17 @@ public async Task UpdateSingleDependencyWithComments() "version": 1, "isRoot": true, "tools": { - "microsoft.botsay": { + "some.dotnet.tool": { // this is a deep comment "version": "1.0.0", "commands": [ - "botsay" + "some.dotnet.tool" ] }, - "dotnetsay": { + "some-other-tool": { "version": "2.1.3", "commands": [ - "dotnetsay" + "some-other-tool" ] } } @@ -216,16 +250,16 @@ public async Task UpdateSingleDependencyWithComments() ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ (".config/dotnet-tools.json", """ @@ -234,23 +268,24 @@ public async Task UpdateSingleDependencyWithComments() "version": 1, "isRoot": true, "tools": { - "microsoft.botsay": { + "some.dotnet.tool": { // this is a deep comment "version": "1.1.0", "commands": [ - "botsay" + "some.dotnet.tool" ] }, - "dotnetsay": { + "some-other-tool": { "version": "2.1.3", "commands": [ - "dotnetsay" + "some-other-tool" ] } } } """) - ]); + ] + ); } } } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs index d5a7a8eeec3..8e00119fc6a 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.GlobalJson.cs @@ -1,5 +1,3 @@ -using System.Threading.Tasks; - using Xunit; namespace NuGetUpdater.Core.Test.Update; @@ -12,36 +10,39 @@ public class GlobalJson : UpdateWorkerTestBase public async Task NoChangeWhenGlobalJsonNotFound() { await TestNoChangeforProject("Microsoft.Build.Traversal", "3.2.0", "4.1.0", + packages: [], // initial projectContents: """ - - - netstandard2.0 - + + + netstandard2.0 + - - - - - """); + + + + + """ + ); } [Fact] public async Task NoChangeWhenDependencyNotFound() { await TestNoChangeforProject("Microsoft.Build.Traversal", "3.2.0", "4.1.0", + packages: [], // initial projectContents: """ - - - netstandard2.0 - + + + netstandard2.0 + - - - - - """, + + + + + """, additionalFiles: [ ("global.json", """ @@ -52,26 +53,28 @@ public async Task NoChangeWhenDependencyNotFound() } } """) - ]); + ] + ); } [Fact] public async Task NoChangeWhenGlobalJsonInUnexpectedLocation() { await TestNoChangeforProject("Microsoft.Build.Traversal", "3.2.0", "4.1.0", + packages: [], // initial projectFilePath: "src/project/project.csproj", projectContents: """ - - - netstandard2.0 - + + + netstandard2.0 + - - - > - - """, + + + > + + """, additionalFiles: [ ("eng/global.json", """ @@ -85,26 +88,33 @@ public async Task NoChangeWhenGlobalJsonInUnexpectedLocation() } } """) - ]); + ] + ); } [Fact] public async Task UpdateSingleDependency() { - await TestUpdateForProject("Microsoft.Build.Traversal", "3.2.0", "4.1.0", + await TestUpdateForProject("Some.MSBuild.Sdk", "3.2.0", "4.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"), + MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "3.2.0"), + MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "4.1.0"), + ], // initial projectFilePath: "src/project/project.csproj", projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ ("src/global.json", """ @@ -114,23 +124,23 @@ public async Task UpdateSingleDependency() "rollForward": "latestPatch" }, "msbuild-sdks": { - "Microsoft.Build.Traversal": "3.2.0" + "Some.MSBuild.Sdk": "3.2.0" } } """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ ("src/global.json", """ @@ -140,29 +150,36 @@ public async Task UpdateSingleDependency() "rollForward": "latestPatch" }, "msbuild-sdks": { - "Microsoft.Build.Traversal": "4.1.0" + "Some.MSBuild.Sdk": "4.1.0" } } """) - ]); + ] + ); } [Fact] public async Task UpdateDependencyWithComments() { - await TestUpdateForProject("Microsoft.Build.Traversal", "3.2.0", "4.1.0", + await TestUpdateForProject("Some.MSBuild.Sdk", "3.2.0", "4.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.3", "net8.0"), + MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "3.2.0"), + MockNuGetPackage.CreateMSBuildSdkPackage("Some.MSBuild.Sdk", "4.1.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ ("global.json", """ @@ -174,23 +191,23 @@ public async Task UpdateDependencyWithComments() }, "msbuild-sdks": { // this is a deep comment - "Microsoft.Build.Traversal": "3.2.0" + "Some.MSBuild.Sdk": "3.2.0" } } """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ ("global.json", """ @@ -202,11 +219,12 @@ public async Task UpdateDependencyWithComments() }, "msbuild-sdks": { // this is a deep comment - "Microsoft.Build.Traversal": "4.1.0" + "Some.MSBuild.Sdk": "4.1.0" } } """) - ]); + ] + ); } } } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs index dc2a83d5742..eaed72bc52c 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs @@ -1,5 +1,3 @@ -using System.Threading.Tasks; - using Xunit; namespace NuGetUpdater.Core.Test.Update; @@ -11,74 +9,79 @@ public class Mixed : UpdateWorkerTestBase [Fact] public async Task ForPackagesProject_UpdatePackageReference_InBuildProps() { - // update Newtonsoft.Json from 7.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + // update Some.Package from 7.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], // existing projectContents: """ - - - - v4.7.2 - - - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.7.2 + + + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + """, additionalFiles: [ ("packages.config", """ - + """), ("Directory.Build.props", """ - + """) ], // expected expectedProjectContents: """ - - - - v4.7.2 - - - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.7.2 + + + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + """, additionalFilesExpected: [ ("packages.config", """ - + """), ("Directory.Build.props", """ - + """) diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs index edab6cb58c8..8c363b15853 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs @@ -9,120 +9,140 @@ public class PackagesConfig : UpdateWorkerTestBase [Fact] public async Task UpdateSingleDependencyInPackagesConfig() { - // update Newtonsoft.Json from 7.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + // update Some.Package from 7.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], // existing projectContents: """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, // expected expectedProjectContents: """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + """, expectedPackagesConfigContents: """ - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdateSingleDependencyInPackagesConfig_ReferenceHasNoAssemblyVersion() { - // update Newtonsoft.Json from 7.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + // update Some.Package from 7.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], // existing projectContents: """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, // expected expectedProjectContents: """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + """, expectedPackagesConfigContents: """ - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdateSingleDependencyInPackagesConfig_SpecifiedDependencyHasNoPackagesPath() { - // update jQuery from 1.6.4 to 3.7.1 - await TestUpdateForProject("jQuery", "1.6.4", "3.7.1", + // update Package.With.No.Assembly from 1.0.0 + await TestUpdateForProject("Package.With.No.Assembly", "1.0.0", "1.1.0", + packages: + [ + // this package has no `lib` directory, but it's still valid because it has a `content` directory + new MockNuGetPackage("Package.With.No.Assembly", "1.0.0", Files: [("content/some-content.txt", [])]), + new MockNuGetPackage("Package.With.No.Assembly", "1.1.0", Files: [("content/some-content.txt", [])]), + // this is a regular package that's not being updated + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net46"), + ], // existing projectContents: """ @@ -134,8 +154,8 @@ public async Task UpdateSingleDependencyInPackagesConfig_SpecifiedDependencyHasN - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + packages\Some.Package.1.0.0\lib\net46\Some.Package.dll True @@ -144,8 +164,8 @@ public async Task UpdateSingleDependencyInPackagesConfig_SpecifiedDependencyHasN """, packagesConfigContents: """ - - + + """, // expected @@ -159,8 +179,8 @@ public async Task UpdateSingleDependencyInPackagesConfig_SpecifiedDependencyHasN - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + packages\Some.Package.1.0.0\lib\net46\Some.Package.dll True @@ -170,8 +190,8 @@ public async Task UpdateSingleDependencyInPackagesConfig_SpecifiedDependencyHasN expectedPackagesConfigContents: """ - - + + """ ); @@ -180,8 +200,14 @@ public async Task UpdateSingleDependencyInPackagesConfig_SpecifiedDependencyHasN [Fact] public async Task UpdateSingleDependencyInPackagesConfig_NoPackagesPathCanBeFound() { - // update jQuery from 3.7.0 to 3.7.1 - await TestUpdateForProject("jQuery", "3.7.0", "3.7.1", + // update Package.With.No.Assembly from 1.0.0 to 1.0.0 + await TestUpdateForProject("Package.With.No.Assembly", "1.0.0", "1.1.0", + packages: + [ + // this package has no `lib` directory, but it's still valid because it has a `content` directory + new MockNuGetPackage("Package.With.No.Assembly", "1.0.0", Files: [("content/some-content.txt", [])]), + new MockNuGetPackage("Package.With.No.Assembly", "1.1.0", Files: [("content/some-content.txt", [])]), + ], // existing projectContents: """ @@ -197,7 +223,7 @@ public async Task UpdateSingleDependencyInPackagesConfig_NoPackagesPathCanBeFoun """, packagesConfigContents: """ - + """, // expected @@ -216,219 +242,299 @@ public async Task UpdateSingleDependencyInPackagesConfig_NoPackagesPathCanBeFoun expectedPackagesConfigContents: """ - + - """); + """ + ); } [Fact] - public async Task UpdateSingleDependencyInPackagesConfigButNotToLatest() + public async Task UpdateDependency_NoAssembliesAndContentDirectoryDiffersByCase() { - // update Newtonsoft.Json from 7.0.1 to 9.0.1, purposefully not updating all the way to the newest - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "9.0.1", + // update Package.With.No.Assembly from 1.0.0 to 1.0.0 + await TestUpdateForProject("Package.With.No.Assembly", "1.0.0", "1.1.0", + packages: + [ + // this package is expected to have a directory named `content`, but here it differs by case as `Content` + new MockNuGetPackage("Package.With.No.Assembly", "1.0.0", Files: [("Content/some-content.txt", [])]), + new MockNuGetPackage("Package.With.No.Assembly", "1.1.0", Files: [("Content/some-content.txt", [])]), + ], // existing projectContents: """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, // expected expectedProjectContents: """ - - - - v4.5 - - - - - - - packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + """, expectedPackagesConfigContents: """ - - - - - """); + + + + + """ + ); } [Fact] - public async Task UpdateSpecifiedVersionInPackagesConfigButNotOthers() + public async Task UpdateSingleDependencyInPackagesConfigButNotToLatest() { - // update Newtonsoft.Json from 7.0.1 to 13.0.1, but leave HtmlAgilityPack alone - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + // update Some.Package from 7.0.1 to 9.0.1, purposefully not updating all the way to the newest + await TestUpdateForProject("Some.Package", "7.0.1", "9.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], // existing projectContents: """ - - - - v4.5 - - - - - - - packages\HtmlAgilityPack.1.11.0\lib\net45\HtmlAgilityPack.dll - True - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + """, packagesConfigContents: """ - - - - - """, + + + + """, // expected expectedProjectContents: """ - - - - v4.5 - - - - - - - packages\HtmlAgilityPack.1.11.0\lib\net45\HtmlAgilityPack.dll - True - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + packages\Some.Package.9.0.1\lib\net45\Some.Package.dll + True + + + + + """, expectedPackagesConfigContents: """ - - - - - - """); + + + + + """ + ); + } + + [Fact] + public async Task UpdateSpecifiedVersionInPackagesConfigButNotOthers() + { + // update Some.Package from 7.0.1 to 13.0.1, but leave Some.Unrelated.Package alone + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + // this package is upgraded + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + // this package is not upgraded + MockNuGetPackage.CreateSimplePackage("Some.Unrelated.Package", "1.0.0", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Unrelated.Package", "1.1.0", "net45"), + ], + // existing + projectContents: """ + + + + v4.5 + + + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + packages\Some.Unrelated.Package.1.0.0\lib\net45\Some.Unrelated.Package.dll + True + + + + + """, + packagesConfigContents: """ + + + + + """, + // expected + expectedProjectContents: """ + + + + v4.5 + + + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + packages\Some.Unrelated.Package.1.0.0\lib\net45\Some.Unrelated.Package.dll + True + + + + + """, + expectedPackagesConfigContents: """ + + + + + + """ + ); } [Fact] public async Task UpdatePackagesConfigWithNonStandardLocationOfPackagesDirectory() { - // update Newtonsoft.Json from 7.0.1 to 13.0.1 with the actual assembly in a non-standard location - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + // update Some.Package from 7.0.1 to 13.0.1 with the actual assembly in a non-standard location + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], // existing projectContents: """ - - - - v4.5 - - - - - - - some-non-standard-location\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + some-non-standard-location\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, // expected expectedProjectContents: """ - - - - v4.5 - - - - - - - some-non-standard-location\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + some-non-standard-location\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + """, expectedPackagesConfigContents: """ - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdateBindingRedirectInAppConfig() { - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "7.0.1", "net45", "7.0.0.0"), + MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "13.0.1", "net45", "13.0.0.0"), + ], projectContents: """ - - - - v4.5 - - - - - - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, additionalFiles: [ ("app.config", """ @@ -436,7 +542,7 @@ public async Task UpdateBindingRedirectInAppConfig() - + @@ -445,32 +551,32 @@ public async Task UpdateBindingRedirectInAppConfig() """) ], expectedProjectContents: """ - - - - v4.5 - - - - - - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - """, + + + + v4.5 + + + + + + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + """, expectedPackagesConfigContents: """ - - - - - """, + + + + + """, additionalFilesExpected: [ ("app.config", """ @@ -478,104 +584,110 @@ public async Task UpdateBindingRedirectInAppConfig() - + """) - ]); + ] + ); } [Fact] public async Task UpdateBindingRedirectInWebConfig() { - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "7.0.1", "net45", "7.0.0.0"), + MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "13.0.1", "net45", "13.0.0.0"), + ], projectContents: """ - - - Debug - AnyCPU - - - 2.0 - ac83fc79-b637-445b-acb0-9be238ad077f - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TestProject - TestProject - v4.5 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - web.config - - - web.config - - - - - - - - - - """, + + + Debug + AnyCPU + + + 2.0 + ac83fc79-b637-445b-acb0-9be238ad077f + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TestProject + TestProject + v4.5 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + + + + + + + + + + + + + + + + + + web.config + + + web.config + + + + + + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, additionalFiles: [ ("web.config", """ @@ -583,7 +695,7 @@ public async Task UpdateBindingRedirectInWebConfig() - + @@ -592,90 +704,90 @@ public async Task UpdateBindingRedirectInWebConfig() """) ], expectedProjectContents: """ - - - Debug - AnyCPU - - - 2.0 - ac83fc79-b637-445b-acb0-9be238ad077f - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TestProject - TestProject - v4.5 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - web.config - - - web.config - - - - - - - - - - """, + + + Debug + AnyCPU + + + 2.0 + ac83fc79-b637-445b-acb0-9be238ad077f + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TestProject + TestProject + v4.5 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + + + + + + + + + + + + + + + + + + web.config + + + web.config + + + + + + + + + + """, expectedPackagesConfigContents: """ - - - - - """, + + + + + """, additionalFilesExpected: [ ("web.config", """ @@ -683,104 +795,110 @@ public async Task UpdateBindingRedirectInWebConfig() - + """) - ]); + ] + ); } [Fact] public async Task AddsBindingRedirectInWebConfig() { - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "7.0.1", "net45", "7.0.0.0"), + MockNuGetPackage.CreatePackageWithAssembly("Some.Package", "13.0.1", "net45", "13.0.0.0"), + ], projectContents: """ - - - Debug - AnyCPU - - - 2.0 - ac83fc79-b637-445b-acb0-9be238ad077f - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TestProject - TestProject - v4.5 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - web.config - - - web.config - - - - - - - - - - """, + + + Debug + AnyCPU + + + 2.0 + ac83fc79-b637-445b-acb0-9be238ad077f + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TestProject + TestProject + v4.5 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + + + + + + + + + + + + + + + + + + web.config + + + web.config + + + + + + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, additionalFiles: [ ("web.config", """ @@ -791,90 +909,90 @@ public async Task AddsBindingRedirectInWebConfig() """) ], expectedProjectContents: """ - - - Debug - AnyCPU - - - 2.0 - ac83fc79-b637-445b-acb0-9be238ad077f - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TestProject - TestProject - v4.5 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - web.config - - - web.config - - - - - - - - - - """, + + + Debug + AnyCPU + + + 2.0 + ac83fc79-b637-445b-acb0-9be238ad077f + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TestProject + TestProject + v4.5 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + + + + + + + + + + + + + + + + + + web.config + + + web.config + + + + + + + + + + """, expectedPackagesConfigContents: """ - - - - - """, + + + + + """, additionalFilesExpected: [ ("web.config", """ @@ -882,345 +1000,358 @@ public async Task AddsBindingRedirectInWebConfig() - + """) - ]); + ] + ); } [Fact] public async Task PackagesConfigUpdateCanHappenEvenWithMismatchedVersionNumbers() { // `packages.config` reports `7.0.1` and that's what we want to update, but the project file has a mismatch that's corrected - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], projectContents: """ - - - Debug - AnyCPU - - - 2.0 - ac83fc79-b637-445b-acb0-9be238ad077f - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TestProject - TestProject - v4.5 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - """, + + + Debug + AnyCPU + + + 2.0 + ac83fc79-b637-445b-acb0-9be238ad077f + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TestProject + TestProject + v4.5 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + packages\Some.Package.6.0.8\lib\net45\Some.Package.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, expectedProjectContents: """ - - - Debug - AnyCPU - - - 2.0 - ac83fc79-b637-445b-acb0-9be238ad077f - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TestProject - TestProject - v4.5 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - - - """, + + + Debug + AnyCPU + + + 2.0 + ac83fc79-b637-445b-acb0-9be238ad077f + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TestProject + TestProject + v4.5 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + + + """, expectedPackagesConfigContents: """ - - - - - """); + + + + + """ + ); } [Fact] public async Task PackagesConfigUpdateIsNotThwartedBy_VSToolsPath_PropertyBeingSetInUserCode() { - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net45"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net45"), + ], projectContents: """ - - - Debug - AnyCPU - - - 2.0 - 68ed3303-52a0-47b8-a687-3abbb07530da - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TestProject - TestProject - v4.5 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - C:\some\path\that\does\not\exist - - - - - - """, + + + Debug + AnyCPU + + + 2.0 + 68ed3303-52a0-47b8-a687-3abbb07530da + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TestProject + TestProject + v4.5 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + packages\Some.Package.7.0.1\lib\net45\Some.Package.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + C:\some\path\that\does\not\exist + + + + + + """, packagesConfigContents: """ - - - - """, + + + + """, expectedProjectContents: """ - - - Debug - AnyCPU - - - 2.0 - 68ed3303-52a0-47b8-a687-3abbb07530da - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - TestProject - TestProject - v4.5 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - True - - - - - - - - - - - - - - - - - - - - - - - - - - C:\some\path\that\does\not\exist - - - - - - """, + + + Debug + AnyCPU + + + 2.0 + 68ed3303-52a0-47b8-a687-3abbb07530da + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + TestProject + TestProject + v4.5 + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + packages\Some.Package.13.0.1\lib\net45\Some.Package.dll + True + + + + + + + + + + + + + + + + + + + + + + + + + + C:\some\path\that\does\not\exist + + + + + + """, expectedPackagesConfigContents: """ - - - - - """); + + + + + """ + ); } [Fact] @@ -1298,7 +1429,8 @@ public async Task PackageCanBeUpdatedWhenAnotherInstalledPackageHasBeenDelisted( string expectedProjectContents, string expectedPackagesConfigContents, (string Path, string Content)[]? additionalFiles = null, - (string Path, string Content)[]? additionalFilesExpected = null) + (string Path, string Content)[]? additionalFilesExpected = null, + MockNuGetPackage[]? packages = null) { var realizedAdditionalFiles = new List<(string Path, string Content)> { @@ -1325,7 +1457,8 @@ public async Task PackageCanBeUpdatedWhenAnotherInstalledPackageHasBeenDelisted( projectContents, expectedProjectContents, additionalFiles: realizedAdditionalFiles.ToArray(), - additionalFilesExpected: realizedAdditionalFilesExpected.ToArray()); + additionalFilesExpected: realizedAdditionalFilesExpected.ToArray(), + packages: packages); } } } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs index 11323bb2c9f..e7b2bf5036e 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Sdk.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Text; using Xunit; @@ -10,160 +11,180 @@ public class Sdk : UpdateWorkerTestBase { [Theory] [InlineData("net472")] - [InlineData("netstandard2.0")] - [InlineData("net5.0")] - [InlineData("net6.0")] [InlineData("net7.0")] [InlineData("net8.0")] public async Task UpdateVersionAttribute_InProjectFile_ForPackageReferenceInclude(string tfm) { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", tfm), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", tfm), + ], // initial projectContents: $""" - - - {tfm} - + + + {tfm} + - - - - - """, + + + + + """, // expected expectedProjectContents: $""" - - - {tfm} - + + + {tfm} + - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdateVersionChildElement_InProjectFile_ForPackageReferenceInclude() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: $""" - - - netstandard2.0 - - - - 9.0.1 - - - - """, + + + net8.0 + + + + 9.0.1 + + + + """, // expected expectedProjectContents: $""" - - - netstandard2.0 - - - - 13.0.1 - - - - """); + + + net8.0 + + + + 13.0.1 + + + + """ + ); } [Fact] public async Task UpdateVersions_InProjectFile_ForDuplicatePackageReferenceInclude() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: $""" - - - netstandard2.0 - - - - - 9.0.1 - - - - """, + + + net8.0 + + + + + 9.0.1 + + + + """, // expected expectedProjectContents: $""" - - - netstandard2.0 - - - - - 13.0.1 - - - - """); + + + net8.0 + + + + + 13.0.1 + + + + """ + ); } [Fact] public async Task PartialUpdate_InMultipleProjectFiles_ForVersionConstraint() { - // update Newtonsoft.Json from 12.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "12.0.1", "13.0.1", + // update Some.Package from 12.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "12.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: $""" - - - netstandard2.0 - - - - - - - """, + + + net8.0 + + + + + + + """, additionalFiles: [ (Path: "src/Project/Project.csproj", Content: """ - netstandard2.0 + net8.0 - + """), ], // expected expectedProjectContents: $""" - - - netstandard2.0 - - - - - - - """, + + + net8.0 + + + + + + + """, additionalFilesExpected: [ (Path: "src/Project/Project.csproj", Content: """ - netstandard2.0 + net8.0 - + """), @@ -173,57 +194,82 @@ public async Task PartialUpdate_InMultipleProjectFiles_ForVersionConstraint() [Fact] public async Task UpdateVersionAttribute_InProjectFile_ForPackageReferenceInclude_Windows() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + // necessary for the `net8.0-windows10.0.19041.0` TFM + new("Microsoft.Windows.SDK.NET.Ref", "10.0.19041.31", Files: + [ + ("data/FrameworkList.xml", Encoding.UTF8.GetBytes(""" + + + + """)), + ("data/RuntimeList.xml", Encoding.UTF8.GetBytes(""" + + + + """)), + ]), + ], // initial projectContents: $""" - - - net8.0-windows10.0.19041.0 - win-x64 - + + + net8.0-windows10.0.19041.0 + win-x64 + - - - - - """, + + + + + """, // expected expectedProjectContents: $""" - - - net8.0-windows10.0.19041.0 - win-x64 - + + + net8.0-windows10.0.19041.0 + win-x64 + - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdateVersionAttribute_InMultipleProjectFiles_ForPackageReferenceInclude() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: $""" - - - net8.0 - + + + net8.0 + - - - + + + - - - - - """, + + + + + """, additionalFiles: [ ("lib/Library.csproj", $""" @@ -233,27 +279,27 @@ public async Task UpdateVersionAttribute_InMultipleProjectFiles_ForPackageRefere - + """) ], // expected expectedProjectContents: $""" - - - net8.0 - + + + net8.0 + - - - + + + - - - - - """, + + + + + """, additionalFilesExpected: [ ("lib/Library.csproj", $""" @@ -263,7 +309,7 @@ public async Task UpdateVersionAttribute_InMultipleProjectFiles_ForPackageRefere - + """) @@ -271,94 +317,120 @@ public async Task UpdateVersionAttribute_InMultipleProjectFiles_ForPackageRefere } [Theory] - [InlineData("$(NewtonsoftJsonVersion")] - [InlineData("$NewtonsoftJsonVersion)")] - [InlineData("$NewtonsoftJsonVersion")] - [InlineData("NewtonsoftJsonVersion)")] + [InlineData("$(SomePackageVersion")] + [InlineData("$SomePackageVersion)")] + [InlineData("$SomePackageVersion")] + [InlineData("SomePackageVersion)")] public async Task Update_InvalidFile_DoesNotThrow(string versionString) { - await TestNoChangeforProject("Newtonsoft.Json", "9.0.1", "13.0.1", - $""" - "> - - netstandard2.0 - 9.0.1 - - - - - - """); + await TestNoChangeforProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], + projectContents: $""" + "> + + net8.0 + 9.0.1 + + + + + + """ + ); } [Fact] public async Task UpdateFindsNearestNugetConfig_AndSucceeds() { - // Clean the cache to ensure we don't find a cached version of packages. - await ProcessEx.RunAsync("dotnet", "nuget locals -c all"); - // If the Top-Level NugetConfig was found we would have failed. - var privateNugetContent = """ + // + // this test needs a very specific setup to run, so we have to do it manually + // + using TemporaryDirectory tempDirectory = new(); + + // the top-level NuGet.Config has a package feed that doesn't exist + await File.WriteAllTextAsync(Path.Combine(tempDirectory.DirectoryPath, "NuGet.Config"), """ - - + - """; - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", - projectFile: (Path: "Directory/Project.csproj", Content: """ - - - netstandard2.0 - - - - - - """), """ + ); + + // now place the "real" test files under `src/` + string srcDirectory = Path.Combine(tempDirectory.DirectoryPath, "src"); + Directory.CreateDirectory(srcDirectory); + + // the project file + string projectPath = Path.Combine(srcDirectory, "project.csproj"); + await File.WriteAllTextAsync(projectPath, """ - netstandard2.0 + net8.0 - + - """, - additionalFiles: + """ + ); + // another NuGet.Config, but with a usable package feed + string packageFeedLocation = Path.Combine(tempDirectory.DirectoryPath, "test-package-feed"); + Directory.CreateDirectory(packageFeedLocation); + await File.WriteAllTextAsync(Path.Combine(srcDirectory, "NuGet.Config"), $""" + + + + + + + + """ + ); + // populate some packages + foreach (MockNuGetPackage package in MockNuGetPackage.CommonPackages.Concat( [ - (Path: "NuGet.config", Content: $""" - - - - - - - - """), - (Path: "Directory/NuGet.config", Content: privateNugetContent) - ]); + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.1.0", "net8.0") + ])) + { + package.WriteToDirectory(packageFeedLocation); + } + + // + // do the update + // + UpdaterWorker worker = new(new(verbose: true)); + await worker.RunAsync(tempDirectory.DirectoryPath, projectPath, "Some.Package", "1.0.0", "1.1.0", isTransitive: false); + + // + // verify the update occurred + // + string actualProjectContents = await File.ReadAllTextAsync(projectPath); + Assert.Contains("Version=\"1.1.0\"", actualProjectContents); } [Fact] public async Task UpdateReturnsEmptyArray_WhenBuildFails() { - // Clean the cache to ensure we don't find a cached version of packages. - await ProcessEx.RunAsync("dotnet", $"nuget locals -c all"); - await TestNoChangeforProject("Newtonsoft.Json", "9.0.1", "13.0.1", - """ - - - netstandard2.0 - - - - - - """, + await TestNoChangeforProject("Some.Package", "9.0.1", "13.0.1", + packages: [], // nothing specified, update will fail + projectContents: """ + + + netstandard2.0 + + + + + + """, additionalFiles: [ (Path: "NuGet.config", Content: """ @@ -373,196 +445,233 @@ public async Task UpdateReturnsEmptyArray_WhenBuildFails() """) - ]); + ] + ); } [Fact] public async Task UpdateExactMatchVersionAttribute_InProjectFile_ForPackageReferenceInclude() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - net6.0 - + + + net8.0 + - - - - - """, + + + + + """, // expected expectedProjectContents: """ - - - net6.0 - + + + net8.0 + - - - - - """); + + + + + """ + ); } [Fact] public async Task AddPackageReference_InProjectFile_ForTransientDependency() { - // add transient System.Text.Json from 5.0.1 to 5.0.2 - await TestUpdateForProject("System.Text.Json", "5.0.1", "5.0.2", isTransitive: true, + // add transient package Some.Transient.Dependency from 5.0.1 to 5.0.2 + await TestUpdateForProject("Some.Transient.Dependency", "5.0.1", "5.0.2", isTransitive: true, + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "3.1.3", "net8.0", [(null, [("Some.Transient.Dependency", "5.0.1")])]), + MockNuGetPackage.CreateSimplePackage("Some.Transient.Dependency", "5.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Transient.Dependency", "5.0.2", "net8.0"), + ], // initial projectContents: """ - + - - netcoreapp3.1 - + + net8.0 + - - - + + + - - """, + + """, // expected expectedProjectContents: """ - + - - netcoreapp3.1 - + + net8.0 + - - - - + + + + - - """); + + """ + ); } [Fact] public async Task UpdateVersionAttribute_InProjectFile_ForAnalyzerPackageReferenceInclude() { - // update Microsoft.CodeAnalysis.Analyzers from 3.3.0 to 3.3.4 - await TestUpdateForProject("Microsoft.CodeAnalysis.Analyzers", "3.3.0", "3.3.4", + // update Some.Analyzer from 3.3.0 to 3.3.4 + await TestUpdateForProject("Some.Analyzer", "3.3.0", "3.3.4", + packages: + [ + MockNuGetPackage.CreateAnalyzerPackage("Some.Analyzer", "3.3.0"), + MockNuGetPackage.CreateAnalyzerPackage("Some.Analyzer", "3.3.4"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - """, + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - """); + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + """ + ); } [Fact] public async Task UpdateVersionAttribute_InProjectFile_ForMultiplePackageReferences() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - - """, + + + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - - """); + + + + + + """ + ); } [Fact] public async Task UpdateVersionAttribute_InProjectFile_ForPackageReferenceUpdate() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - - """, + + + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - - """); + + + + + + """ + ); } [Fact] public async Task UpdateVersionAttribute_InDirectoryPackages_ForPackageVersion() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ ("Directory.Packages.props", """ @@ -572,23 +681,23 @@ public async Task UpdateVersionAttribute_InDirectoryPackages_ForPackageVersion() - + """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ @@ -598,30 +707,36 @@ public async Task UpdateVersionAttribute_InDirectoryPackages_ForPackageVersion() - + """) - ]); + ] + ); } [Fact] public async Task UpdateExactMatchVersionAttribute_InDirectoryPackages_ForPackageVersion() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ ("Directory.Packages.props", """ @@ -631,23 +746,23 @@ public async Task UpdateExactMatchVersionAttribute_InDirectoryPackages_ForPackag - + """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ @@ -657,405 +772,465 @@ public async Task UpdateExactMatchVersionAttribute_InDirectoryPackages_ForPackag - + """) - ]); + ] + ); } [Fact] public async Task UpdatePropertyValue_InProjectFile_ForPackageReferenceIncludeWithExactVersion() { - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - 9.0.1 - + + + net8.0 + 9.0.1 + - - - - - """, + + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - 13.0.1 - + + + net8.0 + 13.0.1 + - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdateDifferentCasedPropertyValue_InProjectFile_ForPackageReferenceInclude() { - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - 9.0.1 - + + + net8.0 + 9.0.1 + - - - - - """, + + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - 13.0.1 - + + + net8.0 + 13.0.1 + - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdatePropertyValue_InProjectFile_ForPackageReferenceInclude() { - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - 9.0.1 - + + + net8.0 + 9.0.1 + - - - - - """, + + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - 13.0.1 - + + + net8.0 + 13.0.1 + - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdateExactMatchPropertyValue_InProjectFile_ForPackageReferenceInclude() { - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - [9.0.1] - + + + net8.0 + [9.0.1] + - - - - - """, + + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - [13.0.1] - + + + net8.0 + [13.0.1] + - - - - - """); + + + + + """ + ); } [Fact] public async Task UpdateVersionAttributeAndPropertyValue_InProjectFile_ForMultiplePackageReferences() { - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - 9.0.1 - + + + net8.0 + 9.0.1 + - - - - - - """, + + + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - 13.0.1 - + + + net8.0 + 13.0.1 + - - - - - - """); + + + + + + """ + ); } [Fact] public async Task UpdatePropertyValue_InProjectFile_ForPackageReferenceUpdate() { - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - 9.0.1 - + + + net8.0 + 9.0.1 + - - - - - - """, + + + + + + """, // expected expectedProjectContents: """ - - - netstandard2.0 - 13.0.1 - + + + net8.0 + 13.0.1 + - - - - - - """); + + + + + + """ + ); } [Fact] public async Task UpdatePropertyValue_InDirectoryProps_ForPackageVersion() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ ("Directory.Packages.props", """ true - 9.0.1 + 9.0.1 - + """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ true - 13.0.1 + 13.0.1 - + """) - ]); + ] + ); } [Fact] public async Task UpdateExactMatchPropertyValue_InDirectoryProps_ForPackageVersion() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ ("Directory.Packages.props", """ true - [9.0.1] + [9.0.1] - + """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ true - [13.0.1] + [13.0.1] - + """) - ]); + ] + ); } [Fact] public async Task UpdateVersionOverrideAttributeAndPropertyValue_InProjectFileAndDirectoryProps_ForPackageVersion() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ ("Directory.Packages.props", """ true - 9.0.1 + 9.0.1 - + """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ true - 13.0.1 + 13.0.1 - + """) - ]); + ] + ); } [Fact] public async Task UpdateVersionAttribute_InDirectoryProps_ForGlobalPackageReference() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - - - """, + + + net8.0 + + + """, additionalFiles: [ ("Directory.Packages.props", """ @@ -1065,19 +1240,19 @@ public async Task UpdateVersionAttribute_InDirectoryProps_ForGlobalPackageRefere - + """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - - - """, + + + net8.0 + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ @@ -1087,191 +1262,215 @@ public async Task UpdateVersionAttribute_InDirectoryProps_ForGlobalPackageRefere - + """) - ]); + ] + ); } [Fact] public async Task UpdatePropertyValue_InDirectoryProps_ForGlobalPackageReference() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - - - """, + + + net8.0 + + + """, additionalFiles: [ ("Directory.Packages.props", """ true - 9.0.1 + 9.0.1 - + """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - - - """, + + + net8.0 + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ true - 13.0.1 + 13.0.1 - + """) - ]); + ] + ); } [Fact] public async Task UpdatePropertyValue_InDirectoryProps_ForPackageReferenceInclude() { - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial project projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ // initial props file ("Directory.Build.props", """ - 9.0.1 + 9.0.1 """) ], // expected project expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ // expected props file ("Directory.Build.props", """ - 13.0.1 + 13.0.1 """) - ]); + ] + ); } [Fact] public async Task UpdatePropertyValue_InProps_ForPackageReferenceInclude() { - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial project projectContents: """ - - + + - - netstandard2.0 - + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ // initial props file ("my-properties.props", """ - 9.0.1 + 9.0.1 """) ], // expected project expectedProjectContents: """ - - + + - - netstandard2.0 - + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ // expected props file ("my-properties.props", """ - 13.0.1 + 13.0.1 """) - ]); + ] + ); } [Fact] public async Task UpdatePropertyValue_InProps_ForPackageVersion() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ // initial props files @@ -1283,30 +1482,30 @@ public async Task UpdatePropertyValue_InProps_ForPackageVersion() - + """), ("Version.props", """ - 9.0.1 + 9.0.1 """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ // expected props files @@ -1318,37 +1517,43 @@ public async Task UpdatePropertyValue_InProps_ForPackageVersion() - + """), ("Version.props", """ - 13.0.1 + 13.0.1 """) - ]); + ] + ); } [Fact] public async Task UpdatePropertyValue_InProps_ThenSubstituted_ForPackageVersion() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ // initial props files @@ -1357,11 +1562,11 @@ public async Task UpdatePropertyValue_InProps_ThenSubstituted_ForPackageVersion( true - $(NewtonsoftJsonVersion) + $(NewtonsoftJsonVersion) - + """), @@ -1375,16 +1580,16 @@ public async Task UpdatePropertyValue_InProps_ThenSubstituted_ForPackageVersion( ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ // expected props files @@ -1393,11 +1598,11 @@ public async Task UpdatePropertyValue_InProps_ThenSubstituted_ForPackageVersion( true - $(NewtonsoftJsonVersion) + $(NewtonsoftJsonVersion) - + """), @@ -1408,26 +1613,32 @@ public async Task UpdatePropertyValue_InProps_ThenSubstituted_ForPackageVersion( """) - ]); + ] + ); } [Fact] public async Task UpdatePropertyValues_InProps_ThenRedefinedAndSubstituted_ForPackageVersion() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], // initial projectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFiles: [ // initial props files @@ -1436,35 +1647,35 @@ public async Task UpdatePropertyValues_InProps_ThenRedefinedAndSubstituted_ForPa true - $(NewtonsoftJsonVersion) + $(SomePackageVersion) - + """), ("Version.props", """ - 9.0.1 - 9.0.1 + 9.0.1 + 9.0.1 """) ], // expected expectedProjectContents: """ - - - netstandard2.0 - + + + net8.0 + - - - - - """, + + + + + """, additionalFilesExpected: [ // expected props files @@ -1473,182 +1684,220 @@ public async Task UpdatePropertyValues_InProps_ThenRedefinedAndSubstituted_ForPa true - $(NewtonsoftJsonVersion) + $(SomePackageVersion) - + """), ("Version.props", """ - 13.0.1 - 13.0.1 + 13.0.1 + 13.0.1 """) - ]); + ] + ); } [Fact] public async Task UpdatePeerDependencyWithInlineVersion() { - await TestUpdateForProject("Microsoft.Extensions.Http", "2.2.0", "7.0.0", + await TestUpdateForProject("Some.Package", "2.2.0", "7.0.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "2.2.0", "net8.0", [(null, [("Peer.Package", "2.2.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.0", "net8.0", [(null, [("Peer.Package", "7.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Peer.Package", "2.2.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Peer.Package", "7.0.0", "net8.0"), + ], projectContents: """ - - - netstandard2.0 - - - - - - - """, + + + net8.0 + + + + + + + """, expectedProjectContents: """ - - - netstandard2.0 - - - - - - - """); + + + net8.0 + + + + + + + """ + ); } [Fact] public async Task UpdatePeerDependencyFromPropertyInSameFile() { - await TestUpdateForProject("Microsoft.Extensions.Http", "2.2.0", "7.0.0", + await TestUpdateForProject("Some.Package", "2.2.0", "7.0.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "2.2.0", "net8.0", [(null, [("Peer.Package", "2.2.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.0", "net8.0", [(null, [("Peer.Package", "7.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Peer.Package", "2.2.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Peer.Package", "7.0.0", "net8.0"), + ], projectContents: """ - - - netstandard2.0 - 2.2.0 - 2.2.0 - - - - - - - """, + + + net8.0 + 2.2.0 + 2.2.0 + + + + + + + """, expectedProjectContents: """ - - - netstandard2.0 - 7.0.0 - 7.0.0 - - - - - - - """); + + + net8.0 + 7.0.0 + 7.0.0 + + + + + + + """ + ); } [Fact] public async Task UpdatePeerDependencyFromPropertyInDifferentFile() { - await TestUpdateForProject("Microsoft.Extensions.Http", "2.2.0", "7.0.0", + await TestUpdateForProject("Some.Package", "2.2.0", "7.0.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "2.2.0", "net8.0", [(null, [("Peer.Package", "2.2.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.0", "net8.0", [(null, [("Peer.Package", "7.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Peer.Package", "2.2.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Peer.Package", "7.0.0", "net8.0"), + ], projectContents: """ - - - - netstandard2.0 - - - - - - - """, + + + + net8.0 + + + + + + + """, additionalFiles: [ ("Versions.props", """ - 2.2.0 - 2.2.0 + 2.2.0 + 2.2.0 """) ], expectedProjectContents: """ - - - - netstandard2.0 - - - - - - - """, + + + + net8.0 + + + + + + + """, additionalFilesExpected: [ ("Versions.props", """ - 7.0.0 - 7.0.0 + 7.0.0 + 7.0.0 """) - ]); + ] + ); } [Fact] public async Task UpdatePeerDependencyWithInlineVersionAndMultipleTfms() { - await TestUpdateForProject("Microsoft.Extensions.Http", "2.2.0", "7.0.0", + await TestUpdateForProject("Some.Package", "2.2.0", "7.0.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "2.2.0", "net7.0", [(null, [("Peer.Package", "2.2.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.0", "net7.0", [(null, [("Peer.Package", "7.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Peer.Package", "2.2.0", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Peer.Package", "7.0.0", "net7.0"), + ], projectContents: """ - - - netstandard2.0;netstandard2.1 - - - - - - - """, + + + net7.0;net8.0 + + + + + + + """, expectedProjectContents: """ - - - netstandard2.0;netstandard2.1 - - - - - - - """); + + + net7.0;net8.0 + + + + + + + """ + ); } [Fact] public async Task NoUpdateForPeerDependenciesWhichAreHigherVersion() { - await TestUpdateForProject("Microsoft.Identity.Web", "2.13.0", "2.13.2", + await TestUpdateForProject("Some.Package", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0", [(null, [("Transitive.Dependency", "1.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.1.0", "net8.0", [(null, [("Transitive.Dependency", "1.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Transitive.Dependency", "1.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Transitive.Dependency", "1.1.0", "net8.0"), // we shouldn't update to this + ], projectContents: """ - - - netstandard2.0 - - - - - - - - - """, + + + net8.0 + + + + + + + """, additionalFiles: [ ("Directory.Packages.props", """ @@ -1658,27 +1907,23 @@ public async Task NoUpdateForPeerDependenciesWhichAreHigherVersion() true - - - - + + """) ], expectedProjectContents: """ - - - netstandard2.0 - - - - - - - - - """, + + + net8.0 + + + + + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ @@ -1688,149 +1933,155 @@ public async Task NoUpdateForPeerDependenciesWhichAreHigherVersion() true - - - - + + """) - ]); + ] + ); } [Fact] public async Task UpdatingToNotCompatiblePackageDoesNothing() { - await TestUpdateForProject("Microsoft.AspNetCore.Authentication.JwtBearer", "3.1.18", "7.0.5", + // can't upgrade to the newer package because of a TFM mismatch + await TestNoChangeforProject("Some.Package", "7.0.0", "8.0.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.0", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "8.0.0", "net8.0"), + ], projectContents: """ - - - netcoreapp3.1 - - - - - - """, - expectedProjectContents: """ - - - netcoreapp3.1 - - - - - - """); + + + net7.0 + + + + + + """ + ); } [Fact] public async Task UpdatingToNotCompatiblePackageDoesNothingWithSingleOfMultileTfmNotSupported() { - // the requested package upgrade is supported on net7.0, but not netcoreapp3.1, so we skip the whole thing - await TestUpdateForProject("Microsoft.AspNetCore.Authentication.JwtBearer", "3.1.18", "7.0.5", + // can't upgrade to the newer package because one of the TFMs doesn't match + await TestNoChangeforProject("Some.Package", "7.0.0", "8.0.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.0", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "8.0.0", "net8.0"), + ], projectContents: """ - - - netcoreapp3.1;net7.0 - - - - - - """, - expectedProjectContents: """ - - - netcoreapp3.1;net7.0 - - - - - - """); + + + net7.0;net8.0 + + + + + + """ + ); } [Fact] public async Task UpdateVersionAttribute_InProjectFile_WhereTargetFrameworksIsSelfReferential() { - // update Newtonsoft.Json from 9.0.1 to 13.0.1 - await TestUpdateForProject("Newtonsoft.Json", "9.0.1", "13.0.1", + // update Some.Package from 9.0.1 to 13.0.1 + await TestUpdateForProject("Some.Package", "9.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "9.0.1", "netstandard2.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "netstandard2.0"), + ], projectContents: """ - - - $(TargetFrameworks);net472 - $(TargetFrameworks);netstandard2.0 - - - - - - """, + + + $(TargetFrameworks);net472 + $(TargetFrameworks);net8.0 + + + + + + """, expectedProjectContents: """ - - - $(TargetFrameworks);net472 - $(TargetFrameworks);netstandard2.0 - - - - - - """); + + + $(TargetFrameworks);net472 + $(TargetFrameworks);net8.0 + + + + + + """ + ); } [Fact] public async Task UpdateOfNonExistantPackageDoesNothingEvenIfTransitiveDependencyIsPresent() { - // package Microsoft.Extensions.Http isn't present, but one of its transitive dependencies is - await TestUpdateForProject("Microsoft.Extensions.Http", "2.2.0", "7.0.0", + // package Some.Package isn't in the project, but one of its transitive dependencies is + await TestNoChangeforProject("Some.Package", "2.2.0", "7.0.0", + packages: + [ + // these packages exist in the feed, but aren't used + MockNuGetPackage.CreateSimplePackage("Some.Package", "2.2.0", "net8.0", [(null, [("Transitive.Dependency", "2.2.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.0", "net8.0", [(null, [("Transitive.Dependency", "7.0.0")])]), + // one of these is used, but we can't update to it + MockNuGetPackage.CreateSimplePackage("Transitive.Dependency", "2.2.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Transitive.Dependency", "7.0.0", "net8.0"), + ], projectContents: """ - - - netstandard2.0 - - - - - - """, - expectedProjectContents: """ - - - netstandard2.0 - - - - - - """); + + + net8.0 + + + + + + """ + ); } [Fact] public async Task AvoidPackageDowngradeWhenUpdatingDependency() { - await TestUpdateForProject("Microsoft.VisualStudio.Sdk.TestFramework.Xunit", "17.2.7", "17.6.16", + // updating from 1.0.0 to 1.1.0 of Some.Package should not cause a downgrade warning of Some.Dependency; it + // should be pulled along, even when the TFM is pulled from a different file. unrelated packages are ignored + await TestUpdateForProject("Some.Package", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0", [(null, [("Some.Dependency", "1.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.1.0", "net8.0", [(null, [("Some.Dependency", "1.1.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Dependency", "1.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Dependency", "1.1.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Unrelated.Package", "1.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Unrelated.Package", "1.1.0", "net8.0"), + ], projectContents: """ - + - - $(PreferredTargetFramework) - false - - + + $(PreferredTargetFramework) + false + + - - - - - - - - + + + + + - - """, + + """, additionalFiles: [ ("Directory.Packages.props", """ @@ -1840,45 +2091,37 @@ public async Task AvoidPackageDowngradeWhenUpdatingDependency() true - - - - - - - - + + + """), ("Directory.Build.props", """ - net7.0 + net8.0 """) ], expectedProjectContents: """ - + - - $(PreferredTargetFramework) - false - - + + $(PreferredTargetFramework) + false + + - - - - - - - - + + + + + - - """, + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ @@ -1888,45 +2131,47 @@ public async Task AvoidPackageDowngradeWhenUpdatingDependency() true - - - - - - - - + + + """), ("Directory.Build.props", """ - net7.0 + net8.0 """) - ]); + ] + ); } [Fact] public async Task AddTransitiveDependencyByAddingPackageReferenceAndVersion() { - await TestUpdateForProject("System.Text.Json", "5.0.0", "5.0.2", isTransitive: true, + await TestUpdateForProject("Some.Transitive.Dependency", "5.0.0", "5.0.2", isTransitive: true, + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "3.1.3", "net8.0", [(null, [("Some.Transitive.Dependency", "5.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "5.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "5.0.2", "net8.0"), + ], // initial projectContents: """ - + - - net5.0 - + + net8.0 + - - - + + + - - """, + + """, additionalFiles: [ // initial props files @@ -1936,26 +2181,26 @@ public async Task AddTransitiveDependencyByAddingPackageReferenceAndVersion() true - + """) ], // expected expectedProjectContents: """ - + - - net5.0 - + + net8.0 + - - - - + + + + - - """, + + """, additionalFilesExpected: [ // expected props files @@ -1965,33 +2210,40 @@ public async Task AddTransitiveDependencyByAddingPackageReferenceAndVersion() true - - + + """) - ]); + ] + ); } [Fact] public async Task PinTransitiveDependencyByAddingPackageVersion() { - await TestUpdateForProject("System.Text.Json", "5.0.0", "5.0.2", isTransitive: true, + await TestUpdateForProject("Some.Transitive.Dependency", "5.0.0", "5.0.2", isTransitive: true, + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "3.1.3", "net8.0", [(null, [("Some.Transitive.Dependency", "5.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "5.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "5.0.2", "net8.0"), + ], // initial projectContents: """ - + - - $(NoWarn);NETSDK1138 - net5.0 - + + $(NoWarn);NETSDK1138 + net8.0 + - - - + + + - - """, + + """, additionalFiles: [ // initial props files @@ -2002,26 +2254,26 @@ public async Task PinTransitiveDependencyByAddingPackageVersion() true - + """) ], // expected expectedProjectContents: """ - + - - $(NoWarn);NETSDK1138 - net5.0 - + + $(NoWarn);NETSDK1138 + net8.0 + - - - + + + - - """, + + """, additionalFilesExpected: [ // expected props files @@ -2032,28 +2284,34 @@ public async Task PinTransitiveDependencyByAddingPackageVersion() true - - + + """) - ]); + ] + ); } [Fact] public async Task PropsFileNameWithDifferentCasing() { - await TestUpdateForProject("Newtonsoft.Json", "12.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "12.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net7.0"), + ], projectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, additionalFiles: [ ("Directory.Build.props", """ @@ -2065,22 +2323,22 @@ public async Task PropsFileNameWithDifferentCasing() ("Versions.Props", """ - 12.0.1 + 12.0.1 """) ], // no change expectedProjectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, additionalFilesExpected: [ // no change @@ -2093,7 +2351,7 @@ public async Task PropsFileNameWithDifferentCasing() ("Versions.Props", """ - 13.0.1 + 13.0.1 """) @@ -2105,27 +2363,32 @@ public async Task PropsFileNameWithDifferentCasing() public async Task VersionAttributeWithDifferentCasing_VersionNumberInline() { // the version attribute in the project has an all lowercase name - await TestUpdateForProject("Newtonsoft.Json", "12.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "12.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net7.0"), + ], projectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, expectedProjectContents: """ - - - net7.0 - - - - - - """ + + + net7.0 + + + + + + """ ); } @@ -2133,17 +2396,22 @@ public async Task VersionAttributeWithDifferentCasing_VersionNumberInline() public async Task VersionAttributeWithDifferentCasing_VersionNumberInProperty() { // the version attribute in the project has an all lowercase name - await TestUpdateForProject("Newtonsoft.Json", "12.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "12.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net7.0"), + ], projectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, additionalFiles: [ ("Directory.Build.props", """ @@ -2154,22 +2422,22 @@ public async Task VersionAttributeWithDifferentCasing_VersionNumberInProperty() ("Versions.props", """ - 12.0.1 + 12.0.1 """) ], // no change expectedProjectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, additionalFilesExpected: [ // no change @@ -2182,7 +2450,7 @@ public async Task VersionAttributeWithDifferentCasing_VersionNumberInProperty() ("Versions.props", """ - 13.0.1 + 13.0.1 """) @@ -2193,18 +2461,24 @@ public async Task VersionAttributeWithDifferentCasing_VersionNumberInProperty() [Fact] public async Task DirectoryPackagesPropsDoesCentralPackagePinningGetsUpdatedIfTransitiveFlagIsSet() { - await TestUpdateForProject("xunit.assert", "2.5.2", "2.5.3", + await TestUpdateForProject("Some.Package.Extensions", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package.Extensions", "1.0.0", "net7.0", [(null, [("Some.Package", "1.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package.Extensions", "1.1.0", "net7.0", [(null, [("Some.Package", "1.0.0")])]), + ], isTransitive: true, projectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, additionalFiles: [ ("Directory.Packages.props", """ @@ -2214,22 +2488,22 @@ public async Task DirectoryPackagesPropsDoesCentralPackagePinningGetsUpdatedIfTr true - - + + """) ], expectedProjectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ @@ -2239,8 +2513,8 @@ public async Task DirectoryPackagesPropsDoesCentralPackagePinningGetsUpdatedIfTr true - - + + """) @@ -2251,18 +2525,24 @@ public async Task DirectoryPackagesPropsDoesCentralPackagePinningGetsUpdatedIfTr [Fact] public async Task DirectoryPackagesPropsDoesNotGetDuplicateEntryIfCentralTransitivePinningIsUsed() { - await TestUpdateForProject("xunit.assert", "2.5.2", "2.5.3", + await TestUpdateForProject("Some.Package.Extensions", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package.Extensions", "1.0.0", "net7.0", [(null, [("Some.Package", "1.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package.Extensions", "1.1.0", "net7.0", [(null, [("Some.Package", "1.0.0")])]), + ], isTransitive: true, projectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, additionalFiles: [ ("Directory.Packages.props", """ @@ -2272,22 +2552,22 @@ public async Task DirectoryPackagesPropsDoesNotGetDuplicateEntryIfCentralTransit true - - + + """) ], expectedProjectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, additionalFilesExpected: [ ("Directory.Packages.props", """ @@ -2297,8 +2577,8 @@ public async Task DirectoryPackagesPropsDoesNotGetDuplicateEntryIfCentralTransit true - - + + """) @@ -2309,170 +2589,189 @@ public async Task DirectoryPackagesPropsDoesNotGetDuplicateEntryIfCentralTransit [Fact] public async Task PackageWithFourPartVersionCanBeUpdated() { - await TestUpdateForProject("AWSSDK.Core", "3.7.204.13", "3.7.204.14", + await TestUpdateForProject("Some.Package", "1.2.3.4", "1.2.3.5", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.3.4", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.3.5", "net7.0"), + ], projectContents: """ - - - net7.0 - - - - - - """, + + + net7.0 + + + + + + """, expectedProjectContents: """ - - - net7.0 - - - - - - """ + + + net7.0 + + + + + + """ ); } [Fact] public async Task PackageWithOnlyBuildTargetsCanBeUpdated() { - await TestUpdateForProject("Microsoft.Windows.Compatibility", "7.0.0", "8.0.0", + await TestUpdateForProject("Some.Package", "7.0.0", "7.1.0", + packages: + [ + new("Some.Package", "7.0.0", Files: [("buildTransitive/net7.0/_._", [])]), + new("Some.Package", "7.1.0", Files: [("buildTransitive/net7.0/_._", [])]), + ], projectContents: """ - - - net5.0 - - - - - - """, + + + net8.0 + + + + + + """, expectedProjectContents: """ - - - net5.0 - - - - - - """ + + + net8.0 + + + + + + """ ); } [Fact] public async Task UpdatePackageVersionFromPropertiesWithAndWithoutConditions() { - await TestUpdateForProject("Newtonsoft.Json", "12.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "12.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], projectContents: """ - - - netstandard2.0 - 7.0.1 - 12.0.1 - 9.0.1 - - - - - - """, + + + net8.0 + 7.0.1 + 12.0.1 + 9.0.1 + + + + + + """, expectedProjectContents: """ - - - netstandard2.0 - 7.0.1 - 13.0.1 - 9.0.1 - - - - - - """ + + + net8.0 + 7.0.1 + 13.0.1 + 9.0.1 + + + + + + """ ); } [Fact] public async Task UpdatePackageVersionFromPropertyWithConditionCheckingForEmptyString() { - await TestUpdateForProject("Newtonsoft.Json", "12.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "12.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], projectContents: """ - - - netstandard2.0 - 12.0.1 - 9.0.1 - - - - - - """, + + + net8.0 + 12.0.1 + 9.0.1 + + + + + + """, expectedProjectContents: """ - - - netstandard2.0 - 13.0.1 - 9.0.1 - - - - - - """ + + + net8.0 + 13.0.1 + 9.0.1 + + + + + + """ ); } [Fact] public async Task NoChange_IfThereAreIncoherentVersions() { - // Make sure we don't update if there are incoherent versions - await TestNoChangeforProject("Microsoft.EntityFrameworkCore.SqlServer", "2.1.0", "2.2.0", + // trying to update `Transitive.Dependency` to 1.1.0 would normally pull `Some.Package` from 1.0.0 to 1.1.0, + // but the TFM doesn't allow it + await TestNoChangeforProject("Transitive.Dependency", "1.0.0", "1.1.0", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net7.0", [(null, [("Transitive.Dependency", "[1.0.0]")])]), + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.1.0", "net8.0", [(null, [("Transitive.Dependency", "[1.1.0]")])]), + MockNuGetPackage.CreateSimplePackage("Transitive.Dependency", "1.0.0", "net7.0"), + MockNuGetPackage.CreateSimplePackage("Transitive.Dependency", "1.1.0", "net7.0"), + ], projectContents: """ - - - netcoreapp2.1 - - - - - - - - - - - - - - - - - - - - - - """); + + + net7.0 + + + + + + + """ + ); } [Fact] public async Task NoChange_IfTargetFrameworkCouldNotBeEvaluated() { // Make sure we don't throw if the project's TFM is an unresolvable property - await TestNoChangeforProject("Newtonsoft.Json", "7.0.1", "13.0.1", + await TestNoChangeforProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], projectContents: """ $(PropertyThatCannotBeResolved) - + """ - ); + ); } [Fact] @@ -2480,7 +2779,12 @@ public async Task ProcessingProjectWithAspireDoesNotFailEvenThoughWorkloadIsNotI { // enumerating the build files will fail if the Aspire workload is not installed; this test ensures we can // still process the update - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + ], projectContents: """ @@ -2488,7 +2792,7 @@ public async Task ProcessingProjectWithAspireDoesNotFailEvenThoughWorkloadIsNotI true - + """, @@ -2499,7 +2803,7 @@ public async Task ProcessingProjectWithAspireDoesNotFailEvenThoughWorkloadIsNotI true - + """ @@ -2509,16 +2813,22 @@ public async Task ProcessingProjectWithAspireDoesNotFailEvenThoughWorkloadIsNotI [Fact] public async Task UnresolvablePropertyDoesNotStopOtherUpdates() { - // the property `$(MauiVersion)` cannot be resolved - await TestUpdateForProject("Newtonsoft.Json", "7.0.1", "13.0.1", + // the property `$(SomeUnresolvableProperty)` cannot be resolved + await TestUpdateForProject("Some.Package", "7.0.1", "13.0.1", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "7.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "13.0.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Other.Package", "1.0.0", "net8.0"), + ], projectContents: """ net8.0 - - + + """, @@ -2528,8 +2838,8 @@ public async Task UnresolvablePropertyDoesNotStopOtherUpdates() net8.0 - - + + """ @@ -2539,31 +2849,40 @@ public async Task UnresolvablePropertyDoesNotStopOtherUpdates() [Fact] public async Task UpdatingPackageAlsoUpdatesAnythingWithADependencyOnTheUpdatedPackage() { - // updating SpecFlow from 3.3.30 requires that SpecFlow.Tools.MsBuild.Generation also be updated - await TestUpdateForProject("SpecFlow", "3.3.30", "3.4.3", + // updating Some.Package from 3.3.30 requires that Some.Package.Extensions also be updated + await TestUpdateForProject("Some.Package", "3.3.30", "3.4.3", + packages: + [ + MockNuGetPackage.CreateSimplePackage("Some.Package", "3.3.30", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "3.4.0", "net8.0"), // this will be ignored + MockNuGetPackage.CreateSimplePackage("Some.Package", "3.4.3", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package.Extensions", "3.3.30", "net8.0", [(null, [("Some.Package", "[3.3.30]")])]), // the dependency version is very strict with [] + MockNuGetPackage.CreateSimplePackage("Some.Package.Extensions", "3.4.0", "net8.0", [(null, [("Some.Package", "[3.4.0]")])]), // this will be ignored + MockNuGetPackage.CreateSimplePackage("Some.Package.Extensions", "3.4.3", "net8.0", [(null, [("Some.Package", "[3.4.3]")])]), + ], projectContents: """ - netstandard2.0 + net8.0 - - + + """, expectedProjectContents: """ - netstandard2.0 + net8.0 - - + + """ - ); + ); } } } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs index 1d4378f8c14..74c79c1c013 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs @@ -1,5 +1,9 @@ using System.Collections.Immutable; +using NuGet.Build.Tasks; + +using NuGetUpdater.Core.Test.Update; + using Xunit; namespace NuGetUpdater.Core.Test.Utilities; @@ -15,10 +19,10 @@ public void GetRootedValue_FindsValue() var projectContents = """ - netstandard2.0 + net8.0 - + """; @@ -36,10 +40,10 @@ public void GetRootedValue_FindsValue() Assert.Equal(""" - netstandard2.0 + net8.0 - + """, evaluatedValue); @@ -52,10 +56,10 @@ public async Task GetRootedValue_DoesNotRecurseAsync() var projectContents = """ - netstandard2.0 + net8.0 - + """; @@ -125,10 +129,13 @@ public async Task TfmsCanBeDeterminedFromProjectContents(string projectContents, [Theory] [MemberData(nameof(GetTopLevelPackageDependencyInfosTestData))] - public async Task TopLevelPackageDependenciesCanBeDetermined(TestFile[] buildFileContents, Dependency[] expectedTopLevelDependencies) + public async Task TopLevelPackageDependenciesCanBeDetermined(TestFile[] buildFileContents, Dependency[] expectedTopLevelDependencies, MockNuGetPackage[] testPackages) { using var testDirectory = new TemporaryDirectory(); var buildFiles = new List(); + + await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(testPackages, testDirectory.DirectoryPath); + foreach (var (path, content) in buildFileContents) { var fullPath = Path.Combine(testDirectory.DirectoryPath, path); @@ -144,30 +151,29 @@ public async Task TopLevelPackageDependenciesCanBeDetermined(TestFile[] buildFil public async Task AllPackageDependenciesCanBeTraversed() { using var temp = new TemporaryDirectory(); - var expectedDependencies = new Dependency[] - { - new("Microsoft.Bcl.AsyncInterfaces", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.DependencyInjection", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.DependencyInjection.Abstractions", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Http", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.Extensions.Logging", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Logging.Abstractions", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Options", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Primitives", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Buffers", "4.5.1", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.ComponentModel.Annotations", "5.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Diagnostics.DiagnosticSource", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Memory", "4.5.5", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Numerics.Vectors", "4.4.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.CompilerServices.Unsafe", "6.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Threading.Tasks.Extensions", "4.5.4", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), + MockNuGetPackage[] testPackages = + [ + MockNuGetPackage.CreateSimplePackage("Package.A", "1.0.0", "netstandard2.0", [(null, [("Package.B", "2.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.B", "2.0.0", "netstandard2.0", [(null, [("Package.C", "3.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.C", "3.0.0", "netstandard2.0", [(null, [("Package.D", "4.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.D", "4.0.0", "netstandard2.0"), + ]; + await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(testPackages, temp.DirectoryPath); + + Dependency[] expectedDependencies = + [ new("NETStandard.Library", "2.0.3", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - }; - var actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync( + new("Package.A", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), + new("Package.B", "2.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), + new("Package.C", "3.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), + new("Package.D", "4.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), + ]; + Dependency[] actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync( temp.DirectoryPath, temp.DirectoryPath, "netstandard2.0", - [new Dependency("Microsoft.Extensions.Http", "7.0.0", DependencyType.Unknown)]); + [new Dependency("Package.A", "1.0.0", DependencyType.Unknown)] + ); AssertEx.Equal(expectedDependencies, actualDependencies); } @@ -175,101 +181,126 @@ public async Task AllPackageDependenciesCanBeTraversed() public async Task AllPackageDependencies_DoNotTruncateLongDependencyLists() { using var temp = new TemporaryDirectory(); - var expectedDependencies = new Dependency[] - { - new("Castle.Core", "4.4.1", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.ApplicationInsights", "2.10.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.ApplicationInsights.Agent.Intercept", "2.4.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.ApplicationInsights.DependencyCollector", "2.10.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.ApplicationInsights.PerfCounterCollector", "2.10.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.ApplicationInsights.WindowsServer", "2.10.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel", "2.10.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.AspNet.TelemetryCorrelation", "1.0.5", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Bcl.AsyncInterfaces", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Caching.Abstractions", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Caching.Memory", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.DependencyInjection", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.DependencyInjection.Abstractions", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.DiagnosticAdapter", "1.1.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Http", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.Extensions.Logging", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Logging.Abstractions", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Options", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.PlatformAbstractions", "1.1.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Primitives", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Moq", "4.16.1", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("MSTest.TestFramework", "2.1.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Newtonsoft.Json", "12.0.1", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("System", "4.1.311.2", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("System.Buffers", "4.5.1", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Collections.Concurrent", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Collections.Immutable", "1.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Collections.NonGeneric", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Collections.Specialized", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.ComponentModel", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.ComponentModel.Annotations", "5.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.ComponentModel.Primitives", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.ComponentModel.TypeConverter", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Core", "3.5.21022.801", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("System.Data.Common", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Diagnostics.DiagnosticSource", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Diagnostics.PerformanceCounter", "4.5.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Diagnostics.StackTrace", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Dynamic.Runtime", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.IO.FileSystem.Primitives", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Linq", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Linq.Expressions", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Memory", "4.5.5", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Net.WebHeaderCollection", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Numerics.Vectors", "4.4.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.ObjectModel", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Private.DataContractSerialization", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Reflection.Emit", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Reflection.Emit.ILGeneration", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Reflection.Emit.Lightweight", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Reflection.Metadata", "1.4.1", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Reflection.TypeExtensions", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.CompilerServices.Unsafe", "6.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.InteropServices.RuntimeInformation", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.Numerics", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.Serialization.Json", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.Serialization.Primitives", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Security.Claims", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Security.Cryptography.OpenSsl", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Security.Cryptography.Primitives", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Security.Principal", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Text.RegularExpressions", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Threading", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Threading.Tasks.Extensions", "4.5.4", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Threading.Thread", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Threading.ThreadPool", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Xml.ReaderWriter", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Xml.XDocument", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Xml.XmlDocument", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Xml.XmlSerializer", "4.3.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.ApplicationInsights.Web", "2.10.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("MSTest.TestAdapter", "2.1.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("NETStandard.Library", "2.0.3", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - }; + MockNuGetPackage[] testPackages = + [ + MockNuGetPackage.CreateSimplePackage("Package.1A", "1.0.0", "net8.0", [(null, [("Package.1B", "2.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1B", "2.0.0", "net8.0", [(null, [("Package.1C", "3.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1C", "3.0.0", "net8.0", [(null, [("Package.1D", "4.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1D", "4.0.0", "net8.0", [(null, [("Package.1E", "5.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1E", "5.0.0", "net8.0", [(null, [("Package.1F", "6.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1F", "6.0.0", "net8.0", [(null, [("Package.1G", "7.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1G", "7.0.0", "net8.0", [(null, [("Package.1H", "8.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1H", "8.0.0", "net8.0", [(null, [("Package.1I", "9.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1I", "9.0.0", "net8.0", [(null, [("Package.1J", "10.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1J", "10.0.0", "net8.0", [(null, [("Package.1K", "11.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1K", "11.0.0", "net8.0", [(null, [("Package.1L", "12.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1L", "12.0.0", "net8.0", [(null, [("Package.1M", "13.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1M", "13.0.0", "net8.0", [(null, [("Package.1N", "14.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1N", "14.0.0", "net8.0", [(null, [("Package.1O", "15.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1O", "15.0.0", "net8.0", [(null, [("Package.1P", "16.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1P", "16.0.0", "net8.0", [(null, [("Package.1Q", "17.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1Q", "17.0.0", "net8.0", [(null, [("Package.1R", "18.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1R", "18.0.0", "net8.0", [(null, [("Package.1S", "19.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1S", "19.0.0", "net8.0", [(null, [("Package.1T", "20.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1T", "20.0.0", "net8.0", [(null, [("Package.1U", "21.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1U", "21.0.0", "net8.0", [(null, [("Package.1V", "22.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1V", "22.0.0", "net8.0", [(null, [("Package.1W", "23.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1W", "23.0.0", "net8.0", [(null, [("Package.1X", "24.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1X", "24.0.0", "net8.0", [(null, [("Package.1Y", "25.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1Y", "25.0.0", "net8.0", [(null, [("Package.1Z", "26.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.1Z", "26.0.0", "net8.0", [(null, [("Package.2A", "1.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2A", "1.0.0", "net8.0", [(null, [("Package.2B", "2.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2B", "2.0.0", "net8.0", [(null, [("Package.2C", "3.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2C", "3.0.0", "net8.0", [(null, [("Package.2D", "4.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2D", "4.0.0", "net8.0", [(null, [("Package.2E", "5.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2E", "5.0.0", "net8.0", [(null, [("Package.2F", "6.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2F", "6.0.0", "net8.0", [(null, [("Package.2G", "7.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2G", "7.0.0", "net8.0", [(null, [("Package.2H", "8.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2H", "8.0.0", "net8.0", [(null, [("Package.2I", "9.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2I", "9.0.0", "net8.0", [(null, [("Package.2J", "10.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2J", "10.0.0", "net8.0", [(null, [("Package.2K", "11.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2K", "11.0.0", "net8.0", [(null, [("Package.2L", "12.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2L", "12.0.0", "net8.0", [(null, [("Package.2M", "13.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2M", "13.0.0", "net8.0", [(null, [("Package.2N", "14.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2N", "14.0.0", "net8.0", [(null, [("Package.2O", "15.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2O", "15.0.0", "net8.0", [(null, [("Package.2P", "16.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2P", "16.0.0", "net8.0", [(null, [("Package.2Q", "17.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2Q", "17.0.0", "net8.0", [(null, [("Package.2R", "18.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2R", "18.0.0", "net8.0", [(null, [("Package.2S", "19.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2S", "19.0.0", "net8.0", [(null, [("Package.2T", "20.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2T", "20.0.0", "net8.0", [(null, [("Package.2U", "21.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2U", "21.0.0", "net8.0", [(null, [("Package.2V", "22.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2V", "22.0.0", "net8.0", [(null, [("Package.2W", "23.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2W", "23.0.0", "net8.0", [(null, [("Package.2X", "24.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2X", "24.0.0", "net8.0", [(null, [("Package.2Y", "25.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2Y", "25.0.0", "net8.0", [(null, [("Package.2Z", "26.0.0")])]), + MockNuGetPackage.CreateSimplePackage("Package.2Z", "26.0.0", "net8.0"), + ]; + await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(testPackages, temp.DirectoryPath); + + Dependency[] expectedDependencies = + [ + new("Package.1A", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + new("Package.1B", "2.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1C", "3.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1D", "4.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1E", "5.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1F", "6.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1G", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1H", "8.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1I", "9.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1J", "10.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1K", "11.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1L", "12.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1M", "13.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1N", "14.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1O", "15.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1P", "16.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1Q", "17.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1R", "18.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + new("Package.1S", "19.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1T", "20.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1U", "21.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1V", "22.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1W", "23.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1X", "24.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1Y", "25.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.1Z", "26.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2A", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + new("Package.2B", "2.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2C", "3.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2D", "4.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2E", "5.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2F", "6.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2G", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2H", "8.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2I", "9.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2J", "10.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2K", "11.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2L", "12.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2M", "13.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2N", "14.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2O", "15.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2P", "16.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2Q", "17.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2R", "18.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + new("Package.2S", "19.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2T", "20.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2U", "21.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2V", "22.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2W", "23.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2X", "24.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2Y", "25.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + new("Package.2Z", "26.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + ]; var packages = new[] { - new Dependency("System", "4.1.311.2", DependencyType.Unknown), - new Dependency("System.Core", "3.5.21022.801", DependencyType.Unknown), - new Dependency("Moq", "4.16.1", DependencyType.Unknown), - new Dependency("Castle.Core", "4.4.1", DependencyType.Unknown), - new Dependency("MSTest.TestAdapter", "2.1.0", DependencyType.Unknown), - new Dependency("MSTest.TestFramework", "2.1.0", DependencyType.Unknown), - new Dependency("Microsoft.ApplicationInsights", "2.10.0", DependencyType.Unknown), - new Dependency("Microsoft.ApplicationInsights.Agent.Intercept", "2.4.0", DependencyType.Unknown), - new Dependency("Microsoft.ApplicationInsights.DependencyCollector", "2.10.0", DependencyType.Unknown), - new Dependency("Microsoft.ApplicationInsights.PerfCounterCollector", "2.10.0", DependencyType.Unknown), - new Dependency("Microsoft.ApplicationInsights.Web", "2.10.0", DependencyType.Unknown), - new Dependency("Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel", "2.10.0", DependencyType.Unknown), - new Dependency("Microsoft.ApplicationInsights.WindowsServer", "2.10.0", DependencyType.Unknown), - new Dependency("Microsoft.Extensions.Http", "7.0.0", DependencyType.Unknown), - new Dependency("Newtonsoft.Json", "12.0.1", DependencyType.Unknown) + new Dependency("Package.1A", "1.0.0", DependencyType.Unknown), + new Dependency("Package.1R", "18.0.0", DependencyType.Unknown), + new Dependency("Package.2A", "1.0.0", DependencyType.Unknown), + new Dependency("Package.2R", "18.0.0", DependencyType.Unknown), }; - var actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(temp.DirectoryPath, temp.DirectoryPath, "netstandard2.0", packages); + var actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(temp.DirectoryPath, temp.DirectoryPath, "net8.0", packages); for (int i = 0; i < actualDependencies.Length; i++) { var ad = actualDependencies[i]; @@ -284,31 +315,26 @@ public async Task AllPackageDependencies_DoNotTruncateLongDependencyLists() public async Task AllPackageDependencies_DoNotIncludeUpdateOnlyPackages() { using var temp = new TemporaryDirectory(); - var expectedDependencies = new Dependency[] - { - new("Microsoft.Bcl.AsyncInterfaces", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.DependencyInjection", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.DependencyInjection.Abstractions", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Http", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("Microsoft.Extensions.Logging", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Logging.Abstractions", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Options", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.Extensions.Primitives", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Buffers", "4.5.1", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.ComponentModel.Annotations", "5.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Diagnostics.DiagnosticSource", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Memory", "4.5.5", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Numerics.Vectors", "4.4.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.CompilerServices.Unsafe", "6.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Threading.Tasks.Extensions", "4.5.4", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("NETStandard.Library", "2.0.3", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - }; + MockNuGetPackage[] testPackages = + [ + MockNuGetPackage.CreateSimplePackage("Package.A", "1.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Package.B", "2.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Package.C", "3.0.0", "net8.0"), + ]; + await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(testPackages, temp.DirectoryPath); + + Dependency[] expectedDependencies = + [ + new("Package.A", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + new("Package.B", "2.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + ]; var packages = new[] { - new Dependency("Microsoft.Extensions.Http", "7.0.0", DependencyType.Unknown), - new Dependency("Newtonsoft.Json", "12.0.1", DependencyType.Unknown, IsUpdate: true) + new Dependency("Package.A", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + new Dependency("Package.B", "2.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + new Dependency("Package.C", "3.0.0", DependencyType.Unknown, IsUpdate: true) }; - var actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(temp.DirectoryPath, temp.DirectoryPath, "netstandard2.0", packages); + var actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync(temp.DirectoryPath, temp.DirectoryPath, "net8.0", packages); AssertEx.Equal(expectedDependencies, actualDependencies); } @@ -344,8 +370,8 @@ public async Task GetAllPackageDependencies_NugetConfigInvalid_DoesNotThrow() var actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync( temp.DirectoryPath, temp.DirectoryPath, - "netstandard2.0", - [new Dependency("Newtonsoft.Json", "4.5.11", DependencyType.Unknown)] + "net8.0", + [new Dependency("Some.Package", "4.5.11", DependencyType.Unknown)] ); } finally @@ -356,72 +382,6 @@ public async Task GetAllPackageDependencies_NugetConfigInvalid_DoesNotThrow() } } - [Fact] - public async Task GetAllPackageDependencies_LocalNuGetRepos_AreCopiedToTempProject() - { - // If we end up using this EnvVar pattern again I think it'd be worth it to abstract it out into an IDisposable. - var nugetPackagesDirectory = Environment.GetEnvironmentVariable("NUGET_PACKAGES"); - var nugetHttpCacheDirectory = Environment.GetEnvironmentVariable("NUGET_HTTP_CACHE_PATH"); - var logger = new Logger(verbose: true); - try - { - // First create a fake local nuget repository - using var restoreDir = new TemporaryDirectory(); - - var restoreNuGetPackagesDirectory = Path.Combine(restoreDir.DirectoryPath, ".nuget", "packages"); - Environment.SetEnvironmentVariable("NUGET_PACKAGES", restoreNuGetPackagesDirectory); - var restoreNuGetHttpCacheDirectory = Path.Combine(restoreDir.DirectoryPath, ".nuget", "v3-cache"); - Environment.SetEnvironmentVariable("NUGET_HTTP_CACHE_PATH", restoreNuGetHttpCacheDirectory); - - using var temp = new TemporaryDirectory(); - using (var restoreProjectTemp = new TemporaryDirectory()) - { - // dotnet restore .csproj with things we want - await MSBuildHelper.DependenciesAreCoherentAsync(restoreProjectTemp.DirectoryPath, restoreProjectTemp.DirectoryPath, "netstandard2.0", - [new Dependency("Newtonsoft.Json", "4.5.11", DependencyType.Unknown)], logger); - Assert.True(Directory.Exists(restoreNuGetPackagesDirectory), "packages directory didn't exist"); - PathHelper.CopyDirectory(restoreNuGetPackagesDirectory, Path.Combine(temp.DirectoryPath, "local_repo")); - } - - // It is important to have empty NuGet caches for this test, so override them with temp directories. - var tempNuGetPackagesDirectory = Path.Combine(temp.DirectoryPath, ".nuget", "packages"); - Environment.SetEnvironmentVariable("NUGET_PACKAGES", tempNuGetPackagesDirectory); - var tempNuGetHttpCacheDirectory = Path.Combine(temp.DirectoryPath, ".nuget", "v3-cache"); - Environment.SetEnvironmentVariable("NUGET_HTTP_CACHE_PATH", tempNuGetHttpCacheDirectory); - - // Write the NuGet.config. - await File.WriteAllTextAsync( - Path.Combine(temp.DirectoryPath, "NuGet.Config"), """ - - - - - - - - """); - var expectedDependencies = new Dependency[] - { - new("Newtonsoft.Json", "4.5.11", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("NETStandard.Library", "2.0.3", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - }; - var actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync( - temp.DirectoryPath, - temp.DirectoryPath, - "netstandard2.0", - [new Dependency("Newtonsoft.Json", "4.5.11", DependencyType.Unknown)] - ); - Assert.False(Directory.Exists(tempNuGetHttpCacheDirectory), "The .nuget/.v3-cache directory was created, meaning http was used."); - AssertEx.Equal(expectedDependencies, actualDependencies); - } - finally - { - // Restore the NuGet caches. - Environment.SetEnvironmentVariable("NUGET_PACKAGES", nugetPackagesDirectory); - Environment.SetEnvironmentVariable("NUGET_HTTP_CACHE_PATH", nugetHttpCacheDirectory); - } - } - [Fact] public async Task AllPackageDependenciesCanBeFoundWithNuGetConfig() { @@ -438,47 +398,38 @@ public async Task AllPackageDependenciesCanBeFoundWithNuGetConfig() var tempNuGetHttpCacheDirectory = Path.Combine(temp.DirectoryPath, ".nuget", "v3-cache"); Environment.SetEnvironmentVariable("NUGET_HTTP_CACHE_PATH", tempNuGetHttpCacheDirectory); - // First validate that we are unable to find dependencies for the package version without a NuGet.config. - var dependenciesNoNuGetConfig = await MSBuildHelper.GetAllPackageDependenciesAsync( - temp.DirectoryPath, - temp.DirectoryPath, - "netstandard2.0", - [new Dependency("Microsoft.CodeAnalysis.Common", "4.8.0-3.23457.5", DependencyType.Unknown)]); - Assert.Equal([], dependenciesNoNuGetConfig); - - // Write the NuGet.config and try again. - await File.WriteAllTextAsync( - Path.Combine(temp.DirectoryPath, "NuGet.Config"), """ - + // create two local package sources with different packages available in each + string localSource1 = Path.Combine(temp.DirectoryPath, "localSource1"); + Directory.CreateDirectory(localSource1); + string localSource2 = Path.Combine(temp.DirectoryPath, "localSource2"); + Directory.CreateDirectory(localSource2); + + // `Package.A` will only live in `localSource1` and will have a dependency on `Package.B` which is only + // available in `localSource2` + MockNuGetPackage.CreateSimplePackage("Package.A", "1.0.0", "net8.0", [(null, [("Package.B", "2.0.0")])]).WriteToDirectory(localSource1); + MockNuGetPackage.CreateSimplePackage("Package.B", "2.0.0", "net8.0").WriteToDirectory(localSource2); + await File.WriteAllTextAsync(Path.Join(temp.DirectoryPath, "NuGet.Config"), """ - - - + + """); - var expectedDependencies = new Dependency[] - { - new("Microsoft.CodeAnalysis.Common", "4.8.0-3.23457.5", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"]), - new("System.Buffers", "4.5.1", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Collections.Immutable", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Memory", "4.5.5", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Numerics.Vectors", "4.4.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Reflection.Metadata", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Runtime.CompilerServices.Unsafe", "6.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Text.Encoding.CodePages", "7.0.0", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("System.Threading.Tasks.Extensions", "4.5.4", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("Microsoft.CodeAnalysis.Analyzers", "3.3.4", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - new("NETStandard.Library", "2.0.3", DependencyType.Unknown, TargetFrameworks: ["netstandard2.0"], IsTransitive: true), - }; - var actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync( + Dependency[] expectedDependencies = + [ + new("Package.A", "1.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]), + new("Package.B", "2.0.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"], IsTransitive: true), + ]; + + Dependency[] actualDependencies = await MSBuildHelper.GetAllPackageDependenciesAsync( temp.DirectoryPath, temp.DirectoryPath, - "netstandard2.0", - [new Dependency("Microsoft.CodeAnalysis.Common", "4.8.0-3.23457.5", DependencyType.Unknown)] + "net8.0", + [new Dependency("Package.A", "1.0.0", DependencyType.Unknown)] ); + AssertEx.Equal(expectedDependencies, actualDependencies); } finally @@ -492,35 +443,48 @@ public async Task AllPackageDependenciesCanBeFoundWithNuGetConfig() [Fact] public async Task DependencyConflictsCanBeResolved() { - // the package `SpecFlow` was already updated from 3.3.30 to 3.4.3, but this causes a conflict with - // `SpecFlow.Tools.MsBuild.Generation` that needs to be resolved var repoRoot = Directory.CreateTempSubdirectory($"test_{nameof(DependencyConflictsCanBeResolved)}_"); + MockNuGetPackage[] testPackages = + [ + // some base packages + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.1.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.0", "net8.0"), + // some packages that are hard-locked to specific versions of the previous package + MockNuGetPackage.CreateSimplePackage("Some.Other.Package", "1.0.0", "net8.0", [(null, [("Some.Package", "[1.0.0]")])]), + MockNuGetPackage.CreateSimplePackage("Some.Other.Package", "1.1.0", "net8.0", [(null, [("Some.Package", "[1.1.0]")])]), + MockNuGetPackage.CreateSimplePackage("Some.Other.Package", "1.2.0", "net8.0", [(null, [("Some.Package", "[1.2.0]")])]), + ]; + await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(testPackages, repoRoot.FullName); + + // the package `Some.Package` was already updated from 1.0.0 to 1.2.0, but this causes a conflict with + // `Some.Other.Package` that needs to be resolved try { var projectPath = Path.Join(repoRoot.FullName, "project.csproj"); await File.WriteAllTextAsync(projectPath, """ - netstandard2.0 + net8.0 - - + + """); var dependencies = new[] { - new Dependency("SpecFlow", "3.4.3", DependencyType.PackageReference), - new Dependency("SpecFlow.Tools.MsBuild.Generation", "3.3.30", DependencyType.PackageReference), + new Dependency("Some.Package", "1.2.0", DependencyType.PackageReference), + new Dependency("Some.Other.Package", "1.0.0", DependencyType.PackageReference), }; - var resolvedDependencies = await MSBuildHelper.ResolveDependencyConflicts(repoRoot.FullName, projectPath, "netstandard2.0", dependencies, new Logger(true)); + var resolvedDependencies = await MSBuildHelper.ResolveDependencyConflicts(repoRoot.FullName, projectPath, "net8.0", dependencies, new Logger(true)); Assert.NotNull(resolvedDependencies); Assert.Equal(2, resolvedDependencies.Length); - Assert.Equal("SpecFlow", resolvedDependencies[0].Name); - Assert.Equal("3.4.3", resolvedDependencies[0].Version); - Assert.Equal("SpecFlow.Tools.MsBuild.Generation", resolvedDependencies[1].Name); - Assert.Equal("3.4.3", resolvedDependencies[1].Version); + Assert.Equal("Some.Package", resolvedDependencies[0].Name); + Assert.Equal("1.2.0", resolvedDependencies[0].Version); + Assert.Equal("Some.Other.Package", resolvedDependencies[1].Name); + Assert.Equal("1.2.0", resolvedDependencies[1].Version); } finally { @@ -539,7 +503,7 @@ yield return ("project.csproj", """ - + """) @@ -548,10 +512,14 @@ yield return new Dependency[] { new( - "Newtonsoft.Json", + "Some.Package", "12.0.1", DependencyType.PackageReference, EvaluationResult: new(EvaluationResultType.Success, "12.0.1", "12.0.1", null, null)) + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0") } ]; @@ -564,7 +532,7 @@ yield return ("project.csproj", """ - + 12.0.1 @@ -575,10 +543,14 @@ yield return new Dependency[] { new( - "Newtonsoft.Json", + "Some.Package", "12.0.1", DependencyType.PackageReference, EvaluationResult: new(EvaluationResultType.Success, "12.0.1", "12.0.1", null, null)) + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0") } ]; @@ -591,10 +563,10 @@ yield return ("project.csproj", """ - 12.0.1 + 12.0.1 - + """) @@ -603,10 +575,14 @@ yield return new Dependency[] { new( - "Newtonsoft.Json", + "Some.Package", "12.0.1", DependencyType.PackageReference, - new(EvaluationResultType.Success, "$(NewtonsoftJsonVersion)", "12.0.1", "NewtonsoftJsonVersion", null)) + new(EvaluationResultType.Success, "$(SomePackageVersion)", "12.0.1", "SomePackageVersion", null)) + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0") } ]; @@ -620,11 +596,11 @@ yield return netstandard2.0 - 12.0.1 - 13.0.1 + 12.0.1 + 13.0.1 - + """) @@ -633,10 +609,14 @@ yield return new Dependency[] { new( - "Newtonsoft.Json", + "Some.Package", "12.0.1", DependencyType.PackageReference, - new(EvaluationResultType.Success, "$(NewtonsoftJsonVersion)", "12.0.1", "NewtonsoftJsonVersion", null)) + new(EvaluationResultType.Success, "$(SomePackageVersion)", "12.0.1", "SomePackageVersion", null)) + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0") } ]; @@ -650,11 +630,11 @@ yield return netstandard2.0 - 12.0.1 - 13.0.1 + 12.0.1 + 13.0.1 - + """) @@ -663,10 +643,14 @@ yield return new Dependency[] { new( - "Newtonsoft.Json", + "Some.Package", "12.0.1", DependencyType.PackageReference, - new(EvaluationResultType.Success, "$(NewtonsoftJsonVersion)", "12.0.1", "NewtonsoftJsonVersion", null)) + new(EvaluationResultType.Success, "$(SomePackageVersion)", "12.0.1", "SomePackageVersion", null)) + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0") } }; @@ -680,11 +664,11 @@ yield return netstandard2.0 - 12.0.1 - 13.0.1 + 12.0.1 + 13.0.1 - + """) @@ -693,10 +677,14 @@ yield return new Dependency[] { new( - "Newtonsoft.Json", + "Some.Package", "12.0.1", DependencyType.PackageReference, - new(EvaluationResultType.Success, "$(NewtonsoftJsonVersion)", "12.0.1", "NewtonsoftJsonVersion", null)) + new(EvaluationResultType.Success, "$(SomePackageVersion)", "12.0.1", "SomePackageVersion", null)) + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0") } ]; @@ -710,11 +698,11 @@ yield return netstandard2.0 - 12.0.1 - 13.0.1 + 12.0.1 + 13.0.1 - + """) @@ -723,10 +711,14 @@ yield return new Dependency[] { new( - "Newtonsoft.Json", + "Some.Package", "12.0.1", DependencyType.PackageReference, - new(EvaluationResultType.Success, "$(NewtonsoftJsonVersion)", "12.0.1", "NewtonsoftJsonVersion", null)) + new(EvaluationResultType.Success, "$(SomePackageVersion)", "12.0.1", "SomePackageVersion", null)) + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Some.Package", "12.0.1", "net8.0") } }; @@ -739,18 +731,18 @@ yield return ("Packages.props", """ - - + + """), ("project.csproj", """ - netstandard2.0 + net8.0 - + """) @@ -759,16 +751,22 @@ yield return new Dependency[] { new( - "Azure.Identity", + "Package.A", "1.6.0", DependencyType.PackageReference, EvaluationResult: new(EvaluationResultType.Success, "1.6.0", "1.6.0", null, null)), new( - "Microsoft.Data.SqlClient", + "Package.B", "5.1.4", DependencyType.PackageReference, EvaluationResult: new(EvaluationResultType.Success, "5.1.4", "5.1.4", null, null), IsUpdate: true), + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Package.A", "1.6.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Package.A", "1.6.1", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Package.B", "5.1.4", "net8.0"), } ]; @@ -781,18 +779,18 @@ yield return ("project.csproj", """ - netstandard2.0 + net8.0 - + """), ("Packages.props", """ - - + + """) @@ -801,16 +799,21 @@ yield return new Dependency[] { new( - "Azure.Identity", + "Package.A", "1.6.0", DependencyType.PackageReference, EvaluationResult: new(EvaluationResultType.Success, "1.6.0", "1.6.0", null, null)), new( - "Microsoft.Data.SqlClient", + "Package.B", "5.1.4", DependencyType.PackageReference, EvaluationResult: new(EvaluationResultType.Success, "5.1.4", "5.1.4", null, null), IsUpdate: true), + }, + new MockNuGetPackage[] + { + MockNuGetPackage.CreateSimplePackage("Package.A", "1.6.0", "net8.0"), + MockNuGetPackage.CreateSimplePackage("Package.B", "5.1.4", "net8.0"), } ]; } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs index 2c658021ac6..75039ba6f87 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs @@ -480,11 +480,15 @@ private static ProjectRootElement CreateProjectRootElement(ProjectBuildFile buil // We need to copy local package sources from the NuGet.Config file to the temp directory foreach (var localSource in packageSources.Where(p => p.IsLocal)) { - var subDir = localSource.Source.Split(nugetConfigDir)[1]; - var destPath = Path.Join(tempDir.FullName, subDir); - if (Directory.Exists(localSource.Source)) + // if the source is relative to the original location, copy it to the temp directory + if (PathHelper.IsSubdirectoryOf(nugetConfigDir!, localSource.Source)) { - PathHelper.CopyDirectory(localSource.Source, destPath); + string sourceRelativePath = Path.GetRelativePath(nugetConfigDir!, localSource.Source); + string destPath = Path.Join(tempDir.FullName, sourceRelativePath); + if (Directory.Exists(localSource.Source)) + { + PathHelper.CopyDirectory(localSource.Source, destPath); + } } } } diff --git a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs index 88380e31d02..e6ee282cfb9 100644 --- a/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +++ b/nuget/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs @@ -111,4 +111,22 @@ public static void CopyDirectory(string sourceDirectory, string destinationDirec CopyDirectory(subDir.FullName, newDestinationDir); } } + + public static bool IsSubdirectoryOf(string parentDirectory, string childDirectory) + { + var parentDirInfo = new DirectoryInfo(parentDirectory); + var childDirInfo = new DirectoryInfo(childDirectory); + + while (childDirInfo.Parent is not null) + { + if (childDirInfo.Parent.FullName == parentDirInfo.FullName) + { + return true; + } + + childDirInfo = childDirInfo.Parent; + } + + return false; + } } diff --git a/nuget/helpers/lib/NuGetUpdater/global.json b/nuget/helpers/lib/NuGetUpdater/global.json new file mode 100644 index 00000000000..82dd9d3bd10 --- /dev/null +++ b/nuget/helpers/lib/NuGetUpdater/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.202", + "rollForward": "latestMinor" + } +} \ No newline at end of file