GivenThatWeWantToVerifyNuGetReferenceCompat.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. using System.Runtime.CompilerServices;
  4. namespace Microsoft.NET.Build.Tests
  5. {
  6. public class GivenThatWeWantToVerifyNuGetReferenceCompat : SdkTest, IClassFixture<DeleteNuGetArtifactsFixture>
  7. {
  8. public GivenThatWeWantToVerifyNuGetReferenceCompat(ITestOutputHelper log) : base(log)
  9. {
  10. }
  11. [Theory]
  12. [InlineData("net45", "Full", "netstandard1.0 netstandard1.1 net45", true, true)]
  13. [InlineData("net451", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 net45 net451", true, true)]
  14. [InlineData("net46", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 net45 net451 net46", true, true)]
  15. [InlineData("net461", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0 net45 net451 net46 net461", true, true)]
  16. [InlineData("net462", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0 net45 net451 net46 net461 net462", true, true)]
  17. [InlineData("netstandard1.0", "Full", "netstandard1.0", true, true)]
  18. [InlineData("netstandard1.1", "Full", "netstandard1.0 netstandard1.1", true, true)]
  19. [InlineData("netstandard1.2", "Full", "netstandard1.0 netstandard1.1 netstandard1.2", true, true)]
  20. [InlineData("netstandard1.3", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3", true, true)]
  21. [InlineData("netstandard1.4", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4", true, true)]
  22. [InlineData("netstandard1.5", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5", true, true)]
  23. [InlineData("netstandard1.6", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6", true, true)]
  24. [InlineData("netstandard2.0", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0", true, true)]
  25. [InlineData("netcoreapp1.0", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netcoreapp1.0", true, true)]
  26. [InlineData("netcoreapp1.1", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netcoreapp1.0 netcoreapp1.1", true, true)]
  27. [InlineData("netcoreapp2.0", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0 netcoreapp1.0 netcoreapp1.1 netcoreapp2.0", true, true)]
  28. [InlineData("netstandard2.0", "OptIn", "net45 net451 net46 net461", true, true)]
  29. [InlineData("netcoreapp2.0", "OptIn", "net45 net451 net46 net461", true, true)]
  30. public void Nuget_reference_compat(string referencerTarget, string testDescription, string rawDependencyTargets,
  31. bool restoreSucceeds, bool buildSucceeds)
  32. {
  33. string referencerDirectoryNamePostfix = "_" + referencerTarget + "_" + testDescription;
  34. TestProject referencerProject = GetTestProject(ConstantStringValues.ReferencerDirectoryName, referencerTarget, true);
  35. // Skip running test if not running on Windows
  36. // https://github.com/dotnet/sdk/issues/335
  37. if (!(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || referencerProject.BuildsOnNonWindows))
  38. {
  39. return;
  40. }
  41. foreach (string dependencyTarget in rawDependencyTargets.Split(',', ';', ' ').ToList())
  42. {
  43. TestProject dependencyProject = GetTestProject(ConstantStringValues.DependencyDirectoryNamePrefix + dependencyTarget.Replace('.', '_'), dependencyTarget, true);
  44. TestPackageReference dependencyPackageReference = new(
  45. dependencyProject.Name,
  46. "1.0.0",
  47. ConstantStringValues.ConstructNuGetPackageReferencePath(dependencyProject, identifier: referencerTarget + testDescription + rawDependencyTargets));
  48. // Skip creating the NuGet package if not running on Windows; or if the NuGet package already exists
  49. // https://github.com/dotnet/sdk/issues/335
  50. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || dependencyProject.BuildsOnNonWindows)
  51. {
  52. if (!dependencyPackageReference.NuGetPackageExists())
  53. {
  54. // Create the NuGet packages
  55. var dependencyTestAsset = _testAssetsManager.CreateTestProject(dependencyProject, identifier: referencerTarget + testDescription + rawDependencyTargets);
  56. var dependencyRestoreCommand = dependencyTestAsset.GetRestoreCommand(Log, relativePath: dependencyProject.Name).Execute().Should().Pass();
  57. var dependencyProjectDirectory = Path.Combine(dependencyTestAsset.TestRoot, dependencyProject.Name);
  58. var dependencyPackCommand = new PackCommand(Log, dependencyProjectDirectory);
  59. var dependencyPackResult = dependencyPackCommand.Execute().Should().Pass();
  60. }
  61. referencerProject.PackageReferences.Add(dependencyPackageReference);
  62. }
  63. }
  64. // Skip running tests if no NuGet packages are referenced
  65. // https://github.com/dotnet/sdk/issues/335
  66. if (referencerProject.PackageReferences == null)
  67. {
  68. return;
  69. }
  70. // Set the referencer project as an Exe unless it targets .NET Standard
  71. if (!referencerProject.TargetFrameworkIdentifiers.Contains(ConstantStringValues.NetstandardTargetFrameworkIdentifier))
  72. {
  73. referencerProject.IsExe = true;
  74. }
  75. // Create the referencing app and run the compat test
  76. var referencerTestAsset = _testAssetsManager.CreateTestProject(referencerProject, ConstantStringValues.TestDirectoriesNamePrefix, referencerDirectoryNamePostfix);
  77. var referencerRestoreCommand = referencerTestAsset.GetRestoreCommand(Log, relativePath: referencerProject.Name);
  78. List<string> referencerRestoreSources = new();
  79. // Modify the restore command to refer to the created NuGet packages
  80. foreach (TestPackageReference packageReference in referencerProject.PackageReferences)
  81. {
  82. var source = Path.Combine(packageReference.NupkgPath, packageReference.ID, "bin", "Debug");
  83. referencerRestoreSources.Add(source);
  84. }
  85. NuGetConfigWriter.Write(referencerTestAsset.TestRoot, referencerRestoreSources);
  86. if (restoreSucceeds)
  87. {
  88. referencerRestoreCommand.Execute().Should().Pass();
  89. }
  90. else
  91. {
  92. referencerRestoreCommand.Execute().Should().Fail();
  93. }
  94. var referencerBuildCommand = new BuildCommand(referencerTestAsset);
  95. var referencerBuildResult = referencerBuildCommand.Execute();
  96. if (buildSucceeds)
  97. {
  98. referencerBuildResult.Should().Pass();
  99. }
  100. else
  101. {
  102. referencerBuildResult.Should().Fail().And.HaveStdOutContaining("It cannot be referenced by a project that targets");
  103. }
  104. }
  105. [WindowsOnlyTheory]
  106. [InlineData("netstandard2.0")]
  107. [InlineData("netcoreapp2.0")]
  108. public void Netfx_is_implicit_for_Netstandard_and_Netcore_20(string targetFramework)
  109. {
  110. var testProjectName = targetFramework.Replace(".", "_") + "implicit_atf";
  111. var (testProjectTestAsset, testPackageReference) = CreateTestAsset(testProjectName, targetFramework, "net461", identifer: targetFramework);
  112. var restoreCommand = testProjectTestAsset.GetRestoreCommand(Log, relativePath: testProjectName);
  113. var source = Path.Combine(testPackageReference.NupkgPath, testPackageReference.ID, "bin", "Debug");
  114. NuGetConfigWriter.Write(testProjectTestAsset.TestRoot, source);
  115. restoreCommand.Execute().Should().Pass();
  116. var buildCommand = new BuildCommand(testProjectTestAsset);
  117. buildCommand.Execute().Should().Pass();
  118. }
  119. [WindowsOnlyTheory]
  120. [InlineData("netstandard1.6")]
  121. [InlineData("netcoreapp1.1")]
  122. public void Netfx_is_not_implicit_for_Netstandard_and_Netcore_less_than_20(string targetFramework)
  123. {
  124. var testProjectName = targetFramework.Replace(".", "_") + "non_implicit_atf";
  125. var (testProjectTestAsset, testPackageReference) = CreateTestAsset(testProjectName, targetFramework, "net461", identifer: targetFramework);
  126. var restoreCommand = testProjectTestAsset.GetRestoreCommand(Log, relativePath: testProjectName);
  127. NuGetConfigWriter.Write(testProjectTestAsset.TestRoot, Path.GetDirectoryName(testPackageReference.NupkgPath));
  128. restoreCommand.Execute().Should().Fail();
  129. }
  130. [WindowsOnlyFact]
  131. public void It_is_possible_to_disable_netfx_implicit_asset_target_fallback()
  132. {
  133. const string testProjectName = "netstandard20_disabled_atf";
  134. var (testProjectTestAsset, testPackageReference) = CreateTestAsset(
  135. testProjectName,
  136. "netstandard2.0",
  137. "net461",
  138. new Dictionary<string, string> { { "DisableImplicitAssetTargetFallback", "true" } });
  139. var restoreCommand = testProjectTestAsset.GetRestoreCommand(Log, relativePath: testProjectName);
  140. NuGetConfigWriter.Write(testProjectTestAsset.TestRoot, Path.GetDirectoryName(testPackageReference.NupkgPath));
  141. restoreCommand.Execute().Should().Fail();
  142. }
  143. [WindowsOnlyFact]
  144. public void It_chooses_lowest_netfx_in_default_atf()
  145. {
  146. var testProjectName = $"{ToolsetInfo.CurrentTargetFramework.Replace(".", "")}_multiple_atf";
  147. var (testProjectTestAsset, testPackageReference) = CreateTestAsset(
  148. testProjectName,
  149. ToolsetInfo.CurrentTargetFramework,
  150. "net462;net472",
  151. new Dictionary<string, string> { ["CopyLocalLockFileAssemblies"] = "true" });
  152. var source = Path.Combine(testPackageReference.NupkgPath, testPackageReference.ID, "bin", "Debug");
  153. NuGetConfigWriter.Write(testProjectTestAsset.TestRoot, source);
  154. var restoreCommand = testProjectTestAsset.GetRestoreCommand(Log, relativePath: testProjectName);
  155. restoreCommand.Execute().Should().Pass();
  156. var buildCommand = new BuildCommand(testProjectTestAsset);
  157. buildCommand.Execute().Should().Pass();
  158. var referencedDll = buildCommand.GetOutputDirectory().File("net462_net472_pkg.dll").FullName;
  159. var referencedTargetFramework = AssemblyInfo.Get(referencedDll)["TargetFrameworkAttribute"];
  160. referencedTargetFramework.Should().Be(".NETFramework,Version=v4.6.2");
  161. }
  162. private (TestAsset, TestPackageReference) CreateTestAsset(
  163. string testProjectName,
  164. string callerTargetFramework,
  165. string calleeTargetFrameworks,
  166. Dictionary<string, string> additionalProperties = null,
  167. [CallerMemberName] string testName = null,
  168. string identifer = null)
  169. {
  170. var testPackageReference = CreateTestPackage(calleeTargetFrameworks, testName, identifer);
  171. var testProject =
  172. new TestProject
  173. {
  174. Name = testProjectName,
  175. TargetFrameworks = callerTargetFramework,
  176. };
  177. if (additionalProperties != null)
  178. {
  179. foreach (var additionalProperty in additionalProperties)
  180. {
  181. testProject.AdditionalProperties.Add(additionalProperty.Key, additionalProperty.Value);
  182. }
  183. }
  184. testProject.PackageReferences.Add(testPackageReference);
  185. var testProjectTestAsset = _testAssetsManager.CreateTestProject(
  186. testProject,
  187. string.Empty,
  188. $"{testProjectName}_{calleeTargetFrameworks}");
  189. return (testProjectTestAsset, testPackageReference);
  190. }
  191. private TestPackageReference CreateTestPackage(string targetFrameworks, string identifier, [CallerMemberName] string callingMethod = "")
  192. {
  193. var project =
  194. new TestProject
  195. {
  196. Name = $"{targetFrameworks.Replace(';', '_')}_pkg",
  197. TargetFrameworks = targetFrameworks,
  198. };
  199. var packageReference =
  200. new TestPackageReference(
  201. project.Name,
  202. "1.0.0",
  203. ConstantStringValues.ConstructNuGetPackageReferencePath(project, identifier, callingMethod));
  204. if (!packageReference.NuGetPackageExists())
  205. {
  206. var testAsset =
  207. _testAssetsManager.CreateTestProject(
  208. project,
  209. callingMethod,
  210. identifier);
  211. var packageRestoreCommand =
  212. testAsset.GetRestoreCommand(Log, relativePath: project.Name).Execute().Should().Pass();
  213. var dependencyProjectDirectory = Path.Combine(testAsset.TestRoot, project.Name);
  214. var packagePackCommand =
  215. new PackCommand(Log, dependencyProjectDirectory).Execute().Should().Pass();
  216. }
  217. return packageReference;
  218. }
  219. TestProject GetTestProject(string name, string target, bool isSdkProject)
  220. {
  221. TestProject ret = new()
  222. {
  223. Name = name,
  224. IsSdkProject = isSdkProject
  225. };
  226. if (isSdkProject)
  227. {
  228. ret.TargetFrameworks = target;
  229. }
  230. else
  231. {
  232. ret.TargetFrameworkVersion = target;
  233. }
  234. return ret;
  235. }
  236. }
  237. }