GivenThatWeWantToBuildAnAppWithTransitiveNonSdkProjectRefs.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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 Microsoft.Extensions.DependencyModel;
  4. namespace Microsoft.NET.Build.Tests
  5. {
  6. public class GivenThatWeWantToBuildAnAppWithTransitiveNonSdkProjectRefs : SdkTest
  7. {
  8. public GivenThatWeWantToBuildAnAppWithTransitiveNonSdkProjectRefs(ITestOutputHelper log) : base(log)
  9. {
  10. }
  11. [WindowsOnlyFact]
  12. public void It_builds_the_project_successfully()
  13. {
  14. // NOTE the projects created by CreateTestProject:
  15. // TestApp --depends on--> MainLibrary --depends on--> AuxLibrary (non-SDK)
  16. // (TestApp transitively depends on AuxLibrary)
  17. var testAsset = _testAssetsManager
  18. .CreateTestProject(CreateTestProject());
  19. VerifyAppBuilds(testAsset, string.Empty);
  20. }
  21. [WindowsOnlyTheory]
  22. [InlineData("")]
  23. [InlineData("TestApp.")]
  24. public void It_builds_deps_correctly_when_projects_do_not_get_restored(string prefix)
  25. {
  26. // NOTE the projects created by CreateTestProject:
  27. // TestApp --depends on--> MainLibrary --depends on--> AuxLibrary
  28. // (TestApp transitively depends on AuxLibrary)
  29. var testAsset = _testAssetsManager
  30. .CreateTestProject(CreateTestProject())
  31. .WithProjectChanges(
  32. (projectName, project) =>
  33. {
  34. string projectFileName = Path.GetFileNameWithoutExtension(projectName);
  35. if (StringComparer.OrdinalIgnoreCase.Equals(projectFileName, "AuxLibrary") ||
  36. StringComparer.OrdinalIgnoreCase.Equals(projectFileName, "MainLibrary"))
  37. {
  38. var ns = project.Root.Name.Namespace;
  39. XElement propertyGroup = project.Root.Element(ns + "PropertyGroup");
  40. if (!string.IsNullOrEmpty(prefix))
  41. {
  42. XElement assemblyName = propertyGroup.Element(ns + "AssemblyName");
  43. assemblyName.RemoveAll();
  44. assemblyName.Add(prefix + projectFileName);
  45. }
  46. // indicate that project restore is not supported for these projects:
  47. var target = new XElement(ns + "Target",
  48. new XAttribute("Name", "_IsProjectRestoreSupported"),
  49. new XAttribute("Returns", "@(_ValidProjectsForRestore)"));
  50. project.Root.Add(target);
  51. }
  52. else // if (StringComparer.OrdinalIgnoreCase.Equals(projectFileName, "TestApp"))
  53. {
  54. var ns = project.Root.Name.Namespace;
  55. XElement propertyGroup = project.Root.Element(ns + "PropertyGroup");
  56. XElement includeProjectsNotInAssetsFileInDepsFile = new(ns + "IncludeProjectsNotInAssetsFileInDepsFile");
  57. includeProjectsNotInAssetsFileInDepsFile.Add("true");
  58. propertyGroup.Add(includeProjectsNotInAssetsFileInDepsFile);
  59. }
  60. });
  61. string outputDirectory = VerifyAppBuilds(testAsset, prefix);
  62. using (var depsJsonFileStream = File.OpenRead(Path.Combine(outputDirectory, "TestApp.deps.json")))
  63. {
  64. var dependencyContext = new DependencyContextJsonReader().Read(depsJsonFileStream);
  65. var projectNames = dependencyContext.RuntimeLibraries.Select(library => library.Name).ToList();
  66. projectNames.Should().BeEquivalentTo(new[] { "TestApp", prefix + "AuxLibrary", prefix + "MainLibrary" });
  67. }
  68. }
  69. private TestProject CreateTestProject()
  70. {
  71. string targetFrameworkVersion = "v4.8";
  72. var auxLibraryProject = new TestProject("AuxLibrary")
  73. {
  74. IsSdkProject = false,
  75. TargetFrameworkVersion = targetFrameworkVersion
  76. };
  77. auxLibraryProject.SourceFiles["Helper.cs"] = @"
  78. using System;
  79. namespace AuxLibrary
  80. {
  81. public static class Helper
  82. {
  83. public static void WriteMessage()
  84. {
  85. Console.WriteLine(""This string came from AuxLibrary!"");
  86. }
  87. }
  88. }
  89. ";
  90. var mainLibraryProject = new TestProject("MainLibrary")
  91. {
  92. IsSdkProject = false,
  93. TargetFrameworkVersion = targetFrameworkVersion
  94. };
  95. mainLibraryProject.ReferencedProjects.Add(auxLibraryProject);
  96. mainLibraryProject.SourceFiles["Helper.cs"] = @"
  97. using System;
  98. namespace MainLibrary
  99. {
  100. public static class Helper
  101. {
  102. public static void WriteMessage()
  103. {
  104. Console.WriteLine(""This string came from MainLibrary!"");
  105. AuxLibrary.Helper.WriteMessage();
  106. }
  107. }
  108. }
  109. ";
  110. var testAppProject = new TestProject("TestApp")
  111. {
  112. IsExe = true,
  113. TargetFrameworks = ToolsetInfo.CurrentTargetFramework
  114. };
  115. testAppProject.AdditionalProperties["ProduceReferenceAssembly"] = "false";
  116. // disable implicit use of the Roslyn Toolset compiler package
  117. testAppProject.AdditionalProperties["BuildWithNetFrameworkHostedCompiler"] = false.ToString();
  118. testAppProject.ReferencedProjects.Add(mainLibraryProject);
  119. testAppProject.SourceFiles["Program.cs"] = @"
  120. using System;
  121. namespace TestApp
  122. {
  123. public class Program
  124. {
  125. public static void Main(string[] args)
  126. {
  127. Console.WriteLine(""TestApp --depends on--> MainLibrary --depends on--> AuxLibrary"");
  128. MainLibrary.Helper.WriteMessage();
  129. }
  130. }
  131. }
  132. ";
  133. return testAppProject;
  134. }
  135. private string VerifyAppBuilds(TestAsset testAsset, string prefix)
  136. {
  137. var buildCommand = new BuildCommand(testAsset, "TestApp");
  138. var outputDirectory = buildCommand.GetOutputDirectory(ToolsetInfo.CurrentTargetFramework);
  139. buildCommand
  140. .Execute()
  141. .Should()
  142. .Pass();
  143. outputDirectory.Should().OnlyHaveFiles(new[] {
  144. "TestApp.dll",
  145. "TestApp.pdb",
  146. $"TestApp{EnvironmentInfo.ExecutableExtension}",
  147. "TestApp.deps.json",
  148. "TestApp.runtimeconfig.json",
  149. prefix + "MainLibrary.dll",
  150. prefix + "MainLibrary.pdb",
  151. prefix + "AuxLibrary.dll",
  152. prefix + "AuxLibrary.pdb",
  153. });
  154. new DotnetCommand(Log, Path.Combine(outputDirectory.FullName, "TestApp.dll"))
  155. .Execute()
  156. .Should()
  157. .Pass()
  158. .And
  159. .HaveStdOutContaining("This string came from MainLibrary!")
  160. .And
  161. .HaveStdOutContaining("This string came from AuxLibrary!");
  162. return outputDirectory.FullName;
  163. }
  164. }
  165. }