dependabot-nuget 0.263.0 → 0.264.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +37 -0
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +3 -3
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs +1 -0
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +169 -0
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +79 -67
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.FrameworkCheck.cs +0 -4
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +10 -11
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalysisResult.cs +11 -0
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +441 -0
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/CompatabilityChecker.cs +177 -0
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +47 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyInfo.cs +12 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Extensions.cs +36 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/NuGetContext.cs +128 -0
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/Requirement.cs +105 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/RequirementConverter.cs +17 -0
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/SecurityVulnerability.cs +11 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/SecurityVulnerabilityExtensions.cs +36 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +179 -0
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionResult.cs +54 -0
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Dependency.cs +5 -2
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +2 -1
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/WorkspaceDiscoveryResult.cs +2 -2
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/CompatabilityChecker.cs +0 -2
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/FrameworkCompatibilityService.cs +0 -3
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/SupportedFrameworks.cs +0 -3
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +0 -5
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectResolver.cs +0 -4
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/SdkPackageUpdater.cs +6 -2
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/WebApplicationTargetsConditionPatcher.cs +0 -4
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/XmlFilePreAndPostProcessor.cs +0 -2
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/HashSetExtensions.cs +0 -2
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/JsonHelper.cs +0 -4
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/Logger.cs +0 -3
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +7 -8
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/PathHelper.cs +0 -4
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +0 -3
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/XmlExtensions.cs +0 -4
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTestBase.cs +90 -0
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +304 -0
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/CompatibilityCheckerTests.cs +145 -0
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/ExpectedAnalysisResult.cs +8 -0
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/RequirementTests.cs +69 -0
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/SecurityVulnerabilityExtensionsTests.cs +78 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/VersionFinderTests.cs +193 -0
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +1 -2
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.DotNetToolsJson.cs +2 -2
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.GlobalJson.cs +2 -2
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +1 -1
  51. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Proj.cs +1 -1
  52. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +102 -9
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +4 -4
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/ExpectedDiscoveryResults.cs +2 -2
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +8 -2
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +2 -1
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +8 -7
  58. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +63 -0
  59. data/lib/dependabot/nuget/analysis/dependency_analysis.rb +63 -0
  60. data/lib/dependabot/nuget/file_fetcher.rb +7 -6
  61. data/lib/dependabot/nuget/file_parser.rb +28 -21
  62. data/lib/dependabot/nuget/file_updater.rb +22 -25
  63. data/lib/dependabot/nuget/metadata_finder.rb +2 -160
  64. data/lib/dependabot/nuget/native_discovery/native_dependency_details.rb +102 -0
  65. data/lib/dependabot/nuget/native_discovery/native_dependency_file_discovery.rb +129 -0
  66. data/lib/dependabot/nuget/native_discovery/native_directory_packages_props_discovery.rb +44 -0
  67. data/lib/dependabot/nuget/native_discovery/native_discovery_json_reader.rb +174 -0
  68. data/lib/dependabot/nuget/native_discovery/native_evaluation_details.rb +63 -0
  69. data/lib/dependabot/nuget/native_discovery/native_project_discovery.rb +82 -0
  70. data/lib/dependabot/nuget/native_discovery/native_property_details.rb +43 -0
  71. data/lib/dependabot/nuget/native_discovery/native_workspace_discovery.rb +68 -0
  72. data/lib/dependabot/nuget/native_helpers.rb +59 -0
  73. data/lib/dependabot/nuget/native_update_checker/native_requirements_updater.rb +105 -0
  74. data/lib/dependabot/nuget/native_update_checker/native_update_checker.rb +200 -0
  75. data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +3 -2
  76. data/lib/dependabot/nuget/update_checker.rb +47 -0
  77. metadata +39 -5
@@ -78,8 +78,10 @@ internal static class SdkPackageUpdater
78
78
  tfm,
79
79
  topLevelDependencies,
80
80
  logger);
