GivenThatWeWantToBuildAnAppWithoutTransitiveProjectRefs.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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.Collections.Immutable;
  4. using System.Runtime.CompilerServices;
  5. using Microsoft.DotNet.Cli.Utils;
  6. namespace Microsoft.NET.Build.Tests
  7. {
  8. public class GivenThatWeWantToBuildAnAppWithoutTransitiveProjectRefs : SdkTest
  9. {
  10. public GivenThatWeWantToBuildAnAppWithoutTransitiveProjectRefs(ITestOutputHelper log) : base(log)
  11. {
  12. }
  13. [Fact]
  14. public void It_builds_the_project_successfully_when_RAR_finds_all_references()
  15. {
  16. BuildAppWithTransitiveDependenciesAndTransitiveCompileReference(new[] { "/p:DisableTransitiveProjectReferences=true" });
  17. }
  18. [Fact]
  19. public void It_builds_the_project_successfully_with_static_graph_and_isolation()
  20. {
  21. BuildAppWithTransitiveDependenciesAndTransitiveCompileReference(new[] { "/graph" });
  22. }
  23. [Fact]
  24. public void It_cleans_the_project_successfully_with_static_graph_and_isolation()
  25. {
  26. var (testAsset, outputDirectories) = BuildAppWithTransitiveDependenciesAndTransitiveCompileReference(new[] { "/graph" });
  27. var cleanCommand = new DotnetCommand(
  28. Log,
  29. "msbuild",
  30. Path.Combine(testAsset.TestRoot, "1", "1.csproj"),
  31. "/t:clean",
  32. "/graph");
  33. cleanCommand
  34. .Execute()
  35. .Should()
  36. .Pass();
  37. foreach (var outputDirectory in outputDirectories)
  38. {
  39. outputDirectory.Value.GetFileSystemInfos()
  40. .Should()
  41. .BeEmpty();
  42. }
  43. }
  44. private (TestAsset TestAsset, IReadOnlyDictionary<string, DirectoryInfo> OutputDirectories)
  45. BuildAppWithTransitiveDependenciesAndTransitiveCompileReference(string[] msbuildArguments, [CallerMemberName] string callingMethod = "")
  46. {
  47. var testAsset = _testAssetsManager.CreateTestProject(DiamondShapeGraphWithRuntimeDependencies(), callingMethod);
  48. testAsset.Restore(Log, "1");
  49. string[] targetFrameworks = { "netcoreapp2.1", "net472" };
  50. var (buildResult, outputDirectories) = Build(testAsset, targetFrameworks, msbuildArguments);
  51. buildResult.Should()
  52. .Pass();
  53. var coreExeFiles = new[]
  54. {
  55. "1.dll",
  56. "1.pdb",
  57. "1.deps.json",
  58. "1.runtimeconfig.json",
  59. "1.runtimeconfig.dev.json"
  60. };
  61. var netFrameworkExeFiles = new[]
  62. {
  63. "1.exe",
  64. "1.pdb",
  65. "1.exe.config",
  66. "System.Diagnostics.DiagnosticSource.dll"
  67. };
  68. foreach (var targetFramework in targetFrameworks)
  69. {
  70. var runtimeFiles = targetFramework.StartsWith("netcoreapp")
  71. ? coreExeFiles
  72. : netFrameworkExeFiles;
  73. outputDirectories[targetFramework].Should()
  74. .OnlyHaveFiles(
  75. runtimeFiles.Concat(
  76. new[]
  77. {
  78. "2.dll",
  79. "2.pdb",
  80. "3.dll",
  81. "3.pdb",
  82. "4.dll",
  83. "4.pdb",
  84. "5.dll",
  85. "5.pdb"
  86. }));
  87. if (targetFramework.StartsWith("net4") && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  88. {
  89. // only windows can build full framework tfms
  90. break;
  91. }
  92. DotnetCommand runCommand = new(
  93. Log,
  94. "run",
  95. "--framework",
  96. targetFramework,
  97. "--project",
  98. Path.Combine(testAsset.TestRoot, "1", "1.csproj"));
  99. runCommand
  100. .Execute()
  101. .Should()
  102. .Pass()
  103. .And
  104. .HaveStdOutContaining("Hello World from 1")
  105. .And
  106. .HaveStdOutContaining("Hello World from 2")
  107. .And
  108. .HaveStdOutContaining("Hello World from 4")
  109. .And
  110. .HaveStdOutContaining("Hello World from 5")
  111. .And
  112. .HaveStdOutContaining("Hello World from 3")
  113. .And
  114. .HaveStdOutContaining("Hello World from 4")
  115. .And
  116. .HaveStdOutContaining("Hello World from 5");
  117. }
  118. return (testAsset, outputDirectories);
  119. }
  120. [Fact]
  121. public void It_builds_the_project_successfully_when_RAR_does_not_find_all_references()
  122. {
  123. var testAsset = _testAssetsManager.CreateTestProject(GraphWithoutRuntimeDependencies());
  124. testAsset.Restore(Log, "1");
  125. var (buildResult, outputDirectories) = Build(testAsset, new[] { "netcoreapp2.1" }, new[] { "/p:DisableTransitiveProjectReferences=true" });
  126. buildResult.Should().Pass();
  127. outputDirectories.Should().ContainSingle().Which.Key.Should().Be("netcoreapp2.1");
  128. var outputDirectory = outputDirectories.First().Value;
  129. outputDirectory.Should().OnlyHaveFiles(new[] {
  130. "1.dll",
  131. "1.pdb",
  132. "1.deps.json",
  133. "1.runtimeconfig.json",
  134. "1.runtimeconfig.dev.json",
  135. "2.dll",
  136. "2.pdb"
  137. });
  138. new DotnetCommand(Log, Path.Combine(outputDirectory.FullName, "1.dll"))
  139. .Execute()
  140. .Should()
  141. .Pass()
  142. .And
  143. .HaveStdOutContaining("Hello World from 1");
  144. }
  145. private (CommandResult BuildResult, IReadOnlyDictionary<string, DirectoryInfo> OutputDirectories) Build(
  146. TestAsset testAsset,
  147. IEnumerable<string> targetFrameworks,
  148. string[] msbuildArguments
  149. )
  150. {
  151. var buildCommand = new BuildCommand(testAsset, "1");
  152. var buildResult = buildCommand.ExecuteWithoutRestore(msbuildArguments);
  153. var outputDirectories = targetFrameworks.ToImmutableDictionary(tf => tf, tf => buildCommand.GetOutputDirectory(tf));
  154. return (buildResult, outputDirectories);
  155. }
  156. private const string SourceFile = @"
  157. using System;
  158. namespace _{0}
  159. {{
  160. public class Class1
  161. {{
  162. static void Main(string[] args)
  163. {{
  164. Message();
  165. }}
  166. public static void Message()
  167. {{
  168. Console.WriteLine(""Hello World from {0}"");
  169. {1}
  170. }}
  171. }}
  172. }}
  173. ";
  174. private TestProject GraphWithoutRuntimeDependencies()
  175. {
  176. var project4 = new TestProject
  177. {
  178. Name = "4",
  179. TargetFrameworks = "netstandard1.3",
  180. SourceFiles =
  181. {
  182. ["Program.cs"] = string.Format(SourceFile, "4", string.Empty)
  183. }
  184. };
  185. var project3 = new TestProject
  186. {
  187. Name = "3",
  188. TargetFrameworks = "netstandard1.6",
  189. ReferencedProjects = { project4 },
  190. SourceFiles =
  191. {
  192. ["Program.cs"] = string.Format(SourceFile, "3", string.Empty)
  193. }
  194. };
  195. var project2 = new TestProject
  196. {
  197. Name = "2",
  198. TargetFrameworks = "netstandard2.0",
  199. ReferencedProjects = { project3 },
  200. SourceFiles =
  201. {
  202. ["Program.cs"] = string.Format(SourceFile, "2", string.Empty)
  203. }
  204. };
  205. var project1 = new TestProject
  206. {
  207. Name = "1",
  208. IsExe = true,
  209. TargetFrameworks = "netcoreapp2.1",
  210. ReferencedProjects = { project2 },
  211. SourceFiles =
  212. {
  213. ["Program.cs"] = string.Format(SourceFile, "1", string.Empty)
  214. }
  215. };
  216. return project1;
  217. }
  218. private TestProject DiamondShapeGraphWithRuntimeDependencies()
  219. {
  220. var project5 = new TestProject
  221. {
  222. Name = "5",
  223. TargetFrameworks = "netstandard1.3",
  224. SourceFiles =
  225. {
  226. ["Program.cs"] = string.Format(SourceFile, "5", string.Empty)
  227. }
  228. };
  229. var project4 = new TestProject
  230. {
  231. Name = "4",
  232. TargetFrameworks = "netstandard1.3;netstandard1.6;net462",
  233. ReferencedProjects = { project5 },
  234. SourceFiles =
  235. {
  236. ["Program.cs"] = string.Format(SourceFile, "4", "_5.Class1.Message();")
  237. }
  238. };
  239. var project3 = new TestProject
  240. {
  241. Name = "3",
  242. TargetFrameworks = "netstandard2.0;net462",
  243. ReferencedProjects = { project4 },
  244. SourceFiles =
  245. {
  246. ["Program.cs"] = string.Format(SourceFile, "3", "_4.Class1.Message();")
  247. }
  248. };
  249. var project2 = new TestProject
  250. {
  251. Name = "2",
  252. TargetFrameworks = "netstandard1.5",
  253. ReferencedProjects = { project4 },
  254. SourceFiles =
  255. {
  256. ["Program.cs"] = string.Format(SourceFile, "2", "_4.Class1.Message();")
  257. }
  258. };
  259. var project1 = new TestProject
  260. {
  261. Name = "1",
  262. IsExe = true,
  263. TargetFrameworks = "netcoreapp2.1;net472",
  264. ReferencedProjects = { project2, project3 },
  265. SourceFiles =
  266. {
  267. ["Program.cs"] = string.Format(SourceFile, "1", " _2.Class1.Message(); _3.Class1.Message();")
  268. }
  269. };
  270. return project1;
  271. }
  272. }
  273. }