TemplateTests.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // Copyright (c) .NET Foundation. All rights reserved.
  2. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Runtime.InteropServices;
  8. using Cli.FunctionalTests.Templates;
  9. using Cli.FunctionalTests.Util;
  10. using NuGet.Versioning;
  11. using NUnit.Framework;
  12. namespace Cli.FunctionalTests
  13. {
  14. [TestFixture]
  15. public class TemplateTests
  16. {
  17. [Test]
  18. [TestCaseSource(nameof(RestoreData))]
  19. public void _1_Restore(Template template)
  20. {
  21. var expected = template.ExpectedObjFilesAfterRestore;
  22. var actual = template.ObjFilesAfterRestore;
  23. CollectionAssert.AreEquivalent(expected, actual);
  24. }
  25. [Test]
  26. [TestCaseSource(nameof(RestoreData))]
  27. public void _2_RestoreIncremental(Template template)
  28. {
  29. var expected = template.ExpectedObjFilesAfterRestore;
  30. var actual = template.ObjFilesAfterRestoreIncremental;
  31. CollectionAssert.AreEquivalent(expected, actual);
  32. }
  33. [Test]
  34. [TestCaseSource(nameof(BuildData))]
  35. public void _3_Build(Template template)
  36. {
  37. var expectedObj = template.ExpectedObjFilesAfterBuild;
  38. var actualObj = template.ObjFilesAfterBuild;
  39. CollectionAssert.AreEquivalent(expectedObj, actualObj);
  40. var expectedBin = template.ExpectedBinFilesAfterBuild;
  41. var actualBin = template.BinFilesAfterBuild;
  42. CollectionAssert.AreEquivalent(expectedBin, actualBin);
  43. }
  44. [Test]
  45. [TestCaseSource(nameof(BuildData))]
  46. public void _4_BuildIncremental(Template template)
  47. {
  48. var expectedObj = template.ExpectedObjFilesAfterBuild;
  49. var actualObj = template.ObjFilesAfterBuildIncremental;
  50. CollectionAssert.AreEquivalent(expectedObj, actualObj);
  51. var expectedBin = template.ExpectedBinFilesAfterBuild;
  52. var actualBin = template.BinFilesAfterBuildIncremental;
  53. CollectionAssert.AreEquivalent(expectedBin, actualBin);
  54. }
  55. [Test]
  56. [TestCaseSource(nameof(RunData))]
  57. public void _5_Run(Template template)
  58. {
  59. var statusCode = template.HttpResponseAfterRun.StatusCode;
  60. Assert.AreEqual(HttpStatusCode.OK, statusCode,
  61. GetMessage(statusCode, template.ServerOutputAfterRun, template.ServerErrorAfterRun));
  62. statusCode = template.HttpsResponseAfterRun.StatusCode;
  63. Assert.AreEqual(HttpStatusCode.OK, statusCode,
  64. GetMessage(statusCode, template.ServerOutputAfterRun, template.ServerErrorAfterRun));
  65. }
  66. [NonParallelizable]
  67. [Test]
  68. [TestCaseSource(nameof(RunNonParallelizableData))]
  69. public void _5_RunNonParallelizable(Template template)
  70. {
  71. _5_Run(template);
  72. }
  73. [Test]
  74. [TestCaseSource(nameof(PublishData))]
  75. public void _6_Publish(Template template)
  76. {
  77. var expected = template.ExpectedFilesAfterPublish;
  78. var actual = template.FilesAfterPublish;
  79. CollectionAssert.AreEquivalent(expected, actual);
  80. }
  81. [Test]
  82. [TestCaseSource(nameof(PublishData))]
  83. public void _7_PublishIncremental(Template template)
  84. {
  85. var expected = template.ExpectedFilesAfterPublish;
  86. var actual = template.FilesAfterPublishIncremental;
  87. CollectionAssert.AreEquivalent(expected, actual);
  88. }
  89. [Test]
  90. [TestCaseSource(nameof(ExecData))]
  91. public void _8_Exec(Template template)
  92. {
  93. var statusCode = template.HttpResponseAfterExec.StatusCode;
  94. Assert.AreEqual(HttpStatusCode.OK, statusCode,
  95. GetMessage(statusCode, template.ServerOutputAfterExec, template.ServerErrorAfterExec));
  96. statusCode = template.HttpsResponseAfterExec.StatusCode;
  97. Assert.AreEqual(HttpStatusCode.OK, statusCode,
  98. GetMessage(statusCode, template.ServerOutputAfterExec, template.ServerErrorAfterExec));
  99. }
  100. private static string GetMessage(HttpStatusCode statusCode, string serverOutput, string serverError)
  101. {
  102. return String.Join(Environment.NewLine,
  103. $"StatusCode: {statusCode}",
  104. string.Empty,
  105. "ServerOutput",
  106. "------------",
  107. serverOutput,
  108. string.Empty,
  109. "ServerError",
  110. "------------",
  111. serverError);
  112. }
  113. private static IEnumerable<Template> GetTemplates(RuntimeIdentifier runtimeIdentifier)
  114. {
  115. // Offline restore is broken in SDK 2.1.301 (https://github.com/aspnet/Universe/issues/1220)
  116. var offlinePackageSource = (DotNetUtil.SdkVersion == new SemanticVersion(2, 1, 301)) ?
  117. NuGetPackageSource.NuGetOrg : NuGetPackageSource.None;
  118. // Pre-release SDKs require a private nuget feed
  119. var onlinePackageSource = DotNetUtil.RequiresPrivateFeed ?
  120. NuGetPackageSource.EnvironmentVariableAndNuGetOrg : NuGetPackageSource.NuGetOrg;
  121. if (runtimeIdentifier == RuntimeIdentifier.None)
  122. {
  123. // Framework-dependent
  124. return new[]
  125. {
  126. Template.GetInstance<ClassLibraryTemplate>(NuGetPackageSource.None, runtimeIdentifier),
  127. Template.GetInstance<ConsoleApplicationTemplate>(offlinePackageSource, runtimeIdentifier),
  128. // Offline restore currently not supported for RazorClassLibrary template (https://github.com/aspnet/Universe/issues/1123)
  129. Template.GetInstance<RazorClassLibraryTemplate>(onlinePackageSource, runtimeIdentifier),
  130. Template.GetInstance<WebTemplate>(offlinePackageSource, runtimeIdentifier),
  131. Template.GetInstance<RazorTemplate>(offlinePackageSource, runtimeIdentifier),
  132. Template.GetInstance<MvcTemplate>(offlinePackageSource, runtimeIdentifier),
  133. Template.GetInstance<AngularTemplate>(offlinePackageSource, runtimeIdentifier),
  134. Template.GetInstance<ReactTemplate>(offlinePackageSource, runtimeIdentifier),
  135. Template.GetInstance<ReactReduxTemplate>(offlinePackageSource, runtimeIdentifier),
  136. Template.GetInstance<WebApiTemplate>(offlinePackageSource, runtimeIdentifier),
  137. };
  138. }
  139. else
  140. {
  141. // Self-contained
  142. return new[]
  143. {
  144. // ClassLibrary does not require a package source, even for self-contained deployments
  145. Template.GetInstance<ClassLibraryTemplate>(NuGetPackageSource.None, runtimeIdentifier),
  146. Template.GetInstance<ConsoleApplicationTemplate>(onlinePackageSource, runtimeIdentifier),
  147. Template.GetInstance<RazorClassLibraryTemplate>(onlinePackageSource, runtimeIdentifier),
  148. Template.GetInstance<WebTemplate>(onlinePackageSource, runtimeIdentifier),
  149. Template.GetInstance<RazorTemplate>(onlinePackageSource, runtimeIdentifier),
  150. Template.GetInstance<MvcTemplate>(onlinePackageSource, runtimeIdentifier),
  151. Template.GetInstance<AngularTemplate>(onlinePackageSource, runtimeIdentifier),
  152. Template.GetInstance<ReactTemplate>(onlinePackageSource, runtimeIdentifier),
  153. Template.GetInstance<ReactReduxTemplate>(onlinePackageSource, runtimeIdentifier),
  154. Template.GetInstance<WebApiTemplate>(onlinePackageSource, runtimeIdentifier),
  155. };
  156. }
  157. }
  158. private static readonly IEnumerable<Template> _restoreTemplates = RuntimeIdentifier.All.SelectMany(r => GetTemplates(r));
  159. // Must call ToList() or similar on RestoreData to ensure TestCaseData instances can be compared to each other,
  160. // which is required to use Except() in RunData.
  161. public static IEnumerable<TestCaseData> RestoreData = _restoreTemplates.Select(t => new TestCaseData(t)).ToList();
  162. public static IEnumerable<TestCaseData> BuildData => RestoreData;
  163. public static IEnumerable<TestCaseData> PublishData => BuildData;
  164. private static readonly IEnumerable<TestCaseData> _runData =
  165. from tcd in BuildData
  166. let t = (Template)tcd.Arguments[0]
  167. // Only interested in verifying web applications
  168. where (t.Type == TemplateType.WebApplication)
  169. // "dotnet run" is only relevant for framework-dependent apps
  170. where (t.RuntimeIdentifier == RuntimeIdentifier.None)
  171. select tcd;
  172. // On Linux, calling "dotnet run" on multiple React templates in parallel may fail since the default
  173. // fs.inotify.max_user_watches is too low. One workaround is to increase fs.inotify.max_user_watches,
  174. // but this means tests will fail on a default machine. A simpler workaround is to disable parallel
  175. // execution for these tests.
  176. public static IEnumerable<TestCaseData> RunNonParallelizableData =
  177. from tcd in _runData
  178. let t = (Template)tcd.Arguments[0]
  179. where (t is ReactTemplate)
  180. select tcd;
  181. public static IEnumerable<TestCaseData> RunData = _runData.Except(RunNonParallelizableData);
  182. public static IEnumerable<TestCaseData> ExecData =
  183. from tcd in PublishData
  184. let t = (Template)tcd.Arguments[0]
  185. // Only interested in verifying web applications
  186. where (t.Type == TemplateType.WebApplication)
  187. // Can only run framework-dependent apps and self-contained apps matching the current platform
  188. let runnable = t.RuntimeIdentifier.OSPlatforms.Any(p => RuntimeInformation.IsOSPlatform(p))
  189. select (runnable ? tcd : tcd.Ignore($"RuntimeIdentifier '{t.RuntimeIdentifier}' cannot be executed on this platform"));
  190. }
  191. }