81
- foreach (var (packageName, packageVersion, _, _, _, _, _, _, _, _) in dependencies)
81
+ foreach (var dependency in dependencies)
82
82
  {
83
+ var packageName = dependency.Name;
84
+ var packageVersion = dependency.Version;
83
85
  if (packageVersion is null)
84
86
  {
85
87
  continue;
@@ -263,8 +265,10 @@ internal static class SdkPackageUpdater
263
265
  var packagesAndVersions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
264
266
  foreach (var (_, dependencies) in tfmsAndDependencies)
265
267
  {
266
- foreach (var (packageName, packageVersion, _, _, _, _, _, _, _, _) in dependencies)
268
+ foreach (var dependency in dependencies)
267
269
  {
270
+ var packageName = dependency.Name;
271
+ var packageVersion = dependency.Version;
268
272
  if (packagesAndVersions.TryGetValue(packageName, out var existingVersion) &&
269
273
  existingVersion != packageVersion)
270
274
  {
@@ -1,7 +1,3 @@
1
- using System;
2
- using System.IO;
3
- using System.Linq;
4
-
5
1
  using Microsoft.Language.Xml;
6
2
 
7
3
  namespace NuGetUpdater.Core.Updater
@@ -1,5 +1,3 @@
1
- using System;
2
-
3
1
  using Microsoft.Language.Xml;
4
2
 
5
3
  namespace NuGetUpdater.Core.Updater
@@ -1,5 +1,3 @@
1
- using System.Collections.Immutable;
2
-
3
1
  namespace NuGetUpdater.Core.Utilities;
4
2
 
5
3
  public static class HashSetExtensions
@@ -1,7 +1,3 @@
1
- using System;
2
- using System.Collections.Generic;
3
- using System.IO;
4
- using System.Linq;
5
1
  using System.Runtime.InteropServices;
6
2
  using System.Text;
7
3
  using System.Text.Encodings.Web;
@@ -1,6 +1,3 @@
1
- using System;
2
- using System.IO;
3
-
4
1
  namespace NuGetUpdater.Core;
5
2
 
6
3
  public sealed class Logger
@@ -231,11 +231,7 @@ internal static partial class MSBuildHelper
231
231
  ? evaluationResult.EvaluatedValue.TrimStart('[', '(').TrimEnd(']', ')')
232
232
  : evaluationResult.EvaluatedValue;
233
233
 
234
- // We don't know the version for range requirements or wildcard
235
- // requirements, so return "" for these.
236
- yield return packageVersion.Contains(',') || packageVersion.Contains('*')
237
- ? new Dependency(name, string.Empty, dependencyType, EvaluationResult: evaluationResult, IsUpdate: isUpdate)
238
- : new Dependency(name, packageVersion, dependencyType, EvaluationResult: evaluationResult, IsUpdate: isUpdate);
234
+ yield return new Dependency(name, packageVersion, dependencyType, EvaluationResult: evaluationResult, IsUpdate: isUpdate);
239
235
  }
240
236
  }
241
237
 
@@ -483,11 +479,13 @@ internal static partial class MSBuildHelper
483
479
  // if the source is relative to the original location, copy it to the temp directory
484
480
  if (PathHelper.IsSubdirectoryOf(nugetConfigDir!, localSource.Source))
485
481
  {
486
- string sourceRelativePath = Path.GetRelativePath(nugetConfigDir!, localSource.Source);
482
+ // normalize the directory separators and copy the contents
483
+ string localSourcePath = localSource.Source.Replace("\\", "/");
484
+ string sourceRelativePath = Path.GetRelativePath(nugetConfigDir!, localSourcePath);
487
485
  string destPath = Path.Join(tempDir.FullName, sourceRelativePath);
488
- if (Directory.Exists(localSource.Source))
486
+ if (Directory.Exists(localSourcePath))
489
487
  {
490
- PathHelper.CopyDirectory(localSource.Source, destPath);
488
+ PathHelper.CopyDirectory(localSourcePath, destPath);
491
489
  }
492
490
  }
493
491
  }
@@ -542,6 +540,7 @@ internal static partial class MSBuildHelper
542
540
  <PropertyGroup>
543
541
  <!-- For Windows-specific apps -->
544
542
  <EnableWindowsTargeting>true</EnableWindowsTargeting>
543
+ <!-- Really ensure CPM is disabled -->
545
544
  <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
546
545
  </PropertyGroup>
547
546
  </Project>
@@ -1,7 +1,3 @@
1
- using System.Collections.Generic;
2
- using System.IO;
3
- using System.Linq;
4
-
5
1
  namespace NuGetUpdater.Core;
6
2
 
7
3
  internal static class PathHelper
@@ -1,8 +1,5 @@
1
- using System;
2
1
  using System.Diagnostics;
3
2
  using System.Text;
4
- using System.Threading;
5
- using System.Threading.Tasks;
6
3
 
7
4
  namespace NuGetUpdater.Core;
8
5
 
@@ -1,7 +1,3 @@
1
- using System;
2
- using System.Collections.Generic;
3
- using System.Linq;
4
-
5
1
  using Microsoft.Language.Xml;
6
2
 
7
3
  namespace NuGetUpdater.Core;
@@ -0,0 +1,90 @@
1
+ using System.Collections.Immutable;
2
+ using System.Text.Json;
3
+
4
+ using NuGetUpdater.Core.Analyze;
5
+ using NuGetUpdater.Core.Discover;
6
+ using NuGetUpdater.Core.Test.Update;
7
+ using NuGetUpdater.Core.Test.Utilities;
8
+
9
+ using Xunit;
10
+
11
+ namespace NuGetUpdater.Core.Test.Analyze;
12
+
13
+ using TestFile = (string Path, string Content);
14
+
15
+ public class AnalyzeWorkerTestBase
16
+ {
17
+ protected static async Task TestAnalyzeAsync(
18
+ WorkspaceDiscoveryResult discovery,
19
+ DependencyInfo dependencyInfo,
20
+ ExpectedAnalysisResult expectedResult,
21
+ MockNuGetPackage[]? packages = null)
22
+ {
23
+ var relativeDependencyPath = $"./dependabot/dependency/{dependencyInfo.Name}.json";
24
+
25
+ TestFile[] files = [
26
+ (DiscoveryWorker.DiscoveryResultFileName, JsonSerializer.Serialize(discovery, AnalyzeWorker.SerializerOptions)),
27
+ (relativeDependencyPath, JsonSerializer.Serialize(dependencyInfo, AnalyzeWorker.SerializerOptions)),
28
+ ];
29
+
30
+ var actualResult = await RunAnalyzerAsync(dependencyInfo.Name, files, async directoryPath =>
31
+ {
32
+ await UpdateWorkerTestBase.MockNuGetPackagesInDirectory(packages, directoryPath);
33
+
34
+ var discoveryPath = Path.GetFullPath(DiscoveryWorker.DiscoveryResultFileName, directoryPath);
35
+ var dependencyPath = Path.GetFullPath(relativeDependencyPath, directoryPath);
36
+ var analysisPath = Path.GetFullPath(AnalyzeWorker.AnalysisDirectoryName, directoryPath);
37
+
38
+ var worker = new AnalyzeWorker(new Logger(verbose: true));
39
+ await worker.RunAsync(directoryPath, discoveryPath, dependencyPath, analysisPath);
40
+ });
41
+
42
+ ValidateAnalysisResult(expectedResult, actualResult);
43
+ }
44
+
45
+ protected static void ValidateAnalysisResult(ExpectedAnalysisResult expectedResult, AnalysisResult actualResult)
46
+ {
47
+ Assert.NotNull(actualResult);
48
+ Assert.Equal(expectedResult.UpdatedVersion, actualResult.UpdatedVersion);
49
+ Assert.Equal(expectedResult.CanUpdate, actualResult.CanUpdate);
50
+ Assert.Equal(expectedResult.VersionComesFromMultiDependencyProperty, actualResult.VersionComesFromMultiDependencyProperty);
51
+ ValidateDependencies(expectedResult.UpdatedDependencies, actualResult.UpdatedDependencies);
52
+ Assert.Equal(expectedResult.ExpectedUpdatedDependenciesCount ?? expectedResult.UpdatedDependencies.Length, actualResult.UpdatedDependencies.Length);
53
+
54
+ return;
55
+
56
+ void ValidateDependencies(ImmutableArray<Dependency> expectedDependencies, ImmutableArray<Dependency> actualDependencies)
57
+ {
58
+ if (expectedDependencies.IsDefault)
59
+ {
60
+ return;
61
+ }
62
+
63
+ foreach (var expectedDependency in expectedDependencies)
64
+ {
65
+ var actualDependency = actualDependencies.Single(d => d.Name == expectedDependency.Name);
66
+ Assert.Equal(expectedDependency.Name, actualDependency.Name);
67
+ Assert.Equal(expectedDependency.Version, actualDependency.Version);
68
+ Assert.Equal(expectedDependency.Type, actualDependency.Type);
69
+ AssertEx.Equal(expectedDependency.TargetFrameworks, actualDependency.TargetFrameworks);
70
+ Assert.Equal(expectedDependency.IsDirect, actualDependency.IsDirect);
71
+ Assert.Equal(expectedDependency.IsTransitive, actualDependency.IsTransitive);
72
+ Assert.Equal(expectedDependency.InfoUrl, actualDependency.InfoUrl);
73
+ }
74
+ }
75
+ }
76
+
77
+ protected static async Task<AnalysisResult> RunAnalyzerAsync(string dependencyName, TestFile[] files, Func<string, Task> action)
78
+ {
79
+ // write initial files
80
+ using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync(files);
81
+
82
+ // run discovery
83
+ await action(temporaryDirectory.DirectoryPath);
84
+
85
+ // gather results
86
+ var resultPath = Path.Join(temporaryDirectory.DirectoryPath, AnalyzeWorker.AnalysisDirectoryName, $"{dependencyName}.json");
87
+ var resultJson = await File.ReadAllTextAsync(resultPath);
88
+ return JsonSerializer.Deserialize<AnalysisResult>(resultJson, DiscoveryWorker.SerializerOptions)!;
89
+ }
90
+ }
@@ -0,0 +1,304 @@
1
+ using NuGetUpdater.Core.Analyze;
2
+
3
+ using Xunit;
4
+
5
+ namespace NuGetUpdater.Core.Test.Analyze;
6
+
7
+ public partial class AnalyzeWorkerTests : AnalyzeWorkerTestBase
8
+ {
9
+ [Fact]
10
+ public async Task FindsUpdatedVersion()
11
+ {
12
+ await TestAnalyzeAsync(
13
+ packages:
14
+ [
15
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.0.0", "net8.0"), // initially this
16
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.1.0", "net8.0"), // should update to this
17
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "1.2.0", "net8.0"), // `IgnoredVersions` should prevent this from being selected
18
+ ],
19
+ discovery: new()
20
+ {
21
+ Path = "/",
22
+ Projects = [
23
+ new()
24
+ {
25
+ FilePath = "./project.csproj",
26
+ TargetFrameworks = ["net8.0"],
27
+ Dependencies = [
28
+ new("Some.Package", "1.0.0", DependencyType.PackageReference),
29
+ ],
30
+ },
31
+ ],
32
+ },
33
+ dependencyInfo: new()
34
+ {
35
+ Name = "Some.Package",
36
+ Version = "1.0.0",
37
+ IgnoredVersions = [Requirement.Parse("> 1.1.0")],
38
+ IsVulnerable = false,
39
+ Vulnerabilities = [],
40
+ },
41
+ expectedResult: new()
42
+ {
43
+ UpdatedVersion = "1.1.0",
44
+ CanUpdate = true,
45
+ VersionComesFromMultiDependencyProperty = false,
46
+ UpdatedDependencies = [
47
+ new("Some.Package", "1.1.0", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
48
+ ],
49
+ }
50
+ );
51
+ }
52
+
53
+ [Fact]
54
+ public async Task FindsUpdatedPeerDependencies()
55
+ {
56
+ await TestAnalyzeAsync(
57
+ packages:
58
+ [
59
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.0.1", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.0.1]")])]), // initially this
60
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.9.2", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.9.2]")])]), // should update to this
61
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.9.3", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.9.3]")])]), // will not update this far
62
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.0.1", "net8.0"),
63
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.9.2", "net8.0"),
64
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.9.3", "net8.0"),
65
+ ],
66
+ discovery: new()
67
+ {
68
+ Path = "/",
69
+ Projects = [
70
+ new()
71
+ {
72
+ FilePath = "./project.csproj",
73
+ TargetFrameworks = ["net8.0"],
74
+ Dependencies = [
75
+ new("Some.Package", "4.0.1", DependencyType.PackageReference),
76
+ new("Some.Transitive.Dependency", "4.0.1", DependencyType.PackageReference),
77
+ ],
78
+ },
79
+ ],
80
+ },
81
+ dependencyInfo: new()
82
+ {
83
+ Name = "Some.Package",
84
+ Version = "4.0.1",
85
+ IgnoredVersions = [Requirement.Parse("> 4.9.2")],
86
+ IsVulnerable = false,
87
+ Vulnerabilities = [],
88
+ },
89
+ expectedResult: new()
90
+ {
91
+ UpdatedVersion = "4.9.2",
92
+ CanUpdate = true,
93
+ VersionComesFromMultiDependencyProperty = false,
94
+ UpdatedDependencies = [
95
+ new("Some.Package", "4.9.2", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
96
+ new("Some.Transitive.Dependency", "4.9.2", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
97
+ ],
98
+ }
99
+ );
100
+ }
101
+
102
+ [Fact]
103
+ public async Task DeterminesMultiPropertyVersion()
104
+ {
105
+ var evaluationResult = new EvaluationResult(EvaluationResultType.Success, "$(SomePackageVersion)", "4.0.1", "SomePackageVersion", ErrorMessage: null);
106
+ await TestAnalyzeAsync(
107
+ packages:
108
+ [
109
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.0.1", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.0.1]")])]), // initially this
110
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.9.2", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.9.2]")])]), // should update to this
111
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.9.3", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.9.3]")])]), // will not update this far
112
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.0.1", "net8.0"),
113
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.9.2", "net8.0"),
114
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.9.3", "net8.0"),
115
+ ],
116
+ discovery: new()
117
+ {
118
+ Path = "/",
119
+ Projects = [
120
+ new()
121
+ {
122
+ FilePath = "./project.csproj",
123
+ TargetFrameworks = ["net8.0"],
124
+ Dependencies = [
125
+ new("Some.Transitive.Dependency", "4.0.1", DependencyType.PackageReference, EvaluationResult: evaluationResult, TargetFrameworks: ["net8.0"]),
126
+ ],
127
+ },
128
+ new()
129
+ {
130
+ FilePath = "./project2.csproj",
131
+ TargetFrameworks = ["net8.0"],
132
+ Dependencies = [
133
+ new("Some.Package", "4.0.1", DependencyType.PackageReference, EvaluationResult: evaluationResult, TargetFrameworks: ["net8.0"]),
134
+ ],
135
+ },
136
+ ],
137
+ },
138
+ dependencyInfo: new()
139
+ {
140
+ Name = "Some.Transitive.Dependency",
141
+ Version = "4.0.1",
142
+ IgnoredVersions = [Requirement.Parse("> 4.9.2")],
143
+ IsVulnerable = false,
144
+ Vulnerabilities = [],
145
+ },
146
+ expectedResult: new()
147
+ {
148
+ UpdatedVersion = "4.9.2",
149
+ CanUpdate = true,
150
+ VersionComesFromMultiDependencyProperty = true,
151
+ UpdatedDependencies = [
152
+ new("Some.Package", "4.9.2", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
153
+ new("Some.Transitive.Dependency", "4.9.2", DependencyType.Unknown, TargetFrameworks: ["net8.0"]),
154
+ ],
155
+ }
156
+ );
157
+ }
158
+
159
+ [Fact]
160
+ public async Task FailsToUpdateMultiPropertyVersion()
161
+ {
162
+ // Package.A and Package.B happen to share some versions but would fail to update in sync with each other.
163
+ var evaluationResult = new EvaluationResult(EvaluationResultType.Success, "$(TestPackageVersion)", "4.5.0", "TestPackageVersion", ErrorMessage: null);
164
+ await TestAnalyzeAsync(
165
+ packages:
166
+ [
167
+ MockNuGetPackage.CreateSimplePackage("Package.A", "4.5.0", "net8.0"), // initial package versions match, purely by accident
168
+ MockNuGetPackage.CreateSimplePackage("Package.A", "4.9.2", "net8.0"), // subsequent versions do not match
169
+ MockNuGetPackage.CreateSimplePackage("Package.A", "4.9.3", "net8.0"),
170
+ MockNuGetPackage.CreateSimplePackage("Package.B", "4.5.0", "net8.0"),
171
+ MockNuGetPackage.CreateSimplePackage("Package.B", "4.5.1", "net8.0"),
172
+ MockNuGetPackage.CreateSimplePackage("Package.B", "4.5.2", "net8.0"),
173
+ ],
174
+ discovery: new()
175
+ {
176
+ Path = "/",
177
+ Projects = [
178
+ new()
179
+ {
180
+ FilePath = "./project.csproj",
181
+ TargetFrameworks = ["net8.0"],
182
+ Dependencies = [
183
+ new("Package.A", "4.5.0", DependencyType.PackageReference, EvaluationResult: evaluationResult, TargetFrameworks: ["net8.0"]),
184
+ ],
185
+ },
186
+ new()
187
+ {
188
+ FilePath = "./project2.csproj",
189
+ TargetFrameworks = ["net8.0"],
190
+ Dependencies = [
191
+ new("Package.B", "4.5.0", DependencyType.PackageReference, EvaluationResult: evaluationResult, TargetFrameworks: ["net8.0"]),
192
+ ],
193
+ },
194
+ ],
195
+ },
196
+ dependencyInfo: new()
197
+ {
198
+ Name = "Package.A",
199
+ Version = "4.5.0",
200
+ IgnoredVersions = [Requirement.Parse("> 4.9.2")],
201
+ IsVulnerable = false,
202
+ Vulnerabilities = [],
203
+ },
204
+ expectedResult: new()
205
+ {
206
+ UpdatedVersion = "4.5.0",
207
+ CanUpdate = false,
208
+ VersionComesFromMultiDependencyProperty = true,
209
+ UpdatedDependencies = [],
210
+ }
211
+ );
212
+ }
213
+
214
+
215
+ [Fact]
216
+ public async Task ReturnsUpToDate_ForMissingVersionProperty()
217
+ {
218
+ await TestAnalyzeAsync(
219
+ packages:
220
+ [
221
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.0.1", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.0.1]")])]), // initially this
222
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.9.2", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.9.2]")])]), // should update to this
223
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.9.3", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.9.3]")])]), // will not update this far
224
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.0.1", "net8.0"),
225
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.9.2", "net8.0"),
226
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.9.3", "net8.0"),
227
+ ],
228
+ discovery: new()
229
+ {
230
+ Path = "/",
231
+ Projects = [
232
+ new()
233
+ {
234
+ FilePath = "./project.csproj",
235
+ TargetFrameworks = ["net8.0"],
236
+ Dependencies = [
237
+ new("Some.Transitive.Dependency", "$(MissingPackageVersion)", DependencyType.PackageReference, EvaluationResult: new EvaluationResult(EvaluationResultType.PropertyNotFound, "$(MissingPackageVersion)", "$(MissingPackageVersion)", "$(MissingPackageVersion)", ErrorMessage: null)),
238
+ ],
239
+ },
240
+ ],
241
+ },
242
+ dependencyInfo: new()
243
+ {
244
+ Name = "Some.Package",
245
+ Version = "$(MissingPackageVersion)",
246
+ IgnoredVersions = [Requirement.Parse("> 4.9.2")],
247
+ IsVulnerable = false,
248
+ Vulnerabilities = [],
249
+ },
250
+ expectedResult: new()
251
+ {
252
+ UpdatedVersion = "$(MissingPackageVersion)",
253
+ CanUpdate = false,
254
+ VersionComesFromMultiDependencyProperty = false,
255
+ UpdatedDependencies = [],
256
+ }
257
+ );
258
+ }
259
+
260
+ [Fact]
261
+ public async Task ReturnsUpToDate_ForMissingDependency()
262
+ {
263
+ await TestAnalyzeAsync(
264
+ packages:
265
+ [
266
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.0.1", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.0.1]")])]), // initially this
267
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.9.2", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.9.2]")])]), // should update to this
268
+ MockNuGetPackage.CreateSimplePackage("Some.Package", "4.9.3", "net8.0", [(null, [("Some.Transitive.Dependency", "[4.9.3]")])]), // will not update this far
269
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.0.1", "net8.0"),
270
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.9.2", "net8.0"),
271
+ MockNuGetPackage.CreateSimplePackage("Some.Transitive.Dependency", "4.9.3", "net8.0"),
272
+ ],
273
+ discovery: new()
274
+ {
275
+ Path = "/",
276
+ Projects = [
277
+ new()
278
+ {
279
+ FilePath = "./project.csproj",
280
+ TargetFrameworks = ["net8.0"],
281
+ Dependencies = [
282
+ new("Some.Transitive.Dependency", "4.0.1", DependencyType.PackageReference),
283
+ ],
284
+ },
285
+ ],
286
+ },
287
+ dependencyInfo: new()
288
+ {
289
+ Name = "Some.Package",
290
+ Version = "4.0.1",
291
+ IgnoredVersions = [Requirement.Parse("> 4.9.2")],
292
+ IsVulnerable = false,
293
+ Vulnerabilities = [],
294
+ },
295
+ expectedResult: new()
296
+ {
297
+ UpdatedVersion = "4.0.1",
298
+ CanUpdate = false,
299
+ VersionComesFromMultiDependencyProperty = false,
300
+ UpdatedDependencies = [],
301
+ }
302
+ );
303
+ }
304
+ }
@@ -0,0 +1,145 @@
1
+ using System.Collections.Immutable;
2
+
3
+ using NuGet.Frameworks;
4
+ using NuGet.Packaging.Core;
5
+ using NuGet.Versioning;
6
+
7
+ using NuGetUpdater.Core.Analyze;
8
+
9
+ using Xunit;
10
+
11
+ namespace NuGetUpdater.Core.Test.Analyze;
12
+
13
+ public class CompatibilityCheckerTests
14
+ {
15
+ [Fact]
16
+ public void PerformCheck_CompatiblePackage_IsCompatible()
17
+ {
18
+ var package = new PackageIdentity("Dependency", NuGetVersion.Parse("1.0.0"));
19
+ ImmutableArray<NuGetFramework> projectFrameworks = [
20
+ NuGetFramework.Parse("net6.0"),
21
+ NuGetFramework.Parse("netstandard2.0"),
22
+ ];
23
+ var isDevDependency = false;
24
+ ImmutableArray<NuGetFramework> packageFrameworks = [
25
+ NuGetFramework.Parse("netstandard1.3"),
26
+ ];
27
+
28
+ var result = CompatibilityChecker.PerformCheck(
29
+ package,
30
+ projectFrameworks,
31
+ isDevDependency,
32
+ packageFrameworks,
33
+ new Logger(verbose: false));
34
+
35
+ Assert.True(result);
36
+ }
37
+
38
+ [Fact]
39
+ public void PerformCheck_IncompatiblePackage_IsIncompatible()
40
+ {
41
+ var package = new PackageIdentity("Dependency", NuGetVersion.Parse("1.0.0"));
42
+ ImmutableArray<NuGetFramework> projectFrameworks = [
43
+ NuGetFramework.Parse("net6.0"),
44
+ NuGetFramework.Parse("netstandard2.0"),
45
+ ];
46
+ var isDevDependency = false;
47
+ ImmutableArray<NuGetFramework> packageFrameworks = [
48
+ NuGetFramework.Parse("net462"),
49
+ ];
50
+
51
+ var result = CompatibilityChecker.PerformCheck(
52
+ package,
53
+ projectFrameworks,
54
+ isDevDependency,
55
+ packageFrameworks,
56
+ new Logger(verbose: false));
57
+
58
+ Assert.False(result);
59
+ }
60
+
61
+ [Fact]
62
+ public void PerformCheck_DevDependencyWithPackageFrameworks_IsChecked()
63
+ {
64
+ var package = new PackageIdentity("Dependency", NuGetVersion.Parse("1.0.0"));
65
+ ImmutableArray<NuGetFramework> projectFrameworks = [
66
+ NuGetFramework.Parse("net6.0"),
67
+ NuGetFramework.Parse("netstandard2.0"),
68
+ ];
69
+ var isDevDependency = true;
70
+ ImmutableArray<NuGetFramework> packageFrameworks = [
71
+ NuGetFramework.Parse("net462"),
72
+ ];
73
+
74
+ var result = CompatibilityChecker.PerformCheck(
75
+ package,
76
+ projectFrameworks,
77
+ isDevDependency,
78
+ packageFrameworks,
79
+ new Logger(verbose: false));
80
+
81
+ Assert.False(result);
82
+ }
83
+
84
+ [Fact]
85
+ public void PerformCheck_DevDependencyWithoutPackageFrameworks_IsCompatibile()
86
+ {
87
+ var package = new PackageIdentity("Dependency", NuGetVersion.Parse("1.0.0"));
88
+ ImmutableArray<NuGetFramework> projectFrameworks = [
89
+ NuGetFramework.Parse("net6.0"),
90
+ NuGetFramework.Parse("netstandard2.0"),
91
+ ];
92
+ var isDevDependency = true;
93
+ ImmutableArray<NuGetFramework> packageFrameworks = [];
94
+
95
+ var result = CompatibilityChecker.PerformCheck(
96
+ package,
97
+ projectFrameworks,
98
+ isDevDependency,
99
+ packageFrameworks,
100
+ new Logger(verbose: false));
101
+
102
+ Assert.True(result);
103
+ }
104
+
105
+ [Fact]
106
+ public void PerformCheck_WithoutPackageFrameworks_IsIncompatibile()
107
+ {
108
+ var package = new PackageIdentity("Dependency", NuGetVersion.Parse("1.0.0"));
109
+ ImmutableArray<NuGetFramework> projectFrameworks = [
110
+ NuGetFramework.Parse("net6.0"),
111
+ NuGetFramework.Parse("netstandard2.0"),
112
+ ];
113
+ var isDevDependency = false;
114
+ ImmutableArray<NuGetFramework> packageFrameworks = [];
115
+
116
+ var result = CompatibilityChecker.PerformCheck(
117
+ package,
118
+ projectFrameworks,
119
+ isDevDependency,
120
+ packageFrameworks,
121
+ new Logger(verbose: false));
122
+
123
+ Assert.False(result);
124
+ }
125
+
126
+ [Fact]
127
+ public void PerformCheck_WithoutProjectFrameworks_IsIncompatible()
128
+ {
129
+ var package = new PackageIdentity("Dependency", NuGetVersion.Parse("1.0.0"));
130
+ ImmutableArray<NuGetFramework> projectFrameworks = [];
131
+ var isDevDependency = true;
132
+ ImmutableArray<NuGetFramework> packageFrameworks = [
133
+ NuGetFramework.Parse("netstandard1.3"),
134
+ ];
135
+
136
+ var result = CompatibilityChecker.PerformCheck(
137
+ package,
138
+ projectFrameworks,
139
+ isDevDependency,
140
+ packageFrameworks,
141
+ new Logger(verbose: false));
142
+
143
+ Assert.False(result);
144
+ }
145
+ }